From 2d43065a2a7bcc8c02c6424592b87cf48e913a06 Mon Sep 17 00:00:00 2001 From: qwerinope Date: Sat, 5 Apr 2025 23:19:11 +0200 Subject: [PATCH] buncha fixes: unused items no longer get subtracted, bot can not get blasted, 3 decimal stats --- README.md | 2 +- src/commands/getloot.ts | 4 +-- src/commands/inventory.ts | 2 +- src/commands/iteminfo.ts | 12 ++++----- src/commands/qbucks.ts | 2 +- src/commands/stats.ts | 2 +- src/commands/timeout.ts | 2 +- src/commands/use.ts | 2 +- src/lib/items.ts | 56 ++++++++++++++++++++++++++------------- src/lib/timeoutHelper.ts | 2 +- 10 files changed, 51 insertions(+), 35 deletions(-) diff --git a/README.md b/README.md index c47a3d7..ff98b98 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ COMMAND|FUNCTION|USER|ALIASES -|-|-|- `!balance [target]`|List write the amount of money the user or the target user has.|anyone|`!bal, !qbucks, !qweribucks` `!inventory [target]`|Show inventory contents of user or the target user.|anyone|`!inv` -`!getloot`|Give user a lootbox. This command has a cooldown that can be changed in `lootbox.ts`. You can optionally require the user to subscribe.|anyone|`None` +`!getloot`|Give user a lootbox. This command has a cooldown that can be changed in `lootbox.ts`.|anyone|`None` `!stats [target]`|Show the stats of user or target user including users shot, TNT used and grenades lobbed.|anyone|`None` `!timeout {target}`|Give the target user a timeout of 60 seconds. This requires 100 qbucks.|anyone|`None` `!use {item}`|Use a specific item. The user needs the specific item in their inventory. For items please look at the table below|anyone|`None` diff --git a/src/commands/getloot.ts b/src/commands/getloot.ts index 3339398..83338ed 100644 --- a/src/commands/getloot.ts +++ b/src/commands/getloot.ts @@ -13,10 +13,8 @@ function getTimeDifference(date1: number, date2: number) { return { days, hours, minutes, seconds }; } -export default createBotCommand('getloot', async (_params, { reply, userId, broadcasterId }) => { +export default createBotCommand('getloot', async (_params, { reply, userId }) => { const user = await api.users.getUserById(userId) - // Remove the comment on the following line to only give lootboxes to subscribed users - //if (!user?.isSubscribedTo(broadcasterId)) { await reply('Subscribe to get loot :)'); return } const data = await lootboxReady(user) if (!data.result) { const { days, hours, minutes, seconds } = getTimeDifference(data.lastlootbox, Date.now() - COOLDOWN) diff --git a/src/commands/inventory.ts b/src/commands/inventory.ts index ea2b464..a7297b4 100644 --- a/src/commands/inventory.ts +++ b/src/commands/inventory.ts @@ -43,7 +43,7 @@ export default createBotCommand('inv', async (params, { userName, say }) => { messagedata.push(`${item.name + (item.amount === 1 ? '' : item.plural)}: ${item.amount}`) } - if (messagedata.length === 0) {await say(`${data.me ? userName : params[0]} has no items mandoooYikes`); return} + if (messagedata.length === 0) {await say(`${data.me ? userName : params[0]} has no items!`); return} await say(` inventory of ${data.me ? userName : params[0]}: diff --git a/src/commands/iteminfo.ts b/src/commands/iteminfo.ts index 81a59ee..097df6e 100644 --- a/src/commands/iteminfo.ts +++ b/src/commands/iteminfo.ts @@ -5,23 +5,23 @@ export default createBotCommand('iteminfo', async (params, { say }) => { let message = '' switch (params[0].toLowerCase()) { case 'blaster': - message = "Item: blaster {target}, Function: Times the target user out for 60 seconds. Aliases: !blast, !blaster" + message = "Use: blaster {target}, Function: Times the target user out for 60 seconds. Aliases: !blast, !blaster" break case 'silver': case 'silverbullet': - message = "`Item: silverbullet {target}, Function: Times the target user out for 24 hours. Aliases: !execute, !silverbullet" + message = "Use: silverbullet {target}, Function: Times the target user out for 24 hours. Aliases: !execute, !silverbullet" break case 'grenade': - message = "Item: grenade, Function: Times a random chatter out for 60 seconds. Aliases: !grenade" + message = "Use: grenade, Function: Times a random chatter out for 60 seconds. Aliases: !grenade" break case 'tnt': - message = "Item: tnt, Function: Times out 1 to 10 chatters for 60 seconds. Aliases: !tnt" + message = "Use: tnt, Function: Times out 1 to 10 chatters for 60 seconds. Aliases: !tnt" break case 'lootbox': - message = "Item: lootbox, Function: Gives the user some qbucks, and possibly some items. Aliases: !lootbox" + message = "Use: lootbox, Function: Gives the user some qbucks, and possibly some items. Aliases: !lootbox" break case 'clipboard': - message = "Item: clipboard {message}, Function: Starts a two minute long poll with the user specified message. Aliases: !clipboard" + message = "Use: clipboard {message}, Function: Starts a two minute long poll with the user specified message. Aliases: !clipboard" break default: message = "Item not found" diff --git a/src/commands/qbucks.ts b/src/commands/qbucks.ts index 9940fd6..9f5b0dc 100644 --- a/src/commands/qbucks.ts +++ b/src/commands/qbucks.ts @@ -14,6 +14,6 @@ export default createBotCommand('balance', async (params, { userName, say }) => } const data = await getBalance(user) - await say(`${user.name} has ${data.balance} qbucks ${data.balance === 0 ? 'mandoooYikes' : 'mandoooSmile'}`) + await say(`${user.name} has ${data.balance} qbucks`) }, { aliases: ['qbucks', 'qweribucks', 'bal'] }) diff --git a/src/commands/stats.ts b/src/commands/stats.ts index fcf1336..72b4d08 100644 --- a/src/commands/stats.ts +++ b/src/commands/stats.ts @@ -21,7 +21,7 @@ export default createBotCommand('stats', async (params, { say, userName }) => { ` Stats of ${data.me ? userName : params[0]}: Users blasted: ${data.stats.shot.blaster}, - Blasted by others: ${data.stats.hit.blaster} (${isNaN(KD) ? 0 : KD} K/D). + Blasted by others: ${data.stats.hit.blaster} (${isNaN(KD) ? 0 : KD.toFixed(3)} K/D). Grenades lobbed: ${data.stats.used.grenade} TNTs lit: ${data.stats.used.tnt}, Silver bullets fired: ${data.stats.shot.silverbullet}, diff --git a/src/commands/timeout.ts b/src/commands/timeout.ts index 13fc4e0..a008d55 100644 --- a/src/commands/timeout.ts +++ b/src/commands/timeout.ts @@ -11,7 +11,7 @@ export default createBotCommand('timeout', async (params, { say, broadcasterId, const target = await api.users.getUserByName(params[0].replace(/[@]/g, '')) const status = await timeout(broadcasterId, target!, 60, `You got blasted by ${userName}`) if (status.status) { - await say(`${params[0]} got blasted by ${userName}! mandoooGOTTEM ${userName} now has ${userbal.balance - 100} qbucks remaining`) + await say(`${params[0]} got blasted by ${userName}! ${userName} now has ${userbal.balance - 100} qbucks remaining`) await changeBalance(attacker!, -100) await addTimeoutToDB(attacker!, target!, 'blaster') } diff --git a/src/commands/use.ts b/src/commands/use.ts index 605b56b..a104b35 100644 --- a/src/commands/use.ts +++ b/src/commands/use.ts @@ -32,6 +32,6 @@ export default createBotCommand('use', async (params, { say, broadcasterId, user await useClipboard(broadcasterId, user!, params.slice(1).join(' '), say) break default: - await say(`${params[0]} does not exist mandoooYikes`) + await say(`${params[0]} does not exist!`) } }) diff --git a/src/lib/items.ts b/src/lib/items.ts index bbbf95b..a012791 100644 --- a/src/lib/items.ts +++ b/src/lib/items.ts @@ -1,5 +1,5 @@ import { HelixUser } from "@twurple/api" -import { addUsedItem, changeBalance, getInventory, updateInventory } from "../lib/userHelper" +import { addUsedItem, changeBalance, getInventory, inventory, updateInventory } from "../lib/userHelper" import { timeout, addTimeoutToDB, vulnerableUsers } from "./timeoutHelper" import api, { broadcasterApi } from "./api" @@ -9,6 +9,7 @@ interface itemChangeResult { result: boolean, reason: string count: number, + inv?: inventory } export async function changeItemCount(user: HelixUser, item: string, amount = -1): Promise { @@ -21,9 +22,10 @@ export async function changeItemCount(user: HelixUser, item: string, amount = -1 Object.defineProperty(inv, item, { value: newcount, }) - await updateInventory(user, inv) - await addUsedItem(user, item) - return { result: true, reason: '', count: inv[item] } + + if (amount > 0) await updateInventory(user, inv) + + return { result: true, reason: '', count: inv[item], inv } } export async function useBlaster(broadcasterId: string, attacker: HelixUser, targetname: string, say: (arg0: string) => Promise) { @@ -31,12 +33,14 @@ export async function useBlaster(broadcasterId: string, attacker: HelixUser, tar const itemResult = await changeItemCount(attacker, 'blaster') - if (!itemResult.result && itemResult.reason === 'negative') { await say('You have no blasters mandoooYikes'); return } + if (!itemResult.result && itemResult.reason === 'negative') { await say('You have no blasters!'); return } const result = await timeout(broadcasterId, target!, 60, `You got blasted by ${attacker.name}`) if (result.status) { - await say(`${targetname} got blasted by ${attacker.name}! mandoooGOTTEM ${attacker.name} has ${itemResult.count} blaster${itemResult.count === 1 ? '' : 's'} remaining`) + await say(`${targetname} got blasted by ${attacker.name}! ${attacker.name} has ${itemResult.count} blaster${itemResult.count === 1 ? '' : 's'} remaining`) await addTimeoutToDB(attacker, target!, 'blaster') + await addUsedItem(attacker, 'blaster') + await updateInventory(attacker, itemResult.inv!) } else { switch (result.reason) { case 'noexist': @@ -57,12 +61,14 @@ export async function useSilverBullet(broadcasterId: string, attacker: HelixUser const target = await api.users.getUserByName(targetname) const itemResult = await changeItemCount(attacker, 'silverbullet') - if (!itemResult.result && itemResult.reason === 'negative') { await say('You have no silver bullets mandoooYikes'); return } + if (!itemResult.result && itemResult.reason === 'negative') { await say('You have no silver bullets!'); return } const result = await timeout(broadcasterId, target!, 60 * 60 * 24, `You got hit by a silver bullet fired by ${attacker.name}`) if (result.status) { - await say(`${target?.name} mandoooSalute mandoooSalute mandoooSalute mandoooSalute mandoooSalute mandoooSalute mandoooSalute mandoooSalute mandoooSalute mandoooSalute mandoooSalute mandoooSalute mandoooSalute mandoooSalute mandoooSalute mandoooSalute mandoooSalute mandoooSalute mandoooSalute mandoooSalute mandoooSalute `) + await say(`${target?.name} got deleted.`) await addTimeoutToDB(attacker, target!, 'silverbullet') + await addUsedItem(attacker, 'silverbullet') + await updateInventory(attacker, itemResult.inv!) } else { switch (result.reason) { case 'noexist': @@ -83,25 +89,26 @@ export async function useGrenade(broadcasterId: string, attacker: HelixUser, say if (vulnerableUsers.length === 0) { await say('No chatters to blow up!'); return } const itemResult = await changeItemCount(attacker, 'grenade') - if (!itemResult.result && itemResult.reason === 'negative') { await say('You have no grenades mandoooYikes'); return } + if (!itemResult.result && itemResult.reason === 'negative') { await say('You have no grenades!'); return } const target = await api.users.getUserById(vulnerableUsers[Math.floor(Math.random() * vulnerableUsers.length)]) const result = await timeout(broadcasterId, target!, 60, `You got hit by ${attacker.name}'s grenade`) if (result.status) { - await say(`${target?.name} got blown up by ${attacker.name}'s grenade! mandoooGOTTEM`) + await say(`${target?.name} got blown up by ${attacker.name}'s grenade!`) await addTimeoutToDB(attacker, target!, 'grenade') + await addUsedItem(attacker, 'grenade') + await updateInventory(attacker, itemResult.inv!) } else { // Banned is not an option, and neither is noexist - await say(`something went wrong mandoooYikes`) + await say(`something went wrong`) console.error(result.reason) } } - export async function useTNT(broadcasterId: string, attacker: HelixUser, say: (args0: string) => Promise) { if (vulnerableUsers.length === 0) { await say('No chatters to blow up!'); return } const itemResult = await changeItemCount(attacker, 'tnt') - if (!itemResult.result && itemResult.reason === 'negative') { await say('You have no TNT mandoooYikes'); return } + if (!itemResult.result && itemResult.reason === 'negative') { await say('You have no TNT!'); return } const min = vulnerableUsers.length < 3 ? vulnerableUsers.length : 3 //if less than 3 chatters, use that else 3 const max = vulnerableUsers.length > 10 ? 10 : vulnerableUsers.length //if more than 10 chatters do 10 else 10 const blastedusers = Math.floor(Math.random() * (max - min + 1)) + min @@ -110,14 +117,16 @@ export async function useTNT(broadcasterId: string, attacker: HelixUser, say: (a for (const target of targets) { const result = await timeout(broadcasterId, target!, 60, `You got hit by ${attacker.name}'s TNT`) if (result.status) { - await say(`${target?.name} got blown up by TNT! mandoooTNT`) + await say(`${target?.name} got blown up by TNT!`) await addTimeoutToDB(attacker, target!, 'tnt') + await addUsedItem(attacker, 'tnt') + await updateInventory(attacker, itemResult.inv!) } else { - await say(`something went wrong mandoooYikes`) + await say(`something went wrong`) console.error(result.reason) } } - await say(`${attacker.name} blew up ${blastedusers} chatters with their TNT mandoooGOTTEM ${attacker.name} has ${itemResult.count} tnt${itemResult.count === 1 ? '' : 's'} remaining`) + await say(`${attacker.name} blew up ${blastedusers} chatters with their TNT! ${attacker.name} has ${itemResult.count} tnt${itemResult.count === 1 ? '' : 's'} remaining`) } function getRandom(): number { @@ -126,7 +135,7 @@ function getRandom(): number { export async function useLootbox(user: HelixUser, say: (arg0: string) => Promise) { const itemResult = await changeItemCount(user, 'lootbox') - if (!itemResult.result && itemResult.reason === 'negative') { await say('You have no lootboxes mandoooYikes'); return } + if (!itemResult.result && itemResult.reason === 'negative') { await say('You have no lootboxes!'); return } // Lootbox logic will for now just be get 25 qbucks, with 50% chance to get a grenade 25% chance to get a blaster and 10% chance to get TNT let inventory = await getInventory(user) let newitems: string[] = [] @@ -135,7 +144,9 @@ export async function useLootbox(user: HelixUser, say: (arg0: string) => Promise if (getRandom() <= 50) { newitems.push('1 grenade'); inventory.grenade += 1 } if (getRandom() <= 25) { newitems.push('1 blaster'); inventory.blaster += 1 } if (getRandom() <= 10) { newitems.push('1 tnt'); inventory.tnt += 1 } + inventory.lootbox = itemResult.inv!.lootbox await updateInventory(user, inventory) + await addUsedItem(user, 'lootbox') await say(`${user.name} got: ${newitems.join(' and ')}`) } @@ -153,10 +164,17 @@ function shuffle(arrayold: any[]) { export async function useClipboard(broadcasterId: string, user: HelixUser, question: string, say: (arg0: string) => Promise) { const tempapi = broadcasterApi ?? api + const polldata = await tempapi.polls.getPolls(broadcasterId) - if (polldata.data.length > 0) {await say('Can\'t have two polls active at once.'); return} + const activepolldata = polldata.data.filter(poll => poll.status === "ACTIVE") + if (activepolldata.length > 0) { await say('Can\'t have two polls active at once.'); return } + const itemResult = await changeItemCount(user, 'clipboard') - if (!itemResult.result && itemResult.reason === 'negative') { await say('You have no clipboards mandoooYikes'); return } + await addUsedItem(user, 'clipboard') + await updateInventory(user, itemResult.inv!) + + if (!itemResult.result && itemResult.reason === 'negative') { await say('You have no clipboards!'); return } + await tempapi.polls.createPoll(broadcasterId, { choices: ['Yes', 'No'], duration: 120, title: question }) await say(`${user.name} used a clipboard! They have ${itemResult.count} clipboard${itemResult.count === 1 ? '' : 's'} remaining`) } diff --git a/src/lib/timeoutHelper.ts b/src/lib/timeoutHelper.ts index 52899a2..799e6ab 100644 --- a/src/lib/timeoutHelper.ts +++ b/src/lib/timeoutHelper.ts @@ -13,7 +13,7 @@ interface statusmessage { export async function timeout(broadcasterid: string, target: HelixUser, duration: number, reason: string): Promise { if (!target) return { status: false, reason: 'noexist' } const tmpapi = broadcasterApi ?? api - // if (target.name === 'qwerinope') return { status: false, reason: 'unknown' } + if (target.name === process.env.BOT_NAME) return { status: false, reason: 'unknown' } if (await tmpapi.moderation.checkUserBan(broadcasterid, target)) return { status: false, reason: 'banned' } try {