diff --git a/auth.js b/auth.js index f3f2bd3..f4de491 100644 --- a/auth.js +++ b/auth.js @@ -1,7 +1,12 @@ -const credentials = { - clientId: "", - scopes: "chat:read chat:edit channel:read:redemptions user:read:email", - channel: "", // your main channel - sender: "", // bot username -}; -export default credentials; +const auth = (function () { + // Authentication and channels - required + const channel = ""; // your channel + const username = ""; // bot account + const oauth = ""; // should be oauth:xxxxxxxxxxxx from the bot account DO NOT INCLUDE oauth: + + return { + channel, + username, + oauth, + }; +})(); diff --git a/index.html b/index.html index fe58ffb..9ffd920 100644 --- a/index.html +++ b/index.html @@ -4,12 +4,10 @@ - + - - - + diff --git a/lib/handleDCF.js b/lib/handleDCF.js deleted file mode 100644 index fe4299f..0000000 --- a/lib/handleDCF.js +++ /dev/null @@ -1,270 +0,0 @@ -class TwitchAuth { - constructor(clientId, scopes) { - this.clientId = clientId; - this.scopes = scopes; - this.access_token = null; - this.refresh_token = null; - } - - async startAuthFlow() { - // Step 1: Request Device Code - const codeData = await this.requestDeviceCode(this.clientId); - this.displayUserCode(codeData.verificationUri); - return codeData; - } - - async continueAuthFlow(codeData) { - // After obtaining Device Code - // Step 2: Poll for Token - const tokenData = await this.pollForToken( - codeData.deviceCode, - this.clientId - ); - - if (!tokenData) { - location.reload(); - } - - const tokenToSave = { - client_id: this.clientId, - scopes: this.scopes, - access_token: tokenData.access_token, - refresh_token: tokenData.refresh_token, - }; - - await this.saveToken(tokenToSave); - } - - async requestDeviceCode(clientId) { - const now = Date.now(); - const url = "https://id.twitch.tv/oauth2/device"; - const body = new URLSearchParams({ - client_id: clientId, - scopes: this.scopes, - }); - const res = await fetch(url, { method: "POST", body }); - const json = await res.json(); - if ("message" in json) { - throw new Error(`[${res.status}] ${json.message}`); - } - - return { - deviceCode: json.device_code, - userCode: json.user_code, - verificationUri: json.verification_uri, - expiresIn: json.expires_in * 1000, - createdAt: now, - interval: json.interval * 1000, - }; - } - - displayUserCode(verificationUri) { - const container = document.getElementById("auth-container"); - container.innerHTML = ` -

Copy Link to browser:
${verificationUri}

- `; - } - - async pollForToken(deviceCode, clientId) { - const endpoint = "https://id.twitch.tv/oauth2/token"; - const body = new FormData(); - body.append("client_id", clientId); - body.append( - "grant_type", - "urn:ietf:params:oauth:grant-type:device_code" - ); - body.append("device_code", deviceCode); - - const response = await fetch(endpoint, { - method: "POST", - body, - }); - const data = await response.json(); - - if (data.access_token) { - return data; - } else { - console.error("Error:", data); - } - } - - async saveToken(tokenData) { - localStorage.setItem("twitch_token", JSON.stringify(tokenData)); - } - - getToken() { - return JSON.parse(localStorage.getItem("twitch_token")) || null; - } - - setupAuthModal() { - // modal overlay - const modalOverlay = document.createElement("div"); - modalOverlay.id = "modal-overlay"; - modalOverlay.style.fontFamily = "Arial, sans-serif"; - modalOverlay.style.position = "fixed"; - modalOverlay.style.top = "0"; - modalOverlay.style.left = "0"; - modalOverlay.style.width = "100%"; - modalOverlay.style.height = "100%"; - modalOverlay.style.backgroundColor = "rgba(0, 0, 0, 0.5)"; - modalOverlay.style.display = "flex"; - modalOverlay.style.justifyContent = "center"; - modalOverlay.style.alignItems = "center"; - modalOverlay.style.zIndex = "1000"; - - modalOverlay.innerHTML = ` - - `; - - // Append modal overlay to body - document.body.appendChild(modalOverlay); - - // Add event listener to the authorization button - document.getElementById("authorized").addEventListener("click", () => { - document.body.removeChild(modalOverlay); - }); - } - - displayNoClientId() { - // modal overlay - const modalOverlay = document.createElement("div"); - modalOverlay.id = "modal-overlay"; - modalOverlay.style.position = "fixed"; - modalOverlay.style.top = "0"; - modalOverlay.style.left = "0"; - modalOverlay.style.width = "100%"; - modalOverlay.style.height = "100%"; - modalOverlay.style.backgroundColor = "rgba(0, 0, 0, 0.5)"; - modalOverlay.style.display = "flex"; - modalOverlay.style.justifyContent = "center"; - modalOverlay.style.alignItems = "center"; - modalOverlay.style.zIndex = "1000"; - modalOverlay.style.fontFamily = "Arial, sans-serif"; - - modalOverlay.innerHTML = ` - - `; - - // Append modal overlay to body - document.body.appendChild(modalOverlay); - - // Add event listener to the refresh button - document - .getElementById("refresh-button") - .addEventListener("click", () => { - location.reload(); - }); - } - - async refreshToken(data) { - const now = Date.now(); - const url = "https://id.twitch.tv/oauth2/token"; - const body = new URLSearchParams({ - client_id: data.client_id, - grant_type: "refresh_token", - refresh_token: data.refresh_token, - }); - - const res = await fetch(url, { - method: "POST", - headers: { - "Content-Type": "application/x-www-form-urlencoded", - }, - body, - }); - - const json = await res.json(); - - if (!res.ok) { - throw new Error( - `[${res.status}] ${json.message || "Failed to refresh token"}` - ); - } - - return { - ...json, - createdAt: now, - }; - } - - async init() { - return new Promise(async (resolve, reject) => { - let token = await this.getToken(); - - if ( - token && - this.clientId && - token.client_id == this.clientId && - token.scopes == this.scopes - ) { - try { - let token_refresh = await this.refreshToken(token); - - const tokenToSave = { - client_id: this.clientId, - scopes: this.scopes, - access_token: token_refresh.access_token, - refresh_token: token_refresh.refresh_token, - }; - - this.access_token = token_refresh.access_token; - this.refresh_token = token_refresh.refresh_token; - - await this.saveToken(tokenToSave); - resolve(tokenToSave); - } catch (error) { - console.error("Error refreshing token:", error); - reject(error); - } - } else if (this.clientId == null || this.clientId == "") { - this.displayNoClientId(); - reject(new Error("Client ID is missing")); - } else { - this.setupAuthModal(); - var codeData = await this.startAuthFlow(); - - document - .getElementById("authorized") - .addEventListener("click", async (e) => { - try { - await this.continueAuthFlow(codeData); - location.reload(); - resolve(); - } catch (error) { - reject(error); - } - }); - } - }); - } -} - -export default TwitchAuth; diff --git a/lib/initComfy.js b/lib/initComfy.js deleted file mode 100644 index 09c5136..0000000 --- a/lib/initComfy.js +++ /dev/null @@ -1,14 +0,0 @@ -// Usage -import TwitchAuth from "./handleDCF.js"; -import credentials from "../auth.js"; - -const twitchAuth = new TwitchAuth(credentials.clientId, credentials.scopes); -twitchAuth.init().then((data) => { - console.log(data); - console.log(credentials); - ComfyJS.Init( - credentials.sender, - `oauth:${twitchAuth.access_token}`, - credentials.channel - ); -}); diff --git a/lib/webfont.js b/lib/webfont.js new file mode 100644 index 0000000..3e95a6c --- /dev/null +++ b/lib/webfont.js @@ -0,0 +1,33 @@ +/* + * Copyright 2016 Small Batch, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +/* Web Font Loader v1.6.26 - (c) Adobe Systems, Google. License: Apache 2.0 */(function(){function aa(a,b,c){return a.call.apply(a.bind,arguments)}function ba(a,b,c){if(!a)throw Error();if(2=b.f?e():a.fonts.load(fa(b.a),b.h).then(function(a){1<=a.length?d():setTimeout(k,25)},function(){e()})}k()}),e=new Promise(function(a,d){setTimeout(d,b.f)});Promise.race([e,d]).then(function(){b.g(b.a)},function(){b.j(b.a)})};function R(a,b,c,d,e,f,g){this.v=a;this.B=b;this.c=c;this.a=d;this.s=g||"BESbswy";this.f={};this.w=e||3E3;this.u=f||null;this.o=this.j=this.h=this.g=null;this.g=new N(this.c,this.s);this.h=new N(this.c,this.s);this.j=new N(this.c,this.s);this.o=new N(this.c,this.s);a=new H(this.a.c+",serif",K(this.a));a=P(a);this.g.a.style.cssText=a;a=new H(this.a.c+",sans-serif",K(this.a));a=P(a);this.h.a.style.cssText=a;a=new H("serif",K(this.a));a=P(a);this.j.a.style.cssText=a;a=new H("sans-serif",K(this.a));a= +P(a);this.o.a.style.cssText=a;O(this.g);O(this.h);O(this.j);O(this.o)}var S={D:"serif",C:"sans-serif"},T=null;function U(){if(null===T){var a=/AppleWebKit\/([0-9]+)(?:\.([0-9]+))/.exec(window.navigator.userAgent);T=!!a&&(536>parseInt(a[1],10)||536===parseInt(a[1],10)&&11>=parseInt(a[2],10))}return T}R.prototype.start=function(){this.f.serif=this.j.a.offsetWidth;this.f["sans-serif"]=this.o.a.offsetWidth;this.A=q();la(this)}; +function ma(a,b,c){for(var d in S)if(S.hasOwnProperty(d)&&b===a.f[S[d]]&&c===a.f[S[d]])return!0;return!1}function la(a){var b=a.g.a.offsetWidth,c=a.h.a.offsetWidth,d;(d=b===a.f.serif&&c===a.f["sans-serif"])||(d=U()&&ma(a,b,c));d?q()-a.A>=a.w?U()&&ma(a,b,c)&&(null===a.u||a.u.hasOwnProperty(a.a.c))?V(a,a.v):V(a,a.B):na(a):V(a,a.v)}function na(a){setTimeout(p(function(){la(this)},a),50)}function V(a,b){setTimeout(p(function(){v(this.g.a);v(this.h.a);v(this.j.a);v(this.o.a);b(this.a)},a),0)};function W(a,b,c){this.c=a;this.a=b;this.f=0;this.o=this.j=!1;this.s=c}var X=null;W.prototype.g=function(a){var b=this.a;b.g&&w(b.f,[b.a.c("wf",a.c,K(a).toString(),"active")],[b.a.c("wf",a.c,K(a).toString(),"loading"),b.a.c("wf",a.c,K(a).toString(),"inactive")]);L(b,"fontactive",a);this.o=!0;oa(this)}; +W.prototype.h=function(a){var b=this.a;if(b.g){var c=y(b.f,b.a.c("wf",a.c,K(a).toString(),"active")),d=[],e=[b.a.c("wf",a.c,K(a).toString(),"loading")];c||d.push(b.a.c("wf",a.c,K(a).toString(),"inactive"));w(b.f,d,e)}L(b,"fontinactive",a);oa(this)};function oa(a){0==--a.f&&a.j&&(a.o?(a=a.a,a.g&&w(a.f,[a.a.c("wf","active")],[a.a.c("wf","loading"),a.a.c("wf","inactive")]),L(a,"active")):M(a.a))};function pa(a){this.j=a;this.a=new ja;this.h=0;this.f=this.g=!0}pa.prototype.load=function(a){this.c=new ca(this.j,a.context||this.j);this.g=!1!==a.events;this.f=!1!==a.classes;qa(this,new ha(this.c,a),a)}; +function ra(a,b,c,d,e){var f=0==--a.h;(a.f||a.g)&&setTimeout(function(){var a=e||null,k=d||null||{};if(0===c.length&&f)M(b.a);else{b.f+=c.length;f&&(b.j=f);var h,m=[];for(h=0;h