aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.vscode/settings.json2
-rw-r--r--src/commands/config/levelRoles.ts122
-rw-r--r--src/lib/extensions/discord.js/BushClientEvents.d.ts3
-rw-r--r--src/lib/models/Guild.ts59
-rw-r--r--src/listeners/custom/bushLevelUpdate.ts47
-rw-r--r--src/listeners/message/autoThread.ts2
-rw-r--r--src/listeners/message/level.ts12
7 files changed, 165 insertions, 82 deletions
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 144c4ca..b6ceb69 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -32,7 +32,7 @@
"prettier.withNodeModules": true,
"prettier.useEditorConfig": false,
"eslint.nodePath": ".yarn/sdks",
- "typescript.tsdk": "node_modules\\typescript\\lib",
+ "typescript.tsdk": "node_modules/typescript/lib",
"typescript.enablePromptUseWorkspaceTsdk": true,
"better-comments.highlightPlainText": true,
"better-comments.multilineComments": true,
diff --git a/src/commands/config/levelRoles.ts b/src/commands/config/levelRoles.ts
index f947d85..36dc50c 100644
--- a/src/commands/config/levelRoles.ts
+++ b/src/commands/config/levelRoles.ts
@@ -1,61 +1,65 @@
-// import { BushCommand, BushMessage, BushSlashMessage } from '@lib';
+import { BushCommand, BushMessage, BushSlashMessage } from '@lib';
-// export default class LevelRolesCommand extends BushCommand {
-// public constructor() {
-// super('levelRole', {
-// aliases: ['level-role', 'level-roles', 'lr'],
-// category: 'config',
-// description: {
-// content: 'Command description.',
-// usage: 'level-role <role> <level>',
-// examples: ['level-role 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']
-// });
-// }
+export default class LevelRolesCommand extends BushCommand {
+ public constructor() {
+ super('levelRole', {
+ aliases: ['level-role', 'level-roles', 'lr'],
+ category: 'config',
+ description: {
+ content: 'Configure roles to be assigned to users upon reaching certain levels.',
+ usage: ['level-role add <level> <role>', 'level-role remove <level>'],
+ examples: ['level-role 1 2']
+ },
+ args: [
+ {
+ id: 'action',
+ customType: ['add', 'remove']
+ },
+ {
+ 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;
-// }
-// }
+ 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/lib/extensions/discord.js/BushClientEvents.d.ts b/src/lib/extensions/discord.js/BushClientEvents.d.ts
index 2c9de89..d8f1146 100644
--- a/src/lib/extensions/discord.js/BushClientEvents.d.ts
+++ b/src/lib/extensions/discord.js/BushClientEvents.d.ts
@@ -237,7 +237,8 @@ export interface BushClientEvents extends ClientEvents {
member: BushGuildMember,
oldLevel: number,
newLevel: number,
- currentXp: number
+ currentXp: number,
+ message: BushMessage & { guild: BushGuild }
];
}
diff --git a/src/lib/models/Guild.ts b/src/lib/models/Guild.ts
index ab18d05..47b4af9 100644
--- a/src/lib/models/Guild.ts
+++ b/src/lib/models/Guild.ts
@@ -4,7 +4,14 @@ import { BushClient } from '../extensions/discord-akairo/BushClient';
import { BaseModel } from './BaseModel';
import { jsonArrayInit, jsonParseGet, jsonParseSet, NEVER_USED } from './__helpers';
-export const guildSettingsObj = {
+export const guildSettingsObj: {
+ [x in GuildSettings]: {
+ name: string;
+ description: string;
+ type: 'string' | 'custom' | 'channel' | 'role' | 'user' | 'channel-array' | 'role-array' | 'user-array';
+ configurable: boolean;
+ };
+} = {
prefix: {
name: 'Prefix',
description: 'The phrase required to trigger text commands in this server.',
@@ -73,12 +80,32 @@ export const guildSettingsObj = {
},
levelRoles: {
name: 'Level Roles',
- description: 'What roles get given at certain levels.',
+ description: 'What roles get given to users when they reach certain levels.',
type: 'custom',
configurable: false
+ },
+ levelUpChannel: {
+ name: 'Level Up Channel',
+ description: 'The channel to send level up messages in instead of last channel.',
+ type: 'channel',
+ configurable: true
}
};
-export type GuildSettings = keyof typeof guildSettingsObj;
+
+export type GuildSettings =
+ | 'prefix'
+ | 'autoPublishChannels'
+ | 'welcomeChannel'
+ | 'muteRole'
+ | 'punishmentEnding'
+ | 'lockdownChannels'
+ | 'joinRoles'
+ | 'bypassChannelBlacklist'
+ | 'logChannels'
+ | 'autoModPhases'
+ | 'noXpChannels'
+ | 'levelRoles'
+ | 'levelUpChannel';
export const settingsArr = Object.keys(guildSettingsObj).filter(
(s) => guildSettingsObj[s as GuildSettings].configurable
) as GuildSettings[];
@@ -119,6 +146,10 @@ export const guildFeaturesObj = {
modsCanPunishMods: {
name: 'Mods Can Punish Mods',
description: 'Allow moderators to punish other moderators.'
+ },
+ sendLevelUpMessages: {
+ name: 'Send Level Up Messages',
+ description: 'Send a message when a user levels up.'
}
};
@@ -163,6 +194,7 @@ export interface GuildModel {
bypassChannelBlacklist: Snowflake[];
noXpChannels: Snowflake[];
levelRoles: { [level: number]: Snowflake };
+ levelUpChannel: Snowflake;
}
export interface GuildModelCreationAttributes {
@@ -183,6 +215,7 @@ export interface GuildModelCreationAttributes {
bypassChannelBlacklist?: Snowflake[];
noXpChannels?: Snowflake[];
levelRoles?: { [level: number]: Snowflake };
+ levelUpChannel?: Snowflake;
}
export class Guild extends BaseModel<GuildModel, GuildModelCreationAttributes> implements GuildModel {
@@ -336,6 +369,9 @@ export class Guild extends BaseModel<GuildModel, GuildModelCreationAttributes> i
throw new Error(NEVER_USED);
}
+ /**
+ * Channels where users will not earn xp for leveling.
+ */
public get noXpChannels(): Snowflake[] {
throw new Error(NEVER_USED);
}
@@ -343,6 +379,9 @@ export class Guild extends BaseModel<GuildModel, GuildModelCreationAttributes> i
throw new Error(NEVER_USED);
}
+ /**
+ * What roles get given to users when they reach certain levels.
+ */
public get levelRoles(): { [level: number]: Snowflake } {
throw new Error(NEVER_USED);
}
@@ -350,6 +389,16 @@ export class Guild extends BaseModel<GuildModel, GuildModelCreationAttributes> i
throw new Error(NEVER_USED);
}
+ /**
+ * The channel to send level up messages in instead of last channel.
+ */
+ public get levelUpChannel(): Snowflake {
+ throw new Error(NEVER_USED);
+ }
+ public set levelUpChannel(_: Snowflake) {
+ throw new Error(NEVER_USED);
+ }
+
public static initModel(sequelize: Sequelize, client: BushClient): void {
Guild.init(
{
@@ -415,6 +464,10 @@ export class Guild extends BaseModel<GuildModel, GuildModelCreationAttributes> i
},
allowNull: false,
defaultValue: '{}'
+ },
+ levelUpChannel: {
+ type: DataTypes.STRING,
+ allowNull: true
}
},
{ sequelize: sequelize }
diff --git a/src/listeners/custom/bushLevelUpdate.ts b/src/listeners/custom/bushLevelUpdate.ts
index 0e24309..9339a4e 100644
--- a/src/listeners/custom/bushLevelUpdate.ts
+++ b/src/listeners/custom/bushLevelUpdate.ts
@@ -1,17 +1,34 @@
-// import { BushListener } from '../../lib';
-// import { BushClientEvents } from '../../lib/extensions/discord.js/BushClientEvents';
+import { Formatters, TextChannel } from 'discord.js';
+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'
-// });
-// }
+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']) {
-// //
-// }
-// }
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ public override async exec(...[member, oldLevel, newLevel, currentXp, message]: BushClientEvents['bushLevelUpdate']) {
+ if (await message.guild.hasFeature('sendLevelUpMessages')) {
+ void (async () => {
+ const channel = ((await message.guild.channels
+ .fetch((await message.guild.getSetting('levelUpChannel')) ?? message.channelId)
+ .catch(() => null)) ?? message.channel) as TextChannel;
+
+ const success = await channel
+ .send(
+ `${Formatters.bold(util.sanitizeWtlAndControl(member.user.tag))} leveled up to level ${Formatters.bold(
+ `${newLevel}`
+ )}.`
+ )
+ .catch(() => null);
+
+ if (!success) await client.console.warn('bushLevelUpdate', `Could not send level up message in ${message.guild}`);
+ })();
+ }
+ }
+}
diff --git a/src/listeners/message/autoThread.ts b/src/listeners/message/autoThread.ts
index a254337..8db3979 100644
--- a/src/listeners/message/autoThread.ts
+++ b/src/listeners/message/autoThread.ts
@@ -37,7 +37,7 @@ export default class autoThreadListener extends BushListener {
// todo: make these configurable etc...
if (message.guild.id !== '516977525906341928') return; // mb
if (message.channel.id !== '714332750156660756') return; // neu-support-1
- if (!(message.channel as BushTextChannel).permissionsFor(message.guild.me!).has('USE_PUBLIC_THREADS')) return;
+ if (!(message.channel as BushTextChannel).permissionsFor(message.guild.me!).has('CREATE_PUBLIC_THREADS')) return;
const thread = await message.startThread({
name: `Support - ${message.author.username}#${message.author.discriminator}`,
autoArchiveDuration: 60,
diff --git a/src/listeners/message/level.ts b/src/listeners/message/level.ts
index 16f616f..f263ff2 100644
--- a/src/listeners/message/level.ts
+++ b/src/listeners/message/level.ts
@@ -1,4 +1,4 @@
-import { BushCommandHandlerEvents, BushListener, Level } from '@lib';
+import { BushCommandHandlerEvents, BushGuild, BushListener, BushMessage, Level } from '@lib';
import { MessageType } from 'discord.js';
export default class LevelListener extends BushListener {
@@ -36,7 +36,15 @@ export default class LevelListener extends BushListener {
return false;
});
const newLevel = Level.convertXpToLevel(user.xp);
- if (previousLevel !== newLevel) client.emit('bushLevelUpdate', message.member!, previousLevel, newLevel, user.xp);
+ if (previousLevel !== newLevel)
+ client.emit(
+ 'bushLevelUpdate',
+ message.member!,
+ previousLevel,
+ newLevel,
+ user.xp,
+ message as BushMessage & { guild: BushGuild }
+ );
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}`);