From 977082f38e51ea70b47187a687006bb5bde91bf6 Mon Sep 17 00:00:00 2001 From: qwerinope Date: Sat, 15 Nov 2025 02:35:39 +0100 Subject: [PATCH] small refactor and small lootbox rebalance SMILERS --- .example.env | 7 +++ README.md | 2 +- bun.lock | 52 +++++++++++++++++++-- package.json | 4 ++ src/cheers/execute.ts | 2 +- src/cheers/grenade.ts | 4 +- src/cheers/index.ts | 2 +- src/cheers/superloot.ts | 6 +-- src/cheers/timeout.ts | 2 +- src/cheers/tnt.ts | 4 +- src/commands/addadmin.ts | 2 +- src/commands/addbot.ts | 4 +- src/commands/addinvuln.ts | 2 +- src/commands/admindonate.ts | 2 +- src/commands/admingive.ts | 2 +- src/commands/alltimekdleaderboard.ts | 2 +- src/commands/alltimestats.ts | 2 +- src/commands/anivtimeouts.ts | 2 +- src/commands/backshot.ts | 4 +- src/commands/buyitem.ts | 2 +- src/commands/disablecheer.ts | 4 +- src/commands/disablecommand.ts | 5 +- src/commands/disableredeem.ts | 2 +- src/commands/donateqbucks.ts | 2 +- src/commands/enablecheer.ts | 4 +- src/commands/enablecommand.ts | 5 +- src/commands/enableredeem.ts | 2 +- src/commands/fakemodme.ts | 2 +- src/commands/getadmins.ts | 2 +- src/commands/getbalance.ts | 2 +- src/commands/getcheers.ts | 4 +- src/commands/getcommands.ts | 5 +- src/commands/getinventory.ts | 2 +- src/commands/getinvulns.ts | 2 +- src/commands/getloot.ts | 6 +-- src/commands/getprices.ts | 2 +- src/commands/gettimeout.ts | 2 +- src/commands/giveitem.ts | 2 +- src/commands/index.ts | 48 +------------------ src/commands/iteminfo.ts | 2 +- src/commands/itemlock.ts | 2 +- src/commands/monthlykdleaderboard.ts | 2 +- src/commands/monthlystats.ts | 2 +- src/commands/qbucksleaderboard.ts | 2 +- src/commands/racetime.ts | 2 +- src/commands/removeadmin.ts | 2 +- src/commands/removebot.ts | 4 +- src/commands/removeinvuln.ts | 2 +- src/commands/roulette.ts | 4 +- src/commands/seiso.ts | 4 +- src/commands/stacking.ts | 4 +- src/commands/testcheer.ts | 2 +- src/commands/useitem.ts | 12 ++--- src/commands/vulnchatters.ts | 4 +- src/commands/yabai.ts | 2 +- src/db/connection.ts | 17 +++---- src/db/dbUser.ts | 4 +- src/events/bans.ts | 5 +- src/events/channelPoints.ts | 5 +- src/events/deleteMessage.ts | 3 +- src/events/handleSubscriptions.ts | 3 +- src/events/index.ts | 2 +- src/events/message.ts | 8 ++-- src/events/moderators.ts | 5 +- src/events/raid.ts | 7 +-- src/events/streamState.ts | 9 ++-- src/events/subscription.ts | 7 +-- src/events/whisper.ts | 7 +-- src/index.ts | 34 +++++++------- src/items/blaster.ts | 6 +-- src/items/grenade.ts | 4 +- src/items/index.ts | 2 +- src/items/silverbullet.ts | 2 +- src/items/tnt.ts | 4 +- src/lib/admins.ts | 2 +- src/lib/commandUtils.ts | 46 ++++++++++++++++++ src/lib/handleAnivMessage.ts | 4 +- src/lib/invuln.ts | 2 +- src/lib/parseCommandArgs.ts | 1 + src/lib/redis.ts | 3 ++ src/lib/timeout.ts | 5 +- src/main.ts | 5 ++ src/pointRedeems/index.ts | 3 +- src/pointRedeems/qbucksredeem.ts | 2 +- src/user.ts | 4 +- src/web/chatWidget/widgetServerFunctions.ts | 5 +- src/web/discordConnection.ts | 17 +++++++ src/web/index.ts | 1 - tsconfig.json | 5 +- 89 files changed, 300 insertions(+), 203 deletions(-) create mode 100644 src/lib/commandUtils.ts create mode 100644 src/lib/redis.ts create mode 100644 src/main.ts create mode 100644 src/web/discordConnection.ts diff --git a/.example.env b/.example.env index b5b6926..8a3be46 100644 --- a/.example.env +++ b/.example.env @@ -25,3 +25,10 @@ POSTGRES_DB=twitchbot # Database name. Recommended value: twitchbot # Redis/Valkey config # REDIS_URL= # Redis URL. Defaults to redis://localhost:6379 + +# Discord bot config +# Not nessecary for twitch bot to run +DISCORD_TOKEN= # Discord bot token +DISCORD_CLIENT_ID= # Discord bot app client id +DISCORD_GUILD_ID= # Discord guild (server) where the bot runs +DISCORD_CHANNEL_ID= # Discord channel id, in guild, where bot should post announcements diff --git a/README.md b/README.md index 90b599f..cd4f28a 100644 --- a/README.md +++ b/README.md @@ -91,7 +91,7 @@ ITEM|RATE `grenade`|`1/5` `blaster`|`1/5` `tnt`|`1/50` -`silver bullet`|`1/250` +`silver bullet`|`1/50` Each of these rates get pulled 3 times, then the result is added to your inventory. It's theoretically possible to get 3 of each item. diff --git a/bun.lock b/bun.lock index 61c2b75..4efb93a 100644 --- a/bun.lock +++ b/bun.lock @@ -4,15 +4,17 @@ "": { "name": "qweribot", "dependencies": { - "@fontsource/jersey-15": "^5.2.6", - "@twurple/auth": "^7.3.0", - "@twurple/eventsub-ws": "^7.3.0", - "drizzle-orm": "^0.44.5", + "@fontsource/jersey-15": "^5.2.8", + "@twurple/api": "7.4.0", + "@twurple/auth": "^7.4.0", + "@twurple/eventsub-ws": "^7.4.0", + "discord.js": "^14.24.0", + "drizzle-orm": "^0.44.6", "kleur": "^4.1.5", }, "devDependencies": { "@types/bun": "latest", - "drizzle-kit": "^0.31.4", + "drizzle-kit": "^0.31.5", "pg": "^8.16.3", }, "peerDependencies": { @@ -41,6 +43,18 @@ "@d-fischer/typed-event-emitter": ["@d-fischer/typed-event-emitter@3.3.3", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-OvSEOa8icfdWDqcRtjSEZtgJTFOFNgTjje7zaL0+nAtu2/kZtRCSK5wUMrI/aXtCH8o0Qz2vA8UqkhWUTARFQQ=="], + "@discordjs/builders": ["@discordjs/builders@1.13.0", "", { "dependencies": { "@discordjs/formatters": "^0.6.1", "@discordjs/util": "^1.1.1", "@sapphire/shapeshift": "^4.0.0", "discord-api-types": "^0.38.31", "fast-deep-equal": "^3.1.3", "ts-mixer": "^6.0.4", "tslib": "^2.6.3" } }, "sha512-COK0uU6ZaJI+LA67H/rp8IbEkYwlZf3mAoBI5wtPh5G5cbEQGNhVpzINg2f/6+q/YipnNIKy6fJDg6kMUKUw4Q=="], + + "@discordjs/collection": ["@discordjs/collection@1.5.3", "", {}, "sha512-SVb428OMd3WO1paV3rm6tSjM4wC+Kecaa1EUGX7vc6/fddvw/6lg90z4QtCqm21zvVe92vMMDt9+DkIvjXImQQ=="], + + "@discordjs/formatters": ["@discordjs/formatters@0.6.1", "", { "dependencies": { "discord-api-types": "^0.38.1" } }, "sha512-5cnX+tASiPCqCWtFcFslxBVUaCetB0thvM/JyavhbXInP1HJIEU+Qv/zMrnuwSsX3yWH2lVXNJZeDK3EiP4HHg=="], + + "@discordjs/rest": ["@discordjs/rest@2.6.0", "", { "dependencies": { "@discordjs/collection": "^2.1.1", "@discordjs/util": "^1.1.1", "@sapphire/async-queue": "^1.5.3", "@sapphire/snowflake": "^3.5.3", "@vladfrangu/async_event_emitter": "^2.4.6", "discord-api-types": "^0.38.16", "magic-bytes.js": "^1.10.0", "tslib": "^2.6.3", "undici": "6.21.3" } }, "sha512-RDYrhmpB7mTvmCKcpj+pc5k7POKszS4E2O9TYc+U+Y4iaCP+r910QdO43qmpOja8LRr1RJ0b3U+CqVsnPqzf4w=="], + + "@discordjs/util": ["@discordjs/util@1.1.1", "", {}, "sha512-eddz6UnOBEB1oITPinyrB2Pttej49M9FZQY8NxgEvc3tq6ZICZ19m70RsmzRdDHk80O9NoYN/25AqJl8vPVf/g=="], + + "@discordjs/ws": ["@discordjs/ws@1.2.3", "", { "dependencies": { "@discordjs/collection": "^2.1.0", "@discordjs/rest": "^2.5.1", "@discordjs/util": "^1.1.0", "@sapphire/async-queue": "^1.5.2", "@types/ws": "^8.5.10", "@vladfrangu/async_event_emitter": "^2.2.4", "discord-api-types": "^0.38.1", "tslib": "^2.6.2", "ws": "^8.17.0" } }, "sha512-wPlQDxEmlDg5IxhJPuxXr3Vy9AjYq5xCvFWGJyD7w7Np8ZGu+Mc+97LCoEc/+AYCo2IDpKioiH0/c/mj5ZR9Uw=="], + "@drizzle-team/brocli": ["@drizzle-team/brocli@0.10.2", "", {}, "sha512-z33Il7l5dKjUgGULTqBsQBQwckHh5AbIuxhdsIxDDiZAzBOrZO6q9ogcWC65kU382AfynTfgNumVcNIjuIua6w=="], "@esbuild-kit/core-utils": ["@esbuild-kit/core-utils@3.3.2", "", { "dependencies": { "esbuild": "~0.18.20", "source-map-support": "^0.5.21" } }, "sha512-sPRAnw9CdSsRmEtnsl2WXWdyquogVpB3yZ3dgwJfe8zrOzTsV7cJvmwrKVa+0ma5BoiGJ+BoqkMvawbayKUsqQ=="], @@ -101,6 +115,12 @@ "@fontsource/jersey-15": ["@fontsource/jersey-15@5.2.8", "", {}, "sha512-JwwDch3yuc2pm33mbmNwlsPRKMjD4jSDTCJk9ooW1+ryJFktQPmXvYBbP5wTAXZqNPaBWSYANibP4dd7CEFYZA=="], + "@sapphire/async-queue": ["@sapphire/async-queue@1.5.5", "", {}, "sha512-cvGzxbba6sav2zZkH8GPf2oGk9yYoD5qrNWdu9fRehifgnFZJMV+nuy2nON2roRO4yQQ+v7MK/Pktl/HgfsUXg=="], + + "@sapphire/shapeshift": ["@sapphire/shapeshift@4.0.0", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "lodash": "^4.17.21" } }, "sha512-d9dUmWVA7MMiKobL3VpLF8P2aeanRTu6ypG2OIaEv/ZHH/SUQ2iHOVyi5wAPjQ+HmnMuL0whK9ez8I/raWbtIg=="], + + "@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-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=="], @@ -121,6 +141,8 @@ "@types/ws": ["@types/ws@8.18.1", "", { "dependencies": { "@types/node": "*" } }, "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg=="], + "@vladfrangu/async_event_emitter": ["@vladfrangu/async_event_emitter@2.4.7", "", {}, "sha512-Xfe6rpCTxSxfbswi/W/Pz7zp1WWSNn4A0eW4mLkQUewCrXXtMj31lCg+iQyTkh/CkusZSq9eDflu7tjEDXUY6g=="], + "buffer-from": ["buffer-from@1.1.2", "", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="], "bun-types": ["bun-types@1.3.0", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-u8X0thhx+yJ0KmkxuEo9HAtdfgCBaM/aI9K90VQcQioAmkVp3SG3FkwWGibUFz3WdXAdcsqOcbU40lK7tbHdkQ=="], @@ -129,6 +151,10 @@ "debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="], + "discord-api-types": ["discord-api-types@0.38.31", "", {}, "sha512-kC94ANsk8ackj8ENTuO8joTNEL0KtymVhHy9dyEC/s4QAZ7GCx40dYEzQaadyo8w+oP0X8QydE/nzAWRylTGtQ=="], + + "discord.js": ["discord.js@14.24.0", "", { "dependencies": { "@discordjs/builders": "^1.13.0", "@discordjs/collection": "1.5.3", "@discordjs/formatters": "^0.6.1", "@discordjs/rest": "^2.6.0", "@discordjs/util": "^1.1.1", "@discordjs/ws": "^1.2.3", "@sapphire/snowflake": "3.5.3", "discord-api-types": "^0.38.31", "fast-deep-equal": "3.1.3", "lodash.snakecase": "4.1.1", "magic-bytes.js": "^1.10.0", "tslib": "^2.6.3", "undici": "6.21.3" } }, "sha512-KNq/ekT8bsmT3ZAfVre8cPbl+DfVYSdlLnDmGZPoz7Cw21LYeWHllRA9MivqNq5b1GPGAxGvyUN1vxbTb/PQWw=="], + "drizzle-kit": ["drizzle-kit@0.31.5", "", { "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-+CHgPFzuoTQTt7cOYCV6MOw2w8vqEn/ap1yv4bpZOWL03u7rlVRQhUY0WYT3rHsgVTXwYQDZaSUJSQrMBUKuWg=="], "drizzle-orm": ["drizzle-orm@0.44.6", "", { "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-uy6uarrrEOc9K1u5/uhBFJbdF5VJ5xQ/Yzbecw3eAYOunv5FDeYkR2m8iitocdHBOHbvorviKOW5GVw0U1j4LQ=="], @@ -137,12 +163,20 @@ "esbuild-register": ["esbuild-register@3.6.0", "", { "dependencies": { "debug": "^4.3.4" }, "peerDependencies": { "esbuild": ">=0.12 <1" } }, "sha512-H2/S7Pm8a9CL1uhp9OvjwrBh5Pvx0H8qVOxNu8Wed9Y7qv56MPtq+GGM8RJpq6glYJn9Wspr8uw7l55uyinNeg=="], + "fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="], + "get-tsconfig": ["get-tsconfig@4.10.1", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ=="], "kleur": ["kleur@4.1.5", "", {}, "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ=="], "klona": ["klona@2.0.6", "", {}, "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA=="], + "lodash": ["lodash@4.17.21", "", {}, "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="], + + "lodash.snakecase": ["lodash.snakecase@4.1.1", "", {}, "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw=="], + + "magic-bytes.js": ["magic-bytes.js@1.12.1", "", {}, "sha512-ThQLOhN86ZkJ7qemtVRGYM+gRgR8GEXNli9H/PMvpnZsE44Xfh3wx9kGJaldg314v85m+bFW6WBMaVHJc/c3zA=="], + "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=="], @@ -183,10 +217,14 @@ "tr46": ["tr46@0.0.3", "", {}, "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="], + "ts-mixer": ["ts-mixer@6.0.4", "", {}, "sha512-ufKpbmrugz5Aou4wcr5Wc1UUFWOLhq+Fm6qa6P0w0K5Qw2yhaUoiWszhCVuNQyNwrlGiscHOmqYoAox1PtvgjA=="], + "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], "typescript": ["typescript@5.8.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ=="], + "undici": ["undici@6.21.3", "", {}, "sha512-gBLkYIlEnSp8pFbT64yFgGE6UIB9tAkhukC23PmMDCe5Nd+cRqKxSjw5y54MK2AZMgZfJWMaNE4nYUHgi1XEOw=="], + "undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="], "webidl-conversions": ["webidl-conversions@3.0.1", "", {}, "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="], @@ -197,6 +235,10 @@ "xtend": ["xtend@4.0.2", "", {}, "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ=="], + "@discordjs/rest/@discordjs/collection": ["@discordjs/collection@2.1.1", "", {}, "sha512-LiSusze9Tc7qF03sLCujF5iZp7K+vRNEDBZ86FT9aQAv3vxMLihUvKvpsCWiQ2DJq1tVckopKm1rxomgNUc9hg=="], + + "@discordjs/ws/@discordjs/collection": ["@discordjs/collection@2.1.1", "", {}, "sha512-LiSusze9Tc7qF03sLCujF5iZp7K+vRNEDBZ86FT9aQAv3vxMLihUvKvpsCWiQ2DJq1tVckopKm1rxomgNUc9hg=="], + "@esbuild-kit/core-utils/esbuild": ["esbuild@0.18.20", "", { "optionalDependencies": { "@esbuild/android-arm": "0.18.20", "@esbuild/android-arm64": "0.18.20", "@esbuild/android-x64": "0.18.20", "@esbuild/darwin-arm64": "0.18.20", "@esbuild/darwin-x64": "0.18.20", "@esbuild/freebsd-arm64": "0.18.20", "@esbuild/freebsd-x64": "0.18.20", "@esbuild/linux-arm": "0.18.20", "@esbuild/linux-arm64": "0.18.20", "@esbuild/linux-ia32": "0.18.20", "@esbuild/linux-loong64": "0.18.20", "@esbuild/linux-mips64el": "0.18.20", "@esbuild/linux-ppc64": "0.18.20", "@esbuild/linux-riscv64": "0.18.20", "@esbuild/linux-s390x": "0.18.20", "@esbuild/linux-x64": "0.18.20", "@esbuild/netbsd-x64": "0.18.20", "@esbuild/openbsd-x64": "0.18.20", "@esbuild/sunos-x64": "0.18.20", "@esbuild/win32-arm64": "0.18.20", "@esbuild/win32-ia32": "0.18.20", "@esbuild/win32-x64": "0.18.20" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA=="], "@esbuild-kit/core-utils/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.18.20", "", { "os": "android", "cpu": "arm" }, "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw=="], diff --git a/package.json b/package.json index d2b727d..89f2903 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,8 @@ "scripts": { "start": "NODE_ENV=production bun src/index.ts", "start-dev": "NODE_ENV=development bun src/index.ts", + "start-discord": "NODE_ENV=production bun src/discord/index.ts", + "start-dev-discord": "NODE_ENV=development bun src/discord/index.ts", "migrate": "drizzle-kit push --config=drizzle-prod.config.ts", "migrate-dev": "drizzle-kit push --config=drizzle-dev.config.ts", "studio": "drizzle-kit studio --config=drizzle-prod.config.ts", @@ -21,8 +23,10 @@ "type": "module", "dependencies": { "@fontsource/jersey-15": "^5.2.8", + "@twurple/api": "7.4.0", "@twurple/auth": "^7.4.0", "@twurple/eventsub-ws": "^7.4.0", + "discord.js": "^14.24.0", "drizzle-orm": "^0.44.6", "kleur": "^4.1.5" } diff --git a/src/cheers/execute.ts b/src/cheers/execute.ts index b24f1de..2d72bfc 100644 --- a/src/cheers/execute.ts +++ b/src/cheers/execute.ts @@ -1,5 +1,5 @@ import { Cheer, handleNoTarget } from "cheers"; -import { sendMessage } from "commands"; +import { sendMessage } from "lib/commandUtils"; import { getUserRecord } from "db/dbUser"; import User from "user"; import { timeout } from "lib/timeout"; diff --git a/src/cheers/grenade.ts b/src/cheers/grenade.ts index dc91a42..3206ecb 100644 --- a/src/cheers/grenade.ts +++ b/src/cheers/grenade.ts @@ -1,5 +1,5 @@ -import { redis } from "bun"; -import { sendMessage } from "commands"; +import { redis } from "lib/redis"; +import { sendMessage } from "lib/commandUtils"; import { timeout } from "lib/timeout"; import User from "user"; import { getUserRecord } from "db/dbUser"; diff --git a/src/cheers/index.ts b/src/cheers/index.ts index ba64c40..0c22285 100644 --- a/src/cheers/index.ts +++ b/src/cheers/index.ts @@ -30,7 +30,7 @@ for (const file of files) { export default cheers; export { namedcheers }; -import { sendMessage } from 'commands'; +import { sendMessage } from 'lib/commandUtils'; import { getUserRecord } from 'db/dbUser'; import { changeItemCount, type items } from 'items'; diff --git a/src/cheers/superloot.ts b/src/cheers/superloot.ts index 802cb53..98c2684 100644 --- a/src/cheers/superloot.ts +++ b/src/cheers/superloot.ts @@ -1,10 +1,10 @@ import { Cheer } from "cheers"; -import { sendMessage } from "commands"; +import { sendMessage } from "lib/commandUtils"; import { getUserRecord, updateUserRecord } from "db/dbUser"; import itemMap, { type inventory, type items } from "items"; import { createGetLootRecord } from "db/dbGetLoot"; import { timeout } from "lib/timeout"; -import { redis } from "bun"; +import { redis } from "lib/redis"; export default new Cheer('superloot', 150, async (msg, user) => { if (!await redis.exists('streamIsLive')) { await sendMessage(`No loot while stream is offline`, msg.messageId); return; }; @@ -38,7 +38,7 @@ export default new Cheer('superloot', 150, async (msg, user) => { if (Math.floor(Math.random() * 5) === 0) itemDiff.grenade! += 1; // 1 in 5 if (Math.floor(Math.random() * 5) === 0) itemDiff.blaster! += 1; // 1 in 5 if (Math.floor(Math.random() * 50) === 0) itemDiff.tnt! += 1; // 1 in 50 - if (Math.floor(Math.random() * 250) === 0) itemDiff.silverbullet! += 1; // 1 in 250 + if (Math.floor(Math.random() * 50) === 0) itemDiff.silverbullet! += 1; // 1 in 50 }; for (const [item, amount] of Object.entries(itemDiff) as [items, number][]) { diff --git a/src/cheers/timeout.ts b/src/cheers/timeout.ts index b9a1610..fcc72f9 100644 --- a/src/cheers/timeout.ts +++ b/src/cheers/timeout.ts @@ -1,5 +1,5 @@ import { Cheer, handleNoTarget } from "cheers"; -import { sendMessage } from "commands"; +import { sendMessage } from "lib/commandUtils"; import { getUserRecord } from "db/dbUser"; import User from "user"; import { timeout } from "lib/timeout"; diff --git a/src/cheers/tnt.ts b/src/cheers/tnt.ts index 016739a..935fd1d 100644 --- a/src/cheers/tnt.ts +++ b/src/cheers/tnt.ts @@ -1,12 +1,12 @@ import { Cheer, handleNoTarget } from "cheers"; -import { sendMessage } from "commands"; +import { sendMessage } from "lib/commandUtils"; import { getUserRecord } from "db/dbUser"; import User from "user"; import { timeout } from "lib/timeout"; import { createTimeoutRecord } from "db/dbTimeouts"; import { createCheerEventRecord } from "db/dbCheerEvents"; import { getTNTTargets } from "items/tnt"; -import { redis } from "bun"; +import { redis } from "lib/redis"; import { playAlert } from "web/alerts/serverFunctions"; const ITEMNAME = 'tnt'; diff --git a/src/commands/addadmin.ts b/src/commands/addadmin.ts index fd94c4a..9997552 100644 --- a/src/commands/addadmin.ts +++ b/src/commands/addadmin.ts @@ -1,4 +1,4 @@ -import { Command, sendMessage } from "commands"; +import { Command, sendMessage } from "lib/commandUtils"; import { addAdmin } from "lib/admins"; import parseCommandArgs from "lib/parseCommandArgs"; import User from "user"; diff --git a/src/commands/addbot.ts b/src/commands/addbot.ts index df70d09..629e23e 100644 --- a/src/commands/addbot.ts +++ b/src/commands/addbot.ts @@ -1,5 +1,5 @@ -import { redis } from "bun"; -import { Command, sendMessage } from "commands"; +import { redis } from "lib/redis"; +import { Command, sendMessage } from "lib/commandUtils"; import parseCommandArgs from "lib/parseCommandArgs"; import { streamerUsers } from "main"; import User from "user"; diff --git a/src/commands/addinvuln.ts b/src/commands/addinvuln.ts index a00b747..b6d18b9 100644 --- a/src/commands/addinvuln.ts +++ b/src/commands/addinvuln.ts @@ -1,5 +1,5 @@ -import { Command, sendMessage } from "commands"; import { addInvuln } from "lib/invuln"; +import { Command, sendMessage } from "lib/commandUtils"; import parseCommandArgs from "lib/parseCommandArgs"; import User from "user"; diff --git a/src/commands/admindonate.ts b/src/commands/admindonate.ts index 97303b0..7e345e7 100644 --- a/src/commands/admindonate.ts +++ b/src/commands/admindonate.ts @@ -1,4 +1,4 @@ -import { Command, sendMessage } from "commands"; +import { Command, sendMessage } from "lib/commandUtils"; import { getUserRecord } from "db/dbUser"; import { changeBalance } from "lib/changeBalance"; import parseCommandArgs from "lib/parseCommandArgs"; diff --git a/src/commands/admingive.ts b/src/commands/admingive.ts index 0828ff1..5040fe9 100644 --- a/src/commands/admingive.ts +++ b/src/commands/admingive.ts @@ -1,4 +1,4 @@ -import { Command, sendMessage } from "commands"; +import { Command, sendMessage } from "lib/commandUtils"; import { getUserRecord } from "db/dbUser"; import items, { changeItemCount } from "items"; import parseCommandArgs from "lib/parseCommandArgs"; diff --git a/src/commands/alltimekdleaderboard.ts b/src/commands/alltimekdleaderboard.ts index 9de0d6c..1b47df9 100644 --- a/src/commands/alltimekdleaderboard.ts +++ b/src/commands/alltimekdleaderboard.ts @@ -1,4 +1,4 @@ -import { Command, sendMessage } from "commands"; +import { Command, sendMessage } from "lib/commandUtils"; import { getKDLeaderboard } from "db/dbUser"; import User from "user"; diff --git a/src/commands/alltimestats.ts b/src/commands/alltimestats.ts index 7b9e486..8d9d70c 100644 --- a/src/commands/alltimestats.ts +++ b/src/commands/alltimestats.ts @@ -1,4 +1,4 @@ -import { Command, sendMessage } from "commands"; +import { Command, sendMessage } from "lib/commandUtils"; import { getTimeoutStats, getItemStats } from "lib/getStats"; import parseCommandArgs from "lib/parseCommandArgs"; import User from "user"; diff --git a/src/commands/anivtimeouts.ts b/src/commands/anivtimeouts.ts index 6163a91..c4bbb36 100644 --- a/src/commands/anivtimeouts.ts +++ b/src/commands/anivtimeouts.ts @@ -1,4 +1,4 @@ -import { Command, sendMessage } from "commands"; +import { Command, sendMessage } from "lib/commandUtils"; import { getAnivTimeouts } from "db/dbAnivTimeouts"; import parseCommandArgs from "lib/parseCommandArgs"; import User from "user"; diff --git a/src/commands/backshot.ts b/src/commands/backshot.ts index e9f7041..8e0ded7 100644 --- a/src/commands/backshot.ts +++ b/src/commands/backshot.ts @@ -1,6 +1,6 @@ -import { Command, sendMessage } from "commands"; +import { Command, sendMessage } from "lib/commandUtils"; import User from "user"; -import { redis } from "bun"; +import { redis } from "lib/redis"; export default new Command({ name: 'backshot', diff --git a/src/commands/buyitem.ts b/src/commands/buyitem.ts index 0735e66..82768c8 100644 --- a/src/commands/buyitem.ts +++ b/src/commands/buyitem.ts @@ -1,4 +1,4 @@ -import { Command, sendMessage } from "commands"; +import { Command, sendMessage } from "lib/commandUtils"; import parseCommandArgs from "lib/parseCommandArgs"; import items from "items"; import { getUserRecord, updateUserRecord } from "db/dbUser"; diff --git a/src/commands/disablecheer.ts b/src/commands/disablecheer.ts index 8f36ffe..6cf0ad9 100644 --- a/src/commands/disablecheer.ts +++ b/src/commands/disablecheer.ts @@ -1,5 +1,5 @@ -import { redis } from "bun"; -import { Command, sendMessage } from "commands"; +import { redis } from "lib/redis"; +import { Command, sendMessage } from "lib/commandUtils"; import parseCommandArgs from "lib/parseCommandArgs"; import { namedcheers } from "cheers"; diff --git a/src/commands/disablecommand.ts b/src/commands/disablecommand.ts index 2d6ddc9..dbb3d2a 100644 --- a/src/commands/disablecommand.ts +++ b/src/commands/disablecommand.ts @@ -1,5 +1,6 @@ -import { redis } from "bun"; -import commands, { Command, sendMessage } from "commands"; +import { redis } from "lib/redis"; +import commands from "commands"; +import { Command, sendMessage } from "lib/commandUtils"; import parseCommandArgs from "lib/parseCommandArgs"; export default new Command({ diff --git a/src/commands/disableredeem.ts b/src/commands/disableredeem.ts index 53f00ab..5137cf7 100644 --- a/src/commands/disableredeem.ts +++ b/src/commands/disableredeem.ts @@ -1,4 +1,4 @@ -import { Command, sendMessage } from "commands"; +import { Command, sendMessage } from "lib/commandUtils"; import parseCommandArgs from "lib/parseCommandArgs"; import { disableRedeem, idMap, namedRedeems, sfxRedeems } from "pointRedeems"; import logger from "lib/logger"; diff --git a/src/commands/donateqbucks.ts b/src/commands/donateqbucks.ts index 3364eee..3d143ef 100644 --- a/src/commands/donateqbucks.ts +++ b/src/commands/donateqbucks.ts @@ -1,4 +1,4 @@ -import { Command, sendMessage } from "commands"; +import { Command, sendMessage } from "lib/commandUtils"; import { getUserRecord } from "db/dbUser"; import parseCommandArgs from "lib/parseCommandArgs"; import { changeBalance } from "lib/changeBalance"; diff --git a/src/commands/enablecheer.ts b/src/commands/enablecheer.ts index f23d5e8..2d88205 100644 --- a/src/commands/enablecheer.ts +++ b/src/commands/enablecheer.ts @@ -1,5 +1,5 @@ -import { redis } from "bun"; -import { Command, sendMessage } from "commands"; +import { redis } from "lib/redis"; +import { Command, sendMessage } from "lib/commandUtils"; import parseCommandArgs from "lib/parseCommandArgs"; import { namedcheers } from "cheers"; diff --git a/src/commands/enablecommand.ts b/src/commands/enablecommand.ts index 21ef5dc..0fda3eb 100644 --- a/src/commands/enablecommand.ts +++ b/src/commands/enablecommand.ts @@ -1,5 +1,6 @@ -import { redis } from "bun"; -import commands, { Command, sendMessage } from "commands"; +import { redis } from "lib/redis"; +import { Command, sendMessage } from "lib/commandUtils"; +import commands from "commands"; import parseCommandArgs from "lib/parseCommandArgs"; export default new Command({ diff --git a/src/commands/enableredeem.ts b/src/commands/enableredeem.ts index 4594ee9..0ef7718 100644 --- a/src/commands/enableredeem.ts +++ b/src/commands/enableredeem.ts @@ -1,4 +1,4 @@ -import { Command, sendMessage } from "commands"; +import { Command, sendMessage } from "lib/commandUtils"; import logger from "lib/logger"; import parseCommandArgs from "lib/parseCommandArgs"; import { enableRedeem, idMap, namedRedeems, sfxRedeems } from "pointRedeems"; diff --git a/src/commands/fakemodme.ts b/src/commands/fakemodme.ts index 5c8c9ec..e9f530e 100644 --- a/src/commands/fakemodme.ts +++ b/src/commands/fakemodme.ts @@ -1,4 +1,4 @@ -import { Command, sendMessage } from "commands"; +import { Command, sendMessage } from "lib/commandUtils"; import { timeout } from "lib/timeout"; export default new Command({ diff --git a/src/commands/getadmins.ts b/src/commands/getadmins.ts index b4cefd3..6b6fdfb 100644 --- a/src/commands/getadmins.ts +++ b/src/commands/getadmins.ts @@ -1,4 +1,4 @@ -import { Command, sendMessage } from "commands"; +import { Command, sendMessage } from "lib/commandUtils"; import { getAdmins } from "lib/admins"; import User from "user"; diff --git a/src/commands/getbalance.ts b/src/commands/getbalance.ts index 76b01da..52ad648 100644 --- a/src/commands/getbalance.ts +++ b/src/commands/getbalance.ts @@ -1,4 +1,4 @@ -import { Command, sendMessage } from "commands"; +import { Command, sendMessage } from "lib/commandUtils"; import { getUserRecord } from "db/dbUser"; import parseCommandArgs from "lib/parseCommandArgs"; import User from "user"; diff --git a/src/commands/getcheers.ts b/src/commands/getcheers.ts index 9795ef4..756886b 100644 --- a/src/commands/getcheers.ts +++ b/src/commands/getcheers.ts @@ -1,5 +1,5 @@ -import { redis } from "bun"; -import { Command, sendMessage } from "commands"; +import { redis } from "lib/redis"; +import { Command, sendMessage } from "lib/commandUtils"; import parseCommandArgs from "lib/parseCommandArgs"; import { namedcheers } from "cheers"; diff --git a/src/commands/getcommands.ts b/src/commands/getcommands.ts index a7bdad8..a9d342c 100644 --- a/src/commands/getcommands.ts +++ b/src/commands/getcommands.ts @@ -1,5 +1,6 @@ -import { redis } from "bun"; -import { basecommands, Command, sendMessage } from "commands"; +import { redis } from "lib/redis"; +import { Command, sendMessage } from "lib/commandUtils"; +import { basecommands } from "commands"; import parseCommandArgs from "lib/parseCommandArgs"; export default new Command({ diff --git a/src/commands/getinventory.ts b/src/commands/getinventory.ts index b9f6597..acc4b6a 100644 --- a/src/commands/getinventory.ts +++ b/src/commands/getinventory.ts @@ -1,4 +1,4 @@ -import { Command, sendMessage } from "commands"; +import { Command, sendMessage } from "lib/commandUtils"; import { getUserRecord } from "db/dbUser"; import parseCommandArgs from "lib/parseCommandArgs"; import User from "user"; diff --git a/src/commands/getinvulns.ts b/src/commands/getinvulns.ts index 8c8df98..222b889 100644 --- a/src/commands/getinvulns.ts +++ b/src/commands/getinvulns.ts @@ -1,4 +1,4 @@ -import { Command, sendMessage } from "commands"; +import { Command, sendMessage } from "lib/commandUtils"; import { getInvulns } from "lib/invuln"; import User from "user"; diff --git a/src/commands/getloot.ts b/src/commands/getloot.ts index 55ccf12..a1946f0 100644 --- a/src/commands/getloot.ts +++ b/src/commands/getloot.ts @@ -1,5 +1,5 @@ -import { redis } from "bun"; -import { Command, sendMessage } from "commands"; +import { redis } from "lib/redis"; +import { Command, sendMessage } from "lib/commandUtils"; import { getUserRecord, updateUserRecord } from "db/dbUser"; import itemMap, { type inventory, type items } from "items"; import { buildTimeString } from "lib/dateManager"; @@ -57,7 +57,7 @@ export default new Command({ if (Math.floor(Math.random() * 5) === 0) itemDiff.grenade! += 1; // 1 in 5 if (Math.floor(Math.random() * 5) === 0) itemDiff.blaster! += 1; // 1 in 5 if (Math.floor(Math.random() * 50) === 0) itemDiff.tnt! += 1; // 1 in 50 - if (Math.floor(Math.random() * 250) === 0) itemDiff.silverbullet! += 1; // 1 in 250 + if (Math.floor(Math.random() * 50) === 0) itemDiff.silverbullet! += 1; // 1 in 50 }; for (const [item, amount] of Object.entries(itemDiff) as [items, number][]) { diff --git a/src/commands/getprices.ts b/src/commands/getprices.ts index a1f18e1..01647fa 100644 --- a/src/commands/getprices.ts +++ b/src/commands/getprices.ts @@ -1,4 +1,4 @@ -import { Command, sendMessage } from "commands"; +import { Command, sendMessage } from "lib/commandUtils"; import { itemObjectArray } from "items"; export default new Command({ diff --git a/src/commands/gettimeout.ts b/src/commands/gettimeout.ts index b0e9aee..9dff265 100644 --- a/src/commands/gettimeout.ts +++ b/src/commands/gettimeout.ts @@ -1,4 +1,4 @@ -import { Command, sendMessage } from "commands"; +import { Command, sendMessage } from "lib/commandUtils"; import { buildTimeString } from "lib/dateManager"; import parseCommandArgs from "lib/parseCommandArgs"; import User from "user"; diff --git a/src/commands/giveitem.ts b/src/commands/giveitem.ts index da573d9..64d763f 100644 --- a/src/commands/giveitem.ts +++ b/src/commands/giveitem.ts @@ -1,4 +1,4 @@ -import { Command, sendMessage } from "commands"; +import { Command, sendMessage } from "lib/commandUtils"; import { getUserRecord } from "db/dbUser"; import items, { changeItemCount } from "items"; import parseCommandArgs from "lib/parseCommandArgs"; diff --git a/src/commands/index.ts b/src/commands/index.ts index d4796c0..b5e24e8 100644 --- a/src/commands/index.ts +++ b/src/commands/index.ts @@ -1,39 +1,4 @@ -import { EventSubChannelChatMessageEvent } from "@twurple/eventsub-base"; -import User from "user"; - -export type userType = 'chatter' | 'admin' | 'streamer' | 'moderator'; - -export type specialExecuteArgs = { - activation?: string; -}; - -export type commandOptions = { - name: string; - aliases: string[]; - usertype: userType; - execution: (message: EventSubChannelChatMessageEvent, sender: User, args?: specialExecuteArgs) => Promise; - disableable?: boolean; - specialaliases?: string[]; -}; - -/** The Command class represents a command */ -export class Command { - public readonly name: string; - public readonly aliases: string[]; - public readonly usertype: userType; - public readonly disableable: boolean; - public readonly specialaliases: string[]; - public readonly execute: (message: EventSubChannelChatMessageEvent, sender: User, args?: specialExecuteArgs) => Promise; - constructor(options: commandOptions) { - this.name = options.name.toLowerCase(); - this.aliases = options.aliases; - this.usertype = options.usertype; - this.execute = options.execution; - this.disableable = options.disableable ?? true; - this.specialaliases = options.specialaliases ?? []; - }; -}; - +import { Command } from 'lib/commandUtils'; import { readdir } from 'node:fs/promises'; const commands = new Map; // This map has all command/item aliases mapped to commands/items (many-to-one) const specialAliasCommands = new Map; // This map has all special command/item aliases mapped to commands/items (just like commands map) @@ -63,14 +28,3 @@ for (const [alias, item] of Array.from(specialAliasItems)) { export default commands; export { specialAliasCommands, basecommands }; - -import { chatterApi, chatterId, streamerId } from "main"; - -/** Helper function to send a message to the stream */ -export const sendMessage = async (message: string, replyParentMessageId?: string) => { - try { - return await chatterApi.chat.sendChatMessageAsApp(chatterId, streamerId, message, { replyParentMessageId }); - } catch (e) { - return await chatterApi.chat.sendChatMessageAsApp(chatterId, streamerId, message); - }; -}; diff --git a/src/commands/iteminfo.ts b/src/commands/iteminfo.ts index 44d2031..fed0156 100644 --- a/src/commands/iteminfo.ts +++ b/src/commands/iteminfo.ts @@ -1,4 +1,4 @@ -import { Command, sendMessage } from "commands"; +import { Command, sendMessage } from "lib/commandUtils"; import items from "items"; import parseCommandArgs from "lib/parseCommandArgs"; diff --git a/src/commands/itemlock.ts b/src/commands/itemlock.ts index b09b377..f4fcd1c 100644 --- a/src/commands/itemlock.ts +++ b/src/commands/itemlock.ts @@ -1,4 +1,4 @@ -import { Command, sendMessage } from "commands"; +import { Command, sendMessage } from "lib/commandUtils"; import parseCommandArgs from "lib/parseCommandArgs"; import User from "user"; diff --git a/src/commands/monthlykdleaderboard.ts b/src/commands/monthlykdleaderboard.ts index 26371b0..d4b6c69 100644 --- a/src/commands/monthlykdleaderboard.ts +++ b/src/commands/monthlykdleaderboard.ts @@ -1,4 +1,4 @@ -import { Command, sendMessage } from "commands"; +import { Command, sendMessage } from "lib/commandUtils"; import { getKDLeaderboard } from "db/dbUser"; import User from "user"; diff --git a/src/commands/monthlystats.ts b/src/commands/monthlystats.ts index ecc5fa5..415c89f 100644 --- a/src/commands/monthlystats.ts +++ b/src/commands/monthlystats.ts @@ -1,4 +1,4 @@ -import { Command, sendMessage } from "commands"; +import { Command, sendMessage } from "lib/commandUtils"; import { getTimeoutStats, getItemStats } from "lib/getStats"; import parseCommandArgs from "lib/parseCommandArgs"; import User from "user"; diff --git a/src/commands/qbucksleaderboard.ts b/src/commands/qbucksleaderboard.ts index 180c914..6deaa90 100644 --- a/src/commands/qbucksleaderboard.ts +++ b/src/commands/qbucksleaderboard.ts @@ -1,4 +1,4 @@ -import { Command, sendMessage } from "commands"; +import { Command, sendMessage } from "lib/commandUtils"; import { getBalanceLeaderboard } from "db/dbUser"; import User from "user"; diff --git a/src/commands/racetime.ts b/src/commands/racetime.ts index 0054563..fb908f5 100644 --- a/src/commands/racetime.ts +++ b/src/commands/racetime.ts @@ -1,4 +1,4 @@ -import { Command, sendMessage } from "commands"; +import { Command, sendMessage } from "lib/commandUtils"; import logger from "lib/logger"; import { streamerId } from "main"; import User from "user"; diff --git a/src/commands/removeadmin.ts b/src/commands/removeadmin.ts index abe52ff..b4ff693 100644 --- a/src/commands/removeadmin.ts +++ b/src/commands/removeadmin.ts @@ -1,4 +1,4 @@ -import { Command, sendMessage } from "commands"; +import { Command, sendMessage } from "lib/commandUtils"; import { streamerUsers } from "main"; import { removeAdmin } from "lib/admins"; import parseCommandArgs from "lib/parseCommandArgs"; diff --git a/src/commands/removebot.ts b/src/commands/removebot.ts index c2a1961..bb423c6 100644 --- a/src/commands/removebot.ts +++ b/src/commands/removebot.ts @@ -1,6 +1,6 @@ -import { Command, sendMessage } from "commands"; +import { Command, sendMessage } from "lib/commandUtils"; import { streamerUsers } from "main"; -import { redis } from "bun"; +import { redis } from "lib/redis"; import parseCommandArgs from "lib/parseCommandArgs"; import User from "user"; diff --git a/src/commands/removeinvuln.ts b/src/commands/removeinvuln.ts index 862422b..708b2ed 100644 --- a/src/commands/removeinvuln.ts +++ b/src/commands/removeinvuln.ts @@ -1,4 +1,4 @@ -import { Command, sendMessage } from "commands"; +import { Command, sendMessage } from "lib/commandUtils"; import { streamerUsers } from "main"; import { removeInvuln } from "lib/invuln"; import parseCommandArgs from "lib/parseCommandArgs"; diff --git a/src/commands/roulette.ts b/src/commands/roulette.ts index f1acff4..6742632 100644 --- a/src/commands/roulette.ts +++ b/src/commands/roulette.ts @@ -1,5 +1,5 @@ -import { Command, sendMessage } from "commands"; -import { redis } from "bun"; +import { Command, sendMessage } from "lib/commandUtils"; +import { redis } from "lib/redis"; import { timeout } from "lib/timeout"; const barrelCount = 6; diff --git a/src/commands/seiso.ts b/src/commands/seiso.ts index e9b3b30..1f6fe6e 100644 --- a/src/commands/seiso.ts +++ b/src/commands/seiso.ts @@ -1,4 +1,4 @@ -import { Command, sendMessage } from "commands"; +import { Command, sendMessage } from "lib/commandUtils"; import { timeout } from "lib/timeout"; export default new Command({ @@ -8,7 +8,7 @@ export default new Command({ execution: async (msg, user) => { const rand = Math.floor(Math.random() * 101); if (rand > 75) await sendMessage(`${rand}% seiso YAAAA`, msg.messageId); - else if (rand > 51) await sendMessage(`${rand}% seiso POGGERS`, msg.messageId); + else if (rand > 50) await sendMessage(`${rand}% seiso POGGERS`, msg.messageId); else if (rand === 50) await sendMessage(`${rand}% seiso ok`, msg.messageId); else if (rand > 30) await sendMessage(`${rand}% seiso SWEAT`, msg.messageId); else if (rand > 10) await sendMessage(`${rand}% seiso catErm`, msg.messageId); diff --git a/src/commands/stacking.ts b/src/commands/stacking.ts index 2cff83a..8d6bb65 100644 --- a/src/commands/stacking.ts +++ b/src/commands/stacking.ts @@ -1,5 +1,5 @@ -import { redis } from "bun"; -import { Command, sendMessage } from "commands"; +import { redis } from "lib/redis"; +import { Command, sendMessage } from "lib/commandUtils"; import { isAdmin } from "lib/admins"; import parseCommandArgs from "lib/parseCommandArgs"; diff --git a/src/commands/testcheer.ts b/src/commands/testcheer.ts index 2cf0449..bfb2d81 100644 --- a/src/commands/testcheer.ts +++ b/src/commands/testcheer.ts @@ -1,4 +1,4 @@ -import { Command, sendMessage } from "commands"; +import { Command, sendMessage } from "lib/commandUtils"; import { handleCheer } from "events/message"; import parseCommandArgs from "lib/parseCommandArgs"; diff --git a/src/commands/useitem.ts b/src/commands/useitem.ts index 9e6042d..8da1957 100644 --- a/src/commands/useitem.ts +++ b/src/commands/useitem.ts @@ -1,9 +1,9 @@ -import { redis } from "bun"; -import { Command, sendMessage } from "commands"; +import { redis } from "lib/redis"; +import { Command, sendMessage } from "lib/commandUtils"; import items from "items"; import { isInvuln, removeInvuln } from "lib/invuln"; import { streamerUsers } from "main"; -import getloot from "./getloot"; +import getloot from "commands/getloot"; export default new Command({ name: 'use', @@ -11,8 +11,8 @@ export default new Command({ usertype: 'chatter', disableable: false, specialaliases: ['i'], - execution: async (msg, user) => { - const messagequery = msg.messageText.trim().split(' ').slice(1); + execution: async (msg, user, specialargs) => { + const messagequery = msg.messageText.trim().split(' ').slice(1); // This selects the item, so on "i blast mrockstar20" it would pick ["blast", "mrockstar20"] const silent = msg.messageText.toLowerCase().startsWith('i'); if (!messagequery[0]) { if (!silent) { await sendMessage('Please specify an item you would like to use', msg.messageId); }; return; }; const selection = items.get(messagequery[0].toLowerCase()); @@ -20,6 +20,6 @@ export default new Command({ if (!selection) { if (!silent) { await sendMessage(`'${messagequery[0]}' is not an item`, msg.messageId); }; return; }; if (await redis.sismember('disabledcommands', selection.name)) { await sendMessage(`The ${selection.prettyName} item is disabled`, msg.messageId); return; }; if (await isInvuln(msg.chatterId) && !streamerUsers.includes(msg.chatterId)) { await sendMessage(`You're no longer an invuln because you used an item.`, msg.messageId); await removeInvuln(msg.chatterId); }; - await selection.execute(msg, user); + await selection.execute(msg, user, specialargs); } }); diff --git a/src/commands/vulnchatters.ts b/src/commands/vulnchatters.ts index c5a20e2..1fa1731 100644 --- a/src/commands/vulnchatters.ts +++ b/src/commands/vulnchatters.ts @@ -1,5 +1,5 @@ -import { redis } from "bun"; -import { Command, sendMessage } from "commands"; +import { redis } from "lib/redis"; +import { Command, sendMessage } from "lib/commandUtils"; export default new Command({ name: 'vulnchatters', diff --git a/src/commands/yabai.ts b/src/commands/yabai.ts index ffa638e..224be1b 100644 --- a/src/commands/yabai.ts +++ b/src/commands/yabai.ts @@ -1,4 +1,4 @@ -import { Command, sendMessage } from "commands"; +import { Command, sendMessage } from "lib/commandUtils"; import { timeout } from "lib/timeout"; // Remake of the !yabai command in ttv/kiara_tv diff --git a/src/db/connection.ts b/src/db/connection.ts index 793bdd1..ef83f2a 100644 --- a/src/db/connection.ts +++ b/src/db/connection.ts @@ -1,15 +1,10 @@ import * as schema from "db/schema"; -import logger from "lib/logger"; -const host = process.env.POSTGRES_HOST ?? ""; -if (!host) { logger.enverr("POSTGRES_HOST"); process.exit(1); }; -const user = process.env.POSTGRES_USER ?? ""; -if (!user) { logger.enverr("POSTGRES_USER"); process.exit(1); }; -const password = process.env.POSTGRES_PASSWORD ?? ""; -if (!password) { logger.enverr("POSTGRES_USER"); process.exit(1); }; -const database = process.env.POSTGRES_DB ?? ""; -if (!database) { logger.enverr("POSTGRES_DB"); process.exit(1); }; -const url = `postgresql://${user}:${password}@${host}/${database}`; +export const host = process.env.POSTGRES_HOST ?? ""; +export const user = process.env.POSTGRES_USER ?? ""; +export const password = process.env.POSTGRES_PASSWORD ?? ""; +export const database = process.env.POSTGRES_DB ?? ""; +export const url = `postgresql://${user}:${password}@${host}/${database}`; import { drizzle } from 'drizzle-orm/bun-sql'; -export default drizzle(url, { schema }); +export default drizzle(url, { schema }) diff --git a/src/db/dbUser.ts b/src/db/dbUser.ts index 1fb8ed0..79ffce8 100644 --- a/src/db/dbUser.ts +++ b/src/db/dbUser.ts @@ -1,8 +1,8 @@ import db from "db/connection"; import { timeouts, users } from "db/schema"; -import { itemarray, type inventory } from "items"; +import { itemarray } from "items"; import type User from "user"; -import { count, desc, eq, inArray, sql, ne, between, and, SQL, type InferInsertModel, type InferSelectModel } from "drizzle-orm"; +import { count, desc, eq, inArray, sql, ne, between, and, SQL, type InferSelectModel } from "drizzle-orm"; /** Use this function to both ensure existance and to retreive data */ export async function getUserRecord(user: User) { diff --git a/src/events/bans.ts b/src/events/bans.ts index d57b7d1..3929d6c 100644 --- a/src/events/bans.ts +++ b/src/events/bans.ts @@ -1,6 +1,7 @@ -import { eventSub, streamerApi, streamerId } from "main"; +import { streamerId } from "main"; import { deleteBannedUserMessagesFromChatWidget } from "web/chatWidget/message"; -import { redis } from "bun"; +import { eventSub, streamerApi } from "index"; +import { redis } from "lib/redis"; eventSub.onChannelBan(streamerId, async msg => { deleteBannedUserMessagesFromChatWidget(msg); diff --git a/src/events/channelPoints.ts b/src/events/channelPoints.ts index dc0cac6..96ef1dc 100644 --- a/src/events/channelPoints.ts +++ b/src/events/channelPoints.ts @@ -1,6 +1,7 @@ -import { sendMessage } from "commands"; +import { sendMessage } from "lib/commandUtils"; +import { eventSub } from "index"; import logger from "lib/logger"; -import { eventSub, streamerId } from "main"; +import { streamerId } from "main"; import { activeRedeems } from "pointRedeems"; import User from "user"; diff --git a/src/events/deleteMessage.ts b/src/events/deleteMessage.ts index 6544b92..e1fdc2b 100644 --- a/src/events/deleteMessage.ts +++ b/src/events/deleteMessage.ts @@ -1,4 +1,5 @@ -import { eventSub, streamerId } from "main"; +import { eventSub } from "index"; +import { streamerId } from "main"; import { deleteMessageFromChatWidget } from "web/chatWidget/message"; eventSub.onChannelChatMessageDelete(streamerId, streamerId, async msg => { diff --git a/src/events/handleSubscriptions.ts b/src/events/handleSubscriptions.ts index c7ee454..b338065 100644 --- a/src/events/handleSubscriptions.ts +++ b/src/events/handleSubscriptions.ts @@ -1,7 +1,8 @@ -import { eventSub, chatterEventSub, streamerApi, streamerId, chatterApi, chatterId } from "main"; +import { streamerId, chatterId } from "main"; import { HelixEventSubSubscription } from "@twurple/api"; import kleur from "kleur"; import logger from "lib/logger"; +import { chatterApi, chatterEventSub, eventSub, streamerApi } from "index"; // This file is such a fucking disaster lmaooooo diff --git a/src/events/index.ts b/src/events/index.ts index 8888d75..2032844 100644 --- a/src/events/index.ts +++ b/src/events/index.ts @@ -1,4 +1,4 @@ -import { eventSub, chatterEventSub } from "main"; +import { eventSub, chatterEventSub } from "index"; import { readdir } from 'node:fs/promises'; const files = await readdir(import.meta.dir); diff --git a/src/events/message.ts b/src/events/message.ts index 9360b41..61d6d0d 100644 --- a/src/events/message.ts +++ b/src/events/message.ts @@ -1,8 +1,8 @@ import { EventSubChannelChatMessageEvent } from "@twurple/eventsub-base" -import { streamerId, eventSub, commandPrefix, streamerUsers } from "main"; +import { streamerId, commandPrefix, streamerUsers } from "main"; import User from "user"; -import commands, { Command, sendMessage, specialAliasCommands } from "commands"; -import { redis } from "bun"; +import commands, { specialAliasCommands } from "commands"; +import { Command, sendMessage } from "lib/commandUtils"; import { isAdmin } from "lib/admins"; import cheers from "cheers"; import logger from "lib/logger"; @@ -12,6 +12,8 @@ import { getUserRecord } from "db/dbUser"; import { createCheerRecord } from "db/dbCheers"; import handleAnivMessage from "lib/handleAnivMessage"; import { Item } from "items"; +import { eventSub } from "index"; +import { redis } from "lib/redis"; eventSub.onChannelChatMessage(streamerId, streamerId, parseChatMessage); diff --git a/src/events/moderators.ts b/src/events/moderators.ts index 3ebc7b8..38c2000 100644 --- a/src/events/moderators.ts +++ b/src/events/moderators.ts @@ -1,5 +1,6 @@ -import { redis } from "bun"; -import { eventSub, streamerId } from "main"; +import { eventSub } from "index"; +import { redis } from "lib/redis"; +import { streamerId } from "main"; eventSub.onChannelModeratorAdd(streamerId, async mod => { await redis.set(`user:${mod.userId}:mod`, '1'); diff --git a/src/events/raid.ts b/src/events/raid.ts index c352469..1aa9270 100644 --- a/src/events/raid.ts +++ b/src/events/raid.ts @@ -1,10 +1,11 @@ -import { redis } from "bun"; -import { sendMessage } from "commands"; +import { sendMessage } from "lib/commandUtils"; import { getUserRecord } from "db/dbUser"; +import { eventSub, streamerApi } from "index"; import { changeItemCount } from "items"; import logger from "lib/logger"; -import { eventSub, streamerApi, streamerId } from "main"; +import { streamerId } from "main"; import User from "user"; +import { redis } from "lib/redis"; eventSub.onChannelRaidTo(streamerId, async msg => { if (await redis.exists(`user:${msg.raidingBroadcasterId}:recentraid`)) { await sendMessage(`Another raid from ${msg.raidedBroadcasterDisplayName}??? SMH`); return; }; diff --git a/src/events/streamState.ts b/src/events/streamState.ts index 65ce115..f05e2d2 100644 --- a/src/events/streamState.ts +++ b/src/events/streamState.ts @@ -1,10 +1,13 @@ -import { redis } from "bun"; -import { sendMessage } from "commands"; -import { eventSub, streamerId } from "main"; +import { sendMessage } from "lib/commandUtils"; +import { eventSub } from "index"; +import { streamerId } from "main"; +import { sendDiscordMessage } from "web/discordConnection"; +import { redis } from "lib/redis"; eventSub.onStreamOnline(streamerId, async msg => { await redis.set('streamIsLive', '1'); await sendMessage(`${msg.broadcasterDisplayName.toUpperCase()} IS LIVE! START DIGGING!`); + await sendDiscordMessage({ message: 'live' }); }); eventSub.onStreamOffline(streamerId, async msg => { diff --git a/src/events/subscription.ts b/src/events/subscription.ts index 44e40be..723b814 100644 --- a/src/events/subscription.ts +++ b/src/events/subscription.ts @@ -1,9 +1,10 @@ -import { redis } from "bun"; -import { sendMessage } from "commands"; +import { sendMessage } from "lib/commandUtils"; import { getUserRecord, updateUserRecord } from "db/dbUser"; +import { eventSub } from "index"; import { changeBalance } from "lib/changeBalance"; -import { eventSub, streamerId } from "main"; +import { streamerId } from "main"; import User from "user"; +import { redis } from "lib/redis"; eventSub.onChannelSubscription(streamerId, async msg => { await redis.set(`user:${msg.userId}:subbed`, msg.tier.slice(0, 1)); diff --git a/src/events/whisper.ts b/src/events/whisper.ts index 4b8c001..8e63239 100644 --- a/src/events/whisper.ts +++ b/src/events/whisper.ts @@ -1,7 +1,8 @@ -import { redis } from "bun"; -import { sendMessage } from "commands"; +import { sendMessage } from "lib/commandUtils"; +import { chatterApi, chatterEventSub } from "index"; import { buildTimeString } from "lib/dateManager"; -import { chatterEventSub, chatterApi, chatterId } from "main"; +import { chatterId } from "main"; +import { redis } from "lib/redis"; const WHISPERCOOLDOWN = 60 * 5; // 5 minutes diff --git a/src/index.ts b/src/index.ts index f635637..2fec10a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,25 +1,17 @@ -import { createAuthProvider } from "./auth"; +import { chatterId, streamerId, singleUserMode, streamerUsers } from "main"; import { ApiClient } from "@twurple/api"; -import { EventSubWsListener } from "@twurple/eventsub-ws"; -import { addAdmin } from "lib/admins"; -import logger from "lib/logger"; -import { addInvuln } from "lib/invuln"; -import { redis } from "bun"; -import { remodMod, timeoutDuration } from "lib/timeout"; -import User from "user"; import { connectionCheck } from "connectionCheck"; +import logger from "lib/logger"; +import { redis } from "lib/redis"; +import { createAuthProvider } from "auth"; +import { EventSubWsListener } from "@twurple/eventsub-ws"; +import { user, password, database, host } from "db/connection"; await connectionCheck(); const CHATTERINTENTS = ["user:read:chat", "user:write:chat", "user:bot", "user:manage:whispers"]; const STREAMERINTENTS = ["channel:bot", "user:read:chat", "moderation:read", "channel:manage:moderators", "moderator:manage:chat_messages", "moderator:manage:banned_users", "bits:read", "channel:moderate", "moderator:manage:shoutouts", "channel:read:subscriptions", "channel:manage:redemptions"]; -export const singleUserMode = process.env.CHATTER_IS_STREAMER === 'true'; -export const chatterId = process.env.CHATTER_ID ?? ""; -if (chatterId === "") { logger.enverr('CHATTER_ID'); process.exit(1); }; -export const streamerId = process.env.STREAMER_ID ?? ""; -if (streamerId === "") { logger.enverr('STREAMER_ID'); process.exit(1); }; - export const chatterAuthProvider = await createAuthProvider(chatterId, singleUserMode ? CHATTERINTENTS.concat(STREAMERINTENTS) : CHATTERINTENTS); export const streamerAuthProvider = singleUserMode ? undefined : await createAuthProvider(streamerId, STREAMERINTENTS, true); @@ -34,11 +26,20 @@ export const eventSub = new EventSubWsListener({ apiClient: streamerApi }); export const chatterEventSub = singleUserMode ? eventSub : new EventSubWsListener({ apiClient: chatterApi }); -export const commandPrefix = process.env.COMMAND_PREFIX ?? "!"; +if (chatterId === "") { logger.enverr('CHATTER_ID'); process.exit(1); }; +if (streamerId === "") { logger.enverr('STREAMER_ID'); process.exit(1); }; +if (!user) { logger.enverr("POSTGRES_USER"); process.exit(1); }; +if (!password) { logger.enverr("POSTGRES_USER"); process.exit(1); }; +if (!database) { logger.enverr("POSTGRES_DB"); process.exit(1); }; +if (!host) { logger.enverr("POSTGRES_HOST"); process.exit(1); }; if (!singleUserMode) await redis.set(`user:${chatterId}:bot`, '1'); -export const streamerUsers = [chatterId, streamerId]; +import { addAdmin } from "lib/admins"; +import { addInvuln } from "lib/invuln"; +import User from "user"; +import { remodMod, timeoutDuration } from "lib/timeout"; + streamerUsers.forEach(async id => await Promise.all([addAdmin(id), addInvuln(id), redis.set(`user:${id}:mod`, '1')])); const banned = await streamerApi.moderation.getBannedUsers(streamerId).then(a => a.data); @@ -88,3 +89,4 @@ await import("./events"); await import("./pointRedeems"); await import("./web"); + diff --git a/src/items/blaster.ts b/src/items/blaster.ts index 0224294..8d4ffce 100644 --- a/src/items/blaster.ts +++ b/src/items/blaster.ts @@ -1,5 +1,5 @@ import { changeItemCount, Item } from "items"; -import { sendMessage } from "commands"; +import { sendMessage } from "lib/commandUtils"; import { createTimeoutRecord } from "db/dbTimeouts"; import { createUsedItemRecord } from "db/dbUsedItems"; import { getUserRecord } from "db/dbUser"; @@ -17,8 +17,8 @@ export default new Item({ description: 'Times a specific person out for 60 seconds', aliases: ['blaster', 'blast'], price: 100, - execution: async (msg, user) => { - const messagequery = parseCommandArgs(msg.messageText); + execution: async (msg, user, specialargs) => { + const messagequery = parseCommandArgs(msg.messageText, specialargs?.activation); if (!messagequery[0]) { await sendMessage('Please specify a target'); return; }; const target = await User.initUsername(messagequery[0].toLowerCase()); if (!target) { await sendMessage(`${messagequery[0]} doesn't exist`); return; }; diff --git a/src/items/grenade.ts b/src/items/grenade.ts index 7f9baf2..f9af6c2 100644 --- a/src/items/grenade.ts +++ b/src/items/grenade.ts @@ -1,5 +1,5 @@ -import { redis } from "bun"; -import { sendMessage } from "commands"; +import { redis } from "lib/redis"; +import { sendMessage } from "lib/commandUtils"; import { timeout } from "lib/timeout"; import { changeItemCount, Item } from "items"; import User from "user"; diff --git a/src/items/index.ts b/src/items/index.ts index 2ed9e05..0e4f309 100644 --- a/src/items/index.ts +++ b/src/items/index.ts @@ -1,6 +1,6 @@ import { EventSubChannelChatMessageEvent } from "@twurple/eventsub-base"; import User from "user"; -import { type userType, type specialExecuteArgs } from "commands"; +import { type userType, type specialExecuteArgs } from "lib/commandUtils"; type itemOptions = { name: items; diff --git a/src/items/silverbullet.ts b/src/items/silverbullet.ts index c60d875..5c13904 100644 --- a/src/items/silverbullet.ts +++ b/src/items/silverbullet.ts @@ -1,5 +1,5 @@ import { changeItemCount, Item } from "items"; -import { sendMessage } from "commands"; +import { sendMessage } from "lib/commandUtils"; import { createTimeoutRecord } from "db/dbTimeouts"; import { createUsedItemRecord } from "db/dbUsedItems"; import { getUserRecord } from "db/dbUser"; diff --git a/src/items/tnt.ts b/src/items/tnt.ts index 2e9f82b..5fe9c89 100644 --- a/src/items/tnt.ts +++ b/src/items/tnt.ts @@ -1,5 +1,5 @@ -import { redis } from "bun"; -import { sendMessage } from "commands"; +import { redis } from "lib/redis"; +import { sendMessage } from "lib/commandUtils"; import { timeout } from "lib/timeout"; import { changeItemCount, Item } from "items"; import User from "user"; diff --git a/src/lib/admins.ts b/src/lib/admins.ts index add8ad7..daa1c8c 100644 --- a/src/lib/admins.ts +++ b/src/lib/admins.ts @@ -1,4 +1,4 @@ -import { redis } from "bun"; +import { redis } from "lib/redis"; export async function getAdmins() { const data = await redis.keys('user:*:admin'); diff --git a/src/lib/commandUtils.ts b/src/lib/commandUtils.ts new file mode 100644 index 0000000..8cbacff --- /dev/null +++ b/src/lib/commandUtils.ts @@ -0,0 +1,46 @@ +import { EventSubChannelChatMessageEvent } from "@twurple/eventsub-base"; +import User from "user"; +import { chatterId, streamerId } from "main"; + +export type userType = 'chatter' | 'admin' | 'streamer' | 'moderator'; + +export type specialExecuteArgs = { + activation?: string; +}; + +export type commandOptions = { + name: string; + aliases: string[]; + usertype: userType; + execution: (message: EventSubChannelChatMessageEvent, sender: User, args?: specialExecuteArgs) => Promise; + disableable?: boolean; + specialaliases?: string[]; +}; + +/** The Command class represents a command */ +export class Command { + public readonly name: string; + public readonly aliases: string[]; + public readonly usertype: userType; + public readonly disableable: boolean; + public readonly specialaliases: string[]; + public readonly execute: (message: EventSubChannelChatMessageEvent, sender: User, args?: specialExecuteArgs) => Promise; + constructor(options: commandOptions) { + this.name = options.name.toLowerCase(); + this.aliases = options.aliases; + this.usertype = options.usertype; + this.execute = options.execution; + this.disableable = options.disableable ?? true; + this.specialaliases = options.specialaliases ?? []; + }; +}; + +/** Helper function to send a message to the stream */ +export const sendMessage = async (message: string, replyParentMessageId?: string) => { + const chatterApi = await import("index").then(m => m.chatterApi); + try { + return await chatterApi.chat.sendChatMessageAsApp(chatterId, streamerId, message, { replyParentMessageId }); + } catch (e) { + return await chatterApi.chat.sendChatMessageAsApp(chatterId, streamerId, message); + }; +}; \ No newline at end of file diff --git a/src/lib/handleAnivMessage.ts b/src/lib/handleAnivMessage.ts index bfe6f60..10bf9e1 100644 --- a/src/lib/handleAnivMessage.ts +++ b/src/lib/handleAnivMessage.ts @@ -1,8 +1,8 @@ import { EventSubChannelChatMessageEvent } from "@twurple/eventsub-base" -import { redis } from "bun"; +import { redis } from "lib/redis"; import type User from "user"; import { timeout } from "lib/timeout"; -import { sendMessage } from "commands"; +import { sendMessage } from "lib/commandUtils"; import { createAnivTimeoutRecord } from "db/dbAnivTimeouts"; const ANIVNAMES: anivBots[] = ['a_n_e_e_v', 'a_n_i_v']; diff --git a/src/lib/invuln.ts b/src/lib/invuln.ts index 5fe18d9..9f93e8e 100644 --- a/src/lib/invuln.ts +++ b/src/lib/invuln.ts @@ -1,4 +1,4 @@ -import { redis } from "bun"; +import { redis } from "lib/redis"; import { streamerUsers } from "main"; export async function getInvulns() { diff --git a/src/lib/parseCommandArgs.ts b/src/lib/parseCommandArgs.ts index 295f79d..c7c2c8a 100644 --- a/src/lib/parseCommandArgs.ts +++ b/src/lib/parseCommandArgs.ts @@ -6,6 +6,7 @@ export default function parseCommandArgs(input: string, specialAlias?: string) { let sliceLength = 0; if (specialAlias) { nice = input.toLowerCase().slice(specialAlias.length).replace(/[^\x00-\x7F]/g, '').trim(); + sliceLength = input.toLowerCase().startsWith('i') ? 1 : 0; } else { nice = input.toLowerCase().slice(commandPrefix.length).replace(/[^\x00-\x7F]/g, '').trim(); sliceLength = nice.startsWith('use') ? 2 : 1; diff --git a/src/lib/redis.ts b/src/lib/redis.ts new file mode 100644 index 0000000..97c61e5 --- /dev/null +++ b/src/lib/redis.ts @@ -0,0 +1,3 @@ +import { RedisClient } from "bun"; + +export const redis = new RedisClient(); \ No newline at end of file diff --git a/src/lib/timeout.ts b/src/lib/timeout.ts index 6cd51eb..a29dd0b 100644 --- a/src/lib/timeout.ts +++ b/src/lib/timeout.ts @@ -1,8 +1,9 @@ -import { streamerApi, streamerId } from "main"; +import { streamerId } from "main"; import logger from "lib/logger"; import User from "user"; import { isInvuln } from "lib/invuln"; -import { redis } from "bun"; +import { streamerApi } from "index"; +import { redis } from "lib/redis"; type SuccessfulTimeout = { status: true; }; type UnSuccessfulTimeout = { status: false; reason: 'banned' | 'unknown' | 'illegal'; }; diff --git a/src/main.ts b/src/main.ts new file mode 100644 index 0000000..9e317e2 --- /dev/null +++ b/src/main.ts @@ -0,0 +1,5 @@ +export const singleUserMode = process.env.CHATTER_IS_STREAMER === 'true'; +export const chatterId = process.env.CHATTER_ID ?? ""; +export const streamerId = process.env.STREAMER_ID ?? ""; +export const commandPrefix = process.env.COMMAND_PREFIX ?? "!"; +export const streamerUsers = [chatterId, streamerId]; diff --git a/src/pointRedeems/index.ts b/src/pointRedeems/index.ts index ceefd1d..b26bbc1 100644 --- a/src/pointRedeems/index.ts +++ b/src/pointRedeems/index.ts @@ -54,8 +54,9 @@ const activeRedeems = new Map; /** Map of redeemname to twitch redeem ID */ const idMap = new Map; -import { streamerApi, streamerId } from "main"; +import { streamerId } from "main"; import logger from "lib/logger"; +import { streamerApi } from "index"; const currentRedeems = new Map; await streamerApi.channelPoints.getCustomRewards(streamerId).then(a => a.map(b => currentRedeems.set(b.title, b.id))); diff --git a/src/pointRedeems/qbucksredeem.ts b/src/pointRedeems/qbucksredeem.ts index 713be35..e91647b 100644 --- a/src/pointRedeems/qbucksredeem.ts +++ b/src/pointRedeems/qbucksredeem.ts @@ -1,4 +1,4 @@ -import { sendMessage } from "commands"; +import { sendMessage } from "lib/commandUtils"; import { getUserRecord } from "db/dbUser"; import { changeBalance } from "lib/changeBalance"; import PointRedeem from "pointRedeems"; diff --git a/src/user.ts b/src/user.ts index 4449f8d..865fee9 100644 --- a/src/user.ts +++ b/src/user.ts @@ -1,5 +1,5 @@ -import { redis } from "bun"; -import { chatterApi } from "main"; +import { redis } from "lib/redis"; +import { chatterApi } from "index"; import { HelixUser } from "@twurple/api" import logger from "lib/logger"; diff --git a/src/web/chatWidget/widgetServerFunctions.ts b/src/web/chatWidget/widgetServerFunctions.ts index 7bb106a..c6fe51a 100644 --- a/src/web/chatWidget/widgetServerFunctions.ts +++ b/src/web/chatWidget/widgetServerFunctions.ts @@ -1,5 +1,6 @@ -import { streamerId, chatterApi } from "main"; -import { redis } from "bun"; +import { streamerId } from "main"; +import { chatterApi } from "index"; +import { redis } from "lib/redis"; type badgeObject = { [key: string]: { diff --git a/src/web/discordConnection.ts b/src/web/discordConnection.ts new file mode 100644 index 0000000..9aba52b --- /dev/null +++ b/src/web/discordConnection.ts @@ -0,0 +1,17 @@ +import server from "web"; + +type liveMessage = { + message: 'live'; +}; + +type offlineMessage = { + message: 'offline'; +}; + +export type discordMessage = + | liveMessage + | offlineMessage; + +export async function sendDiscordMessage(message: discordMessage) { + server.publish('discordbot', JSON.stringify(message)); +}; diff --git a/src/web/index.ts b/src/web/index.ts index 77f5b14..0b266fc 100644 --- a/src/web/index.ts +++ b/src/web/index.ts @@ -60,4 +60,3 @@ export default Bun.serve({ return new Response("Internal Server Error", { status: 500 }) }, }); - diff --git a/tsconfig.json b/tsconfig.json index faf5091..7ed479d 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -7,7 +7,7 @@ "./lib/*" ], "main": [ - "./index.ts" + "./main.ts" ], "user": [ "./user.ts" @@ -29,6 +29,9 @@ ], "pointRedeems": [ "./pointRedeems/index.ts" + ], + "discord": [ + "./discord/*" ] } },