diff --git a/.env.example b/.env.example index 9bff6a0..b631ba5 100644 --- a/.env.example +++ b/.env.example @@ -1,5 +1,6 @@ PREFIX=prefixLike! -USERNAME=usernameOfBot -ACCESS_TOKEN=oauthAccessToken +BOT_USER_ID=botUserId +CLIENT_ID=clientId +CLIENT_SECRET=clientSecret CHANNELS=channelsOfBot DEVELOPERS=userIdOfDeveloper diff --git a/package-lock.json b/package-lock.json index 8383d38..cd849e2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,11 +9,11 @@ "version": "1.0.0", "license": "ISC", "dependencies": { - "@changesets/logger": "^0.1.1", "@discordjs/collection": "^2.1.1", + "@twurple/auth": "^7.4.0", + "@twurple/chat": "^7.4.0", "chalk": "^5.6.2", - "dotenv": "^17.2.2", - "tmi.js": "^1.8.5" + "dotenv": "^17.2.2" }, "devDependencies": { "@types/node": "^24.5.2", @@ -24,15 +24,6 @@ "typescript": "^5.9.2" } }, - "node_modules/@changesets/logger": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@changesets/logger/-/logger-0.1.1.tgz", - "integrity": "sha512-OQtR36ZlnuTxKqoW4Sv6x5YIhOmClRd5pWsjZsddYxpWs517R0HkyiefQPIytCVh4ZcC5x9XaG8KTdd5iRQUfg==", - "license": "MIT", - "dependencies": { - "picocolors": "^1.1.0" - } - }, "node_modules/@cspotcode/source-map-support": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", @@ -46,6 +37,137 @@ "node": ">=12" } }, + "node_modules/@d-fischer/cache-decorators": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@d-fischer/cache-decorators/-/cache-decorators-4.0.1.tgz", + "integrity": "sha512-HNYLBLWs/t28GFZZeqdIBqq8f37mqDIFO6xNPof94VjpKvuP6ROqCZGafx88dk5zZUlBfViV9jD8iNNlXfc4CA==", + "license": "MIT", + "dependencies": { + "@d-fischer/shared-utils": "^3.6.3", + "tslib": "^2.6.2" + } + }, + "node_modules/@d-fischer/connection": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@d-fischer/connection/-/connection-9.0.0.tgz", + "integrity": "sha512-Mljp/EbaE+eYWfsFXUOk+RfpbHgrWGL/60JkAvjYixw6KREfi5r17XdUiXe54ByAQox6jwgdN2vebdmW1BT+nQ==", + "license": "MIT", + "dependencies": { + "@d-fischer/isomorphic-ws": "^7.0.0", + "@d-fischer/logger": "^4.2.1", + "@d-fischer/shared-utils": "^3.5.0", + "@d-fischer/typed-event-emitter": "^3.3.0", + "@types/ws": "^8.5.4", + "tslib": "^2.4.1", + "ws": "^8.11.0" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + } + }, + "node_modules/@d-fischer/cross-fetch": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@d-fischer/cross-fetch/-/cross-fetch-5.0.5.tgz", + "integrity": "sha512-symjDUPInTrkfIsZc2n2mo9hiAJLcTJsZkNICjZajEWnWpJ3s3zn50/FY8xpNUAf5w3eFuQii2wxztTGpvG1Xg==", + "license": "MIT", + "dependencies": { + "node-fetch": "^2.6.12" + } + }, + "node_modules/@d-fischer/deprecate": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@d-fischer/deprecate/-/deprecate-2.0.2.tgz", + "integrity": "sha512-wlw3HwEanJFJKctwLzhfOM6LKwR70FPfGZGoKOhWBKyOPXk+3a9Cc6S9zhm6tka7xKtpmfxVIReGUwPnMbIaZg==", + "license": "MIT" + }, + "node_modules/@d-fischer/detect-node": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@d-fischer/detect-node/-/detect-node-3.0.1.tgz", + "integrity": "sha512-0Rf3XwTzuTh8+oPZW9SfxTIiL+26RRJ0BRPwj5oVjZFyFKmsj9RGfN2zuTRjOuA3FCK/jYm06HOhwNK+8Pfv8w==", + "license": "MIT" + }, + "node_modules/@d-fischer/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@d-fischer/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-7eoxnxcto5eVPW5h1T+ePnVFukmI9f/ZR9nlBLh1t3kyzJDUNor2C+YW9H/Terw3YnbZSDgDYrpCJCHtOtAQHw==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/@d-fischer/isomorphic-ws": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@d-fischer/isomorphic-ws/-/isomorphic-ws-7.0.2.tgz", + "integrity": "sha512-xK+qIJUF0ne3dsjq5Y3BviQ4M+gx9dzkN+dPP7abBMje4YRfow+X9jBgeEoTe5e+Q6+8hI9R0b37Okkk8Vf0hQ==", + "license": "MIT", + "peerDependencies": { + "ws": "^8.2.0" + } + }, + "node_modules/@d-fischer/logger": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/@d-fischer/logger/-/logger-4.2.4.tgz", + "integrity": "sha512-TFMZ/SVW8xyQtyJw9Rcuci4betSKy0qbQn2B5+1+72vVXeO8Qb1pYvuwF5qr0vDGundmSWq7W8r19nVPnXXSvA==", + "license": "MIT", + "dependencies": { + "@d-fischer/detect-node": "^3.0.1", + "@d-fischer/shared-utils": "^3.6.1", + "tslib": "^2.5.0" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + } + }, + "node_modules/@d-fischer/qs": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@d-fischer/qs/-/qs-7.0.2.tgz", + "integrity": "sha512-yAu3xDooiL+ef84Jo8nLjDjWBRk7RXk163Y6aTvRB7FauYd3spQD/dWvgT7R4CrN54Juhrrc3dMY7mc+jZGurQ==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + } + }, + "node_modules/@d-fischer/rate-limiter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@d-fischer/rate-limiter/-/rate-limiter-1.1.0.tgz", + "integrity": "sha512-O5HgACwApyCZhp4JTEBEtbv/W3eAwEkrARFvgWnEsDmXgCMWjIHwohWoHre5BW6IYXFSHBGsuZB/EvNL3942kQ==", + "license": "MIT", + "dependencies": { + "@d-fischer/logger": "^4.2.3", + "@d-fischer/shared-utils": "^3.6.3", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + } + }, + "node_modules/@d-fischer/shared-utils": { + "version": "3.6.4", + "resolved": "https://registry.npmjs.org/@d-fischer/shared-utils/-/shared-utils-3.6.4.tgz", + "integrity": "sha512-BPkVLHfn2Lbyo/ENDBwtEB8JVQ+9OzkjJhUunLaxkw4k59YFlQxUUwlDBejVSFcpQT0t+D3CQlX+ySZnQj0wxw==", + "license": "MIT", + "dependencies": { + "tslib": "^2.4.1" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + } + }, + "node_modules/@d-fischer/typed-event-emitter": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/@d-fischer/typed-event-emitter/-/typed-event-emitter-3.3.3.tgz", + "integrity": "sha512-OvSEOa8icfdWDqcRtjSEZtgJTFOFNgTjje7zaL0+nAtu2/kZtRCSK5wUMrI/aXtCH8o0Qz2vA8UqkhWUTARFQQ==", + "license": "MIT", + "dependencies": { + "tslib": "^2.4.0" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + } + }, "node_modules/@discordjs/collection": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-2.1.1.tgz", @@ -155,11 +277,81 @@ "dev": true, "license": "MIT" }, + "node_modules/@twurple/api-call": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@twurple/api-call/-/api-call-7.4.0.tgz", + "integrity": "sha512-WNxvjp/hMqZREElbvE4rHMyUIrHdGY5cbG8xbqgSM9CESFvJ1wm5BubhyANOyKd1TxABacLddbfbO//Fz9YHgA==", + "license": "MIT", + "dependencies": { + "@d-fischer/cross-fetch": "^5.0.1", + "@d-fischer/qs": "^7.0.2", + "@d-fischer/shared-utils": "^3.6.1", + "@twurple/common": "7.4.0", + "tslib": "^2.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + } + }, + "node_modules/@twurple/auth": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@twurple/auth/-/auth-7.4.0.tgz", + "integrity": "sha512-WAQV6nJGkfY7r2BkRYhnzUpdfozLvjNsCxkyNVprl4dCWdJzccnTvqkKTdDRJc5ZJxDVaB9Drzwx9/fCp/gRDA==", + "license": "MIT", + "peer": true, + "dependencies": { + "@d-fischer/logger": "^4.2.1", + "@d-fischer/shared-utils": "^3.6.1", + "@d-fischer/typed-event-emitter": "^3.3.1", + "@twurple/api-call": "7.4.0", + "@twurple/common": "7.4.0", + "tslib": "^2.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + } + }, + "node_modules/@twurple/chat": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@twurple/chat/-/chat-7.4.0.tgz", + "integrity": "sha512-SYppFwnWt7I8mH/I7fF/ZPO61aBzOz7BOOHQhVWzuQ/7qgPfZnmPJmUwfMnsMmKJ95TfsScZnAWxhdwNdRe3wg==", + "license": "MIT", + "dependencies": { + "@d-fischer/cache-decorators": "^4.0.0", + "@d-fischer/deprecate": "^2.0.2", + "@d-fischer/logger": "^4.2.1", + "@d-fischer/rate-limiter": "^1.1.0", + "@d-fischer/shared-utils": "^3.6.1", + "@d-fischer/typed-event-emitter": "^3.3.0", + "@twurple/common": "7.4.0", + "ircv3": "^0.33.0", + "tslib": "^2.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "@twurple/auth": "7.4.0" + } + }, + "node_modules/@twurple/common": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@twurple/common/-/common-7.4.0.tgz", + "integrity": "sha512-lX5cVkYar6jGvni6iLmMYjhxH1oPSl2v7XVeZ4C7U1GbLz/Jwk0L0uldQNGUIf9gpRHPY+TXRlk0UIpz2yo8DA==", + "license": "MIT", + "dependencies": { + "@d-fischer/shared-utils": "^3.6.1", + "klona": "^2.0.4", + "tslib": "^2.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + } + }, "node_modules/@types/node": { "version": "24.5.2", "resolved": "https://registry.npmjs.org/@types/node/-/node-24.5.2.tgz", "integrity": "sha512-FYxk1I7wPv3K2XBaoyH2cTnocQEu8AOZ60hPbsyukMPLv5/5qr7V1i8PLHdl6Zf87I+xZXFvPCXYjiTFq+YSDQ==", - "dev": true, "license": "MIT", "peer": true, "dependencies": { @@ -173,6 +365,15 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/ws": { + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz", + "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/acorn": { "version": "8.15.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", @@ -529,6 +730,24 @@ "dev": true, "license": "ISC" }, + "node_modules/ircv3": { + "version": "0.33.0", + "resolved": "https://registry.npmjs.org/ircv3/-/ircv3-0.33.0.tgz", + "integrity": "sha512-7rK1Aial3LBiFycE8w3MHiBBFb41/2GG2Ll/fR2IJj1vx0pLpn1s+78K+z/I4PZTqCCSp/Sb4QgKMh3NMhx0Kg==", + "license": "MIT", + "dependencies": { + "@d-fischer/connection": "^9.0.0", + "@d-fischer/escape-string-regexp": "^5.0.0", + "@d-fischer/logger": "^4.2.1", + "@d-fischer/shared-utils": "^3.5.0", + "@d-fischer/typed-event-emitter": "^3.3.0", + "klona": "^2.0.5", + "tslib": "^2.4.1" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + } + }, "node_modules/is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", @@ -608,6 +827,15 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/klona": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.6.tgz", + "integrity": "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, "node_modules/lru-cache": { "version": "11.2.2", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.2.tgz", @@ -764,12 +992,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "license": "ISC" - }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", @@ -1002,19 +1224,6 @@ "node": ">=4" } }, - "node_modules/tmi.js": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/tmi.js/-/tmi.js-1.8.5.tgz", - "integrity": "sha512-A9qrydfe1e0VWM9MViVhhxVgvLpnk7pFShVUWePsSTtoi+A1X+Zjdoa7OJd7/YsgHXGj3GkNEvnWop/1WwZuew==", - "license": "MIT", - "dependencies": { - "node-fetch": "^2.6.1", - "ws": "^8.2.0" - }, - "engines": { - "node": ">=10.0.0" - } - }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -1088,6 +1297,12 @@ } } }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, "node_modules/typescript": { "version": "5.9.2", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz", @@ -1114,7 +1329,6 @@ "version": "7.12.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.12.0.tgz", "integrity": "sha512-goOacqME2GYyOZZfb5Lgtu+1IDmAlAEu5xnD3+xTzS10hT0vzpf0SPjkXwAw9Jm+4n/mQGDP3LO8CPbYROeBfQ==", - "dev": true, "license": "MIT" }, "node_modules/v8-compile-cache-lib": { @@ -1259,6 +1473,7 @@ "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", "license": "MIT", + "peer": true, "engines": { "node": ">=10.0.0" }, diff --git a/package.json b/package.json index 0bacf60..a358843 100644 --- a/package.json +++ b/package.json @@ -23,8 +23,9 @@ }, "dependencies": { "@discordjs/collection": "^2.1.1", + "@twurple/auth": "^7.4.0", + "@twurple/chat": "^7.4.0", "chalk": "^5.6.2", - "dotenv": "^17.2.2", - "tmi.js": "^1.8.5" + "dotenv": "^17.2.2" } } diff --git a/src/bot.ts b/src/bot.ts index 7a640df..566e12b 100644 --- a/src/bot.ts +++ b/src/bot.ts @@ -1,13 +1,5 @@ -import type { Events } from "tmi.js"; import { client } from "./core/client.ts"; -import { events } from "./events/collection.ts"; - -// Register all events with the TMI client -for (const [eventName, eventHandler] of events) { - client.on( - eventName as keyof Events, - eventHandler.triggered.bind(null, client), - ); -} +import { registerAllEvents } from "./events/registry.ts"; +registerAllEvents(client); client.connect(); diff --git a/src/commands/command-song.ts b/src/commands/command-song.ts index 41fc0dc..d254dd8 100644 --- a/src/commands/command-song.ts +++ b/src/commands/command-song.ts @@ -1,4 +1,5 @@ -import type { ChatUserstate, Client } from "tmi.js"; +import type { ChatMessage } from "@twurple/chat"; +import { logSuccess } from "../logger/logger.ts"; import type { ICommand, ICommandRequirements } from "./interface.ts"; export class SongCommand implements ICommand { @@ -12,12 +13,12 @@ export class SongCommand implements ICommand { }; triggered = async ( - client: Client, channel: string, - _state: ChatUserstate, - _message: string, - _args: Array, + user: string, + text: string, + msg: ChatMessage, ) => { - client.say(channel, "testing"); + logSuccess(`${channel} song command triggered`); + // client.say(channel, "testing"); }; } diff --git a/src/config/config.ts b/src/config/config.ts index d081d5e..4f504e6 100644 --- a/src/config/config.ts +++ b/src/config/config.ts @@ -4,8 +4,9 @@ dotenv.config(); export const Config = { prefix: process.env.PREFIX || "", - username: process.env.USERNAME || "", - access_token: process.env.ACCESS_TOKEN || "", + bot_user_id: process.env.BOT_USER_ID || "", + client_id: process.env.CLIENT_ID || "", + client_secret: process.env.CLIENT_SECRET || "", channels: [process.env.CHANNELS || ""], developers: [process.env.DEVELOPERS || ""], }; diff --git a/src/core/client.ts b/src/core/client.ts index 3aa720a..7aa7d7d 100644 --- a/src/core/client.ts +++ b/src/core/client.ts @@ -1,11 +1,30 @@ -import { Client } from "tmi.js"; +import { promises as fs } from "node:fs"; +import { RefreshingAuthProvider } from "@twurple/auth"; +import { ChatClient } from "@twurple/chat"; import { Config } from "../config/config.ts"; -export const client = new Client({ - connection: { reconnect: true, secure: true }, - identity: { - username: Config.username, - password: `oauth:${Config.access_token}`, - }, +// Auth Token Stuff +const tokenData = JSON.parse( + await fs.readFile("./tokens.125328655.json", "utf-8"), +); + +const authProvider = new RefreshingAuthProvider({ + clientId: Config.client_id, + clientSecret: Config.client_secret, +}); + +authProvider.onRefresh( + async (userId, newTokenData) => + await fs.writeFile( + `./tokens.${userId}.json`, + JSON.stringify(newTokenData, null, 4), + "utf-8", + ), +); + +await authProvider.addUserForToken(tokenData, ["chat"]); + +export const client = new ChatClient({ + authProvider, channels: Config.channels, }); diff --git a/src/events/collection.ts b/src/events/collection.ts deleted file mode 100644 index dc4cb2c..0000000 --- a/src/events/collection.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { Collection } from "@discordjs/collection"; -import ConnectedEvent from "./event-connected.ts"; -import MessageEvent from "./event-message.ts"; -import type { IEvent } from "./interface.ts"; - -export const events = new Collection(); - -events.set(ConnectedEvent.name, new ConnectedEvent()); -events.set(MessageEvent.name, new MessageEvent()); diff --git a/src/events/event-connected.ts b/src/events/event-connected.ts index f4cb931..88c0836 100644 --- a/src/events/event-connected.ts +++ b/src/events/event-connected.ts @@ -1,11 +1,11 @@ -import type { Events } from "tmi.js"; import { logSuccess } from "../logger/logger.ts"; import type { IEvent } from "./interface.ts"; +import type { EventName } from "./registry.ts"; export default class ConnectedEvent implements IEvent { - name: keyof Events = "connected"; + name: EventName = "connected"; triggered = async () => { - logSuccess("connected"); + logSuccess(this.name); }; } diff --git a/src/events/event-message.ts b/src/events/event-message.ts index 66cbd76..730a1ad 100644 --- a/src/events/event-message.ts +++ b/src/events/event-message.ts @@ -1,66 +1,63 @@ import { Collection } from "@discordjs/collection"; -import type { ChatUserstate, Client, Events } from "tmi.js"; +import type { ChatMessage } from "@twurple/chat"; import { commands } from "../commands/collection.ts"; import type { ICommand } from "../commands/interface.ts"; import { Config } from "../config/config.ts"; import type { IEvent } from "./interface.ts"; +import type { EventName } from "./registry.ts"; const Cooldowns = new Collection(); export default class MessageEvent implements IEvent { - name: keyof Events = "message"; + name: EventName = "message"; triggered = async ( - client: Client, channel: string, - state: ChatUserstate, - message: string, - self: boolean, + user: string, + text: string, + msg: ChatMessage, ) => { - if (self) return; - await checkMessage(client, channel, state, message); + await checkMessage(channel, user, text, msg); }; } async function checkMessage( - client: Client, channel: string, - state: ChatUserstate, - message: string, + user: string, + text: string, + msg: ChatMessage, ) { const prefix = Config.prefix; + if (!text.startsWith(prefix)) return; - if (!message.startsWith(prefix)) return; - - const args = message.slice(prefix.length).trim().split(/ +/g); - const commandName = args[0].toLowerCase(); + const commandName = text + .slice(prefix.length) + .trim() + .split(/ +/g)[0] + .toLowerCase(); const command = commands.get(commandName); if (!command) return; if (!command.enabled) return; - const userId = state["user-id"] as string; - if (command.requirements.developer && !isDeveloper(userId)) return; - if (command.requirements.mod && !isMod(state)) return; + if (command.requirements.developer && !isDeveloper(msg.userInfo.userId)) + return; + if (command.requirements.mod && !msg.userInfo.isMod) return; const timeLeft = checkCooldown(command); if (timeLeft > 0) { - return client.say( - channel, - `you must wait ${timeLeft} more seconds to use the command again`, - ); + // return client.say( + // channel, + // `@${user}, you must wait ${timeLeft} more seconds to use the command again`, + // ); } - await command.triggered(client, channel, state, message, args); + await command.triggered(channel, user, text, msg); } function isDeveloper(userId: string): boolean { return Config.developers.includes(userId); } -function isMod(state: ChatUserstate): boolean { - return state.mod as boolean; -} - function checkCooldown(command: ICommand): number { const now = Date.now(); if (command.cooldown > 0) { diff --git a/src/events/interface.ts b/src/events/interface.ts index 666ed35..1106ca0 100644 --- a/src/events/interface.ts +++ b/src/events/interface.ts @@ -1,6 +1,6 @@ -import type { Events } from "tmi.js"; +import type { EventName } from "./registry"; export interface IEvent { - name: keyof Events; + name: EventName; triggered(...args: unknown[]): Promise; } diff --git a/src/events/registry.ts b/src/events/registry.ts new file mode 100644 index 0000000..48a4eda --- /dev/null +++ b/src/events/registry.ts @@ -0,0 +1,24 @@ +import type { ChatClient } from "@twurple/chat"; +import ConnectedEvent from "./event-connected"; +import MessageEvent from "./event-message"; +import type { IEvent } from "./interface"; + +export const eventRegistry = { + message: (client: ChatClient, handler: IEvent) => + client.onMessage(handler.triggered), + connected: (client: ChatClient, handler: IEvent) => + client.onConnect(handler.triggered), +}; + +export function registerAllEvents(client: ChatClient) { + const events = [new MessageEvent(), new ConnectedEvent()]; + + for (const event of events) { + const registerFn = eventRegistry[event.name]; + if (registerFn) { + registerFn(client, event); + } + } +} + +export type EventName = keyof typeof eventRegistry;