mirror of https://github.com/clickscodes/nucleus
parent
4f164f3adb
commit
8b4b17f93e
@ -0,0 +1,35 @@
|
|||||||
|
m!info - Info has moved to /help
|
||||||
|
m!stats - Stats has moved to /nucleus help
|
||||||
|
m!settings - Settings has changed, type /settings to see the full list
|
||||||
|
m!user - User is now /user info
|
||||||
|
m!avatar - Avatar is now /user avatar
|
||||||
|
m!roleall - Roleall has moved to /roll all
|
||||||
|
m!suggest - Suggest has been moved to /nucleus suggest
|
||||||
|
m!ping - Ping has moved to /nucleus ping
|
||||||
|
m!server - Server has been moved to /server info
|
||||||
|
m!tag - Tag has changed to /tag
|
||||||
|
m!role - Role is now /role
|
||||||
|
m!viewas - Viewas has moved to /viewas
|
||||||
|
m!verify - Verify has moved to /verify, please contact the server owners if the information message has not been updated
|
||||||
|
m!setverify - Setverify has moved to /settings verify role
|
||||||
|
m!mail - Mail has moved to /ticket create, please contact the server owners if the information message has not been updated
|
||||||
|
m!prefix - Nucleus' prefix has changed to /
|
||||||
|
m!setprefix - The prefix is now required to be / due to Discord's new rules on bots
|
||||||
|
m!warn - Warn has moved to /mod warn
|
||||||
|
m!clear - Clear has moved to /mod clear
|
||||||
|
m!kick - Kick has moved to /mod kick
|
||||||
|
m!softban - Softban has moved to /mod softban
|
||||||
|
m!ban - Ban has moved to /mod ban
|
||||||
|
m!unban - Unban has moved to /mod unban
|
||||||
|
m!purge - Purge has moved to /mod purge
|
||||||
|
m!punish - Punish options can now be viewed by typing /mod
|
||||||
|
m!setlog - Setlog has moved to /settings log channel
|
||||||
|
m!ignore - Ignore has moved to /settings log ignore
|
||||||
|
m!ignored - Ignored has moved to /settings log ignored
|
||||||
|
m!stafflog - stafflog has moved to /settings mod channel
|
||||||
|
m!auto - Auto has been moved to /settings automation
|
||||||
|
m!modmail - Modmail has been moved to /settings tickets
|
||||||
|
m!slowmode - Slowmode has moved to /mod slowmode
|
||||||
|
m!lock - Lock has moved to /mod lock action:add
|
||||||
|
m!unlock - Unlock has moved to /mod lock action:remove
|
||||||
|
m!reset - Reset can be found under /settings all
|
||||||
@ -1,20 +1,92 @@
|
|||||||
import { CommandInteraction } from "discord.js";
|
import { CommandInteraction, GuildMember } from "discord.js";
|
||||||
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
|
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
|
||||||
import { WrappedCheck } from "jshaiku";
|
import { WrappedCheck } from "jshaiku";
|
||||||
|
import confirmationMessage from "../../utils/confirmationMessage.js";
|
||||||
|
import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
|
||||||
|
import keyValueList from "../../utils/generateKeyValueList.js";
|
||||||
|
|
||||||
const command = (builder: SlashCommandSubcommandBuilder) =>
|
const command = (builder: SlashCommandSubcommandBuilder) =>
|
||||||
builder
|
builder
|
||||||
.setName("kick")
|
.setName("kick")
|
||||||
.setDescription("Clears a users messages in a channel")
|
.setDescription("Kicks a user from the server")
|
||||||
|
.addUserOption(option => option.setName("user").setDescription("The user to kick").setRequired(true))
|
||||||
|
.addStringOption(option => option.setName("reason").setDescription("The reason for the kick").setRequired(false))
|
||||||
|
.addStringOption(option => option.setName("notify").setDescription("If the user should get a message when they are kicked | Default yes").setRequired(false)
|
||||||
|
.addChoices([["Yes", "yes"], ["No", "no"]])
|
||||||
|
)
|
||||||
|
|
||||||
const callback = (interaction: CommandInteraction) => {
|
const callback = async (interaction: CommandInteraction) => {
|
||||||
interaction.reply("Command incomplete [mod/kick]");
|
// TODO:[Modals] Replace this with a modal
|
||||||
|
if (await new confirmationMessage(interaction)
|
||||||
|
.setEmoji("PUNISH.KICK.RED")
|
||||||
|
.setTitle("Kick")
|
||||||
|
.setDescription(keyValueList({
|
||||||
|
"user": `<@!${(interaction.options.getMember("user") as GuildMember).id}> (${(interaction.options.getMember("user") as GuildMember).user.username})`,
|
||||||
|
"reason": `\n> ${interaction.options.getString("reason") ? interaction.options.getString("reason") : "*No reason provided*"}`
|
||||||
|
})
|
||||||
|
+ `The user **will${interaction.options.getString("notify") === "no" ? ' not' : ''}** be notified\n\n`
|
||||||
|
+ `Are you sure you want to kick <@!${(interaction.options.getMember("user") as GuildMember).id}>?`)
|
||||||
|
.setColor("Danger")
|
||||||
|
// pluralize("day", interaction.options.getInteger("delete"))
|
||||||
|
// const pluralize = (word: string, count: number) => { return count === 1 ? word : word + "s" }
|
||||||
|
.send()) {
|
||||||
|
let dmd = false
|
||||||
|
try {
|
||||||
|
if (interaction.options.getString("notify") != "no") {
|
||||||
|
await (interaction.options.getMember("user") as GuildMember).send({
|
||||||
|
embeds: [new EmojiEmbed()
|
||||||
|
.setEmoji("PUNISH.KICK.RED")
|
||||||
|
.setTitle("Kicked")
|
||||||
|
.setDescription(`You have been kicked in ${interaction.guild.name}` +
|
||||||
|
(interaction.options.getString("reason") ? ` for:\n> ${interaction.options.getString("reason")}` : " with no reason provided."))
|
||||||
|
.setStatus("Danger")
|
||||||
|
]
|
||||||
|
})
|
||||||
|
dmd = true
|
||||||
|
}
|
||||||
|
} catch {}
|
||||||
|
try {
|
||||||
|
(interaction.options.getMember("user") as GuildMember).kick(interaction.options.getString("reason") ?? "No reason provided.")
|
||||||
|
let failed = (dmd == false && interaction.options.getString("notify") != "no")
|
||||||
|
await interaction.editReply({embeds: [new EmojiEmbed()
|
||||||
|
.setEmoji(`PUNISH.KICK.${failed ? "YELLOW" : "GREEN"}`)
|
||||||
|
.setTitle(`Kick`)
|
||||||
|
.setDescription("The member was kicked" + (failed ? ", but could not be notified" : ""))
|
||||||
|
.setStatus(failed ? "Warning" : "Success")
|
||||||
|
], components: []})
|
||||||
|
} catch {
|
||||||
|
await interaction.editReply({embeds: [new EmojiEmbed()
|
||||||
|
.setEmoji("PUNISH.KICK.RED")
|
||||||
|
.setTitle(`Kick`)
|
||||||
|
.setDescription("Something went wrong and the user was not kicked")
|
||||||
|
.setStatus("Danger")
|
||||||
|
], components: []})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
await interaction.editReply({embeds: [new EmojiEmbed()
|
||||||
|
.setEmoji("PUNISH.KICK.GREEN")
|
||||||
|
.setTitle(`Kick`)
|
||||||
|
.setDescription("No changes were made")
|
||||||
|
.setStatus("Success")
|
||||||
|
], components: []})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const check = (interaction: CommandInteraction, defaultCheck: WrappedCheck) => {
|
const check = (interaction: CommandInteraction, defaultCheck: WrappedCheck) => {
|
||||||
return true;
|
// Check if Nucleus can kick the member
|
||||||
|
if (! (interaction.guild.me.roles.highest.position > (interaction.member as GuildMember).roles.highest.position)) throw "I do not have a role higher than that member"
|
||||||
|
// Check if Nucleus has permission to kick
|
||||||
|
if (! interaction.guild.me.permissions.has("KICK_MEMBERS")) throw "I do not have the `kick_members` permission";
|
||||||
|
// Do not allow kicking Nucleus
|
||||||
|
if ((interaction.member as GuildMember).id == interaction.guild.me.id) throw "I cannot kick myself"
|
||||||
|
// Allow the owner to kick anyone
|
||||||
|
if ((interaction.member as GuildMember).id == interaction.guild.ownerId) return true
|
||||||
|
// Check if the user has kick_members permission
|
||||||
|
if (! (interaction.member as GuildMember).permissions.has("KICK_MEMBERS")) throw "You do not have the `kick_members` permission";
|
||||||
|
// Check if the user is below on the role list
|
||||||
|
if (! ((interaction.member as GuildMember).roles.highest.position > (interaction.options.getMember("user") as GuildMember).roles.highest.position)) throw "You do not have a role higher than that member"
|
||||||
|
// Allow kick
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
export { command };
|
export { command, callback, check };
|
||||||
export { callback };
|
|
||||||
export { check };
|
|
||||||
@ -0,0 +1,191 @@
|
|||||||
|
import Discord, { CommandInteraction, GuildMember, MessageActionRow } from "discord.js";
|
||||||
|
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
|
||||||
|
import { WrappedCheck } from "jshaiku";
|
||||||
|
import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
|
||||||
|
import getEmojiByName from "../../utils/getEmojiByName.js";
|
||||||
|
import confirmationMessage from "../../utils/confirmationMessage.js";
|
||||||
|
import keyValueList from "../../utils/generateKeyValueList.js";
|
||||||
|
import humanizeDuration from "humanize-duration";
|
||||||
|
|
||||||
|
const command = (builder: SlashCommandSubcommandBuilder) =>
|
||||||
|
builder
|
||||||
|
.setName("mute")
|
||||||
|
.setDescription("Mutes a member using Discord's \"Timeout\" feature")
|
||||||
|
.addUserOption(option => option.setName("user").setDescription("The user to mute").setRequired(true))
|
||||||
|
.addIntegerOption(option => option.setName("days").setDescription("The number of days to mute the user for | Default 0").setMinValue(0).setMaxValue(27).setRequired(false))
|
||||||
|
.addIntegerOption(option => option.setName("hours").setDescription("The number of hours to mute the user for | Default 0").setMinValue(0).setMaxValue(23).setRequired(false))
|
||||||
|
.addIntegerOption(option => option.setName("minutes").setDescription("The number of minutes to mute the user for | Default 0").setMinValue(0).setMaxValue(59).setRequired(false))
|
||||||
|
.addIntegerOption(option => option.setName("seconds").setDescription("The number of seconds to mute the user for | Default 0").setMinValue(0).setMaxValue(59).setRequired(false))
|
||||||
|
.addStringOption(option => option.setName("reason").setDescription("The reason for the mute").setRequired(false))
|
||||||
|
.addStringOption(option => option.setName("notify").setDescription("The user to notify they have been muted").setRequired(false))
|
||||||
|
// TODO: notify the user when the mute is lifted
|
||||||
|
|
||||||
|
const callback = async (interaction: CommandInteraction) => {
|
||||||
|
const user = interaction.options.getMember("user") as GuildMember
|
||||||
|
const reason = interaction.options.getString("reason")
|
||||||
|
const time = {
|
||||||
|
days: interaction.options.getInteger("days") || 0,
|
||||||
|
hours: interaction.options.getInteger("hours") || 0,
|
||||||
|
minutes: interaction.options.getInteger("minutes") || 0,
|
||||||
|
seconds: interaction.options.getInteger("seconds") || 0
|
||||||
|
}
|
||||||
|
let muteTime = (time.days * 24 * 60 * 60) + (time.hours * 60 * 60) + (time.minutes * 60) + time.seconds
|
||||||
|
if (muteTime == 0) {
|
||||||
|
let m = await interaction.reply({embeds: [
|
||||||
|
new EmojiEmbed()
|
||||||
|
.setEmoji("PUNISH.MUTE.GREEN")
|
||||||
|
.setTitle("Mute")
|
||||||
|
.setDescription("How long should the user be muted")
|
||||||
|
.setStatus("Success")
|
||||||
|
], components: [
|
||||||
|
new MessageActionRow().addComponents([
|
||||||
|
new Discord.MessageButton()
|
||||||
|
.setCustomId("1m")
|
||||||
|
.setLabel("1 Minute")
|
||||||
|
.setStyle("SECONDARY"),
|
||||||
|
new Discord.MessageButton()
|
||||||
|
.setCustomId("10m")
|
||||||
|
.setLabel("10 Minutes")
|
||||||
|
.setStyle("SECONDARY"),
|
||||||
|
new Discord.MessageButton()
|
||||||
|
.setCustomId("30m")
|
||||||
|
.setLabel("30 Minutes")
|
||||||
|
.setStyle("SECONDARY"),
|
||||||
|
new Discord.MessageButton()
|
||||||
|
.setCustomId("1h")
|
||||||
|
.setLabel("1 Hour")
|
||||||
|
.setStyle("SECONDARY")
|
||||||
|
]),
|
||||||
|
new MessageActionRow().addComponents([
|
||||||
|
new Discord.MessageButton()
|
||||||
|
.setCustomId("6h")
|
||||||
|
.setLabel("6 Hours")
|
||||||
|
.setStyle("SECONDARY"),
|
||||||
|
new Discord.MessageButton()
|
||||||
|
.setCustomId("12h")
|
||||||
|
.setLabel("12 Hours")
|
||||||
|
.setStyle("SECONDARY"),
|
||||||
|
new Discord.MessageButton()
|
||||||
|
.setCustomId("1d")
|
||||||
|
.setLabel("1 Day")
|
||||||
|
.setStyle("SECONDARY"),
|
||||||
|
new Discord.MessageButton()
|
||||||
|
.setCustomId("1w")
|
||||||
|
.setLabel("1 Week")
|
||||||
|
.setStyle("SECONDARY")
|
||||||
|
]),
|
||||||
|
new MessageActionRow().addComponents([
|
||||||
|
new Discord.MessageButton()
|
||||||
|
.setCustomId("cancel")
|
||||||
|
.setLabel("Cancel")
|
||||||
|
.setStyle("DANGER")
|
||||||
|
.setEmoji(getEmojiByName("CONTROL.CROSS", "id"))
|
||||||
|
])
|
||||||
|
], ephemeral: true, fetchReply: true})
|
||||||
|
let component;
|
||||||
|
try {
|
||||||
|
component = await (m as Discord.Message).awaitMessageComponent({filter: (m) => m.user.id === interaction.user.id, time: 2.5 * 60 * 1000});
|
||||||
|
} catch { return }
|
||||||
|
component.deferUpdate();
|
||||||
|
if (component.customId == "cancel") return interaction.editReply({embeds: [new EmojiEmbed()
|
||||||
|
.setEmoji("PUNISH.MUTE.RED")
|
||||||
|
.setTitle("Mute")
|
||||||
|
.setDescription("Mute cancelled")
|
||||||
|
.setStatus("Danger")
|
||||||
|
]})
|
||||||
|
switch (component.customId) {
|
||||||
|
case "1m": { muteTime = 60; break; }
|
||||||
|
case "10m": { muteTime = 60 * 10; break; }
|
||||||
|
case "30m": { muteTime = 60 * 30; break; }
|
||||||
|
case "1h": { muteTime = 60 * 60; break; }
|
||||||
|
case "6h": { muteTime = 60 * 60 * 6; break; }
|
||||||
|
case "12h": { muteTime = 60 * 60 * 12; break; }
|
||||||
|
case "1d": { muteTime = 60 * 60 * 24; break; }
|
||||||
|
case "1w": { muteTime = 60 * 60 * 24 * 7; break; }
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
await interaction.reply({embeds: [
|
||||||
|
new EmojiEmbed()
|
||||||
|
.setEmoji("PUNISH.MUTE.GREEN")
|
||||||
|
.setTitle("Mute")
|
||||||
|
.setDescription("Loading...")
|
||||||
|
.setStatus("Success")
|
||||||
|
], ephemeral: true, fetchReply: true})
|
||||||
|
}
|
||||||
|
if (await new confirmationMessage(interaction)
|
||||||
|
.setEmoji("PUNISH.MUTE.RED")
|
||||||
|
.setTitle("Mute")
|
||||||
|
.setDescription(keyValueList({
|
||||||
|
"user": `<@!${user.id}> (${user.user.username})`,
|
||||||
|
"time": `${humanizeDuration(muteTime * 1000, {round: true})}`,
|
||||||
|
"reason": `\n> ${interaction.options.getString("reason") ? interaction.options.getString("reason") : "*No reason provided*"}`
|
||||||
|
})
|
||||||
|
+ `The user **will${interaction.options.getString("notify") === "no" ? ' not' : ''}** be notified\n\n`
|
||||||
|
+ `Are you sure you want to mute <@!${(interaction.options.getMember("user") as GuildMember).id}>?`)
|
||||||
|
.setColor("Danger")
|
||||||
|
// pluralize("day", interaction.options.getInteger("delete"))
|
||||||
|
// const pluralize = (word: string, count: number) => { return count === 1 ? word : word + "s" }
|
||||||
|
.send(true)) {
|
||||||
|
let dmd = false
|
||||||
|
try {
|
||||||
|
if (interaction.options.getString("notify") != "no") {
|
||||||
|
await (interaction.options.getMember("user") as GuildMember).send({
|
||||||
|
embeds: [new EmojiEmbed()
|
||||||
|
.setEmoji("PUNISH.MUTE.RED")
|
||||||
|
.setTitle("Muted")
|
||||||
|
.setDescription(`You have been muted in ${interaction.guild.name}` +
|
||||||
|
(interaction.options.getString("reason") ? ` for:\n> ${interaction.options.getString("reason")}` : " with no reason provided.\n\n" +
|
||||||
|
`You will be unmuted at: <t:${Math.round((new Date).getTime() / 1000) + muteTime}:D> at <t:${Math.round((new Date).getTime() / 1000) + muteTime}:T> (<t:${Math.round((new Date).getTime() / 1000) + muteTime}:R>)`))
|
||||||
|
.setStatus("Danger")
|
||||||
|
]
|
||||||
|
})
|
||||||
|
dmd = true
|
||||||
|
}
|
||||||
|
} catch {}
|
||||||
|
try {
|
||||||
|
(interaction.options.getMember("user") as GuildMember).timeout(muteTime * 1000, interaction.options.getString("reason") || "No reason provided")
|
||||||
|
let failed = (dmd == false && interaction.options.getString("notify") != "no")
|
||||||
|
await interaction.editReply({embeds: [new EmojiEmbed()
|
||||||
|
.setEmoji(`PUNISH.MUTE.${failed ? "YELLOW" : "GREEN"}`)
|
||||||
|
.setTitle(`Mute`)
|
||||||
|
.setDescription("The member was muted" + (failed ? ", but could not be notified" : ""))
|
||||||
|
.setStatus(failed ? "Warning" : "Success")
|
||||||
|
], components: []})
|
||||||
|
} catch {
|
||||||
|
await interaction.editReply({embeds: [new EmojiEmbed()
|
||||||
|
.setEmoji("PUNISH.MUTE.RED")
|
||||||
|
.setTitle(`Mute`)
|
||||||
|
.setDescription("Something went wrong and the user was not kicked")
|
||||||
|
.setStatus("Danger")
|
||||||
|
], components: []})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
await interaction.editReply({embeds: [new EmojiEmbed()
|
||||||
|
.setEmoji("PUNISH.MUTE.GREEN")
|
||||||
|
.setTitle(`Mute`)
|
||||||
|
.setDescription("No changes were made")
|
||||||
|
.setStatus("Success")
|
||||||
|
], components: []})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const check = (interaction: CommandInteraction, defaultCheck: WrappedCheck) => {
|
||||||
|
// Check if Nucleus can mute the member
|
||||||
|
if (! (interaction.guild.me.roles.highest.position > (interaction.member as GuildMember).roles.highest.position)) throw "I do not have a role higher than that member"
|
||||||
|
// Check if Nucleus has permission to mute
|
||||||
|
if (! interaction.guild.me.permissions.has("MODERATE_MEMBERS")) throw "I do not have the `moderate_members` permission";
|
||||||
|
// Do not allow the user to have admin or be the owner
|
||||||
|
if ((interaction.options.getMember("user") as GuildMember).permissions.has("ADMINISTRATOR") || (interaction.options.getMember("user") as GuildMember).id == interaction.guild.ownerId) throw "You cannot mute an admin or the owner"
|
||||||
|
// Do not allow muting Nucleus
|
||||||
|
if ((interaction.member as GuildMember).id == interaction.guild.me.id) throw "I cannot mute myself"
|
||||||
|
// Allow the owner to mute anyone
|
||||||
|
if ((interaction.member as GuildMember).id == interaction.guild.ownerId) return true
|
||||||
|
// Check if the user has moderate_members permission
|
||||||
|
if (! (interaction.member as GuildMember).permissions.has("MODERATE_MEMBERS")) throw "You do not have the `moderate_members` permission";
|
||||||
|
// Check if the user is below on the role list
|
||||||
|
if (! ((interaction.member as GuildMember).roles.highest.position > (interaction.options.getMember("user") as GuildMember).roles.highest.position)) throw "You do not have a role higher than that member"
|
||||||
|
// Allow mute
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
export { command, callback, check };
|
||||||
@ -1,20 +1,194 @@
|
|||||||
import { CommandInteraction } from "discord.js";
|
import Discord, { CommandInteraction, GuildChannel, GuildMember, TextChannel } from "discord.js";
|
||||||
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
|
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
|
||||||
import { WrappedCheck } from "jshaiku";
|
import { WrappedCheck } from "jshaiku";
|
||||||
|
import confirmationMessage from "../../utils/confirmationMessage.js";
|
||||||
|
import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
|
||||||
|
import keyValueList from "../../utils/generateKeyValueList.js";
|
||||||
|
import getEmojiByName from "../../utils/getEmojiByName.js";
|
||||||
|
|
||||||
const command = (builder: SlashCommandSubcommandBuilder) =>
|
const command = (builder: SlashCommandSubcommandBuilder) =>
|
||||||
builder
|
builder
|
||||||
.setName("purge")
|
.setName("purge")
|
||||||
.setDescription("Clears messages in a channel")
|
.setDescription("Bulk deletes messages in a channel")
|
||||||
|
.addIntegerOption(option => option
|
||||||
|
.setName("amount")
|
||||||
|
.setDescription("The amount of messages to delete")
|
||||||
|
.setRequired(false)
|
||||||
|
.setMinValue(1)
|
||||||
|
.setMaxValue(50))
|
||||||
|
.addChannelOption(option => option.setName("channel").setDescription("The channel to purge messages from").setRequired(false))
|
||||||
|
.addUserOption(option => option.setName("user").setDescription("The user to purge messages from").setRequired(false))
|
||||||
|
.addStringOption(option => option.setName("reason").setDescription("The reason for the purge").setRequired(false))
|
||||||
|
|
||||||
const callback = (interaction: CommandInteraction) => {
|
const callback = async (interaction: CommandInteraction) => {
|
||||||
interaction.reply("Command incomplete [mod/purge]");
|
let channel = (interaction.options.getChannel("channel") as GuildChannel) ?? interaction.channel
|
||||||
|
let thischannel
|
||||||
|
if ((interaction.options.getChannel("channel") as GuildChannel) == null) {
|
||||||
|
thischannel = true
|
||||||
|
} else {
|
||||||
|
thischannel = (interaction.options.getChannel("channel") as GuildChannel).id == interaction.channel.id
|
||||||
|
}
|
||||||
|
if (!(["GUILD_TEXT", "GUILD_NEWS", "GUILD_NEWS_THREAD", "GUILD_PUBLIC_THREAD", "GUILD_PRIVATE_THREAD"].includes(channel.type.toString()))) {
|
||||||
|
return await interaction.reply({
|
||||||
|
embeds: [
|
||||||
|
new EmojiEmbed()
|
||||||
|
.setEmoji("CHANNEL.PURGE.RED")
|
||||||
|
.setTitle("Purge")
|
||||||
|
.setDescription("You cannot purge this channel")
|
||||||
|
.setStatus("Danger")
|
||||||
|
],
|
||||||
|
components: [],
|
||||||
|
ephemeral: true,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// TODO:[Modals] Replace this with a modal
|
||||||
|
if ( !interaction.options.getInteger("amount") ) {
|
||||||
|
await interaction.reply({
|
||||||
|
embeds: [
|
||||||
|
new EmojiEmbed()
|
||||||
|
.setEmoji("CHANNEL.PURGE.RED")
|
||||||
|
.setTitle("Purge")
|
||||||
|
.setDescription("Select how many messages to delete")
|
||||||
|
.setStatus("Danger")
|
||||||
|
],
|
||||||
|
components: [],
|
||||||
|
ephemeral: true,
|
||||||
|
fetchReply: true
|
||||||
|
})
|
||||||
|
let deleted = []
|
||||||
|
while (true) {
|
||||||
|
let m = await interaction.editReply({
|
||||||
|
embeds: [
|
||||||
|
new EmojiEmbed()
|
||||||
|
.setEmoji("CHANNEL.PURGE.RED")
|
||||||
|
.setTitle("Purge")
|
||||||
|
.setDescription("Select how many messages to delete. You can continue clicking until all messages are cleared.")
|
||||||
|
.setStatus("Danger")
|
||||||
|
],
|
||||||
|
components: [
|
||||||
|
new Discord.MessageActionRow().addComponents([
|
||||||
|
new Discord.MessageButton()
|
||||||
|
.setCustomId("1")
|
||||||
|
.setLabel("1")
|
||||||
|
.setStyle("SECONDARY"),
|
||||||
|
new Discord.MessageButton()
|
||||||
|
.setCustomId("3")
|
||||||
|
.setLabel("3")
|
||||||
|
.setStyle("SECONDARY"),
|
||||||
|
new Discord.MessageButton()
|
||||||
|
.setCustomId("5")
|
||||||
|
.setLabel("5")
|
||||||
|
.setStyle("SECONDARY")
|
||||||
|
]),
|
||||||
|
new Discord.MessageActionRow().addComponents([
|
||||||
|
new Discord.MessageButton()
|
||||||
|
.setCustomId("10")
|
||||||
|
.setLabel("10")
|
||||||
|
.setStyle("SECONDARY"),
|
||||||
|
new Discord.MessageButton()
|
||||||
|
.setCustomId("25")
|
||||||
|
.setLabel("25")
|
||||||
|
.setStyle("SECONDARY"),
|
||||||
|
new Discord.MessageButton()
|
||||||
|
.setCustomId("50")
|
||||||
|
.setLabel("50")
|
||||||
|
.setStyle("SECONDARY")
|
||||||
|
]),
|
||||||
|
new Discord.MessageActionRow().addComponents([
|
||||||
|
new Discord.MessageButton()
|
||||||
|
.setCustomId("done")
|
||||||
|
.setLabel("Done")
|
||||||
|
.setStyle("SUCCESS")
|
||||||
|
.setEmoji(getEmojiByName("CONTROL.TICK", "id"))
|
||||||
|
])
|
||||||
|
]
|
||||||
|
})
|
||||||
|
let component;
|
||||||
|
try {
|
||||||
|
component = await (m as Discord.Message).awaitMessageComponent({filter: (m) => m.user.id === interaction.user.id, time: 2.5 * 60 * 1000});
|
||||||
|
} catch (e) { break; }
|
||||||
|
component.deferUpdate();
|
||||||
|
if (component.customId === "done") break;
|
||||||
|
let amount;
|
||||||
|
try { amount = parseInt(component.customId); } catch { break; }
|
||||||
|
await (channel as TextChannel).bulkDelete(amount, true); // TODO: Add to deleted list | TODO: Support for users
|
||||||
|
}
|
||||||
|
if (deleted.length === 0) return await interaction.editReply({
|
||||||
|
embeds: [
|
||||||
|
new EmojiEmbed()
|
||||||
|
.setEmoji("CHANNEL.PURGE.RED")
|
||||||
|
.setTitle("Purge")
|
||||||
|
.setDescription("No messages were deleted")
|
||||||
|
.setStatus("Danger")
|
||||||
|
],
|
||||||
|
components: []
|
||||||
|
})
|
||||||
|
return await interaction.editReply({
|
||||||
|
embeds: [
|
||||||
|
new EmojiEmbed()
|
||||||
|
.setEmoji("CHANNEL.PURGE.GREEN")
|
||||||
|
.setTitle("Purge")
|
||||||
|
.setDescription(`Deleted ${deleted.length} messages`)
|
||||||
|
.setStatus("Success")
|
||||||
|
],
|
||||||
|
components: []
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
if (await new confirmationMessage(interaction)
|
||||||
|
.setEmoji("CHANNEL.PURGE.RED")
|
||||||
|
.setTitle("Purge")
|
||||||
|
.setDescription(keyValueList({
|
||||||
|
"channel": `<#${channel.id}> (${(channel as GuildChannel).name})` + (thischannel ? " [This channel]" : ""),
|
||||||
|
"amount": interaction.options.getInteger("amount").toString(),
|
||||||
|
"reason": `\n> ${interaction.options.getString("reason") ? interaction.options.getString("reason") : "*No reason provided*"}`
|
||||||
|
}))
|
||||||
|
.setColor("Danger")
|
||||||
|
// pluralize("day", interaction.options.getInteger("amount"))
|
||||||
|
// const pluralize = (word: string, count: number) => { return count === 1 ? word : word + "s" }
|
||||||
|
.send()) {
|
||||||
|
try {
|
||||||
|
let messages = await (channel as TextChannel).bulkDelete(interaction.options.getInteger("amount"), true) // TODO: Support for users
|
||||||
|
let out = ""
|
||||||
|
messages.reverse().forEach(message => {
|
||||||
|
out += `${message.author.username}#${message.author.discriminator} (${message.author.id})\n`
|
||||||
|
let lines = message.content.split("\n")
|
||||||
|
lines.forEach(line => {out += `> ${line}\n`}) // TODO: Humanize timestamp
|
||||||
|
out += `\n\n`
|
||||||
|
}) // TODO: Upload as file
|
||||||
|
await interaction.editReply({embeds: [new EmojiEmbed()
|
||||||
|
.setEmoji(`CHANNEL.PURGE.GREEN`)
|
||||||
|
.setTitle(`Purge`)
|
||||||
|
.setDescription("Messages cleared")
|
||||||
|
.setStatus("Success")
|
||||||
|
], components: []})
|
||||||
|
} catch {
|
||||||
|
await interaction.editReply({embeds: [new EmojiEmbed()
|
||||||
|
.setEmoji("CHANNEL.PURGE.RED")
|
||||||
|
.setTitle(`Purge`)
|
||||||
|
.setDescription("Something went wrong and no messages were deleted")
|
||||||
|
.setStatus("Danger")
|
||||||
|
], components: []})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
await interaction.editReply({embeds: [new EmojiEmbed()
|
||||||
|
.setEmoji("CHANNEL.PURGE.GREEN")
|
||||||
|
.setTitle(`Purge`)
|
||||||
|
.setDescription("No changes were made")
|
||||||
|
.setStatus("Success")
|
||||||
|
], components: []})
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const check = (interaction: CommandInteraction, defaultCheck: WrappedCheck) => {
|
const check = (interaction: CommandInteraction, defaultCheck: WrappedCheck) => {
|
||||||
return true;
|
// Allow the owner to purge
|
||||||
|
if ((interaction.member as GuildMember).id == interaction.guild.ownerId) return true
|
||||||
|
// Check if the user has manage_messages permission
|
||||||
|
if (! (interaction.member as GuildMember).permissions.has("MANAGE_MESSAGES")) throw "You do not have the `manage_messages` permission";
|
||||||
|
// Check if nucleus has the manage_messages permission
|
||||||
|
if (! interaction.guild.me.permissions.has("MANAGE_MESSAGES")) throw "I do not have the `manage_messages` permission";
|
||||||
|
// Allow warn
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
export { command };
|
export { command, callback, check };
|
||||||
export { callback };
|
|
||||||
export { check };
|
|
||||||
@ -1,20 +1,97 @@
|
|||||||
import { CommandInteraction } from "discord.js";
|
import { CommandInteraction, GuildMember } from "discord.js";
|
||||||
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
|
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
|
||||||
import { WrappedCheck } from "jshaiku";
|
import { WrappedCheck } from "jshaiku";
|
||||||
|
import confirmationMessage from "../../utils/confirmationMessage.js";
|
||||||
|
import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
|
||||||
|
import keyValueList from "../../utils/generateKeyValueList.js";
|
||||||
|
|
||||||
const command = (builder: SlashCommandSubcommandBuilder) =>
|
const command = (builder: SlashCommandSubcommandBuilder) =>
|
||||||
builder
|
builder
|
||||||
.setName("softban")
|
.setName("softban")
|
||||||
.setDescription("Softbans a user")
|
.setDescription("Kicks a user and deletes their messages")
|
||||||
|
.addUserOption(option => option.setName("user").setDescription("The user to softban").setRequired(true))
|
||||||
|
.addStringOption(option => option.setName("reason").setDescription("The reason for the softban").setRequired(false))
|
||||||
|
.addStringOption(option => option.setName("notify").setDescription("If the user should get a message when they are banbanned | Default yes").setRequired(false)
|
||||||
|
.addChoices([["Yes", "yes"], ["No", "no"]])
|
||||||
|
)
|
||||||
|
.addIntegerOption(option => option.setName("delete").setDescription("The days of messages to delete | Default 0").setMinValue(0).setMaxValue(7).setRequired(false))
|
||||||
|
|
||||||
const callback = (interaction: CommandInteraction) => {
|
const callback = async (interaction: CommandInteraction) => {
|
||||||
interaction.reply("Command incomplete [mod/softban]");
|
// TODO:[Modals] Replace this with a modal
|
||||||
|
if (await new confirmationMessage(interaction)
|
||||||
|
.setEmoji("PUNISH.BAN.RED")
|
||||||
|
.setTitle("Softban")
|
||||||
|
.setDescription(keyValueList({
|
||||||
|
"user": `<@!${(interaction.options.getMember("user") as GuildMember).id}> (${(interaction.options.getMember("user") as GuildMember).user.username})`,
|
||||||
|
"reason": `\n> ${interaction.options.getString("reason") ? interaction.options.getString("reason") : "*No reason provided*"}`
|
||||||
|
})
|
||||||
|
+ `The user **will${interaction.options.getString("notify") === "no" ? ' not' : ''}** be notified\n`
|
||||||
|
+ `${interaction.options.getInteger("delete") ? interaction.options.getInteger("delete") : 0} day${interaction.options.getInteger("delete") === 1 || interaction.options.getInteger("delete") === null ? "s" : ""} of messages will be deleted\n\n` // TODO:[s addition]
|
||||||
|
+ `Are you sure you want to softban <@!${(interaction.options.getMember("user") as GuildMember).id}>?`)
|
||||||
|
.setColor("Danger")
|
||||||
|
// pluralize("day", interaction.options.getInteger("delete"))
|
||||||
|
// const pluralize = (word: string, count: number) => { return count === 1 ? word : word + "s" }
|
||||||
|
.send()) {
|
||||||
|
let dmd = false
|
||||||
|
try {
|
||||||
|
if (interaction.options.getString("notify") != "no") {
|
||||||
|
await (interaction.options.getMember("user") as GuildMember).send({
|
||||||
|
embeds: [new EmojiEmbed()
|
||||||
|
.setEmoji("PUNISH.BAN.RED")
|
||||||
|
.setTitle("Kick")
|
||||||
|
.setDescription(`You have been kicked from ${interaction.guild.name}` +
|
||||||
|
(interaction.options.getString("reason") ? ` for:\n> ${interaction.options.getString("reason")}` : " with no reason provided."))
|
||||||
|
.setStatus("Danger")
|
||||||
|
]
|
||||||
|
})
|
||||||
|
dmd = true
|
||||||
|
}
|
||||||
|
} catch {}
|
||||||
|
try {
|
||||||
|
(interaction.options.getMember("user") as GuildMember).ban({
|
||||||
|
days: Number(interaction.options.getInteger("delete") ?? 0),
|
||||||
|
reason: interaction.options.getString("reason")
|
||||||
|
}) // TODO: unban here
|
||||||
|
let failed = (dmd == false && interaction.options.getString("notify") != "no")
|
||||||
|
await interaction.editReply({embeds: [new EmojiEmbed()
|
||||||
|
.setEmoji(`PUNISH.BAN.${failed ? "YELLOW" : "GREEN"}`)
|
||||||
|
.setTitle(`Softban`)
|
||||||
|
.setDescription("The member was softbanned" + (failed ? ", but could not be notified" : ""))
|
||||||
|
.setStatus(failed ? "Warning" : "Success")
|
||||||
|
], components: []})
|
||||||
|
} catch {
|
||||||
|
await interaction.editReply({embeds: [new EmojiEmbed()
|
||||||
|
.setEmoji("PUNISH.BAN.RED")
|
||||||
|
.setTitle(`Softban`)
|
||||||
|
.setDescription("Something went wrong and the user was not softbanned")
|
||||||
|
.setStatus("Danger")
|
||||||
|
], components: []})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
await interaction.editReply({embeds: [new EmojiEmbed()
|
||||||
|
.setEmoji("PUNISH.BAN.GREEN")
|
||||||
|
.setTitle(`Softban`)
|
||||||
|
.setDescription("No changes were made")
|
||||||
|
.setStatus("Success")
|
||||||
|
], components: []})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const check = (interaction: CommandInteraction, defaultCheck: WrappedCheck) => {
|
const check = (interaction: CommandInteraction, defaultCheck: WrappedCheck) => {
|
||||||
return true;
|
// Check if Nucleus can ban the member
|
||||||
|
if (! (interaction.guild.me.roles.highest.position > (interaction.member as GuildMember).roles.highest.position)) throw "I do not have a role higher than that member"
|
||||||
|
// Check if Nucleus has permission to ban
|
||||||
|
if (! interaction.guild.me.permissions.has("BAN_MEMBERS")) throw "I do not have the `ban_members` permission";
|
||||||
|
// Do not allow softbanning Nucleus
|
||||||
|
if ((interaction.member as GuildMember).id == interaction.guild.me.id) throw "I cannot softban myself"
|
||||||
|
// Allow the owner to ban anyone
|
||||||
|
if ((interaction.member as GuildMember).id == interaction.guild.ownerId) return true
|
||||||
|
// Check if the user has ban_members permission
|
||||||
|
if (! (interaction.member as GuildMember).permissions.has("BAN_MEMBERS")) throw "You do not have the `ban_members` permission";
|
||||||
|
// Check if the user is below on the role list
|
||||||
|
if (! ((interaction.member as GuildMember).roles.highest.position > (interaction.options.getMember("user") as GuildMember).roles.highest.position)) throw "You do not have a role higher than that member"
|
||||||
|
// Allow softban
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
export { command };
|
export { command, callback, check };
|
||||||
export { callback };
|
|
||||||
export { check };
|
|
||||||
@ -1,20 +1,86 @@
|
|||||||
import { CommandInteraction } from "discord.js";
|
import { CommandInteraction, GuildMember } from "discord.js";
|
||||||
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
|
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
|
||||||
import { WrappedCheck } from "jshaiku";
|
import { WrappedCheck } from "jshaiku";
|
||||||
|
import confirmationMessage from "../../utils/confirmationMessage.js";
|
||||||
|
import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
|
||||||
|
import keyValueList from "../../utils/generateKeyValueList.js";
|
||||||
|
|
||||||
const command = (builder: SlashCommandSubcommandBuilder) =>
|
const command = (builder: SlashCommandSubcommandBuilder) =>
|
||||||
builder
|
builder
|
||||||
.setName("warn")
|
.setName("warn")
|
||||||
.setDescription("Warns a user")
|
.setDescription("Warns a user")
|
||||||
|
.addUserOption(option => option.setName("user").setDescription("The user to warn").setRequired(true))
|
||||||
|
.addStringOption(option => option.setName("reason").setDescription("The reason for the warn").setRequired(false))
|
||||||
|
.addStringOption(option => option.setName("notify").setDescription("If the user should get a message when they are warned | Default yes").setRequired(false)
|
||||||
|
.addChoices([["Yes", "yes"], ["No", "no"]])
|
||||||
|
)
|
||||||
|
|
||||||
const callback = (interaction: CommandInteraction) => {
|
const callback = async (interaction: CommandInteraction) => {
|
||||||
interaction.reply("Command incomplete [mod/warn]");
|
// TODO:[Modals] Replace this with a modal
|
||||||
|
if (await new confirmationMessage(interaction)
|
||||||
|
.setEmoji("PUNISH.WARN.RED")
|
||||||
|
.setTitle("Warn")
|
||||||
|
.setDescription(keyValueList({
|
||||||
|
"user": `<@!${(interaction.options.getMember("user") as GuildMember).id}> (${(interaction.options.getMember("user") as GuildMember).user.username})`,
|
||||||
|
"reason": `\n> ${interaction.options.getString("reason") ? interaction.options.getString("reason") : "*No reason provided*"}`
|
||||||
|
})
|
||||||
|
+ `The user **will${interaction.options.getString("notify") === "no" ? ' not' : ''}** be notified\n\n`)
|
||||||
|
.setColor("Danger")
|
||||||
|
// pluralize("day", interaction.options.getInteger("delete"))
|
||||||
|
// const pluralize = (word: string, count: number) => { return count === 1 ? word : word + "s" }
|
||||||
|
.send()) {
|
||||||
|
let dmd = false
|
||||||
|
try {
|
||||||
|
if (interaction.options.getString("notify") != "no") {
|
||||||
|
await (interaction.options.getMember("user") as GuildMember).send({
|
||||||
|
embeds: [new EmojiEmbed()
|
||||||
|
.setEmoji("PUNISH.WARN.RED")
|
||||||
|
.setTitle("Warned")
|
||||||
|
.setDescription(`You have been warned in ${interaction.guild.name}` +
|
||||||
|
(interaction.options.getString("reason") ? ` for:\n> ${interaction.options.getString("reason")}` : " with no reason provided."))
|
||||||
|
.setStatus("Danger")
|
||||||
|
]
|
||||||
|
})
|
||||||
|
dmd = true
|
||||||
|
}
|
||||||
|
} catch {}
|
||||||
|
try {
|
||||||
|
let failed = (dmd == false && interaction.options.getString("notify") != "no") // TODO: some way of dealing with not DMing users
|
||||||
|
await interaction.editReply({embeds: [new EmojiEmbed()
|
||||||
|
.setEmoji(`PUNISH.WARN.${failed ? "YELLOW" : "GREEN"}`)
|
||||||
|
.setTitle(`Warn`)
|
||||||
|
.setDescription(failed ? "The user cannot be messaged and was not warned" : "The user was warned")
|
||||||
|
.setStatus(failed ? "Warning" : "Success")
|
||||||
|
], components: []})
|
||||||
|
} catch {
|
||||||
|
await interaction.editReply({embeds: [new EmojiEmbed()
|
||||||
|
.setEmoji("PUNISH.WARN.RED")
|
||||||
|
.setTitle(`Warn`)
|
||||||
|
.setDescription("Something went wrong and the user was not warned")
|
||||||
|
.setStatus("Danger")
|
||||||
|
], components: []})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
await interaction.editReply({embeds: [new EmojiEmbed()
|
||||||
|
.setEmoji("PUNISH.WARN.GREEN")
|
||||||
|
.setTitle(`Warn`)
|
||||||
|
.setDescription("No changes were made")
|
||||||
|
.setStatus("Success")
|
||||||
|
], components: []})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const check = (interaction: CommandInteraction, defaultCheck: WrappedCheck) => {
|
const check = (interaction: CommandInteraction, defaultCheck: WrappedCheck) => {
|
||||||
return true;
|
// Do not allow warning bots
|
||||||
|
if ((interaction.member as GuildMember).user.bot) throw "I cannot warn bots"
|
||||||
|
// Allow the owner to warn anyone
|
||||||
|
if ((interaction.member as GuildMember).id == interaction.guild.ownerId) return true
|
||||||
|
// Check if the user has moderate_members permission
|
||||||
|
if (! (interaction.member as GuildMember).permissions.has("MODERATE_MEMBERS")) throw "You do not have the `moderate_members` permission";
|
||||||
|
// Check if the user is below on the role list
|
||||||
|
if (! ((interaction.member as GuildMember).roles.highest.position > (interaction.options.getMember("user") as GuildMember).roles.highest.position)) throw "You do not have a role higher than that member"
|
||||||
|
// Allow warn
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
export { command };
|
export { command, callback, check };
|
||||||
export { callback };
|
|
||||||
export { check };
|
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
import { CommandInteraction } from "discord.js";
|
||||||
|
import { SlashCommandBuilder } from "@discordjs/builders";
|
||||||
|
import { WrappedCheck } from "jshaiku";
|
||||||
|
|
||||||
|
const command = new SlashCommandBuilder()
|
||||||
|
.setName("server")
|
||||||
|
.setDescription("Shows info about the server")
|
||||||
|
|
||||||
|
const callback = (interaction: CommandInteraction) => {
|
||||||
|
interaction.reply("Command incomplete [server]");
|
||||||
|
}
|
||||||
|
|
||||||
|
const check = (interaction: CommandInteraction, defaultCheck: WrappedCheck) => {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
export { command };
|
||||||
|
export { callback };
|
||||||
|
export { check };
|
||||||
Loading…
Reference in new issue