tested & working basic bot
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import * as crypto from "node:crypto";
|
||||
import {
|
||||
createServer,
|
||||
type IncomingMessage,
|
||||
@@ -5,6 +6,7 @@ import {
|
||||
} from "node:http";
|
||||
import { URL } from "node:url";
|
||||
import { Config } from "../config/config.ts";
|
||||
import { logError, logInfo } from "./logger.ts";
|
||||
|
||||
export class TwitchAuth {
|
||||
private readonly redirectUri: string;
|
||||
@@ -13,20 +15,29 @@ export class TwitchAuth {
|
||||
this.redirectUri = redirectUri;
|
||||
}
|
||||
|
||||
getAuthorizationUrl(scopes: string[]): string {
|
||||
getAuthorizationUrl(scopes: string[], state: string): string {
|
||||
const baseUrl = "https://id.twitch.tv/oauth2/authorize";
|
||||
const params = new URLSearchParams({
|
||||
response_type: "code",
|
||||
client_id: Config.client_id,
|
||||
redirect_uri: this.redirectUri,
|
||||
scope: scopes.join(" "),
|
||||
state: state,
|
||||
});
|
||||
|
||||
return `${baseUrl}?${params.toString()}`;
|
||||
}
|
||||
|
||||
startCallbackServer(port: number, timeoutS: number = 120): Promise<string> {
|
||||
return new Promise((resolve, reject) => {
|
||||
generateState(): string {
|
||||
return crypto.randomBytes(20).toString("hex");
|
||||
}
|
||||
|
||||
startCallbackServer(
|
||||
port: number,
|
||||
timeoutS: number = 120,
|
||||
state: string,
|
||||
): Promise<string> {
|
||||
return new Promise((resolve) => {
|
||||
const server = createServer(
|
||||
(req: IncomingMessage, res: ServerResponse) => {
|
||||
if (!req.url) {
|
||||
@@ -38,8 +49,15 @@ export class TwitchAuth {
|
||||
const url = new URL(req.url, `http://localhost:${port}`);
|
||||
const code = url.searchParams.get("code");
|
||||
const error = url.searchParams.get("error");
|
||||
const responseState = url.searchParams.get("state");
|
||||
const errorDescription = url.searchParams.get("error_description");
|
||||
|
||||
if (state !== responseState) {
|
||||
res.writeHead(400, { "Content-Type": "text/html" });
|
||||
res.end("<h1>Wrong state</h1><p>Invalid state param</p>");
|
||||
return;
|
||||
}
|
||||
|
||||
if (error) {
|
||||
res.writeHead(400, { "Content-Type": "text/html" });
|
||||
res.end(`
|
||||
@@ -49,10 +67,8 @@ export class TwitchAuth {
|
||||
<p>You can close this window.</p>
|
||||
`);
|
||||
server.close();
|
||||
reject(
|
||||
new Error(`Authorization failed: ${error} - ${errorDescription}`),
|
||||
);
|
||||
return;
|
||||
logError(`authorization failed: ${error} - ${errorDescription}`);
|
||||
throw new Error();
|
||||
}
|
||||
|
||||
if (code) {
|
||||
@@ -73,18 +89,20 @@ export class TwitchAuth {
|
||||
);
|
||||
|
||||
server.listen(port, "localhost", () => {
|
||||
console.log(
|
||||
`Waiting for authorization callback on http://localhost:${port}`,
|
||||
logInfo(
|
||||
`waiting for authorization callback on http://localhost:${port}`,
|
||||
);
|
||||
});
|
||||
|
||||
server.on("error", (err) => {
|
||||
reject(new Error(`Server error: ${err.message}`));
|
||||
logError(`server error: ${err.message}`);
|
||||
throw new Error();
|
||||
});
|
||||
|
||||
const timeout = setTimeout(() => {
|
||||
server.close();
|
||||
reject(new Error("Authorization timeout. Please try again."));
|
||||
logError("authorization timeout");
|
||||
throw new Error();
|
||||
}, timeoutS * 1000);
|
||||
|
||||
server.on("close", () => {
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import * as readline from "node:readline";
|
||||
import { apiClient } from "../core/api-client.ts";
|
||||
import { logError, logInfo } from "./logger.ts";
|
||||
import { logSuccess, logWarning } from "./logger.ts";
|
||||
|
||||
export async function getUserId(username: string): Promise<string | null> {
|
||||
const user = await apiClient.users.getUserByName(username);
|
||||
if (user) {
|
||||
logInfo(`${user.name} => ${user.id}`);
|
||||
if (user?.id) {
|
||||
logSuccess(`${user.name} => ${user.id}`);
|
||||
return user.id;
|
||||
}
|
||||
logError(`no user with name ${username} found`);
|
||||
logWarning(`no user with name ${username} found`);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import chalk from "chalk";
|
||||
|
||||
const verbose = process.argv.includes("--verbose");
|
||||
|
||||
export function logError(...args: unknown[]) {
|
||||
console.log(chalk.red(args));
|
||||
}
|
||||
@@ -15,7 +13,5 @@ export function logSuccess(...args: unknown[]) {
|
||||
}
|
||||
|
||||
export function logInfo(...args: unknown[]) {
|
||||
if (verbose) {
|
||||
console.log(chalk.cyan(args));
|
||||
}
|
||||
console.log(chalk.cyan(args));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user