blob: 09753759d7ca5ec4f8e9f84b98292bc1a6a7c1e1 [file] [log] [blame]
pineafanbd02b4a2022-08-05 22:01:38 +01001import { CommandInteraction, GuildMember } from "discord.js";
PineaFan64486c42022-12-28 09:21:04 +00002import type { 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
PineaFan64486c42022-12-28 09:21:04 +00008
9const command = (builder: SlashCommandSubcommandBuilder) => builder
10 .setName("nick")
11 .setDescription("Changes a users nickname")
12 .addUserOption((option) => option.setName("user").setDescription("The user to change").setRequired(true))
13 .addStringOption((option) =>
14 option.setName("name").setDescription("The name to set | Leave blank to clear").setRequired(false)
15 );
16
pineafan32767212022-03-14 21:27:39 +000017
pineafan3a02ea32022-08-11 21:35:04 +010018const callback = async (interaction: CommandInteraction): Promise<unknown> => {
pineafan63fc5e22022-08-04 22:04:10 +010019 const { renderUser } = client.logger;
pineafan377794f2022-04-18 19:01:01 +010020 // TODO:[Modals] Replace this with a modal
pineafan02ba0232022-07-24 22:16:15 +010021 let notify = true;
22 let confirmation;
Skyler Greyad002172022-08-16 18:48:26 +010023 let timedOut = false;
24 let success = false;
25 while (!timedOut && !success) {
pineafan02ba0232022-07-24 22:16:15 +010026 confirmation = await new confirmationMessage(interaction)
27 .setEmoji("PUNISH.NICKNAME.RED")
28 .setTitle("Nickname")
Skyler Grey75ea9172022-08-06 10:22:23 +010029 .setDescription(
30 keyValueList({
31 user: renderUser(interaction.options.getUser("user")),
32 "new nickname": `${
Skyler Grey11236ba2022-08-08 21:13:33 +010033 interaction.options.getString("name") ? interaction.options.getString("name") : "*No nickname*"
Skyler Grey75ea9172022-08-06 10:22:23 +010034 }`
35 }) +
36 `The user **will${notify ? "" : " not"}** be notified\n\n` +
Skyler Grey11236ba2022-08-08 21:13:33 +010037 `Are you sure you want to ${interaction.options.getString("name") ? "change" : "clear"} <@!${
38 (interaction.options.getMember("user") as GuildMember).id
Skyler Grey75ea9172022-08-06 10:22:23 +010039 }>'s nickname?`
40 )
pineafan02ba0232022-07-24 22:16:15 +010041 .setColor("Danger")
Skyler Grey75ea9172022-08-06 10:22:23 +010042 .addCustomBoolean(
43 "notify",
44 "Notify user",
45 false,
46 null,
47 null,
PineaFana34d04b2023-01-03 22:05:42 +000048 null,
Skyler Grey75ea9172022-08-06 10:22:23 +010049 "ICONS.NOTIFY." + (notify ? "ON" : "OFF"),
50 notify
51 )
pineafan63fc5e22022-08-04 22:04:10 +010052 .send(interaction.options.getString("name") !== null);
Skyler Greyad002172022-08-16 18:48:26 +010053 if (confirmation.cancelled) timedOut = true;
54 else if (confirmation.success) success = true;
55 else if (confirmation.components) {
pineafan63fc5e22022-08-04 22:04:10 +010056 notify = confirmation.components.notify.active;
pineafan02ba0232022-07-24 22:16:15 +010057 }
58 }
Skyler Greyad002172022-08-16 18:48:26 +010059 if (timedOut) {
60 return await interaction.editReply({
Skyler Grey75ea9172022-08-06 10:22:23 +010061 embeds: [
62 new EmojiEmbed()
63 .setEmoji("PUNISH.NICKNAME.GREEN")
64 .setTitle("Nickname")
65 .setDescription("No changes were made")
66 .setStatus("Success")
67 ],
68 components: []
69 });
pineafan377794f2022-04-18 19:01:01 +010070 }
Skyler Greyad002172022-08-16 18:48:26 +010071 let dmd = false;
72 let dm;
73 try {
74 if (notify) {
75 dm = await (interaction.options.getMember("user") as GuildMember).send({
76 embeds: [
77 new EmojiEmbed()
78 .setEmoji("PUNISH.NICKNAME.RED")
79 .setTitle("Nickname changed")
80 .setDescription(
81 `Your nickname was ${interaction.options.getString("name") ? "changed" : "cleared"} in ${
82 interaction.guild.name
83 }.` +
84 (interaction.options.getString("name")
85 ? ` it is now: ${interaction.options.getString("name")}`
86 : "") +
87 "\n\n" +
88 (confirmation.components.appeal.response
89 ? `You can appeal this here: <#${confirmation.components.appeal.response}>`
90 : "")
91 )
92 .setStatus("Danger")
93 ]
94 });
95 dmd = true;
96 }
97 } catch {
98 dmd = false;
99 }
100 try {
101 const member = interaction.options.getMember("user") as GuildMember;
102 const before = member.nickname;
103 const nickname = interaction.options.getString("name");
104 member.setNickname(nickname ?? null, "Nucleus Nickname command");
105 await client.database.history.create(
106 "nickname",
107 interaction.guild.id,
108 member.user,
109 interaction.user,
110 null,
111 before,
112 nickname
113 );
114 const { log, NucleusColors, entry, renderUser, renderDelta } = client.logger;
115 const data = {
116 meta: {
117 type: "memberUpdate",
118 displayName: "Member Updated",
119 calculateType: "guildMemberUpdate",
120 color: NucleusColors.yellow,
121 emoji: "PUNISH.NICKNAME.YELLOW",
122 timestamp: new Date().getTime()
123 },
124 list: {
125 memberId: entry(member.id, `\`${member.id}\``),
126 before: entry(before, before ? before : "*None*"),
127 after: entry(nickname, nickname ? nickname : "*None*"),
128 updated: entry(new Date().getTime(), renderDelta(new Date().getTime())),
129 updatedBy: entry(interaction.user.id, renderUser(interaction.user))
130 },
131 hidden: {
132 guild: interaction.guild.id
133 }
134 };
135 log(data);
136 } catch {
137 await interaction.editReply({
138 embeds: [
139 new EmojiEmbed()
140 .setEmoji("PUNISH.NICKNAME.RED")
141 .setTitle("Nickname")
142 .setDescription("Something went wrong and the users nickname could not be changed.")
143 .setStatus("Danger")
144 ],
145 components: []
146 });
147 if (dmd) await dm.delete();
148 return;
149 }
150 const failed = !dmd && notify;
151 await interaction.editReply({
152 embeds: [
153 new EmojiEmbed()
154 .setEmoji(`PUNISH.NICKNAME.${failed ? "YELLOW" : "GREEN"}`)
155 .setTitle("Nickname")
156 .setDescription(
157 "The members nickname was changed" +
158 (failed ? ", but was not notified" : "") +
159 (confirmation.components.appeal.response
160 ? ` and an appeal ticket was opened in <#${confirmation.components.appeal.response}>`
161 : "")
162 )
163 .setStatus(failed ? "Warning" : "Success")
164 ],
165 components: []
166 });
pineafan63fc5e22022-08-04 22:04:10 +0100167};
pineafan32767212022-03-14 21:27:39 +0000168
pineafanbd02b4a2022-08-05 22:01:38 +0100169const check = (interaction: CommandInteraction) => {
Skyler Grey75ea9172022-08-06 10:22:23 +0100170 const member = interaction.member as GuildMember;
171 const me = interaction.guild.me!;
172 const apply = interaction.options.getMember("user") as GuildMember;
pineafan3a02ea32022-08-11 21:35:04 +0100173 if (member === null || me === null || apply === null) throw new Error("That member is not in the server");
pineafan62ce1922022-08-25 20:34:45 +0100174 const memberPos = member.roles.cache.size ? member.roles.highest.position : 0;
175 const mePos = me.roles.cache.size ? me.roles.highest.position : 0;
176 const applyPos = apply.roles.cache.size ? apply.roles.highest.position : 0;
pineafanc1c18792022-08-03 21:41:36 +0100177 // Do not allow any changing of the owner
pineafan3a02ea32022-08-11 21:35:04 +0100178 if (member.id === interaction.guild.ownerId) throw new Error("You cannot change the owner's nickname");
pineafan377794f2022-04-18 19:01:01 +0100179 // Check if Nucleus can change the nickname
pineafan3a02ea32022-08-11 21:35:04 +0100180 if (!(mePos > applyPos)) throw new Error("I do not have a role higher than that member");
pineafan377794f2022-04-18 19:01:01 +0100181 // Check if Nucleus has permission to change the nickname
pineafan3a02ea32022-08-11 21:35:04 +0100182 if (!me.permissions.has("MANAGE_NICKNAMES")) throw new Error("I do not have the *Manage Nicknames* permission");
pineafan377794f2022-04-18 19:01:01 +0100183 // Allow the owner to change anyone's nickname
pineafan63fc5e22022-08-04 22:04:10 +0100184 if (member.id === interaction.guild.ownerId) return true;
pineafan377794f2022-04-18 19:01:01 +0100185 // Check if the user has manage_nicknames permission
pineafan3a02ea32022-08-11 21:35:04 +0100186 if (!member.permissions.has("MANAGE_NICKNAMES"))
187 throw new Error("You do not have the *Manage Nicknames* permission");
pineafane625d782022-05-09 18:04:32 +0100188 // Allow changing your own nickname
pineafan63fc5e22022-08-04 22:04:10 +0100189 if (member === apply) return true;
pineafan377794f2022-04-18 19:01:01 +0100190 // Check if the user is below on the role list
pineafan3a02ea32022-08-11 21:35:04 +0100191 if (!(memberPos > applyPos)) throw new Error("You do not have a role higher than that member");
pineafan377794f2022-04-18 19:01:01 +0100192 // Allow change
pineafan63fc5e22022-08-04 22:04:10 +0100193 return true;
194};
pineafan32767212022-03-14 21:27:39 +0000195
Skyler Grey75ea9172022-08-06 10:22:23 +0100196export { command, callback, check };