blob: 9a101e820b0db5a1d5cd99cda6f567c3176d6bd9 [file] [log] [blame]
pineafanbd02b4a2022-08-05 22:01:38 +01001import { CommandInteraction, GuildMember } from "discord.js";
pineafan32767212022-03-14 21:27:39 +00002import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
pineafan32767212022-03-14 21:27:39 +00003import confirmationMessage from "../../utils/confirmationMessage.js";
pineafan4edb7762022-06-26 19:21:04 +01004import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
pineafan32767212022-03-14 21:27:39 +00005import keyValueList from "../../utils/generateKeyValueList.js";
pineafan63fc5e22022-08-04 22:04:10 +01006import client from "../../utils/client.js";
pineafan32767212022-03-14 21:27:39 +00007
8const command = (builder: SlashCommandSubcommandBuilder) =>
9 builder
pineafan63fc5e22022-08-04 22:04:10 +010010 .setName("nick")
11 .setDescription("Changes a users nickname")
Skyler Grey11236ba2022-08-08 21:13:33 +010012 .addUserOption((option) => option.setName("user").setDescription("The user to change").setRequired(true))
Skyler Grey75ea9172022-08-06 10:22:23 +010013 .addStringOption((option) =>
Skyler Grey11236ba2022-08-08 21:13:33 +010014 option.setName("name").setDescription("The name to set | Leave blank to clear").setRequired(false)
Skyler Grey75ea9172022-08-06 10:22:23 +010015 );
pineafan32767212022-03-14 21:27:39 +000016
pineafan3a02ea32022-08-11 21:35:04 +010017const callback = async (interaction: CommandInteraction): Promise<unknown> => {
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;
Skyler Greyad002172022-08-16 18:48:26 +010022 let timedOut = false;
23 let success = false;
24 while (!timedOut && !success) {
pineafan02ba0232022-07-24 22:16:15 +010025 confirmation = await new confirmationMessage(interaction)
26 .setEmoji("PUNISH.NICKNAME.RED")
27 .setTitle("Nickname")
Skyler Grey75ea9172022-08-06 10:22:23 +010028 .setDescription(
29 keyValueList({
30 user: renderUser(interaction.options.getUser("user")),
31 "new nickname": `${
Skyler Grey11236ba2022-08-08 21:13:33 +010032 interaction.options.getString("name") ? interaction.options.getString("name") : "*No nickname*"
Skyler Grey75ea9172022-08-06 10:22:23 +010033 }`
34 }) +
35 `The user **will${notify ? "" : " not"}** be notified\n\n` +
Skyler Grey11236ba2022-08-08 21:13:33 +010036 `Are you sure you want to ${interaction.options.getString("name") ? "change" : "clear"} <@!${
37 (interaction.options.getMember("user") as GuildMember).id
Skyler Grey75ea9172022-08-06 10:22:23 +010038 }>'s nickname?`
39 )
pineafan02ba0232022-07-24 22:16:15 +010040 .setColor("Danger")
Skyler Grey75ea9172022-08-06 10:22:23 +010041 .addCustomBoolean(
42 "notify",
43 "Notify user",
44 false,
45 null,
46 null,
47 "ICONS.NOTIFY." + (notify ? "ON" : "OFF"),
48 notify
49 )
pineafan63fc5e22022-08-04 22:04:10 +010050 .send(interaction.options.getString("name") !== null);
Skyler Greyad002172022-08-16 18:48:26 +010051 if (confirmation.cancelled) timedOut = true;
52 else if (confirmation.success) success = true;
53 else if (confirmation.components) {
pineafan63fc5e22022-08-04 22:04:10 +010054 notify = confirmation.components.notify.active;
pineafan02ba0232022-07-24 22:16:15 +010055 }
56 }
Skyler Greyad002172022-08-16 18:48:26 +010057 if (timedOut) {
58 return await interaction.editReply({
Skyler Grey75ea9172022-08-06 10:22:23 +010059 embeds: [
60 new EmojiEmbed()
61 .setEmoji("PUNISH.NICKNAME.GREEN")
62 .setTitle("Nickname")
63 .setDescription("No changes were made")
64 .setStatus("Success")
65 ],
66 components: []
67 });
pineafan377794f2022-04-18 19:01:01 +010068 }
Skyler Greyad002172022-08-16 18:48:26 +010069 let dmd = false;
70 let dm;
71 try {
72 if (notify) {
73 dm = await (interaction.options.getMember("user") as GuildMember).send({
74 embeds: [
75 new EmojiEmbed()
76 .setEmoji("PUNISH.NICKNAME.RED")
77 .setTitle("Nickname changed")
78 .setDescription(
79 `Your nickname was ${interaction.options.getString("name") ? "changed" : "cleared"} in ${
80 interaction.guild.name
81 }.` +
82 (interaction.options.getString("name")
83 ? ` it is now: ${interaction.options.getString("name")}`
84 : "") +
85 "\n\n" +
86 (confirmation.components.appeal.response
87 ? `You can appeal this here: <#${confirmation.components.appeal.response}>`
88 : "")
89 )
90 .setStatus("Danger")
91 ]
92 });
93 dmd = true;
94 }
95 } catch {
96 dmd = false;
97 }
98 try {
99 const member = interaction.options.getMember("user") as GuildMember;
100 const before = member.nickname;
101 const nickname = interaction.options.getString("name");
102 member.setNickname(nickname ?? null, "Nucleus Nickname command");
103 await client.database.history.create(
104 "nickname",
105 interaction.guild.id,
106 member.user,
107 interaction.user,
108 null,
109 before,
110 nickname
111 );
112 const { log, NucleusColors, entry, renderUser, renderDelta } = client.logger;
113 const data = {
114 meta: {
115 type: "memberUpdate",
116 displayName: "Member Updated",
117 calculateType: "guildMemberUpdate",
118 color: NucleusColors.yellow,
119 emoji: "PUNISH.NICKNAME.YELLOW",
120 timestamp: new Date().getTime()
121 },
122 list: {
123 memberId: entry(member.id, `\`${member.id}\``),
124 before: entry(before, before ? before : "*None*"),
125 after: entry(nickname, nickname ? nickname : "*None*"),
126 updated: entry(new Date().getTime(), renderDelta(new Date().getTime())),
127 updatedBy: entry(interaction.user.id, renderUser(interaction.user))
128 },
129 hidden: {
130 guild: interaction.guild.id
131 }
132 };
133 log(data);
134 } catch {
135 await interaction.editReply({
136 embeds: [
137 new EmojiEmbed()
138 .setEmoji("PUNISH.NICKNAME.RED")
139 .setTitle("Nickname")
140 .setDescription("Something went wrong and the users nickname could not be changed.")
141 .setStatus("Danger")
142 ],
143 components: []
144 });
145 if (dmd) await dm.delete();
146 return;
147 }
148 const failed = !dmd && notify;
149 await interaction.editReply({
150 embeds: [
151 new EmojiEmbed()
152 .setEmoji(`PUNISH.NICKNAME.${failed ? "YELLOW" : "GREEN"}`)
153 .setTitle("Nickname")
154 .setDescription(
155 "The members nickname was changed" +
156 (failed ? ", but was not notified" : "") +
157 (confirmation.components.appeal.response
158 ? ` and an appeal ticket was opened in <#${confirmation.components.appeal.response}>`
159 : "")
160 )
161 .setStatus(failed ? "Warning" : "Success")
162 ],
163 components: []
164 });
pineafan63fc5e22022-08-04 22:04:10 +0100165};
pineafan32767212022-03-14 21:27:39 +0000166
pineafanbd02b4a2022-08-05 22:01:38 +0100167const check = (interaction: CommandInteraction) => {
Skyler Grey75ea9172022-08-06 10:22:23 +0100168 const member = interaction.member as GuildMember;
169 const me = interaction.guild.me!;
170 const apply = interaction.options.getMember("user") as GuildMember;
pineafan3a02ea32022-08-11 21:35:04 +0100171 if (member === null || me === null || apply === null) throw new Error("That member is not in the server");
pineafan62ce1922022-08-25 20:34:45 +0100172 const memberPos = member.roles.cache.size ? member.roles.highest.position : 0;
173 const mePos = me.roles.cache.size ? me.roles.highest.position : 0;
174 const applyPos = apply.roles.cache.size ? apply.roles.highest.position : 0;
pineafanc1c18792022-08-03 21:41:36 +0100175 // Do not allow any changing of the owner
pineafan3a02ea32022-08-11 21:35:04 +0100176 if (member.id === interaction.guild.ownerId) throw new Error("You cannot change the owner's nickname");
pineafan377794f2022-04-18 19:01:01 +0100177 // Check if Nucleus can change the nickname
pineafan3a02ea32022-08-11 21:35:04 +0100178 if (!(mePos > applyPos)) throw new Error("I do not have a role higher than that member");
pineafan377794f2022-04-18 19:01:01 +0100179 // Check if Nucleus has permission to change the nickname
pineafan3a02ea32022-08-11 21:35:04 +0100180 if (!me.permissions.has("MANAGE_NICKNAMES")) throw new Error("I do not have the *Manage Nicknames* permission");
pineafan377794f2022-04-18 19:01:01 +0100181 // Allow the owner to change anyone's nickname
pineafan63fc5e22022-08-04 22:04:10 +0100182 if (member.id === interaction.guild.ownerId) return true;
pineafan377794f2022-04-18 19:01:01 +0100183 // Check if the user has manage_nicknames permission
pineafan3a02ea32022-08-11 21:35:04 +0100184 if (!member.permissions.has("MANAGE_NICKNAMES"))
185 throw new Error("You do not have the *Manage Nicknames* permission");
pineafane625d782022-05-09 18:04:32 +0100186 // Allow changing your own nickname
pineafan63fc5e22022-08-04 22:04:10 +0100187 if (member === apply) return true;
pineafan377794f2022-04-18 19:01:01 +0100188 // Check if the user is below on the role list
pineafan3a02ea32022-08-11 21:35:04 +0100189 if (!(memberPos > applyPos)) throw new Error("You do not have a role higher than that member");
pineafan377794f2022-04-18 19:01:01 +0100190 // Allow change
pineafan63fc5e22022-08-04 22:04:10 +0100191 return true;
192};
pineafan32767212022-03-14 21:27:39 +0000193
Skyler Grey75ea9172022-08-06 10:22:23 +0100194export { command, callback, check };