aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/commands/admin/channelPermissions.ts4
-rw-r--r--src/commands/config/customAutomodPhrases.ts64
-rw-r--r--src/commands/config/levelRoles.ts61
-rw-r--r--src/commands/leveling/setLevel.ts2
-rw-r--r--src/commands/moderation/_lockdown.ts2
-rw-r--r--src/commands/moderation/hideCase.ts5
-rw-r--r--src/commands/moderation/mute.ts8
-rw-r--r--src/commands/moderation/role.ts2
-rw-r--r--src/commands/utilities/activity.ts12
-rw-r--r--src/commands/utilities/suicide.ts3
-rw-r--r--src/inhibitors/blacklist/channelGlobalBlacklist.ts6
-rw-r--r--src/inhibitors/blacklist/channelGuildBlacklist.ts16
-rw-r--r--src/lib/extensions/discord-akairo/BushCommand.ts29
-rw-r--r--src/lib/extensions/discord-akairo/BushCommandHandler.ts19
-rw-r--r--src/lib/extensions/discord.js/BushClientEvents.d.ts7
-rw-r--r--src/lib/models/Guild.ts64
-rw-r--r--src/listeners/commands/commandBlocked.ts4
-rw-r--r--src/listeners/custom/bushLevelUpdate.ts17
-rw-r--r--src/listeners/message/automodCreate.ts13
-rw-r--r--src/listeners/message/level.ts6
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}`);