mirror of
https://gitlab.com/qwerinope/qweribot.git
synced 2026-02-04 12:36:59 +01:00
Compare commits
8 Commits
64dd8e6dd5
...
v2
| Author | SHA1 | Date | |
|---|---|---|---|
| b88a93a6cf | |||
| f3c6f6a6b3 | |||
|
aa757a563d
|
|||
|
5a17e405fa
|
|||
|
e24e00701c
|
|||
|
92fe7bb75d
|
|||
|
cb08cc0786
|
|||
|
45e09482be
|
@@ -170,6 +170,7 @@ COMMAND|FUNCTION|USER|ALIASES|DISABLEABLE
|
|||||||
`anivtimeouts`|Get the amount of timeouts, dodges and dodge percentage from aniv timeouts [(info)](#aniv-timeouts)|anyone|`anivtimeouts` `anivtimeout`|:white_check_mark:
|
`anivtimeouts`|Get the amount of timeouts, dodges and dodge percentage from aniv timeouts [(info)](#aniv-timeouts)|anyone|`anivtimeouts` `anivtimeout`|:white_check_mark:
|
||||||
`racetime`|Get the racetime.gg room the streamer is currently in. Needs to have twitch linked to racetime account|anyone|`racetime` `raceroom`|:white_check_mark:
|
`racetime`|Get the racetime.gg room the streamer is currently in. Needs to have twitch linked to racetime account|anyone|`racetime` `raceroom`|:white_check_mark:
|
||||||
`randomchatter`|Get a random chatter for whatever reason|moderators|`randomchatter`|:white_check_mark:
|
`randomchatter`|Get a random chatter for whatever reason|moderators|`randomchatter`|:white_check_mark:
|
||||||
|
`economy`|Get a count of all items in circulation|anyone|`economy` `eco`|:white_check_mark:
|
||||||
|
|
||||||
### Qweribucks/Item commands
|
### Qweribucks/Item commands
|
||||||
|
|
||||||
@@ -225,7 +226,7 @@ NAME|COMMAND|FUNCTION|ALIASES|COST
|
|||||||
-|-|-|-|-
|
-|-|-|-|-
|
||||||
Blaster|`blaster {target}`|Times targeted user out for 60 seconds|`blaster` `blast`|100
|
Blaster|`blaster {target}`|Times targeted user out for 60 seconds|`blaster` `blast`|100
|
||||||
Grenade|`grenade`|Times a random vulnerable chatter out for 60 seconds|`grenade`|99
|
Grenade|`grenade`|Times a random vulnerable chatter out for 60 seconds|`grenade`|99
|
||||||
Silver Bullet|`silverbullet [target]`|Times targeted or random vulnerable user out for 30 minutes|`silverbullet` `execute` `{blastin}`|666
|
Silver Bullet|`silverbullet [target]`|Times targeted or random vulnerable user out for 30 minutes|`silverbullet` `execute` `{blastin}` `{fuck}`|666
|
||||||
TNT|`tnt`|Give 5-10 random chatters 60 second timeouts|`tnt`|1000
|
TNT|`tnt`|Give 5-10 random chatters 60 second timeouts|`tnt`|1000
|
||||||
|
|
||||||
## Cheers
|
## Cheers
|
||||||
@@ -250,4 +251,4 @@ NAME|COST|DESCRIPTION|INTERNALNAME
|
|||||||
`Welcome to the Madhouse`|100|Sound: mrockstar20 says: "Welcome to the Madhouse"|`sfxmrockmadhouse`
|
`Welcome to the Madhouse`|100|Sound: mrockstar20 says: "Welcome to the Madhouse"|`sfxmrockmadhouse`
|
||||||
`Eddie Scream`|100|Sound: Eddie screams|`sfxeddiescream`
|
`Eddie Scream`|100|Sound: Eddie screams|`sfxeddiescream`
|
||||||
`Factorio Building Destroyed`|100|Sound: Factorio Building Destroyed alert|`sfxfactorioalert`
|
`Factorio Building Destroyed`|100|Sound: Factorio Building Destroyed alert|`sfxfactorioalert`
|
||||||
`Fail`|100|Sound: Either the sad trumpet or trombone meme sound|`sfxFail`
|
`Fail`|100|Sound: Either the sad trumpet or trombone meme sound|`sfxfail`
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://biomejs.dev/schemas/2.3.8/schema.json",
|
"$schema": "https://biomejs.dev/schemas/2.3.13/schema.json",
|
||||||
"vcs": {
|
"vcs": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"clientKind": "git",
|
"clientKind": "git",
|
||||||
|
|||||||
103
bun.lock
103
bun.lock
@@ -6,58 +6,51 @@
|
|||||||
"name": "qweribot",
|
"name": "qweribot",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fontsource/jersey-15": "^5.2.8",
|
"@fontsource/jersey-15": "^5.2.8",
|
||||||
"@twurple/api": "7.4.0",
|
"@twurple/api": "8.0.3",
|
||||||
"@twurple/auth": "^7.4.0",
|
"@twurple/auth": "^8.0.3",
|
||||||
"@twurple/eventsub-http": "^7.4.0",
|
"@twurple/eventsub-http": "^8.0.3",
|
||||||
"discord.js": "^14.24.0",
|
"discord.js": "^14.25.1",
|
||||||
"drizzle-orm": "^0.44.6",
|
"drizzle-orm": "^0.45.1",
|
||||||
"kleur": "^4.1.5",
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@biomejs/biome": "^2.3.8",
|
"@biomejs/biome": "^2.3.13",
|
||||||
"@twurple/eventsub-ngrok": "^7.4.0",
|
"@twurple/eventsub-ngrok": "^8.0.3",
|
||||||
"@types/bun": "latest",
|
"@types/bun": "latest",
|
||||||
"drizzle-kit": "^0.31.5",
|
"drizzle-kit": "^0.31.8",
|
||||||
"pg": "^8.16.3",
|
"pg": "^8.17.2",
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"typescript": "^5.8.3",
|
"typescript": "^5.9.3",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"packages": {
|
"packages": {
|
||||||
"@biomejs/biome": ["@biomejs/biome@2.3.8", "", { "optionalDependencies": { "@biomejs/cli-darwin-arm64": "2.3.8", "@biomejs/cli-darwin-x64": "2.3.8", "@biomejs/cli-linux-arm64": "2.3.8", "@biomejs/cli-linux-arm64-musl": "2.3.8", "@biomejs/cli-linux-x64": "2.3.8", "@biomejs/cli-linux-x64-musl": "2.3.8", "@biomejs/cli-win32-arm64": "2.3.8", "@biomejs/cli-win32-x64": "2.3.8" }, "bin": { "biome": "bin/biome" } }, "sha512-Qjsgoe6FEBxWAUzwFGFrB+1+M8y/y5kwmg5CHac+GSVOdmOIqsAiXM5QMVGZJ1eCUCLlPZtq4aFAQ0eawEUuUA=="],
|
"@biomejs/biome": ["@biomejs/biome@2.3.13", "", { "optionalDependencies": { "@biomejs/cli-darwin-arm64": "2.3.13", "@biomejs/cli-darwin-x64": "2.3.13", "@biomejs/cli-linux-arm64": "2.3.13", "@biomejs/cli-linux-arm64-musl": "2.3.13", "@biomejs/cli-linux-x64": "2.3.13", "@biomejs/cli-linux-x64-musl": "2.3.13", "@biomejs/cli-win32-arm64": "2.3.13", "@biomejs/cli-win32-x64": "2.3.13" }, "bin": { "biome": "bin/biome" } }, "sha512-Fw7UsV0UAtWIBIm0M7g5CRerpu1eKyKAXIazzxhbXYUyMkwNrkX/KLkGI7b+uVDQ5cLUMfOC9vR60q9IDYDstA=="],
|
||||||
|
|
||||||
"@biomejs/cli-darwin-arm64": ["@biomejs/cli-darwin-arm64@2.3.8", "", { "os": "darwin", "cpu": "arm64" }, "sha512-HM4Zg9CGQ3txTPflxD19n8MFPrmUAjaC7PQdLkugeeC0cQ+PiVrd7i09gaBS/11QKsTDBJhVg85CEIK9f50Qww=="],
|
"@biomejs/cli-darwin-arm64": ["@biomejs/cli-darwin-arm64@2.3.13", "", { "os": "darwin", "cpu": "arm64" }, "sha512-0OCwP0/BoKzyJHnFdaTk/i7hIP9JHH9oJJq6hrSCPmJPo8JWcJhprK4gQlhFzrwdTBAW4Bjt/RmCf3ZZe59gwQ=="],
|
||||||
|
|
||||||
"@biomejs/cli-darwin-x64": ["@biomejs/cli-darwin-x64@2.3.8", "", { "os": "darwin", "cpu": "x64" }, "sha512-lUDQ03D7y/qEao7RgdjWVGCu+BLYadhKTm40HkpJIi6kn8LSv5PAwRlew/DmwP4YZ9ke9XXoTIQDO1vAnbRZlA=="],
|
"@biomejs/cli-darwin-x64": ["@biomejs/cli-darwin-x64@2.3.13", "", { "os": "darwin", "cpu": "x64" }, "sha512-AGr8OoemT/ejynbIu56qeil2+F2WLkIjn2d8jGK1JkchxnMUhYOfnqc9sVzcRxpG9Ycvw4weQ5sprRvtb7Yhcw=="],
|
||||||
|
|
||||||
"@biomejs/cli-linux-arm64": ["@biomejs/cli-linux-arm64@2.3.8", "", { "os": "linux", "cpu": "arm64" }, "sha512-Uo1OJnIkJgSgF+USx970fsM/drtPcQ39I+JO+Fjsaa9ZdCN1oysQmy6oAGbyESlouz+rzEckLTF6DS7cWse95g=="],
|
"@biomejs/cli-linux-arm64": ["@biomejs/cli-linux-arm64@2.3.13", "", { "os": "linux", "cpu": "arm64" }, "sha512-xvOiFkrDNu607MPMBUQ6huHmBG1PZLOrqhtK6pXJW3GjfVqJg0Z/qpTdhXfcqWdSZHcT+Nct2fOgewZvytESkw=="],
|
||||||
|
|
||||||
"@biomejs/cli-linux-arm64-musl": ["@biomejs/cli-linux-arm64-musl@2.3.8", "", { "os": "linux", "cpu": "arm64" }, "sha512-PShR4mM0sjksUMyxbyPNMxoKFPVF48fU8Qe8Sfx6w6F42verbwRLbz+QiKNiDPRJwUoMG1nPM50OBL3aOnTevA=="],
|
"@biomejs/cli-linux-arm64-musl": ["@biomejs/cli-linux-arm64-musl@2.3.13", "", { "os": "linux", "cpu": "arm64" }, "sha512-TUdDCSY+Eo/EHjhJz7P2GnWwfqet+lFxBZzGHldrvULr59AgahamLs/N85SC4+bdF86EhqDuuw9rYLvLFWWlXA=="],
|
||||||
|
|
||||||
"@biomejs/cli-linux-x64": ["@biomejs/cli-linux-x64@2.3.8", "", { "os": "linux", "cpu": "x64" }, "sha512-QDPMD5bQz6qOVb3kiBui0zKZXASLo0NIQ9JVJio5RveBEFgDgsvJFUvZIbMbUZT3T00M/1wdzwWXk4GIh0KaAw=="],
|
"@biomejs/cli-linux-x64": ["@biomejs/cli-linux-x64@2.3.13", "", { "os": "linux", "cpu": "x64" }, "sha512-s+YsZlgiXNq8XkgHs6xdvKDFOj/bwTEevqEY6rC2I3cBHbxXYU1LOZstH3Ffw9hE5tE1sqT7U23C00MzkXztMw=="],
|
||||||
|
|
||||||
"@biomejs/cli-linux-x64-musl": ["@biomejs/cli-linux-x64-musl@2.3.8", "", { "os": "linux", "cpu": "x64" }, "sha512-YGLkqU91r1276uwSjiUD/xaVikdxgV1QpsicT0bIA1TaieM6E5ibMZeSyjQ/izBn4tKQthUSsVZacmoJfa3pDA=="],
|
"@biomejs/cli-linux-x64-musl": ["@biomejs/cli-linux-x64-musl@2.3.13", "", { "os": "linux", "cpu": "x64" }, "sha512-0bdwFVSbbM//Sds6OjtnmQGp4eUjOTt6kHvR/1P0ieR9GcTUAlPNvPC3DiavTqq302W34Ae2T6u5VVNGuQtGlQ=="],
|
||||||
|
|
||||||
"@biomejs/cli-win32-arm64": ["@biomejs/cli-win32-arm64@2.3.8", "", { "os": "win32", "cpu": "arm64" }, "sha512-H4IoCHvL1fXKDrTALeTKMiE7GGWFAraDwBYFquE/L/5r1927Te0mYIGseXi4F+lrrwhSWbSGt5qPFswNoBaCxg=="],
|
"@biomejs/cli-win32-arm64": ["@biomejs/cli-win32-arm64@2.3.13", "", { "os": "win32", "cpu": "arm64" }, "sha512-QweDxY89fq0VvrxME+wS/BXKmqMrOTZlN9SqQ79kQSIc3FrEwvW/PvUegQF6XIVaekncDykB5dzPqjbwSKs9DA=="],
|
||||||
|
|
||||||
"@biomejs/cli-win32-x64": ["@biomejs/cli-win32-x64@2.3.8", "", { "os": "win32", "cpu": "x64" }, "sha512-RguzimPoZWtBapfKhKjcWXBVI91tiSprqdBYu7tWhgN8pKRZhw24rFeNZTNf6UiBfjCYCi9eFQs/JzJZIhuK4w=="],
|
"@biomejs/cli-win32-x64": ["@biomejs/cli-win32-x64@2.3.13", "", { "os": "win32", "cpu": "x64" }, "sha512-trDw2ogdM2lyav9WFQsdsfdVy1dvZALymRpgmWsvSez0BJzBjulhOT/t+wyKeh3pZWvwP3VMs1SoOKwO3wecMQ=="],
|
||||||
|
|
||||||
"@d-fischer/cache-decorators": ["@d-fischer/cache-decorators@4.0.1", "", { "dependencies": { "@d-fischer/shared-utils": "^3.6.3", "tslib": "^2.6.2" } }, "sha512-HNYLBLWs/t28GFZZeqdIBqq8f37mqDIFO6xNPof94VjpKvuP6ROqCZGafx88dk5zZUlBfViV9jD8iNNlXfc4CA=="],
|
"@d-fischer/cache-decorators": ["@d-fischer/cache-decorators@4.0.1", "", { "dependencies": { "@d-fischer/shared-utils": "^3.6.3", "tslib": "^2.6.2" } }, "sha512-HNYLBLWs/t28GFZZeqdIBqq8f37mqDIFO6xNPof94VjpKvuP6ROqCZGafx88dk5zZUlBfViV9jD8iNNlXfc4CA=="],
|
||||||
|
|
||||||
"@d-fischer/cross-fetch": ["@d-fischer/cross-fetch@5.0.5", "", { "dependencies": { "node-fetch": "^2.6.12" } }, "sha512-symjDUPInTrkfIsZc2n2mo9hiAJLcTJsZkNICjZajEWnWpJ3s3zn50/FY8xpNUAf5w3eFuQii2wxztTGpvG1Xg=="],
|
|
||||||
|
|
||||||
"@d-fischer/detect-node": ["@d-fischer/detect-node@3.0.1", "", {}, "sha512-0Rf3XwTzuTh8+oPZW9SfxTIiL+26RRJ0BRPwj5oVjZFyFKmsj9RGfN2zuTRjOuA3FCK/jYm06HOhwNK+8Pfv8w=="],
|
"@d-fischer/detect-node": ["@d-fischer/detect-node@3.0.1", "", {}, "sha512-0Rf3XwTzuTh8+oPZW9SfxTIiL+26RRJ0BRPwj5oVjZFyFKmsj9RGfN2zuTRjOuA3FCK/jYm06HOhwNK+8Pfv8w=="],
|
||||||
|
|
||||||
"@d-fischer/logger": ["@d-fischer/logger@4.2.3", "", { "dependencies": { "@d-fischer/detect-node": "^3.0.1", "@d-fischer/shared-utils": "^3.2.0", "tslib": "^2.0.3" } }, "sha512-mJUx9OgjrNVLQa4od/+bqnmD164VTCKnK5B4WOW8TX5y/3w2i58p+PMRE45gUuFjk2BVtOZUg55JQM3d619fdw=="],
|
"@d-fischer/logger": ["@d-fischer/logger@4.2.3", "", { "dependencies": { "@d-fischer/detect-node": "^3.0.1", "@d-fischer/shared-utils": "^3.2.0", "tslib": "^2.0.3" } }, "sha512-mJUx9OgjrNVLQa4od/+bqnmD164VTCKnK5B4WOW8TX5y/3w2i58p+PMRE45gUuFjk2BVtOZUg55JQM3d619fdw=="],
|
||||||
|
|
||||||
"@d-fischer/qs": ["@d-fischer/qs@7.0.2", "", {}, "sha512-yAu3xDooiL+ef84Jo8nLjDjWBRk7RXk163Y6aTvRB7FauYd3spQD/dWvgT7R4CrN54Juhrrc3dMY7mc+jZGurQ=="],
|
|
||||||
|
|
||||||
"@d-fischer/rate-limiter": ["@d-fischer/rate-limiter@1.1.0", "", { "dependencies": { "@d-fischer/logger": "^4.2.3", "@d-fischer/shared-utils": "^3.6.3", "tslib": "^2.6.2" } }, "sha512-O5HgACwApyCZhp4JTEBEtbv/W3eAwEkrARFvgWnEsDmXgCMWjIHwohWoHre5BW6IYXFSHBGsuZB/EvNL3942kQ=="],
|
"@d-fischer/rate-limiter": ["@d-fischer/rate-limiter@1.1.0", "", { "dependencies": { "@d-fischer/logger": "^4.2.3", "@d-fischer/shared-utils": "^3.6.3", "tslib": "^2.6.2" } }, "sha512-O5HgACwApyCZhp4JTEBEtbv/W3eAwEkrARFvgWnEsDmXgCMWjIHwohWoHre5BW6IYXFSHBGsuZB/EvNL3942kQ=="],
|
||||||
|
|
||||||
"@d-fischer/raw-body": ["@d-fischer/raw-body@2.4.3", "", { "dependencies": { "bytes": "3.1.0", "http-errors": "1.7.3", "iconv-lite": "0.4.24", "unpipe": "1.0.0" } }, "sha512-rtPTezQLROnTDdRij0Vo5OJ41aGvfKj9pQ7CkzFssQy+Jyc9BUVLV/DXLIGgvEGUaWt09Jq3im4WgvvPYqTomw=="],
|
|
||||||
|
|
||||||
"@d-fischer/shared-utils": ["@d-fischer/shared-utils@3.6.4", "", { "dependencies": { "tslib": "^2.4.1" } }, "sha512-BPkVLHfn2Lbyo/ENDBwtEB8JVQ+9OzkjJhUunLaxkw4k59YFlQxUUwlDBejVSFcpQT0t+D3CQlX+ySZnQj0wxw=="],
|
"@d-fischer/shared-utils": ["@d-fischer/shared-utils@3.6.4", "", { "dependencies": { "tslib": "^2.4.1" } }, "sha512-BPkVLHfn2Lbyo/ENDBwtEB8JVQ+9OzkjJhUunLaxkw4k59YFlQxUUwlDBejVSFcpQT0t+D3CQlX+ySZnQj0wxw=="],
|
||||||
|
|
||||||
"@d-fischer/typed-event-emitter": ["@d-fischer/typed-event-emitter@3.3.3", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-OvSEOa8icfdWDqcRtjSEZtgJTFOFNgTjje7zaL0+nAtu2/kZtRCSK5wUMrI/aXtCH8o0Qz2vA8UqkhWUTARFQQ=="],
|
"@d-fischer/typed-event-emitter": ["@d-fischer/typed-event-emitter@3.3.3", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-OvSEOa8icfdWDqcRtjSEZtgJTFOFNgTjje7zaL0+nAtu2/kZtRCSK5wUMrI/aXtCH8o0Qz2vA8UqkhWUTARFQQ=="],
|
||||||
@@ -168,23 +161,23 @@
|
|||||||
|
|
||||||
"@sapphire/snowflake": ["@sapphire/snowflake@3.5.3", "", {}, "sha512-jjmJywLAFoWeBi1W7994zZyiNWPIiqRRNAmSERxyg93xRGzNYvGjlZ0gR6x0F4gPRi2+0O6S71kOZYyr3cxaIQ=="],
|
"@sapphire/snowflake": ["@sapphire/snowflake@3.5.3", "", {}, "sha512-jjmJywLAFoWeBi1W7994zZyiNWPIiqRRNAmSERxyg93xRGzNYvGjlZ0gR6x0F4gPRi2+0O6S71kOZYyr3cxaIQ=="],
|
||||||
|
|
||||||
"@twurple/api": ["@twurple/api@7.4.0", "", { "dependencies": { "@d-fischer/cache-decorators": "^4.0.0", "@d-fischer/cross-fetch": "^5.0.1", "@d-fischer/detect-node": "^3.0.1", "@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.1", "@twurple/api-call": "7.4.0", "@twurple/common": "7.4.0", "retry": "^0.13.1", "tslib": "^2.0.3" }, "peerDependencies": { "@twurple/auth": "7.4.0" } }, "sha512-RlXLs4ZvS8n0+iIk7YyVDwrjhlwpn+N+h7fX5Q61HoxlmzoCShmnnFo03abYw9i8Cc3deGpbQATOSVmigXM4qg=="],
|
"@twurple/api": ["@twurple/api@8.0.3", "", { "dependencies": { "@d-fischer/cache-decorators": "^4.0.0", "@d-fischer/detect-node": "^3.0.1", "@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.1", "@twurple/api-call": "8.0.3", "@twurple/common": "8.0.3", "retry": "^0.13.1", "tslib": "^2.0.3" }, "peerDependencies": { "@twurple/auth": "8.0.3" } }, "sha512-vnqVi9YlNDbCqgpUUvTIq4sDitKCY0dkTw9zPluZvRNqUB1eCsuoaRNW96HQDhKtA9P4pRzwZ8xU7v/1KU2ytg=="],
|
||||||
|
|
||||||
"@twurple/api-call": ["@twurple/api-call@7.4.0", "", { "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" } }, "sha512-WNxvjp/hMqZREElbvE4rHMyUIrHdGY5cbG8xbqgSM9CESFvJ1wm5BubhyANOyKd1TxABacLddbfbO//Fz9YHgA=="],
|
"@twurple/api-call": ["@twurple/api-call@8.0.3", "", { "dependencies": { "@d-fischer/shared-utils": "^3.6.1", "@twurple/common": "8.0.3", "tslib": "^2.0.3" } }, "sha512-/5DBTqFjpYB+qqOkkFzoTWE79a7+I8uLXmBIIIYjGoq/CIPxKcHnlemXlU8cQhTr87PVa3th8zJXGYiNkpRx8w=="],
|
||||||
|
|
||||||
"@twurple/auth": ["@twurple/auth@7.4.0", "", { "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" } }, "sha512-WAQV6nJGkfY7r2BkRYhnzUpdfozLvjNsCxkyNVprl4dCWdJzccnTvqkKTdDRJc5ZJxDVaB9Drzwx9/fCp/gRDA=="],
|
"@twurple/auth": ["@twurple/auth@8.0.3", "", { "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": "8.0.3", "@twurple/common": "8.0.3", "tslib": "^2.0.3" } }, "sha512-Xlv+WNXmGQir4aBXYeRCqdno5XurA6jzYTIovSEHa7FZf3AMHMFqtzW7yqTCUn4iOahfUSA2TIIxmxFM0wis0g=="],
|
||||||
|
|
||||||
"@twurple/common": ["@twurple/common@7.4.0", "", { "dependencies": { "@d-fischer/shared-utils": "^3.6.1", "klona": "^2.0.4", "tslib": "^2.0.3" } }, "sha512-lX5cVkYar6jGvni6iLmMYjhxH1oPSl2v7XVeZ4C7U1GbLz/Jwk0L0uldQNGUIf9gpRHPY+TXRlk0UIpz2yo8DA=="],
|
"@twurple/common": ["@twurple/common@8.0.3", "", { "dependencies": { "@d-fischer/shared-utils": "^3.6.1", "klona": "^2.0.4", "tslib": "^2.0.3" } }, "sha512-JQ2lb5qSFT21Y9qMfIouAILb94ppedLHASq49Fe/AP8oq0k3IC9Q7tX2n6tiMzGWqn+n8MnONUpMSZ6FhulMXA=="],
|
||||||
|
|
||||||
"@twurple/eventsub-base": ["@twurple/eventsub-base@7.4.0", "", { "dependencies": { "@d-fischer/logger": "^4.2.1", "@d-fischer/shared-utils": "^3.6.1", "@d-fischer/typed-event-emitter": "^3.3.0", "@twurple/api": "7.4.0", "@twurple/auth": "7.4.0", "@twurple/common": "7.4.0", "tslib": "^2.0.3" } }, "sha512-Umx0kNZKxBUTF2/MHAlnnCuNPs8Tl1Aw8EzDJI2AW10tOiWvgeCR889fKCFBPlHXvcMYSEvsItkX+pXeZ8GkeQ=="],
|
"@twurple/eventsub-base": ["@twurple/eventsub-base@8.0.3", "", { "dependencies": { "@d-fischer/logger": "^4.2.1", "@d-fischer/shared-utils": "^3.6.1", "@d-fischer/typed-event-emitter": "^3.3.0", "@twurple/api": "8.0.3", "@twurple/auth": "8.0.3", "@twurple/common": "8.0.3", "tslib": "^2.0.3" } }, "sha512-59G5xJbHWLTSO6NAgwtkHPfIlmdjrABgiEumFnHhNusMbLM9qdA+kLcW5NB2NImNliytl6zZtqY92FInzUE6NA=="],
|
||||||
|
|
||||||
"@twurple/eventsub-http": ["@twurple/eventsub-http@7.4.0", "", { "dependencies": { "@d-fischer/logger": "^4.2.1", "@d-fischer/raw-body": "^2.4.3", "@d-fischer/shared-utils": "^3.6.1", "@d-fischer/typed-event-emitter": "^3.3.0", "@twurple/auth": "7.4.0", "@twurple/common": "7.4.0", "@twurple/eventsub-base": "7.4.0", "@types/express-serve-static-core": "^4.17.24", "httpanda": "^0.4.6", "tslib": "^2.0.3" }, "peerDependencies": { "@twurple/api": "7.4.0" } }, "sha512-Ua8cP4OPfgyUxlNG2BSJ2Ck02Axk3YXIBoQqoTURlSI0wix8+kTK0X4QuDvxicPxn9iRV1prNimOSvt4HXSkrQ=="],
|
"@twurple/eventsub-http": ["@twurple/eventsub-http@8.0.3", "", { "dependencies": { "@d-fischer/logger": "^4.2.1", "@d-fischer/shared-utils": "^3.6.1", "@d-fischer/typed-event-emitter": "^3.3.0", "@twurple/auth": "8.0.3", "@twurple/common": "8.0.3", "@twurple/eventsub-base": "8.0.3", "@types/express-serve-static-core": "^5.1.0", "httpanda": "^0.4.6", "raw-body": "^3.0.2", "tslib": "^2.0.3" }, "peerDependencies": { "@twurple/api": "8.0.3" } }, "sha512-ds8l01GfsIC0hhILepv/UUn/Ix8s0wLg9aGy10xWaG9/Hlfe82NPI8gAg0LYsmlCsOADPwJZSckMTGPJrpw1Iw=="],
|
||||||
|
|
||||||
"@twurple/eventsub-ngrok": ["@twurple/eventsub-ngrok@7.4.0", "", { "dependencies": { "@d-fischer/shared-utils": "^3.6.1", "@ngrok/ngrok": "^0.5.1", "tslib": "^2.0.3" }, "peerDependencies": { "@twurple/api": "7.4.0", "@twurple/eventsub-http": "7.4.0" } }, "sha512-YPk4TtYmCFQwBuIUgEpd6D29wqhJJQq6fxjWG83E86lp3vfcaY6aq7kE39kSqTz8TDkx62xnSH9lsMmZImIQ0w=="],
|
"@twurple/eventsub-ngrok": ["@twurple/eventsub-ngrok@8.0.3", "", { "dependencies": { "@d-fischer/shared-utils": "^3.6.1", "@ngrok/ngrok": "^0.5.1", "tslib": "^2.0.3" }, "peerDependencies": { "@twurple/api": "8.0.3", "@twurple/eventsub-http": "8.0.3" } }, "sha512-wt4keLIivnEpv0EpQw1zgBD6tinaDmVf5VhvQqr8NABCpL4TuZNQAIveIUelHmY+phlISIX/42mvXqHNfmMTwg=="],
|
||||||
|
|
||||||
"@types/bun": ["@types/bun@1.3.4", "", { "dependencies": { "bun-types": "1.3.4" } }, "sha512-EEPTKXHP+zKGPkhRLv+HI0UEX8/o+65hqARxLy8Ov5rIxMBPNTjeZww00CIihrIQGEQBYg+0roO5qOnS/7boGA=="],
|
"@types/bun": ["@types/bun@1.3.7", "", { "dependencies": { "bun-types": "1.3.7" } }, "sha512-lmNuMda+Z9b7tmhA0tohwy8ZWFSnmQm1UDWXtH5r9F7wZCfkeO3Jx7wKQ1EOiKq43yHts7ky6r8SDJQWRNupkA=="],
|
||||||
|
|
||||||
"@types/express-serve-static-core": ["@types/express-serve-static-core@4.19.7", "", { "dependencies": { "@types/node": "*", "@types/qs": "*", "@types/range-parser": "*", "@types/send": "*" } }, "sha512-FvPtiIf1LfhzsaIXhv/PHan/2FeQBbtBDtfX2QfvPxdUelMDEckK08SM6nqo1MIZY3RUlfA+HV8+hFUSio78qg=="],
|
"@types/express-serve-static-core": ["@types/express-serve-static-core@5.1.1", "", { "dependencies": { "@types/node": "*", "@types/qs": "*", "@types/range-parser": "*", "@types/send": "*" } }, "sha512-v4zIMr/cX7/d2BpAEX3KNKL/JrT1s43s96lLvvdTmza1oEvDudCqK9aF/djc/SWgy8Yh0h30TZx5VpzqFCxk5A=="],
|
||||||
|
|
||||||
"@types/node": ["@types/node@22.15.18", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-v1DKRfUdyW+jJhZNEI1PYy29S2YRxMV5AOO/x/SjKmW0acCIOqmbj6Haf9eHAhsPmrhlHSxEhv/1WszcLWV4cg=="],
|
"@types/node": ["@types/node@22.15.18", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-v1DKRfUdyW+jJhZNEI1PYy29S2YRxMV5AOO/x/SjKmW0acCIOqmbj6Haf9eHAhsPmrhlHSxEhv/1WszcLWV4cg=="],
|
||||||
|
|
||||||
@@ -200,13 +193,13 @@
|
|||||||
|
|
||||||
"buffer-from": ["buffer-from@1.1.2", "", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="],
|
"buffer-from": ["buffer-from@1.1.2", "", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="],
|
||||||
|
|
||||||
"bun-types": ["bun-types@1.3.4", "", { "dependencies": { "@types/node": "*" } }, "sha512-5ua817+BZPZOlNaRgGBpZJOSAQ9RQ17pkwPD0yR7CfJg+r8DgIILByFifDTa+IPDDxzf5VNhtNlcKqFzDgJvlQ=="],
|
"bun-types": ["bun-types@1.3.7", "", { "dependencies": { "@types/node": "*" } }, "sha512-qyschsA03Qz+gou+apt6HNl6HnI+sJJLL4wLDke4iugsE6584CMupOtTY1n+2YC9nGVrEKUlTs99jjRLKgWnjQ=="],
|
||||||
|
|
||||||
"bytes": ["bytes@3.1.0", "", {}, "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg=="],
|
"bytes": ["bytes@3.1.2", "", {}, "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg=="],
|
||||||
|
|
||||||
"debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
|
"debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
|
||||||
|
|
||||||
"depd": ["depd@1.1.2", "", {}, "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ=="],
|
"depd": ["depd@2.0.0", "", {}, "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="],
|
||||||
|
|
||||||
"discord-api-types": ["discord-api-types@0.38.36", "", {}, "sha512-qrbUbjjwtyeBg5HsAlm1C859epfOyiLjPqAOzkdWlCNsZCWJrertnETF/NwM8H+waMFU58xGSc5eXUfXah+WTQ=="],
|
"discord-api-types": ["discord-api-types@0.38.36", "", {}, "sha512-qrbUbjjwtyeBg5HsAlm1C859epfOyiLjPqAOzkdWlCNsZCWJrertnETF/NwM8H+waMFU58xGSc5eXUfXah+WTQ=="],
|
||||||
|
|
||||||
@@ -214,7 +207,7 @@
|
|||||||
|
|
||||||
"drizzle-kit": ["drizzle-kit@0.31.8", "", { "dependencies": { "@drizzle-team/brocli": "^0.10.2", "@esbuild-kit/esm-loader": "^2.5.5", "esbuild": "^0.25.4", "esbuild-register": "^3.5.0" }, "bin": { "drizzle-kit": "bin.cjs" } }, "sha512-O9EC/miwdnRDY10qRxM8P3Pg8hXe3LyU4ZipReKOgTwn4OqANmftj8XJz1UPUAS6NMHf0E2htjsbQujUTkncCg=="],
|
"drizzle-kit": ["drizzle-kit@0.31.8", "", { "dependencies": { "@drizzle-team/brocli": "^0.10.2", "@esbuild-kit/esm-loader": "^2.5.5", "esbuild": "^0.25.4", "esbuild-register": "^3.5.0" }, "bin": { "drizzle-kit": "bin.cjs" } }, "sha512-O9EC/miwdnRDY10qRxM8P3Pg8hXe3LyU4ZipReKOgTwn4OqANmftj8XJz1UPUAS6NMHf0E2htjsbQujUTkncCg=="],
|
||||||
|
|
||||||
"drizzle-orm": ["drizzle-orm@0.44.7", "", { "peerDependencies": { "@aws-sdk/client-rds-data": ">=3", "@cloudflare/workers-types": ">=4", "@electric-sql/pglite": ">=0.2.0", "@libsql/client": ">=0.10.0", "@libsql/client-wasm": ">=0.10.0", "@neondatabase/serverless": ">=0.10.0", "@op-engineering/op-sqlite": ">=2", "@opentelemetry/api": "^1.4.1", "@planetscale/database": ">=1.13", "@prisma/client": "*", "@tidbcloud/serverless": "*", "@types/better-sqlite3": "*", "@types/pg": "*", "@types/sql.js": "*", "@upstash/redis": ">=1.34.7", "@vercel/postgres": ">=0.8.0", "@xata.io/client": "*", "better-sqlite3": ">=7", "bun-types": "*", "expo-sqlite": ">=14.0.0", "gel": ">=2", "knex": "*", "kysely": "*", "mysql2": ">=2", "pg": ">=8", "postgres": ">=3", "sql.js": ">=1", "sqlite3": ">=5" }, "optionalPeers": ["@aws-sdk/client-rds-data", "@cloudflare/workers-types", "@electric-sql/pglite", "@libsql/client", "@libsql/client-wasm", "@neondatabase/serverless", "@op-engineering/op-sqlite", "@opentelemetry/api", "@planetscale/database", "@prisma/client", "@tidbcloud/serverless", "@types/better-sqlite3", "@types/pg", "@types/sql.js", "@upstash/redis", "@vercel/postgres", "@xata.io/client", "better-sqlite3", "bun-types", "expo-sqlite", "gel", "knex", "kysely", "mysql2", "pg", "postgres", "sql.js", "sqlite3"] }, "sha512-quIpnYznjU9lHshEOAYLoZ9s3jweleHlZIAWR/jX9gAWNg/JhQ1wj0KGRf7/Zm+obRrYd9GjPVJg790QY9N5AQ=="],
|
"drizzle-orm": ["drizzle-orm@0.45.1", "", { "peerDependencies": { "@aws-sdk/client-rds-data": ">=3", "@cloudflare/workers-types": ">=4", "@electric-sql/pglite": ">=0.2.0", "@libsql/client": ">=0.10.0", "@libsql/client-wasm": ">=0.10.0", "@neondatabase/serverless": ">=0.10.0", "@op-engineering/op-sqlite": ">=2", "@opentelemetry/api": "^1.4.1", "@planetscale/database": ">=1.13", "@prisma/client": "*", "@tidbcloud/serverless": "*", "@types/better-sqlite3": "*", "@types/pg": "*", "@types/sql.js": "*", "@upstash/redis": ">=1.34.7", "@vercel/postgres": ">=0.8.0", "@xata.io/client": "*", "better-sqlite3": ">=7", "bun-types": "*", "expo-sqlite": ">=14.0.0", "gel": ">=2", "knex": "*", "kysely": "*", "mysql2": ">=2", "pg": ">=8", "postgres": ">=3", "sql.js": ">=1", "sqlite3": ">=5" }, "optionalPeers": ["@aws-sdk/client-rds-data", "@cloudflare/workers-types", "@electric-sql/pglite", "@libsql/client", "@libsql/client-wasm", "@neondatabase/serverless", "@op-engineering/op-sqlite", "@opentelemetry/api", "@planetscale/database", "@prisma/client", "@tidbcloud/serverless", "@types/better-sqlite3", "@types/pg", "@types/sql.js", "@upstash/redis", "@vercel/postgres", "@xata.io/client", "better-sqlite3", "bun-types", "expo-sqlite", "gel", "knex", "kysely", "mysql2", "pg", "postgres", "sql.js", "sqlite3"] }, "sha512-Te0FOdKIistGNPMq2jscdqngBRfBpC8uMFVwqjf6gtTVJHIQ/dosgV/CLBU2N4ZJBsXL5savCba9b0YJskKdcA=="],
|
||||||
|
|
||||||
"esbuild": ["esbuild@0.25.9", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.9", "@esbuild/android-arm": "0.25.9", "@esbuild/android-arm64": "0.25.9", "@esbuild/android-x64": "0.25.9", "@esbuild/darwin-arm64": "0.25.9", "@esbuild/darwin-x64": "0.25.9", "@esbuild/freebsd-arm64": "0.25.9", "@esbuild/freebsd-x64": "0.25.9", "@esbuild/linux-arm": "0.25.9", "@esbuild/linux-arm64": "0.25.9", "@esbuild/linux-ia32": "0.25.9", "@esbuild/linux-loong64": "0.25.9", "@esbuild/linux-mips64el": "0.25.9", "@esbuild/linux-ppc64": "0.25.9", "@esbuild/linux-riscv64": "0.25.9", "@esbuild/linux-s390x": "0.25.9", "@esbuild/linux-x64": "0.25.9", "@esbuild/netbsd-arm64": "0.25.9", "@esbuild/netbsd-x64": "0.25.9", "@esbuild/openbsd-arm64": "0.25.9", "@esbuild/openbsd-x64": "0.25.9", "@esbuild/openharmony-arm64": "0.25.9", "@esbuild/sunos-x64": "0.25.9", "@esbuild/win32-arm64": "0.25.9", "@esbuild/win32-ia32": "0.25.9", "@esbuild/win32-x64": "0.25.9" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-CRbODhYyQx3qp7ZEwzxOk4JBqmD/seJrzPa/cGjY1VtIn5E09Oi9/dB4JwctnfZ8Q8iT7rioVv5k/FNT/uf54g=="],
|
"esbuild": ["esbuild@0.25.9", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.9", "@esbuild/android-arm": "0.25.9", "@esbuild/android-arm64": "0.25.9", "@esbuild/android-x64": "0.25.9", "@esbuild/darwin-arm64": "0.25.9", "@esbuild/darwin-x64": "0.25.9", "@esbuild/freebsd-arm64": "0.25.9", "@esbuild/freebsd-x64": "0.25.9", "@esbuild/linux-arm": "0.25.9", "@esbuild/linux-arm64": "0.25.9", "@esbuild/linux-ia32": "0.25.9", "@esbuild/linux-loong64": "0.25.9", "@esbuild/linux-mips64el": "0.25.9", "@esbuild/linux-ppc64": "0.25.9", "@esbuild/linux-riscv64": "0.25.9", "@esbuild/linux-s390x": "0.25.9", "@esbuild/linux-x64": "0.25.9", "@esbuild/netbsd-arm64": "0.25.9", "@esbuild/netbsd-x64": "0.25.9", "@esbuild/openbsd-arm64": "0.25.9", "@esbuild/openbsd-x64": "0.25.9", "@esbuild/openharmony-arm64": "0.25.9", "@esbuild/sunos-x64": "0.25.9", "@esbuild/win32-arm64": "0.25.9", "@esbuild/win32-ia32": "0.25.9", "@esbuild/win32-x64": "0.25.9" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-CRbODhYyQx3qp7ZEwzxOk4JBqmD/seJrzPa/cGjY1VtIn5E09Oi9/dB4JwctnfZ8Q8iT7rioVv5k/FNT/uf54g=="],
|
||||||
|
|
||||||
@@ -224,16 +217,14 @@
|
|||||||
|
|
||||||
"get-tsconfig": ["get-tsconfig@4.10.1", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ=="],
|
"get-tsconfig": ["get-tsconfig@4.10.1", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ=="],
|
||||||
|
|
||||||
"http-errors": ["http-errors@1.7.3", "", { "dependencies": { "depd": "~1.1.2", "inherits": "2.0.4", "setprototypeof": "1.1.1", "statuses": ">= 1.5.0 < 2", "toidentifier": "1.0.0" } }, "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw=="],
|
"http-errors": ["http-errors@2.0.1", "", { "dependencies": { "depd": "~2.0.0", "inherits": "~2.0.4", "setprototypeof": "~1.2.0", "statuses": "~2.0.2", "toidentifier": "~1.0.1" } }, "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ=="],
|
||||||
|
|
||||||
"httpanda": ["httpanda@0.4.7", "", { "dependencies": { "@types/node": "^14.11.2", "tslib": "^2.0.3" } }, "sha512-NieTiR7kfOheL9OeEi6+JKFmJ2JP9ZRqUQ4tiXZ9J+EMMKxApHUQlEM5l4gZ+l67lxE9Er6oigZnujmhlodNCg=="],
|
"httpanda": ["httpanda@0.4.7", "", { "dependencies": { "@types/node": "^14.11.2", "tslib": "^2.0.3" } }, "sha512-NieTiR7kfOheL9OeEi6+JKFmJ2JP9ZRqUQ4tiXZ9J+EMMKxApHUQlEM5l4gZ+l67lxE9Er6oigZnujmhlodNCg=="],
|
||||||
|
|
||||||
"iconv-lite": ["iconv-lite@0.4.24", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3" } }, "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA=="],
|
"iconv-lite": ["iconv-lite@0.7.2", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw=="],
|
||||||
|
|
||||||
"inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="],
|
"inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="],
|
||||||
|
|
||||||
"kleur": ["kleur@4.1.5", "", {}, "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ=="],
|
|
||||||
|
|
||||||
"klona": ["klona@2.0.6", "", {}, "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA=="],
|
"klona": ["klona@2.0.6", "", {}, "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA=="],
|
||||||
|
|
||||||
"lodash": ["lodash@4.17.21", "", {}, "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="],
|
"lodash": ["lodash@4.17.21", "", {}, "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="],
|
||||||
@@ -244,19 +235,17 @@
|
|||||||
|
|
||||||
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
|
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
|
||||||
|
|
||||||
"node-fetch": ["node-fetch@2.7.0", "", { "dependencies": { "whatwg-url": "^5.0.0" }, "peerDependencies": { "encoding": "^0.1.0" }, "optionalPeers": ["encoding"] }, "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A=="],
|
"pg": ["pg@8.17.2", "", { "dependencies": { "pg-connection-string": "^2.10.1", "pg-pool": "^3.11.0", "pg-protocol": "^1.11.0", "pg-types": "2.2.0", "pgpass": "1.0.5" }, "optionalDependencies": { "pg-cloudflare": "^1.3.0" }, "peerDependencies": { "pg-native": ">=3.0.1" }, "optionalPeers": ["pg-native"] }, "sha512-vjbKdiBJRqzcYw1fNU5KuHyYvdJ1qpcQg1CeBrHFqV1pWgHeVR6j/+kX0E1AAXfyuLUGY1ICrN2ELKA/z2HWzw=="],
|
||||||
|
|
||||||
"pg": ["pg@8.16.3", "", { "dependencies": { "pg-connection-string": "^2.9.1", "pg-pool": "^3.10.1", "pg-protocol": "^1.10.3", "pg-types": "2.2.0", "pgpass": "1.0.5" }, "optionalDependencies": { "pg-cloudflare": "^1.2.7" }, "peerDependencies": { "pg-native": ">=3.0.1" }, "optionalPeers": ["pg-native"] }, "sha512-enxc1h0jA/aq5oSDMvqyW3q89ra6XIIDZgCX9vkMrnz5DFTw/Ny3Li2lFQ+pt3L6MCgm/5o2o8HW9hiJji+xvw=="],
|
"pg-cloudflare": ["pg-cloudflare@1.3.0", "", {}, "sha512-6lswVVSztmHiRtD6I8hw4qP/nDm1EJbKMRhf3HCYaqud7frGysPv7FYJ5noZQdhQtN2xJnimfMtvQq21pdbzyQ=="],
|
||||||
|
|
||||||
"pg-cloudflare": ["pg-cloudflare@1.2.7", "", {}, "sha512-YgCtzMH0ptvZJslLM1ffsY4EuGaU0cx4XSdXLRFae8bPP4dS5xL1tNB3k2o/N64cHJpwU7dxKli/nZ2lUa5fLg=="],
|
"pg-connection-string": ["pg-connection-string@2.10.1", "", {}, "sha512-iNzslsoeSH2/gmDDKiyMqF64DATUCWj3YJ0wP14kqcsf2TUklwimd+66yYojKwZCA7h2yRNLGug71hCBA2a4sw=="],
|
||||||
|
|
||||||
"pg-connection-string": ["pg-connection-string@2.9.1", "", {}, "sha512-nkc6NpDcvPVpZXxrreI/FOtX3XemeLl8E0qFr6F2Lrm/I8WOnaWNhIPK2Z7OHpw7gh5XJThi6j6ppgNoaT1w4w=="],
|
|
||||||
|
|
||||||
"pg-int8": ["pg-int8@1.0.1", "", {}, "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw=="],
|
"pg-int8": ["pg-int8@1.0.1", "", {}, "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw=="],
|
||||||
|
|
||||||
"pg-pool": ["pg-pool@3.10.1", "", { "peerDependencies": { "pg": ">=8.0" } }, "sha512-Tu8jMlcX+9d8+QVzKIvM/uJtp07PKr82IUOYEphaWcoBhIYkoHpLXN3qO59nAI11ripznDsEzEv8nUxBVWajGg=="],
|
"pg-pool": ["pg-pool@3.11.0", "", { "peerDependencies": { "pg": ">=8.0" } }, "sha512-MJYfvHwtGp870aeusDh+hg9apvOe2zmpZJpyt+BMtzUWlVqbhFmMK6bOBXLBUPd7iRtIF9fZplDc7KrPN3PN7w=="],
|
||||||
|
|
||||||
"pg-protocol": ["pg-protocol@1.10.3", "", {}, "sha512-6DIBgBQaTKDJyxnXaLiLR8wBpQQcGWuAESkRBX/t6OwA8YsqP+iVSiond2EDy6Y/dsGk8rh/jtax3js5NeV7JQ=="],
|
"pg-protocol": ["pg-protocol@1.11.0", "", {}, "sha512-pfsxk2M9M3BuGgDOfuy37VNRRX3jmKgMjcvAcWqNDpZSf4cUmv8HSOl5ViRQFsfARFn0KuUQTgLxVMbNq5NW3g=="],
|
||||||
|
|
||||||
"pg-types": ["pg-types@2.2.0", "", { "dependencies": { "pg-int8": "1.0.1", "postgres-array": "~2.0.0", "postgres-bytea": "~1.0.0", "postgres-date": "~1.0.4", "postgres-interval": "^1.1.0" } }, "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA=="],
|
"pg-types": ["pg-types@2.2.0", "", { "dependencies": { "pg-int8": "1.0.1", "postgres-array": "~2.0.0", "postgres-bytea": "~1.0.0", "postgres-date": "~1.0.4", "postgres-interval": "^1.1.0" } }, "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA=="],
|
||||||
|
|
||||||
@@ -270,13 +259,15 @@
|
|||||||
|
|
||||||
"postgres-interval": ["postgres-interval@1.2.0", "", { "dependencies": { "xtend": "^4.0.0" } }, "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ=="],
|
"postgres-interval": ["postgres-interval@1.2.0", "", { "dependencies": { "xtend": "^4.0.0" } }, "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ=="],
|
||||||
|
|
||||||
|
"raw-body": ["raw-body@3.0.2", "", { "dependencies": { "bytes": "~3.1.2", "http-errors": "~2.0.1", "iconv-lite": "~0.7.0", "unpipe": "~1.0.0" } }, "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA=="],
|
||||||
|
|
||||||
"resolve-pkg-maps": ["resolve-pkg-maps@1.0.0", "", {}, "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw=="],
|
"resolve-pkg-maps": ["resolve-pkg-maps@1.0.0", "", {}, "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw=="],
|
||||||
|
|
||||||
"retry": ["retry@0.13.1", "", {}, "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg=="],
|
"retry": ["retry@0.13.1", "", {}, "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg=="],
|
||||||
|
|
||||||
"safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="],
|
"safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="],
|
||||||
|
|
||||||
"setprototypeof": ["setprototypeof@1.1.1", "", {}, "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw=="],
|
"setprototypeof": ["setprototypeof@1.2.0", "", {}, "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="],
|
||||||
|
|
||||||
"source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="],
|
"source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="],
|
||||||
|
|
||||||
@@ -284,11 +275,9 @@
|
|||||||
|
|
||||||
"split2": ["split2@4.2.0", "", {}, "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg=="],
|
"split2": ["split2@4.2.0", "", {}, "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg=="],
|
||||||
|
|
||||||
"statuses": ["statuses@1.5.0", "", {}, "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA=="],
|
"statuses": ["statuses@2.0.2", "", {}, "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw=="],
|
||||||
|
|
||||||
"toidentifier": ["toidentifier@1.0.0", "", {}, "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw=="],
|
"toidentifier": ["toidentifier@1.0.1", "", {}, "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="],
|
||||||
|
|
||||||
"tr46": ["tr46@0.0.3", "", {}, "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="],
|
|
||||||
|
|
||||||
"ts-mixer": ["ts-mixer@6.0.4", "", {}, "sha512-ufKpbmrugz5Aou4wcr5Wc1UUFWOLhq+Fm6qa6P0w0K5Qw2yhaUoiWszhCVuNQyNwrlGiscHOmqYoAox1PtvgjA=="],
|
"ts-mixer": ["ts-mixer@6.0.4", "", {}, "sha512-ufKpbmrugz5Aou4wcr5Wc1UUFWOLhq+Fm6qa6P0w0K5Qw2yhaUoiWszhCVuNQyNwrlGiscHOmqYoAox1PtvgjA=="],
|
||||||
|
|
||||||
@@ -302,10 +291,6 @@
|
|||||||
|
|
||||||
"unpipe": ["unpipe@1.0.0", "", {}, "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ=="],
|
"unpipe": ["unpipe@1.0.0", "", {}, "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ=="],
|
||||||
|
|
||||||
"webidl-conversions": ["webidl-conversions@3.0.1", "", {}, "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="],
|
|
||||||
|
|
||||||
"whatwg-url": ["whatwg-url@5.0.0", "", { "dependencies": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" } }, "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw=="],
|
|
||||||
|
|
||||||
"ws": ["ws@8.18.3", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg=="],
|
"ws": ["ws@8.18.3", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg=="],
|
||||||
|
|
||||||
"xtend": ["xtend@4.0.2", "", {}, "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ=="],
|
"xtend": ["xtend@4.0.2", "", {}, "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ=="],
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
in {
|
in {
|
||||||
devShells."${system}" = {
|
devShells."${system}" = {
|
||||||
default = pkgs.mkShell {
|
default = pkgs.mkShell {
|
||||||
packages = with pkgs; [ bun nodejs deno ];
|
packages = with pkgs; [ bun biome ];
|
||||||
shellHook = ''
|
shellHook = ''
|
||||||
echo Loaded the qweribot dev shell
|
echo Loaded the qweribot dev shell
|
||||||
'';
|
'';
|
||||||
|
|||||||
15
package.json
15
package.json
@@ -2,11 +2,11 @@
|
|||||||
"name": "qweribot",
|
"name": "qweribot",
|
||||||
"module": "src/index.ts",
|
"module": "src/index.ts",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@biomejs/biome": "^2.3.8",
|
"@biomejs/biome": "^2.3.13",
|
||||||
"@twurple/eventsub-ngrok": "^7.4.0",
|
"@twurple/eventsub-ngrok": "^8.0.3",
|
||||||
"@types/bun": "latest",
|
"@types/bun": "latest",
|
||||||
"drizzle-kit": "^0.31.8",
|
"drizzle-kit": "^0.31.8",
|
||||||
"pg": "^8.16.3"
|
"pg": "^8.17.2"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"check": "biome check && tsc -b",
|
"check": "biome check && tsc -b",
|
||||||
@@ -26,11 +26,10 @@
|
|||||||
"type": "module",
|
"type": "module",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fontsource/jersey-15": "^5.2.8",
|
"@fontsource/jersey-15": "^5.2.8",
|
||||||
"@twurple/api": "7.4.0",
|
"@twurple/api": "8.0.3",
|
||||||
"@twurple/auth": "^7.4.0",
|
"@twurple/auth": "^8.0.3",
|
||||||
"@twurple/eventsub-http": "^7.4.0",
|
"@twurple/eventsub-http": "^8.0.3",
|
||||||
"discord.js": "^14.25.1",
|
"discord.js": "^14.25.1",
|
||||||
"drizzle-orm": "^0.44.7",
|
"drizzle-orm": "^0.45.1"
|
||||||
"kleur": "^4.1.5"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
20
src/auth.ts
20
src/auth.ts
@@ -9,7 +9,6 @@ import {
|
|||||||
getAuthRecord,
|
getAuthRecord,
|
||||||
updateAuthRecord,
|
updateAuthRecord,
|
||||||
} from "db/dbAuth";
|
} from "db/dbAuth";
|
||||||
import kleur from "kleur";
|
|
||||||
import logger from "lib/logger";
|
import logger from "lib/logger";
|
||||||
|
|
||||||
async function initAuth(
|
async function initAuth(
|
||||||
@@ -26,15 +25,10 @@ async function initAuth(
|
|||||||
const state = Bun.randomUUIDv7().replace(/-/g, "").slice(0, 32).toUpperCase();
|
const state = Bun.randomUUIDv7().replace(/-/g, "").slice(0, 32).toUpperCase();
|
||||||
// Generate random state variable to prevent cross-site-scripting attacks
|
// Generate random state variable to prevent cross-site-scripting attacks
|
||||||
|
|
||||||
const instruction = `Visit this URL as ${kleur
|
const instruction = `Visit this URL as \x1b[3;4;1;95m${streamer ? "the streamer" : "the chatter"}\x1b[0;97m to authenticate the bot.`;
|
||||||
.red()
|
|
||||||
.underline()
|
|
||||||
.italic(
|
|
||||||
streamer ? "the streamer" : "the chatter",
|
|
||||||
)} to authenticate the bot.`;
|
|
||||||
logger.info(instruction);
|
logger.info(instruction);
|
||||||
logger.info(
|
logger.info(
|
||||||
`https://id.twitch.tv/oauth2/authorize?client_id=${clientId}&redirect_uri=${redirectURL}&response_type=code&scope=${requestedIntents.join("+")}&state=${state}`,
|
`\x1b[3;4;1;95mhttps://id.twitch.tv/oauth2/authorize?client_id=${clientId}&redirect_uri=${redirectURL}&response_type=code&scope=${requestedIntents.join("+")}&state=${state}\x1b[0;97m`,
|
||||||
);
|
);
|
||||||
|
|
||||||
const createCodePromise = () => {
|
const createCodePromise = () => {
|
||||||
@@ -61,7 +55,7 @@ async function initAuth(
|
|||||||
return new Response("Successfully authenticated!");
|
return new Response("Successfully authenticated!");
|
||||||
} else {
|
} else {
|
||||||
return new Response(
|
return new Response(
|
||||||
`Authentication attempt unsuccessful, please make sure the redirect url in the twitch developer console is set to ${redirectURL} and that the bot is listening to that url & port.`,
|
`Authentication attempt unsuccessful, please make sure the redirect url in the twitch developer console is set to \x1b[3;4;1;95m${redirectURL}\x1b[0;97m and that the bot is listening to that url & port.`,
|
||||||
{ status: 400 },
|
{ status: 400 },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -112,13 +106,15 @@ export async function createAuthProvider(
|
|||||||
});
|
});
|
||||||
|
|
||||||
authData.onRefresh(async (user, token) => {
|
authData.onRefresh(async (user, token) => {
|
||||||
logger.ok(`Successfully refreshed auth for user ${user}`);
|
logger.ok(
|
||||||
|
`Successfully refreshed auth for user \x1b[3;4;1;95m${user}\x1b[0;97m`,
|
||||||
|
);
|
||||||
await updateAuthRecord(user, token);
|
await updateAuthRecord(user, token);
|
||||||
});
|
});
|
||||||
|
|
||||||
authData.onRefreshFailure((user, err) => {
|
authData.onRefreshFailure((user, err) => {
|
||||||
logger.err(
|
logger.err(
|
||||||
`Failed to refresh auth for user ${user}: ${err.name} ${err.message}`,
|
`Failed to refresh auth for user \x1b[3;4;1;95m${user}\x1b[0;97m: ${err.name} ${err.message}`,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -149,7 +145,7 @@ export async function createAuthProvider(
|
|||||||
await authData.refreshAccessTokenForUser(user.userId);
|
await authData.refreshAccessTokenForUser(user.userId);
|
||||||
} catch (_err) {
|
} catch (_err) {
|
||||||
logger.err(
|
logger.err(
|
||||||
`Failed to refresh user ${user.userId}. Please restart the bot and re-authenticate it. Make sure the user that auths the bot and the user that's defined in .env are the same.`,
|
`Failed to refresh user \x1b[3;4;1;95m${user.userId}\x1b[0;97m. Please restart the bot and re-authenticate it. Make sure the user that auths the bot and the user that's defined in .env are the same.`,
|
||||||
);
|
);
|
||||||
await deleteAuthRecord(user.userId);
|
await deleteAuthRecord(user.userId);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import { Cheer, handleNoTarget } from "cheers";
|
import { Cheer, handleNoTarget } from "cheers";
|
||||||
import { createCheerEventRecord } from "db/dbCheerEvents";
|
import {
|
||||||
import { createTimeoutRecord } from "db/dbTimeouts";
|
createCompensatedItemCheer,
|
||||||
|
createTimeoutEventCheer,
|
||||||
|
} from "db/CheerEvents";
|
||||||
import { getUserRecord } from "db/dbUser";
|
import { getUserRecord } from "db/dbUser";
|
||||||
import { sendMessage } from "lib/commandUtils";
|
import { sendMessage } from "lib/commandUtils";
|
||||||
import { parseCheerArgs } from "lib/parseCommandArgs";
|
import { parseCheerArgs } from "lib/parseCommandArgs";
|
||||||
@@ -30,7 +32,8 @@ export default new Cheer({
|
|||||||
}
|
}
|
||||||
if (users.length === 0) {
|
if (users.length === 0) {
|
||||||
await sendMessage("No vulnerable chatters");
|
await sendMessage("No vulnerable chatters");
|
||||||
await handleNoTarget(msg, user, ITEMNAME, true);
|
const compensated = await handleNoTarget(msg, user, ITEMNAME, true);
|
||||||
|
if (compensated) await createCompensatedItemCheer(user, ITEMNAME);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
target = users[Math.floor(Math.random() * users.length)]!;
|
target = users[Math.floor(Math.random() * users.length)]!;
|
||||||
@@ -45,7 +48,8 @@ export default new Cheer({
|
|||||||
target = await User.initUsername(args[0].toLowerCase());
|
target = await User.initUsername(args[0].toLowerCase());
|
||||||
}
|
}
|
||||||
if (!target) {
|
if (!target) {
|
||||||
await handleNoTarget(msg, user, ITEMNAME, false);
|
const compensated = await handleNoTarget(msg, user, ITEMNAME);
|
||||||
|
if (compensated) await createCompensatedItemCheer(user, ITEMNAME);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await getUserRecord(target);
|
await getUserRecord(target);
|
||||||
@@ -60,8 +64,7 @@ export default new Cheer({
|
|||||||
sendMessage(
|
sendMessage(
|
||||||
`KEKPOINT KEKPOINT KEKPOINT ${target.displayName.toUpperCase()} RIPBOZO RIPBOZO RIPBOZO RIPBOZO RIPBOZO RIPBOZO RIPBOZO`,
|
`KEKPOINT KEKPOINT KEKPOINT ${target.displayName.toUpperCase()} RIPBOZO RIPBOZO RIPBOZO RIPBOZO RIPBOZO RIPBOZO RIPBOZO`,
|
||||||
),
|
),
|
||||||
createTimeoutRecord(user, target, ITEMNAME),
|
createTimeoutEventCheer(user, target, "execute"),
|
||||||
createCheerEventRecord(user, ITEMNAME),
|
|
||||||
playAlert({
|
playAlert({
|
||||||
name: "userExecution",
|
name: "userExecution",
|
||||||
user: user.displayName,
|
user: user.displayName,
|
||||||
@@ -69,7 +72,8 @@ export default new Cheer({
|
|||||||
}),
|
}),
|
||||||
]);
|
]);
|
||||||
else {
|
else {
|
||||||
await handleNoTarget(msg, user, ITEMNAME);
|
const compensated = await handleNoTarget(msg, user, ITEMNAME);
|
||||||
|
if (compensated) await createCompensatedItemCheer(user, ITEMNAME);
|
||||||
switch (result.reason) {
|
switch (result.reason) {
|
||||||
case "banned":
|
case "banned":
|
||||||
await sendMessage(
|
await sendMessage(
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import { Cheer, handleNoTarget } from "cheers";
|
import { Cheer, handleNoTarget } from "cheers";
|
||||||
import { createCheerEventRecord } from "db/dbCheerEvents";
|
import {
|
||||||
import { createTimeoutRecord } from "db/dbTimeouts";
|
createCompensatedItemCheer,
|
||||||
|
createTimeoutEventCheer,
|
||||||
|
} from "db/CheerEvents";
|
||||||
import { getUserRecord } from "db/dbUser";
|
import { getUserRecord } from "db/dbUser";
|
||||||
import { sendMessage } from "lib/commandUtils";
|
import { sendMessage } from "lib/commandUtils";
|
||||||
import { redis } from "lib/redis";
|
import { redis } from "lib/redis";
|
||||||
@@ -18,7 +20,8 @@ export default new Cheer({
|
|||||||
const targets = await redis.keys(`user:*:vulnerable`);
|
const targets = await redis.keys(`user:*:vulnerable`);
|
||||||
if (targets.length === 0) {
|
if (targets.length === 0) {
|
||||||
await sendMessage("No vulnerable chatters to blow up!", msg.messageId);
|
await sendMessage("No vulnerable chatters to blow up!", msg.messageId);
|
||||||
await handleNoTarget(msg, user, ITEMNAME);
|
const compensated = await handleNoTarget(msg, user, ITEMNAME, true);
|
||||||
|
if (compensated) await createCompensatedItemCheer(user, ITEMNAME);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const selection = targets[Math.floor(Math.random() * targets.length)]!;
|
const selection = targets[Math.floor(Math.random() * targets.length)]!;
|
||||||
@@ -32,8 +35,7 @@ export default new Cheer({
|
|||||||
sendMessage(
|
sendMessage(
|
||||||
`wybuh ${target?.displayName} got hit by ${user.displayName}'s grenade wybuh`,
|
`wybuh ${target?.displayName} got hit by ${user.displayName}'s grenade wybuh`,
|
||||||
),
|
),
|
||||||
createTimeoutRecord(user, target!, ITEMNAME),
|
createTimeoutEventCheer(user, target!, "grenade"),
|
||||||
createCheerEventRecord(user, ITEMNAME),
|
|
||||||
playAlert({
|
playAlert({
|
||||||
name: "grenadeExplosion",
|
name: "grenadeExplosion",
|
||||||
user: user.displayName,
|
user: user.displayName,
|
||||||
|
|||||||
@@ -63,13 +63,13 @@ export async function handleNoTarget(
|
|||||||
user: User,
|
user: User,
|
||||||
itemname: items,
|
itemname: items,
|
||||||
silent = true,
|
silent = true,
|
||||||
) {
|
): Promise<boolean> {
|
||||||
if (await user.itemLock()) {
|
if (await user.itemLock()) {
|
||||||
await sendMessage(
|
await sendMessage(
|
||||||
`Cannot give ${user.displayName} a ${itemname} (itemlock)`,
|
`Cannot give ${user.displayName} a ${itemname} (itemlock)`,
|
||||||
msg.messageId,
|
msg.messageId,
|
||||||
);
|
);
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
await user.setLock();
|
await user.setLock();
|
||||||
const userRecord = await getUserRecord(user);
|
const userRecord = await getUserRecord(user);
|
||||||
@@ -80,4 +80,5 @@ export async function handleNoTarget(
|
|||||||
);
|
);
|
||||||
await changeItemCount(user, userRecord, itemname, 1);
|
await changeItemCount(user, userRecord, itemname, 1);
|
||||||
await user.clearLock();
|
await user.clearLock();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { Cheer } from "cheers";
|
import { Cheer } from "cheers";
|
||||||
import { createCheerEventRecord } from "db/dbCheerEvents";
|
import { createTimeoutEventCheer } from "db/CheerEvents";
|
||||||
import { createTimeoutRecord } from "db/dbTimeouts";
|
|
||||||
import { getUserRecord } from "db/dbUser";
|
import { getUserRecord } from "db/dbUser";
|
||||||
import { sendMessage } from "lib/commandUtils";
|
import { sendMessage } from "lib/commandUtils";
|
||||||
import { parseCheerArgs } from "lib/parseCommandArgs";
|
import { parseCheerArgs } from "lib/parseCommandArgs";
|
||||||
@@ -57,8 +56,7 @@ export default new Cheer({
|
|||||||
sendMessage(
|
sendMessage(
|
||||||
`KEKPOINT KEKPOINT KEKPOINT ${target.displayName.toUpperCase()} RIPBOZO RIPBOZO RIPBOZO RIPBOZO RIPBOZO RIPBOZO RIPBOZO`,
|
`KEKPOINT KEKPOINT KEKPOINT ${target.displayName.toUpperCase()} RIPBOZO RIPBOZO RIPBOZO RIPBOZO RIPBOZO RIPBOZO RIPBOZO`,
|
||||||
),
|
),
|
||||||
createTimeoutRecord(user, target, "realsilverbullet"),
|
createTimeoutEventCheer(user, target, "realsilverbullet"),
|
||||||
createCheerEventRecord(user, "realsilverbullet"),
|
|
||||||
playAlert({
|
playAlert({
|
||||||
name: "userExecution",
|
name: "userExecution",
|
||||||
user: user.displayName,
|
user: user.displayName,
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { Cheer } from "cheers";
|
import { Cheer } from "cheers";
|
||||||
import { createCheerEventRecord } from "db/dbCheerEvents";
|
import { createSuperLootEvent } from "db/CheerEvents";
|
||||||
import { createGetLootRecord } from "db/dbGetLoot";
|
|
||||||
import { getUserRecord, updateUserRecord } from "db/dbUser";
|
import { getUserRecord, updateUserRecord } from "db/dbUser";
|
||||||
import itemMap, { type inventory, type items } from "items";
|
import itemMap, { type inventory, type items } from "items";
|
||||||
import { sendMessage } from "lib/commandUtils";
|
import { sendMessage } from "lib/commandUtils";
|
||||||
@@ -12,10 +11,10 @@ export default new Cheer({
|
|||||||
amount: 150,
|
amount: 150,
|
||||||
isItem: true,
|
isItem: true,
|
||||||
async execute(msg, user) {
|
async execute(msg, user) {
|
||||||
if (!(await redis.exists("streamIsLive"))) {
|
// if (!(await redis.exists("streamIsLive"))) {
|
||||||
await sendMessage(`No loot while stream is offline`, msg.messageId);
|
// await sendMessage(`No loot while stream is offline`, msg.messageId);
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
if (await user.itemLock()) {
|
if (await user.itemLock()) {
|
||||||
await sendMessage(`Cannot get loot (itemlock)`, msg.messageId);
|
await sendMessage(`Cannot get loot (itemlock)`, msg.messageId);
|
||||||
return;
|
return;
|
||||||
@@ -81,8 +80,7 @@ export default new Cheer({
|
|||||||
await Promise.all([
|
await Promise.all([
|
||||||
updateUserRecord(user, userData),
|
updateUserRecord(user, userData),
|
||||||
sendMessage(message, msg.messageId),
|
sendMessage(message, msg.messageId),
|
||||||
createCheerEventRecord(user, "superloot"),
|
createSuperLootEvent(user, gainedqbucks, itemDiff),
|
||||||
createGetLootRecord(user, gainedqbucks, itemDiff, "superloot"),
|
|
||||||
user.clearLock(),
|
user.clearLock(),
|
||||||
]);
|
]);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import { Cheer, handleNoTarget } from "cheers";
|
import { Cheer, handleNoTarget } from "cheers";
|
||||||
import { createCheerEventRecord } from "db/dbCheerEvents";
|
import {
|
||||||
import { createTimeoutRecord } from "db/dbTimeouts";
|
createTimeoutEventCheer,
|
||||||
|
createCompensatedItemCheer,
|
||||||
|
} from "db/CheerEvents";
|
||||||
import { getUserRecord } from "db/dbUser";
|
import { getUserRecord } from "db/dbUser";
|
||||||
import { sendMessage } from "lib/commandUtils";
|
import { sendMessage } from "lib/commandUtils";
|
||||||
import { parseCheerArgs } from "lib/parseCommandArgs";
|
import { parseCheerArgs } from "lib/parseCommandArgs";
|
||||||
@@ -17,12 +19,14 @@ export default new Cheer({
|
|||||||
async execute(msg, user) {
|
async execute(msg, user) {
|
||||||
const args = parseCheerArgs(msg.messageText);
|
const args = parseCheerArgs(msg.messageText);
|
||||||
if (!args[0]) {
|
if (!args[0]) {
|
||||||
await handleNoTarget(msg, user, ITEMNAME, false);
|
const compensated = await handleNoTarget(msg, user, ITEMNAME, false);
|
||||||
|
if (compensated) await createCompensatedItemCheer(user, ITEMNAME);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const target = await User.initUsername(args[0].toLowerCase());
|
const target = await User.initUsername(args[0].toLowerCase());
|
||||||
if (!target) {
|
if (!target) {
|
||||||
await handleNoTarget(msg, user, ITEMNAME, false);
|
const compensated = await handleNoTarget(msg, user, ITEMNAME, false);
|
||||||
|
if (compensated) await createCompensatedItemCheer(user, ITEMNAME);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await getUserRecord(target);
|
await getUserRecord(target);
|
||||||
@@ -37,8 +41,7 @@ export default new Cheer({
|
|||||||
sendMessage(
|
sendMessage(
|
||||||
`GOTTEM ${target.displayName} got BLASTED by ${user.displayName} GOTTEM`,
|
`GOTTEM ${target.displayName} got BLASTED by ${user.displayName} GOTTEM`,
|
||||||
),
|
),
|
||||||
createTimeoutRecord(user, target, ITEMNAME),
|
createTimeoutEventCheer(user, target, "timeout"),
|
||||||
createCheerEventRecord(user, ITEMNAME),
|
|
||||||
playAlert({
|
playAlert({
|
||||||
name: "userBlast",
|
name: "userBlast",
|
||||||
user: user.displayName,
|
user: user.displayName,
|
||||||
@@ -46,7 +49,8 @@ export default new Cheer({
|
|||||||
}),
|
}),
|
||||||
]);
|
]);
|
||||||
else {
|
else {
|
||||||
await handleNoTarget(msg, user, ITEMNAME);
|
const compensated = await handleNoTarget(msg, user, ITEMNAME);
|
||||||
|
if (compensated) await createCompensatedItemCheer(user, ITEMNAME);
|
||||||
switch (result.reason) {
|
switch (result.reason) {
|
||||||
case "banned":
|
case "banned":
|
||||||
await sendMessage(
|
await sendMessage(
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import { Cheer, handleNoTarget } from "cheers";
|
import { Cheer, handleNoTarget } from "cheers";
|
||||||
import { createCheerEventRecord } from "db/dbCheerEvents";
|
import {
|
||||||
import { createTimeoutRecord } from "db/dbTimeouts";
|
createTimeoutEventCheer,
|
||||||
|
createCompensatedItemCheer,
|
||||||
|
} from "db/CheerEvents";
|
||||||
import { getUserRecord } from "db/dbUser";
|
import { getUserRecord } from "db/dbUser";
|
||||||
import { getTNTTargets } from "items/tnt";
|
import { getTNTTargets } from "items/tnt";
|
||||||
import { sendMessage } from "lib/commandUtils";
|
import { sendMessage } from "lib/commandUtils";
|
||||||
@@ -21,7 +23,8 @@ export default new Cheer({
|
|||||||
.then((a) => a.map((b) => b.slice(5, -11)));
|
.then((a) => a.map((b) => b.slice(5, -11)));
|
||||||
if (vulntargets.length === 0) {
|
if (vulntargets.length === 0) {
|
||||||
await sendMessage("No vulnerable chatters to blow up", msg.messageId);
|
await sendMessage("No vulnerable chatters to blow up", msg.messageId);
|
||||||
await handleNoTarget(msg, user, ITEMNAME);
|
const compensated = await handleNoTarget(msg, user, ITEMNAME, true);
|
||||||
|
if (compensated) await createCompensatedItemCheer(user, ITEMNAME);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const targets = getTNTTargets(vulntargets);
|
const targets = getTNTTargets(vulntargets);
|
||||||
@@ -36,13 +39,12 @@ export default new Cheer({
|
|||||||
sendMessage(
|
sendMessage(
|
||||||
`wybuh ${target?.displayName} got hit by ${user.displayName}'s TNT wybuh`,
|
`wybuh ${target?.displayName} got hit by ${user.displayName}'s TNT wybuh`,
|
||||||
),
|
),
|
||||||
createTimeoutRecord(user, target!, ITEMNAME),
|
|
||||||
]);
|
]);
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
createCheerEventRecord(user, ITEMNAME),
|
createTimeoutEventCheer(user, targets, "tnt"),
|
||||||
playAlert({
|
playAlert({
|
||||||
name: "tntExplosion",
|
name: "tntExplosion",
|
||||||
user: user.displayName,
|
user: user.displayName,
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ export default new Command({
|
|||||||
const selection = namedRedeems.get(args[0]);
|
const selection = namedRedeems.get(args[0]);
|
||||||
if (!selection) {
|
if (!selection) {
|
||||||
await sendMessage(
|
await sendMessage(
|
||||||
`Redeem ${args[0]} doesn't exist. The internal names for redeems are here: https://github.com/qwerinope/qweribot#point-redeems`,
|
`Redeem ${args[0]} doesn't exist. The internal names for redeems are here: https://gitlab.com/qwerinope/qweribot#point-redeems`,
|
||||||
msg.messageId,
|
msg.messageId,
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
|
|||||||
22
src/commands/economy.ts
Normal file
22
src/commands/economy.ts
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import { getTotalItemCounts } from "db/dbUser";
|
||||||
|
import itemAliasMap from "items";
|
||||||
|
import { Command, sendMessage } from "lib/commandUtils";
|
||||||
|
|
||||||
|
export default new Command({
|
||||||
|
name: "economy",
|
||||||
|
aliases: ["economy", "eco"],
|
||||||
|
usertype: "chatter",
|
||||||
|
execution: async (msg) => {
|
||||||
|
const allitems = await getTotalItemCounts();
|
||||||
|
const itemList = Object.entries(allitems)
|
||||||
|
.sort(([, a], [, b]) => b - a)
|
||||||
|
.map(([item, count]) => {
|
||||||
|
const itemobj = itemAliasMap.get(item);
|
||||||
|
if (itemobj) return `${itemobj.prettyName}: ${count}`;
|
||||||
|
return `${item}: ${count}`; // Fallback if an item doesn't have their name as an alias
|
||||||
|
})
|
||||||
|
.join(" | ");
|
||||||
|
|
||||||
|
await sendMessage(`Total Items in circulation: ${itemList}`, msg.messageId);
|
||||||
|
},
|
||||||
|
});
|
||||||
@@ -39,7 +39,7 @@ export default new Command({
|
|||||||
const selection = namedRedeems.get(args[0]);
|
const selection = namedRedeems.get(args[0]);
|
||||||
if (!selection) {
|
if (!selection) {
|
||||||
await sendMessage(
|
await sendMessage(
|
||||||
`Redeem ${args[0]} doesn't exist. The internal names for redeems are here: https://github.com/qwerinope/qweribot#point-redeems`,
|
`Redeem ${args[0]} doesn't exist. The internal names for redeems are here: https://gitlab.com/qwerinope/qweribot#point-redeems`,
|
||||||
msg.messageId,
|
msg.messageId,
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ export default new Command({
|
|||||||
const args = parseCommandArgs(msg.messageText);
|
const args = parseCommandArgs(msg.messageText);
|
||||||
if (!args[0]) {
|
if (!args[0]) {
|
||||||
await sendMessage(
|
await sendMessage(
|
||||||
`A full list of cheers can be found here: https://github.com/qwerinope/qweribot#cheers`,
|
`A full list of cheers can be found here: https://gitlab.com/qwerinope/qweribot#cheers`,
|
||||||
msg.messageId,
|
msg.messageId,
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ export default new Command({
|
|||||||
const args = parseCommandArgs(msg.messageText);
|
const args = parseCommandArgs(msg.messageText);
|
||||||
if (!args[0]) {
|
if (!args[0]) {
|
||||||
await sendMessage(
|
await sendMessage(
|
||||||
`A full list of commands can be found here: https://github.com/qwerinope/qweribot#commands-1`,
|
`A full list of commands can be found here: https://gitlab.com/qwerinope/qweribot#commands-1`,
|
||||||
msg.messageId,
|
msg.messageId,
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { createGetLootRecord } from "db/dbGetLoot";
|
|
||||||
import { getUserRecord, updateUserRecord } from "db/dbUser";
|
import { getUserRecord, updateUserRecord } from "db/dbUser";
|
||||||
|
import { createGetLootEvent } from "db/LootEvents";
|
||||||
import itemMap, { type inventory, type items } from "items";
|
import itemMap, { type inventory, type items } from "items";
|
||||||
import { Command, sendMessage } from "lib/commandUtils";
|
import { Command, sendMessage } from "lib/commandUtils";
|
||||||
import { buildTimeString } from "lib/dateManager";
|
import { buildTimeString } from "lib/dateManager";
|
||||||
@@ -132,8 +132,11 @@ export default new Command({
|
|||||||
await Promise.all([
|
await Promise.all([
|
||||||
updateUserRecord(user, userData),
|
updateUserRecord(user, userData),
|
||||||
sendMessage(message, msg.messageId),
|
sendMessage(message, msg.messageId),
|
||||||
createGetLootRecord(user, gainedqbucks, itemDiff, "getloot"),
|
createGetLootEvent(user, gainedqbucks, itemDiff, "getloot"),
|
||||||
user.clearLock(),
|
user.clearLock(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
if (itemstrings.length === 0 && gainedqbucks < 100)
|
||||||
|
await sendMessage("YEOP THAT'S A SCAMBOX YEOP");
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -25,6 +25,10 @@ export default new Command({
|
|||||||
}
|
}
|
||||||
const selection = items.get(messagequery[0].toLowerCase());
|
const selection = items.get(messagequery[0].toLowerCase());
|
||||||
if (messagequery[0].toLowerCase() === "lootbox") {
|
if (messagequery[0].toLowerCase() === "lootbox") {
|
||||||
|
if (await redis.sismember("disabledcommands", "getloot")) {
|
||||||
|
await sendMessage("Lootboxes are currently disabled", msg.messageId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
await getloot.execute(msg, user);
|
await getloot.execute(msg, user);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ export async function connectionCheck() {
|
|||||||
redisstatus = true;
|
redisstatus = true;
|
||||||
} catch {}
|
} catch {}
|
||||||
logger.info(
|
logger.info(
|
||||||
`Currently using the "${process.env.NODE_ENV ?? "production"}" database`,
|
`Currently using the \x1b[3;4;1;95m"${process.env.NODE_ENV ?? "production"}"\x1b[0;97m database`,
|
||||||
);
|
);
|
||||||
pgstatus
|
pgstatus
|
||||||
? logger.ok(`Postgresql status: good`)
|
? logger.ok(`Postgresql status: good`)
|
||||||
|
|||||||
151
src/db/CheerEvents.ts
Normal file
151
src/db/CheerEvents.ts
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
import type { cheers } from "cheers";
|
||||||
|
import db from "db/connection";
|
||||||
|
import { cheerEvents, events, timeouts } from "db/schema";
|
||||||
|
import type { inventory, items } from "items";
|
||||||
|
import type User from "user";
|
||||||
|
import { createGetLootEvent } from "./LootEvents";
|
||||||
|
import { eq } from "drizzle-orm";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use this function to create a cheer event with timeouts
|
||||||
|
* This can only be used if the cheer succeeded
|
||||||
|
*
|
||||||
|
* The target can either be a single User object or an array of targetIDs
|
||||||
|
*/
|
||||||
|
export async function createTimeoutEventCheer(
|
||||||
|
user: User,
|
||||||
|
target: User | string[],
|
||||||
|
event: cheers,
|
||||||
|
) {
|
||||||
|
const userInt = parseInt(user.id, 10);
|
||||||
|
return await db.transaction(async (tx) => {
|
||||||
|
const cheerEventRecord = await tx
|
||||||
|
.insert(cheerEvents)
|
||||||
|
.values({
|
||||||
|
user: userInt,
|
||||||
|
event,
|
||||||
|
status: "success",
|
||||||
|
})
|
||||||
|
.returning();
|
||||||
|
|
||||||
|
if (Array.isArray(target))
|
||||||
|
target.map(
|
||||||
|
async (ripbozo) =>
|
||||||
|
await tx.insert(timeouts).values({
|
||||||
|
user: userInt,
|
||||||
|
target: parseInt(ripbozo, 10),
|
||||||
|
item: event,
|
||||||
|
cheer: cheerEventRecord[0]?.id,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
else
|
||||||
|
await tx.insert(timeouts).values({
|
||||||
|
user: userInt,
|
||||||
|
target: parseInt(target.id, 10),
|
||||||
|
item: event,
|
||||||
|
cheer: cheerEventRecord[0]?.id,
|
||||||
|
});
|
||||||
|
|
||||||
|
await tx.insert(events).values({
|
||||||
|
user: userInt,
|
||||||
|
cheer: cheerEventRecord[0]?.id,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!cheerEventRecord[0]) {
|
||||||
|
tx.rollback();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use this function to create a cheer event without timeouts
|
||||||
|
* This can only be used if the cheer succeeded
|
||||||
|
*/
|
||||||
|
export async function createRegularEventCheer(
|
||||||
|
user: User,
|
||||||
|
event: cheers | items,
|
||||||
|
) {
|
||||||
|
const userInt = parseInt(user.id, 10);
|
||||||
|
return await db.transaction(async (tx) => {
|
||||||
|
const cheerEventRecord = await tx
|
||||||
|
.insert(cheerEvents)
|
||||||
|
.values({
|
||||||
|
user: userInt,
|
||||||
|
event,
|
||||||
|
status: "success",
|
||||||
|
})
|
||||||
|
.returning();
|
||||||
|
|
||||||
|
await tx.insert(events).values({
|
||||||
|
user: userInt,
|
||||||
|
cheer: cheerEventRecord[0]?.id,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!cheerEventRecord[0]) {
|
||||||
|
tx.rollback();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use this function to create a cheer event where the user got an item after the cheer failed
|
||||||
|
*/
|
||||||
|
export async function createCompensatedItemCheer(user: User, item: items) {
|
||||||
|
const userInt = parseInt(user.id, 10);
|
||||||
|
return await db.transaction(async (tx) => {
|
||||||
|
const cheerEventRecord = await tx
|
||||||
|
.insert(cheerEvents)
|
||||||
|
.values({ user: userInt, event: item, status: "compensated" })
|
||||||
|
.returning();
|
||||||
|
|
||||||
|
await tx.insert(events).values({
|
||||||
|
user: userInt,
|
||||||
|
cheer: cheerEventRecord[0]?.id,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!cheerEventRecord[0]) {
|
||||||
|
tx.rollback();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Because superloot is a special case for cheers, as the event needs to link to the getLoot table and the cheerEvents table, we have this special function
|
||||||
|
*/
|
||||||
|
export async function createSuperLootEvent(
|
||||||
|
user: User,
|
||||||
|
qbucks: number,
|
||||||
|
inventory: inventory,
|
||||||
|
) {
|
||||||
|
const eventRecord = await createGetLootEvent(
|
||||||
|
user,
|
||||||
|
qbucks,
|
||||||
|
inventory,
|
||||||
|
"superloot",
|
||||||
|
);
|
||||||
|
|
||||||
|
if (eventRecord === false) return;
|
||||||
|
|
||||||
|
return await db.transaction(async (tx) => {
|
||||||
|
const cheerEventRecord = await tx
|
||||||
|
.insert(cheerEvents)
|
||||||
|
.values({
|
||||||
|
user: parseInt(user.id, 10),
|
||||||
|
event: "superloot",
|
||||||
|
})
|
||||||
|
.returning();
|
||||||
|
|
||||||
|
await tx
|
||||||
|
.update(events)
|
||||||
|
.set({ cheer: cheerEventRecord[0]?.id })
|
||||||
|
.where(eq(events.id, eventRecord.id));
|
||||||
|
|
||||||
|
if (!cheerEventRecord[0]) {
|
||||||
|
tx.rollback();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
72
src/db/ItemEvents.ts
Normal file
72
src/db/ItemEvents.ts
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
import db from "db/connection";
|
||||||
|
import { events, timeouts, usedItems } from "db/schema";
|
||||||
|
import type { items } from "items";
|
||||||
|
import type User from "user";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use this function for doing all item usages with timeouts
|
||||||
|
*/
|
||||||
|
export async function createTimeoutEventItem(
|
||||||
|
user: User,
|
||||||
|
target: User | string[],
|
||||||
|
item: items,
|
||||||
|
) {
|
||||||
|
const userInt = parseInt(user.id, 10);
|
||||||
|
return await db.transaction(async (tx) => {
|
||||||
|
const usedItemRecord = await tx
|
||||||
|
.insert(usedItems)
|
||||||
|
.values({ user: userInt, item })
|
||||||
|
.returning();
|
||||||
|
|
||||||
|
if (Array.isArray(target))
|
||||||
|
target.map(
|
||||||
|
async (ripbozo) =>
|
||||||
|
await tx.insert(timeouts).values({
|
||||||
|
user: userInt,
|
||||||
|
target: parseInt(ripbozo, 10),
|
||||||
|
item,
|
||||||
|
usedItem: usedItemRecord[0]?.id,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
else
|
||||||
|
await tx.insert(timeouts).values({
|
||||||
|
user: userInt,
|
||||||
|
target: parseInt(target.id, 10),
|
||||||
|
item,
|
||||||
|
usedItem: usedItemRecord[0]?.id,
|
||||||
|
});
|
||||||
|
|
||||||
|
await tx.insert(events).values({
|
||||||
|
user: userInt,
|
||||||
|
usedItem: usedItemRecord[0]?.id,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!usedItemRecord[0]) {
|
||||||
|
tx.rollback();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use this function for doing all regular item usages (no timeouts)
|
||||||
|
*/
|
||||||
|
export async function createNormalEventItem(user: User, item: items) {
|
||||||
|
const userInt = parseInt(user.id, 10);
|
||||||
|
return await db.transaction(async (tx) => {
|
||||||
|
const usedItemRecord = await tx
|
||||||
|
.insert(usedItems)
|
||||||
|
.values({ user: userInt, item })
|
||||||
|
.returning();
|
||||||
|
|
||||||
|
await tx.insert(events).values({
|
||||||
|
user: userInt,
|
||||||
|
usedItem: usedItemRecord[0]?.id,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!usedItemRecord[0]) {
|
||||||
|
tx.rollback();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
39
src/db/LootEvents.ts
Normal file
39
src/db/LootEvents.ts
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
import db from "db/connection";
|
||||||
|
import type { lootTriggers } from "db/schema";
|
||||||
|
import { events, getLoots } from "db/schema";
|
||||||
|
import type { inventory } from "items";
|
||||||
|
import type User from "user";
|
||||||
|
|
||||||
|
export async function createGetLootEvent(
|
||||||
|
user: User,
|
||||||
|
qbucks: number,
|
||||||
|
inventory: inventory,
|
||||||
|
trigger: lootTriggers,
|
||||||
|
) {
|
||||||
|
return await db.transaction(async (tx) => {
|
||||||
|
const glRecord = await tx
|
||||||
|
.insert(getLoots)
|
||||||
|
.values({
|
||||||
|
user: parseInt(user.id, 10),
|
||||||
|
qbucks: qbucks,
|
||||||
|
items: inventory,
|
||||||
|
trigger,
|
||||||
|
})
|
||||||
|
.returning();
|
||||||
|
|
||||||
|
const eventRecord = await tx
|
||||||
|
.insert(events)
|
||||||
|
.values({
|
||||||
|
user: parseInt(user.id, 10),
|
||||||
|
getLoot: glRecord[0]?.id,
|
||||||
|
})
|
||||||
|
.returning();
|
||||||
|
|
||||||
|
if (!glRecord[0]) {
|
||||||
|
tx.rollback();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return eventRecord[0]!;
|
||||||
|
});
|
||||||
|
}
|
||||||
4
src/db/UndoEvent.ts
Normal file
4
src/db/UndoEvent.ts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
import db from "db/connection";
|
||||||
|
import { events } from "db/schema";
|
||||||
|
import type User from "user";
|
||||||
|
import { desc, eq, and } from "drizzle-orm";
|
||||||
@@ -1,19 +1,8 @@
|
|||||||
import type { cheers } from "cheers";
|
|
||||||
import db from "db/connection";
|
import db from "db/connection";
|
||||||
import { cheerEvents } from "db/schema";
|
import { cheerEvents } from "db/schema";
|
||||||
import { and, between, eq, type SQL } from "drizzle-orm";
|
import { and, between, eq, type SQL } from "drizzle-orm";
|
||||||
import type { items } from "items";
|
|
||||||
import type User from "user";
|
import type User from "user";
|
||||||
|
|
||||||
export async function createCheerEventRecord(
|
|
||||||
user: User,
|
|
||||||
cheer: items | cheers,
|
|
||||||
): Promise<void> {
|
|
||||||
await db
|
|
||||||
.insert(cheerEvents)
|
|
||||||
.values({ user: parseInt(user.id, 10), event: cheer });
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function getCheerEvents(user: User, monthData?: string) {
|
export async function getCheerEvents(user: User, monthData?: string) {
|
||||||
let condition: SQL<unknown> | undefined = eq(
|
let condition: SQL<unknown> | undefined = eq(
|
||||||
cheerEvents.user,
|
cheerEvents.user,
|
||||||
|
|||||||
@@ -1,18 +0,0 @@
|
|||||||
import db from "db/connection";
|
|
||||||
import { getLoots, type lootTriggers } from "db/schema";
|
|
||||||
import type { inventory } from "items";
|
|
||||||
import type User from "user";
|
|
||||||
|
|
||||||
export async function createGetLootRecord(
|
|
||||||
user: User,
|
|
||||||
qbucks: number,
|
|
||||||
inventory: inventory,
|
|
||||||
trigger: lootTriggers,
|
|
||||||
) {
|
|
||||||
await db.insert(getLoots).values({
|
|
||||||
user: parseInt(user.id, 10),
|
|
||||||
qbucks: qbucks,
|
|
||||||
items: inventory,
|
|
||||||
trigger,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,22 +1,8 @@
|
|||||||
import type { cheers } from "cheers";
|
|
||||||
import db from "db/connection";
|
import db from "db/connection";
|
||||||
import { timeouts } from "db/schema";
|
import { timeouts } from "db/schema";
|
||||||
import { and, between, eq, type SQL } from "drizzle-orm";
|
import { and, between, eq, type SQL } from "drizzle-orm";
|
||||||
import type { items } from "items";
|
|
||||||
import type User from "user";
|
import type User from "user";
|
||||||
|
|
||||||
export async function createTimeoutRecord(
|
|
||||||
user: User,
|
|
||||||
target: User,
|
|
||||||
item: items | cheers,
|
|
||||||
): Promise<void> {
|
|
||||||
await db.insert(timeouts).values({
|
|
||||||
user: parseInt(user.id, 10),
|
|
||||||
target: parseInt(target.id, 10),
|
|
||||||
item,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function getTimeoutsAsUser(user: User, monthData?: string) {
|
export async function getTimeoutsAsUser(user: User, monthData?: string) {
|
||||||
let condition: SQL<unknown> | undefined = eq(
|
let condition: SQL<unknown> | undefined = eq(
|
||||||
timeouts.user,
|
timeouts.user,
|
||||||
|
|||||||
@@ -1,16 +1,8 @@
|
|||||||
import db from "db/connection";
|
import db from "db/connection";
|
||||||
import { usedItems } from "db/schema";
|
import { usedItems } from "db/schema";
|
||||||
import { and, between, eq, type SQL } from "drizzle-orm";
|
import { and, between, eq, type SQL } from "drizzle-orm";
|
||||||
import type { items } from "items";
|
|
||||||
import type User from "user";
|
import type User from "user";
|
||||||
|
|
||||||
export async function createUsedItemRecord(
|
|
||||||
user: User,
|
|
||||||
item: items,
|
|
||||||
): Promise<void> {
|
|
||||||
await db.insert(usedItems).values({ user: parseInt(user.id, 10), item });
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function getItemsUsed(user: User, monthData?: string) {
|
export async function getItemsUsed(user: User, monthData?: string) {
|
||||||
let condition: SQL<unknown> | undefined = eq(
|
let condition: SQL<unknown> | undefined = eq(
|
||||||
usedItems.user,
|
usedItems.user,
|
||||||
|
|||||||
@@ -12,7 +12,8 @@ import {
|
|||||||
type SQL,
|
type SQL,
|
||||||
sql,
|
sql,
|
||||||
} from "drizzle-orm";
|
} from "drizzle-orm";
|
||||||
import { itemarray } from "items";
|
import { itemarray, type items } from "items";
|
||||||
|
import { ANIVNAMES } from "lib/handleAnivMessage";
|
||||||
import type User from "user";
|
import type User from "user";
|
||||||
|
|
||||||
/** Use this function to both ensure existance and to retreive data */
|
/** Use this function to both ensure existance and to retreive data */
|
||||||
@@ -120,3 +121,25 @@ export async function getKDLeaderboard(monthData?: string) {
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ItemCounts = Record<items, number>;
|
||||||
|
|
||||||
|
export async function getTotalItemCounts(): Promise<ItemCounts> {
|
||||||
|
const allUsers = await db
|
||||||
|
.select({ username: users.username, inventory: users.inventory })
|
||||||
|
.from(users);
|
||||||
|
|
||||||
|
const filteredUsers = allUsers.filter(
|
||||||
|
(user) =>
|
||||||
|
!Array.from<string>(ANIVNAMES).includes(user.username.toLowerCase()),
|
||||||
|
);
|
||||||
|
|
||||||
|
const counts = itemarray.reduce((acc, item) => {
|
||||||
|
acc[item] = filteredUsers.reduce((sum, user) => {
|
||||||
|
return sum + (user.inventory[item] || 0);
|
||||||
|
}, 0);
|
||||||
|
return acc;
|
||||||
|
}, {} as ItemCounts);
|
||||||
|
|
||||||
|
return counts;
|
||||||
|
}
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ export const usersRelations = relations(users, ({ many }) => ({
|
|||||||
cheers: many(cheers),
|
cheers: many(cheers),
|
||||||
anivTimeouts: many(anivTimeouts),
|
anivTimeouts: many(anivTimeouts),
|
||||||
getLoots: many(getLoots),
|
getLoots: many(getLoots),
|
||||||
|
events: many(events),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const timeouts = pgTable("timeouts", {
|
export const timeouts = pgTable("timeouts", {
|
||||||
@@ -45,6 +46,8 @@ export const timeouts = pgTable("timeouts", {
|
|||||||
.references(() => users.id),
|
.references(() => users.id),
|
||||||
item: varchar().$type<items | cheertypes>().notNull(),
|
item: varchar().$type<items | cheertypes>().notNull(),
|
||||||
created: timestamp().defaultNow().notNull(),
|
created: timestamp().defaultNow().notNull(),
|
||||||
|
cheer: uuid().references(() => cheerEvents.id),
|
||||||
|
usedItem: uuid().references(() => usedItems.id),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const timeoutsRelations = relations(timeouts, ({ one }) => ({
|
export const timeoutsRelations = relations(timeouts, ({ one }) => ({
|
||||||
@@ -58,6 +61,14 @@ export const timeoutsRelations = relations(timeouts, ({ one }) => ({
|
|||||||
references: [users.id],
|
references: [users.id],
|
||||||
relationName: "target",
|
relationName: "target",
|
||||||
}),
|
}),
|
||||||
|
cheer: one(cheerEvents, {
|
||||||
|
fields: [timeouts.cheer],
|
||||||
|
references: [cheerEvents.id],
|
||||||
|
}),
|
||||||
|
usedItem: one(usedItems, {
|
||||||
|
fields: [timeouts.usedItem],
|
||||||
|
references: [usedItems.id],
|
||||||
|
}),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const usedItems = pgTable("usedItems", {
|
export const usedItems = pgTable("usedItems", {
|
||||||
@@ -69,27 +80,36 @@ export const usedItems = pgTable("usedItems", {
|
|||||||
created: timestamp().defaultNow().notNull(),
|
created: timestamp().defaultNow().notNull(),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const usedItemsRelations = relations(usedItems, ({ one }) => ({
|
export const usedItemsRelations = relations(usedItems, ({ one, many }) => ({
|
||||||
user: one(users, {
|
user: one(users, {
|
||||||
fields: [usedItems.user],
|
fields: [usedItems.user],
|
||||||
references: [users.id],
|
references: [users.id],
|
||||||
}),
|
}),
|
||||||
|
timeouts: many(timeouts),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* "success" when everything works
|
||||||
|
* "compensated" when the user gets an item in their inventory for a cheer
|
||||||
|
*/
|
||||||
|
export type cheerEventStatus = "success" | "compensated";
|
||||||
|
|
||||||
export const cheerEvents = pgTable("cheerEvents", {
|
export const cheerEvents = pgTable("cheerEvents", {
|
||||||
id: uuid().defaultRandom().primaryKey(),
|
id: uuid().defaultRandom().primaryKey(),
|
||||||
user: integer()
|
user: integer()
|
||||||
.notNull()
|
.notNull()
|
||||||
.references(() => users.id),
|
.references(() => users.id),
|
||||||
event: varchar().$type<items | cheertypes>().notNull(),
|
event: varchar().$type<items | cheertypes>().notNull(),
|
||||||
|
status: varchar().$type<cheerEventStatus>().default("success").notNull(),
|
||||||
created: timestamp().defaultNow().notNull(),
|
created: timestamp().defaultNow().notNull(),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const cheerEventsRelations = relations(cheerEvents, ({ one }) => ({
|
export const cheerEventsRelations = relations(cheerEvents, ({ one, many }) => ({
|
||||||
user: one(users, {
|
user: one(users, {
|
||||||
fields: [cheerEvents.user],
|
fields: [cheerEvents.user],
|
||||||
references: [users.id],
|
references: [users.id],
|
||||||
}),
|
}),
|
||||||
|
timeouts: many(timeouts),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const cheers = pgTable("cheers", {
|
export const cheers = pgTable("cheers", {
|
||||||
@@ -146,3 +166,33 @@ export const getLootsRelations = relations(getLoots, ({ one }) => ({
|
|||||||
references: [users.id],
|
references: [users.id],
|
||||||
}),
|
}),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
export const events = pgTable("events", {
|
||||||
|
id: uuid().defaultRandom().primaryKey(),
|
||||||
|
user: integer()
|
||||||
|
.notNull()
|
||||||
|
.references(() => users.id),
|
||||||
|
created: timestamp().defaultNow().notNull(),
|
||||||
|
usedItem: uuid().references(() => usedItems.id),
|
||||||
|
cheer: uuid().references(() => cheerEvents.id),
|
||||||
|
getLoot: uuid().references(() => getLoots.id),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const eventsRelations = relations(events, ({ one }) => ({
|
||||||
|
user: one(users, {
|
||||||
|
fields: [events.user],
|
||||||
|
references: [users.id],
|
||||||
|
}),
|
||||||
|
usedItem: one(usedItems, {
|
||||||
|
fields: [events.usedItem],
|
||||||
|
references: [usedItems.id],
|
||||||
|
}),
|
||||||
|
cheer: one(cheerEvents, {
|
||||||
|
fields: [events.cheer],
|
||||||
|
references: [cheerEvents.id],
|
||||||
|
}),
|
||||||
|
getLoot: one(getLoots, {
|
||||||
|
fields: [events.getLoot],
|
||||||
|
references: [getLoots.id],
|
||||||
|
}),
|
||||||
|
}));
|
||||||
|
|||||||
@@ -14,8 +14,6 @@ eventSub.onChannelRedemptionAdd(streamerId, async (msg) => {
|
|||||||
const user = await User.initUsername(msg.userName);
|
const user = await User.initUsername(msg.userName);
|
||||||
try {
|
try {
|
||||||
await selection.execute(msg, user!);
|
await selection.execute(msg, user!);
|
||||||
if (process.env.NODE_ENV === "production")
|
|
||||||
await msg.updateStatus("FULFILLED"); // only on prod
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
await sendMessage(
|
await sendMessage(
|
||||||
`[ERROR]: Something went wrong with ${user?.displayName}'s redeem!`,
|
`[ERROR]: Something went wrong with ${user?.displayName}'s redeem!`,
|
||||||
|
|||||||
@@ -1,34 +1,33 @@
|
|||||||
import { api, eventSub } from "index";
|
import { api, eventSub } from "index";
|
||||||
import kleur from "kleur";
|
|
||||||
import logger from "lib/logger";
|
import logger from "lib/logger";
|
||||||
|
|
||||||
eventSub.onRevoke((event) => {
|
eventSub.onRevoke((event) => {
|
||||||
logger.ok(
|
logger.ok(
|
||||||
`Successfully revoked EventSub subscription: ${kleur.underline(event.id)}`,
|
`Successfully revoked EventSub subscription: \x1b[3;4;1;95m${event.id}`,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
eventSub.onSubscriptionCreateSuccess((event) => {
|
eventSub.onSubscriptionCreateSuccess((event) => {
|
||||||
logger.ok(
|
logger.ok(
|
||||||
`Successfully created EventSub subscription: ${kleur.underline(event.id)}`,
|
`Successfully created EventSub subscription: \x1b[3;4;1;95m${event.id}`,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
eventSub.onSubscriptionCreateFailure((event) => {
|
eventSub.onSubscriptionCreateFailure((event) => {
|
||||||
logger.err(
|
logger.err(
|
||||||
`Failed to create EventSub subscription: ${kleur.underline(event.id)}`,
|
`Failed to create EventSub subscription: \x1b[3;4;4;95m${event.id}`,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
eventSub.onSubscriptionDeleteSuccess((event) => {
|
eventSub.onSubscriptionDeleteSuccess((event) => {
|
||||||
logger.ok(
|
logger.ok(
|
||||||
`Successfully deleted EventSub subscription: ${kleur.underline(event.id)}`,
|
`Successfully deleted EventSub subscription: \x1b[3;4;1;95m${event.id}`,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
eventSub.onSubscriptionDeleteFailure((event) => {
|
eventSub.onSubscriptionDeleteFailure((event) => {
|
||||||
logger.err(
|
logger.err(
|
||||||
`Failed to delete EventSub subscription: ${kleur.underline(event.id)}`,
|
`Failed to delete EventSub subscription: \x1b[3;4;1;95m${event.id}`,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ async function parseChatMessage(msg: EventSubChannelChatMessageEvent) {
|
|||||||
) {
|
) {
|
||||||
// The msg.sourceMessageId checks if the message is from shared chat. shared chat should be ignored
|
// The msg.sourceMessageId checks if the message is from shared chat. shared chat should be ignored
|
||||||
const message = await sendMessage(
|
const message = await sendMessage(
|
||||||
`Welcome ${user?.displayName}. Please note: This chat has PvP, if you get timed out that's part of the qwerinope experience. You have 10 minutes of invincibility. A full list of commands and items can be found here: https://github.com/qwerinope/qweribot/#qweribot`,
|
`Welcome ${user?.displayName}. Please note: This chat has PvP, if you get timed out that's part of the qwerinope experience. You have 10 minutes of invincibility. A full list of commands and items can be found here: https://gitlab.com/qwerinope/qweribot/#qweribot`,
|
||||||
);
|
);
|
||||||
await redis.set(`user:${user?.id}:haschatted`, "1");
|
await redis.set(`user:${user?.id}:haschatted`, "1");
|
||||||
await redis.set(`user:${user?.id}:welcomemessageid`, message.id);
|
await redis.set(`user:${user?.id}:welcomemessageid`, message.id);
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ eventSub.onChannelSubscription(streamerId, async (msg) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
eventSub.onChannelSubscriptionGift(streamerId, async (msg) => {
|
eventSub.onChannelSubscriptionGift(streamerId, async (msg) => {
|
||||||
if (msg.isAnonymous) {
|
if (msg.gifterName === null) {
|
||||||
switch (msg.tier) {
|
switch (msg.tier) {
|
||||||
case "1000":
|
case "1000":
|
||||||
await sendMessage(
|
await sendMessage(
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ eventSub.onUserWhisperMessage(chatterId, async (msg) => {
|
|||||||
if (!msg.messageText.startsWith(commandPrefix)) {
|
if (!msg.messageText.startsWith(commandPrefix)) {
|
||||||
await whisper(
|
await whisper(
|
||||||
msg.senderUserId,
|
msg.senderUserId,
|
||||||
`Whisper commands start with '${commandPrefix}'. All whisper commands can be found here: https://github.com/qwerinope/qweribot#whisper-commands-1`,
|
`Whisper commands start with '${commandPrefix}'. All whisper commands can be found here: https://gitlab.com/qwerinope/qweribot#whisper-commands-1`,
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -25,7 +25,7 @@ eventSub.onUserWhisperMessage(chatterId, async (msg) => {
|
|||||||
case "h":
|
case "h":
|
||||||
await whisper(
|
await whisper(
|
||||||
msg.senderUserId,
|
msg.senderUserId,
|
||||||
`All whisper commands can be found here: https://github.com/qwerinope/qweribot#whisper-commands-1`,
|
`All whisper commands can be found here: https://gitlab.com/qwerinope/qweribot#whisper-commands-1`,
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case "ghostwhisper":
|
case "ghostwhisper":
|
||||||
|
|||||||
11
src/index.ts
11
src/index.ts
@@ -144,6 +144,11 @@ streamerUsers.forEach(
|
|||||||
]),
|
]),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Deleting all timeouts to prevent ghosts while bot was off
|
||||||
|
await redis
|
||||||
|
.keys("user:*:timeout")
|
||||||
|
.then(async (a) => a.map(async (b) => await redis.del(b)));
|
||||||
|
|
||||||
const banned = await api.moderation
|
const banned = await api.moderation
|
||||||
.getBannedUsers(streamerId)
|
.getBannedUsers(streamerId)
|
||||||
.then((a) => a.data);
|
.then((a) => a.data);
|
||||||
@@ -156,7 +161,7 @@ for (const ban of banned) {
|
|||||||
Math.floor((ban.expiryDate.getTime() - Date.now()) / 1000) + 1,
|
Math.floor((ban.expiryDate.getTime() - Date.now()) / 1000) + 1,
|
||||||
);
|
);
|
||||||
logger.info(
|
logger.info(
|
||||||
`Set the timeout of ${ban.userDisplayName} in the Redis/Valkey database.`,
|
`Set the timeout of \x1b[3;4;1;95m${ban.userDisplayName}\x1b[0;97m in the Redis/Valkey database.`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -165,7 +170,7 @@ const mods = await api.moderation.getModerators(streamerId).then((a) => a.data);
|
|||||||
for (const mod of mods) {
|
for (const mod of mods) {
|
||||||
await redis.set(`user:${mod.userId}:mod`, "1");
|
await redis.set(`user:${mod.userId}:mod`, "1");
|
||||||
logger.info(
|
logger.info(
|
||||||
`Set the mod status of ${mod.userDisplayName} in the Redis/Valkey database.`,
|
`Set the mod status of \x1b[3;4;1;95m${mod.userDisplayName}\x1b[0;97m in the Redis/Valkey database.`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -180,7 +185,7 @@ for (const remod of bannedmods) {
|
|||||||
duration = Math.floor((durationdata * 1000 - Date.now()) / 1000);
|
duration = Math.floor((durationdata * 1000 - Date.now()) / 1000);
|
||||||
remodMod(target!, duration);
|
remodMod(target!, duration);
|
||||||
logger.info(
|
logger.info(
|
||||||
`Set the remod timer for ${target?.displayName} to ${duration} seconds.`,
|
`Set the remod timer for \x1b[3;4;1;95m${target?.displayName}\x1b[0;97m to \x1b[3;4;1;95m${duration}\x1b[0;97m seconds.`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { createTimeoutRecord } from "db/dbTimeouts";
|
|
||||||
import { createUsedItemRecord } from "db/dbUsedItems";
|
|
||||||
import { getUserRecord } from "db/dbUser";
|
import { getUserRecord } from "db/dbUser";
|
||||||
|
import { createTimeoutEventItem } from "db/ItemEvents";
|
||||||
import { changeItemCount, Item } from "items";
|
import { changeItemCount, Item } from "items";
|
||||||
import { sendMessage } from "lib/commandUtils";
|
import { sendMessage } from "lib/commandUtils";
|
||||||
import parseCommandArgs from "lib/parseCommandArgs";
|
import parseCommandArgs from "lib/parseCommandArgs";
|
||||||
@@ -28,7 +27,7 @@ export default new Item({
|
|||||||
}
|
}
|
||||||
const target = await User.initUsername(messagequery[0].toLowerCase());
|
const target = await User.initUsername(messagequery[0].toLowerCase());
|
||||||
if (!target) {
|
if (!target) {
|
||||||
await sendMessage(`${messagequery[0]} doesn't exist`);
|
await sendMessage(`${messagequery[0]} doesn't exist`, msg.messageId);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await getUserRecord(target); // make sure the user record exist in the database
|
await getUserRecord(target); // make sure the user record exist in the database
|
||||||
@@ -57,8 +56,7 @@ export default new Item({
|
|||||||
`GOTTEM ${target.displayName} got BLASTED by ${user.displayName} GOTTEM`,
|
`GOTTEM ${target.displayName} got BLASTED by ${user.displayName} GOTTEM`,
|
||||||
),
|
),
|
||||||
changeItemCount(user, userObj, ITEMNAME),
|
changeItemCount(user, userObj, ITEMNAME),
|
||||||
createTimeoutRecord(user, target, ITEMNAME),
|
createTimeoutEventItem(user, target, ITEMNAME),
|
||||||
createUsedItemRecord(user, ITEMNAME),
|
|
||||||
playAlert({
|
playAlert({
|
||||||
name: "userBlast",
|
name: "userBlast",
|
||||||
user: user.displayName,
|
user: user.displayName,
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { createTimeoutRecord } from "db/dbTimeouts";
|
|
||||||
import { createUsedItemRecord } from "db/dbUsedItems";
|
|
||||||
import { getUserRecord } from "db/dbUser";
|
import { getUserRecord } from "db/dbUser";
|
||||||
|
import { createTimeoutEventItem } from "db/ItemEvents";
|
||||||
import { changeItemCount, Item } from "items";
|
import { changeItemCount, Item } from "items";
|
||||||
import { sendMessage } from "lib/commandUtils";
|
import { sendMessage } from "lib/commandUtils";
|
||||||
import { redis } from "lib/redis";
|
import { redis } from "lib/redis";
|
||||||
@@ -47,8 +46,7 @@ export default new Item({
|
|||||||
`wybuh ${target?.displayName} got hit by ${user.displayName}'s grenade wybuh`,
|
`wybuh ${target?.displayName} got hit by ${user.displayName}'s grenade wybuh`,
|
||||||
),
|
),
|
||||||
changeItemCount(user, userObj, ITEMNAME),
|
changeItemCount(user, userObj, ITEMNAME),
|
||||||
createTimeoutRecord(user, target!, ITEMNAME),
|
createTimeoutEventItem(user, target!, ITEMNAME),
|
||||||
createUsedItemRecord(user, ITEMNAME),
|
|
||||||
playAlert({
|
playAlert({
|
||||||
name: "grenadeExplosion",
|
name: "grenadeExplosion",
|
||||||
user: user.displayName,
|
user: user.displayName,
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { createTimeoutRecord } from "db/dbTimeouts";
|
|
||||||
import { createUsedItemRecord } from "db/dbUsedItems";
|
|
||||||
import { getUserRecord } from "db/dbUser";
|
import { getUserRecord } from "db/dbUser";
|
||||||
|
import { createTimeoutEventItem } from "db/ItemEvents";
|
||||||
import { changeItemCount, Item } from "items";
|
import { changeItemCount, Item } from "items";
|
||||||
import { sendMessage } from "lib/commandUtils";
|
import { sendMessage } from "lib/commandUtils";
|
||||||
import parseCommandArgs from "lib/parseCommandArgs";
|
import parseCommandArgs from "lib/parseCommandArgs";
|
||||||
@@ -18,7 +17,7 @@ export default new Item({
|
|||||||
plural: "s",
|
plural: "s",
|
||||||
description: "Times targeted or random vulnerable user out for 30 minutes",
|
description: "Times targeted or random vulnerable user out for 30 minutes",
|
||||||
aliases: ["execute", "silverbullet"],
|
aliases: ["execute", "silverbullet"],
|
||||||
specialaliases: ["blastin"],
|
specialaliases: ["blastin", "fuck"],
|
||||||
price: 666,
|
price: 666,
|
||||||
execution: async (msg, user, specialargs) => {
|
execution: async (msg, user, specialargs) => {
|
||||||
const messagequery = parseCommandArgs(
|
const messagequery = parseCommandArgs(
|
||||||
@@ -67,7 +66,7 @@ export default new Item({
|
|||||||
}
|
}
|
||||||
if (!target) {
|
if (!target) {
|
||||||
await user.clearLock();
|
await user.clearLock();
|
||||||
await sendMessage(`${messagequery[0]} doesn't exist`);
|
await sendMessage(`${messagequery[0]} doesn't exist`, msg.messageId);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,21 +77,24 @@ export default new Item({
|
|||||||
`You got blasted by ${user.displayName}!`,
|
`You got blasted by ${user.displayName}!`,
|
||||||
60 * 30,
|
60 * 30,
|
||||||
);
|
);
|
||||||
if (result.status)
|
if (result.status) {
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
sendMessage(
|
sendMessage(
|
||||||
`KEKPOINT KEKPOINT KEKPOINT ${target.displayName.toUpperCase()} RIPBOZO RIPBOZO RIPBOZO RIPBOZO RIPBOZO RIPBOZO RIPBOZO`,
|
`KEKPOINT KEKPOINT KEKPOINT ${target.displayName.toUpperCase()} RIPBOZO RIPBOZO RIPBOZO RIPBOZO RIPBOZO RIPBOZO RIPBOZO`,
|
||||||
),
|
),
|
||||||
changeItemCount(user, userObj, ITEMNAME),
|
|
||||||
createTimeoutRecord(user, target, ITEMNAME),
|
|
||||||
createUsedItemRecord(user, ITEMNAME),
|
|
||||||
playAlert({
|
playAlert({
|
||||||
name: "userExecution",
|
name: "userExecution",
|
||||||
user: user.displayName,
|
user: user.displayName,
|
||||||
target: target.displayName,
|
target: target.displayName,
|
||||||
}),
|
}),
|
||||||
]);
|
]);
|
||||||
else {
|
if (user.id !== streamerId || process.env.NODE_ENV === "development")
|
||||||
|
// streamer doesn't consume bullets and doesn't count for timeouts
|
||||||
|
await Promise.all([
|
||||||
|
changeItemCount(user, userObj, ITEMNAME),
|
||||||
|
createTimeoutEventItem(user, target, ITEMNAME),
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
switch (result.reason) {
|
switch (result.reason) {
|
||||||
case "banned":
|
case "banned":
|
||||||
await sendMessage(
|
await sendMessage(
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { createTimeoutRecord } from "db/dbTimeouts";
|
|
||||||
import { createUsedItemRecord } from "db/dbUsedItems";
|
|
||||||
import { getUserRecord } from "db/dbUser";
|
import { getUserRecord } from "db/dbUser";
|
||||||
|
import { createTimeoutEventItem } from "db/ItemEvents";
|
||||||
import { changeItemCount, Item } from "items";
|
import { changeItemCount, Item } from "items";
|
||||||
import { sendMessage } from "lib/commandUtils";
|
import { sendMessage } from "lib/commandUtils";
|
||||||
import { redis } from "lib/redis";
|
import { redis } from "lib/redis";
|
||||||
@@ -49,13 +48,12 @@ export default new Item({
|
|||||||
sendMessage(
|
sendMessage(
|
||||||
`wybuh ${target?.displayName} got hit by ${user.displayName}'s TNT wybuh`,
|
`wybuh ${target?.displayName} got hit by ${user.displayName}'s TNT wybuh`,
|
||||||
),
|
),
|
||||||
createTimeoutRecord(user, target!, ITEMNAME),
|
|
||||||
]);
|
]);
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
createUsedItemRecord(user, ITEMNAME),
|
createTimeoutEventItem(user, targets, ITEMNAME),
|
||||||
playAlert({
|
playAlert({
|
||||||
name: "tntExplosion",
|
name: "tntExplosion",
|
||||||
user: user.displayName,
|
user: user.displayName,
|
||||||
|
|||||||
@@ -1,18 +1,39 @@
|
|||||||
import kleur from "kleur";
|
|
||||||
|
|
||||||
const logger = {
|
const logger = {
|
||||||
err: (arg: string) =>
|
err: (arg: string) =>
|
||||||
console.error(
|
console.error(
|
||||||
kleur.red().bold().italic("[ERROR] ") + kleur.red().bold(arg),
|
Bun.wrapAnsi(
|
||||||
|
`\x1b[1;91m[ERROR]: \x1b[0;97m${arg}\x1b[0m`,
|
||||||
|
process.stdout.columns,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
warn: (arg: string) =>
|
warn: (arg: string) =>
|
||||||
console.warn(
|
console.warn(
|
||||||
kleur.yellow().bold().italic("[WARN] ") + kleur.yellow().bold(arg),
|
Bun.wrapAnsi(
|
||||||
|
`\x1b[1;93m[WARN]: \x1b[0;97m${arg}\x1b[0m`,
|
||||||
|
process.stdout.columns,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
info: (arg: string) =>
|
info: (arg: string) =>
|
||||||
console.info(kleur.white().bold().italic("[INFO] ") + kleur.white(arg)),
|
console.info(
|
||||||
ok: (arg: string) => console.info(kleur.green().bold(arg)),
|
Bun.wrapAnsi(
|
||||||
enverr: (arg: string) => logger.err(`Please provide a ${arg} in the .env`),
|
`\x1b[37;1m[INFO]: \x1b[0;97m${arg}\x1b[0m`,
|
||||||
|
process.stdout.columns,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
ok: (arg: string) =>
|
||||||
|
console.info(
|
||||||
|
Bun.wrapAnsi(
|
||||||
|
`\x1b[1;92m[OK]: \x1b[0;97m${arg}\x1b[0m`,
|
||||||
|
process.stdout.columns,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
enverr: (arg: string) =>
|
||||||
|
logger.err(
|
||||||
|
Bun.wrapAnsi(
|
||||||
|
`Please provide a \x1b[4;3;93m${arg}\x1b[0;97m in the .env`,
|
||||||
|
process.stdout.columns,
|
||||||
|
),
|
||||||
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
export default logger;
|
export default logger;
|
||||||
|
|||||||
@@ -88,7 +88,9 @@ for (const [_, redeem] of Array.from(namedRedeems)) {
|
|||||||
backgroundColor: redeem.color,
|
backgroundColor: redeem.color,
|
||||||
userInputRequired: redeem.input,
|
userInputRequired: redeem.input,
|
||||||
});
|
});
|
||||||
logger.ok(`Created custom point redeem ${redeem.title}`);
|
logger.ok(
|
||||||
|
`Created custom point redeem \x1b[3;4;1;95m${redeem.title}\x1b[0;97m`,
|
||||||
|
);
|
||||||
idMap.set(redeem.name, creation.id);
|
idMap.set(redeem.name, creation.id);
|
||||||
activeRedeems.set(creation.id, redeem);
|
activeRedeems.set(creation.id, redeem);
|
||||||
}
|
}
|
||||||
@@ -97,7 +99,7 @@ for (const [_, redeem] of Array.from(namedRedeems)) {
|
|||||||
Array.from(currentRedeems).map(async ([title, redeem]) => {
|
Array.from(currentRedeems).map(async ([title, redeem]) => {
|
||||||
if (process.env.NODE_ENV !== "production") return;
|
if (process.env.NODE_ENV !== "production") return;
|
||||||
await api.channelPoints.deleteCustomReward(streamerId, redeem);
|
await api.channelPoints.deleteCustomReward(streamerId, redeem);
|
||||||
logger.ok(`Deleted custom point redeem ${title}`);
|
logger.ok(`Deleted custom point redeem \x1b[3;4;1;95m${title}\x1b[0;97m`);
|
||||||
});
|
});
|
||||||
|
|
||||||
logger.ok("Successfully synced all custom point redeems");
|
logger.ok("Successfully synced all custom point redeems");
|
||||||
@@ -108,7 +110,7 @@ export async function enableRedeem(redeem: PointRedeem, id: string) {
|
|||||||
isEnabled: true,
|
isEnabled: true,
|
||||||
});
|
});
|
||||||
activeRedeems.set(id, redeem);
|
activeRedeems.set(id, redeem);
|
||||||
logger.ok(`Enabled the ${redeem.name} point redeem`);
|
logger.ok(`Enabled the \x1b[3;4;1;95m${redeem.name}\x1b[0;97m point redeem`);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function disableRedeem(redeem: PointRedeem, id: string) {
|
export async function disableRedeem(redeem: PointRedeem, id: string) {
|
||||||
@@ -117,7 +119,7 @@ export async function disableRedeem(redeem: PointRedeem, id: string) {
|
|||||||
isEnabled: false,
|
isEnabled: false,
|
||||||
});
|
});
|
||||||
activeRedeems.delete(id);
|
activeRedeems.delete(id);
|
||||||
logger.ok(`Disabled the ${redeem.name} point redeem`);
|
logger.ok(`Disabled the \x1b[3;4;1;95m${redeem.name}\x1b[0;97m point redeem`);
|
||||||
}
|
}
|
||||||
|
|
||||||
export { activeRedeems, idMap };
|
export { activeRedeems, idMap };
|
||||||
|
|||||||
Reference in New Issue
Block a user