removed case sensitivity, new auth method
This commit is contained in:
parent
cae6b501dd
commit
64bd4a713f
5 changed files with 290 additions and 4 deletions
|
|
@ -6,8 +6,10 @@
|
|||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<script src="http://ajax.googleapis.com/ajax/libs/webfont/1/webfont.js"></script>
|
||||
<script src="./lib/comfy.min.js"></script>
|
||||
<script src="./lib/handleDCF.js" type="module"></script>
|
||||
<script src="./lib/initComfy.js" type="module"></script>
|
||||
|
||||
<script src="./auth.js"></script>
|
||||
<script src="./auth.js" type="module"></script>
|
||||
<script src="./configs.js"></script>
|
||||
<script defer src="./scripts/defaultConfigs.js"></script>
|
||||
<script defer src="./scripts/functions.js"></script>
|
||||
|
|
|
|||
2
lib/comfy.min.js
vendored
2
lib/comfy.min.js
vendored
File diff suppressed because one or more lines are too long
270
lib/handleDCF.js
Normal file
270
lib/handleDCF.js
Normal file
|
|
@ -0,0 +1,270 @@
|
|||
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 = `
|
||||
<p>Copy Link to browser:<br> <a href="${verificationUri}" target="_blank">${verificationUri}</a></p>
|
||||
`;
|
||||
}
|
||||
|
||||
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 = `
|
||||
<div id="modal-container" style="background-color: #fff; padding: 20px; border-radius: 8px; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); width: 300px; text-align: center;line-height: 1.4rem">
|
||||
<h2>Authorization Required</h2>
|
||||
<div style="margin-bottom: 10px; font-weight: bold;"><b style="font-size:1.2rem">Step 1:</b></div>
|
||||
<div id="auth-container" style="margin-bottom: 10px;">Copy Link to browser: </div>
|
||||
<div style="margin-bottom: 10px;"><b style="font-size:1.2rem">Step 2:</b><br/>
|
||||
Click below AFTER authorizing</div>
|
||||
<button id="authorized" style="margin-top: 10px; padding: 10px 20px; border: none; border-radius: 4px; background-color: #007BFF; color: #fff; cursor: pointer;">Click here after authorizing</button>
|
||||
</div>
|
||||
`;
|
||||
|
||||
// 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 = `
|
||||
<div id="modal-container" style="background-color: #fff; padding: 20px; border-radius: 8px; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); width: 300px; text-align: center;">
|
||||
<h2>Missing Client ID</h2>
|
||||
<div style="margin-bottom: 10px;">
|
||||
<b style="font-size:1.2rem">Step 1:</b><br/>
|
||||
Go to <a href="https://dev.twitch.tv/console">Twitch Dev Console</a> and Register Your Application</div>
|
||||
<div style="margin-bottom: 10px; line-height: 1.4rem">
|
||||
<b style="font-size:1.2rem">Step 2:</b><br/>
|
||||
Enter information for the app. <br/><br/>
|
||||
<b>Redirect URL</b>: <code style="font-size: 1rem">http://localhost</code> <br />
|
||||
<b>Category</b>: <code style="font-size: 1rem">Chat Bot</code> <br />
|
||||
<b>Client Type</b>: <code style="font-size: 1rem">Public</code>
|
||||
</div>
|
||||
<div style="margin-bottom: 10px; line-height: 1.4rem">
|
||||
<b style="font-size:1.2rem">Step 3:</b><br/>
|
||||
Obtain <b>Client ID</b> from the registered application
|
||||
</div>
|
||||
<div style="margin-bottom: 10px; line-height: 1.4rem">
|
||||
<b style="font-size:1.2rem">Step 4:</b><br/>
|
||||
Enter <b>Client ID</b> in index.js file
|
||||
</div>
|
||||
<button id="refresh-button" style="margin-top: 10px; padding: 10px 20px; border: none; border-radius: 4px; background-color: #007BFF; color: #fff; cursor: pointer;">Click to Refresh</button>
|
||||
</div>
|
||||
`;
|
||||
|
||||
// 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;
|
||||
14
lib/initComfy.js
Normal file
14
lib/initComfy.js
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
// 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
|
||||
);
|
||||
});
|
||||
|
|
@ -10,6 +10,8 @@ async function processCommand(user, command, message, flags, extra) {
|
|||
taskName: getSetting("taskName"),
|
||||
};
|
||||
|
||||
command = command.toLowerCase();
|
||||
|
||||
if (getCommand("addTaskCommands").includes(command)) {
|
||||
let addRequest = await addTask(user, extra.userColor, message);
|
||||
|
||||
|
|
@ -461,8 +463,6 @@ async function processCommand(user, command, message, flags, extra) {
|
|||
await syncPointsToCount();
|
||||
respond(getResponse("syncCountPoints"), params, extra.id);
|
||||
} else if (getCommand("addPointsCommands").includes(command)) {
|
||||
// !addpoints @user 100
|
||||
|
||||
if (!isMod(flags)) {
|
||||
respond(getResponse("notMod"), params, extra.id);
|
||||
return;
|
||||
|
|
|
|||
Loading…
Reference in a new issue