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 = `
-
-
Authorization Required
-
Step 1:
-
Copy Link to browser:
-
Step 2:
- Click below AFTER authorizing
-
-
- `;
-
- // 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 = `
-
-
Missing Client ID
-
-
- Step 2:
- Enter information for the app.
- Redirect URL: http://localhost
- Category: Chat Bot
- Client Type: Public
-
-
- Step 3:
- Obtain Client ID from the registered application
-
-
- Step 4:
- Enter Client ID in index.js file
-
-
-
- `;
-
- // 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