From 1c6d451ffd63f9805b978e8565807e8a6b528681 Mon Sep 17 00:00:00 2001 From: IRONM00N <64110067+IRONM00N@users.noreply.github.com> Date: Thu, 29 Jul 2021 21:16:30 -0400 Subject: added a rudimentary automod, fixed a bunch of stuff, added some more listeners --- src/commands/dev/eval.ts | 2 - src/commands/info/avatar.ts | 3 +- src/commands/info/guildInfo.ts | 57 ++-- src/commands/info/userInfo.ts | 18 +- src/commands/moderation/slowmode.ts | 21 +- src/commands/skyblock-reborn/chooseColor.ts | 179 +++++++++++++ src/commands/skyblock-reborn/chooseColorCommand.ts | 179 ------------- src/lib/badlinks.json | 289 +++++++++++++++++++++ src/lib/badwords.json | 15 ++ src/lib/extensions/discord-akairo/BushClient.ts | 12 + .../extensions/discord-akairo/BushClientUtil.ts | 86 +++++- src/lib/extensions/discord-akairo/BushCommand.ts | 7 +- .../discord.js/BushApplicationCommandManager.d.ts | 43 +++ .../discord.js/BushApplicationCommandManager.ts | 26 -- .../BushApplicationCommandPermissionsManager.d.ts | 54 ++++ .../BushApplicationCommandPermissionsManager.ts | 31 --- .../extensions/discord.js/BushClientEvents.d.ts | 6 + src/lib/extensions/discord.js/BushGuild.ts | 7 +- .../BushGuildApplicationCommandManager.d.ts | 18 ++ .../BushGuildApplicationCommandManager.ts | 10 - .../discord.js/BushGuildEmojiRoleManager.d.ts | 19 ++ .../discord.js/BushGuildEmojiRoleManager.ts | 13 - .../discord.js/BushGuildMemberManager.d.ts | 35 +++ .../discord.js/BushGuildMemberManager.ts | 11 - .../extensions/discord.js/BushMessageManager.d.ts | 33 +++ .../extensions/discord.js/BushMessageManager.ts | 15 -- .../extensions/discord.js/BushThreadManager.d.ts | 25 ++ src/lib/extensions/discord.js/BushThreadManager.ts | 11 - .../discord.js/BushThreadMemberManager.d.ts | 15 ++ .../discord.js/BushThreadMemberManager.ts | 14 - src/lib/index.ts | 8 - src/lib/utils/BushConstants.ts | 77 +++--- src/listeners/guild/syncUnban.ts | 4 +- src/listeners/message/autoPublisher.ts | 25 ++ src/listeners/message/automodCreate.ts | 2 +- src/listeners/message/automodUpdate.ts | 2 +- src/listeners/message/blacklistedFile.ts | 159 ++++++++++++ src/listeners/message/booster.ts | 20 ++ src/listeners/message/directMessage.ts | 44 ++++ src/listeners/message/verbose.ts | 20 ++ src/listeners/other/consoleListener.ts | 1 - 41 files changed, 1207 insertions(+), 409 deletions(-) create mode 100644 src/commands/skyblock-reborn/chooseColor.ts delete mode 100644 src/commands/skyblock-reborn/chooseColorCommand.ts create mode 100644 src/lib/badlinks.json create mode 100644 src/lib/badwords.json create mode 100644 src/lib/extensions/discord.js/BushApplicationCommandManager.d.ts delete mode 100644 src/lib/extensions/discord.js/BushApplicationCommandManager.ts create mode 100644 src/lib/extensions/discord.js/BushApplicationCommandPermissionsManager.d.ts delete mode 100644 src/lib/extensions/discord.js/BushApplicationCommandPermissionsManager.ts create mode 100644 src/lib/extensions/discord.js/BushClientEvents.d.ts create mode 100644 src/lib/extensions/discord.js/BushGuildApplicationCommandManager.d.ts delete mode 100644 src/lib/extensions/discord.js/BushGuildApplicationCommandManager.ts create mode 100644 src/lib/extensions/discord.js/BushGuildEmojiRoleManager.d.ts delete mode 100644 src/lib/extensions/discord.js/BushGuildEmojiRoleManager.ts create mode 100644 src/lib/extensions/discord.js/BushGuildMemberManager.d.ts delete mode 100644 src/lib/extensions/discord.js/BushGuildMemberManager.ts create mode 100644 src/lib/extensions/discord.js/BushMessageManager.d.ts delete mode 100644 src/lib/extensions/discord.js/BushMessageManager.ts create mode 100644 src/lib/extensions/discord.js/BushThreadManager.d.ts delete mode 100644 src/lib/extensions/discord.js/BushThreadManager.ts create mode 100644 src/lib/extensions/discord.js/BushThreadMemberManager.d.ts delete mode 100644 src/lib/extensions/discord.js/BushThreadMemberManager.ts create mode 100644 src/listeners/message/autoPublisher.ts create mode 100644 src/listeners/message/blacklistedFile.ts create mode 100644 src/listeners/message/booster.ts create mode 100644 src/listeners/message/directMessage.ts create mode 100644 src/listeners/message/verbose.ts (limited to 'src') diff --git a/src/commands/dev/eval.ts b/src/commands/dev/eval.ts index abdf2b9..4f6a293 100644 --- a/src/commands/dev/eval.ts +++ b/src/commands/dev/eval.ts @@ -86,10 +86,8 @@ export default class EvalCommand extends BushCommand { config = client.config, members = message.guild?.members, roles = message.guild?.roles, - client = client, emojis = util.emojis, colors = util.colors, - util = util, { ActivePunishment, Global, Guild, Level, ModLog, StickyRole } = await import('@lib'), { ButtonInteraction, diff --git a/src/commands/info/avatar.ts b/src/commands/info/avatar.ts index dc10f7d..4f7449b 100644 --- a/src/commands/info/avatar.ts +++ b/src/commands/info/avatar.ts @@ -43,9 +43,8 @@ export default class AvatarCommand extends BushCommand { const embed = new MessageEmbed() .setTimestamp() .setColor(util.colors.default) - .setTitle(user.tag) + .setTitle(`${user.tag}'s Avatar`) .setImage(user.avatarURL({ size: 2048, format: 'png', dynamic: true })); - await message.util.reply({ embeds: [embed] }); } } diff --git a/src/commands/info/guildInfo.ts b/src/commands/info/guildInfo.ts index e82a5fe..577086b 100644 --- a/src/commands/info/guildInfo.ts +++ b/src/commands/info/guildInfo.ts @@ -1,8 +1,7 @@ import { Argument, Constants } from 'discord-akairo'; -import { Guild, GuildPreview, MessageEmbed, Snowflake, Vanity } from 'discord.js'; +import { BaseGuildVoiceChannel, Guild, GuildPreview, MessageEmbed, Snowflake, Vanity } from 'discord.js'; import { BushCommand, BushMessage, BushSlashMessage } from '../../lib'; -// TODO: Implement regions and security export default class GuildInfoCommand extends BushCommand { public constructor() { super('guildInfo', { @@ -58,9 +57,9 @@ export default class GuildInfoCommand extends BushCommand { const guild: Guild | GuildPreview = (args?.guild as Guild | GuildPreview) || (message.guild as Guild); const emojis: string[] = []; const guildAbout: string[] = []; - // const guildSecurity = []; - if (['516977525906341928', '784597260465995796', '717176538717749358', '767448775450820639'].includes(guild.id)) - emojis.push(client.consts.mappings.otherEmojis.BUSH_VERIFIED); + const guildSecurity = []; + const verifiedGuilds = Object.values(client.consts.mappings.guilds); + if (verifiedGuilds.includes(guild.id)) emojis.push(client.consts.mappings.otherEmojis.BUSH_VERIFIED); if (!isPreview && guild instanceof Guild) { if (guild.premiumTier) emojis.push(client.consts.mappings.otherEmojis['BOOST_' + guild.premiumTier]); @@ -91,21 +90,29 @@ export default class GuildInfoCommand extends BushCommand { .size.toLocaleString()}` ]; - // TODO add guild regions - // const guildRegions = []; + const guildRegions = []; + guild.channels.cache.forEach((channel) => { + if (!channel.type.includes('VOICE')) return; + else if (!guildRegions.includes((channel as BaseGuildVoiceChannel).rtcRegion ?? 'automatic')) { + guildRegions.push((channel as BaseGuildVoiceChannel).rtcRegion ?? 'automatic'); + } + }); guildAbout.push( `**Owner:** ${guild.members.cache.get(guild.ownerId)?.user.tag}`, - `**Created** ${guild.createdAt.toLocaleString()}`, - `**Members:** ${guild.memberCount.toLocaleString()}`, - `**Online:** ${guild.approximatePresenceCount?.toLocaleString()}`, - `**Channels:** ${guild.channels.cache.size} (${channelTypes.join(', ')})`, - `**Emojis:** ${guild.emojis.cache.size.toLocaleString()}` - // `**Region:** ${guildRegions.join()}` + `**Created** ${guild.createdAt.toLocaleString()} (${util.dateDelta(guild.createdAt)})`, + `**Members:** ${guild.memberCount.toLocaleString() ?? 0}`, + `**Online:** ${guild.approximatePresenceCount?.toLocaleString() ?? 0}`, + `**Channels:** ${guild.channels.cache.size?.toLocaleString() ?? 0} (${channelTypes.join(', ')})`, + `**Emojis:** ${guild.emojis.cache.size?.toLocaleString() ?? 0}`, + `**Stickers:** ${guild.stickers.cache.size?.toLocaleString() ?? 0}`, + `**Regions:** ${guildRegions.map((region) => client.consts.mappings.regions[region] || region).join(', ')}` ); if (guild.premiumSubscriptionCount) guildAbout.push( - `**Boosts:** Level ${guild.premiumTier.slice(0, 4)} with ${guild.premiumSubscriptionCount ?? 0} boosts` + `**Boosts:** Level ${guild.premiumTier == 'NONE' ? '0' : guild.premiumTier[5]} with ${ + guild.premiumSubscriptionCount ?? 0 + } boosts` ); if (guild.me?.permissions.has('MANAGE_GUILD') && guild.vanityURLCode) { const vanityInfo: Vanity = await guild.fetchVanityData(); @@ -115,12 +122,22 @@ export default class GuildInfoCommand extends BushCommand { ); } - // guildSecurity.push; + guildSecurity.push( + `**Verification Level**: ${guild.verificationLevel.toLowerCase().replace(/_/g, ' ')}`, + `**Explicit Content Filter:** ${guild.explicitContentFilter.toLowerCase().replace(/_/g, ' ')}`, + `**Default Message Notifications:** ${ + typeof guild.defaultMessageNotifications === 'string' + ? guild.defaultMessageNotifications.toLowerCase().replace(/_/g, ' ') + : guild.defaultMessageNotifications + }`, + `**2FA Required**: ${guild.mfaLevel === 'ELEVATED' ? 'yes' : 'no'}` + ); } else { guildAbout.push( `**Members:** ${guild.approximateMemberCount?.toLocaleString()}`, `**Online:** ${guild.approximatePresenceCount?.toLocaleString()}`, - `**Emojis:** ${(guild as GuildPreview).emojis.size}` + `**Emojis:** ${(guild as GuildPreview).emojis.size?.toLocaleString() ?? 0}` + // `**Stickers:** ${(guild as GuildPreview).stickers.size}` ); } @@ -160,11 +177,11 @@ export default class GuildInfoCommand extends BushCommand { if (guildIcon) { guildInfoEmbed.setThumbnail(guildIcon); } - // if (!isPreview) { - // guildInfoEmbed.addField('» Security', guildSecurity.join('\n')); - // } + if (!isPreview) { + guildInfoEmbed.addField('» Security', guildSecurity.join('\n')); + } if (emojis) { - guildInfoEmbed.setDescription(emojis.join(' ')); + guildInfoEmbed.setDescription('\u200B' /*zero width space*/ + emojis.join(' ')); } return await message.util.reply({ embeds: [guildInfoEmbed] }); } diff --git a/src/commands/info/userInfo.ts b/src/commands/info/userInfo.ts index 87235a9..e36e92b 100644 --- a/src/commands/info/userInfo.ts +++ b/src/commands/info/userInfo.ts @@ -1,6 +1,5 @@ import { BushCommand, BushMessage, BushSlashMessage } from '@lib'; import { GuildMember, MessageEmbed } from 'discord.js'; -import moment from 'moment'; // TODO: Allow looking up a user not in the guild and not cached // TODO: Re-Implement Status Emojis @@ -78,11 +77,11 @@ export default class UserInfoCommand extends BushCommand { if (user.premiumSinceTimestamp) emojis.push(client.consts.mappings.otherEmojis.BOOSTER); const createdAt = user.user.createdAt.toLocaleString(), - createdAtDelta = moment(moment(user.user.createdAt).diff(moment())).toLocaleString(), + createdAtDelta = util.dateDelta(user.user.createdAt), joinedAt = user.joinedAt?.toLocaleString(), - joinedAtDelta = moment(user.joinedAt)?.diff(moment()).toLocaleString(), + joinedAtDelta = util.dateDelta(user.joinedAt, 2), premiumSince = user.premiumSince?.toLocaleString(), - premiumSinceDelta = moment(user.premiumSince)?.diff(moment()).toLocaleString(); + premiumSinceDelta = util.dateDelta(user.premiumSince, 2); // General Info const generalInfo = [ @@ -101,12 +100,12 @@ export default class UserInfoCommand extends BushCommand { if (premiumSince) serverUserInfo.push(`**Boosting Since:** ${premiumSince} (${premiumSinceDelta} ago)`); if (user.displayHexColor) serverUserInfo.push(`**Display Color:** ${user.displayHexColor}`); if (user.id == '322862723090219008' && message.guild.id == client.consts.mappings.guilds.bush) - serverUserInfo.push(`**General Deletions:** 2`); + serverUserInfo.push(`**General Deletions:** 1⅓`); if ( ['384620942577369088', '496409778822709251'].includes(user.id) && message.guild.id == client.consts.mappings.guilds.bush ) - serverUserInfo.push(`**General Deletions:** 1`); + serverUserInfo.push(`**General Deletions:** ⅓`); if (user.nickname) serverUserInfo.push(`**Nickname** ${user.nickname}`); if (serverUserInfo.length) userEmbed.addField('» Server Info', serverUserInfo.join('\n')).setColor(user.displayColor || util.colors.default); @@ -128,10 +127,11 @@ export default class UserInfoCommand extends BushCommand { if (user.presence.clientStatus) devices = Object.keys(user.presence.clientStatus); const presenceInfo = []; if (user.presence.status) presenceInfo.push(`**Status:** ${user.presence.status}`); - if (devices) presenceInfo.push(`**${devices.length - 1 ? 'Devices' : 'Device'}:** ${util.oxford(devices, 'and', '')}`); + if (devices && devices.length) + presenceInfo.push(`**${devices.length - 1 ? 'Devices' : 'Device'}:** ${util.oxford(devices, 'and', '')}`); if (activitiesNames.length) presenceInfo.push(`**Activit${activitiesNames.length - 1 ? 'ies' : 'y'}:** ${util.oxford(activitiesNames, 'and', '')}`); - if (customStatus) presenceInfo.push(`**Custom Status:** ${customStatus}`); + if (customStatus && customStatus.length) presenceInfo.push(`**Custom Status:** ${customStatus}`); userEmbed.addField('» Presence', presenceInfo.join('\n')); } @@ -148,7 +148,7 @@ export default class UserInfoCommand extends BushCommand { } if (perms.length) userEmbed.addField('» Important Perms', perms.join(' ')); - if (emojis) userEmbed.setDescription('​' /*zero width space*/ + emojis.join(' ')); + if (emojis) userEmbed.setDescription('\u200B' /*zero width space*/ + emojis.join(' ')); return await message.util.reply({ embeds: [userEmbed] }); } diff --git a/src/commands/moderation/slowmode.ts b/src/commands/moderation/slowmode.ts index f9ffbab..9b0d300 100644 --- a/src/commands/moderation/slowmode.ts +++ b/src/commands/moderation/slowmode.ts @@ -1,6 +1,6 @@ -import { BushCommand, BushMessage, BushSlashMessage } from '@lib'; -import { Argument, Constants } from 'discord-akairo'; -import { TextChannel, ThreadChannel } from 'discord.js'; +import { BushCommand, BushMessage, BushNewsChannel, BushSlashMessage, BushTextChannel, BushThreadChannel } from '@lib'; +import { Argument } from 'discord-akairo'; +import { NewsChannel, TextChannel, ThreadChannel } from 'discord.js'; export default class SlowModeCommand extends BushCommand { public constructor() { @@ -25,8 +25,7 @@ export default class SlowModeCommand extends BushCommand { }, { id: 'channel', - type: Constants.ArgumentTypes.CHANNEL, - match: Constants.ArgumentMatches.PHRASE, + type: 'channel', prompt: { start: 'What channel would you like to change?', retry: '{error} Choose a valid channel.', @@ -51,12 +50,18 @@ export default class SlowModeCommand extends BushCommand { public async exec( message: BushMessage | BushSlashMessage, - { length, channel }: { length: number | 'off' | 'none' | 'disable'; channel: TextChannel | ThreadChannel } + { + length, + channel + }: { + length: number | 'off' | 'none' | 'disable'; + channel: TextChannel | ThreadChannel | BushTextChannel | BushNewsChannel | BushThreadChannel | NewsChannel; + } ): Promise { if (message.channel.type === 'DM') return await message.util.reply(`${util.emojis.error} This command cannot be run in dms.`); - if (!channel) channel = message.channel as ThreadChannel | TextChannel; - if (!(channel instanceof TextChannel) || !(channel instanceof ThreadChannel)) + if (!channel) channel = message.channel; + if (!(channel instanceof TextChannel) && !(channel instanceof ThreadChannel)) return await message.util.reply(`${util.emojis.error} <#${channel.id}> is not a text or thread channel.`); if (length) { length = diff --git a/src/commands/skyblock-reborn/chooseColor.ts b/src/commands/skyblock-reborn/chooseColor.ts new file mode 100644 index 0000000..2b72301 --- /dev/null +++ b/src/commands/skyblock-reborn/chooseColor.ts @@ -0,0 +1,179 @@ +import { AllowedMentions, BushCommand, BushGuildMember, BushMessage, BushSlashMessage } from '@lib'; +import { Constants } from 'discord-akairo'; +import { CommandInteraction, Role, RoleResolvable, Snowflake } from 'discord.js'; + +const roleColorMap = [ + { + name: 'Brown', + value: '840952499883737108' + }, + { + name: 'Dark Red', + value: '840952434574229546' + }, + { + name: 'Red', + value: '840952208552230913' + }, + { + name: 'Pink', + value: '840952722681364531' + }, + { + name: 'Hot Pink', + value: '840952638309007412' + }, + { + name: 'Yellow', + value: '840952282598473778' + }, + { + name: 'Gold', + value: '840952256764313610' + }, + { + name: 'Light Green', + value: '846394838744170517' + }, + { + name: 'Green', + value: '840952308702642206' + }, + { + name: 'Sea Green', + value: '840952901853511690' + }, + { + name: 'Forest Green', + value: '840952382510858260' + }, + { + name: 'Dark Green', + value: '840952336339042315' + }, + { + name: 'Blue', + value: '840952833200750682' + }, + { + name: 'Dark Blue', + value: '840952875734532137' + }, + { + name: 'Blurple', + value: '853037502188617778' + }, + { + name: 'Wizard Purple', + value: '840952750816755723' + }, + { + name: 'White', + value: '840953158276743208' + }, + { + name: 'Dark Mode', + value: '840953434785710110' + }, + { + name: 'Black', + value: '840953275326660629' + } +]; +export default class ChooseColorCommand extends BushCommand { + public constructor() { + super('chooseColor', { + aliases: ['choosecolor'], + category: 'Skyblock: Reborn', + description: { + content: 'Choose a color.', + usage: 'color ', + examples: ['report IRONM00N'] + }, + args: [ + { + id: 'color', + type: 'role', + match: Constants.ArgumentMatches.REST, + prompt: { + start: 'Please choose a valid color.', + retry: `{error} Provide what did they do wrong.`, + optional: true + } + } + ], + clientPermissions: ['EMBED_LINKS', 'SEND_MESSAGES', 'MANAGE_ROLES'], + channel: 'guild', + restrictedGuilds: ['839287012409999391'], + slash: true, + slashGuilds: ['839287012409999391'], + slashOptions: [ + { + name: 'color', + description: 'The color you would like to have.', + type: 'STRING', + choices: roleColorMap, + required: true + } + ] + }); + } + + public async exec(message: BushMessage | BushSlashMessage, args: { color: Role | RoleResolvable }): Promise { + if (message.guild.id != client.consts.mappings.guilds.sbr) { + return await message.util.reply(`${util.emojis.error} This command can only be run in Skyblock: Reborn.`); + } + const allowedRoles: Snowflake[] = [ + '839317526395879449', //Server Booster + '840949387534008360' //Mega Donator + ]; + + if ( + !( + allowedRoles.some((role) => (message.member as BushGuildMember).roles.cache.has(role)) || + (message.member as BushGuildMember).permissions.has('ADMINISTRATOR') || + message.guild.ownerId === message.author.id + ) + ) { + const allowed = util.oxford( + allowedRoles.map((id) => `<@&${id}>s`), + 'and', + '' + ); + return await message.util.reply({ + content: `${util.emojis.error} Only ${allowed} can use this command.`, + allowedMentions: AllowedMentions.none(), + ephemeral: true + }); + } + if (message.util.isSlash) await (message.interaction as CommandInteraction).defer(); + // new Array( + // roleColorMap.map(obj => obj.name.toLowerCase()), + // roleColorMap.map(obj => obj.value) + // ); + const colorID = message.util.isSlash ? (args.color as string) : (args.color as Role).id; + if (!roleColorMap.map((obj) => obj.value).includes(colorID)) { + return await message.util.reply({ + content: `${util.emojis.error} ${args.color} is not a whitelisted color role.`, + allowedMentions: AllowedMentions.none() + }); + } + const memberColorRoles = (message.member as BushGuildMember).roles.cache.filter((role) => + roleColorMap.map((obj) => obj.value).includes(role.id) + ); + + await (message.member as BushGuildMember).roles.add(args.color, 'Choose Color Command.'); + + if (memberColorRoles.size) { + memberColorRoles.forEach( + (role) => (message.member as BushGuildMember).roles.remove(role), + 'Removing Duplicate Color Roles.' + ); + } + + return await message.util.reply({ + content: `${util.emojis.success} Assigned you the <@&${colorID}> role.`, + allowedMentions: AllowedMentions.none() + }); + } +} diff --git a/src/commands/skyblock-reborn/chooseColorCommand.ts b/src/commands/skyblock-reborn/chooseColorCommand.ts deleted file mode 100644 index 0138e36..0000000 --- a/src/commands/skyblock-reborn/chooseColorCommand.ts +++ /dev/null @@ -1,179 +0,0 @@ -import { AllowedMentions, BushCommand, BushGuildMember, BushMessage, BushSlashMessage } from '@lib'; -import { Constants } from 'discord-akairo'; -import { CommandInteraction, Role, RoleResolvable, Snowflake } from 'discord.js'; - -const roleColorMap = [ - { - name: 'Brown', - value: '840952499883737108' - }, - { - name: 'Dark Red', - value: '840952434574229546' - }, - { - name: 'Red', - value: '840952208552230913' - }, - { - name: 'Pink', - value: '840952722681364531' - }, - { - name: 'Hot Pink', - value: '840952638309007412' - }, - { - name: 'Yellow', - value: '840952282598473778' - }, - { - name: 'Gold', - value: '840952256764313610' - }, - { - name: 'Light Green', - value: '846394838744170517' - }, - { - name: 'Green', - value: '840952308702642206' - }, - { - name: 'Sea Green', - value: '840952901853511690' - }, - { - name: 'Forest Green', - value: '840952382510858260' - }, - { - name: 'Dark Green', - value: '840952336339042315' - }, - { - name: 'Blue', - value: '840952833200750682' - }, - { - name: 'Dark Blue', - value: '840952875734532137' - }, - { - name: 'Blurple', - value: '853037502188617778' - }, - { - name: 'Wizard Purple', - value: '840952750816755723' - }, - { - name: 'White', - value: '840953158276743208' - }, - { - name: 'Dark Mode', - value: '840953434785710110' - }, - { - name: 'Black', - value: '840953275326660629' - } -]; -export default class ChooseColorCommand extends BushCommand { - public constructor() { - super('chooseColor', { - aliases: ['choosecolor'], - category: 'Skyblock: Reborn', - description: { - content: 'Choose a color.', - usage: 'color ', - examples: ['report IRONM00N'] - }, - args: [ - { - id: 'color', - type: Constants.ArgumentTypes.ROLE, - match: Constants.ArgumentMatches.REST, - prompt: { - start: 'Please choose a valid color.', - retry: `{error} Provide what did they do wrong.`, - optional: true - } - } - ], - clientPermissions: ['EMBED_LINKS', 'SEND_MESSAGES'], - channel: 'guild', - restrictedGuilds: ['839287012409999391'], - slash: true, - slashGuilds: ['839287012409999391'], - slashOptions: [ - { - name: 'color', - description: 'The color you would like to have.', - type: 'STRING', - choices: roleColorMap, - required: true - } - ] - }); - } - - public async exec(message: BushMessage | BushSlashMessage, args: { color: Role | RoleResolvable }): Promise { - if (message.guild.id != client.consts.mappings.guilds.sbr) { - return await message.util.reply(`${util.emojis.error} This command can only be run in Skyblock: Reborn.`); - } - const allowedRoles: Snowflake[] = [ - '839317526395879449', //Server Booster - '840949387534008360' //Mega Donator - ]; - - if ( - !( - allowedRoles.some((role) => (message.member as BushGuildMember).roles.cache.has(role)) || - (message.member as BushGuildMember).permissions.has('ADMINISTRATOR') || - message.guild.ownerId === message.author.id - ) - ) { - const allowed = util.oxford( - allowedRoles.map((id) => `<@&${id}>s`), - 'and', - '' - ); - return await message.util.reply({ - content: `${util.emojis.error} Only ${allowed} can use this command.`, - allowedMentions: AllowedMentions.none(), - ephemeral: true - }); - } - if (message.util.isSlash) await (message.interaction as CommandInteraction).defer(); - // new Array( - // roleColorMap.map(obj => obj.name.toLowerCase()), - // roleColorMap.map(obj => obj.value) - // ); - const colorID = message.util.isSlash ? (args.color as string) : (args.color as Role).id; - if (!roleColorMap.map((obj) => obj.value).includes(colorID)) { - return await message.util.reply({ - content: `${util.emojis.error} ${args.color} is not a whitelisted color role.`, - allowedMentions: AllowedMentions.none() - }); - } - const memberColorRoles = (message.member as BushGuildMember).roles.cache.filter((role) => - roleColorMap.map((obj) => obj.value).includes(role.id) - ); - - await (message.member as BushGuildMember).roles.add(args.color, 'Choose Color Command.'); - - if (memberColorRoles.size) { - memberColorRoles.forEach( - (role) => (message.member as BushGuildMember).roles.remove(role), - 'Removing Duplicate Color Roles.' - ); - } - - return await message.util.reply({ - content: `${util.emojis.success} Assigned you the <@&${colorID}> role.`, - allowedMentions: AllowedMentions.none() - }); - } -} diff --git a/src/lib/badlinks.json b/src/lib/badlinks.json new file mode 100644 index 0000000..f010bc3 --- /dev/null +++ b/src/lib/badlinks.json @@ -0,0 +1,289 @@ +[ + "streammcomunnity.ru", + "stceamcomminity.com", + "steamcommnuninty.com", + "steamcommnunily.com", + "steamncommuniity.com", + "steamcommuniiy.ru", + "steamcomnumity.ru", + "steamoemmunity.com", + "streancommunuty.ru", + "streamcommuninnity.com", + "streamcomnumity.ru", + "stemcommunnilty.com", + "steamsupportpowered.icu", + "staemcomrnunity.store", + "steam-trades.icu", + "facecup.fun", + "fatown.net", + "ultracup.fun", + "iemcup.com", + "esea-mdl.com", + "uspringcup.com", + "denforapasi.cf", + "streamcommulinty.com", + "csskill.com", + "csgo-gifts.com", + "eplcups.com", + "tf2market.store", + "gamerich.xyz", + "anomalygiveaways.pro", + "casefire.fun", + "fineleague.fun", + "stearmcommunnitty.online", + "stearncomminuty.ru", + "stiemcommunitty.ru", + "strearmcommunity.ru", + "steancomunnity.ru", + "cloud9team.space", + "streancommunuty.ru", + "strearmcomunity.ru", + "stermccommunitty.ru", + "steamcommunytu.ru", + "streamcomunity.com", + "steamncommunity.com", + "steamcommunily.uno", + "acercup.com", + "xgamercup.com", + "lootxmarket.com", + "roll4tune.com", + "fivetown.net", + "giveavvay.com", + "stermcommuniity.com", + "skinxinfo.net", + "bit-skins.ru", + "aladdinhub.fun", + "allskinz.xyz", + "ano-skinspin.xyz", + "anomalyknifes.xyz", + "anomalyskin.xyz", + "anomalyskinz.xyz", + "anoskinzz.xyz", + "berrygamble.com", + "bitknife.xyz", + "bitskines.ru", + "challengeme.vip", + "challengeme.in", + "challengme.ru", + "cmepure.com", + "cmskillcup.com", + "counterpaid.xyz", + "counterspin.top", + "counterstrikegift.xyz", + "cs-beast.xyz", + "cs-lucky.xyz", + "cs-pill.xyz", + "cs-prizeskins.xyz", + "cs-prizeskinz.xyz", + "cs-simpleroll.xyz", + "cs-skinz.xyz", + "cs-smoke.xyz", + "cs-spinz.xyz", + "cs-victory.xyz", + "csallskin.xyz", + "csbuyskins.in", + "cscoat.eu", + "csgo-analyst.com", + "csgo-cash.eu", + "csgo-steamanalyst.net", + "csgo-swapskin.com", + "csgo-trade.net", + "csgo-up.com", + "csgobeats.com", + "csgocase.one", + "csgocashs.com", + "csgocheck.ru", + "csgocompetive.com", + "csgodetails.info", + "csgodreamer.com", + "csgodrs.com", + "csgoelite.xyz", + "csgoencup.com", + "csgoevent.xyz", + "csgoindex.ru", + "csgoitemdetails.com", + "csgoitemsprices.com", + "csgoko.tk", + "csgomarble.xyz", + "csgomarketplace.net", + "csgomarkets.net", + "csgoprocupgo.com", + "csgorcup.com", + "csgorose.com", + "csgoroyalskins1.com", + "csgoskill.ru", + "csgoskinprices.com", + "csgoskinsinfo.com", + "csgoskinsroll.com", + "csgosteamanalysis.com", + "csgosteamanalyst.ru", + "csgoteammate.gq", + "csgothunby.com", + "csgotrades.net", + "csgovip.ru", + "csgoxgiveaway.ru", + "csgozone.net.in", + "csgunskins.xyz", + "csmoneyskinz.xyz", + "csmvcecup.com", + "csprices.in", + "csskillpro.xyz", + "csskinz.xyz", + "cstournament.ru", + "csxrnoney.com", + "cybergamearena.ru", + "d2cups.com", + "d2faceit.com", + "deamonbets.ru", + "demonbets.ru", + "diablobets.com", + "doatgiveaway.top", + "dopeskins.com", + "dota2fight.ru", + "dota2fight.net", + "dota2giveaway.top", + "dota2giveaways.top", + "dotafights.vip", + "dotagiveaway.win", + "earnskinz.xyz", + "emeraldbets.ru", + "esportgaming.ru", + "event-games4roll.com", + "exchangeuritems.gq", + "extraskinscs.xyz", + "ezwin24.ru", + "faceiteasyleague.ru", + "fireopencase.com", + "free-skins.ru", + "game4roll.com", + "gameluck.ru", + "games-roll.ru", + "games-roll.ml", + "games-roll.ga", + "giveawayskin.com", + "global-skins.gq", + "globalcsskins.xyz", + "globalskins.tk", + "goldendota.com", + "goodskins.gq", + "gosteamanalyst.com", + "gtakey.ru", + "hellgiveaway.trade", + "hltvcsgo.com", + "hltvgames.net", + "knifespin.top", + "knifespin.xyz", + "knifespin.top", + "knifespins.xyz", + "knifez-roll.xyz", + "knifez-win.xyz", + "league-csgo.com", + "lehatop-01.ru", + "loungeztrade.com", + "lucky-skins.xyz", + "makson-gta.ru", + "maxskins.xyz", + "mvcsgo.com", + "mvpcup.ru", + "mvptournament.com", + "mygames4roll.com", + "night-skins.com", + "ownerbets.com", + "playerskinz.xyz", + "rangskins.com", + "roll-skins.ru", + "roll4knife.xyz", + "rollknfez.xyz", + "rollskin-simple.xyz", + "csgo-market.ru.com", + "sakuralive.ru.com", + "csgocupp.ru.com", + "csgoeasywin.ru.com", + "csgocybersport.ru.com", + "csgocheck.ru.com", + "csgo-market.ru.com", + "csgoindex.ru.com", + "rushbskins.xyz", + "rushskins.xyz", + "s1mple-spin.xyz", + "simple-knifez.xyz", + "simple-win.xyz", + "simplegamepro.ru", + "simpleroll-cs.xyz", + "simplespinz.xyz", + "simplewinz.xyz", + "skin-index.com", + "skin888trade.com", + "skincs-spin.xyz", + "skincs-spin.top", + "skinmarkets.net", + "skins-hub.top", + "skins-info.net", + "skins-jungle.xyz", + "skinsboost.ru", + "skinsdatabse.com", + "skinsind.com", + "skinsmind.ru", + "skinspace.ru", + "skinsplane.com", + "skinsplanes.com", + "skinsplanets.com", + "skinxmarket.site", + "skinz-spin.top", + "skinz-spin.xyz", + "skinzjar.ru", + "skinzprize.xyz", + "skinzspin-cs.xyz", + "skinzspinz.xyz", + "spin-games.com", + "spin4skinzcs.top", + "spin4skinzcs.xyz", + "spinforskin.ml", + "sponsored-simple.xyz", + "staffstatsgo.com", + "starrygamble.com", + "stat-csgo.ru", + "stats-cs.ru", + "steam-analyst.ru", + "steamanalysts.com", + "steamgamesroll.ru", + "stewie2k-giveaway-150days.pro", + "sunnygamble.com", + "swapskins.live", + "test-domuin2.com", + "test-domuin3.ru", + "test-domuin4.ru", + "test-domuin5.ru", + "tournamentt.com", + "waterbets.ru", + "ultimateskins.xyz", + "win-skin.top", + "win-skin.xyz", + "winknifespin.xyz", + "winskin-simple.xyz", + "winskins.top", + "wintheskin.xyz", + "steemcommnunity.ru", + "steamcomminytu.ru", + "stearncommunity.ru", + "stearncommunytiy.ru", + "steamcommutiny.com", + "steamcomrunity.com", + "steamcommunytiu.ru", + "steamcommnuntiy.com", + "steamcomminytiu.ru", + "steamcomminytiu.com", + "steancomunyiti.ru", + "steamcormmuntiy.com", + "store-stempowered.com", + "dlscord.store", + "streamcommuunnity.com", + "steamcommunityw.com", + "steamconmunlty.com", + "steamcommrutiny.ru", + "dlscord.info", + "steamcomnmuituy.com", + "steamcommunityu.com", + "dicsord.gifts", + "discod.gift" +] diff --git a/src/lib/badwords.json b/src/lib/badwords.json new file mode 100644 index 0000000..94c854f --- /dev/null +++ b/src/lib/badwords.json @@ -0,0 +1,15 @@ +{ + "nigger": 3, + "nigga": 3, + "retard": 2, + "retarted": 2, + "faggot": 2, + "slut": 1, + "whore": 1, + "卍": 3, + "found a cool software that improves the": 3, + "hi, bro h am leaving cs:go and giving away my skin": 3, + "hi friend, today i am leaving this fucking game": 3, + "hi guys, i'm leaving this fucking game, take my": 3, + "you can choose any skin for yourself": 3 +} diff --git a/src/lib/extensions/discord-akairo/BushClient.ts b/src/lib/extensions/discord-akairo/BushClient.ts index 10db18d..54b5250 100644 --- a/src/lib/extensions/discord-akairo/BushClient.ts +++ b/src/lib/extensions/discord-akairo/BushClient.ts @@ -1,6 +1,7 @@ import chalk from 'chalk'; import { AkairoClient } from 'discord-akairo'; import { + Collection, Guild, Intents, InteractionReplyOptions, @@ -31,6 +32,7 @@ import { BushCache } from '../../utils/BushCache'; import { BushConstants } from '../../utils/BushConstants'; import { BushLogger } from '../../utils/BushLogger'; import { Config } from '../../utils/Config'; +import { BushApplicationCommand } from '../discord.js/BushApplicationCommand'; import { BushButtonInteraction } from '../discord.js/BushButtonInteraction'; import { BushCategoryChannel } from '../discord.js/BushCategoryChannel'; import { BushCommandInteraction } from '../discord.js/BushCommandInteraction'; @@ -42,6 +44,7 @@ import { BushMessage } from '../discord.js/BushMessage'; import { BushMessageReaction } from '../discord.js/BushMessageReaction'; import { BushNewsChannel } from '../discord.js/BushNewsChannel'; import { BushPresence } from '../discord.js/BushPresence'; +import { BushReactionEmoji } from '../discord.js/BushReactionEmoji'; import { BushRole } from '../discord.js/BushRole'; import { BushSelectMenuInteraction } from '../discord.js/BushSelectMenuInteraction'; import { BushStoreChannel } from '../discord.js/BushStoreChannel'; @@ -66,6 +69,15 @@ export type BushThreadMemberResolvable = BushThreadMember | BushUserResolvable; export type BushUserResolvable = BushUser | Snowflake | BushMessage | BushGuildMember | BushThreadMember; export type BushGuildMemberResolvable = BushGuildMember | BushUserResolvable; export type BushRoleResolvable = BushRole | Snowflake; +export type BushMessageResolvable = BushMessage | Snowflake; +export type BushEmojiResolvable = Snowflake | BushGuildEmoji | BushReactionEmoji; +export type BushEmojiIdentifierResolvable = string | BushEmojiResolvable; +export type BushThreadChannelResolvable = BushThreadChannel | Snowflake; +export type BushApplicationCommandResolvable = BushApplicationCommand | Snowflake; +export interface BushFetchedThreads { + threads: Collection; + hasMore?: boolean; +} const rl = readline.createInterface({ input: process.stdin, diff --git a/src/lib/extensions/discord-akairo/BushClientUtil.ts b/src/lib/extensions/discord-akairo/BushClientUtil.ts index ebac9eb..926a529 100644 --- a/src/lib/extensions/discord-akairo/BushClientUtil.ts +++ b/src/lib/extensions/discord-akairo/BushClientUtil.ts @@ -38,7 +38,10 @@ import { } from 'discord.js'; import got from 'got'; import humanizeDuration from 'humanize-duration'; +import moment from 'moment'; import { inspect, InspectOptions, promisify } from 'util'; +import _badLinks from '../../badlinks.json'; // Stolen from https://github.com/nacrt/SkyblockClient-REPO/blob/main/files/scamlinks.json +import badWords from '../../badwords.json'; import { ActivePunishment, ActivePunishmentType } from '../../models/ActivePunishment'; import { BushNewsChannel } from '../discord.js/BushNewsChannel'; import { BushTextChannel } from '../discord.js/BushTextChannel'; @@ -752,8 +755,13 @@ export class BushClientUtil extends ClientUtil { return typeMap[type]; } - public humanizeDuration(duration: number): string { - return humanizeDuration(duration, { language: 'en', maxDecimalPoints: 2 }); + public humanizeDuration(duration: number, largest?: number): string { + if (largest) return humanizeDuration(duration, { language: 'en', maxDecimalPoints: 2, largest }); + else return humanizeDuration(duration, { language: 'en', maxDecimalPoints: 2 }); + } + + public dateDelta(date: Date, largest?: number) { + return this.humanizeDuration(moment(date).diff(moment()), largest ?? 3); } public async findUUID(player: string): Promise { @@ -790,8 +798,78 @@ export class BushClientUtil extends ClientUtil { /* eslint-enable @typescript-eslint/no-unused-vars */ public async automod(message: BushMessage) { - const autoModPhases = await message.guild.getSetting('autoModPhases'); - if (autoModPhases.includes(message.content.toString()) && message.deletable) return await message.delete(); + if (message.guild.id !== client.consts.mappings.guilds.bush) return; // just temporary + /* await message.guild.getSetting('autoModPhases'); */ + const badLinks = _badLinks.map((link) => { + return { [link]: 3 }; + }); + + const wordArray = [...Object.keys(badWords), ...Object.keys(badLinks)]; + const offences: { [key: string]: number } = {}; + wordArray.forEach((word) => { + if (message.content?.toLowerCase().replace(/ /g, '').includes(word.toLowerCase().replace(/ /g, ''))) { + if (offences[word]) offences[word] = wordArray[word]; + } + }); + if (!Object.keys(offences)?.length) return; + + const highestOffence = Object.values(offences).sort((a, b) => b - a)[0]; + + switch (highestOffence) { + case 0: { + if (message.deletable) void message.delete(); + break; + } + case 1: { + if (message.deletable) void message.delete(); + void message.member.warn({ + moderator: message.guild.me, + reason: 'Saying a blacklisted word.' + }); + break; + } + case 2: { + if (message.deletable) void message.delete(); + void message.member.mute({ + moderator: message.guild.me, + reason: 'Saying a blacklisted word.', + duration: 900_000 // 15 minutes + }); + break; + } + case 3: { + if (message.deletable) void message.delete(); + void message.member.mute({ + moderator: message.guild.me, + reason: 'Saying a blacklisted word.', + duration: 0 // perm + }); + break; + } + } + + const color = + highestOffence === 0 + ? util.colors.lightGray + : highestOffence === 1 + ? util.colors.yellow + : highestOffence === 2 + ? util.colors.orange + : util.colors.red; + void (message.guild.channels.cache.get('783088333055066212') as TextChannel).send({ + embeds: [ + new MessageEmbed() + .setTitle(`[Severity ${highestOffence}] Automod Action Performed`) + .setDescription( + `**User:** ${message.author} (${message.author.tag})\n**Blacklisted Words:** ${util + .surroundArray(Object.keys(offences), '`') + .join()}` + ) + .addField('Message Content', `${this.codeblock(message.content, 1024)}`) + .setColor(color) + .setTimestamp() + ] + }); } public capitalizeFirstLetter(string: string): string { diff --git a/src/lib/extensions/discord-akairo/BushCommand.ts b/src/lib/extensions/discord-akairo/BushCommand.ts index 0127a59..3f79aeb 100644 --- a/src/lib/extensions/discord-akairo/BushCommand.ts +++ b/src/lib/extensions/discord-akairo/BushCommand.ts @@ -78,7 +78,7 @@ export interface BushArgumentOptions extends BaseBushArgumentOptions { type?: BushArgumentType; } export interface CustomBushArgumentOptions extends BaseBushArgumentOptions { - type?: ArgumentTypeCaster | (string | string[])[] | RegExp | string; + customType?: ArgumentTypeCaster | (string | string[])[] | RegExp | string; } export interface BushCommandOptions extends CommandOptions { @@ -122,6 +122,11 @@ export class BushCommand extends Command { this.restrictedChannels = options.restrictedChannels; this.restrictedGuilds = options.restrictedGuilds; this.completelyHide = options.completelyHide; + if (options.args && typeof options.args !== 'function') { + options.args.forEach((arg: BushArgumentOptions | CustomBushArgumentOptions) => { + if (arg['customType']) arg.type = arg['customType']; + }); + } } public exec(message: BushMessage, args: any): any; diff --git a/src/lib/extensions/discord.js/BushApplicationCommandManager.d.ts b/src/lib/extensions/discord.js/BushApplicationCommandManager.d.ts new file mode 100644 index 0000000..0e071ff --- /dev/null +++ b/src/lib/extensions/discord.js/BushApplicationCommandManager.d.ts @@ -0,0 +1,43 @@ +import { ApplicationCommandData, CachedManager, Collection, FetchApplicationCommandOptions, Snowflake } from 'discord.js'; +import { BushApplicationCommandResolvable, BushClient } from '../discord-akairo/BushClient'; +import { BushApplicationCommand } from './BushApplicationCommand'; +import { BushApplicationCommandPermissionsManager } from './BushApplicationCommandPermissionsManager'; +import { BushGuildResolvable } from './BushCommandInteraction'; + +export class BushApplicationCommandManager< + ApplicationCommandType = BushApplicationCommand<{ guild: BushGuildResolvable }>, + PermissionsOptionsExtras = { guild: BushGuildResolvable }, + PermissionsGuildType = null +> extends CachedManager { + public constructor(client: BushClient, iterable?: Iterable); + public declare readonly client: BushClient; + public permissions: BushApplicationCommandPermissionsManager< + { command?: BushApplicationCommandResolvable } & PermissionsOptionsExtras, + { command: BushApplicationCommandResolvable } & PermissionsOptionsExtras, + PermissionsOptionsExtras, + PermissionsGuildType, + null + >; + private commandPath({ id, guildId }: { id?: Snowflake; guildId?: Snowflake }): unknown; + public create(command: ApplicationCommandData): Promise; + public create(command: ApplicationCommandData, guildId: Snowflake): Promise; + public delete(command: BushApplicationCommandResolvable, guildId?: Snowflake): Promise; + public edit(command: BushApplicationCommandResolvable, data: ApplicationCommandData): Promise; + public edit( + command: BushApplicationCommandResolvable, + data: ApplicationCommandData, + guildId: Snowflake + ): Promise; + public fetch( + id: Snowflake, + options: FetchApplicationCommandOptions & { guildId: Snowflake } + ): Promise; + public fetch(id: Snowflake, options?: FetchApplicationCommandOptions): Promise; + public fetch( + id?: Snowflake, + options?: FetchApplicationCommandOptions + ): Promise>; + public set(commands: ApplicationCommandData[]): Promise>; + public set(commands: ApplicationCommandData[], guildId: Snowflake): Promise>; + private static transformCommand(command: ApplicationCommandData): unknown; +} diff --git a/src/lib/extensions/discord.js/BushApplicationCommandManager.ts b/src/lib/extensions/discord.js/BushApplicationCommandManager.ts deleted file mode 100644 index a8abb6f..0000000 --- a/src/lib/extensions/discord.js/BushApplicationCommandManager.ts +++ /dev/null @@ -1,26 +0,0 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ -import { ApplicationCommandManager, GuildResolvable, Snowflake } from 'discord.js'; -import { BushClient } from '../discord-akairo/BushClient'; -import { BushApplicationCommand } from './BushApplicationCommand'; -import { BushApplicationCommandPermissionsManager } from './BushApplicationCommandPermissionsManager'; -import { BushGuildResolvable } from './BushCommandInteraction'; - -export type BushApplicationCommandResolvable = BushApplicationCommand | Snowflake; - -export class BushApplicationCommandManager< - ApplicationCommandType = BushApplicationCommand<{ guild: BushGuildResolvable }>, - PermissionsOptionsExtras = { guild: GuildResolvable }, - PermissionsGuildType = null -> extends ApplicationCommandManager { - public declare permissions: BushApplicationCommandPermissionsManager< - { command?: BushApplicationCommandResolvable } & PermissionsOptionsExtras, - { command: BushApplicationCommandResolvable } & PermissionsOptionsExtras, - PermissionsOptionsExtras, - PermissionsGuildType, - null - >; - - public constructor(client: BushClient, iterable?: Iterable) { - super(client, iterable); - } -} diff --git a/src/lib/extensions/discord.js/BushApplicationCommandPermissionsManager.d.ts b/src/lib/extensions/discord.js/BushApplicationCommandPermissionsManager.d.ts new file mode 100644 index 0000000..443fee2 --- /dev/null +++ b/src/lib/extensions/discord.js/BushApplicationCommandPermissionsManager.d.ts @@ -0,0 +1,54 @@ +import { + ApplicationCommand, + ApplicationCommandManager, + ApplicationCommandPermissionData, + ApplicationCommandPermissions, + BaseManager, + Collection, + GuildApplicationCommandManager, + GuildApplicationCommandPermissionData, + Snowflake +} from 'discord.js'; +import { BushClient, BushRoleResolvable, BushUserResolvable } from '../discord-akairo/BushClient'; + +export class BushApplicationCommandPermissionsManager< + BaseOptions, + FetchSingleOptions, + FullPermissionsOptions, + GuildType, + CommandIdType +> extends BaseManager { + public constructor(manager: ApplicationCommandManager | GuildApplicationCommandManager | ApplicationCommand); + public declare readonly client: BushClient; + public commandId: CommandIdType; + public guild: GuildType; + public guildId: Snowflake | null; + public manager: ApplicationCommandManager | GuildApplicationCommandManager | ApplicationCommand; + public add( + options: FetchSingleOptions & { permissions: ApplicationCommandPermissionData[] } + ): Promise; + public has(options: FetchSingleOptions & { permissionId: BushUserResolvable | BushRoleResolvable }): Promise; + public fetch(options: FetchSingleOptions): Promise; + public fetch(options: BaseOptions): Promise>; + public remove( + options: + | (FetchSingleOptions & { + users: BushUserResolvable | BushUserResolvable[]; + roles?: BushRoleResolvable | BushRoleResolvable[]; + }) + | (FetchSingleOptions & { + users?: BushUserResolvable | BushUserResolvable[]; + roles: BushRoleResolvable | BushRoleResolvable[]; + }) + ): Promise; + public set( + options: FetchSingleOptions & { permissions: ApplicationCommandPermissionData[] } + ): Promise; + public set( + options: FullPermissionsOptions & { + fullPermissions: GuildApplicationCommandPermissionData[]; + } + ): Promise>; + private permissionsPath(guildId: Snowflake, commandId?: Snowflake): unknown; + private static transformPermissions(permissions: ApplicationCommandPermissionData, received?: boolean): unknown; +} diff --git a/src/lib/extensions/discord.js/BushApplicationCommandPermissionsManager.ts b/src/lib/extensions/discord.js/BushApplicationCommandPermissionsManager.ts deleted file mode 100644 index 3a98833..0000000 --- a/src/lib/extensions/discord.js/BushApplicationCommandPermissionsManager.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { - ApplicationCommand, - ApplicationCommandManager, - ApplicationCommandPermissionsManager, - GuildApplicationCommandManager -} from 'discord.js'; -import { BushClient } from '../discord-akairo/BushClient'; -import { BushApplicationCommand } from './BushApplicationCommand'; -import { BushApplicationCommandManager } from './BushApplicationCommandManager'; -import { BushGuildApplicationCommandManager } from './BushGuildApplicationCommandManager'; - -export class BushApplicationCommandPermissionsManager< - BaseOptions, - FetchSingleOptions, - FullPermissionsOptions, - GuildType, - CommandIdType -> extends ApplicationCommandPermissionsManager< - BaseOptions, - FetchSingleOptions, - FullPermissionsOptions, - GuildType, - CommandIdType -> { - public declare client: BushClient; - public declare manager: BushApplicationCommandManager | BushGuildApplicationCommandManager | BushApplicationCommand; - - public constructor(manager: ApplicationCommandManager | GuildApplicationCommandManager | ApplicationCommand) { - super(manager); - } -} diff --git a/src/lib/extensions/discord.js/BushClientEvents.d.ts b/src/lib/extensions/discord.js/BushClientEvents.d.ts new file mode 100644 index 0000000..6c1fec5 --- /dev/null +++ b/src/lib/extensions/discord.js/BushClientEvents.d.ts @@ -0,0 +1,6 @@ +import { ClientEvents } from 'discord.js'; +import { BushMessage } from './BushMessage'; + +export interface BushClientEvents extends ClientEvents { + messageCreate: [message: BushMessage]; +} diff --git a/src/lib/extensions/discord.js/BushGuild.ts b/src/lib/extensions/discord.js/BushGuild.ts index 9d618ec..dd41dad 100644 --- a/src/lib/extensions/discord.js/BushGuild.ts +++ b/src/lib/extensions/discord.js/BushGuild.ts @@ -1,12 +1,13 @@ import { Guild, User } from 'discord.js'; -import { ModLogType } from '../..'; +import { BushGuildMember, ModLogType } from '../..'; import { Guild as GuildDB, GuildModel } from '../../models/Guild'; import { BushClient, BushUserResolvable } from '../discord-akairo/BushClient'; +import { BushGuildMemberManager } from './BushGuildMemberManager'; export class BushGuild extends Guild { public declare readonly client: BushClient; - // I cba to do this - //// public declare members: GuildMemberManager; + public declare readonly me: BushGuildMember | null; + public declare members: BushGuildMemberManager; public constructor(client: BushClient, data: unknown) { super(client, data); } diff --git a/src/lib/extensions/discord.js/BushGuildApplicationCommandManager.d.ts b/src/lib/extensions/discord.js/BushGuildApplicationCommandManager.d.ts new file mode 100644 index 0000000..c0400ce --- /dev/null +++ b/src/lib/extensions/discord.js/BushGuildApplicationCommandManager.d.ts @@ -0,0 +1,18 @@ +/* eslint-disable @typescript-eslint/ban-types */ +import { ApplicationCommandData, BaseFetchOptions, Collection, Snowflake } from 'discord.js'; +import { BushApplicationCommandResolvable, BushClient } from '../discord-akairo/BushClient'; +import { BushApplicationCommand } from './BushApplicationCommand'; +import { BushApplicationCommandManager } from './BushApplicationCommandManager'; +import { BushGuild } from './BushGuild'; + +export class BushGuildApplicationCommandManager extends BushApplicationCommandManager { + public constructor(guild: BushGuild, iterable?: Iterable); + public declare readonly client: BushClient; + public guild: BushGuild; + public create(command: ApplicationCommandData): Promise; + public delete(command: BushApplicationCommandResolvable): Promise; + public edit(command: BushApplicationCommandResolvable, data: ApplicationCommandData): Promise; + public fetch(id: Snowflake, options?: BaseFetchOptions): Promise; + public fetch(id?: undefined, options?: BaseFetchOptions): Promise>; + public set(commands: ApplicationCommandData[]): Promise>; +} diff --git a/src/lib/extensions/discord.js/BushGuildApplicationCommandManager.ts b/src/lib/extensions/discord.js/BushGuildApplicationCommandManager.ts deleted file mode 100644 index 3dd79a4..0000000 --- a/src/lib/extensions/discord.js/BushGuildApplicationCommandManager.ts +++ /dev/null @@ -1,10 +0,0 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ -import { GuildApplicationCommandManager } from 'discord.js'; -import { BushGuild } from './BushGuild'; - -export class BushGuildApplicationCommandManager extends GuildApplicationCommandManager { - public declare guild: BushGuild; - public constructor(guild: BushGuild, iterable?: Iterable) { - super(guild, iterable); - } -} diff --git a/src/lib/extensions/discord.js/BushGuildEmojiRoleManager.d.ts b/src/lib/extensions/discord.js/BushGuildEmojiRoleManager.d.ts new file mode 100644 index 0000000..6e36292 --- /dev/null +++ b/src/lib/extensions/discord.js/BushGuildEmojiRoleManager.d.ts @@ -0,0 +1,19 @@ +import { Collection, DataManager, Snowflake } from 'discord.js'; +import { BushClient, BushRoleResolvable } from '../discord-akairo/BushClient'; +import { BushGuild } from './BushGuild'; +import { BushGuildEmoji } from './BushGuildEmoji'; +import { BushRole } from './BushRole'; + +export class BushGuildEmojiRoleManager extends DataManager { + public constructor(emoji: BushGuildEmoji); + public declare readonly client: BushClient; + public emoji: BushGuildEmoji; + public guild: BushGuild; + public add( + roleOrRoles: BushRoleResolvable | readonly BushRoleResolvable[] | Collection + ): Promise; + public set(roles: readonly BushRoleResolvable[] | Collection): Promise; + public remove( + roleOrRoles: BushRoleResolvable | readonly BushRoleResolvable[] | Collection + ): Promise; +} diff --git a/src/lib/extensions/discord.js/BushGuildEmojiRoleManager.ts b/src/lib/extensions/discord.js/BushGuildEmojiRoleManager.ts deleted file mode 100644 index 00afb25..0000000 --- a/src/lib/extensions/discord.js/BushGuildEmojiRoleManager.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { Collection, GuildEmojiRoleManager, Snowflake } from 'discord.js'; -import { BushGuild } from './BushGuild'; -import { BushGuildEmoji } from './BushGuildEmoji'; -import { BushRole } from './BushRole'; - -export class BushGuildEmojiRoleManager extends GuildEmojiRoleManager { - public declare emoji: BushGuildEmoji; - public declare guild: BushGuild; - public declare cache: Collection; - public constructor(emoji: BushGuildEmoji) { - super(emoji); - } -} diff --git a/src/lib/extensions/discord.js/BushGuildMemberManager.d.ts b/src/lib/extensions/discord.js/BushGuildMemberManager.d.ts new file mode 100644 index 0000000..96b99e5 --- /dev/null +++ b/src/lib/extensions/discord.js/BushGuildMemberManager.d.ts @@ -0,0 +1,35 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { + BanOptions, + CachedManager, + Collection, + FetchMemberOptions, + FetchMembersOptions, + GuildMember, + GuildMemberEditData, + GuildPruneMembersOptions, + GuildSearchMembersOptions, + Snowflake, + User, + UserResolvable +} from 'discord.js'; +import { BushClient, BushGuildMemberResolvable, BushUserResolvable } from '../discord-akairo/BushClient'; +import { BushGuild } from './BushGuild'; +import { BushGuildMember } from './BushGuildMember'; + +export class BushGuildMemberManager extends CachedManager { + public constructor(guild: BushGuild, iterable?: Iterable); + public declare readonly client: BushClient; + public guild: BushGuild; + public ban(user: BushUserResolvable, options?: BanOptions): Promise; + public edit(user: BushUserResolvable, data: GuildMemberEditData, reason?: string): Promise; + public fetch( + options: UserResolvable | FetchMemberOptions | (FetchMembersOptions & { user: UserResolvable }) + ): Promise; + public fetch(options?: FetchMembersOptions): Promise>; + public kick(user: UserResolvable, reason?: string): Promise; + public prune(options: GuildPruneMembersOptions & { dry?: false; count: false }): Promise; + public prune(options?: GuildPruneMembersOptions): Promise; + public search(options: GuildSearchMembersOptions): Promise>; + public unban(user: UserResolvable, reason?: string): Promise; +} diff --git a/src/lib/extensions/discord.js/BushGuildMemberManager.ts b/src/lib/extensions/discord.js/BushGuildMemberManager.ts deleted file mode 100644 index dbc2da5..0000000 --- a/src/lib/extensions/discord.js/BushGuildMemberManager.ts +++ /dev/null @@ -1,11 +0,0 @@ -// /* eslint-disable @typescript-eslint/no-explicit-any */ -// import { GuildMemberManager } from 'discord.js'; -// import { BushGuild } from './BushGuild'; - -// export class BushGuildMemberManager extends GuildMemberManager { -// public guild: BushGuild; - -// public constructor(guild: BushGuild, iterable?: Iterable) { -// super(guild, iterable); -// } -// } diff --git a/src/lib/extensions/discord.js/BushMessageManager.d.ts b/src/lib/extensions/discord.js/BushMessageManager.d.ts new file mode 100644 index 0000000..bf795ad --- /dev/null +++ b/src/lib/extensions/discord.js/BushMessageManager.d.ts @@ -0,0 +1,33 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { + BaseFetchOptions, + CachedManager, + ChannelLogsQueryOptions, + Collection, + EmojiIdentifierResolvable, + MessageEditOptions, + MessagePayload, + Snowflake, + TextBasedChannelFields +} from 'discord.js'; +import { BushClient, BushMessageResolvable } from '../discord-akairo/BushClient'; +import { BushDMChannel } from './BushDMChannel'; +import { BushMessage } from './BushMessage'; +import { BushTextChannel } from './BushTextChannel'; +import { BushThreadChannel } from './BushThreadChannel'; + +export class BushMessageManager extends CachedManager { + public constructor(channel: BushTextChannel | BushDMChannel | BushThreadChannel, iterable?: Iterable); + public declare readonly client: BushClient; + public channel: TextBasedChannelFields; + public cache: Collection; + public crosspost(message: BushMessageResolvable): Promise; + public delete(message: BushMessageResolvable): Promise; + public edit(message: BushMessageResolvable, options: MessagePayload | MessageEditOptions): Promise; + public fetch(message: Snowflake, options?: BaseFetchOptions): Promise; + public fetch(options?: ChannelLogsQueryOptions, cacheOptions?: BaseFetchOptions): Promise>; + public fetchPinned(cache?: boolean): Promise>; + public react(message: BushMessageResolvable, emoji: EmojiIdentifierResolvable): Promise; + public pin(message: BushMessageResolvable): Promise; + public unpin(message: BushMessageResolvable): Promise; +} diff --git a/src/lib/extensions/discord.js/BushMessageManager.ts b/src/lib/extensions/discord.js/BushMessageManager.ts deleted file mode 100644 index 181808a..0000000 --- a/src/lib/extensions/discord.js/BushMessageManager.ts +++ /dev/null @@ -1,15 +0,0 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ -import { Collection, MessageManager, Snowflake } from 'discord.js'; -import { BushClient } from '../discord-akairo/BushClient'; -import { BushDMChannel } from './BushDMChannel'; -import { BushMessage } from './BushMessage'; -import { BushTextChannel } from './BushTextChannel'; -import { BushThreadChannel } from './BushThreadChannel'; - -export class BushMessageManager extends MessageManager { - public declare readonly client: BushClient; - public declare cache: Collection; - public constructor(channel: BushTextChannel | BushDMChannel | BushThreadChannel, iterable?: Iterable) { - super(channel, iterable); - } -} diff --git a/src/lib/extensions/discord.js/BushThreadManager.d.ts b/src/lib/extensions/discord.js/BushThreadManager.d.ts new file mode 100644 index 0000000..6b8250b --- /dev/null +++ b/src/lib/extensions/discord.js/BushThreadManager.d.ts @@ -0,0 +1,25 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { + BaseFetchOptions, + CachedManager, + FetchArchivedThreadOptions, + FetchThreadsOptions, + Snowflake, + ThreadChannelResolvable, + ThreadCreateOptions +} from 'discord.js'; +import { BushClient, BushFetchedThreads, BushThreadChannelResolvable } from '../discord-akairo/BushClient'; +import { BushNewsChannel } from './BushNewsChannel'; +import { BushTextChannel } from './BushTextChannel'; +import { BushThreadChannel } from './BushThreadChannel'; + +export class BushThreadManager extends CachedManager { + public constructor(channel: BushTextChannel | BushNewsChannel, iterable?: Iterable); + public declare readonly client: BushClient; + public channel: BushTextChannel | BushNewsChannel; + public create(options: ThreadCreateOptions): Promise; + public fetch(options: BushThreadChannelResolvable, cacheOptions?: BaseFetchOptions): Promise; + public fetch(options?: FetchThreadsOptions, cacheOptions?: { cache?: boolean }): Promise; + public fetchArchived(options?: FetchArchivedThreadOptions, cache?: boolean): Promise; + public fetchActive(cache?: boolean): Promise; +} diff --git a/src/lib/extensions/discord.js/BushThreadManager.ts b/src/lib/extensions/discord.js/BushThreadManager.ts deleted file mode 100644 index 50eaa2d..0000000 --- a/src/lib/extensions/discord.js/BushThreadManager.ts +++ /dev/null @@ -1,11 +0,0 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ -import { ThreadManager } from 'discord.js'; -import { BushNewsChannel } from './BushNewsChannel'; -import { BushTextChannel } from './BushTextChannel'; - -export class BushThreadManager extends ThreadManager { - public declare channel: BushTextChannel | BushNewsChannel; - public constructor(channel: BushTextChannel | BushNewsChannel, iterable?: Iterable) { - super(channel, iterable); - } -} diff --git a/src/lib/extensions/discord.js/BushThreadMemberManager.d.ts b/src/lib/extensions/discord.js/BushThreadMemberManager.d.ts new file mode 100644 index 0000000..ba9b90b --- /dev/null +++ b/src/lib/extensions/discord.js/BushThreadMemberManager.d.ts @@ -0,0 +1,15 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +/* eslint-disable @typescript-eslint/no-empty-interface */ +import { CachedManager, Collection, Snowflake, ThreadChannel, ThreadMember, UserResolvable } from 'discord.js'; +import { BushClient, BushThreadMemberResolvable } from '../discord-akairo/BushClient'; +import { BushThreadChannel } from './BushThreadChannel'; +import { BushThreadMember } from './BushThreadMember'; + +export class BushThreadMemberManager extends CachedManager { + public constructor(thread: BushThreadChannel, iterable?: Iterable); + public declare readonly client: BushClient; + public thread: ThreadChannel; + public add(member: UserResolvable | '@me', reason?: string): Promise; + public fetch(cache?: boolean): Promise>; + public remove(id: Snowflake | '@me', reason?: string): Promise; +} diff --git a/src/lib/extensions/discord.js/BushThreadMemberManager.ts b/src/lib/extensions/discord.js/BushThreadMemberManager.ts deleted file mode 100644 index e585ee7..0000000 --- a/src/lib/extensions/discord.js/BushThreadMemberManager.ts +++ /dev/null @@ -1,14 +0,0 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ -/* eslint-disable @typescript-eslint/no-empty-interface */ -import { ThreadMemberManager } from 'discord.js'; -import { BushClient } from '../discord-akairo/BushClient'; -import { BushThreadChannel } from './BushThreadChannel'; - -export class BushThreadMemberManager extends ThreadMemberManager { - public declare thread: BushThreadChannel; - public declare readonly client: BushClient; - - public constructor(thread: BushThreadChannel, iterable?: Iterable) { - super(thread, iterable); - } -} diff --git a/src/lib/index.ts b/src/lib/index.ts index 73cee56..1e789e5 100644 --- a/src/lib/index.ts +++ b/src/lib/index.ts @@ -13,22 +13,16 @@ export * from './extensions/discord-akairo/BushTask'; export * from './extensions/discord-akairo/BushTaskHandler'; export * from './extensions/discord.js/BushActivity'; export * from './extensions/discord.js/BushApplicationCommand'; -export * from './extensions/discord.js/BushApplicationCommandManager'; -expor