diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/commands/dev/eval.ts | 11 | ||||
-rw-r--r-- | src/commands/utilities/viewraw.ts | 33 | ||||
-rw-r--r-- | src/lib/extensions/discord-akairo/BushClientUtil.ts | 27 | ||||
-rw-r--r-- | src/lib/extensions/discord.js/BushApplicationCommandManager.d.ts | 19 | ||||
-rw-r--r-- | src/lib/extensions/discord.js/BushChannel.d.ts | 3 | ||||
-rw-r--r-- | src/lib/extensions/discord.js/BushCommandInteraction.ts | 4 | ||||
-rw-r--r-- | src/lib/extensions/discord.js/BushGuildMember.ts | 38 | ||||
-rw-r--r-- | src/lib/extensions/discord.js/BushGuildMemberManager.d.ts | 2 | ||||
-rw-r--r-- | src/listeners/client/interactionCreate.ts | 11 | ||||
-rw-r--r-- | src/listeners/message/automodCreate.ts | 6 | ||||
-rw-r--r-- | src/tasks/removeExpiredPunishements.ts | 2 |
11 files changed, 117 insertions, 39 deletions
diff --git a/src/commands/dev/eval.ts b/src/commands/dev/eval.ts index 19667dd..5b44db2 100644 --- a/src/commands/dev/eval.ts +++ b/src/commands/dev/eval.ts @@ -22,6 +22,11 @@ export default class EvalCommand extends BushCommand { { id: 'typescript', match: 'flag', flag: '--ts' }, { id: 'hidden', match: 'flag', flag: '--hidden' }, { id: 'show_proto', match: 'flag', flag: '--proto' }, + // { + // id: 'show_methods', + // match: 'flag', + // flag: ['--func', '--function', '--functions', '--meth', '--method', '--methods'] + // }, { id: 'code', match: 'rest', @@ -38,6 +43,7 @@ export default class EvalCommand extends BushCommand { { name: 'typescript', description: 'Whether or not the code is typescript.', type: 'BOOLEAN', required: false }, { name: 'hidden', description: 'Whether or not to show hidden items.', type: 'BOOLEAN', required: false }, { name: 'show_proto', description: 'Show prototype.', type: 'BOOLEAN', required: false } + // { name: 'show_methods', description: 'Show class functions.', type: 'BOOLEAN', required: false } ], ownerOnly: true }); @@ -54,6 +60,7 @@ export default class EvalCommand extends BushCommand { typescript: boolean; hidden: boolean; show_proto: boolean; + // show_methods: boolean; } ): Promise<unknown> { if (!message.author.isOwner()) @@ -114,11 +121,12 @@ export default class EvalCommand extends BushCommand { try { const rawOutput = code[code.lang].replace(/ /g, '').includes('9+10' || '10+9') ? '21' : await eval(code.js); const output = await util.inspectCleanRedactCodeblock(rawOutput, 'js', { - depth: args.sel_depth || 0, + depth: args.sel_depth ?? 0, showHidden: args.hidden, getters: true, showProxy: true }); + // const methods = args.show_methods ? await util.inspectCleanRedactCodeblock(util.getMethods(rawOutput), 'js') : undefined; const proto = args.show_proto ? await util.inspectCleanRedactCodeblock(Object.getPrototypeOf(rawOutput), 'js', { depth: 1, @@ -131,6 +139,7 @@ export default class EvalCommand extends BushCommand { if (inputTS) embed.addField('📥 Input (typescript)', inputTS).addField('📥 Input (transpiled javascript)', inputJS); else embed.addField('📥 Input', inputJS); embed.addField('📤 Output', output); + // if (methods) embed.addField('🔧 Methods', methods); if (proto) embed.addField('⚙️ Proto', proto); } catch (e) { embed.setTitle(`${emojis.errorFull} Code was not able to be evaluated.`).setColor(colors.error); diff --git a/src/commands/utilities/viewraw.ts b/src/commands/utilities/viewraw.ts index 0a5f9e2..e783dec 100644 --- a/src/commands/utilities/viewraw.ts +++ b/src/commands/utilities/viewraw.ts @@ -31,12 +31,17 @@ export default class ViewRawCommand extends BushCommand { retry: '{error} Choose a valid channel.', optional: true }, - default: (m) => m.channel + default: (m: Message) => m.channel }, { id: 'json', match: 'flag', flag: '--json' + }, + { + id: 'js', + match: 'flag', + flag: '--js' } ] }); @@ -44,7 +49,7 @@ export default class ViewRawCommand extends BushCommand { public override async exec( message: BushMessage | BushSlashMessage, - args: { message: Message | BigInt; channel: TextChannel | NewsChannel | DMChannel; json?: boolean } + args: { message: Message | BigInt; channel: TextChannel | NewsChannel | DMChannel; json?: boolean; js: boolean } ): Promise<unknown> { let newMessage: Message | 0; if (!(typeof args.message === 'object')) { @@ -59,14 +64,24 @@ export default class ViewRawCommand extends BushCommand { } else { newMessage = args.message as Message; } - const content = args.json ? inspect(newMessage.toJSON()) || '[No Content]' : newMessage.content || '[No Content]'; - const messageEmbed = new MessageEmbed() - .setFooter(newMessage.author.tag, newMessage.author.avatarURL({ dynamic: true })) - .setTimestamp(newMessage.createdTimestamp) - .setColor(newMessage.member?.roles?.color?.color || util.colors.default) - .setTitle('Raw Message Information') - .setDescription(await util.codeblock(content, 2048, 'js')); + + const messageEmbed = await ViewRawCommand.getRawData(newMessage as BushMessage, { json: args.json, js: args.js }); return await message.util.reply({ embeds: [messageEmbed] }); } + + public static async getRawData(message: BushMessage, options: { json?: boolean; js: boolean }): Promise<unknown> { + const content = + options.json || options.js + ? options.json + ? inspect(JSON.stringify(message.toJSON())) + : inspect(message.toJSON()) || '[No Content]' + : message.content || '[No Content]'; + return new MessageEmbed() + .setFooter(message.author.tag, message.author.avatarURL({ dynamic: true })) + .setTimestamp(message.createdTimestamp) + .setColor(message.member?.roles?.color?.color || util.colors.default) + .setTitle('Raw Message Information') + .setDescription(await util.codeblock(content, 2048, 'js')); + } } diff --git a/src/lib/extensions/discord-akairo/BushClientUtil.ts b/src/lib/extensions/discord-akairo/BushClientUtil.ts index 2a01f6a..4f9f09b 100644 --- a/src/lib/extensions/discord-akairo/BushClientUtil.ts +++ b/src/lib/extensions/discord-akairo/BushClientUtil.ts @@ -1371,4 +1371,31 @@ export class BushClientUtil extends ClientUtil { public async sleep(s: number): Promise<unknown> { return new Promise((resolve) => setTimeout(resolve, s * 1000)); } + + // modified from https://stackoverflow.com/questions/31054910/get-functions-methods-of-a-class + // answer by Bruno Grieder + // public getMethods(obj: any): string { + // let props = []; + + // do { + // const l = Object.getOwnPropertyNames(obj) + // .concat(Object.getOwnPropertySymbols(obj).map((s) => s.toString())) + // .sort() + // .filter( + // (p, i, arr) => + // typeof obj[p] === 'function' && //only the methods + // p !== 'constructor' && //not the constructor + // (i == 0 || p !== arr[i - 1]) && //not overriding in this prototype + // props.indexOf(p) === -1 //not overridden in a child + // ); + // props = props.concat( + // l /* .map((p) => (obj[p] && obj[p][Symbol.toStringTag] === 'AsyncFunction' ? 'async ' : '' + p + '();')) */ + // ); + // } while ( + // (obj = Object.getPrototypeOf(obj)) && //walk-up the prototype chain + // Object.getPrototypeOf(obj) //not the the Object prototype methods (hasOwnProperty, etc...) + // ); + + // return props.join('\n'); + // } } diff --git a/src/lib/extensions/discord.js/BushApplicationCommandManager.d.ts b/src/lib/extensions/discord.js/BushApplicationCommandManager.d.ts index 8eec9a7..fb4f84c 100644 --- a/src/lib/extensions/discord.js/BushApplicationCommandManager.d.ts +++ b/src/lib/extensions/discord.js/BushApplicationCommandManager.d.ts @@ -1,17 +1,16 @@ import { APIApplicationCommand } from 'discord-api-types'; import { ApplicationCommandData, CachedManager, Collection, FetchApplicationCommandOptions, Snowflake } from 'discord.js'; -import { RawApplicationCommandData } from 'discord.js/typings/rawDataTypes'; 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 }>, + ApplicationCommandScope = BushApplicationCommand<{ guild: BushGuildResolvable }>, PermissionsOptionsExtras = { guild: BushGuildResolvable }, PermissionsGuildType = null -> extends CachedManager<Snowflake, ApplicationCommandType, BushApplicationCommandResolvable> { - public constructor(client: BushClient, iterable?: Iterable<RawApplicationCommandData>); +> extends CachedManager<Snowflake, ApplicationCommandScope, BushApplicationCommandResolvable> { + public constructor(client: BushClient, iterable?: Iterable<unknown>); public permissions: BushApplicationCommandPermissionsManager< { command?: BushApplicationCommandResolvable } & PermissionsOptionsExtras, { command: BushApplicationCommandResolvable } & PermissionsOptionsExtras, @@ -20,10 +19,10 @@ export class BushApplicationCommandManager< null >; private commandPath({ id, guildId }: { id?: Snowflake; guildId?: Snowflake }): unknown; - public create(command: ApplicationCommandData): Promise<ApplicationCommandType>; + public create(command: ApplicationCommandData): Promise<ApplicationCommandScope>; public create(command: ApplicationCommandData, guildId: Snowflake): Promise<BushApplicationCommand>; - public delete(command: BushApplicationCommandResolvable, guildId?: Snowflake): Promise<ApplicationCommandType | null>; - public edit(command: BushApplicationCommandResolvable, data: ApplicationCommandData): Promise<ApplicationCommandType>; + public delete(command: BushApplicationCommandResolvable, guildId?: Snowflake): Promise<ApplicationCommandScope | null>; + public edit(command: BushApplicationCommandResolvable, data: ApplicationCommandData): Promise<ApplicationCommandScope>; public edit( command: BushApplicationCommandResolvable, data: ApplicationCommandData, @@ -33,12 +32,12 @@ export class BushApplicationCommandManager< id: Snowflake, options: FetchApplicationCommandOptions & { guildId: Snowflake } ): Promise<BushApplicationCommand>; - public fetch(id: Snowflake, options?: FetchApplicationCommandOptions): Promise<ApplicationCommandType>; + public fetch(id: Snowflake, options?: FetchApplicationCommandOptions): Promise<ApplicationCommandScope>; public fetch( id?: Snowflake, options?: FetchApplicationCommandOptions - ): Promise<Collection<Snowflake, ApplicationCommandType>>; - public set(commands: ApplicationCommandData[]): Promise<Collection<Snowflake, ApplicationCommandType>>; + ): Promise<Collection<Snowflake, ApplicationCommandScope>>; + public set(commands: ApplicationCommandData[]): Promise<Collection<Snowflake, ApplicationCommandScope>>; public set(commands: ApplicationCommandData[], guildId: Snowflake): Promise<Collection<Snowflake, BushApplicationCommand>>; private static transformCommand( command: ApplicationCommandData diff --git a/src/lib/extensions/discord.js/BushChannel.d.ts b/src/lib/extensions/discord.js/BushChannel.d.ts index 333ce06..2e465a5 100644 --- a/src/lib/extensions/discord.js/BushChannel.d.ts +++ b/src/lib/extensions/discord.js/BushChannel.d.ts @@ -3,7 +3,9 @@ import { Channel, ChannelMention } from 'discord.js'; import { ChannelTypes } from 'discord.js/typings/enums'; import { RawChannelData } from 'discord.js/typings/rawDataTypes'; import { BushClient, BushTextBasedChannels } from '../discord-akairo/BushClient'; +import { BushStageChannel } from './BushStageChannel'; import { BushThreadChannel } from './BushThreadChannel'; +import { BushVoiceChannel } from './BushVoiceChannel'; export class BushChannel extends Channel { public constructor(client: BushClient, data?: RawChannelData, immediatePatch?: boolean); @@ -16,6 +18,7 @@ export class BushChannel extends Channel { public delete(): Promise<BushChannel>; public fetch(force?: boolean): Promise<BushChannel>; public isText(): this is BushTextBasedChannels; + public isVoice(): this is BushVoiceChannel | BushStageChannel; public isThread(): this is BushThreadChannel; public toString(): ChannelMention; } diff --git a/src/lib/extensions/discord.js/BushCommandInteraction.ts b/src/lib/extensions/discord.js/BushCommandInteraction.ts index 9e30f79..56cdb75 100644 --- a/src/lib/extensions/discord.js/BushCommandInteraction.ts +++ b/src/lib/extensions/discord.js/BushCommandInteraction.ts @@ -1,5 +1,5 @@ import { APIInteractionGuildMember } from 'discord-api-types/v9'; -import { ApplicationCommand, CommandInteraction, Invite, Snowflake } from 'discord.js'; +import { CommandInteraction, Invite, Snowflake } from 'discord.js'; import { RawCommandInteractionData } from 'discord.js/typings/rawDataTypes'; import { BushClient, BushTextBasedChannels } from '../discord-akairo/BushClient'; import { BushApplicationCommand } from './BushApplicationCommand'; @@ -24,7 +24,7 @@ export class BushCommandInteraction extends CommandInteraction { super(client, data); } public declare readonly client: BushClient; - public declare readonly command: BushApplicationCommand | ApplicationCommand<{ guild: BushGuildResolvable }> | null; + public declare readonly command: BushApplicationCommand | BushApplicationCommand<{ guild: BushGuildResolvable }> | null; public declare readonly channel: BushTextBasedChannels | null; public declare readonly guild: BushGuild | null; public declare member: BushGuildMember | APIInteractionGuildMember | null; diff --git a/src/lib/extensions/discord.js/BushGuildMember.ts b/src/lib/extensions/discord.js/BushGuildMember.ts index 1606ad6..7db31c5 100644 --- a/src/lib/extensions/discord.js/BushGuildMember.ts +++ b/src/lib/extensions/discord.js/BushGuildMember.ts @@ -81,7 +81,7 @@ export class BushGuildMember extends GuildMember { } public async warn(options: BushPunishmentOptions): Promise<{ result: WarnResponse; caseNum: number }> { - const moderator = client.users.cache.get(client.users.resolveId(options.moderator || client.user)); + const moderator = client.users.cache.get(client.users.resolveId(options.moderator)) ?? client.user; // add modlog entry const result = await util.createModLogEntry( { @@ -101,7 +101,7 @@ export class BushGuildMember extends GuildMember { content: `You have been warned in **${this.guild}** for **${options.reason || 'No reason provided'}**.${ ending ? `\n\n${ending}` : '' }` - }).catch(() => null); + }).catch(() => false); if (!dmSuccess) return { result: 'failed to dm', caseNum: result.caseNum }; @@ -112,7 +112,7 @@ export class BushGuildMember extends GuildMember { const ifShouldAddRole = this.#checkIfShouldAddRole(options.role); if (ifShouldAddRole !== true) return ifShouldAddRole; - const moderator = client.users.cache.get(client.users.resolveId(options.moderator || client.user)); + const moderator = client.users.cache.get(client.users.resolveId(options.moderator)) ?? client.user; if (options.addToModlog) { const { log: modlog } = await util.createModLogEntry({ @@ -147,7 +147,7 @@ export class BushGuildMember extends GuildMember { const ifShouldAddRole = this.#checkIfShouldAddRole(options.role); if (ifShouldAddRole !== true) return ifShouldAddRole; - const moderator = client.users.cache.get(client.users.resolveId(options.moderator || client.user)); + const moderator = client.users.cache.get(client.users.resolveId(options.moderator)) ?? client.user; if (options.addToModlog) { const { log: modlog } = await util.createModLogEntry({ @@ -195,12 +195,15 @@ export class BushGuildMember extends GuildMember { if (!muteRole) return 'invalid mute role'; if (muteRole.position >= this.guild.me.roles.highest.position || muteRole.managed) return 'mute role not manageable'; - const moderator = client.users.cache.get(client.users.resolveId(options.moderator || client.user)); + const moderator = client.users.cache.get(client.users.resolveId(options.moderator)) ?? client.user; // add role const muteSuccess = await this.roles .add(muteRole, `[Mute] ${moderator.tag} | ${options.reason || 'No reason provided.'}`) - .catch(() => null); + .catch(async (e) => { + await client.console.warn('muteRoleAddError', e?.stack || e); + return false; + }); if (!muteSuccess) return 'error giving mute role'; // add modlog entry @@ -232,7 +235,7 @@ export class BushGuildMember extends GuildMember { content: `You have been muted ${ options.duration ? 'for ' + util.humanizeDuration(options.duration) : 'permanently' } in **${this.guild}** for **${options.reason || 'No reason provided'}**.${ending ? `\n\n${ending}` : ''}` - }); + }).catch(() => false); if (!dmSuccess) return 'failed to dm'; @@ -248,12 +251,15 @@ export class BushGuildMember extends GuildMember { if (!muteRole) return 'invalid mute role'; if (muteRole.position >= this.guild.me.roles.highest.position || muteRole.managed) return 'mute role not manageable'; - const moderator = client.users.cache.get(client.users.resolveId(options.moderator || client.user)); + const moderator = client.users.cache.get(client.users.resolveId(options.moderator)) ?? client.user; //remove role const muteSuccess = await this.roles .remove(muteRole, `[Unmute] ${moderator.tag} | ${options.reason || 'No reason provided.'}`) - .catch(() => null); + .catch(async (e) => { + await client.console.warn('muteRoleAddError', e?.stack || e); + return false; + }); if (!muteSuccess) return 'error removing mute role'; //remove modlog entry @@ -279,7 +285,7 @@ export class BushGuildMember extends GuildMember { //dm user const dmSuccess = await this.send({ content: `You have been unmuted in **${this.guild}** because **${options.reason || 'No reason provided'}**.` - }).catch(() => null); + }).catch(() => false); if (!dmSuccess) return 'failed to dm'; @@ -290,7 +296,7 @@ export class BushGuildMember extends GuildMember { // checks if (!this.guild.me.permissions.has('KICK_MEMBERS') || !this.kickable) return 'missing permissions'; - const moderator = client.users.cache.get(client.users.resolveId(options.moderator || client.user)); + const moderator = client.users.cache.get(client.users.resolveId(options.moderator)) ?? client.user; // dm user const ending = await this.guild.getSetting('punishmentEnding'); @@ -298,10 +304,10 @@ export class BushGuildMember extends GuildMember { content: `You have been kicked from **${this.guild}** for **${options.reason || 'No reason provided'}**.${ ending ? `\n\n${ending}` : '' }` - }).catch(() => null); + }).catch(() => false); // kick - const kickSuccess = await this.kick(`${moderator.tag} | ${options.reason || 'No reason provided.'}`).catch(() => null); + const kickSuccess = await this.kick(`${moderator.tag} | ${options.reason || 'No reason provided.'}`).catch(() => false); if (!kickSuccess) return 'error kicking'; // add modlog entry @@ -323,7 +329,7 @@ export class BushGuildMember extends GuildMember { // checks if (!this.guild.me.permissions.has('BAN_MEMBERS') || !this.bannable) return 'missing permissions'; - const moderator = client.users.cache.get(client.users.resolveId(options.moderator || client.user)); + const moderator = client.users.cache.get(client.users.resolveId(options.moderator)) ?? client.user; // dm user const ending = await this.guild.getSetting('punishmentEnding'); @@ -331,13 +337,13 @@ export class BushGuildMember extends GuildMember { content: `You have been banned ${ options.duration ? 'for ' + util.humanizeDuration(options.duration) : 'permanently' } from **${this.guild}** for **${options.reason || 'No reason provided'}**.${ending ? `\n\n${ending}` : ''}` - }).catch(() => null); + }).catch(() => false); // ban const banSuccess = await this.ban({ reason: `${moderator.tag} | ${options.reason || 'No reason provided.'}`, days: options.deleteDays - }); + }).catch(() => false); if (!banSuccess) return 'error banning'; // add modlog entry diff --git a/src/lib/extensions/discord.js/BushGuildMemberManager.d.ts b/src/lib/extensions/discord.js/BushGuildMemberManager.d.ts index cd74fff..e868b10 100644 --- a/src/lib/extensions/discord.js/BushGuildMemberManager.d.ts +++ b/src/lib/extensions/discord.js/BushGuildMemberManager.d.ts @@ -5,6 +5,7 @@ import { Collection, FetchMemberOptions, FetchMembersOptions, + GuildListMembersOptions, GuildMemberEditData, GuildPruneMembersOptions, GuildSearchMembersOptions, @@ -32,6 +33,7 @@ export class BushGuildMemberManager extends CachedManager<Snowflake, BushGuildMe ): Promise<BushGuildMember>; public fetch(options?: FetchMembersOptions): Promise<Collection<Snowflake, BushGuildMember>>; public kick(user: BushUserResolvable, reason?: string): Promise<BushGuildMember | BushUser | Snowflake>; + public list(options?: GuildListMembersOptions): Promise<Collection<Snowflake, BushGuildMember>>; public prune(options: GuildPruneMembersOptions & { dry?: false; count: false }): Promise<null>; public prune(options?: GuildPruneMembersOptions): Promise<number>; public search(options: GuildSearchMembersOptions): Promise<Collection<Snowflake, BushGuildMember>>; diff --git a/src/listeners/client/interactionCreate.ts b/src/listeners/client/interactionCreate.ts index 17249a9..e719517 100644 --- a/src/listeners/client/interactionCreate.ts +++ b/src/listeners/client/interactionCreate.ts @@ -1,5 +1,6 @@ -import { BushListener } from '@lib'; +import { BushListener, BushMessage } from '@lib'; import { ClientEvents } from 'discord.js'; +import ViewRawCommand from '../../commands/utilities/viewraw'; export default class InteractionCreateListener extends BushListener { public constructor() { @@ -32,6 +33,14 @@ export default class InteractionCreateListener extends BushListener { }.`, ephemeral: true }); + } else if (interaction.isContextMenu()) { + if (interaction.id === 'View Raw') { + const embed = await ViewRawCommand.getRawData(interaction.options.getMessage('message') as BushMessage, { + json: false, + js: false + }); + return await interaction.reply({ embeds: [embed], ephemeral: true }); + } } } } diff --git a/src/listeners/message/automodCreate.ts b/src/listeners/message/automodCreate.ts index 2584c21..c69245a 100644 --- a/src/listeners/message/automodCreate.ts +++ b/src/listeners/message/automodCreate.ts @@ -53,6 +53,7 @@ export default class AutomodMessageCreateListener extends BushListener { moderator: message.guild.me, reason: 'Saying a blacklisted word.' }); + break; } case 2: { @@ -75,6 +76,11 @@ export default class AutomodMessageCreateListener extends BushListener { } } + void client.console.info( + 'AutoMod', + `Severity <<${highestOffence}>> action performed on <<${message.author.tag}>> (<<${message.author.id}>>) in <<${message.guild.name}>>` + ); + const color = highestOffence === 0 ? util.colors.lightGray diff --git a/src/tasks/removeExpiredPunishements.ts b/src/tasks/removeExpiredPunishements.ts index 4ad1794..c079363 100644 --- a/src/tasks/removeExpiredPunishements.ts +++ b/src/tasks/removeExpiredPunishements.ts @@ -49,6 +49,7 @@ export default class RemoveExpiredPunishmentsTask extends BushTask { break; } case ActivePunishmentType.MUTE: { + if (!member) continue; const result = await member.unmute({ reason: 'Punishment expired.' }); if (['success', 'failed to dm'].includes(result)) await entry.destroy(); else throw new Error(result); @@ -56,6 +57,7 @@ export default class RemoveExpiredPunishmentsTask extends BushTask { break; } case ActivePunishmentType.ROLE: { + if (!member) continue; const role = guild?.roles?.cache?.get(entry.extraInfo); const result = await member.removeRole({ reason: 'Punishment expired.', |