From 199d413119f3656d9f2da118f91a22a3cc55f6bb Mon Sep 17 00:00:00 2001 From: TymanWasTaken <32660892+tymanwastaken@users.noreply.github.com> Date: Tue, 11 May 2021 10:52:26 -0600 Subject: whoops forgot about these --- src/commands/admin/PrefixCommand.ts | 30 ------- src/commands/admin/prefix.ts | 30 +++++++ src/commands/info/BotInfoCommand.ts | 58 ------------- src/commands/info/HelpCommand.ts | 79 ----------------- src/commands/info/PingCommand.ts | 69 --------------- src/commands/info/botinfo.ts | 58 +++++++++++++ src/commands/info/help.ts | 79 +++++++++++++++++ src/commands/info/ping.ts | 69 +++++++++++++++ src/commands/moderation/BanCommand.ts | 137 ----------------------------- src/commands/moderation/KickCommand.ts | 72 ---------------- src/commands/moderation/ModlogCommand.ts | 143 ------------------------------- src/commands/moderation/WarnCommand.ts | 54 ------------ src/commands/moderation/ban.ts | 137 +++++++++++++++++++++++++++++ src/commands/moderation/kick.ts | 72 ++++++++++++++++ src/commands/moderation/modlog.ts | 143 +++++++++++++++++++++++++++++++ src/commands/moderation/warn.ts | 54 ++++++++++++ 16 files changed, 642 insertions(+), 642 deletions(-) delete mode 100644 src/commands/admin/PrefixCommand.ts create mode 100644 src/commands/admin/prefix.ts delete mode 100644 src/commands/info/BotInfoCommand.ts delete mode 100644 src/commands/info/HelpCommand.ts delete mode 100644 src/commands/info/PingCommand.ts create mode 100644 src/commands/info/botinfo.ts create mode 100644 src/commands/info/help.ts create mode 100644 src/commands/info/ping.ts delete mode 100644 src/commands/moderation/BanCommand.ts delete mode 100644 src/commands/moderation/KickCommand.ts delete mode 100644 src/commands/moderation/ModlogCommand.ts delete mode 100644 src/commands/moderation/WarnCommand.ts create mode 100644 src/commands/moderation/ban.ts create mode 100644 src/commands/moderation/kick.ts create mode 100644 src/commands/moderation/modlog.ts create mode 100644 src/commands/moderation/warn.ts (limited to 'src/commands') diff --git a/src/commands/admin/PrefixCommand.ts b/src/commands/admin/PrefixCommand.ts deleted file mode 100644 index 8fb50f8..0000000 --- a/src/commands/admin/PrefixCommand.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { BotCommand } from '../../lib/extensions/BotCommand'; -import { BotMessage } from '../../lib/extensions/BotMessage'; - -export default class PrefixCommand extends BotCommand { - constructor() { - super('prefix', { - aliases: ['prefix'], - args: [ - { - id: 'prefix' - } - ], - userPermissions: ['MANAGE_GUILD'] - }); - } - async exec( - message: BotMessage, - { prefix }: { prefix?: string } - ): Promise { - if (prefix) { - await message.settings.setPrefix(prefix); - await message.util.send(`Sucessfully set prefix to \`${prefix}\``); - } else { - await message.settings.setPrefix(this.client.config.prefix); - await message.util.send( - `Sucessfully reset prefix to \`${this.client.config.prefix}\`` - ); - } - } -} diff --git a/src/commands/admin/prefix.ts b/src/commands/admin/prefix.ts new file mode 100644 index 0000000..8fb50f8 --- /dev/null +++ b/src/commands/admin/prefix.ts @@ -0,0 +1,30 @@ +import { BotCommand } from '../../lib/extensions/BotCommand'; +import { BotMessage } from '../../lib/extensions/BotMessage'; + +export default class PrefixCommand extends BotCommand { + constructor() { + super('prefix', { + aliases: ['prefix'], + args: [ + { + id: 'prefix' + } + ], + userPermissions: ['MANAGE_GUILD'] + }); + } + async exec( + message: BotMessage, + { prefix }: { prefix?: string } + ): Promise { + if (prefix) { + await message.settings.setPrefix(prefix); + await message.util.send(`Sucessfully set prefix to \`${prefix}\``); + } else { + await message.settings.setPrefix(this.client.config.prefix); + await message.util.send( + `Sucessfully reset prefix to \`${this.client.config.prefix}\`` + ); + } + } +} diff --git a/src/commands/info/BotInfoCommand.ts b/src/commands/info/BotInfoCommand.ts deleted file mode 100644 index 27e14c4..0000000 --- a/src/commands/info/BotInfoCommand.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { MessageEmbed } from 'discord.js'; -import { BotCommand } from '../../lib/extensions/BotCommand'; -import { duration } from 'moment'; -import { BotMessage } from '../../lib/extensions/BotMessage'; - -export default class BotInfoCommand extends BotCommand { - constructor() { - super('botinfo', { - aliases: ['botinfo'], - description: { - content: 'Shows information about the bot', - usage: 'botinfo', - examples: ['botinfo'] - } - }); - } - - public async exec(message: BotMessage): Promise { - const owners = (await this.client.util.mapIDs(this.client.ownerID)) - .map((u) => u.tag) - .join('\n'); - const currentCommit = ( - await this.client.util.shell('git rev-parse HEAD') - ).stdout.replace('\n', ''); - const repoUrl = ( - await this.client.util.shell('git remote get-url origin') - ).stdout.replace('\n', ''); - const embed = new MessageEmbed() - .setTitle('Bot Info:') - .addFields([ - { - name: 'Owners', - value: owners, - inline: true - }, - { - name: 'Uptime', - value: this.client.util.capitalize( - duration(this.client.uptime, 'milliseconds').humanize() - ) - }, - { - name: 'User count', - value: this.client.users.cache.size, - inline: true - }, - { - name: 'Current commit', - value: `[${currentCommit.substring( - 0, - 7 - )}](${repoUrl}/commit/${currentCommit})` - } - ]) - .setTimestamp(); - await message.util.send(embed); - } -} diff --git a/src/commands/info/HelpCommand.ts b/src/commands/info/HelpCommand.ts deleted file mode 100644 index 4aa45e0..0000000 --- a/src/commands/info/HelpCommand.ts +++ /dev/null @@ -1,79 +0,0 @@ -import { Message, MessageEmbed } from 'discord.js'; -import { BotCommand } from '../../lib/extensions/BotCommand'; -import { stripIndent } from 'common-tags'; -import { BotMessage } from '../../lib/extensions/BotMessage'; - -export default class HelpCommand extends BotCommand { - constructor() { - super('help', { - aliases: ['help'], - description: { - content: 'Shows the commands of the bot', - usage: 'help', - examples: ['help'] - }, - clientPermissions: ['EMBED_LINKS'], - args: [ - { - id: 'command', - type: 'commandAlias' - } - ] - }); - } - - public async exec( - message: BotMessage, - { command }: { command: BotCommand } - ): Promise { - const prefix = this.handler.prefix; - if (!command) { - const embed = new MessageEmbed() - .addField( - 'Commands', - stripIndent`A list of available commands. - For additional info on a command, type \`${prefix}help \` - ` - ) - .setFooter( - `For more information about a command use "${this.client.config.prefix}help "` - ) - .setTimestamp(); - for (const category of this.handler.categories.values()) { - embed.addField( - `${category.id.replace(/(\b\w)/gi, (lc): string => - lc.toUpperCase() - )}`, - `${category - .filter((cmd): boolean => cmd.aliases.length > 0) - .map((cmd): string => `\`${cmd.aliases[0]}\``) - .join(' ')}` - ); - } - return message.util.send(embed); - } - - const embed = new MessageEmbed() - .setColor([155, 200, 200]) - .setTitle( - `\`${command.description.usage ? command.description.usage : ''}\`` - ) - .addField( - 'Description', - `${command.description.content ? command.description.content : ''} ${ - command.ownerOnly ? '\n__Owner Only__' : '' - }` - ); - - if (command.aliases.length > 1) - embed.addField('Aliases', `\`${command.aliases.join('` `')}\``, true); - if (command.description.examples && command.description.examples.length) - embed.addField( - 'Examples', - `\`${command.description.examples.join('`\n`')}\``, - true - ); - - return message.util.send(embed); - } -} diff --git a/src/commands/info/PingCommand.ts b/src/commands/info/PingCommand.ts deleted file mode 100644 index 7f8ab6b..0000000 --- a/src/commands/info/PingCommand.ts +++ /dev/null @@ -1,69 +0,0 @@ -import { CommandInteraction } from 'discord.js'; -import { Message } from 'discord.js'; -import { MessageEmbed } from 'discord.js'; -import { BotCommand } from '../../lib/extensions/BotCommand'; -import { BotMessage } from '../../lib/extensions/BotMessage'; - -export default class PingCommand extends BotCommand { - constructor() { - super('ping', { - aliases: ['ping'], - description: { - content: 'Gets the latency of the bot', - usage: 'ping', - examples: ['ping'] - } - }); - } - - public async exec(message: BotMessage): Promise { - const sentMessage = await message.util.send('Pong!'); - const timestamp: number = message.editedTimestamp - ? message.editedTimestamp - : message.createdTimestamp; - const botLatency = `\`\`\`\n ${Math.floor( - sentMessage.createdTimestamp - timestamp - )}ms \`\`\``; - const apiLatency = `\`\`\`\n ${Math.round( - message.client.ws.ping - )}ms \`\`\``; - const embed = new MessageEmbed() - .setTitle('Pong! 🏓') - .addField('Bot Latency', botLatency, true) - .addField('API Latency', apiLatency, true) - .setFooter( - message.author.username, - message.author.displayAvatarURL({ dynamic: true }) - ) - .setTimestamp(); - await sentMessage.edit({ - content: null, - embed - }); - } - - public async execSlash(message: CommandInteraction): Promise { - const timestamp1 = message.createdTimestamp; - await message.reply('Pong!'); - const timestamp2 = await message - .fetchReply() - .then((m) => (m as Message).createdTimestamp); - const botLatency = `\`\`\`\n ${Math.floor( - timestamp2 - timestamp1 - )}ms \`\`\``; - const apiLatency = `\`\`\`\n ${Math.round(this.client.ws.ping)}ms \`\`\``; - const embed = new MessageEmbed() - .setTitle('Pong! 🏓') - .addField('Bot Latency', botLatency, true) - .addField('API Latency', apiLatency, true) - .setFooter( - message.user.username, - message.user.displayAvatarURL({ dynamic: true }) - ) - .setTimestamp(); - await message.editReply({ - content: null, - embeds: [embed] - }); - } -} diff --git a/src/commands/info/botinfo.ts b/src/commands/info/botinfo.ts new file mode 100644 index 0000000..27e14c4 --- /dev/null +++ b/src/commands/info/botinfo.ts @@ -0,0 +1,58 @@ +import { MessageEmbed } from 'discord.js'; +import { BotCommand } from '../../lib/extensions/BotCommand'; +import { duration } from 'moment'; +import { BotMessage } from '../../lib/extensions/BotMessage'; + +export default class BotInfoCommand extends BotCommand { + constructor() { + super('botinfo', { + aliases: ['botinfo'], + description: { + content: 'Shows information about the bot', + usage: 'botinfo', + examples: ['botinfo'] + } + }); + } + + public async exec(message: BotMessage): Promise { + const owners = (await this.client.util.mapIDs(this.client.ownerID)) + .map((u) => u.tag) + .join('\n'); + const currentCommit = ( + await this.client.util.shell('git rev-parse HEAD') + ).stdout.replace('\n', ''); + const repoUrl = ( + await this.client.util.shell('git remote get-url origin') + ).stdout.replace('\n', ''); + const embed = new MessageEmbed() + .setTitle('Bot Info:') + .addFields([ + { + name: 'Owners', + value: owners, + inline: true + }, + { + name: 'Uptime', + value: this.client.util.capitalize( + duration(this.client.uptime, 'milliseconds').humanize() + ) + }, + { + name: 'User count', + value: this.client.users.cache.size, + inline: true + }, + { + name: 'Current commit', + value: `[${currentCommit.substring( + 0, + 7 + )}](${repoUrl}/commit/${currentCommit})` + } + ]) + .setTimestamp(); + await message.util.send(embed); + } +} diff --git a/src/commands/info/help.ts b/src/commands/info/help.ts new file mode 100644 index 0000000..4aa45e0 --- /dev/null +++ b/src/commands/info/help.ts @@ -0,0 +1,79 @@ +import { Message, MessageEmbed } from 'discord.js'; +import { BotCommand } from '../../lib/extensions/BotCommand'; +import { stripIndent } from 'common-tags'; +import { BotMessage } from '../../lib/extensions/BotMessage'; + +export default class HelpCommand extends BotCommand { + constructor() { + super('help', { + aliases: ['help'], + description: { + content: 'Shows the commands of the bot', + usage: 'help', + examples: ['help'] + }, + clientPermissions: ['EMBED_LINKS'], + args: [ + { + id: 'command', + type: 'commandAlias' + } + ] + }); + } + + public async exec( + message: BotMessage, + { command }: { command: BotCommand } + ): Promise { + const prefix = this.handler.prefix; + if (!command) { + const embed = new MessageEmbed() + .addField( + 'Commands', + stripIndent`A list of available commands. + For additional info on a command, type \`${prefix}help \` + ` + ) + .setFooter( + `For more information about a command use "${this.client.config.prefix}help "` + ) + .setTimestamp(); + for (const category of this.handler.categories.values()) { + embed.addField( + `${category.id.replace(/(\b\w)/gi, (lc): string => + lc.toUpperCase() + )}`, + `${category + .filter((cmd): boolean => cmd.aliases.length > 0) + .map((cmd): string => `\`${cmd.aliases[0]}\``) + .join(' ')}` + ); + } + return message.util.send(embed); + } + + const embed = new MessageEmbed() + .setColor([155, 200, 200]) + .setTitle( + `\`${command.description.usage ? command.description.usage : ''}\`` + ) + .addField( + 'Description', + `${command.description.content ? command.description.content : ''} ${ + command.ownerOnly ? '\n__Owner Only__' : '' + }` + ); + + if (command.aliases.length > 1) + embed.addField('Aliases', `\`${command.aliases.join('` `')}\``, true); + if (command.description.examples && command.description.examples.length) + embed.addField( + 'Examples', + `\`${command.description.examples.join('`\n`')}\``, + true + ); + + return message.util.send(embed); + } +} diff --git a/src/commands/info/ping.ts b/src/commands/info/ping.ts new file mode 100644 index 0000000..7f8ab6b --- /dev/null +++ b/src/commands/info/ping.ts @@ -0,0 +1,69 @@ +import { CommandInteraction } from 'discord.js'; +import { Message } from 'discord.js'; +import { MessageEmbed } from 'discord.js'; +import { BotCommand } from '../../lib/extensions/BotCommand'; +import { BotMessage } from '../../lib/extensions/BotMessage'; + +export default class PingCommand extends BotCommand { + constructor() { + super('ping', { + aliases: ['ping'], + description: { + content: 'Gets the latency of the bot', + usage: 'ping', + examples: ['ping'] + } + }); + } + + public async exec(message: BotMessage): Promise { + const sentMessage = await message.util.send('Pong!'); + const timestamp: number = message.editedTimestamp + ? message.editedTimestamp + : message.createdTimestamp; + const botLatency = `\`\`\`\n ${Math.floor( + sentMessage.createdTimestamp - timestamp + )}ms \`\`\``; + const apiLatency = `\`\`\`\n ${Math.round( + message.client.ws.ping + )}ms \`\`\``; + const embed = new MessageEmbed() + .setTitle('Pong! 🏓') + .addField('Bot Latency', botLatency, true) + .addField('API Latency', apiLatency, true) + .setFooter( + message.author.username, + message.author.displayAvatarURL({ dynamic: true }) + ) + .setTimestamp(); + await sentMessage.edit({ + content: null, + embed + }); + } + + public async execSlash(message: CommandInteraction): Promise { + const timestamp1 = message.createdTimestamp; + await message.reply('Pong!'); + const timestamp2 = await message + .fetchReply() + .then((m) => (m as Message).createdTimestamp); + const botLatency = `\`\`\`\n ${Math.floor( + timestamp2 - timestamp1 + )}ms \`\`\``; + const apiLatency = `\`\`\`\n ${Math.round(this.client.ws.ping)}ms \`\`\``; + const embed = new MessageEmbed() + .setTitle('Pong! 🏓') + .addField('Bot Latency', botLatency, true) + .addField('API Latency', apiLatency, true) + .setFooter( + message.user.username, + message.user.displayAvatarURL({ dynamic: true }) + ) + .setTimestamp(); + await message.editReply({ + content: null, + embeds: [embed] + }); + } +} diff --git a/src/commands/moderation/BanCommand.ts b/src/commands/moderation/BanCommand.ts deleted file mode 100644 index 300101b..0000000 --- a/src/commands/moderation/BanCommand.ts +++ /dev/null @@ -1,137 +0,0 @@ -import { User } from 'discord.js'; -import { BotCommand } from '../../lib/extensions/BotCommand'; -import { BotMessage } from '../../lib/extensions/BotMessage'; -import { Ban, Modlog, ModlogType } from '../../lib/types/Models'; -import moment from 'moment'; - -const durationAliases: Record = { - weeks: ['w', 'weeks', 'week', 'wk', 'wks'], - days: ['d', 'days', 'day'], - hours: ['h', 'hours', 'hour', 'hr', 'hrs'], - minutes: ['m', 'min', 'mins', 'minutes', 'minute'], - months: ['mo', 'month', 'months'] -}; -const durationRegex = /(?:(\d+)(d(?:ays?)?|h(?:ours?|rs?)?|m(?:inutes?|ins?)?|mo(?:nths?)?|w(?:eeks?|ks?)?)(?: |$))/g; - -export default class PrefixCommand extends BotCommand { - constructor() { - super('ban', { - aliases: ['ban'], - args: [ - { - id: 'user', - type: 'user', - prompt: { - start: 'What user would you like to ban?', - retry: 'Invalid response. What user would you like to ban?' - } - }, - { - id: 'reason' - }, - { - id: 'time', - match: 'option', - flag: '--time' - } - ], - clientPermissions: ['BAN_MEMBERS'], - userPermissions: ['BAN_MEMBERS'] - }); - } - async exec( - message: BotMessage, - { user, reason, time }: { user: User; reason?: string; time?: string } - ): Promise { - const duration = moment.duration(); - let modlogEnry: Modlog; - let banEntry: Ban; - const translatedTime: string[] = []; - try { - try { - if (time) { - const parsed = [...time.matchAll(durationRegex)]; - if (parsed.length < 1) { - await message.util.send('Invalid time.'); - return; - } - for (const part of parsed) { - const translated = Object.keys(durationAliases).find((k) => - durationAliases[k].includes(part[2]) - ); - translatedTime.push(part[1] + ' ' + translated); - duration.add( - Number(part[1]), - translated as 'weeks' | 'days' | 'hours' | 'months' | 'minutes' - ); - } - modlogEnry = Modlog.build({ - user: user.id, - guild: message.guild.id, - reason, - type: ModlogType.TEMPBAN, - duration: duration.asMilliseconds(), - moderator: message.author.id - }); - banEntry = Ban.build({ - user: user.id, - guild: message.guild.id, - reason, - expires: new Date(new Date().getTime() + duration.asMilliseconds()), - modlog: modlogEnry.id - }); - } else { - modlogEnry = Modlog.build({ - user: user.id, - guild: message.guild.id, - reason, - type: ModlogType.BAN, - moderator: message.author.id - }); - banEntry = Ban.build({ - user: user.id, - guild: message.guild.id, - reason, - modlog: modlogEnry.id - }); - } - await modlogEnry.save(); - await banEntry.save(); - } catch (e) { - console.error(e); - await message.util.send( - 'Error saving to database. Please report this to a developer.' - ); - return; - } - try { - await user.send( - `You were banned in ${message.guild.name} ${ - translatedTime.length >= 1 - ? `for ${translatedTime.join(', ')}` - : 'permanently' - } with reason \`${reason || 'No reason given'}\`` - ); - } catch (e) { - await message.channel.send('Error sending message to user'); - } - await message.guild.members.ban(user, { - reason: `Banned by ${message.author.tag} with ${ - reason ? `reason ${reason}` : 'no reason' - }` - }); - await message.util.send( - `Banned <@!${user.id}> ${ - translatedTime.length >= 1 - ? `for ${translatedTime.join(', ')}` - : 'permanently' - } with reason \`${reason || 'No reason given'}\`` - ); - } catch { - await message.util.send('Error banning :/'); - await modlogEnry.destroy(); - await banEntry.destroy(); - return; - } - } -} diff --git a/src/commands/moderation/KickCommand.ts b/src/commands/moderation/KickCommand.ts deleted file mode 100644 index 0dc4276..0000000 --- a/src/commands/moderation/KickCommand.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { BotCommand } from '../../lib/extensions/BotCommand'; -import { BotMessage } from '../../lib/extensions/BotMessage'; -import { Modlog, ModlogType } from '../../lib/types/Models'; -import { GuildMember } from 'discord.js'; - -export default class PrefixCommand extends BotCommand { - constructor() { - super('kick', { - aliases: ['kick'], - args: [ - { - id: 'user', - type: 'member', - prompt: { - start: 'What user would you like to kick?', - retry: 'Invalid response. What user would you like to kick?' - } - }, - { - id: 'reason' - } - ], - clientPermissions: ['KICK_MEMBERS'], - userPermissions: ['KICK_MEMBERS'] - }); - } - async exec( - message: BotMessage, - { user, reason }: { user: GuildMember; reason?: string } - ): Promise { - let modlogEnry: Modlog; - try { - modlogEnry = Modlog.build({ - user: user.id, - guild: message.guild.id, - moderator: message.author.id, - type: ModlogType.KICK, - reason - }); - await modlogEnry.save(); - } catch (e) { - console.error(e); - await message.util.send( - 'Error saving to database. Please report this to a developer.' - ); - return; - } - try { - await user.send( - `You were kicked in ${message.guild.name} with reason \`${ - reason || 'No reason given' - }\`` - ); - } catch (e) { - await message.channel.send('Error sending message to user'); - } - try { - await user.kick( - `Kicked by ${message.author.tag} with ${ - reason ? `reason ${reason}` : 'no reason' - }` - ); - } catch { - await message.util.send('Error kicking :/'); - await modlogEnry.destroy(); - return; - } - await message.util.send( - `Kicked <@!${user.id}> with reason \`${reason || 'No reason given'}\`` - ); - } -} diff --git a/src/commands/moderation/ModlogCommand.ts b/src/commands/moderation/ModlogCommand.ts deleted file mode 100644 index ea35198..0000000 --- a/src/commands/moderation/ModlogCommand.ts +++ /dev/null @@ -1,143 +0,0 @@ -import { BotCommand } from '../../lib/extensions/BotCommand'; -import { Message } from 'discord.js'; -import { Modlog } from '../../lib/types/Models'; -import { MessageEmbed } from 'discord.js'; -import moment from 'moment'; -import { stripIndent } from 'common-tags'; -import { Argument } from 'discord-akairo'; - -export default class ModlogCommand extends BotCommand { - constructor() { - super('modlog', { - aliases: ['modlog', 'modlogs'], - args: [ - { - id: 'search', - prompt: { - start: 'What modlog id or user would you like to see?' - } - }, - { - id: 'page', - type: 'number' - } - ], - userPermissions: ['MANAGE_MESSAGES'] - }); - } - *args(): unknown { - const search = yield { - id: 'search', - type: Argument.union('user', 'string'), - prompt: { - start: 'What modlog id or user would you like to see?' - } - }; - if (typeof search === 'string') return { search, page: null }; - else { - const page = yield { - id: 'page', - type: 'number', - prompt: { - start: 'What page?', - retry: 'Not a number. What page?', - optional: true - } - }; - return { search, page }; - } - } - async exec( - message: Message, - { search, page }: { search: string; page: number } - ): Promise { - const foundUser = await this.client.util.resolveUserAsync(search); - if (foundUser) { - const logs = await Modlog.findAll({ - where: { - guild: message.guild.id, - user: foundUser.id - }, - order: [['createdAt', 'ASC']] - }); - const niceLogs: string[] = []; - for (const log of logs) { - niceLogs.push(stripIndent` - ID: ${log.id} - Type: ${log.type.toLowerCase()} - User: <@!${log.user}> (${log.user}) - Moderator: <@!${log.moderator}> (${log.moderator}) - Duration: ${ - log.duration - ? moment.duration(log.duration, 'milliseconds').humanize() - : 'N/A' - } - Reason: ${log.reason || 'None given'} - ${this.client.util.ordinal(logs.indexOf(log) + 1)} action - `); - } - const chunked: string[][] = this.client.util.chunk(niceLogs, 3); - const embedPages = chunked.map( - (e, i) => - new MessageEmbed({ - title: `Modlogs page ${i + 1}`, - description: e.join( - '\n-------------------------------------------------------\n' - ), - footer: { - text: `Page ${i + 1}/${chunked.length}` - } - }) - ); - if (page) { - await message.util.send(embedPages[page - 1]); - return; - } else { - await message.util.send(embedPages[0]); - return; - } - } else if (search) { - const entry = await Modlog.findByPk(search); - if (!entry) { - await message.util.send('That modlog does not exist.'); - return; - } - await message.util.send( - new MessageEmbed({ - title: `Modlog ${entry.id}`, - fields: [ - { - name: 'Type', - value: entry.type.toLowerCase(), - inline: true - }, - { - name: 'Duration', - value: `${ - entry.duration - ? moment.duration(entry.duration, 'milliseconds').humanize() - : 'N/A' - }`, - inline: true - }, - { - name: 'Reason', - value: `${entry.reason || 'None given'}`, - inline: true - }, - { - name: 'Moderator', - value: `<@!${entry.moderator}> (${entry.moderator})`, - inline: true - }, - { - name: 'User', - value: `<@!${entry.user}> (${entry.user})`, - inline: true - } - ] - }) - ); - } - } -} diff --git a/src/commands/moderation/WarnCommand.ts b/src/commands/moderation/WarnCommand.ts deleted file mode 100644 index 676615d..0000000 --- a/src/commands/moderation/WarnCommand.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { GuildMember } from 'discord.js'; -import { BotCommand } from '../../lib/extensions/BotCommand'; -import { BotMessage } from '../../lib/extensions/BotMessage'; -import { Modlog, ModlogType } from '../../lib/types/Models'; - -export default class WarnCommand extends BotCommand { - public constructor() { - super('warn', { - aliases: ['warn'], - userPermissions: ['MANAGE_MESSAGES'], - args: [ - { - id: 'member', - type: 'member' - }, - { - id: 'reason', - match: 'rest' - } - ] - }); - } - public async exec( - message: BotMessage, - { member, reason }: { member: GuildMember; reason: string } - ): Promise { - try { - const entry = Modlog.build({ - user: member.id, - guild: message.guild.id, - moderator: message.author.id, - type: ModlogType.WARN, - reason - }); - await entry.save(); - } catch (e) { - await message.util.send( - 'Error saving to database, please contact the developers' - ); - return; - } - try { - await member.send( - `You were warned in ${message.guild.name} for reason "${reason}".` - ); - } catch (e) { - await message.util.send('Error messaging user, warning still saved.'); - return; - } - await message.util.send( - `${member.user.tag} was warned for reason "${reason}".` - ); - } -} diff --git a/src/commands/moderation/ban.ts b/src/commands/moderation/ban.ts new file mode 100644 index 0000000..300101b --- /dev/null +++ b/src/commands/moderation/ban.ts @@ -0,0 +1,137 @@ +import { User } from 'discord.js'; +import { BotCommand } from '../../lib/extensions/BotCommand'; +import { BotMessage } from '../../lib/extensions/BotMessage'; +import { Ban, Modlog, ModlogType } from '../../lib/types/Models'; +import moment from 'moment'; + +const durationAliases: Record = { + weeks: ['w', 'weeks', 'week', 'wk', 'wks'], + days: ['d', 'days', 'day'], + hours: ['h', 'hours', 'hour', 'hr', 'hrs'], + minutes: ['m', 'min', 'mins', 'minutes', 'minute'], + months: ['mo', 'month', 'months'] +}; +const durationRegex = /(?:(\d+)(d(?:ays?)?|h(?:ours?|rs?)?|m(?:inutes?|ins?)?|mo(?:nths?)?|w(?:eeks?|ks?)?)(?: |$))/g; + +export default class PrefixCommand extends BotCommand { + constructor() { + super('ban', { + aliases: ['ban'], + args: [ + { + id: 'user', + type: 'user', + prompt: { + start: 'What user would you like to ban?', + retry: 'Invalid response. What user would you like to ban?' + } + }, + { + id: 'reason' + }, + { + id: 'time', + match: 'option', + flag: '--time' + } + ], + clientPermissions: ['BAN_MEMBERS'], + userPermissions: ['BAN_MEMBERS'] + }); + } + async exec( + message: BotMessage, + { user, reason, time }: { user: User; reason?: string; time?: string } + ): Promise { + const duration = moment.duration(); + let modlogEnry: Modlog; + let banEntry: Ban; + const translatedTime: string[] = []; + try { + try { + if (time) { + const parsed = [...time.matchAll(durationRegex)]; + if (parsed.length < 1) { + await message.util.send('Invalid time.'); + return; + } + for (const part of parsed) { + const translated = Object.keys(durationAliases).find((k) => + durationAliases[k].includes(part[2]) + ); + translatedTime.push(part[1] + ' ' + translated); + duration.add( + Number(part[1]), + translated as 'weeks' | 'days' | 'hours' | 'months' | 'minutes' + ); + } + modlogEnry = Modlog.build({ + user: user.id, + guild: message.guild.id, + reason, + type: ModlogType.TEMPBAN, + duration: duration.asMilliseconds(), + moderator: message.author.id + }); + banEntry = Ban.build({ + user: user.id, + guild: message.guild.id, + reason, + expires: new Date(new Date().getTime() + duration.asMilliseconds()), + modlog: modlogEnry.id + }); + } else { + modlogEnry = Modlog.build({ + user: user.id, + guild: message.guild.id, + reason, + type: ModlogType.BAN, + moderator: message.author.id + }); + banEntry = Ban.build({ + user: user.id, + guild: message.guild.id, + reason, + modlog: modlogEnry.id + }); + } + await modlogEnry.save(); + await banEntry.save(); + } catch (e) { + console.error(e); + await message.util.send( + 'Error saving to database. Please report this to a developer.' + ); + return; + } + try { + await user.send( + `You were banned in ${message.guild.name} ${ + translatedTime.length >= 1 + ? `for ${translatedTime.join(', ')}` + : 'permanently' + } with reason \`${reason || 'No reason given'}\`` + ); + } catch (e) { + await message.channel.send('Error sending message to user'); + } + await message.guild.members.ban(user, { + reason: `Banned by ${message.author.tag} with ${ + reason ? `reason ${reason}` : 'no reason' + }` + }); + await message.util.send( + `Banned <@!${user.id}> ${ + translatedTime.length >= 1 + ? `for ${translatedTime.join(', ')}` + : 'permanently' + } with reason \`${reason || 'No reason given'}\`` + ); + } catch { + await message.util.send('Error banning :/'); + await modlogEnry.destroy(); + await banEntry.destroy(); + return; + } + } +} diff --git a/src/commands/moderation/kick.ts b/src/commands/moderation/kick.ts new file mode 100644 index 0000000..0dc4276 --- /dev/null +++ b/src/commands/moderation/kick.ts @@ -0,0 +1,72 @@ +import { BotCommand } from '../../lib/extensions/BotCommand'; +import { BotMessage } from '../../lib/extensions/BotMessage'; +import { Modlog, ModlogType } from '../../lib/types/Models'; +import { GuildMember } from 'discord.js'; + +export default class PrefixCommand extends BotCommand { + constructor() { + super('kick', { + aliases: ['kick'], + args: [ + { + id: 'user', + type: 'member', + prompt: { + start: 'What user would you like to kick?', + retry: 'Invalid response. What user would you like to kick?' + } + }, + { + id: 'reason' + } + ], + clientPermissions: ['KICK_MEMBERS'], + userPermissions: ['KICK_MEMBERS'] + }); + } + async exec( + message: BotMessage, + { user, reason }: { user: GuildMember; reason?: string } + ): Promise { + let modlogEnry: Modlog; + try { + modlogEnry = Modlog.build({ + user: user.id, + guild: message.guild.id, + moderator: message.author.id, + type: ModlogType.KICK, + reason + }); + await modlogEnry.save(); + } catch (e) { + console.error(e); + await message.util.send( + 'Error saving to database. Please report this to a developer.' + ); + return; + } + try { + await user.send( + `You were kicked in ${message.guild.name} with reason \`${ + reason || 'No reason given' + }\`` + ); + } catch (e) { + await message.channel.send('Error sending message to user'); + } + try { + await user.kick( + `Kicked by ${message.author.tag} with ${ + reason ? `reason ${reason}` : 'no reason' + }` + ); + } catch { + await message.util.send('Error kicking :/'); + await modlogEnry.destroy(); + return; + } + await message.util.send( + `Kicked <@!${user.id}> with reason \`${reason || 'No reason given'}\`` + ); + } +} diff --git a/src/commands/moderation/modlog.ts b/src/commands/moderation/modlog.ts new file mode 100644 index 0000000..ea35198 --- /dev/null +++ b/src/commands/moderation/modlog.ts @@ -0,0 +1,143 @@ +import { BotCommand } from '../../lib/extensions/BotCommand'; +import { Message } from 'discord.js'; +import { Modlog } from '../../lib/types/Models'; +import { MessageEmbed } from 'discord.js'; +import moment from 'moment'; +import { stripIndent } from 'common-tags'; +import { Argument } from 'discord-akairo'; + +export default class ModlogCommand extends BotCommand { + constructor() { + super('modlog', { + aliases: ['modlog', 'modlogs'], + args: [ + { + id: 'search', + prompt: { + start: 'What modlog id or user would you like to see?' + } + }, + { + id: 'page', + type: 'number' + } + ], + userPermissions: ['MANAGE_MESSAGES'] + }); + } + *args(): unknown { + const search = yield { + id: 'search', + type: Argument.union('user', 'string'), + prompt: { + start: 'What modlog id or user would you like to see?' + } + }; + if (typeof search === 'string') return { search, page: null }; + else { + const page = yield { + id: 'page', + type: 'number', + prompt: { + start: 'What page?', + retry: 'Not a number. What page?', + optional: true + } + }; + return { search, page }; + } + } + async exec( + message: Message, + { search, page }: { search: string; page: number } + ): Promise { + const foundUser = await this.client.util.resolveUserAsync(search); + if (foundUser) { + const logs = await Modlog.findAll({ + where: { + guild: message.guild.id, + user: foundUser.id + }, + order: [['createdAt', 'ASC']] + }); + const niceLogs: string[] = []; + for (const log of logs) { + niceLogs.push(stripIndent` + ID: ${log.id} + Type: ${log.type.toLowerCase()} + User: <@!${log.user}> (${log.user}) + Moderator: <@!${log.moderator}> (${log.moderator}) + Duration: ${ + log.duration + ? moment.duration(log.duration, 'milliseconds').humanize() + : 'N/A' + } + Reason: ${log.reason || 'None given'} + ${this.client.util.ordinal(logs.indexOf(log) + 1)} action + `); + } + const chunked: string[][] = this.client.util.chunk(niceLogs, 3); + const embedPages = chunked.map( + (e, i) => + new MessageEmbed({ + title: `Modlogs page ${i + 1}`, + description: e.join( + '\n-------------------------------------------------------\n' + ), + footer: { + text: `Page ${i + 1}/${chunked.length}` + } + }) + ); + if (page) { + await message.util.send(embedPages[page - 1]); + return; + } else { + await message.util.send(embedPages[0]); + return; + } + } else if (search) { + const entry = await Modlog.findByPk(search); + if (!entry) { + await message.util.send('That modlog does not exist.'); + return; + } + await message.util.send( + new MessageEmbed({ + title: `Modlog ${entry.id}`, + fields: [ + { + name: 'Type', + value: entry.type.toLowerCase(), + inline: true + }, + { + name: 'Duration', + value: `${ + entry.duration + ? moment.duration(entry.duration, 'milliseconds').humanize() + : 'N/A' + }`, + inline: true + }, + { + name: 'Reason', + value: `${entry.reason || 'None given'}`, + inline: true + }, + { + name: 'Moderator', + value: `<@!${entry.moderator}> (${entry.moderator})`, + inline: true + }, + { + name: 'User', + value: `<@!${entry.user}> (${entry.user})`, + inline: true + } + ] + }) + ); + } + } +} diff --git a/src/commands/moderation/warn.ts b/src/commands/moderation/warn.ts new file mode 100644 index 0000000..676615d --- /dev/null +++ b/src/commands/moderation/warn.ts @@ -0,0 +1,54 @@ +import { GuildMember } from 'discord.js'; +import { BotCommand } from '../../lib/extensions/BotCommand'; +import { BotMessage } from '../../lib/extensions/BotMessage'; +import { Modlog, ModlogType } from '../../lib/types/Models'; + +export default class WarnCommand extends BotCommand { + public constructor() { + super('warn', { + aliases: ['warn'], + userPermissions: ['MANAGE_MESSAGES'], + args: [ + { + id: 'member', + type: 'member' + }, + { + id: 'reason', + match: 'rest' + } + ] + }); + } + public async exec( + message: BotMessage, + { member, reason }: { member: GuildMember; reason: string } + ): Promise { + try { + const entry = Modlog.build({ + user: member.id, + guild: message.guild.id, + moderator: message.author.id, + type: ModlogType.WARN, + reason + }); + await entry.save(); + } catch (e) { + await message.util.send( + 'Error saving to database, please contact the developers' + ); + return; + } + try { + await member.send( + `You were warned in ${message.guild.name} for reason "${reason}".` + ); + } catch (e) { + await message.util.send('Error messaging user, warning still saved.'); + return; + } + await message.util.send( + `${member.user.tag} was warned for reason "${reason}".` + ); + } +} -- cgit