From 4463bc6035863dfa761d7488bcc28e33151530b1 Mon Sep 17 00:00:00 2001 From: qwerinope Date: Thu, 11 Sep 2025 16:26:57 +0200 Subject: [PATCH] major reworks, prefixless commands added --- src/commands/addadmin.ts | 24 ++++--- src/commands/addinvuln.ts | 24 ++++--- src/commands/admindonate.ts | 41 +++++++----- src/commands/admingive.ts | 49 +++++++------- src/commands/alltimestats.ts | 27 ++++---- src/commands/backshot.ts | 15 +++-- src/commands/banclanker.ts | 20 ------ src/commands/disablecheer.ts | 24 ++++--- src/commands/disablecommand.ts | 26 +++++--- src/commands/donateqbucks.ts | 71 ++++++++++---------- src/commands/enablecheer.ts | 24 ++++--- src/commands/enablecommand.ts | 24 ++++--- src/commands/getadmins.ts | 24 ++++--- src/commands/getbalance.ts | 17 +++-- src/commands/getcheers.ts | 52 ++++++++------- src/commands/getcommands.ts | 42 +++++++----- src/commands/getinventory.ts | 39 ++++++----- src/commands/getinvulns.ts | 24 ++++--- src/commands/getloot.ts | 117 +++++++++++++++++---------------- src/commands/gettimeout.ts | 23 ++++--- src/commands/giveitem.ts | 75 +++++++++++---------- src/commands/index.ts | 40 ++++++++--- src/commands/iteminfo.ts | 17 +++-- src/commands/itemlock.ts | 24 ++++--- src/commands/monthlystats.ts | 27 ++++---- src/commands/removeadmin.ts | 26 +++++--- src/commands/removeinvuln.ts | 26 +++++--- src/commands/roulette.ts | 31 +++++---- src/commands/seiso.ts | 27 ++++---- src/commands/stacking.ts | 40 ++++++----- src/commands/testcheer.ts | 20 ++++-- src/commands/timeout.ts | 65 +++++++++--------- src/commands/useitem.ts | 22 ++++--- src/commands/vulnchatters.ts | 13 ++-- src/commands/yabai.ts | 25 ++++--- src/events/message.ts | 66 ++++++++++++------- src/items/blaster.ts | 13 ++-- src/items/grenade.ts | 13 ++-- src/items/index.ts | 45 ++++++++----- src/items/silverbullet.ts | 14 ++-- src/items/tnt.ts | 13 ++-- src/lib/parseCommandArgs.ts | 12 +++- 42 files changed, 796 insertions(+), 565 deletions(-) delete mode 100644 src/commands/banclanker.ts diff --git a/src/commands/addadmin.ts b/src/commands/addadmin.ts index 34f286a..fd94c4a 100644 --- a/src/commands/addadmin.ts +++ b/src/commands/addadmin.ts @@ -3,12 +3,18 @@ import { addAdmin } from "lib/admins"; import parseCommandArgs from "lib/parseCommandArgs"; import User from "user"; -export default new Command('addadmin', ['addadmin'], 'streamer', async msg => { - const args = parseCommandArgs(msg.messageText); - if (!args[0]) { await sendMessage('Please specify a target', msg.messageId); return; }; - const target = await User.initUsername(args[0].toLowerCase()); - if (!target) { await sendMessage(`Chatter ${args[0]} doesn't exist`, msg.messageId); return; }; - const data = await addAdmin(target.id); - if (data === "OK") await sendMessage(`${target.displayName} is now an admin`, msg.messageId); - else await sendMessage(`${target.displayName} is already an admin`, msg.messageId); -}, false); +export default new Command({ + name: 'addadmin', + aliases: ['addadmin'], + usertype: 'streamer', + disableable: false, + execution: async msg => { + const args = parseCommandArgs(msg.messageText); + if (!args[0]) { await sendMessage('Please specify a target', msg.messageId); return; }; + const target = await User.initUsername(args[0].toLowerCase()); + if (!target) { await sendMessage(`Chatter ${args[0]} doesn't exist`, msg.messageId); return; }; + const data = await addAdmin(target.id); + if (data === "OK") await sendMessage(`${target.displayName} is now an admin`, msg.messageId); + else await sendMessage(`${target.displayName} is already an admin`, msg.messageId); + } +}); diff --git a/src/commands/addinvuln.ts b/src/commands/addinvuln.ts index ea5ba03..9f6855b 100644 --- a/src/commands/addinvuln.ts +++ b/src/commands/addinvuln.ts @@ -3,12 +3,18 @@ import { addInvuln } from "lib/invuln"; import parseCommandArgs from "lib/parseCommandArgs"; import User from "user"; -export default new Command('addinvuln', ['addinvuln'], 'admin', async msg => { - const args = parseCommandArgs(msg.messageText); - if (!args[0]) { await sendMessage('Please specify a target', msg.messageId); return; }; - const target = await User.initUsername(args[0].toLowerCase()); - if (!target) { await sendMessage(`Chatter ${args[0]} doesn't exist`, msg.messageId); return; }; - const data = await addInvuln(target.id); - if (data === "OK") await sendMessage(`${target.displayName} is now an invuln`, msg.messageId); - else await sendMessage(`${target.displayName} is already an invuln`, msg.messageId); -}, false); +export default new Command({ + name: 'addinvuln', + aliases: ['addinvuln'], + usertype: 'admin', + disableable: false, + execution: async msg => { + const args = parseCommandArgs(msg.messageText); + if (!args[0]) { await sendMessage('Please specify a target', msg.messageId); return; }; + const target = await User.initUsername(args[0].toLowerCase()); + if (!target) { await sendMessage(`Chatter ${args[0]} doesn't exist`, msg.messageId); return; }; + const data = await addInvuln(target.id); + if (data === "OK") await sendMessage(`${target.displayName} is now an invuln`, msg.messageId); + else await sendMessage(`${target.displayName} is already an invuln`, msg.messageId); + } +}); diff --git a/src/commands/admindonate.ts b/src/commands/admindonate.ts index 9e86f32..0fa4b74 100644 --- a/src/commands/admindonate.ts +++ b/src/commands/admindonate.ts @@ -4,22 +4,27 @@ import { changeBalance } from "lib/changeBalance"; import parseCommandArgs from "lib/parseCommandArgs"; import User from "user"; -export default new Command('admindonate', ['admindonate'], 'admin', async msg => { - const args = parseCommandArgs(msg.messageText); - 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; }; - const userRecord = await getUserRecord(target); - 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 lock is set', msg.messageId); return; }; - await target.setLock(); - const data = await changeBalance(target, userRecord, amount); - if (!data) { - await sendMessage(`Failed to give ${target.displayName} ${amount} qweribuck${amount === 1 ? '' : 's'}`, msg.messageId); - } else { - await sendMessage(`${target.displayName} now has ${data.balance} qweribuck${data.balance === 1 ? '' : 's'}`, msg.messageId); - }; - await target.clearLock(); +export default new Command({ + name: 'admindonate', + aliases: ['admindonate'], + usertype: 'admin', + execution: async msg => { + const args = parseCommandArgs(msg.messageText); + 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; }; + const userRecord = await getUserRecord(target); + 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 lock is set', msg.messageId); return; }; + await target.setLock(); + const data = await changeBalance(target, userRecord, amount); + if (!data) { + await sendMessage(`Failed to give ${target.displayName} ${amount} qweribuck${amount === 1 ? '' : 's'}`, msg.messageId); + } else { + await sendMessage(`${target.displayName} now has ${data.balance} qweribuck${data.balance === 1 ? '' : 's'}`, msg.messageId); + }; + await target.clearLock(); + } }); diff --git a/src/commands/admingive.ts b/src/commands/admingive.ts index b97d547..46fe1ff 100644 --- a/src/commands/admingive.ts +++ b/src/commands/admingive.ts @@ -4,26 +4,31 @@ import items, { changeItemCount } from "items"; import parseCommandArgs from "lib/parseCommandArgs"; import User from "user"; -export default new Command('admingive', ['admingive'], 'admin', async msg => { - const args = parseCommandArgs(msg.messageText); - 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; }; - const userRecord = await getUserRecord(target); - if (!args[1]) { await sendMessage('Please specify an item to give', msg.messageId); return; }; - const item = items.get(args[1].toLowerCase()); - if (!item) { await sendMessage(`Item ${args[1]} doesn't exist`, msg.messageId); return; }; - 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 lock is set', msg.messageId); return; }; - await target.setLock(); - const data = await changeItemCount(target, userRecord, item.name, amount); - if (data) { - const newamount = data.inventory[item.name]!; - await sendMessage(`${target.displayName} now has ${newamount} ${item.prettyName + (newamount === 1 ? '' : item.plural)}`, msg.messageId); - } else { - await sendMessage(`Failed to give ${target.displayName} ${amount} ${item.prettyName + (amount === 1 ? '' : item.plural)}`, msg.messageId); - }; - await target.clearLock(); +export default new Command({ + name: 'admingive', + aliases: ['admingive'], + usertype: 'admin', + execution: async msg => { + const args = parseCommandArgs(msg.messageText); + 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; }; + const userRecord = await getUserRecord(target); + if (!args[1]) { await sendMessage('Please specify an item to give', msg.messageId); return; }; + const item = items.get(args[1].toLowerCase()); + if (!item) { await sendMessage(`Item ${args[1]} doesn't exist`, msg.messageId); return; }; + 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 lock is set', msg.messageId); return; }; + await target.setLock(); + const data = await changeItemCount(target, userRecord, item.name, amount); + if (data) { + const newamount = data.inventory[item.name]!; + await sendMessage(`${target.displayName} now has ${newamount} ${item.prettyName + (newamount === 1 ? '' : item.plural)}`, msg.messageId); + } else { + await sendMessage(`Failed to give ${target.displayName} ${amount} ${item.prettyName + (amount === 1 ? '' : item.plural)}`, msg.messageId); + }; + await target.clearLock(); + } }); diff --git a/src/commands/alltimestats.ts b/src/commands/alltimestats.ts index ab1bc6d..7b9e486 100644 --- a/src/commands/alltimestats.ts +++ b/src/commands/alltimestats.ts @@ -3,20 +3,24 @@ import { getTimeoutStats, getItemStats } from "lib/getStats"; import parseCommandArgs from "lib/parseCommandArgs"; import User from "user"; -export default new Command('alltimestats', ['alltime', 'alltimestats'], 'chatter', async (msg, user) => { - const args = parseCommandArgs(msg.messageText); - let target: User | null = user; - if (args[0]) { - target = await User.initUsername(args[0]); - if (!target) { await sendMessage(`User ${args[0]} doesn't exist!`, msg.messageId); return; }; - }; +export default new Command({ + name: 'alltimestats', + aliases: ['alltime', 'alltimestats'], + usertype: 'chatter', + execution: async (msg, user) => { + const args = parseCommandArgs(msg.messageText); + let target: User | null = user; + if (args[0]) { + target = await User.initUsername(args[0]); + if (!target) { await sendMessage(`User ${args[0]} doesn't exist!`, msg.messageId); return; }; + }; - const [timeout, item] = await Promise.all([getTimeoutStats(target, false), getItemStats(target, false)]); - if (!timeout || !item) { await sendMessage(`ERROR: Something went wrong!`, msg.messageId); return; }; + const [timeout, item] = await Promise.all([getTimeoutStats(target, false), getItemStats(target, false)]); + if (!timeout || !item) { await sendMessage(`ERROR: Something went wrong!`, msg.messageId); return; }; - const KD = timeout.shot.blaster / timeout.hit.blaster; + const KD = timeout.shot.blaster / timeout.hit.blaster; - await sendMessage(` + await sendMessage(` Alltime: stats of ${target.displayName}: Users blasted: ${timeout.shot.blaster}, Blasted by others: ${timeout.hit.blaster} (${isNaN(KD) ? 0 : KD.toFixed(2)} K/D). @@ -25,4 +29,5 @@ export default new Command('alltimestats', ['alltime', 'alltimestats'], 'chatter Silver bullets fired: ${timeout.shot.silverbullet}, Silver bullets taken: ${timeout.hit.silverbullet}. `, msg.messageId); + } }); diff --git a/src/commands/backshot.ts b/src/commands/backshot.ts index c475b69..e9f7041 100644 --- a/src/commands/backshot.ts +++ b/src/commands/backshot.ts @@ -2,9 +2,14 @@ import { Command, sendMessage } from "commands"; import User from "user"; import { redis } from "bun"; -export default new Command('backshot', ['backshot'], 'chatter', async (msg, user) => { - const targets = await redis.keys(`user:*:haschatted`); - const selection = targets[Math.floor(Math.random() * targets.length)]!; - const target = await User.initUserId(selection.slice(5, -11)); - await sendMessage(`${user.displayName} backshotted ${target?.displayName}`, msg.messageId); +export default new Command({ + name: 'backshot', + aliases: ['backshot'], + usertype: 'chatter', + execution: async (msg, user) => { + const targets = await redis.keys(`user:*:haschatted`); + const selection = targets[Math.floor(Math.random() * targets.length)]!; + const target = await User.initUserId(selection.slice(5, -11)); + await sendMessage(`${user.displayName} backshotted ${target?.displayName}`, msg.messageId); + } }); diff --git a/src/commands/banclanker.ts b/src/commands/banclanker.ts deleted file mode 100644 index 691bb7f..0000000 --- a/src/commands/banclanker.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { Command, sendMessage } from "commands"; -import parseCommandArgs from "lib/parseCommandArgs"; -import { timeout } from "lib/timeout"; -import User from "user"; -import { playAlert } from "web/alerts/serverFunctions"; - -export default new Command('banclanker', ['banclanker', 'banbot'], 'moderator', async msg => { - const args = parseCommandArgs(msg.messageText); - if (!args[0]) { await sendMessage(`Specify a clanker to ban`, msg.messageId); return; }; - const target = await User.initUsername(args[0]); - if (!target) { await sendMessage(`Clanker ${args[0]} doesn't exist`, msg.messageId); return; }; - await Promise.all([ - timeout(target, `get fucked`), - playAlert({ - name: 'userExecution', - user: msg.chatterDisplayName, - target: target.displayName - }) - ]); -}); diff --git a/src/commands/disablecheer.ts b/src/commands/disablecheer.ts index df3a784..dc46ff3 100644 --- a/src/commands/disablecheer.ts +++ b/src/commands/disablecheer.ts @@ -3,12 +3,18 @@ import { Command, sendMessage } from "commands"; import parseCommandArgs from "lib/parseCommandArgs"; import { namedcheers } from "cheers"; -export default new Command('disablecheer', ['disablecheer'], 'admin', async msg => { - const args = parseCommandArgs(msg.messageText); - if (!args[0]) { await sendMessage('Please specify a cheer to disable', msg.messageId); return; }; - const selection = namedcheers.get(args[0].toLowerCase()); - if (!selection) { await sendMessage(`There is no ${args[0]} cheer`, msg.messageId); return; }; - const result = await redis.sadd('disabledcheers', selection.name); - if (result === 0) { await sendMessage(`The ${selection.name} cheer is already disabled`, msg.messageId); return; }; - await sendMessage(`Successfully disabled the ${selection.name} cheer`, msg.messageId); -}, false); +export default new Command({ + name: 'disablecheer', + aliases: ['disablecheer'], + usertype: 'admin', + disableable: false, + execution: async msg => { + const args = parseCommandArgs(msg.messageText); + if (!args[0]) { await sendMessage('Please specify a cheer to disable', msg.messageId); return; }; + const selection = namedcheers.get(args[0].toLowerCase()); + if (!selection) { await sendMessage(`There is no ${args[0]} cheer`, msg.messageId); return; }; + const result = await redis.sadd('disabledcheers', selection.name); + if (result === 0) { await sendMessage(`The ${selection.name} cheer is already disabled`, msg.messageId); return; }; + await sendMessage(`Successfully disabled the ${selection.name} cheer`, msg.messageId); + } +}); diff --git a/src/commands/disablecommand.ts b/src/commands/disablecommand.ts index d7306af..4431b9d 100644 --- a/src/commands/disablecommand.ts +++ b/src/commands/disablecommand.ts @@ -2,13 +2,19 @@ import { redis } from "bun"; import commands, { Command, sendMessage } from "commands"; import parseCommandArgs from "lib/parseCommandArgs"; -export default new Command('disablecommand', ['disablecommand'], 'admin', async msg => { - const args = parseCommandArgs(msg.messageText); - if (!args[0]) { await sendMessage('Please specify a command to disable', msg.messageId); return; }; - const selection = commands.get(args[0].toLowerCase()); - if (!selection) { await sendMessage(`There is no ${args[0]} command`, msg.messageId); return; }; - if (!selection.disableable) { await sendMessage(`Cannot disable ${selection.name} as the command is not disableable`, msg.messageId); return; }; - const result = await redis.sadd('disabledcommands', selection.name); - if (result === 0) { await sendMessage(`The ${selection.name} command is already disabled`, msg.messageId); return; }; - await sendMessage(`Successfully disabled the ${selection.name} command`, msg.messageId); -}, false); +export default new Command({ + name: 'disablecommand', + aliases: ['disablecommand'], + usertype: 'admin', + disableable: false, + execution: async msg => { + const args = parseCommandArgs(msg.messageText); + if (!args[0]) { await sendMessage('Please specify a command to disable', msg.messageId); return; }; + const selection = commands.get(args[0].toLowerCase()); + if (!selection) { await sendMessage(`There is no ${args[0]} command`, msg.messageId); return; }; + if (!selection.disableable) { await sendMessage(`Cannot disable ${selection.name} as the command is not disableable`, msg.messageId); return; }; + const result = await redis.sadd('disabledcommands', selection.name); + if (result === 0) { await sendMessage(`The ${selection.name} command is already disabled`, msg.messageId); return; }; + await sendMessage(`Successfully disabled the ${selection.name} command`, msg.messageId); + } +}); diff --git a/src/commands/donateqbucks.ts b/src/commands/donateqbucks.ts index fac7782..340c4a2 100644 --- a/src/commands/donateqbucks.ts +++ b/src/commands/donateqbucks.ts @@ -6,43 +6,48 @@ import { changeBalance } from "lib/changeBalance"; import User from "user"; import logger from "lib/logger"; -export default new Command('donate', ['donate'], 'chatter', async (msg, user) => { - const args = parseCommandArgs(msg.messageText); - 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]); - if (isNaN(amount) || amount < 0) { await sendMessage(`${args[1]} is not a valid amount`); return; }; +export default new Command({ + name: 'donate', + aliases: ['donate'], + usertype: 'chatter', + execution: async (msg, user) => { + const args = parseCommandArgs(msg.messageText); + 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]); + if (isNaN(amount) || amount < 0) { await sendMessage(`${args[1]} is not a valid amount`); return; }; - const userRecord = await getUserRecord(user); - if (userRecord.balance < amount) { await sendMessage(`You can't give qweribucks you don't have!`, msg.messageId); return; }; + 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', msg.messageId); return; }; + if (await user.itemLock() || await target.itemLock()) { await sendMessage('Cannot give qweribucks', msg.messageId); return; }; - await Promise.all([ - user.setLock(), - target.setLock() - ]); + await Promise.all([ + user.setLock(), + target.setLock() + ]); - const data = await Promise.all([ - await changeBalance(target, targetRecord, amount), - await changeBalance(user, userRecord, -amount) - ]); + const data = await Promise.all([ + await changeBalance(target, targetRecord, amount), + await changeBalance(user, userRecord, -amount) + ]); - if (!data.includes(false)) { - const { balance: newamount } = data[0] as userRecord; - await sendMessage(`${user.displayName} gave ${amount} qweribuck${amount === 1 ? '' : 's'} to ${target.displayName}. They now have ${newamount} qweribuck${newamount === 1 ? '' : 's'}`, msg.messageId); - } else { - // TODO: Rewrite this section - await sendMessage(`Failed to give ${target.displayName} ${amount} qbuck${(amount === 1 ? '' : 's')}`, msg.messageId); - logger.err(`WARNING: Qweribucks donation failed: target success: ${data[0] !== false}, donator success: ${data[1] !== false}`); - }; + if (!data.includes(false)) { + const { balance: newamount } = data[0] as userRecord; + await sendMessage(`${user.displayName} gave ${amount} qweribuck${amount === 1 ? '' : 's'} to ${target.displayName}. They now have ${newamount} qweribuck${newamount === 1 ? '' : 's'}`, msg.messageId); + } else { + // TODO: Rewrite this section + await sendMessage(`Failed to give ${target.displayName} ${amount} qbuck${(amount === 1 ? '' : 's')}`, msg.messageId); + logger.err(`WARNING: Qweribucks donation failed: target success: ${data[0] !== false}, donator success: ${data[1] !== false}`); + }; - await Promise.all([ - user.clearLock(), - target.clearLock() - ]); + await Promise.all([ + user.clearLock(), + target.clearLock() + ]); + } }); diff --git a/src/commands/enablecheer.ts b/src/commands/enablecheer.ts index 593fc0f..be3d506 100644 --- a/src/commands/enablecheer.ts +++ b/src/commands/enablecheer.ts @@ -3,12 +3,18 @@ import { Command, sendMessage } from "commands"; import parseCommandArgs from "lib/parseCommandArgs"; import { namedcheers } from "cheers"; -export default new Command('enablecheer', ['enablecheer'], 'admin', async msg => { - const args = parseCommandArgs(msg.messageText); - if (!args[0]) { await sendMessage('Please specify a cheer to enable', msg.messageId); return; }; - const selection = namedcheers.get(args[0].toLowerCase()); - if (!selection) { await sendMessage(`There is no ${args[0]} cheer`, msg.messageId); return; }; - const result = await redis.srem('disabledcheers', selection.name); - if (result === 0) { await sendMessage(`The ${selection.name} cheer isn't disabled`, msg.messageId); return; }; - await sendMessage(`Successfully enabled the ${selection.name} cheer`, msg.messageId); -}, false); +export default new Command({ + name: 'enablecheer', + aliases: ['enablecheer'], + usertype: 'admin', + disableable: false, + execution: async msg => { + const args = parseCommandArgs(msg.messageText); + if (!args[0]) { await sendMessage('Please specify a cheer to enable', msg.messageId); return; }; + const selection = namedcheers.get(args[0].toLowerCase()); + if (!selection) { await sendMessage(`There is no ${args[0]} cheer`, msg.messageId); return; }; + const result = await redis.srem('disabledcheers', selection.name); + if (result === 0) { await sendMessage(`The ${selection.name} cheer isn't disabled`, msg.messageId); return; }; + await sendMessage(`Successfully enabled the ${selection.name} cheer`, msg.messageId); + } +}); diff --git a/src/commands/enablecommand.ts b/src/commands/enablecommand.ts index c85e810..bfdadae 100644 --- a/src/commands/enablecommand.ts +++ b/src/commands/enablecommand.ts @@ -2,12 +2,18 @@ import { redis } from "bun"; import commands, { Command, sendMessage } from "commands"; import parseCommandArgs from "lib/parseCommandArgs"; -export default new Command('enablecommand', ['enablecommand'], 'admin', async msg => { - const args = parseCommandArgs(msg.messageText); - if (!args[0]) { await sendMessage('Please specify a command to enable', msg.messageId); return; }; - const selection = commands.get(args[0].toLowerCase()); - if (!selection) { await sendMessage(`There is no ${args[0]} command`, msg.messageId); return; }; - const result = await redis.srem('disabledcommands', selection.name); - if (result === 0) { await sendMessage(`The ${selection.name} command isn't disabled`, msg.messageId); return; }; - await sendMessage(`Successfully enabled the ${selection.name} command`, msg.messageId); -}, false); +export default new Command({ + name: 'enablecommand', + aliases: ['enablecommand'], + usertype: 'admin', + disableable: false, + execution: async msg => { + const args = parseCommandArgs(msg.messageText); + if (!args[0]) { await sendMessage('Please specify a command to enable', msg.messageId); return; }; + const selection = commands.get(args[0].toLowerCase()); + if (!selection) { await sendMessage(`There is no ${args[0]} command`, msg.messageId); return; }; + const result = await redis.srem('disabledcommands', selection.name); + if (result === 0) { await sendMessage(`The ${selection.name} command isn't disabled`, msg.messageId); return; }; + await sendMessage(`Successfully enabled the ${selection.name} command`, msg.messageId); + } +}); diff --git a/src/commands/getadmins.ts b/src/commands/getadmins.ts index dcef4ec..b4cefd3 100644 --- a/src/commands/getadmins.ts +++ b/src/commands/getadmins.ts @@ -2,12 +2,18 @@ import { Command, sendMessage } from "commands"; import { getAdmins } from "lib/admins"; import User from "user"; -export default new Command('getadmins', ['getadmins'], 'chatter', async msg => { - const admins = await getAdmins() - const adminnames: string[] = []; - for (const id of admins) { - const admin = await User.initUserId(id); - adminnames.push(admin?.displayName!); - }; - await sendMessage(`Current admins: ${adminnames.join(', ')}`, msg.messageId); -}, false); +export default new Command({ + name: 'getadmins', + aliases: ['getadmins'], + usertype: 'chatter', + disableable: false, + execution: async msg => { + const admins = await getAdmins() + const adminnames: string[] = []; + for (const id of admins) { + const admin = await User.initUserId(id); + adminnames.push(admin?.displayName!); + }; + await sendMessage(`Current admins: ${adminnames.join(', ')}`, msg.messageId); + } +}); diff --git a/src/commands/getbalance.ts b/src/commands/getbalance.ts index 65e88ff..76b01da 100644 --- a/src/commands/getbalance.ts +++ b/src/commands/getbalance.ts @@ -3,10 +3,15 @@ import { getUserRecord } from "db/dbUser"; import parseCommandArgs from "lib/parseCommandArgs"; import User from "user"; -export default new Command('getbalance', ['getbalance', 'balance', 'qbucks', 'qweribucks', 'wallet', 'getwallet'], 'chatter', async (msg, user) => { - const args = parseCommandArgs(msg.messageText); - const target = args[0] ? await User.initUsername(args[0].toLowerCase()) : user; - if (!target) { await sendMessage(`Chatter ${args[0]} doesn't exist!`, msg.messageId); return; }; - const data = await getUserRecord(target); - await sendMessage(`${target.displayName} has ${data.balance} qbuck${data.balance === 1 ? '' : 's'}`, msg.messageId); +export default new Command({ + name: 'getbalance', + aliases: ['getbalance', 'balance', 'qbucks', 'qweribucks', 'wallet', 'getwallet'], + usertype: 'chatter', + execution: async (msg, user) => { + const args = parseCommandArgs(msg.messageText); + const target = args[0] ? await User.initUsername(args[0].toLowerCase()) : user; + if (!target) { await sendMessage(`Chatter ${args[0]} doesn't exist!`, msg.messageId); return; }; + const data = await getUserRecord(target); + await sendMessage(`${target.displayName} has ${data.balance} qbuck${data.balance === 1 ? '' : 's'}`, msg.messageId); + } }); diff --git a/src/commands/getcheers.ts b/src/commands/getcheers.ts index 1dbe1f0..9795ef4 100644 --- a/src/commands/getcheers.ts +++ b/src/commands/getcheers.ts @@ -3,31 +3,37 @@ import { Command, sendMessage } from "commands"; import parseCommandArgs from "lib/parseCommandArgs"; import { namedcheers } from "cheers"; -export default new Command('getcheers', ['getcheers', 'getcheer'], 'chatter', async msg => { - const args = parseCommandArgs(msg.messageText); - if (!args[0]) { await sendMessage(`A full list of cheers can be found here: https://github.com/qwerinope/qweribot#cheers`, msg.messageId); return; }; - const disabledcheers = await redis.smembers('disabledcheers'); - const cheerstrings: string[] = []; +export default new Command({ + name: 'getcheers', + aliases: ['getcheers', 'getcheer'], + usertype: 'chatter', + disableable: false, + execution: async msg => { + const args = parseCommandArgs(msg.messageText); + if (!args[0]) { await sendMessage(`A full list of cheers can be found here: https://github.com/qwerinope/qweribot#cheers`, msg.messageId); return; }; + const disabledcheers = await redis.smembers('disabledcheers'); + const cheerstrings: string[] = []; - if (args[0].toLowerCase() === "enabled") { - for (const [name, cheer] of Array.from(namedcheers.entries())) { - if (disabledcheers.includes(name)) continue; - cheerstrings.push(`${cheer.amount}: ${name}`); - }; + if (args[0].toLowerCase() === "enabled") { + for (const [name, cheer] of Array.from(namedcheers.entries())) { + if (disabledcheers.includes(name)) continue; + cheerstrings.push(`${cheer.amount}: ${name}`); + }; - const last = cheerstrings.pop(); - if (!last) { await sendMessage("No enabled cheers", msg.messageId); return; }; - await sendMessage(cheerstrings.length === 0 ? last : cheerstrings.join(', ') + " and " + last, msg.messageId); + const last = cheerstrings.pop(); + if (!last) { await sendMessage("No enabled cheers", msg.messageId); return; }; + await sendMessage(cheerstrings.length === 0 ? last : cheerstrings.join(', ') + " and " + last, msg.messageId); - } else if (args[0].toLowerCase() === "disabled") { - for (const [name, cheer] of Array.from(namedcheers.entries())) { - if (!disabledcheers.includes(name)) continue; - cheerstrings.push(`${cheer.amount}: ${name}`); - }; + } else if (args[0].toLowerCase() === "disabled") { + for (const [name, cheer] of Array.from(namedcheers.entries())) { + if (!disabledcheers.includes(name)) continue; + cheerstrings.push(`${cheer.amount}: ${name}`); + }; - const last = cheerstrings.pop(); - if (!last) { await sendMessage("No disabled cheers", msg.messageId); return; }; - await sendMessage(cheerstrings.length === 0 ? last : cheerstrings.join(', ') + " and " + last, msg.messageId); + const last = cheerstrings.pop(); + if (!last) { await sendMessage("No disabled cheers", msg.messageId); return; }; + await sendMessage(cheerstrings.length === 0 ? last : cheerstrings.join(', ') + " and " + last, msg.messageId); - } else await sendMessage('Please specify if you want the enabled or disabled cheers', msg.messageId); -}, false); + } else await sendMessage('Please specify if you want the enabled or disabled cheers', msg.messageId); + } +}); diff --git a/src/commands/getcommands.ts b/src/commands/getcommands.ts index b9fe994..109c300 100644 --- a/src/commands/getcommands.ts +++ b/src/commands/getcommands.ts @@ -2,22 +2,28 @@ import { redis } from "bun"; import { basecommands, Command, sendMessage } from "commands"; import parseCommandArgs from "lib/parseCommandArgs"; -export default new Command('getcommands', ['getcommands', 'getc'], 'chatter', async msg => { - const args = parseCommandArgs(msg.messageText); - if (!args[0]) { await sendMessage(`A full list of commands can be found here: https://github.com/qwerinope/qweribot#commands-1`, msg.messageId); return; }; - const disabledcommands = await redis.smembers('disabledcommands'); - if (args[0].toLowerCase() === 'enabled') { - const commandnames: string[] = []; - for (const [name, command] of Array.from(basecommands.entries())) { - if (command.usertype !== 'chatter') continue; // Admin only commands should be somewhat hidden - if (disabledcommands.includes(name)) continue; - commandnames.push(name); - }; - if (commandnames.length === 0) await sendMessage('No commands besides non-disableable commands are enabled', msg.messageId); - else await sendMessage(`Currently enabled commands: ${commandnames.join(', ')}`, msg.messageId); - } else if (args[0].toLowerCase() === 'disabled') { - if (disabledcommands.length === 0) await sendMessage('No commands are disabled', msg.messageId); - else await sendMessage(`Currently disabled commands: ${disabledcommands.join(', ')}`); +export default new Command({ + name: 'getcommands', + aliases: ['getcommands', 'getc'], + usertype: 'chatter', + disableable: false, + execution: async msg => { + const args = parseCommandArgs(msg.messageText); + if (!args[0]) { await sendMessage(`A full list of commands can be found here: https://github.com/qwerinope/qweribot#commands-1`, msg.messageId); return; }; + const disabledcommands = await redis.smembers('disabledcommands'); + if (args[0].toLowerCase() === 'enabled') { + const commandnames: string[] = []; + for (const [name, command] of Array.from(basecommands.entries())) { + if (command.usertype !== 'chatter') continue; // Admin only commands should be somewhat hidden + if (disabledcommands.includes(name)) continue; + commandnames.push(name); + }; + if (commandnames.length === 0) await sendMessage('No commands besides non-disableable commands are enabled', msg.messageId); + else await sendMessage(`Currently enabled commands: ${commandnames.join(', ')}`, msg.messageId); + } else if (args[0].toLowerCase() === 'disabled') { + if (disabledcommands.length === 0) await sendMessage('No commands are disabled', msg.messageId); + else await sendMessage(`Currently disabled commands: ${disabledcommands.join(', ')}`); + } + else await sendMessage('Please specify if you want the enabled or disabled commands', msg.messageId); } - else await sendMessage('Please specify if you want the enabled or disabled commands', msg.messageId); -}, false); +}); diff --git a/src/commands/getinventory.ts b/src/commands/getinventory.ts index 05b3c08..b9f6597 100644 --- a/src/commands/getinventory.ts +++ b/src/commands/getinventory.ts @@ -4,23 +4,28 @@ import parseCommandArgs from "lib/parseCommandArgs"; import User from "user"; import items from "items"; -export default new Command('inventory', ['inv', 'inventory', 'pocket'], 'chatter', async (msg, user) => { - const args = parseCommandArgs(msg.messageText); - let target: User = user; - if (args[0]) { - const obj = await User.initUsername(args[0].toLowerCase()); - if (!obj) { await sendMessage(`User ${args[0]} doesn't exist`, msg.messageId); return; }; - target = obj; - }; +export default new Command({ + name: 'inventory', + aliases: ['inv', 'inventory', 'pocket'], + usertype: 'chatter', + execution: async (msg, user) => { + const args = parseCommandArgs(msg.messageText); + let target: User = user; + if (args[0]) { + const obj = await User.initUsername(args[0].toLowerCase()); + if (!obj) { await sendMessage(`User ${args[0]} doesn't exist`, msg.messageId); return; }; + target = obj; + }; - const data = await getUserRecord(target); - const messagedata: string[] = []; - for (const [key, amount] of Object.entries(data.inventory)) { - if (amount === 0) continue; - const itemselection = items.get(key); - messagedata.push(`${itemselection?.prettyName}${amount === 1 ? '' : itemselection?.plural}: ${amount}`); - }; + const data = await getUserRecord(target); + const messagedata: string[] = []; + for (const [key, amount] of Object.entries(data.inventory)) { + if (amount === 0) continue; + const itemselection = items.get(key); + messagedata.push(`${itemselection?.prettyName}${amount === 1 ? '' : itemselection?.plural}: ${amount}`); + }; - if (messagedata.length === 0) { await sendMessage(`${target.displayName} has no items`, msg.messageId); return; }; - await sendMessage(`Inventory of ${target.displayName}: ${messagedata.join(', ')}`, msg.messageId); + if (messagedata.length === 0) { await sendMessage(`${target.displayName} has no items`, msg.messageId); return; }; + await sendMessage(`Inventory of ${target.displayName}: ${messagedata.join(', ')}`, msg.messageId); + } }); diff --git a/src/commands/getinvulns.ts b/src/commands/getinvulns.ts index d470537..8c8df98 100644 --- a/src/commands/getinvulns.ts +++ b/src/commands/getinvulns.ts @@ -2,12 +2,18 @@ import { Command, sendMessage } from "commands"; import { getInvulns } from "lib/invuln"; import User from "user"; -export default new Command('getinvulns', ['getinvulns'], 'chatter', async msg => { - const invulns = await getInvulns() - const invulnnames: string[] = []; - for (const id of invulns) { - const invuln = await User.initUserId(id); - invulnnames.push(invuln?.displayName!); - }; - await sendMessage(`Current invulnerable chatters: ${invulnnames.join(', ')}`, msg.messageId); -}, false); +export default new Command({ + name: 'getinvulns', + aliases: ['getinvulns'], + usertype: 'chatter', + disableable: false, + execution: async msg => { + const invulns = await getInvulns() + const invulnnames: string[] = []; + for (const id of invulns) { + const invuln = await User.initUserId(id); + invulnnames.push(invuln?.displayName!); + }; + await sendMessage(`Current invulnerable chatters: ${invulnnames.join(', ')}`, msg.messageId); + } +}); diff --git a/src/commands/getloot.ts b/src/commands/getloot.ts index 7559d09..ffeb178 100644 --- a/src/commands/getloot.ts +++ b/src/commands/getloot.ts @@ -7,71 +7,76 @@ import { timeout } from "lib/timeout"; const COOLDOWN = 10 * 60 * 1000; // 10 mins (ms) -export default new Command('getloot', ['getloot', 'dig', 'loot'], 'chatter', async (msg, user) => { - if (!await redis.exists('streamIsLive')) { await sendMessage(`No loot while stream is offline`, msg.messageId); return; }; - if (await user.itemLock()) { await sendMessage(`Cannot get loot (itemlock)`, msg.messageId); return; }; - const userData = await getUserRecord(user); - const lastlootbox = Date.parse(userData.lastlootbox); - const now = Date.now(); - if ((lastlootbox + COOLDOWN) > now) { - if (await user.greedy()) { - await Promise.all([ - sendMessage(`${user.displayName} STOP BEING GREEDY!!! UltraMad UltraMad UltraMad`), - timeout(user, `Wait ${buildTimeString(now - COOLDOWN, lastlootbox)}`, 60) - ]); - return; - } else { - await Promise.all([ - user.setGreed(), - sendMessage(`Wait ${buildTimeString(now - COOLDOWN, lastlootbox)} for another lootbox.`, msg.messageId) - ]); - return; +export default new Command({ + name: 'getloot', + aliases: ['getloot', 'dig', 'loot'], + usertype: 'chatter', + execution: async (msg, user) => { + if (!await redis.exists('streamIsLive')) { await sendMessage(`No loot while stream is offline`, msg.messageId); return; }; + if (await user.itemLock()) { await sendMessage(`Cannot get loot (itemlock)`, msg.messageId); return; }; + const userData = await getUserRecord(user); + const lastlootbox = Date.parse(userData.lastlootbox); + const now = Date.now(); + if ((lastlootbox + COOLDOWN) > now) { + if (await user.greedy()) { + await Promise.all([ + sendMessage(`${user.displayName} STOP BEING GREEDY!!! UltraMad UltraMad UltraMad`), + timeout(user, `Wait ${buildTimeString(now - COOLDOWN, lastlootbox)}`, 60) + ]); + return; + } else { + await Promise.all([ + user.setGreed(), + sendMessage(`Wait ${buildTimeString(now - COOLDOWN, lastlootbox)} for another lootbox.`, msg.messageId) + ]); + return; + }; }; - }; - await user.clearGreed(); - await user.setLock(); + await user.clearGreed(); + await user.setLock(); - userData.lastlootbox = new Date(now).toISOString(); + userData.lastlootbox = new Date(now).toISOString(); - const gainedqbucks = Math.floor(Math.random() * 100) + 50; // range from 50 to 150 - userData.balance += gainedqbucks; + const gainedqbucks = Math.floor(Math.random() * 100) + 50; // range from 50 to 150 + userData.balance += gainedqbucks; - const itemDiff = { - grenade: 0, - blaster: 0, - tnt: 0, - silverbullet: 0 - }; + const itemDiff = { + grenade: 0, + blaster: 0, + tnt: 0, + silverbullet: 0 + }; - for (let i = 0; i < 5; i++) { - if (Math.floor(Math.random() * 5) === 0) itemDiff.grenade += 1; - if (Math.floor(Math.random() * 5) === 0) itemDiff.blaster += 1; - if (Math.floor(Math.random() * 25) === 0) itemDiff.tnt += 1; - if (Math.floor(Math.random() * 250) === 0) itemDiff.silverbullet += 1; - }; + for (let i = 0; i < 5; i++) { + if (Math.floor(Math.random() * 5) === 0) itemDiff.grenade += 1; + if (Math.floor(Math.random() * 5) === 0) itemDiff.blaster += 1; + if (Math.floor(Math.random() * 25) === 0) itemDiff.tnt += 1; + if (Math.floor(Math.random() * 250) === 0) itemDiff.silverbullet += 1; + }; - for (const [item, amount] of Object.entries(itemDiff)) { - if (userData.inventory[item]) userData.inventory[item] += amount; - else userData.inventory[item] = amount; - }; + for (const [item, amount] of Object.entries(itemDiff)) { + if (userData.inventory[item]) userData.inventory[item] += amount; + else userData.inventory[item] = amount; + }; - const itemstrings: string[] = [`${gainedqbucks} qbucks`]; + const itemstrings: string[] = [`${gainedqbucks} qbucks`]; - for (const [item, amount] of Object.entries(itemDiff)) { - if (amount === 0) continue; - const selection = items.get(item); - if (!selection) continue; - itemstrings.push(`${amount} ${selection.prettyName + (amount === 1 ? '' : selection.plural)}`); - }; + for (const [item, amount] of Object.entries(itemDiff)) { + if (amount === 0) continue; + const selection = items.get(item); + if (!selection) continue; + itemstrings.push(`${amount} ${selection.prettyName + (amount === 1 ? '' : selection.plural)}`); + }; - const last = itemstrings.pop(); - const itemstring = itemstrings.length === 0 ? last : itemstrings.join(', ') + " and " + last; - const message = `You got ${itemstring}`; + const last = itemstrings.pop(); + const itemstring = itemstrings.length === 0 ? last : itemstrings.join(', ') + " and " + last; + const message = `You got ${itemstring}`; - await Promise.all([ - updateUserRecord(user, userData), - sendMessage(message, msg.messageId), - user.clearLock() - ]); + await Promise.all([ + updateUserRecord(user, userData), + sendMessage(message, msg.messageId), + user.clearLock() + ]); + } }); diff --git a/src/commands/gettimeout.ts b/src/commands/gettimeout.ts index 3778c5a..aadef93 100644 --- a/src/commands/gettimeout.ts +++ b/src/commands/gettimeout.ts @@ -4,13 +4,18 @@ import parseCommandArgs from "lib/parseCommandArgs"; import User from "user"; import { timeoutDuration } from "lib/timeout"; -export default new Command('gettimeout', ['gett', 'gettimeout'], 'chatter', async msg => { - const args = parseCommandArgs(msg.messageText); - if (!args[0]) { await sendMessage('Please specify a target', msg.messageId); return; }; - const target = await User.initUsername(args[0].toLowerCase()); - if (!target) { await sendMessage(`Chatter ${args[0]} doesn't exist`, msg.messageId); return; }; - const data = await timeoutDuration(target); - if (data === false) { await sendMessage(`Chatter ${target.displayName} isn't timed out`, msg.messageId); return; }; - if (data) { await sendMessage(`${target.displayName} is still timed out for ${buildTimeString(data * 1000, Date.now())}`, msg.messageId); return; }; - await sendMessage(`${target.displayName} is permanently banned`, msg.messageId); +export default new Command({ + name: 'gettimeout', + aliases: ['gett', 'gettimeout'], + usertype: 'chatter', + execution: async msg => { + const args = parseCommandArgs(msg.messageText); + if (!args[0]) { await sendMessage('Please specify a target', msg.messageId); return; }; + const target = await User.initUsername(args[0].toLowerCase()); + if (!target) { await sendMessage(`Chatter ${args[0]} doesn't exist`, msg.messageId); return; }; + const data = await timeoutDuration(target); + if (data === false) { await sendMessage(`Chatter ${target.displayName} isn't timed out`, msg.messageId); return; }; + if (data) { await sendMessage(`${target.displayName} is still timed out for ${buildTimeString(data * 1000, Date.now())}`, msg.messageId); return; }; + await sendMessage(`${target.displayName} is permanently banned`, msg.messageId); + } }); diff --git a/src/commands/giveitem.ts b/src/commands/giveitem.ts index 63316f9..5a6ece3 100644 --- a/src/commands/giveitem.ts +++ b/src/commands/giveitem.ts @@ -6,44 +6,49 @@ import parseCommandArgs from "lib/parseCommandArgs"; import User from "user"; import logger from "lib/logger"; -export default new Command('give', ['give'], 'chatter', async (msg, user) => { - const args = parseCommandArgs(msg.messageText); - 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()); - if (!item) { await sendMessage(`Item ${args[1]} doesn't exist`, msg.messageId); return; }; - 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) || amount < 0) { await sendMessage(`${args[2]} is not a valid amount`); return; }; +export default new Command({ + name: 'give', + aliases: ['give'], + usertype: 'chatter', + execution: async (msg, user) => { + const args = parseCommandArgs(msg.messageText); + 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()); + if (!item) { await sendMessage(`Item ${args[1]} doesn't exist`, msg.messageId); return; }; + 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) || amount < 0) { await sendMessage(`${args[2]} is not a valid amount`); return; }; - 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; }; + 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', msg.messageId); return; }; + if (await user.itemLock() || await target.itemLock()) { await sendMessage('Cannot give item', msg.messageId); return; }; - await Promise.all([ - user.setLock(), - target.setLock() - ]); + await Promise.all([ + user.setLock(), + target.setLock() + ]); - const data = await Promise.all([ - await changeItemCount(target, targetRecord, item.name, amount), - await changeItemCount(user, userRecord, item.name, -amount) - ]); + const data = await Promise.all([ + await changeItemCount(target, targetRecord, item.name, amount), + await changeItemCount(user, userRecord, item.name, -amount) + ]); - if (!data.includes(false)) { - const tempdata = data[0] as userRecord; - const newamount = tempdata.inventory[item.name]!; - await sendMessage(`${user.displayName} gave ${amount} ${item.prettyName + (amount === 1 ? '' : item.plural)} to ${target.displayName}. They now have ${newamount} ${item.prettyName + (newamount === 1 ? '' : item.plural)}`, msg.messageId); - } else { - // TODO: Rewrite this section - await sendMessage(`Failed to give ${target.displayName} ${amount} ${item.prettyName + (amount === 1 ? '' : item.plural)}`, msg.messageId); - logger.warn(`WARNING: Item donation failed: target success: ${data[0] !== false}, donator success: ${data[1] !== false}`); - }; - await user.clearLock(); - await target.clearLock(); + if (!data.includes(false)) { + const tempdata = data[0] as userRecord; + const newamount = tempdata.inventory[item.name]!; + await sendMessage(`${user.displayName} gave ${amount} ${item.prettyName + (amount === 1 ? '' : item.plural)} to ${target.displayName}. They now have ${newamount} ${item.prettyName + (newamount === 1 ? '' : item.plural)}`, msg.messageId); + } else { + // TODO: Rewrite this section + await sendMessage(`Failed to give ${target.displayName} ${amount} ${item.prettyName + (amount === 1 ? '' : item.plural)}`, msg.messageId); + logger.warn(`WARNING: Item donation failed: target success: ${data[0] !== false}, donator success: ${data[1] !== false}`); + }; + await user.clearLock(); + await target.clearLock(); + } }); diff --git a/src/commands/index.ts b/src/commands/index.ts index c2b7db1..b124bb5 100644 --- a/src/commands/index.ts +++ b/src/commands/index.ts @@ -3,24 +3,40 @@ 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 execute: (message: EventSubChannelChatMessageEvent, sender: User) => Promise; - constructor(name: string, aliases: string[], usertype: userType, execution: (message: EventSubChannelChatMessageEvent, sender: User) => Promise, disableable?: boolean) { - this.name = name.toLowerCase(); - this.aliases = aliases; - this.usertype = usertype; - this.execute = execution; - this.disableable = disableable ?? true; + 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 { 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) const basecommands = new Map; // This map has all command names mapped to commands (one-to-one) (no items) const files = await readdir(import.meta.dir); @@ -32,15 +48,21 @@ for (const file of files) { for (const alias of command.aliases) { commands.set(alias, command); // Since it's not a primitive type the map is filled with references to the command, not the actual object }; + for (const alias of command.specialaliases) { + specialAliasCommands.set(alias, command); + }; }; -import items from "items"; +import items, { specialAliasItems } from "items"; for (const [name, item] of Array.from(items)) { commands.set(name, item); // As Item is basically just Command but with more parameters, this should work fine }; +for (const [alias, item] of Array.from(specialAliasItems)) { + specialAliasCommands.set(alias, item); +}; export default commands; -export { basecommands }; +export { specialAliasCommands, basecommands }; import { chatterApi, chatterId, streamerId } from "main"; diff --git a/src/commands/iteminfo.ts b/src/commands/iteminfo.ts index af4b24c..44d2031 100644 --- a/src/commands/iteminfo.ts +++ b/src/commands/iteminfo.ts @@ -2,10 +2,15 @@ import { Command, sendMessage } from "commands"; import items from "items"; import parseCommandArgs from "lib/parseCommandArgs"; -export default new Command('iteminfo', ['iteminfo', 'itemhelp', 'info'], 'chatter', async msg => { - const messagequery = parseCommandArgs(msg.messageText).join(' '); - if (!messagequery) { await sendMessage('Please specify an item you would like to get info about', msg.messageId); return; }; - const selection = items.get(messagequery.toLowerCase()); - if (!selection) { await sendMessage(`'${messagequery}' is not an item`, msg.messageId); return; }; - await sendMessage(`Name: ${selection.prettyName}, Description: ${selection.description}, Aliases: ${selection.aliases.join(', ')}`, msg.messageId); +export default new Command({ + name: 'iteminfo', + aliases: ['iteminfo', 'itemhelp', 'info'], + usertype: 'chatter', + execution: async msg => { + const messagequery = parseCommandArgs(msg.messageText).join(' '); + if (!messagequery) { await sendMessage('Please specify an item you would like to get info about', msg.messageId); return; }; + const selection = items.get(messagequery.toLowerCase()); + if (!selection) { await sendMessage(`'${messagequery}' is not an item`, msg.messageId); return; }; + await sendMessage(`Name: ${selection.prettyName}, Description: ${selection.description}, Aliases: ${selection.aliases.join(', ')}`, msg.messageId); + } }); diff --git a/src/commands/itemlock.ts b/src/commands/itemlock.ts index b8854f0..37da4d1 100644 --- a/src/commands/itemlock.ts +++ b/src/commands/itemlock.ts @@ -2,12 +2,18 @@ import { Command, sendMessage } from "commands"; 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); +export default new Command({ + name: 'itemlock', + aliases: ['itemlock'], + usertype: 'admin', + disableable: false, + execution: 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); + } +}); diff --git a/src/commands/monthlystats.ts b/src/commands/monthlystats.ts index e45aeb7..ecc5fa5 100644 --- a/src/commands/monthlystats.ts +++ b/src/commands/monthlystats.ts @@ -3,20 +3,24 @@ import { getTimeoutStats, getItemStats } from "lib/getStats"; import parseCommandArgs from "lib/parseCommandArgs"; import User from "user"; -export default new Command('monthlystats', ['stats', 'monthlystats'], 'chatter', async (msg, user) => { - const args = parseCommandArgs(msg.messageText); - let target: User | null = user; - if (args[0]) { - target = await User.initUsername(args[0]); - if (!target) { await sendMessage(`User ${args[0]} doesn't exist!`, msg.messageId); return; }; - }; +export default new Command({ + name: 'monthlystats', + aliases: ['stats', 'monthlystats'], + usertype: 'chatter', + execution: async (msg, user) => { + const args = parseCommandArgs(msg.messageText); + let target: User | null = user; + if (args[0]) { + target = await User.initUsername(args[0]); + if (!target) { await sendMessage(`User ${args[0]} doesn't exist!`, msg.messageId); return; }; + }; - const [timeout, item] = await Promise.all([getTimeoutStats(target, true), getItemStats(target, true)]); - if (!timeout || !item) { await sendMessage(`ERROR: Something went wrong!`, msg.messageId); return; }; + const [timeout, item] = await Promise.all([getTimeoutStats(target, true), getItemStats(target, true)]); + if (!timeout || !item) { await sendMessage(`ERROR: Something went wrong!`, msg.messageId); return; }; - const KD = timeout.shot.blaster / timeout.hit.blaster; + const KD = timeout.shot.blaster / timeout.hit.blaster; - await sendMessage(` + await sendMessage(` This month: stats of ${target.displayName}: Users blasted: ${timeout.shot.blaster}, Blasted by others: ${timeout.hit.blaster} (${isNaN(KD) ? 0 : KD.toFixed(2)} K/D). @@ -25,4 +29,5 @@ export default new Command('monthlystats', ['stats', 'monthlystats'], 'chatter', Silver bullets fired: ${timeout.shot.silverbullet}, Silver bullets taken: ${timeout.hit.silverbullet}. `, msg.messageId); + } }); diff --git a/src/commands/removeadmin.ts b/src/commands/removeadmin.ts index 860cd32..abe52ff 100644 --- a/src/commands/removeadmin.ts +++ b/src/commands/removeadmin.ts @@ -4,13 +4,19 @@ import { removeAdmin } from "lib/admins"; import parseCommandArgs from "lib/parseCommandArgs"; import User from "user"; -export default new Command('removeadmin', ['removeadmin'], 'streamer', async msg => { - const args = parseCommandArgs(msg.messageText); - if (!args[0]) { await sendMessage('Please specify a target', 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 (streamerUsers.includes(target.id)) { await sendMessage(`Can't remove admin ${target.displayName} as they are managed by the bot program`, msg.messageId); return; }; - const data = await removeAdmin(target.id); - if (data === 1) await sendMessage(`${target.displayName} is no longer an admin`, msg.messageId); - else await sendMessage(`${target.displayName} isn't an admin`, msg.messageId); -}, false); +export default new Command({ + name: 'removeadmin', + aliases: ['removeadmin'], + usertype: 'streamer', + disableable: false, + execution: async msg => { + const args = parseCommandArgs(msg.messageText); + if (!args[0]) { await sendMessage('Please specify a target', 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 (streamerUsers.includes(target.id)) { await sendMessage(`Can't remove admin ${target.displayName} as they are managed by the bot program`, msg.messageId); return; }; + const data = await removeAdmin(target.id); + if (data === 1) await sendMessage(`${target.displayName} is no longer an admin`, msg.messageId); + else await sendMessage(`${target.displayName} isn't an admin`, msg.messageId); + } +}); diff --git a/src/commands/removeinvuln.ts b/src/commands/removeinvuln.ts index 744dbc3..1157fe3 100644 --- a/src/commands/removeinvuln.ts +++ b/src/commands/removeinvuln.ts @@ -4,13 +4,19 @@ import { removeInvuln } from "lib/invuln"; import parseCommandArgs from "lib/parseCommandArgs"; import User from "user"; -export default new Command('removeinvuln', ['removeinvuln'], 'admin', async msg => { - const args = parseCommandArgs(msg.messageText); - if (!args[0]) { await sendMessage('Please specify a target', 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 (streamerUsers.includes(target.id)) { await sendMessage(`Can't remove invulnerability from ${target.displayName} as they are managed by the bot program`, msg.messageId); return; }; - const data = await removeInvuln(target.id); - if (data === 1) await sendMessage(`${target.displayName} is no longer invulnerable`, msg.messageId); - else await sendMessage(`${target.displayName} isn't invulnerable`, msg.messageId); -}, false); +export default new Command({ + name: 'removeinvuln', + aliases: ['removeinvuln'], + usertype: 'admin', + disableable: false, + execution: async msg => { + const args = parseCommandArgs(msg.messageText); + if (!args[0]) { await sendMessage('Please specify a target', 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 (streamerUsers.includes(target.id)) { await sendMessage(`Can't remove invulnerability from ${target.displayName} as they are managed by the bot program`, msg.messageId); return; }; + const data = await removeInvuln(target.id); + if (data === 1) await sendMessage(`${target.displayName} is no longer invulnerable`, msg.messageId); + else await sendMessage(`${target.displayName} isn't invulnerable`, msg.messageId); + } +}); diff --git a/src/commands/roulette.ts b/src/commands/roulette.ts index a4632e0..f1acff4 100644 --- a/src/commands/roulette.ts +++ b/src/commands/roulette.ts @@ -4,17 +4,22 @@ import { timeout } from "lib/timeout"; const barrelCount = 6; -export default new Command('roulette', ['roulette'], 'chatter', async (msg, user) => { - if (!await redis.exists('rouletteCount')) await redis.set('rouletteCount', "0"); - const currentChamber = Number(await redis.get('rouletteCount')); - const shot = Math.random() < 1 / (barrelCount - currentChamber); - if (!shot) await Promise.all([ - redis.incr('rouletteCount'), - sendMessage("SWEAT Click SWEAT", msg.messageId) - ]); - else await Promise.all([ - redis.set('rouletteCount', "0"), - sendMessage("wybuh BANG!! wybuh"), - timeout(user, "You lost at russian roulette!", 5 * 60) - ]); +export default new Command({ + name: 'roulette', + aliases: ['roulette'], + usertype: 'chatter', + execution: async (msg, user) => { + if (!await redis.exists('rouletteCount')) await redis.set('rouletteCount', "0"); + const currentChamber = Number(await redis.get('rouletteCount')); + const shot = Math.random() < 1 / (barrelCount - currentChamber); + if (!shot) await Promise.all([ + redis.incr('rouletteCount'), + sendMessage("SWEAT Click SWEAT", msg.messageId) + ]); + else await Promise.all([ + redis.set('rouletteCount', "0"), + sendMessage("wybuh BANG!! wybuh"), + timeout(user, "You lost at russian roulette!", 5 * 60) + ]); + } }); diff --git a/src/commands/seiso.ts b/src/commands/seiso.ts index 56c0ea4..e9b3b30 100644 --- a/src/commands/seiso.ts +++ b/src/commands/seiso.ts @@ -1,15 +1,20 @@ import { Command, sendMessage } from "commands"; import { timeout } from "lib/timeout"; -export default new Command('seiso', ['seiso'], 'chatter', 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 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); - else await Promise.all([ - sendMessage(`${rand}% seiso RIPBOZO`), - timeout(user, 'TOO YABAI!', 60) - ]); +export default new Command({ + name: 'seiso', + aliases: ['seiso'], + usertype: 'chatter', + 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 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); + else await Promise.all([ + sendMessage(`${rand}% seiso RIPBOZO`), + timeout(user, 'TOO YABAI!', 60) + ]); + } }); diff --git a/src/commands/stacking.ts b/src/commands/stacking.ts index 2561ea7..2cff83a 100644 --- a/src/commands/stacking.ts +++ b/src/commands/stacking.ts @@ -3,20 +3,26 @@ import { Command, sendMessage } from "commands"; import { isAdmin } from "lib/admins"; import parseCommandArgs from "lib/parseCommandArgs"; -export default new Command('stacking', ['stacking'], 'chatter', async msg => { - const args = parseCommandArgs(msg.messageText); - if (!args[0] || !await isAdmin(msg.chatterId)) { await sendMessage(`Timeout stacking is currently ${await redis.exists('timeoutStacking') ? "on" : "off"}`, msg.messageId); return; }; - // Only admins can reach this part of code - switch (args[0]) { - case 'enable': - case 'on': - await redis.set('timeoutStacking', '1'); - await sendMessage('Timeout stacking is now on') - break; - case 'disable': - case 'off': - await redis.del('timeoutStacking'); - await sendMessage('Timeout stacking is now off') - break; - }; -}, false); +export default new Command({ + name: 'stacking', + aliases: ['stacking'], + usertype: 'chatter', + disableable: false, + execution: async msg => { + const args = parseCommandArgs(msg.messageText); + if (!args[0] || !await isAdmin(msg.chatterId)) { await sendMessage(`Timeout stacking is currently ${await redis.exists('timeoutStacking') ? "on" : "off"}`, msg.messageId); return; }; + // Only admins can reach this part of code + switch (args[0]) { + case 'enable': + case 'on': + await redis.set('timeoutStacking', '1'); + await sendMessage('Timeout stacking is now on') + break; + case 'disable': + case 'off': + await redis.del('timeoutStacking'); + await sendMessage('Timeout stacking is now off') + break; + }; + } +}); diff --git a/src/commands/testcheer.ts b/src/commands/testcheer.ts index 4ffb104..2296d76 100644 --- a/src/commands/testcheer.ts +++ b/src/commands/testcheer.ts @@ -2,10 +2,16 @@ import { Command, sendMessage } from "commands"; import { handleCheer } from "events/message"; import parseCommandArgs from "lib/parseCommandArgs"; -export default new Command('testcheer', ['testcheer'], 'streamer', async (msg, user) => { - const args = parseCommandArgs(msg.messageText); - if (!args[0]) { await sendMessage('Please specify the amount of fake bits you want to send', msg.messageId); return; }; - if (isNaN(Number(args[0]))) { await sendMessage(`${args[0]} is not a valid amout of bits`); return; }; - const bits = Number(args.shift()); // we shift it so the amount of bits isn't part of the handleCheer message, we already know that args[0] can be parsed as a number so this is fine. - await handleCheer(msg, bits, user); -}, false); +export default new Command({ + name: 'testcheer', + aliases: ['testcheer'], + usertype: 'streamer', + disableable: false, + execution: async (msg, user) => { + const args = parseCommandArgs(msg.messageText); + if (!args[0]) { await sendMessage('Please specify the amount of fake bits you want to send', msg.messageId); return; }; + if (isNaN(Number(args[0]))) { await sendMessage(`${args[0]} is not a valid amout of bits`); return; }; + const bits = Number(args.shift()); // we shift it so the amount of bits isn't part of the handleCheer message, we already know that args[0] can be parsed as a number so this is fine. + await handleCheer(msg, bits, user); + } +}); diff --git a/src/commands/timeout.ts b/src/commands/timeout.ts index 5130386..399eb8e 100644 --- a/src/commands/timeout.ts +++ b/src/commands/timeout.ts @@ -6,36 +6,41 @@ import { timeout } from "lib/timeout"; import { changeBalance } from "lib/changeBalance"; import { createTimeoutRecord } from "db/dbTimeouts"; -export default new Command('timeout', ['timeout'], 'chatter', async (msg, user) => { - const userObj = await getUserRecord(user); - if (userObj.balance < 100) { await sendMessage(`You don't have enough qweribucks (need 100, have ${userObj.balance})`, msg.messageId); return; }; - const messagequery = parseCommandArgs(msg.messageText); - 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; }; - await getUserRecord(target); // make sure the user record exist in the database +export default new Command({ + name: 'timeout', + aliases: ['timeout'], + usertype: 'chatter', + execution: async (msg, user) => { + const userObj = await getUserRecord(user); + if (userObj.balance < 100) { await sendMessage(`You don't have enough qweribucks (need 100, have ${userObj.balance})`, msg.messageId); return; }; + const messagequery = parseCommandArgs(msg.messageText); + 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; }; + await getUserRecord(target); // make sure the user record exist in the database - const result = await timeout(target, `You got BLASTED by ${user.displayName}`, 60); - if (result.status) { - await Promise.all([ - sendMessage(`GOTTEM ${target.displayName} got BLASTED by ${user.displayName} GOTTEM`), - changeBalance(user, userObj, -100), - createTimeoutRecord(user, target, 'blaster') - ]); - } else { - switch (result.reason) { - case "banned": - await sendMessage(`${target.displayName} is already timed out/banned`, msg.messageId); - break; - case "illegal": - await Promise.all([ - sendMessage(`${user.displayName} Nou Nou Nou`), - timeout(user, 'nah', 60) - ]); - break; - case "unknown": - await sendMessage('Something went wrong...', msg.messageId); - break; + const result = await timeout(target, `You got BLASTED by ${user.displayName}`, 60); + if (result.status) { + await Promise.all([ + sendMessage(`GOTTEM ${target.displayName} got BLASTED by ${user.displayName} GOTTEM`), + changeBalance(user, userObj, -100), + createTimeoutRecord(user, target, 'blaster') + ]); + } else { + switch (result.reason) { + case "banned": + await sendMessage(`${target.displayName} is already timed out/banned`, msg.messageId); + break; + case "illegal": + await Promise.all([ + sendMessage(`${user.displayName} Nou Nou Nou`), + timeout(user, 'nah', 60) + ]); + break; + case "unknown": + await sendMessage('Something went wrong...', msg.messageId); + break; + }; }; - }; + } }); diff --git a/src/commands/useitem.ts b/src/commands/useitem.ts index 655bd4c..fedc0fd 100644 --- a/src/commands/useitem.ts +++ b/src/commands/useitem.ts @@ -2,11 +2,17 @@ import { redis } from "bun"; import { Command, sendMessage } from "commands"; import items from "items"; -export default new Command('use', ['use'], 'chatter', async (msg, user) => { - const messagequery = msg.messageText.trim().split(' ').slice(1); - if (!messagequery[0]) { await sendMessage('Please specify an item you would like to use', msg.messageId); return; }; - const selection = items.get(messagequery[0].toLowerCase()); - if (!selection) { 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; }; - await selection.execute(msg, user); -}, false); +export default new Command({ + name: 'use', + aliases: ['use'], + usertype: 'chatter', + disableable: false, + execution: async (msg, user) => { + const messagequery = msg.messageText.trim().split(' ').slice(1); + if (!messagequery[0]) { await sendMessage('Please specify an item you would like to use', msg.messageId); return; }; + const selection = items.get(messagequery[0].toLowerCase()); + if (!selection) { 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; }; + await selection.execute(msg, user); + } +}); diff --git a/src/commands/vulnchatters.ts b/src/commands/vulnchatters.ts index aedc520..0c34547 100644 --- a/src/commands/vulnchatters.ts +++ b/src/commands/vulnchatters.ts @@ -1,8 +1,13 @@ import { redis } from "bun"; import { Command, sendMessage } from "commands"; -export default new Command('vulnchatters', ['vulnchatters', 'vulnc'], 'chatter', async msg => { - const data = await redis.keys('user:*:vulnerable'); - const one = data.length === 1; - await sendMessage(`There ${one ? 'is' : 'are'} ${data.length} vulnerable chatter${one ? '' : 's'}`, msg.messageId); +export default new Command({ + name: 'vulnchatters', + aliases: ['vulnchatters', 'vulnc'], + usertype: 'chatter', + execution: async msg => { + const data = await redis.keys('user:*:vulnerable'); + const one = data.length === 1; + await sendMessage(`There ${one ? 'is' : 'are'} ${data.length} vulnerable chatter${one ? '' : 's'}`, msg.messageId); + } }); diff --git a/src/commands/yabai.ts b/src/commands/yabai.ts index a1d8759..ffa638e 100644 --- a/src/commands/yabai.ts +++ b/src/commands/yabai.ts @@ -2,14 +2,19 @@ import { Command, sendMessage } from "commands"; import { timeout } from "lib/timeout"; // Remake of the !yabai command in ttv/kiara_tv -export default new Command('yabai', ['yabai', 'goon'], 'chatter', async (msg, user) => { - const rand = Math.floor(Math.random() * 101); - if (rand < 25) sendMessage(`${rand}% yabai! GIGACHAD`, msg.messageId); - else if (rand < 50) sendMessage(`${rand}% yabai POGGERS`, msg.messageId); - else if (rand === 50) sendMessage(`${rand}% yabai ok`, msg.messageId); - else if (rand < 90) sendMessage(`${rand}% yabai AINTNOWAY`, msg.messageId); - else await Promise.all([ - sendMessage(`${msg.chatterDisplayName} is ${rand}% yabai CAUGHT`), - timeout(user, "TOO YABAI!", 60) - ]); +export default new Command({ + name: 'yabai', + aliases: ['yabai', 'goon'], + usertype: 'chatter', + execution: async (msg, user) => { + const rand = Math.floor(Math.random() * 101); + if (rand < 25) sendMessage(`${rand}% yabai! GIGACHAD`, msg.messageId); + else if (rand < 50) sendMessage(`${rand}% yabai POGGERS`, msg.messageId); + else if (rand === 50) sendMessage(`${rand}% yabai ok`, msg.messageId); + else if (rand < 90) sendMessage(`${rand}% yabai AINTNOWAY`, msg.messageId); + else await Promise.all([ + sendMessage(`${msg.chatterDisplayName} is ${rand}% yabai CAUGHT`), + timeout(user, "TOO YABAI!", 60) + ]); + } }); diff --git a/src/events/message.ts b/src/events/message.ts index 82f8fdf..db00486 100644 --- a/src/events/message.ts +++ b/src/events/message.ts @@ -1,7 +1,7 @@ import { EventSubChannelChatMessageEvent } from "@twurple/eventsub-base" import { streamerId, eventSub, commandPrefix, streamerUsers } from "main"; import User from "user"; -import commands, { sendMessage } from "commands"; +import commands, { Command, sendMessage, specialAliasCommands } from "commands"; import { redis } from "bun"; import { isAdmin } from "lib/admins"; import cheers from "cheers"; @@ -11,6 +11,7 @@ import { isInvuln, setTemporaryInvuln } from "lib/invuln"; import { getUserRecord } from "db/dbUser"; import { createCheerRecord } from "db/dbCheers"; import handleAnivMessage from "lib/handleAnivMessage"; +import { spec } from "node:test/reporters"; eventSub.onChannelChatMessage(streamerId, streamerId, parseChatMessage); @@ -46,31 +47,48 @@ async function handleChatMessage(msg: EventSubChannelChatMessageEvent, user: Use handleAnivMessage(msg, user); // Parse commands: - if (msg.messageText.startsWith(commandPrefix)) { - const commandSelection = msg.messageText.slice(commandPrefix.length).split(' ')[0]!; - const selected = commands.get(commandSelection.toLowerCase()); - if (!selected) return; - if (await redis.sismember('disabledcommands', selected.name)) return; + const selected = selectCommand(msg.messageText); + if (!selected) return; + const { cmd: selection, activation } = selected; + if (await redis.sismember('disabledcommands', selection.name)) return; - switch (selected.usertype) { - case "admin": - if (!await isAdmin(user.id)) return; - break; - case "streamer": - if (!streamerUsers.includes(msg.chatterId)) return; - break; - case "moderator": - if (!await redis.exists(`user:${user.id}:mod`)) return; - break; - }; - - try { await selected.execute(msg, user); } - catch (err) { - logger.err(err as string); - await sendMessage('ERROR: Something went wrong', msg.messageId); - await user.clearLock(); - }; + switch (selection.usertype) { + case "admin": + if (!await isAdmin(user.id)) return; + break; + case "streamer": + if (!streamerUsers.includes(msg.chatterId)) return; + break; + case "moderator": + if (!await redis.exists(`user:${user.id}:mod`)) return; + break; }; + + try { + await selection.execute(msg, user, { + activation + }); + } + catch (err) { + logger.err(err as string); + await sendMessage('ERROR: Something went wrong', msg.messageId); + await user.clearLock(); + }; +}; + +type selectedCommand = { + cmd: Command; + activation: string; +}; + +function selectCommand(message: string): selectedCommand | false { + const specialcmdselector = message.trim().toLowerCase().split(' ')[0]!; + const specialcmd = specialAliasCommands.get(specialcmdselector); + if (specialcmd) return { cmd: specialcmd, activation: specialcmdselector }; + const commandSelector = message.slice(commandPrefix.length).trim().toLowerCase().split(' ')[0]!; + const normalcmd = commands.get(commandSelector); + if (normalcmd) return { cmd: normalcmd, activation: commandPrefix + commandSelector }; + return false; }; export async function handleCheer(msg: EventSubChannelChatMessageEvent, bits: number, user: User) { diff --git a/src/items/blaster.ts b/src/items/blaster.ts index 2f30393..9cba835 100644 --- a/src/items/blaster.ts +++ b/src/items/blaster.ts @@ -10,10 +10,13 @@ import { playAlert } from "web/alerts/serverFunctions"; const ITEMNAME = 'blaster'; -export default new Item(ITEMNAME, 'Blaster', 's', - 'Times a specific person out for 60 seconds', - ['blaster', 'blast'], - async (msg, user) => { +export default new Item({ + name: ITEMNAME, + prettyName: 'Blaster', + plural: 's', + description: 'Times a specific person out for 60 seconds', + aliases: ['blaster', 'blast'], + execution: async (msg, user) => { const userObj = await getUserRecord(user); if (userObj.inventory[ITEMNAME]! < 1) { await sendMessage(`You don't have any blasters!`, msg.messageId); return; }; const messagequery = parseCommandArgs(msg.messageText); @@ -54,4 +57,4 @@ export default new Item(ITEMNAME, 'Blaster', 's', }; await user.clearLock(); } -); +}); diff --git a/src/items/grenade.ts b/src/items/grenade.ts index 0be5c89..4cd8830 100644 --- a/src/items/grenade.ts +++ b/src/items/grenade.ts @@ -10,10 +10,13 @@ import { playAlert } from "web/alerts/serverFunctions"; const ITEMNAME = 'grenade'; -export default new Item(ITEMNAME, 'Grenade', 's', - 'Give a random chatter a 60s timeout', - ['grenade'], - async (msg, user) => { +export default new Item({ + name: ITEMNAME, + prettyName: 'Grenade', + plural: 's', + description: 'Give a random chatter a 60s timeout', + aliases: ['grenade'], + execution: async (msg, user) => { const userObj = await getUserRecord(user); if (userObj.inventory[ITEMNAME]! < 1) { await sendMessage(`You don't have any grenades!`, msg.messageId); return; }; const targets = await redis.keys(`user:*:vulnerable`); @@ -40,4 +43,4 @@ export default new Item(ITEMNAME, 'Grenade', 's', ]); await user.clearLock(); } -); +}); diff --git a/src/items/index.ts b/src/items/index.ts index 322fac2..6805ac2 100644 --- a/src/items/index.ts +++ b/src/items/index.ts @@ -1,6 +1,16 @@ import { EventSubChannelChatMessageEvent } from "@twurple/eventsub-base"; import User from "user"; -import { type userType } from "commands"; +import { type userType, type specialExecuteArgs } from "commands"; + +type itemOptions = { + name: string; + aliases: string[]; + prettyName: string; + plural: string; + description: string; + execution: (message: EventSubChannelChatMessageEvent, sender: User, args?: specialExecuteArgs) => Promise; + specialaliases?: string[]; +}; export class Item { public readonly name: string; @@ -8,25 +18,22 @@ export class Item { public readonly plural: string; public readonly description: string; public readonly aliases: string[]; + public readonly specialaliases: string[]; public readonly usertype: userType; - public readonly execute: (message: EventSubChannelChatMessageEvent, sender: User) => Promise; + public readonly execute: (message: EventSubChannelChatMessageEvent, sender: User, args?: specialExecuteArgs) => Promise; public readonly disableable: boolean; - /** Creates an item object - * @param name - internal name of item - * @param prettyName - name of item for presenting to chat - * @param plural - plural appendage; example: lootbox(es) - * @param description - description of what item does - * @param aliases - alternative ways to activate item - * @param execution - code that gets executed when item gets used */ - constructor(name: string, prettyName: string, plural: string, description: string, aliases: string[], execution: (message: EventSubChannelChatMessageEvent, sender: User) => Promise) { - this.name = name; - this.prettyName = prettyName; - this.plural = plural; - this.description = description; - this.aliases = aliases; + + /** Creates an item object */ + constructor(options: itemOptions) { + this.name = options.name.toLowerCase(); + this.prettyName = options.prettyName; + this.plural = options.plural; + this.description = options.description; + this.aliases = options.aliases; this.usertype = 'chatter'; // Items are usable by everyone - this.execute = execution; + this.execute = options.execution; this.disableable = true; + this.specialaliases = options.specialaliases ?? []; }; }; @@ -34,6 +41,7 @@ import { readdir } from 'node:fs/promises'; import type { userRecord } from "db/connection"; import { updateUserRecord } from "db/dbUser"; const items = new Map; +const specialAliasItems = new Map; const emptyInventory: inventory = {}; const itemarray: string[] = []; @@ -47,10 +55,13 @@ for (const file of files) { for (const alias of item.aliases) { items.set(alias, item); // Since it's not a primitive type the map is filled with references to the item, not the actual object }; + for (const alias of item.specialaliases) { + specialAliasItems.set(alias, item); + }; }; export default items; -export { emptyInventory, itemarray }; +export { emptyInventory, itemarray, specialAliasItems }; export type inventory = { [key: string]: number; }; diff --git a/src/items/silverbullet.ts b/src/items/silverbullet.ts index fe95317..d945795 100644 --- a/src/items/silverbullet.ts +++ b/src/items/silverbullet.ts @@ -10,10 +10,14 @@ import User from "user"; const ITEMNAME = 'silverbullet'; -export default new Item(ITEMNAME, 'Silver bullet', 's', - 'Times a specific person out for 24 hours', - ['execute', 'silverbullet'], - async (msg, user) => { +export default new Item({ + name: ITEMNAME, + prettyName: 'Silver bullet', + plural: 's', + description: 'Times a specific person out for 24 hours', + aliases: ['execute', 'silverbullet'], + specialaliases: ['blastin'], + execution: async (msg, user, specialargs) => { const userObj = await getUserRecord(user); if (userObj.inventory[ITEMNAME]! < 1) { await sendMessage(`You don't have any silver bullets!`, msg.messageId); return; }; const messagequery = parseCommandArgs(msg.messageText); @@ -54,4 +58,4 @@ export default new Item(ITEMNAME, 'Silver bullet', 's', }; await user.clearLock(); } -); +}); diff --git a/src/items/tnt.ts b/src/items/tnt.ts index 33df92c..017a5f8 100644 --- a/src/items/tnt.ts +++ b/src/items/tnt.ts @@ -10,10 +10,13 @@ import { playAlert } from "web/alerts/serverFunctions"; const ITEMNAME = 'tnt'; -export default new Item(ITEMNAME, 'TNT', 's', - 'Give 5-10 random chatters 60 second timeouts', - ['tnt'], - async (msg, user) => { +export default new Item({ + name: ITEMNAME, + prettyName: 'TNT', + plural: 's', + description: 'Give 5-10 random chatters 60 second timeouts', + aliases: ['tnt'], + execution: 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('user:*:vulnerable').then(a => a.map(b => b.slice(5, -11))); @@ -46,7 +49,7 @@ export default new Item(ITEMNAME, 'TNT', 's', await user.clearLock(); await sendMessage(`RIPBOZO ${user.displayName} exploded ${targets.length} chatter${targets.length === 1 ? '' : 's'} with their TNT RIPBOZO`); } -); +}); export function getTNTTargets(arr: T[]): T[] { if (arr.length <= 5) { diff --git a/src/lib/parseCommandArgs.ts b/src/lib/parseCommandArgs.ts index 4e18320..1c5a64a 100644 --- a/src/lib/parseCommandArgs.ts +++ b/src/lib/parseCommandArgs.ts @@ -1,9 +1,15 @@ import { commandPrefix } from "main"; /** Helper function to extract arguments from commands */ -export default function parseCommandArgs(input: string) { - const nice = input.toLowerCase().slice(commandPrefix.length).trim(); - const sliceLength = nice.startsWith('use') ? 2 : 1; +export default function parseCommandArgs(input: string, specialAlias?: string) { + let nice = ''; + let sliceLength = 0; + if (specialAlias) { + nice = input.toLowerCase().slice(specialAlias.length).trim(); + } else { + nice = input.toLowerCase().slice(commandPrefix.length).trim(); + sliceLength = nice.startsWith('use') ? 2 : 1; + } return nice.split(' ').slice(sliceLength); };