diff --git a/slash_commands/Administrator/clear-warnings.js b/slash_commands/Administrator/clear-warnings.js new file mode 100644 index 00000000..44161bc2 --- /dev/null +++ b/slash_commands/Administrator/clear-warnings.js @@ -0,0 +1,83 @@ +const { EmbedBuilder, SlashCommandBuilder } = require('discord.js'); +const { QuickDB } = require('quick.db'); +const db = new QuickDB(); + +exports.conf = { + permLevel: 'Administrator', + guildOnly: true, +}; + +exports.commandData = new SlashCommandBuilder() + .setName('clear-warnings') + .setDescription('Clear all the warnings of the specific user.') + .addUserOption((option) => option.setName('user').setDescription('The user to clear warnings from').setRequired(true)) + .setDMPermission(false); + +exports.run = async (interaction) => { + await interaction.deferReply(); + const mem = interaction.options.getUser('user'); + const color = interaction.settings.embedColor; + + const otherWarns = await interaction.client.util.getWarns(mem.id, interaction); + const previousPoints = await interaction.client.util.getTotalPoints(mem.id, interaction); + const logChan = await db.get(`servers.${interaction.guild.id}.warns.channel`); + + if (!otherWarns || otherWarns.length < 1) return interaction.client.util.errorEmbed(interaction, 'That user has no warnings.'); + + for (const i of otherWarns) { + await db.delete(`servers.${interaction.guild.id}.warns.warnings.${i.warnID}`); + } + + if (previousPoints >= 10) { + if (!interaction.guild.members.me.permissions.has('BanMembers')) { + interaction.client.util.errorEmbed( + interaction, + 'Please unban the user manually, the bot does not have Ban Members permission.', + 'Missing Permission', + ); + } else { + await interaction.guild.members.unban(mem.id).catch(() => null); + } + } + + const otherCases = otherWarns.map((w) => `\`${w.warnID}\``).join(', '); + const username = interaction.user.discriminator === '0' ? interaction.user.username : interaction.user.tag; + + const userEmbed = new EmbedBuilder() + .setDescription('Warnings Cleared') + .setColor(color) + .addFields([ + { name: 'Moderator', value: `${username} (${interaction.user.id})`, inline: true }, + { name: 'Cleared Cases', value: otherCases, inline: true }, + { name: 'Issued In', value: interaction.guild.name, inline: true }, + ]); + const userMessage = await mem.send({ embeds: [userEmbed] }).catch(() => null); + + const logEmbed = new EmbedBuilder() + .setTitle('Warnings Cleared') + .setColor(color) + .addFields([ + { name: 'Moderator', value: `${username} (${interaction.user.id})`, inline: true }, + { name: 'User', value: `${mem} (${mem.id})`, inline: true }, + { name: 'Cleared Cases', value: otherCases, inline: true }, + ]); + if (!userMessage) logEmbed.setFooter({ text: 'Failed to send a DM to the user. (User has DMs disabled)' }); + + if (logChan) { + const channelEmbed = new EmbedBuilder() + .setTitle('Warnings Cleared') + .setColor(color) + .addFields([ + { name: 'User', value: `${mem} (${mem.id})` }, + { name: 'Cleared Cases', value: otherCases }, + ]); + + interaction.channel.send({ embeds: [channelEmbed] }).then((embed) => { + setTimeout(() => embed.delete(), 30000); + }); + + return interaction.guild.channels.cache.get(logChan).send({ embeds: [logEmbed] }); + } else { + return interaction.editReply({ embeds: [logEmbed] }); + } +}; diff --git a/slash_commands/Administrator/delete-warning.js b/slash_commands/Administrator/delete-warning.js new file mode 100644 index 00000000..b13254f1 --- /dev/null +++ b/slash_commands/Administrator/delete-warning.js @@ -0,0 +1,90 @@ +const { EmbedBuilder, SlashCommandBuilder } = require('discord.js'); +const { QuickDB } = require('quick.db'); +const db = new QuickDB(); + +exports.conf = { + permLevel: 'Administrator', + guildOnly: true, +}; + +exports.commandData = new SlashCommandBuilder() + .setName('delete-warning') + .setDescription('Delete a specific warnings case.') + .addStringOption((option) => option.setName('case_id').setDescription(' The Case ID To delete').setRequired(true)) + .setDMPermission(false); + +exports.run = async (interaction) => { + await interaction.deferReply(); + let title = 'Case Cleared'; + let color = interaction.settings.embedColor; + + const caseID = interaction.options.getString('case_id'); + const warning = await db.get(`servers.${interaction.guild.id}.warns.warnings.${caseID}`); + + if (!warning) return interaction.client.util.errorEmbed(interaction, 'No warning case found', 'Invalid Case ID'); + + const logChan = await db.get(`servers.${interaction.guild.id}.warns.channel`); + const userID = warning.user; + const user = await interaction.client.users.fetch(userID); + const warnReason = warning.reason || '???'; + + if (!user) return interaction.client.util.errorEmbed(interaction, 'User not found', 'Invalid User'); + + const previousPoints = interaction.client.util.getTotalPoints(userID, interaction); + await db.delete(`servers.${interaction.guild.id}.warns.warnings.${caseID}`); + const newerPoints = interaction.client.util.getTotalPoints(userID, interaction); + + if (previousPoints >= 10 && newerPoints < 10) { + if (!interaction.guild.members.me.permissions.has('BanMembers')) { + interaction.client.util.errorEmbed( + interaction, + 'Please unban the user manually, the bot does not have Ban Members permission.', + 'Missing Permission', + ); + } else { + await interaction.guild.members.unban(userID).catch(() => null); + title += ' & User Unbanned'; + color = interaction.settings.embedSuccessColor; + } + } + + const userEmbed = new EmbedBuilder() + .setTitle(title) + .setColor(color) + .addFields([ + { name: 'Moderator', value: `${interaction.user} (${interaction.user.id})`, inline: true }, + { name: 'Deleted Case', value: `\`${caseID}\``, inline: true }, + { name: 'Case Reason', value: warnReason, inline: true }, + { name: 'Issued In', value: interaction.guild.name, inline: true }, + ]); + const userMessage = await user.send({ embeds: [userEmbed] }).catch(() => null); + + const logEmbed = new EmbedBuilder() + .setTitle(title) + .setColor(color) + .addFields([ + { name: 'Moderator', value: `${interaction.user} (${interaction.user.id})`, inline: true }, + { name: 'User', value: `${user} (${user.id})`, inline: true }, + { name: 'Deleted Case', value: `\`${caseID}\``, inline: true }, + { name: 'Case Reason', value: warnReason, inline: true }, + ]); + if (!userMessage) logEmbed.setFooter({ text: 'Failed to send a DM to the user. (User has DMs disabled)' }); + + if (logChan) { + const channelEmbed = new EmbedBuilder() + .setTitle(title) + .setColor(color) + .addFields([ + { name: 'User', value: `${user} (${user.id})`, inline: true }, + { name: 'Deleted Case', value: `\`${caseID}\``, inline: true }, + ]); + + interaction.guild.channel.send({ embeds: [channelEmbed] }).then((embed) => { + setTimeout(() => embed.delete(), 30000); + }); + + return interaction.guild.channels.cache.get(logChan).send({ embeds: [logEmbed] }); + } else { + return interaction.editReply({ embeds: [logEmbed] }); + } +}; diff --git a/slash_commands/Administrator/persistent-roles.js b/slash_commands/Administrator/persistent-roles.js new file mode 100644 index 00000000..ded36842 --- /dev/null +++ b/slash_commands/Administrator/persistent-roles.js @@ -0,0 +1,55 @@ +const { SlashCommandBuilder } = require('discord.js'); +const { QuickDB } = require('quick.db'); +const db = new QuickDB(); + +exports.conf = { + permLevel: 'Administrator', + guildOnly: true, +}; + +exports.commandData = new SlashCommandBuilder() + .setName('persistent-roles') + .setDescription('Enable/Disable Persistent-Roles') + .addStringOption((option) => + option + .setName('type') + .setDescription('Enable/Disable or get information') + .setRequired(true) + .addChoices( + { name: 'Enable', value: 'enable' }, + { name: 'Disable', value: 'disable' }, + { name: 'Information', value: 'information' }, + ), + ) + .setDMPermission(false); + +exports.run = async (interaction) => { + await interaction.deferReply(); + const type = interaction.options.getString('type'); + + if (!interaction.guild.members.me.permissions.has('ManageRoles')) { + return interaction.client.util.errorEmbed( + interaction, + 'Manage Roles permission is required on the bot to use this.', + 'Missing Permission', + ); + } + + switch (type) { + case 'enable': { + await db.set(`servers.${interaction.guild.id}.proles.system`, true); + return interaction.editReply('The persistent role system for this server has been enabled'); + } + + case 'disable': { + await db.set(`servers.${interaction.guild.id}.proles.system`, false); + return interaction.editReply('The persistent role system for this server has been disabled'); + } + + case 'information': { + return interaction.editReply( + 'When persistent roles is enabled users who leave the guild will have their roles automatically returned when they come back.', + ); + } + } +}; diff --git a/slash_commands/Moderator/purge.js b/slash_commands/Moderator/purge.js index d9b4c5f5..f62c5189 100644 --- a/slash_commands/Moderator/purge.js +++ b/slash_commands/Moderator/purge.js @@ -146,7 +146,7 @@ exports.run = async (interaction) => { const linkRegex = /https?:\/\/[\w\d-_]/gi; if (!interaction.guild.members.me.permissions.has('ManageMessages')) - return this.client.util.errorEmbed( + return interaction.client.util.errorEmbed( interaction, 'The bot needs `Manage Messages` permission.', 'Missing Permission', @@ -181,7 +181,7 @@ exports.run = async (interaction) => { return messages.size; }) .catch((err) => { - return this.client.util.errorEmbed(interaction, err); + return interaction.client.util.errorEmbed(interaction, err); }); } @@ -220,7 +220,7 @@ exports.run = async (interaction) => { if (progress) purgeMsg.edit(`Purging messages... ${Math.ceil((purged / total) * 100)}%`).catch(() => false); if (!messages.size) count = 0; - await this.client.util.wait(1100); + await interaction.client.util.wait(1100); count -= Math.min(count, 100); } diff --git a/slash_commands/NSFW/pornhub.js b/slash_commands/NSFW/pornhub.js new file mode 100644 index 00000000..1abec149 --- /dev/null +++ b/slash_commands/NSFW/pornhub.js @@ -0,0 +1,24 @@ +const { SlashCommandBuilder } = require('discord.js'); +const pornhub = require('@justalk/pornhub-api'); + +exports.conf = { + permLevel: 'User', + guildOnly: false, +}; + +exports.commandData = new SlashCommandBuilder() + .setName('pornhub') + .setDescription('Search pornhub for a video') + .setNSFW(true) + .addStringOption((option) => option.setName('query').setDescription('Video to search for').setRequired(true)); + +exports.run = async (interaction) => { + await interaction.deferReply(); + const query = interaction.options.getString('query'); + + // Search pornhub by query and get the first result + const results = await pornhub.search(query); + const firstResult = results.results[0]; + + return interaction.editReply(firstResult.link); +};