From a698cb25d5511d26d196a966ecf82c94482f6ff4 Mon Sep 17 00:00:00 2001 From: qwerinope Date: Wed, 2 Jul 2025 18:10:28 +0200 Subject: [PATCH] added itemlock command, added TNT item, minor bugfixes --- README.md | 1 + bot/commands/admindonate.ts | 2 +- bot/commands/admingive.ts | 2 +- bot/commands/donateqbucks.ts | 3 +- bot/commands/giveitem.ts | 3 +- bot/commands/itemlock.ts | 13 +++++++++ bot/db/dbUser.ts | 2 +- bot/events/message.ts | 8 ++++-- bot/items/blaster.ts | 2 +- bot/items/grenade.ts | 2 +- bot/items/tnt.ts | 53 ++++++++++++++++++++++++++++++++++++ 11 files changed, 82 insertions(+), 9 deletions(-) create mode 100644 bot/commands/itemlock.ts create mode 100644 bot/items/tnt.ts diff --git a/README.md b/README.md index 963b2d0..54c0b16 100644 --- a/README.md +++ b/README.md @@ -52,6 +52,7 @@ COMMAND|FUNCTION|USER|ALIASES|DISABLEABLE `disablecommand {command/item}`|Disable a specific command/item|admins|`disablecommand`|:x: `enablecommand {command/item}`|Re-enable a specific command/item|admins|`enablecommand`|:x: `getadmins`|Get a list of every admin in the channel|anyone|`getadmins`|:x: +`itemlock {target}`|Toggle the itemlock on the specified target|admins|:x: `addadmin {target}`|Adds an admin|streamer/botchatter|`addadmin`|:x: `removeadmin {target}`|Removes an admin|streamer/botchatter|`removeadmin`|:x: diff --git a/bot/commands/admindonate.ts b/bot/commands/admindonate.ts index c575f48..25fa008 100644 --- a/bot/commands/admindonate.ts +++ b/bot/commands/admindonate.ts @@ -13,7 +13,7 @@ export default new Command('admindonate', ['admindonate'], 'admin', async msg => if (!args[1]) { await sendMessage('Please specify the amount qweribucks you want to give', msg.messageId); return; }; const amount = Number(args[1]); if (isNaN(amount)) { await sendMessage(`${args[1]} is not a valid amount`); return; }; - if (await target.itemLock()) { await sendMessage('Cannot give qweribucks: item transaction in progress', msg.messageId); return; }; + if (await target.itemLock()) { await sendMessage('Cannot give qweribucks: item lock is set', msg.messageId); return; }; await target.setLock(); const data = await changeBalance(target, userRecord, amount); if (!data) { diff --git a/bot/commands/admingive.ts b/bot/commands/admingive.ts index 2541717..4e350dd 100644 --- a/bot/commands/admingive.ts +++ b/bot/commands/admingive.ts @@ -16,7 +16,7 @@ export default new Command('admingive', ['admingive'], 'admin', async msg => { if (!args[2]) { await sendMessage('Please specify the amount of the item you want to give', msg.messageId); return; }; const amount = Number(args[2]); if (isNaN(amount)) { await sendMessage(`${args[2]} is not a valid amount`); return; }; - if (await target.itemLock()) { await sendMessage('Cannot give item: item transaction in progress', msg.messageId); return; }; + if (await target.itemLock()) { await sendMessage('Cannot give item: item lock is set', msg.messageId); return; }; await target.setLock(); const data = await changeItemCount(target, userRecord, item.name, amount); if (data) { diff --git a/bot/commands/donateqbucks.ts b/bot/commands/donateqbucks.ts index a0c30ed..63d4147 100644 --- a/bot/commands/donateqbucks.ts +++ b/bot/commands/donateqbucks.ts @@ -10,6 +10,7 @@ export default new Command('donate', ['donate'], 'chatter', async (msg, user) => if (!args[0]) { await sendMessage('Please specify a user', msg.messageId); return; }; const target = await User.initUsername(args[0].toLowerCase()); if (!target) { await sendMessage(`Chatter ${args[0]} doesn't exist`, msg.messageId); return; }; + if (target.username === user.username) { await sendMessage("You can't give yourself qweribucks", msg.messageId); return; }; const targetRecord = await getUserRecord(target); if (!args[1]) { await sendMessage('Please specify the amount of the item you want to give', msg.messageId); return; }; const amount = Number(args[1]); @@ -18,7 +19,7 @@ export default new Command('donate', ['donate'], 'chatter', async (msg, user) => const userRecord = await getUserRecord(user); if (userRecord.balance < amount) { await sendMessage(`You can't give qweribucks you don't have!`, msg.messageId); return; }; - if (await user.itemLock() || await target.itemLock()) { await sendMessage('Cannot give qweribucks. Please try again!', msg.messageId); return; }; + if (await user.itemLock() || await target.itemLock()) { await sendMessage('Cannot give qweribucks', msg.messageId); return; }; await Promise.all([ user.setLock(), diff --git a/bot/commands/giveitem.ts b/bot/commands/giveitem.ts index 3923edc..a31787c 100644 --- a/bot/commands/giveitem.ts +++ b/bot/commands/giveitem.ts @@ -10,6 +10,7 @@ export default new Command('give', ['give'], 'chatter', async (msg, user) => { if (!args[0]) { await sendMessage('Please specify a user', msg.messageId); return; }; const target = await User.initUsername(args[0].toLowerCase()); if (!target) { await sendMessage(`Chatter ${args[0]} doesn't exist`, msg.messageId); return; }; + if (target.username === user.username) { await sendMessage("You can't give yourself items", msg.messageId); return; }; const targetRecord = await getUserRecord(target); if (!args[1]) { await sendMessage('Please specify an item to give', msg.messageId); return; }; const item = items.get(args[1].toLowerCase()); @@ -21,7 +22,7 @@ export default new Command('give', ['give'], 'chatter', async (msg, user) => { const userRecord = await getUserRecord(user); if (userRecord.inventory[item.name]! < amount) { await sendMessage(`You can't give items you don't have!`, msg.messageId); return; }; - if (await user.itemLock() || await target.itemLock()) { await sendMessage('Cannot give item. Please try again!', msg.messageId); return; }; + if (await user.itemLock() || await target.itemLock()) { await sendMessage('Cannot give item', msg.messageId); return; }; await Promise.all([ user.setLock(), diff --git a/bot/commands/itemlock.ts b/bot/commands/itemlock.ts new file mode 100644 index 0000000..5477155 --- /dev/null +++ b/bot/commands/itemlock.ts @@ -0,0 +1,13 @@ +import { Command, sendMessage } from "."; +import parseCommandArgs from "../lib/parseCommandArgs"; +import { User } from "../user"; + +export default new Command('itemlock', ['itemlock'], 'admin', async msg => { + const args = parseCommandArgs(msg.messageText); + if (!args[0]) { await sendMessage('Please specify a chatter to toggle the lock for', msg.messageId); return; }; + const target = await User.initUsername(args[0].toLowerCase()); + if (!target) { await sendMessage('Targeted user does not exist', msg.messageId); return; }; + const status = await target.itemLock(); + status ? await target.clearLock() : await target.setLock(); + await sendMessage(`Successfully ${status ? 'cleared' : 'set'} the item lock on ${target.displayName}`, msg.messageId); +}, false); diff --git a/bot/db/dbUser.ts b/bot/db/dbUser.ts index e403517..d735907 100644 --- a/bot/db/dbUser.ts +++ b/bot/db/dbUser.ts @@ -10,7 +10,7 @@ export async function getUserRecord(user: User): Promise { if (Object.keys(data.inventory).sort().toString() !== itemarray.sort().toString()) { // If the items in the user inventory are missing an item. itemarray.forEach(key => { - if (!(key in data.inventory)) Object.defineProperty(data.inventory, key, { value: 0 }); + if (!(key in data.inventory)) data.inventory[key] = 0; }); }; diff --git a/bot/events/message.ts b/bot/events/message.ts index 5769b1a..84d6aa1 100644 --- a/bot/events/message.ts +++ b/bot/events/message.ts @@ -1,6 +1,6 @@ import { chatterId, streamerId, eventSub, commandPrefix, singleUserMode, streamerUsers } from ".."; import { User } from "../user"; -import commands from "../commands"; +import commands, { sendMessage } from "../commands"; import { redis } from "bun"; import { isAdmin } from "../lib/admins"; @@ -42,6 +42,10 @@ eventSub.onChannelChatMessage(streamerId, streamerId, async msg => { }; try { await selected.execute(msg, user!); } - catch (err) { console.error(err); }; + catch (err) { + console.error(err); + await sendMessage('ERROR: Something went wrong', msg.messageId); + await user?.clearLock(); + }; }; }); diff --git a/bot/items/blaster.ts b/bot/items/blaster.ts index 1a6b635..2571b38 100644 --- a/bot/items/blaster.ts +++ b/bot/items/blaster.ts @@ -21,7 +21,7 @@ export default new Item(ITEMNAME, 'Blaster', 's', if (!target) { await sendMessage(`${messagequery[0]} doesn't exist`); return; }; await getUserRecord(target); // make sure the user record exist in the database - if (await user.itemLock()) { await sendMessage('Can\'t use two items at once pepeW', msg.messageId); return; }; + if (await user.itemLock()) { await sendMessage('Cannot use an item right now', msg.messageId); return; }; await user.setLock(); const result = await timeout(target, `You got blasted by ${user.displayName}!`, 60); if (result.status) await Promise.all([ diff --git a/bot/items/grenade.ts b/bot/items/grenade.ts index 5632260..fa386bd 100644 --- a/bot/items/grenade.ts +++ b/bot/items/grenade.ts @@ -22,7 +22,7 @@ export default new Item(ITEMNAME, 'Grenade', 's', await getUserRecord(target!); // make sure the user record exist in the database - if (await user.itemLock()) { await sendMessage('Can\'t use two items at once pepeW', msg.messageId); return; }; + if (await user.itemLock()) { await sendMessage('Cannot use an item right now', msg.messageId); return; }; await user.setLock(); await Promise.all([ timeout(target!, `You got hit by ${user.displayName}'s grenade!`, 60), diff --git a/bot/items/tnt.ts b/bot/items/tnt.ts new file mode 100644 index 0000000..5c4a44d --- /dev/null +++ b/bot/items/tnt.ts @@ -0,0 +1,53 @@ +import { redis } from "bun"; +import { sendMessage } from "../commands"; +import { timeout } from "../lib/timeout"; +import { changeItemCount, Item } from "."; +import { User } from "../user"; +import { getUserRecord } from "../db/dbUser"; +import { createTimeoutRecord } from "../db/dbTimeouts"; +import { createUsedItemRecord } from "../db/dbUsedItems"; + +const ITEMNAME = 'tnt'; + +export default new Item(ITEMNAME, 'TNT', 's', + 'Give 5-10 random chatters 60 second timeouts', + ['tnt'], + async (msg, user) => { + const userObj = await getUserRecord(user); + if (userObj.inventory[ITEMNAME]! < 1) { await sendMessage(`You don't have any TNTs!`, msg.messageId); return; }; + const vulntargets = await redis.keys('vulnchatters:*'); + if (vulntargets.length === 0) { await sendMessage('No vulnerable chatters to blow up', msg.messageId); return; }; + const targets = getTNTTargets(vulntargets); + + if (await user.itemLock()) { await sendMessage('Cannot use an item right now', msg.messageId); return; }; + await user.setLock(); + + await Promise.all(targets.map(async targetid => { + const target = await User.initUserId(targetid.split(':')[1]!); + await getUserRecord(target!); // make sure the user record exist in the database + await Promise.all([ + timeout(target!, `You got hit by ${user.displayName}'s TNT!`, 60), + redis.del(targetid), + sendMessage(`wybuh ${target?.displayName} got hit by ${user.displayName}'s TNT wybuh`), + createTimeoutRecord(user, target!, ITEMNAME), + ]); + })); + + await Promise.all([ + createUsedItemRecord(user, ITEMNAME), + changeItemCount(user, userObj, ITEMNAME) + ]); + await user.clearLock(); + await sendMessage(`RIPBOZO ${user.displayName} exploded ${targets.length} chatter${targets.length === 1 ? '' : 's'} with their TNT RIPBOZO`); + } +); + +function getTNTTargets(arr: T[]): T[] { + if (arr.length <= 5) { + return arr; + }; + + const count = Math.floor(Math.random() * 6) + 5; // Random number between 5 and 10 + const shuffled = [...arr].sort(() => 0.5 - Math.random()); // Shuffle array + return shuffled.slice(0, Math.min(count, arr.length)); // Return up to `count` entries +};