disabled items can no longer be used with !use, admingive is now disableable, removed command specific intents, simplified command permission system

This commit is contained in:
2025-06-29 15:26:03 +02:00
parent 773a694714
commit 898e0b7b70
23 changed files with 72 additions and 85 deletions

View File

@@ -2,10 +2,8 @@ import { Command, sendMessage } from ".";
import { addAdmin } from "../lib/admins";
import parseCommandArgs from "../lib/parseCommandArgs";
import { User } from "../user";
import { unbannableUsers } from "..";
export default new Command('addadmin', ['addadmin'], [], async msg => {
if (!unbannableUsers.includes(msg.chatterId)) return;
export default new Command('addadmin', ['addadmin'], 'unbannable', 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());

View File

@@ -1,12 +1,10 @@
import { Command, sendMessage } from ".";
import { getUserRecord } from "../db/dbUser";
import items, { changeItemCount } from "../items";
import { isAdmin } from "../lib/admins";
import parseCommandArgs from "../lib/parseCommandArgs";
import { User } from "../user";
export default new Command('admingive', ['admingive'], [], async msg => {
if (!await isAdmin(msg.chatterId)) return;
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());
@@ -28,4 +26,4 @@ export default new Command('admingive', ['admingive'], [], async msg => {
await sendMessage(`Failed to give ${target.displayName} ${amount} ${item.prettyName + (amount === 1 ? '' : item.plural)}`, msg.messageId);
};
await target.clearLock();
}, false);
});

View File

@@ -1,10 +1,8 @@
import { redis } from "bun";
import commands, { Command, sendMessage } from ".";
import { isAdmin } from "../lib/admins";
import parseCommandArgs from "../lib/parseCommandArgs";
export default new Command('disablecommand', ['disablecommand'], [], async msg => {
if (!await isAdmin(msg.chatterId)) return;
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());

View File

@@ -1,10 +1,8 @@
import { redis } from "bun";
import commands, { Command, sendMessage } from ".";
import { isAdmin } from "../lib/admins";
import parseCommandArgs from "../lib/parseCommandArgs";
export default new Command('enablecommand', ['enablecommand'], [], async msg => {
if (!await isAdmin(msg.chatterId)) return;
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());

View File

@@ -2,7 +2,7 @@ import { Command, sendMessage } from ".";
import { getAdmins } from "../lib/admins";
import { User } from "../user";
export default new Command('getadmins', ['getadmins'], [], async msg => {
export default new Command('getadmins', ['getadmins'], 'chatter', async msg => {
const admins = await getAdmins()
const adminnames: string[] = [];
for (const id of admins) {

View File

@@ -2,14 +2,14 @@ import { redis } from "bun";
import { basecommands, Command, sendMessage } from ".";
import parseCommandArgs from "../lib/parseCommandArgs";
export default new Command('getcommands', ['getcommands', 'getc'], [], async msg => {
export default new Command('getcommands', ['getcommands', 'getc'], 'chatter', async msg => {
const args = parseCommandArgs(msg.messageText);
if (!args[0]) { await sendMessage(`A list of commands can be found here: https://github.com/qwerinope/qweribot#commands`, msg.messageId); return; };
if (!args[0]) { await sendMessage(`A full list of commands can be found here: https://github.com/qwerinope/qweribot#commands`, 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.disableable) continue;
if (command.usertype !== 'chatter') continue; // Admin only commands should be somewhat hidden
if (disabledcommands.includes(name)) continue;
commandnames.push(name);
};

View File

@@ -5,7 +5,7 @@ import items, { changeItemCount } from "../items";
import parseCommandArgs from "../lib/parseCommandArgs";
import { User } from "../user";
export default new Command('give', ['give'], [], async (msg, user) => {
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());
@@ -34,6 +34,7 @@ export default new Command('give', ['give'], [], async (msg, user) => {
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);
console.error(`WARNING: Item donation failed: target success: ${data[0] !== false}, donator success: ${data[0] !== false}`);
};

View File

@@ -1,17 +1,19 @@
import { EventSubChannelChatMessageEvent } from "@twurple/eventsub-base";
import { User } from "../user";
export type userType = 'chatter' | 'admin' | 'unbannable';
/** The Command class represents a command */
export class Command {
public readonly name: string;
public readonly aliases: string[];
public readonly requiredIntents: string[];
public readonly usertype: userType;
public readonly disableable: boolean;
public readonly execute: (message: EventSubChannelChatMessageEvent, sender: User) => Promise<void>;
constructor(name: string, aliases: string[], requiredIntents: string[], execution: (message: EventSubChannelChatMessageEvent, sender: User) => Promise<void>, disableable?: boolean) {
constructor(name: string, aliases: string[], usertype: userType, execution: (message: EventSubChannelChatMessageEvent, sender: User) => Promise<void>, disableable?: boolean) {
this.name = name.toLowerCase();
this.aliases = aliases;
this.requiredIntents = requiredIntents;
this.usertype = usertype;
this.execute = execution;
this.disableable = disableable ?? true;
};
@@ -19,7 +21,6 @@ export class Command {
import { readdir } from 'node:fs/promises';
const commands = new Map<string, Command>;
const commandintents: string[] = [];
const basecommands = new Map<string, Command>;
const files = await readdir(import.meta.dir);
@@ -27,7 +28,6 @@ for (const file of files) {
if (!file.endsWith('.ts')) continue;
if (file === import.meta.file) continue;
const command: Command = await import(import.meta.dir + '/' + file.slice(0, -3)).then(a => a.default);
commandintents.push(...command.requiredIntents);
basecommands.set(command.name, command);
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
@@ -40,7 +40,7 @@ for (const [name, item] of Array.from(items)) {
};
export default commands;
export { commandintents, basecommands };
export { basecommands };
import { singleUserMode, chatterApi, chatterId, streamerId } from "..";

View File

@@ -4,7 +4,7 @@ import parseCommandArgs from "../lib/parseCommandArgs";
import { User } from "../user";
import items from "../items";
export default new Command('inventory', ['inv', 'inventory'], [], async (msg, user) => {
export default new Command('inventory', ['inv', 'inventory'], 'chatter', async (msg, user) => {
const args = parseCommandArgs(msg.messageText);
let target: User = user;
if (args[0]) {

View File

@@ -2,7 +2,7 @@ import { Command, sendMessage } from ".";
import items from "../items";
import parseCommandArgs from "../lib/parseCommandArgs";
export default new Command('iteminfo', ['iteminfo', 'itemhelp', 'info'], [], async msg => {
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());

View File

@@ -1,10 +1,6 @@
import { Command, sendMessage } from ".";
// This command is purely for testing
export default new Command('ping',
['ping'],
[],
async msg => {
await sendMessage('pong!', msg.messageId);
}
);
export default new Command('ping', ['ping'], 'chatter', async msg => {
await sendMessage('pong!', msg.messageId);
});

View File

@@ -4,8 +4,7 @@ import { removeAdmin } from "../lib/admins";
import parseCommandArgs from "../lib/parseCommandArgs";
import { User } from "../user";
export default new Command('removeadmin', ['removeadmin'], [], async msg => {
if (!unbannableUsers.includes(msg.chatterId)) return;
export default new Command('removeadmin', ['removeadmin'], 'unbannable', 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());

View File

@@ -1,15 +1,15 @@
import { Command, sendMessage } from ".";
import { timeout } from "../lib/timeout";
export default new Command('seiso', ['seiso'], ['moderator:manage:banned_users'], async (msg, user) => {
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 sendMessage(`${rand}% seiso RIPBOZO`);
timeout(user, 'TOO YABAI!', 60);
};
else await Promise.all([
sendMessage(`${rand}% seiso RIPBOZO`),
timeout(user, 'TOO YABAI!', 60)
]);
});

View File

@@ -1,10 +1,12 @@
import { redis } from "bun";
import { Command, sendMessage } from ".";
import items from "../items";
export default new Command('use', ['use'], [], async (msg, user) => {
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);
});

View File

@@ -1,12 +1,8 @@
import { redis } from "bun";
import { Command, sendMessage } from ".";
export default new Command('vulnchatters',
['vulnchatters', 'vulnc'],
[],
async msg => {
const data = await redis.keys('vulnchatters:*');
const one = data.length === 1;
await sendMessage(`There ${one ? 'is' : 'are'} ${data.length} vulnerable chatter${one ? '' : 's'}`, msg.messageId);
}
);
export default new Command('vulnchatters', ['vulnchatters', 'vulnc'], 'chatter', async msg => {
const data = await redis.keys('vulnchatters:*');
const one = data.length === 1;
await sendMessage(`There ${one ? 'is' : 'are'} ${data.length} vulnerable chatter${one ? '' : 's'}`, msg.messageId);
});

View File

@@ -2,18 +2,14 @@ import { Command, sendMessage } from ".";
import { timeout } from "../lib/timeout";
// Remake of the !yabai command in ttv/kiara_tv
export default new Command('yabai',
['yabai', 'goon'],
['moderator:manage:banned_users'],
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 {
sendMessage(`${msg.chatterDisplayName} is ${rand}% yabai CAUGHT`);
timeout(user, "TOO YABAI!", 60);
};
}
);
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)
]);
});