blob: 9cc8a7c13cff4e09221aa3c4bbabc58525f9398d [file] [log] [blame]
pineafan377794f2022-04-18 19:01:01 +01001import { CommandInteraction, GuildMember, MessageActionRow, MessageButton } from "discord.js";
pineafan32767212022-03-14 21:27:39 +00002import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
3import { WrappedCheck } from "jshaiku";
4import confirmationMessage from "../../utils/confirmationMessage.js";
pineafan4edb7762022-06-26 19:21:04 +01005import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
pineafan32767212022-03-14 21:27:39 +00006import keyValueList from "../../utils/generateKeyValueList.js";
pineafan73a7c4a2022-07-24 10:38:04 +01007import { create, areTicketsEnabled } from "../../actions/createModActionTicket.js";
pineafan63fc5e22022-08-04 22:04:10 +01008import client from "../../utils/client.js";
pineafan32767212022-03-14 21:27:39 +00009
10const command = (builder: SlashCommandSubcommandBuilder) =>
11 builder
pineafan63fc5e22022-08-04 22:04:10 +010012 .setName("nick")
13 .setDescription("Changes a users nickname")
14 .addUserOption(option => option.setName("user").setDescription("The user to change").setRequired(true))
15 .addStringOption(option => option.setName("name").setDescription("The name to set | Leave blank to clear").setRequired(false));
pineafan32767212022-03-14 21:27:39 +000016
pineafan4edb7762022-06-26 19:21:04 +010017const callback = async (interaction: CommandInteraction): Promise<any> => {
pineafan63fc5e22022-08-04 22:04:10 +010018 const { renderUser } = client.logger;
pineafan377794f2022-04-18 19:01:01 +010019 // TODO:[Modals] Replace this with a modal
pineafan02ba0232022-07-24 22:16:15 +010020 let notify = true;
21 let confirmation;
22 while (true) {
23 confirmation = await new confirmationMessage(interaction)
24 .setEmoji("PUNISH.NICKNAME.RED")
25 .setTitle("Nickname")
26 .setDescription(keyValueList({
27 "user": renderUser(interaction.options.getUser("user")),
28 "new nickname": `${interaction.options.getString("name") ? interaction.options.getString("name") : "*No nickname*"}`
29 })
pineafan63fc5e22022-08-04 22:04:10 +010030 + `The user **will${notify ? "" : " not"}** be notified\n\n`
pineafan02ba0232022-07-24 22:16:15 +010031 + `Are you sure you want to ${interaction.options.getString("name") ? "change" : "clear"} <@!${(interaction.options.getMember("user") as GuildMember).id}>'s nickname?`)
32 .setColor("Danger")
33 .addCustomBoolean("notify", "Notify user", false, null, null, "ICONS.NOTIFY." + (notify ? "ON" : "OFF" ), notify)
pineafan63fc5e22022-08-04 22:04:10 +010034 .send(interaction.options.getString("name") !== null);
35 if (confirmation.cancelled) return;
36 if (confirmation.success) break;
pineafan02ba0232022-07-24 22:16:15 +010037 if (confirmation.components) {
pineafan63fc5e22022-08-04 22:04:10 +010038 notify = confirmation.components.notify.active;
pineafan02ba0232022-07-24 22:16:15 +010039 }
40 }
pineafan377794f2022-04-18 19:01:01 +010041 if (confirmation.success) {
pineafan63fc5e22022-08-04 22:04:10 +010042 let dmd = false;
pineafan377794f2022-04-18 19:01:01 +010043 let dm;
44 try {
pineafan02ba0232022-07-24 22:16:15 +010045 if (notify) {
pineafan377794f2022-04-18 19:01:01 +010046 dm = await (interaction.options.getMember("user") as GuildMember).send({
pineafan4edb7762022-06-26 19:21:04 +010047 embeds: [new EmojiEmbed()
pineafan377794f2022-04-18 19:01:01 +010048 .setEmoji("PUNISH.NICKNAME.RED")
49 .setTitle("Nickname changed")
pineafane625d782022-05-09 18:04:32 +010050 .setDescription(`Your nickname was ${interaction.options.getString("name") ? "changed" : "cleared"} in ${interaction.guild.name}.` +
51 (interaction.options.getString("name") ? ` it is now: ${interaction.options.getString("name")}` : "") + "\n\n" +
pineafan63fc5e22022-08-04 22:04:10 +010052 (confirmation.components.appeal.response ? `You can appeal this here: <#${confirmation.components.appeal.response}>` : ""))
pineafan377794f2022-04-18 19:01:01 +010053 .setStatus("Danger")
54 ]
pineafan63fc5e22022-08-04 22:04:10 +010055 });
56 dmd = true;
pineafan377794f2022-04-18 19:01:01 +010057 }
pineafan63fc5e22022-08-04 22:04:10 +010058 } catch { dmd = false; }
pineafan377794f2022-04-18 19:01:01 +010059 try {
pineafan63fc5e22022-08-04 22:04:10 +010060 const member = (interaction.options.getMember("user") as GuildMember);
61 const before = member.nickname;
62 const nickname = interaction.options.getString("name");
63 member.setNickname(nickname ?? null, "Nucleus Nickname command");
64 await client.database.history.create(
pineafan4edb7762022-06-26 19:21:04 +010065 "nickname", interaction.guild.id, member.user, interaction.user,
pineafan63fc5e22022-08-04 22:04:10 +010066 null, before, nickname);
67 const { log, NucleusColors, entry, renderUser, renderDelta } = client.logger;
68 const data = {
pineafane625d782022-05-09 18:04:32 +010069 meta: {
pineafan63fc5e22022-08-04 22:04:10 +010070 type: "memberUpdate",
71 displayName: "Member Updated",
72 calculateType: "guildMemberUpdate",
pineafane625d782022-05-09 18:04:32 +010073 color: NucleusColors.yellow,
74 emoji: "PUNISH.NICKNAME.YELLOW",
75 timestamp: new Date().getTime()
76 },
77 list: {
pineafanda6e5342022-07-03 10:03:16 +010078 memberId: entry(member.id, `\`${member.id}\``),
pineafan63fc5e22022-08-04 22:04:10 +010079 before: entry(before, before ? before : "*None*"),
80 after: entry(nickname, nickname ? nickname : "*None*"),
pineafane625d782022-05-09 18:04:32 +010081 updated: entry(new Date().getTime(), renderDelta(new Date().getTime())),
82 updatedBy: entry(interaction.user.id, renderUser(interaction.user))
83 },
84 hidden: {
85 guild: interaction.guild.id
86 }
pineafan63fc5e22022-08-04 22:04:10 +010087 };
pineafan4edb7762022-06-26 19:21:04 +010088 log(data);
pineafan377794f2022-04-18 19:01:01 +010089 } catch {
pineafan4edb7762022-06-26 19:21:04 +010090 await interaction.editReply({embeds: [new EmojiEmbed()
pineafan377794f2022-04-18 19:01:01 +010091 .setEmoji("PUNISH.NICKNAME.RED")
pineafan63fc5e22022-08-04 22:04:10 +010092 .setTitle("Nickname")
pineafan377794f2022-04-18 19:01:01 +010093 .setDescription("Something went wrong and the users nickname could not be changed.")
94 .setStatus("Danger")
pineafan63fc5e22022-08-04 22:04:10 +010095 ], components: []});
96 if (dmd) await dm.delete();
97 return;
pineafan377794f2022-04-18 19:01:01 +010098 }
pineafan63fc5e22022-08-04 22:04:10 +010099 const failed = (dmd === false && notify);
pineafan4edb7762022-06-26 19:21:04 +0100100 await interaction.editReply({embeds: [new EmojiEmbed()
pineafan377794f2022-04-18 19:01:01 +0100101 .setEmoji(`PUNISH.NICKNAME.${failed ? "YELLOW" : "GREEN"}`)
pineafan63fc5e22022-08-04 22:04:10 +0100102 .setTitle("Nickname")
103 .setDescription("The members nickname was changed" + (failed ? ", but was not notified" : "") + (confirmation.components.appeal.response ? ` and an appeal ticket was opened in <#${confirmation.components.appeal.response}>` : ""))
pineafan377794f2022-04-18 19:01:01 +0100104 .setStatus(failed ? "Warning" : "Success")
pineafan63fc5e22022-08-04 22:04:10 +0100105 ], components: []});
pineafan377794f2022-04-18 19:01:01 +0100106 } else {
pineafan4edb7762022-06-26 19:21:04 +0100107 await interaction.editReply({embeds: [new EmojiEmbed()
pineafan377794f2022-04-18 19:01:01 +0100108 .setEmoji("PUNISH.NICKNAME.GREEN")
pineafan63fc5e22022-08-04 22:04:10 +0100109 .setTitle("Nickname")
pineafan377794f2022-04-18 19:01:01 +0100110 .setDescription("No changes were made")
111 .setStatus("Success")
pineafan63fc5e22022-08-04 22:04:10 +0100112 ], components: []});
pineafan377794f2022-04-18 19:01:01 +0100113 }
pineafan63fc5e22022-08-04 22:04:10 +0100114};
pineafan32767212022-03-14 21:27:39 +0000115
116const check = (interaction: CommandInteraction, defaultCheck: WrappedCheck) => {
pineafan63fc5e22022-08-04 22:04:10 +0100117 const member = (interaction.member as GuildMember);
118 const me = (interaction.guild.me as GuildMember);
119 const apply = (interaction.options.getMember("user") as GuildMember);
120 if (member === null || me === null || apply === null) throw "That member is not in the server";
121 const memberPos = member.roles ? member.roles.highest.position : 0;
122 const mePos = me.roles ? me.roles.highest.position : 0;
123 const applyPos = apply.roles ? apply.roles.highest.position : 0;
pineafanc1c18792022-08-03 21:41:36 +0100124 // Do not allow any changing of the owner
pineafan63fc5e22022-08-04 22:04:10 +0100125 if (member.id === interaction.guild.ownerId) throw "You cannot change the owner's nickname";
pineafan377794f2022-04-18 19:01:01 +0100126 // Check if Nucleus can change the nickname
pineafan63fc5e22022-08-04 22:04:10 +0100127 if (! (mePos > applyPos)) throw "I do not have a role higher than that member";
pineafan377794f2022-04-18 19:01:01 +0100128 // Check if Nucleus has permission to change the nickname
pineafane23c4ec2022-07-27 21:56:27 +0100129 if (! me.permissions.has("MANAGE_NICKNAMES")) throw "I do not have the *Manage Nicknames* permission";
pineafan377794f2022-04-18 19:01:01 +0100130 // Allow the owner to change anyone's nickname
pineafan63fc5e22022-08-04 22:04:10 +0100131 if (member.id === interaction.guild.ownerId) return true;
pineafan377794f2022-04-18 19:01:01 +0100132 // Check if the user has manage_nicknames permission
pineafane23c4ec2022-07-27 21:56:27 +0100133 if (! member.permissions.has("MANAGE_NICKNAMES")) throw "You do not have the *Manage Nicknames* permission";
pineafane625d782022-05-09 18:04:32 +0100134 // Allow changing your own nickname
pineafan63fc5e22022-08-04 22:04:10 +0100135 if (member === apply) return true;
pineafan377794f2022-04-18 19:01:01 +0100136 // Check if the user is below on the role list
pineafan63fc5e22022-08-04 22:04:10 +0100137 if (! (memberPos > applyPos)) throw "You do not have a role higher than that member";
pineafan377794f2022-04-18 19:01:01 +0100138 // Allow change
pineafan63fc5e22022-08-04 22:04:10 +0100139 return true;
140};
pineafan32767212022-03-14 21:27:39 +0000141
142export { command, callback, check };