diff options
Diffstat (limited to 'src')
20 files changed, 292 insertions, 52 deletions
diff --git a/src/commands/admin/channelPermissions.ts b/src/commands/admin/channelPermissions.ts index 3b8c157..993e811 100644 --- a/src/commands/admin/channelPermissions.ts +++ b/src/commands/admin/channelPermissions.ts @@ -81,8 +81,8 @@ export default class ChannelPermissionsCommand extends BushCommand { const failure = failedChannels.map((e) => `<#${e.id}>`).join(' '); if (failure.length > 2000) { const paginate: MessageEmbed[] = []; - for (let i = 0; i < failure.length; i += 2000) { - paginate.push(new MessageEmbed().setDescription(failure.substring(i, Math.min(failure.length, i + 2000)))); + for (let i = 0; i < failure.length; i += 4000) { + paginate.push(new MessageEmbed().setDescription(failure.substring(i, Math.min(failure.length, i + 4000)))); } const normalMessage = `Finished changing perms! Failed channels:`; return await client.util.buttonPaginate(message, paginate, normalMessage); diff --git a/src/commands/config/customAutomodPhrases.ts b/src/commands/config/customAutomodPhrases.ts new file mode 100644 index 0000000..7735939 --- /dev/null +++ b/src/commands/config/customAutomodPhrases.ts @@ -0,0 +1,64 @@ +// import { BushCommand, BushMessage, BushSlashMessage } from '@lib'; + +// export default class CustomAutomodPhrasesCommand extends BushCommand { +// public constructor() { +// super('customAutomodPhrases', { +// aliases: ['customautomodphrases'], +// category: 'config', +// description: { +// content: 'Configure additional phrases to be used for automod.', +// usage: 'customautomodphrases <requiredArg> [optionalArg]', +// examples: ['template 1 2'] +// }, +// args: [ +// { +// id: 'required_argument', +// type: 'string', +// prompt: { +// start: 'What would you like to set your first argument to be?', +// retry: '{error} Pick a valid argument.', +// optional: false +// } +// }, +// { +// id: 'optional_argument', +// type: 'string', +// prompt: { +// start: 'What would you like to set your second argument to be?', +// retry: '{error} Pick a valid argument.', +// optional: true +// } +// } +// ], +// slash: false, //set this to true +// slashOptions: [ +// { +// name: 'required_argument', +// description: 'What would you like to set your first argument to be?', +// type: 'STRING', +// required: true +// }, +// { +// name: 'optional_argument', +// description: 'What would you like to set your second argument to be?', +// type: 'STRING', +// required: false +// } +// ], +// superUserOnly: true, +// ownerOnly: true, +// channel: 'guild', +// hidden: true, +// clientPermissions: ['SEND_MESSAGES'], +// userPermissions: ['SEND_MESSAGES'] +// }); +// } + +// public override async exec( +// message: BushMessage | BushSlashMessage, +// args: { required_argument: string; optional_argument: string } +// ): Promise<unknown> { +// return await message.util.reply(`${util.emojis.error} Do not use the template command.`); +// args; +// } +// } diff --git a/src/commands/config/levelRoles.ts b/src/commands/config/levelRoles.ts new file mode 100644 index 0000000..df63914 --- /dev/null +++ b/src/commands/config/levelRoles.ts @@ -0,0 +1,61 @@ +import { BushCommand, BushMessage, BushSlashMessage } from '@lib'; + +export default class LevelRolesCommand extends BushCommand { + public constructor() { + super('levelRole', { + aliases: ['levelrole', 'levelroles', 'lr'], + category: 'config', + description: { + content: 'Command description.', + usage: 'levelrole <role> <level>', + examples: ['levelrole 1 2'] + }, + args: [ + { + id: 'role', + type: 'role', + prompt: { + start: 'What would you like to set your first argument to be?', + retry: '{error} Pick a valid argument.', + optional: false + } + }, + { + id: 'level', + type: 'integer', + prompt: { + start: 'What would you like to set your second argument to be?', + retry: '{error} Pick a valid argument.', + optional: false + } + } + ], + slash: true, + slashOptions: [ + { + name: 'role', + description: 'What would you like to set your first argument to be?', + type: 'STRING', + required: true + }, + { + name: 'level', + description: 'What would you like to set your second argument to be?', + type: 'STRING', + required: true + } + ], + channel: 'guild', + clientPermissions: ['SEND_MESSAGES'], + userPermissions: ['SEND_MESSAGES', 'MANAGE_GUILD', 'MANAGE_ROLES'] + }); + } + + public override async exec( + message: BushMessage | BushSlashMessage, + args: { required_argument: string; optional_argument: string } + ): Promise<unknown> { + return await message.util.reply(`${util.emojis.error} Do not use the template command.`); + args; + } +} diff --git a/src/commands/leveling/setLevel.ts b/src/commands/leveling/setLevel.ts index 2cd9099..1869773 100644 --- a/src/commands/leveling/setLevel.ts +++ b/src/commands/leveling/setLevel.ts @@ -22,7 +22,7 @@ export default class SetLevelCommand extends BushCommand { }, { id: 'level', - type: 'number', + type: 'integer', prompt: { start: 'What level would you like to set the user to?', retry: '{error} Choose a valid level to set the user to.' diff --git a/src/commands/moderation/_lockdown.ts b/src/commands/moderation/_lockdown.ts index 68197df..5df9f18 100644 --- a/src/commands/moderation/_lockdown.ts +++ b/src/commands/moderation/_lockdown.ts @@ -34,7 +34,7 @@ export default class LockdownCommand extends BushCommand { } public override async exec(message: BushMessage | BushSlashMessage, { all }: { all: boolean }): Promise<unknown> { - return await message.util.reply('no'); + return await message.util.reply('Unfortunately my developer is too lazy to implement this command.'); if (!all) { if (!['GUILD_TEXT', 'GUILD_NEWS'].includes(message.channel!.type)) return message.util.reply(`${util.emojis.error} You can only lock down text and announcement channels.`); diff --git a/src/commands/moderation/hideCase.ts b/src/commands/moderation/hideCase.ts index 2529531..cf7b4de 100644 --- a/src/commands/moderation/hideCase.ts +++ b/src/commands/moderation/hideCase.ts @@ -20,7 +20,10 @@ export default class HideCaseCommand extends BushCommand { } } ], - userPermissions: ['MANAGE_MESSAGES'], + userPermissions: (message) => { + return message.member?.permissions.has('MANAGE_MESSAGES') ? null : ['MANAGE_MESSAGES']; + }, + clientPermissions: ['SEND_MESSAGES'], slash: true, slashOptions: [ { diff --git a/src/commands/moderation/mute.ts b/src/commands/moderation/mute.ts index de79b32..9e68d63 100644 --- a/src/commands/moderation/mute.ts +++ b/src/commands/moderation/mute.ts @@ -99,13 +99,13 @@ export default class MuteCommand extends BushCommand { const prefix = await message.guild!.getSetting('prefix'); switch (responseCode) { case 'missing permissions': - return `${util.emojis.error} Could not mute ${victimBoldTag} because I am missing the \`Manage Roles\` permission.`; + return `${util.emojis.error} Could not mute ${victimBoldTag} because I am missing the **Manage Roles** permission.`; case 'no mute role': - return `${util.emojis.error} Could not mute ${victimBoldTag}, you must set a mute role with \`${prefix}muterole\`.`; + return `${util.emojis.error} Could not mute ${victimBoldTag}, you must set a mute role with \`${prefix}config muteRole\`.`; case 'invalid mute role': - return `${util.emojis.error} Could not mute ${victimBoldTag} because the current mute role no longer exists. Please set a new mute role with \`${prefix}muterole\`.`; + return `${util.emojis.error} Could not mute ${victimBoldTag} because the current mute role no longer exists. Please set a new mute role with \`${prefix}config muteRole\`.`; case 'mute role not manageable': - return `${util.emojis.error} Could not mute ${victimBoldTag} because I cannot assign the current mute role, either change the role's position or set a new mute role with \`${prefix}muterole\`.`; + return `${util.emojis.error} Could not mute ${victimBoldTag} because I cannot assign the current mute role, either change the role's position or set a new mute role with \`${prefix}config muteRole\`.`; case 'error giving mute role': return `${util.emojis.error} Could not mute ${victimBoldTag}, there was an error assigning them the mute role.`; case 'error creating modlog entry': diff --git a/src/commands/moderation/role.ts b/src/commands/moderation/role.ts index fd7b817..8cdfea0 100644 --- a/src/commands/moderation/role.ts +++ b/src/commands/moderation/role.ts @@ -9,7 +9,7 @@ export default class RoleCommand extends BushCommand { description: { content: "Manages users' roles.", usage: 'role <add|remove> <user> <role> [duration]', - examples: ['role add spammer nogiveaways 7days'] + examples: ['role add spammer nogiveaways 7days', 'ra tyman muted', 'rr tyman staff'] }, slash: true, slashOptions: [ diff --git a/src/commands/utilities/activity.ts b/src/commands/utilities/activity.ts index 2d818e7..30f11cb 100644 --- a/src/commands/utilities/activity.ts +++ b/src/commands/utilities/activity.ts @@ -6,16 +6,19 @@ const activityMap = { 'Betrayal.io': '773336526917861400', 'Fishington.io': '814288819477020702', 'YouTube Together': '755600276941176913', - 'Chess in the Park': '832012774040141894' + 'Chess in the Park': '832012774040141894', + 'Watch Together': '880218394199220334' }; function map(phase: string) { - if (['yt', 'youtube'].includes(phase)) return activityMap['YouTube Together']; + if (client.consts.regex.snowflake.test(phase)) return phase; + else if (Object.keys(activityMap).includes(phase)) return activityMap[phase as keyof typeof activityMap]; + else if (['yt', 'youtube'].includes(phase)) return activityMap['Watch Together']; else if (['chess', 'park'].includes(phase)) return activityMap['Chess in the Park']; else if (['poker'].includes(phase)) return activityMap['Poker Night']; else if (['fish', 'fishing', 'fishington'].includes(phase)) return activityMap['Fishington.io']; else if (['betrayal'].includes(phase)) return activityMap['Betrayal.io']; - else return undefined; + else return null; } const activityTypeCaster = (_message: Message | BushMessage | BushSlashMessage, phrase: string) => { @@ -76,7 +79,8 @@ export default class YouTubeCommand extends BushCommand { { name: 'Betrayal.io', value: '773336526917861400' }, { name: 'Fishington.io', value: '814288819477020702' }, { name: 'YouTube Together', value: '755600276941176913' }, - { name: 'Chess in the Park', value: '832012774040141894' } + { name: 'Chess in the Park', value: '832012774040141894' }, + { name: 'Watch Together', value: '880218394199220334' } ] } ], diff --git a/src/commands/utilities/suicide.ts b/src/commands/utilities/suicide.ts index 0ec84a5..a05cdaa 100644 --- a/src/commands/utilities/suicide.ts +++ b/src/commands/utilities/suicide.ts @@ -13,7 +13,8 @@ export default class TemplateCommand extends BushCommand { }, slash: true, clientPermissions: ['SEND_MESSAGES'], - userPermissions: ['SEND_MESSAGES'] + userPermissions: ['SEND_MESSAGES'], + bypassChannelBlacklist: true }); } diff --git a/src/inhibitors/blacklist/channelGlobalBlacklist.ts b/src/inhibitors/blacklist/channelGlobalBlacklist.ts index d870307..2725431 100644 --- a/src/inhibitors/blacklist/channelGlobalBlacklist.ts +++ b/src/inhibitors/blacklist/channelGlobalBlacklist.ts @@ -1,4 +1,4 @@ -import { BushInhibitor, BushMessage, BushSlashMessage } from '@lib'; +import { BushCommand, BushInhibitor, BushMessage, BushSlashMessage } from '@lib'; export default class UserGlobalBlacklistInhibitor extends BushInhibitor { public constructor() { @@ -10,11 +10,11 @@ export default class UserGlobalBlacklistInhibitor extends BushInhibitor { }); } - public override exec(message: BushMessage | BushSlashMessage): boolean { + public override exec(message: BushMessage | BushSlashMessage, command: BushCommand): boolean { if (!message.author || !message.guild) return false; if (client.isOwner(message.author) || /* client.isSuperUser(message.author) ||*/ client.user!.id === message.author.id) return false; - if (client.cache.global.blacklistedChannels.includes(message.channel!.id)) { + if (client.cache.global.blacklistedChannels.includes(message.channel!.id) && !command.bypassChannelBlacklist) { return true; } return false; diff --git a/src/inhibitors/blacklist/channelGuildBlacklist.ts b/src/inhibitors/blacklist/channelGuildBlacklist.ts index d02408c..63334c4 100644 --- a/src/inhibitors/blacklist/channelGuildBlacklist.ts +++ b/src/inhibitors/blacklist/channelGuildBlacklist.ts @@ -1,4 +1,4 @@ -import { BushInhibitor, BushMessage, BushSlashMessage } from '@lib'; +import { BushCommand, BushInhibitor, BushMessage, BushSlashMessage } from '@lib'; export default class ChannelGuildBlacklistInhibitor extends BushInhibitor { public constructor() { @@ -10,12 +10,20 @@ export default class ChannelGuildBlacklistInhibitor extends BushInhibitor { }); } - public override async exec(message: BushMessage | BushSlashMessage): Promise<boolean> { + public override async exec(message: BushMessage | BushSlashMessage, command: BushCommand): Promise<boolean> { if (!message.author || !message.guild) return false; if (client.isOwner(message.author) || /* client.isSuperUser(message.author) || */ client.user!.id === message.author.id) return false; - if ((await message.guild.getSetting('bypassChannelBlacklist'))?.includes(message.author.id)) return false; - if ((await message.guild.getSetting('blacklistedChannels'))?.includes(message.channel!.id)) { + if ( + (await message.guild.getSetting('bypassChannelBlacklist'))?.includes(message.author.id) && + !command.bypassChannelBlacklist + ) { + return false; + } + if ( + (await message.guild.getSetting('blacklistedChannels'))?.includes(message.channel!.id) && + !command.bypassChannelBlacklist + ) { return true; } return false; diff --git a/src/lib/extensions/discord-akairo/BushCommand.ts b/src/lib/extensions/discord-akairo/BushCommand.ts index 1c8ea5b..073221d 100644 --- a/src/lib/extensions/discord-akairo/BushCommand.ts +++ b/src/lib/extensions/discord-akairo/BushCommand.ts @@ -1,5 +1,5 @@ import { ArgumentOptions, ArgumentPromptOptions, ArgumentTypeCaster, Command, CommandOptions } from 'discord-akairo'; -import { Snowflake } from 'discord.js'; +import { PermissionResolvable, Snowflake } from 'discord.js'; import { BushMessage } from '../discord.js/BushMessage'; import { BushClient } from './BushClient'; import { BushCommandHandler } from './BushCommandHandler'; @@ -136,7 +136,9 @@ export interface CustomBushArgumentOptions extends BaseBushArgumentOptions { customType?: ArgumentTypeCaster | (string | string[])[] | RegExp | string | null; } -export interface BushCommandOptions extends CommandOptions { +export type BushMissingPermissionSupplier = (message: BushMessage | BushSlashMessage) => Promise<any> | any; + +export interface BushCommandOptions extends Omit<CommandOptions, 'userPermissions' | 'clientPermissions'> { hidden?: boolean; restrictedChannels?: Snowflake[]; restrictedGuilds?: Snowflake[]; @@ -148,6 +150,9 @@ export interface BushCommandOptions extends CommandOptions { args?: BushArgumentOptions[] & CustomBushArgumentOptions[]; category: string; pseudo?: boolean; + bypassChannelBlacklist?: boolean; + clientPermissions?: PermissionResolvable | PermissionResolvable[] | BushMissingPermissionSupplier; + userPermissions?: PermissionResolvable | PermissionResolvable[] | BushMissingPermissionSupplier; } export class BushCommand extends Command { @@ -155,13 +160,14 @@ export class BushCommand extends Command { public declare handler: BushCommandHandler; + /** The command's options */ public options: BushCommandOptions; /** The channels the command is limited to run in. */ - public restrictedChannels: Snowflake[]; + public restrictedChannels: Snowflake[] | undefined; /** The guilds the command is limited to run in. */ - public restrictedGuilds: Snowflake[]; + public restrictedGuilds: Snowflake[] | undefined; /** Whether the command is hidden from the help command. */ public hidden: boolean; @@ -169,6 +175,9 @@ export class BushCommand extends Command { /** A fake command, completely hidden from the help command. */ public pseudo: boolean; + /** Allow this command to be run in channels that are blacklisted. */ + public bypassChannelBlacklist: boolean; + public constructor(id: string, options: BushCommandOptions) { if (options.args && typeof options.args !== 'function') { options.args.forEach((_, index: number) => { @@ -179,12 +188,14 @@ export class BushCommand extends Command { } }); } - super(id, options); + // incompatible options + super(id, options as any); this.options = options; - this.hidden = options.hidden ?? false; - this.restrictedChannels = options.restrictedChannels!; - this.restrictedGuilds = options.restrictedGuilds!; - this.pseudo = options.pseudo!; + this.hidden = Boolean(options.hidden); + this.restrictedChannels = options.restrictedChannels; + this.restrictedGuilds = options.restrictedGuilds; + this.pseudo = Boolean(options.pseudo); + this.bypassChannelBlacklist = Boolean(options.bypassChannelBlacklist); } public override exec(message: BushMessage, args: any): any; diff --git a/src/lib/extensions/discord-akairo/BushCommandHandler.ts b/src/lib/extensions/discord-akairo/BushCommandHandler.ts index f8dcd93..8ab47d8 100644 --- a/src/lib/extensions/discord-akairo/BushCommandHandler.ts +++ b/src/lib/extensions/discord-akairo/BushCommandHandler.ts @@ -9,17 +9,30 @@ export type BushCommandHandlerOptions = CommandHandlerOptions; export interface BushCommandHandlerEvents extends CommandHandlerEvents { commandBlocked: [message: BushMessage, command: BushCommand, reason: string]; - + commandBreakout: [message: BushMessage, command: BushCommand, breakMessage: BushMessage]; + commandCancelled: [message: BushMessage, command: BushCommand, retryMessage?: BushMessage]; + commandFinished: [message: BushMessage, command: BushCommand, args: any, returnValue: any]; + commandInvalid: [message: BushMessage, command: BushCommand]; + commandLocked: [message: BushMessage, command: BushCommand]; + commandStarted: [message: BushMessage, command: BushCommand, args: any]; + cooldown: [message: BushMessage | BushSlashMessage, command: BushCommand, remaining: number]; + error: [error: Error, message: BushMessage, command?: BushCommand]; + inPrompt: [message: BushMessage]; + load: [command: BushCommand, isReload: boolean]; + messageBlocked: [message: BushMessage | BushSlashMessage, reason: string]; + messageInvalid: [message: BushMessage]; missingPermissions: [message: BushMessage, command: BushCommand, type: 'client' | 'user', missing: Array<PermissionString>]; - + remove: [command: BushCommand]; slashBlocked: [message: BushSlashMessage, command: BushCommand, reason: string]; - + slashError: [error: Error, message: BushSlashMessage, command: BushCommand]; + slashFinished: [message: BushSlashMessage, command: BushCommand, args: any, returnValue: any]; slashMissingPermissions: [ message: BushSlashMessage, command: BushCommand, type: 'client' | 'user', missing: Array<PermissionString> ]; + slashStarted: [message: BushSlashMessage, command: BushCommand, args: any]; } export class BushCommandHandler extends CommandHandler { diff --git a/src/lib/extensions/discord.js/BushClientEvents.d.ts b/src/lib/extensions/discord.js/BushClientEvents.d.ts index eb36153..2c9de89 100644 --- a/src/lib/extensions/discord.js/BushClientEvents.d.ts +++ b/src/lib/extensions/discord.js/BushClientEvents.d.ts @@ -233,7 +233,12 @@ export interface BushClientEvents extends ClientEvents { caseID: string, dmSuccess: boolean ]; - bushLevelUp: []; + bushLevelUpdate: [ + member: BushGuildMember, + oldLevel: number, + newLevel: number, + currentXp: number + ]; } type Setting = diff --git a/src/lib/models/Guild.ts b/src/lib/models/Guild.ts index f59bed1..1897068 100644 --- a/src/lib/models/Guild.ts +++ b/src/lib/models/Guild.ts @@ -64,6 +64,18 @@ export const guildSettingsObj = { description: 'Custom phrases to be detected by automod.', type: 'custom', configurable: false + }, + noXpChannels: { + name: 'No Xp Channels', + description: 'Channels where users will not earn xp for leveling.', + type: 'channel-array', + configurable: true + }, + levelRoles: { + name: 'Level Roles', + description: 'What roles get given at certain levels.', + type: 'custom', + configurable: false } }; export type GuildSettings = keyof typeof guildSettingsObj; @@ -144,11 +156,13 @@ export interface GuildModel { punishmentEnding: string; disabledCommands: string[]; lockdownChannels: Snowflake[]; - autoModPhases: string[]; + autoModPhases: { [word: string]: 0 | 1 | 2 | 3 }; enabledFeatures: GuildFeatures[]; joinRoles: Snowflake[]; logChannels: LogChannelDB; bypassChannelBlacklist: Snowflake[]; + noXpChannels: Snowflake[]; + levelRoles: { [level: number]: Snowflake }; } export interface GuildModelCreationAttributes { @@ -162,11 +176,13 @@ export interface GuildModelCreationAttributes { punishmentEnding?: string; disabledCommands?: string[]; lockdownChannels?: Snowflake[]; - autoModPhases?: string[]; + autoModPhases?: { [word: string]: 0 | 1 | 2 | 3 }; enabledFeatures?: GuildFeatures[]; joinRoles?: Snowflake[]; logChannels?: LogChannelDB; bypassChannelBlacklist?: Snowflake[]; + noXpChannels?: Snowflake[]; + levelRoles?: { [level: number]: Snowflake }; } export class Guild extends BaseModel<GuildModel, GuildModelCreationAttributes> implements GuildModel { @@ -273,10 +289,10 @@ export class Guild extends BaseModel<GuildModel, GuildModelCreationAttributes> i /** * Custom automod phases */ - public get autoModPhases(): string[] { + public get autoModPhases(): { [word: string]: 0 | 1 | 2 | 3 } { throw new Error(NEVER_USED); } - public set autoModPhases(_: string[]) { + public set autoModPhases(_: { [word: string]: 0 | 1 | 2 | 3 }) { throw new Error(NEVER_USED); } @@ -320,6 +336,20 @@ export class Guild extends BaseModel<GuildModel, GuildModelCreationAttributes> i throw new Error(NEVER_USED); } + public get noXpChannels(): Snowflake[] { + throw new Error(NEVER_USED); + } + public set noXpChannels(_: Snowflake[]) { + throw new Error(NEVER_USED); + } + + public get levelRoles(): { [level: number]: Snowflake } { + throw new Error(NEVER_USED); + } + public set levelRoles(_: { [level: number]: Snowflake }) { + throw new Error(NEVER_USED); + } + public static initModel(sequelize: Sequelize, client: BushClient): void { Guild.init( { @@ -349,7 +379,17 @@ export class Guild extends BaseModel<GuildModel, GuildModelCreationAttributes> i }, disabledCommands: jsonArrayInit('disabledCommands'), lockdownChannels: jsonArrayInit('lockdownChannels'), - autoModPhases: jsonArrayInit('autoModPhases'), + autoModPhases: { + type: DataTypes.TEXT, + get: function (): { [level: number]: Snowflake } { + return jsonParseGet.call(this, 'autoModPhases'); + }, + set: function (val: { [level: number]: Snowflake }) { + return jsonParseSet.call(this, 'autoModPhases', val); + }, + allowNull: false, + defaultValue: '{}' + }, enabledFeatures: jsonArrayInit('enabledFeatures'), joinRoles: jsonArrayInit('joinRoles'), logChannels: { @@ -363,7 +403,19 @@ export class Guild extends BaseModel<GuildModel, GuildModelCreationAttributes> i allowNull: false, defaultValue: '{}' }, - bypassChannelBlacklist: jsonArrayInit('bypassChannelBlacklist') + bypassChannelBlacklist: jsonArrayInit('bypassChannelBlacklist'), + noXpChannels: jsonArrayInit('noXpChannels'), + levelRoles: { + type: DataTypes.TEXT, + get: function (): { [level: number]: Snowflake } { + return jsonParseGet.call(this, 'levelRoles'); + }, + set: function (val: { [level: number]: Snowflake }) { + return jsonParseSet.call(this, 'levelRoles', val); + }, + allowNull: false, + defaultValue: '{}' + } }, { sequelize: sequelize } ); diff --git a/src/listeners/commands/commandBlocked.ts b/src/listeners/commands/commandBlocked.ts index 3be9d1f..8329c83 100644 --- a/src/listeners/commands/commandBlocked.ts +++ b/src/listeners/commands/commandBlocked.ts @@ -82,7 +82,7 @@ export default class CommandBlockedListener extends BushListener { if (!command) break; const channels = command.restrictedChannels; const names: string[] = []; - channels.forEach((c) => { + channels!.forEach((c) => { names.push(`<#${c}>`); }); const pretty = util.oxford(names, 'and'); @@ -95,7 +95,7 @@ export default class CommandBlockedListener extends BushListener { if (!command) break; const guilds = command.restrictedGuilds; const names: string[] = []; - guilds.forEach((g) => { + guilds!.forEach((g) => { names.push(`\`${client.guilds.cache.get(g)?.name}\``); }); const pretty = util.oxford(names, 'and'); diff --git a/src/listeners/custom/bushLevelUpdate.ts b/src/listeners/custom/bushLevelUpdate.ts new file mode 100644 index 0000000..0b7ebfa --- /dev/null +++ b/src/listeners/custom/bushLevelUpdate.ts @@ -0,0 +1,17 @@ +import { BushListener } from '../../lib'; +import { BushClientEvents } from '../../lib/extensions/discord.js/BushClientEvents'; + +export default class BushLevelUpdateListener extends BushListener { + public constructor() { + super('bushLevelUpdate', { + emitter: 'client', + event: 'bushLevelUpdate', + category: 'custom' + }); + } + + // eslint-disable-next-line @typescript-eslint/no-unused-vars + public override async exec(...[member, oldLevel, newLevel, currentXp]: BushClientEvents['bushLevelUpdate']) { + // + } +} diff --git a/src/listeners/message/automodCreate.ts b/src/listeners/message/automodCreate.ts index b708e30..c3c89ff 100644 --- a/src/listeners/message/automodCreate.ts +++ b/src/listeners/message/automodCreate.ts @@ -1,10 +1,10 @@ import { BushListener, BushMessage } from '@lib'; // @ts-expect-error: ts doesn't recognize json5 -import _badLinks from '@root/lib/badlinks'; // Stolen from https://github.com/nacrt/SkyblockClient-REPO/blob/main/files/scamlinks.json +import _badLinks from '@root/lib/badlinks'; // partially uses https://github.com/nacrt/SkyblockClient-REPO/blob/main/files/scamlinks.json // @ts-expect-error: ts doesn't recognize json5 import _badLinksSecret from '@root/lib/badlinks-secret'; // shhhh // @ts-expect-error: ts doesn't recognize json5 -import badWords from '@root/lib/badwords'; +import _badWords from '@root/lib/badwords'; import { MessageEmbed } from 'discord.js'; import { BushClientEvents } from '../../lib/extensions/discord.js/BushClientEvents'; @@ -25,19 +25,20 @@ export default class AutomodMessageCreateListener extends BushListener { if (message.channel.type === 'DM' || !message.guild) return; if (!(await message.guild.hasFeature('automod'))) return; - /* await message.guild.getSetting('autoModPhases'); */ + const customAutomodPhrases = (await message.guild.getSetting('autoModPhases')) ?? {}; - const badLinks: { [key: string]: number } = {}; + const badLinks: { [key: string]: 0 | 1 | 2 | 3 } = {}; let temp = _badLinks; if (_badLinksSecret) temp = temp.concat(_badLinksSecret); temp.forEach((link: string) => { badLinks[link] = 3; }); + const badWords: { [key: string]: 0 | 1 | 2 | 3 } = _badWords; - const wordMap = { ...badWords, ...badLinks }; + const wordMap = { ...badWords, ...badLinks, ...customAutomodPhrases }; const wordKeys = Object.keys(wordMap); - const offences: { [key: string]: number } = {}; + const offences: { [key: string]: 0 | 1 | 2 | 3 } = {}; const cleanMessageContent = message.content?.toLowerCase().replace(/ /g, ''); wordKeys.forEach((word) => { diff --git a/src/listeners/message/level.ts b/src/listeners/message/level.ts index aff8190..16f616f 100644 --- a/src/listeners/message/level.ts +++ b/src/listeners/message/level.ts @@ -3,7 +3,6 @@ import { MessageType } from 'discord.js'; export default class LevelListener extends BushListener { #levelCooldowns: Set<string> = new Set(); - #blacklistedChannels = ['702456294874808330']; public constructor() { super('level', { emitter: 'commandHandler', @@ -14,7 +13,8 @@ export default class LevelListener extends BushListener { public override async exec(...[message]: BushCommandHandlerEvents['messageInvalid']): Promise<void> { if (message.author.bot || !message.author || !message.guild) return; if (this.#levelCooldowns.has(`${message.guild.id}-${message.author.id}`)) return; - if (this.#blacklistedChannels.includes(message.channel.id)) return; + + if ((await message.guild.getSetting('noXpChannels')).includes(message.channel.id)) return; const allowedMessageTypes: MessageType[] = ['DEFAULT', 'REPLY']; // this is so ts will yell at me when discord.js makes some unnecessary breaking change if (!allowedMessageTypes.includes(message.type)) return; //checks for join messages, slash commands, booster messages etc const [user] = await Level.findOrBuild({ @@ -36,7 +36,7 @@ export default class LevelListener extends BushListener { return false; }); const newLevel = Level.convertXpToLevel(user.xp); - if (previousLevel < newLevel) client.emit('bushLevelUp'); + if (previousLevel !== newLevel) client.emit('bushLevelUpdate', message.member!, previousLevel, newLevel, user.xp); if (success) void client.logger.verbose(`level`, `Gave <<${xpToGive}>> XP to <<${message.author.tag}>> in <<${message.guild}>>.`); this.#levelCooldowns.add(`${message.guild.id}-${message.author.id}`); |