aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/arguments/contentWithDuration.ts6
-rw-r--r--src/arguments/discordEmoji.ts9
-rw-r--r--src/arguments/duration.ts4
-rw-r--r--src/arguments/snowflake.ts8
-rw-r--r--src/commands/config/features.ts29
-rw-r--r--src/commands/config/settings.ts25
-rw-r--r--src/commands/utilities/steal.ts50
-rw-r--r--src/lib/extensions/discord-akairo/BushClient.ts6
-rw-r--r--src/lib/extensions/discord-akairo/BushCommand.ts11
-rw-r--r--src/lib/models/Guild.ts34
-rw-r--r--src/lib/utils/BushConstants.ts15
11 files changed, 155 insertions, 42 deletions
diff --git a/src/arguments/contentWithDuration.ts b/src/arguments/contentWithDuration.ts
index 314b761..38b3fa4 100644
--- a/src/arguments/contentWithDuration.ts
+++ b/src/arguments/contentWithDuration.ts
@@ -1,8 +1,8 @@
-import { BushArgumentTypeCaster, BushMessage } from '@lib';
+import { BushArgumentTypeCaster } from '@lib';
export const contentWithDurationTypeCaster: BushArgumentTypeCaster = async (
- _message: BushMessage,
- phrase: string
+ _,
+ phrase
): Promise<{ duration: number; contentWithoutTime: string | null }> => {
return client.util.parseDuration(phrase);
};
diff --git a/src/arguments/discordEmoji.ts b/src/arguments/discordEmoji.ts
new file mode 100644
index 0000000..47e734d
--- /dev/null
+++ b/src/arguments/discordEmoji.ts
@@ -0,0 +1,9 @@
+import { Snowflake } from 'discord-api-types';
+import { BushArgumentTypeCaster } from '../lib';
+
+export const discordEmojiTypeCaster: BushArgumentTypeCaster = (_, phrase): { name: string; id: Snowflake } | null => {
+ if (!phrase) return null;
+ const validEmoji: RegExpExecArray | null = client.consts.regex.discordEmoji.exec(phrase);
+ if (!validEmoji || !validEmoji.groups) return null;
+ return { name: validEmoji.groups.name, id: validEmoji.groups.id };
+};
diff --git a/src/arguments/duration.ts b/src/arguments/duration.ts
index ce181e8..6e76034 100644
--- a/src/arguments/duration.ts
+++ b/src/arguments/duration.ts
@@ -1,5 +1,5 @@
-import { BushArgumentTypeCaster, BushMessage } from '@lib';
+import { BushArgumentTypeCaster } from '@lib';
-export const durationTypeCaster: BushArgumentTypeCaster = (_message: BushMessage, phrase): number => {
+export const durationTypeCaster: BushArgumentTypeCaster = (_, phrase): number => {
return client.util.parseDuration(phrase).duration;
};
diff --git a/src/arguments/snowflake.ts b/src/arguments/snowflake.ts
new file mode 100644
index 0000000..0e6136f
--- /dev/null
+++ b/src/arguments/snowflake.ts
@@ -0,0 +1,8 @@
+import { Snowflake } from 'discord.js';
+import { BushArgumentTypeCaster } from '../lib';
+
+export const snowflakeTypeCaster: BushArgumentTypeCaster = (_, phrase): Snowflake | null => {
+ if (!phrase) return null;
+ if (client.consts.regex.snowflake.test(phrase)) return phrase;
+ return null;
+};
diff --git a/src/commands/config/features.ts b/src/commands/config/features.ts
new file mode 100644
index 0000000..0547bd0
--- /dev/null
+++ b/src/commands/config/features.ts
@@ -0,0 +1,29 @@
+// import { BushCommand, BushMessage, BushSlashMessage, guildFeatures } from '@lib';
+// import { MessageEmbed } from 'discord.js';
+
+// export default class FeaturesCommand extends BushCommand {
+// public constructor() {
+// super('features', {
+// aliases: ['features'],
+// category: 'config',
+// description: {
+// content: 'Toggle features the server.',
+// usage: 'features',
+// examples: ['features']
+// },
+// slash: true,
+// channel: 'guild',
+// clientPermissions: ['SEND_MESSAGES', 'EMBED_LINKS'],
+// userPermissions: ['SEND_MESSAGES', 'MANAGE_GUILD']
+// });
+// }
+// public override async exec(message: BushMessage | BushSlashMessage): Promise<unknown> {
+// if (!message.guild) return await message.util.reply(`${util.emojis.error} This command can only be used in servers.`);
+// const featureEmbed = new MessageEmbed().setTitle(`${message.guild.name}'s Features`).setColor(util.colors.default);
+// const featureList: string[] = [];
+// const enabledFeatures = message.guild.getSetting('enabledFeatures');
+// guildFeatures.forEach(feature => {
+// featureList.push(`${}`)
+// })
+// }
+// }
diff --git a/src/commands/config/settings.ts b/src/commands/config/settings.ts
index f474804..0b71629 100644
--- a/src/commands/config/settings.ts
+++ b/src/commands/config/settings.ts
@@ -1,28 +1,28 @@
-// import { BushCommand, BushMessage, BushSlashMessage } from '@lib';
+// import { BushCommand, BushMessage, BushSlashMessage, guildSettings } from '@lib';
// export default class SettingsCommand extends BushCommand {
// public constructor() {
// super('settings', {
-// aliases: ['settings'],
+// aliases: ['settings', 'settings', 'configure', 'config'],
// category: 'config',
// description: {
-// content: 'Configure options for ',
-// usage: 'template <requiredArg> [optionalArg]',
+// content: 'Configure server options. Hint this is easier to use with the slash command.',
+// usage: 'config <\'add\'|\'remove\'|\'toggle\'> <setting>',
// examples: ['template 1 2']
// },
// args: [
// {
-// id: 'required_argument',
-// type: 'string',
+// id: 'action',
+// customType: ['add', 'remove', 'toggle'],
// prompt: {
-// start: 'What would you like to set your first argument to be?',
-// retry: '{error} Pick a valid argument.',
+// start: 'What action would you like to perform, it can be `add`, `remove`, or `toggle`.',
+// retry: '{error} Choose a either `add`, `remove`, or `toggle`.',
// optional: false
// }
// },
// {
-// id: 'optional_argument',
-// type: 'string',
+// id: 'setting',
+// customType: Object.keys(guildSettings),
// prompt: {
// start: 'What would you like to set your second argument to be?',
// retry: '{error} Pick a valid argument.',
@@ -30,7 +30,7 @@
// }
// }
// ],
-// slash: false, //set this to true
+// slash: true,
// slashOptions: [
// {
// name: 'required_argument',
@@ -45,10 +45,7 @@
// required: false
// }
// ],
-// superUserOnly: true,
-// ownerOnly: true,
// channel: 'guild',
-// hidden: true,
// clientPermissions: ['SEND_MESSAGES'],
// userPermissions: ['SEND_MESSAGES']
// });
diff --git a/src/commands/utilities/steal.ts b/src/commands/utilities/steal.ts
index 92abcb2..01c39ea 100644
--- a/src/commands/utilities/steal.ts
+++ b/src/commands/utilities/steal.ts
@@ -1,5 +1,5 @@
import { BushCommand, BushMessage } from '@lib';
-import { Emoji } from 'discord.js';
+import { Snowflake } from 'discord-api-types';
export default class StealCommand extends BushCommand {
public constructor() {
@@ -8,20 +8,22 @@ export default class StealCommand extends BushCommand {
category: 'utilities',
description: {
content: 'Steal an emoji from another server and add it to your own.',
- usage: 'steal <emoji/url> [--name name]',
- examples: ['steal <:omegaclown:782630946435366942> --name ironm00n']
+ usage: 'steal <emoji/emoji id/url> [name]',
+ examples: ['steal <:omegaclown:782630946435366942> ironm00n']
},
args: [
{
- id: 'emoji',
- customType: util.arg.union('emoji', 'url'),
+ id: 'emojiOrName',
+ customType: util.arg.union('discordEmoji', 'snowflake', 'url'),
prompt: {
start: 'What emoji would you like to steal?',
- retry: '{error} Pick a valid emoji.',
+ retry: '{error} Pick a valid emoji, emoji id, or image url.',
optional: true
}
},
- { id: 'name', match: 'option', flag: '--name', default: 'stolen_emoji' }
+ {
+ id: 'name2'
+ }
],
slash: false,
channel: 'guild',
@@ -29,22 +31,38 @@ export default class StealCommand extends BushCommand {
userPermissions: ['SEND_MESSAGES', 'MANAGE_EMOJIS_AND_STICKERS']
});
}
- public override async exec(message: BushMessage, args: { emoji?: URL | Emoji; name: string }): Promise<unknown> {
- if ((!args || !args.emoji) && !message.attachments.size)
+ public override async exec(
+ message: BushMessage,
+ args?: { emojiOrName?: { name: string; id: Snowflake } | Snowflake | URL | string; name2: string }
+ ): Promise<unknown> {
+ if ((!args || !args.emojiOrName) && !message.attachments.size)
return await message.util.reply(`${util.emojis.error} You must provide an emoji to steal.`);
+
const image =
- message.attachments.size && message.attachments.first()!.contentType?.includes('image/')
+ message.attachments.size && message.attachments.first()?.contentType?.includes('image/')
? message.attachments.first()!.url
- : args?.emoji instanceof Emoji
- ? `https://cdn.discordapp.com/emojis/${args.emoji.id}`
- : args?.emoji instanceof URL
- ? args.emoji.href
+ : args?.emojiOrName instanceof URL
+ ? args.emojiOrName.href
+ : typeof args?.emojiOrName === 'object'
+ ? `https://cdn.discordapp.com/emojis/${args.emojiOrName.id}`
+ : client.consts.regex.snowflake.test(args?.emojiOrName ?? '')
+ ? `https://cdn.discordapp.com/emojis/${args!.emojiOrName}`
: undefined;
- if (!image) return await message.util.reply(`${util.emojis.error} You must provide an emoji to steal.`);
+ if (image === undefined) return await message.util.reply(`${util.emojis.error} You must provide an emoji to steal.`);
+ if (message.attachments.size && typeof args?.emojiOrName !== 'string')
+ return await message.util.reply(`${util.emojis.error} You cannot attach an image and provide an argument.`);
+
+ const emojiName = message.attachments.size
+ ? (args?.emojiOrName as string) ?? 'stolen_emoji'
+ : args?.emojiOrName instanceof URL
+ ? args?.name2 ?? 'stolen_emoji'
+ : typeof args?.emojiOrName === 'object'
+ ? args?.name2 ?? args.emojiOrName.name ?? 'stolen_emoji'
+ : 'stolen_emoji';
const creationSuccess = await message
- .guild!.emojis.create(image, args.name, {
+ .guild!.emojis.create(image, emojiName, {
reason: `Stolen by ${message.author.tag} (${message.author.id})`
})
.catch((e: Error) => e);
diff --git a/src/lib/extensions/discord-akairo/BushClient.ts b/src/lib/extensions/discord-akairo/BushClient.ts
index 3feae96..ee92ded 100644
--- a/src/lib/extensions/discord-akairo/BushClient.ts
+++ b/src/lib/extensions/discord-akairo/BushClient.ts
@@ -21,8 +21,10 @@ import { exit } from 'process';
import readline from 'readline';
import { Sequelize } from 'sequelize';
import { contentWithDurationTypeCaster } from '../../../arguments/contentWithDuration';
+import { discordEmojiTypeCaster } from '../../../arguments/discordEmoji';
import { durationTypeCaster } from '../../../arguments/duration';
import { permissionTypeCaster } from '../../../arguments/permission';
+import { snowflakeTypeCaster } from '../../../arguments/snowflake';
import { UpdateCacheTask } from '../../../tasks/updateCache';
import { ActivePunishment } from '../../models/ActivePunishment';
import { Global } from '../../models/Global';
@@ -250,7 +252,9 @@ export class BushClient<Ready extends boolean = boolean> extends AkairoClient<Re
this.commandHandler.resolver.addTypes({
duration: durationTypeCaster,
contentWithDuration: contentWithDurationTypeCaster,
- permission: permissionTypeCaster
+ permission: permissionTypeCaster,
+ snowflake: snowflakeTypeCaster,
+ discordEmoji: discordEmojiTypeCaster
});
// loads all the handlers
const loaders = {
diff --git a/src/lib/extensions/discord-akairo/BushCommand.ts b/src/lib/extensions/discord-akairo/BushCommand.ts
index 0eaa5e0..7ecb679 100644
--- a/src/lib/extensions/discord-akairo/BushCommand.ts
+++ b/src/lib/extensions/discord-akairo/BushCommand.ts
@@ -6,7 +6,7 @@ import { BushClient } from './BushClient';
import { BushCommandHandler } from './BushCommandHandler';
import { BushSlashMessage } from './BushSlashMessage';
-export type BushArgumentType =
+export type BaseBushArgumentType =
| 'string'
| 'lowercase'
| 'uppercase'
@@ -61,7 +61,12 @@ export type BushArgumentType =
| 'listener'
| 'duration'
| 'contentWithDuration'
- | 'permission';
+ | 'permission'
+ | 'snowflake'
+ | 'discordEmoji';
+
+export type BushArgumentType = BaseBushArgumentType | RegExp;
+
interface BaseBushArgumentOptions extends Omit<ArgumentOptions, 'type'> {
id: string;
description?: string;
@@ -116,7 +121,7 @@ export interface BushArgumentOptions extends BaseBushArgumentOptions {
* - `contentWithDuration` tries to parse duration in milliseconds and returns the remaining content with the duration
* removed
*/
- type?: BushArgumentType;
+ type?: BushArgumentType | BaseBushArgumentType[];
}
export interface CustomBushArgumentOptions extends BaseBushArgumentOptions {
/**
diff --git a/src/lib/models/Guild.ts b/src/lib/models/Guild.ts
index 3473ea4..dfba90c 100644
--- a/src/lib/models/Guild.ts
+++ b/src/lib/models/Guild.ts
@@ -15,6 +15,7 @@ export interface GuildModel {
disabledCommands: string[];
lockdownChannels: Snowflake[];
autoModPhases: string[];
+ enabledFeatures: string[];
}
export interface GuildModelCreationAttributes {
@@ -29,8 +30,20 @@ export interface GuildModelCreationAttributes {
disabledCommands?: string[];
lockdownChannels?: Snowflake[];
autoModPhases?: string[];
+ enabledFeatures?: string[];
}
+export const guildSettings = {
+ prefix: { type: 'string' },
+ autoPublishChannels: { type: 'channel-array' },
+ welcomeChannel: { type: 'channel-array' },
+ muteRole: { type: 'role' },
+ punishmentEnding: { type: 'string' },
+ lockdownChannels: { type: 'channel-array' }
+};
+
+export const guildFeatures = ['automodEnabled', 'supportThreads', 'stickyRoles'];
+
const NEVER_USED = 'This should never be executed';
export class Guild extends BaseModel<GuildModel, GuildModelCreationAttributes> implements GuildModel {
@@ -144,6 +157,16 @@ export class Guild extends BaseModel<GuildModel, GuildModelCreationAttributes> i
throw new Error(NEVER_USED);
}
+ /**
+ * The features enabled in a guild
+ */
+ public get enabledFeatures(): string[] {
+ throw new Error(NEVER_USED);
+ }
+ public set enabledFeatures(_: string[]) {
+ throw new Error(NEVER_USED);
+ }
+
public static initModel(sequelize: Sequelize, client: BushClient): void {
Guild.init(
{
@@ -233,6 +256,17 @@ export class Guild extends BaseModel<GuildModel, GuildModelCreationAttributes> i
},
allowNull: false,
defaultValue: '[]'
+ },
+ enabledFeatures: {
+ type: DataTypes.TEXT,
+ get: function () {
+ return JSON.parse(this.getDataValue('enabledFeatures') as unknown as string);
+ },
+ set: function (val: string[]) {
+ return this.setDataValue('enabledFeatures', JSON.stringify(val) as unknown as string[]);
+ },
+ allowNull: false,
+ defaultValue: '[]'
}
},
{ sequelize: sequelize }
diff --git a/src/lib/utils/BushConstants.ts b/src/lib/utils/BushConstants.ts
index 68393c4..bcc34ae 100644
--- a/src/lib/utils/BushConstants.ts
+++ b/src/lib/utils/BushConstants.ts
@@ -21,12 +21,13 @@ interface bushColors {
black: '#000000';
orange: '#E86100';
}
+
export class BushConstants {
public static emojis = {
- success: '<:checkmark:837109864101707807>',
+ success: '<:success:837109864101707807>',
warn: '<:warn:848726900876247050>',
error: '<:error:837123021016924261>',
- successFull: '<:checkmark_full:850118767576088646>',
+ successFull: '<:success_full:850118767576088646>',
warnFull: '<:warn_full:850118767391539312>',
errorFull: '<:error_full:850118767295201350>',
mad: '<:mad:783046135392239626>',
@@ -36,7 +37,9 @@ export class BushConstants {
offlineCircle: '<:offline:787550565382750239>',
dndCircle: '<:dnd:787550487633330176>',
idleCircle: '<:idle:787550520956551218>',
- onlineCircle: '<:online:787550449435803658>'
+ onlineCircle: '<:online:787550449435803658>',
+ cross: '<:cross:878319362539421777>',
+ check: ''
};
public static colors: bushColors = {
@@ -99,6 +102,12 @@ export class BushConstants {
}
};
+ public static regex = {
+ snowflake: /\d{15,21}/im,
+ // eslint-disable-next-line no-useless-escape
+ discordEmoji: /<a?:(?<name>[a-zA-Z0-9\_]+):(?<id>\d{15,21})>/im
+ };
+
/** A bunch of mappings */
public static mappings = {
guilds: {