rework auth a little

This commit is contained in:
Darius
2025-10-02 23:04:31 +02:00
parent 0c54b1f776
commit fd420fa59a
13 changed files with 130 additions and 41 deletions

View File

@@ -8,8 +8,8 @@
"build": "npm run clean && tsc -p .",
"start": "node dist/bot.js",
"dev": "nodemon src/bot.ts",
"setup:env": "nodemon src/setup-env.ts",
"setup:auth": "nodemon src/setup-auth.ts"
"setup:env": "node src/setup/setup-env.ts",
"setup:auth": "node src/setup/setup-auth.ts"
},
"keywords": [],
"author": "",

View File

@@ -1,4 +1,4 @@
import { chatClient } from "./core/chat-client.ts";
import { chatClient } from "./core/client.ts";
import { registerAllEvents } from "./events/registry.ts";
registerAllEvents();

View File

@@ -1,6 +1,6 @@
import type { ChatUser } from "@twurple/chat";
import { Config } from "../config/config.ts";
import { chatClient } from "../core/chat-client.ts";
import { chatClient } from "../core/client.ts";
import type { ICommand, ICommandRequirements } from "./interface.ts";
export abstract class BaseCommand implements ICommand {

View File

@@ -1,3 +1,4 @@
import { ApiClient } from "@twurple/api";
import { type AccessToken, RefreshingAuthProvider } from "@twurple/auth";
import { ChatClient } from "@twurple/chat";
import { Config } from "../config/config.ts";
@@ -12,18 +13,20 @@ if (!tokenData) {
throw new Error();
}
const authProviderPrivate = new RefreshingAuthProvider({
export const authProviderUserToken = new RefreshingAuthProvider({
clientId: Config.client_id,
clientSecret: Config.client_secret,
});
authProviderPrivate.onRefresh(async (_userId, newTokenData: AccessToken) =>
authProviderUserToken.onRefresh(async (_userId, newTokenData: AccessToken) =>
tokenManager.createTokenFile(newTokenData),
);
authProviderPrivate.addUser(Config.bot_user_id, tokenData, ["chat"]);
authProviderUserToken.addUser(Config.bot_user_id, tokenData, ["chat"]);
export const chatClient = new ChatClient({
authProvider: authProviderPrivate,
authProvider: authProviderUserToken,
channels: Config.channels,
});
export const apiClient = new ApiClient({ authProvider: authProviderUserToken });

View File

@@ -1,4 +1,4 @@
import { chatClient } from "../core/chat-client.ts";
import { chatClient } from "../core/client.ts";
import type { IEvent } from "./interface.ts";
import type { EventName } from "./registry.ts";

View File

@@ -1,4 +1,4 @@
import { chatClient } from "../core/chat-client.ts";
import { chatClient } from "../core/client.ts";
import { logInfo } from "../util/logger.ts";
import ConnectedEvent from "./impl/connected.ts";
import MessageEvent from "./impl/message.ts";

View File

@@ -1,22 +0,0 @@
import { exchangeCode } from "@twurple/auth";
import { Config } from "./config/config.ts";
import { TokenManager } from "./core/token-manager.ts";
import { TwitchAuth } from "./util/auth.ts";
import { logInfo } from "./util/logger.ts";
const port = 3000;
const redirectUri = `http://localhost:${port}`;
const scopes = ["chat:read", "chat:edit", "channel:moderate"];
const auth = new TwitchAuth(redirectUri);
const state = auth.generateState();
const authUrl = auth.getAuthorizationUrl(scopes, state);
logInfo("To authorize your Twitch bot, visit this URL:");
logInfo(authUrl);
const code = await auth.startCallbackServer(port, 120, state);
const tokenManager = new TokenManager(Config.bot_user_id);
tokenManager.createTokenFile(
await exchangeCode(Config.client_id, Config.client_secret, code, redirectUri),
);

97
src/setup/setup-auth.ts Normal file
View File

@@ -0,0 +1,97 @@
import { exchangeCode } from "@twurple/auth";
import { Config } from "../config/config.ts";
import { TokenManager } from "../core/token-manager.ts";
import { TwitchAuth } from "../util/auth.ts";
import { logInfo } from "../util/logger.ts";
const port = 3000;
const redirectUri = `http://localhost:${port}`;
const scopes = [
"analytics:read:extensions",
"analytics:read:games",
"bits:read",
"channel:manage:ads",
"channel:read:ads",
"channel:manage:broadcast",
"channel:read:charity",
"channel:edit:commercial",
"channel:read:editors",
"channel:manage:extensions",
"channel:read:goals",
"channel:read:guest_star",
"channel:manage:guest_star",
"channel:read:hype_train",
"channel:manage:moderators",
"channel:read:polls",
"channel:manage:polls",
"channel:read:predictions",
"channel:manage:predictions",
"channel:manage:raids",
"channel:read:redemptions",
"channel:manage:redemptions",
"channel:manage:schedule",
"channel:read:stream_key",
"channel:read:subscriptions",
"channel:manage:videos",
"channel:read:vips",
"channel:manage:vips",
"clips:edit",
"moderation:read",
"moderator:manage:announcements",
"moderator:manage:automod",
"moderator:read:automod_settings",
"moderator:manage:automod_settings",
"moderator:manage:banned_users",
"moderator:read:blocked_terms",
"moderator:manage:blocked_terms",
"moderator:manage:chat_messages",
"moderator:read:chat_settings",
"moderator:manage:chat_settings",
"moderator:read:chatters",
"moderator:read:followers",
"moderator:read:guest_star",
"moderator:manage:guest_star",
"moderator:read:shield_mode",
"moderator:manage:shield_mode",
"moderator:read:shoutouts",
"moderator:manage:shoutouts",
"moderator:read:unban_requests",
"moderator:manage:unban_requests",
"user:edit",
"user:edit:follows",
"user:read:blocked_users",
"user:manage:blocked_users",
"user:read:broadcast",
"user:manage:chat_color",
"user:read:email",
"user:read:emotes",
"user:read:follows",
"user:read:moderated_channels",
"user:read:subscriptions",
"user:manage:whispers",
"channel:bot",
"channel:moderate",
"chat:edit",
"chat:read",
"user:bot",
"user:read:chat",
"user:write:chat",
"whispers:read",
"whispers:edit",
"moderator:manage:warnings",
];
const auth = new TwitchAuth(redirectUri);
const state = auth.generateState();
const authUrl = auth.getAuthorizationUrl(scopes, state);
logInfo("To authorize your Twitch bot, visit this URL:");
logInfo(authUrl);
const code = await auth.startCallbackServer(port, 120, state);
const tokenManager = new TokenManager(Config.bot_user_id);
tokenManager.createTokenFile(
await exchangeCode(Config.client_id, Config.client_secret, code, redirectUri),
);
logInfo("Token file created");

View File

@@ -7,4 +7,4 @@ const authProvider = new AppTokenAuthProvider(
Config.client_secret,
);
export const apiClient = new ApiClient({ authProvider });
export const setupClient = new ApiClient({ authProvider });

View File

@@ -1,12 +1,23 @@
import { getUserId, promptForInput } from "./util/general.ts";
import { logError, logSuccess, logWarning } from "./util/logger.ts";
import { promptForInput } from "../util/general.ts";
import { logError, logSuccess, logWarning } from "../util/logger.ts";
import { setupClient } from "./setup-client.ts";
const botname = await promptForInput("enter bot username: ");
const developers = (
await promptForInput("enter developer usernames (,separated): ")
).split(",");
const botId = await getUserId(botname);
const getUid = async (username: string) => {
const user = await setupClient.users.getUserByName(username);
if (user?.id) {
logSuccess(`${user.name} => ${user.id}`);
return user.id;
}
logWarning(`no user with name ${username} found`);
return "";
};
const botId = await getUid(botname);
if (!botId) {
logError("bot not found. please check the configuration");
throw new Error();
@@ -14,7 +25,7 @@ if (!botId) {
const developerIds = [];
for (const dev of developers) {
const devId = await getUserId(dev);
const devId = await getUid(dev);
if (devId) {
developerIds.push(devId);
} else {

View File

@@ -1,6 +1,6 @@
import type { UserIdResolvable } from "@twurple/api";
import { HellFreezesOverError, type UserIdResolvable } from "@twurple/api";
import { Config } from "../config/config.ts";
import { apiClient } from "../core/api-client.ts";
import { apiClient } from "../core/client.ts";
import { getUserId } from "./general.ts";
import { logError } from "./logger.ts";

View File

@@ -1,6 +1,6 @@
import * as readline from "node:readline";
import type { UserIdResolvable } from "@twurple/api";
import { apiClient } from "../core/api-client.ts";
import { apiClient } from "../core/client.ts";
import { logSuccess, logWarning } from "./logger.ts";
export async function getUserId(username: string): Promise<UserIdResolvable> {