switch to twurple

This commit is contained in:
Darius
2025-09-26 15:14:03 +02:00
parent 9a961363f3
commit 47a4103176
12 changed files with 345 additions and 103 deletions

View File

@@ -1,5 +1,6 @@
PREFIX=prefixLike! PREFIX=prefixLike!
USERNAME=usernameOfBot BOT_USER_ID=botUserId
ACCESS_TOKEN=oauthAccessToken CLIENT_ID=clientId
CLIENT_SECRET=clientSecret
CHANNELS=channelsOfBot CHANNELS=channelsOfBot
DEVELOPERS=userIdOfDeveloper DEVELOPERS=userIdOfDeveloper

281
package-lock.json generated
View File

@@ -9,11 +9,11 @@
"version": "1.0.0", "version": "1.0.0",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"@changesets/logger": "^0.1.1",
"@discordjs/collection": "^2.1.1", "@discordjs/collection": "^2.1.1",
"@twurple/auth": "^7.4.0",
"@twurple/chat": "^7.4.0",
"chalk": "^5.6.2", "chalk": "^5.6.2",
"dotenv": "^17.2.2", "dotenv": "^17.2.2"
"tmi.js": "^1.8.5"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "^24.5.2", "@types/node": "^24.5.2",
@@ -24,15 +24,6 @@
"typescript": "^5.9.2" "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": { "node_modules/@cspotcode/source-map-support": {
"version": "0.8.1", "version": "0.8.1",
"resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
@@ -46,6 +37,137 @@
"node": ">=12" "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": { "node_modules/@discordjs/collection": {
"version": "2.1.1", "version": "2.1.1",
"resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-2.1.1.tgz", "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-2.1.1.tgz",
@@ -155,11 +277,81 @@
"dev": true, "dev": true,
"license": "MIT" "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": { "node_modules/@types/node": {
"version": "24.5.2", "version": "24.5.2",
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.5.2.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-24.5.2.tgz",
"integrity": "sha512-FYxk1I7wPv3K2XBaoyH2cTnocQEu8AOZ60hPbsyukMPLv5/5qr7V1i8PLHdl6Zf87I+xZXFvPCXYjiTFq+YSDQ==", "integrity": "sha512-FYxk1I7wPv3K2XBaoyH2cTnocQEu8AOZ60hPbsyukMPLv5/5qr7V1i8PLHdl6Zf87I+xZXFvPCXYjiTFq+YSDQ==",
"dev": true,
"license": "MIT", "license": "MIT",
"peer": true, "peer": true,
"dependencies": { "dependencies": {
@@ -173,6 +365,15 @@
"dev": true, "dev": true,
"license": "MIT" "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": { "node_modules/acorn": {
"version": "8.15.0", "version": "8.15.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
@@ -529,6 +730,24 @@
"dev": true, "dev": true,
"license": "ISC" "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": { "node_modules/is-binary-path": {
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "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" "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": { "node_modules/lru-cache": {
"version": "11.2.2", "version": "11.2.2",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.2.tgz", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.2.tgz",
@@ -764,12 +992,6 @@
"url": "https://github.com/sponsors/isaacs" "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": { "node_modules/picomatch": {
"version": "2.3.1", "version": "2.3.1",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
@@ -1002,19 +1224,6 @@
"node": ">=4" "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": { "node_modules/to-regex-range": {
"version": "5.0.1", "version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "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": { "node_modules/typescript": {
"version": "5.9.2", "version": "5.9.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz",
@@ -1114,7 +1329,6 @@
"version": "7.12.0", "version": "7.12.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.12.0.tgz", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.12.0.tgz",
"integrity": "sha512-goOacqME2GYyOZZfb5Lgtu+1IDmAlAEu5xnD3+xTzS10hT0vzpf0SPjkXwAw9Jm+4n/mQGDP3LO8CPbYROeBfQ==", "integrity": "sha512-goOacqME2GYyOZZfb5Lgtu+1IDmAlAEu5xnD3+xTzS10hT0vzpf0SPjkXwAw9Jm+4n/mQGDP3LO8CPbYROeBfQ==",
"dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/v8-compile-cache-lib": { "node_modules/v8-compile-cache-lib": {
@@ -1259,6 +1473,7 @@
"resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz",
"integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==",
"license": "MIT", "license": "MIT",
"peer": true,
"engines": { "engines": {
"node": ">=10.0.0" "node": ">=10.0.0"
}, },

View File

@@ -23,8 +23,9 @@
}, },
"dependencies": { "dependencies": {
"@discordjs/collection": "^2.1.1", "@discordjs/collection": "^2.1.1",
"@twurple/auth": "^7.4.0",
"@twurple/chat": "^7.4.0",
"chalk": "^5.6.2", "chalk": "^5.6.2",
"dotenv": "^17.2.2", "dotenv": "^17.2.2"
"tmi.js": "^1.8.5"
} }
} }

View File

@@ -1,13 +1,5 @@
import type { Events } from "tmi.js";
import { client } from "./core/client.ts"; import { client } from "./core/client.ts";
import { events } from "./events/collection.ts"; import { registerAllEvents } from "./events/registry.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),
);
}
registerAllEvents(client);
client.connect(); client.connect();

View File

@@ -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"; import type { ICommand, ICommandRequirements } from "./interface.ts";
export class SongCommand implements ICommand { export class SongCommand implements ICommand {
@@ -12,12 +13,12 @@ export class SongCommand implements ICommand {
}; };
triggered = async ( triggered = async (
client: Client,
channel: string, channel: string,
_state: ChatUserstate, user: string,
_message: string, text: string,
_args: Array<string>, msg: ChatMessage,
) => { ) => {
client.say(channel, "testing"); logSuccess(`${channel} song command triggered`);
// client.say(channel, "testing");
}; };
} }

View File

@@ -4,8 +4,9 @@ dotenv.config();
export const Config = { export const Config = {
prefix: process.env.PREFIX || "", prefix: process.env.PREFIX || "",
username: process.env.USERNAME || "", bot_user_id: process.env.BOT_USER_ID || "",
access_token: process.env.ACCESS_TOKEN || "", client_id: process.env.CLIENT_ID || "",
client_secret: process.env.CLIENT_SECRET || "",
channels: [process.env.CHANNELS || ""], channels: [process.env.CHANNELS || ""],
developers: [process.env.DEVELOPERS || ""], developers: [process.env.DEVELOPERS || ""],
}; };

View File

@@ -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"; import { Config } from "../config/config.ts";
export const client = new Client({ // Auth Token Stuff
connection: { reconnect: true, secure: true }, const tokenData = JSON.parse(
identity: { await fs.readFile("./tokens.125328655.json", "utf-8"),
username: Config.username, );
password: `oauth:${Config.access_token}`,
}, 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, channels: Config.channels,
}); });

View File

@@ -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<string, IEvent>();
events.set(ConnectedEvent.name, new ConnectedEvent());
events.set(MessageEvent.name, new MessageEvent());

View File

@@ -1,11 +1,11 @@
import type { Events } from "tmi.js";
import { logSuccess } from "../logger/logger.ts"; import { logSuccess } from "../logger/logger.ts";
import type { IEvent } from "./interface.ts"; import type { IEvent } from "./interface.ts";
import type { EventName } from "./registry.ts";
export default class ConnectedEvent implements IEvent { export default class ConnectedEvent implements IEvent {
name: keyof Events = "connected"; name: EventName = "connected";
triggered = async () => { triggered = async () => {
logSuccess("connected"); logSuccess(this.name);
}; };
} }

View File

@@ -1,66 +1,63 @@
import { Collection } from "@discordjs/collection"; 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 { commands } from "../commands/collection.ts";
import type { ICommand } from "../commands/interface.ts"; import type { ICommand } from "../commands/interface.ts";
import { Config } from "../config/config.ts"; import { Config } from "../config/config.ts";
import type { IEvent } from "./interface.ts"; import type { IEvent } from "./interface.ts";
import type { EventName } from "./registry.ts";
const Cooldowns = new Collection<string, number>(); const Cooldowns = new Collection<string, number>();
export default class MessageEvent implements IEvent { export default class MessageEvent implements IEvent {
name: keyof Events = "message"; name: EventName = "message";
triggered = async ( triggered = async (
client: Client,
channel: string, channel: string,
state: ChatUserstate, user: string,
message: string, text: string,
self: boolean, msg: ChatMessage,
) => { ) => {
if (self) return; await checkMessage(channel, user, text, msg);
await checkMessage(client, channel, state, message);
}; };
} }
async function checkMessage( async function checkMessage(
client: Client,
channel: string, channel: string,
state: ChatUserstate, user: string,
message: string, text: string,
msg: ChatMessage,
) { ) {
const prefix = Config.prefix; const prefix = Config.prefix;
if (!text.startsWith(prefix)) return;
if (!message.startsWith(prefix)) return; const commandName = text
.slice(prefix.length)
const args = message.slice(prefix.length).trim().split(/ +/g); .trim()
const commandName = args[0].toLowerCase(); .split(/ +/g)[0]
.toLowerCase();
const command = commands.get(commandName); const command = commands.get(commandName);
if (!command) return; if (!command) return;
if (!command.enabled) return; if (!command.enabled) return;
const userId = state["user-id"] as string; if (command.requirements.developer && !isDeveloper(msg.userInfo.userId))
if (command.requirements.developer && !isDeveloper(userId)) return; return;
if (command.requirements.mod && !isMod(state)) return; if (command.requirements.mod && !msg.userInfo.isMod) return;
const timeLeft = checkCooldown(command); const timeLeft = checkCooldown(command);
if (timeLeft > 0) { if (timeLeft > 0) {
return client.say( // return client.say(
channel, // channel,
`you must wait ${timeLeft} more seconds to use the command again`, // `@${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 { function isDeveloper(userId: string): boolean {
return Config.developers.includes(userId); return Config.developers.includes(userId);
} }
function isMod(state: ChatUserstate): boolean {
return state.mod as boolean;
}
function checkCooldown(command: ICommand): number { function checkCooldown(command: ICommand): number {
const now = Date.now(); const now = Date.now();
if (command.cooldown > 0) { if (command.cooldown > 0) {

View File

@@ -1,6 +1,6 @@
import type { Events } from "tmi.js"; import type { EventName } from "./registry";
export interface IEvent { export interface IEvent {
name: keyof Events; name: EventName;
triggered(...args: unknown[]): Promise<unknown>; triggered(...args: unknown[]): Promise<unknown>;
} }

24
src/events/registry.ts Normal file
View File

@@ -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;