blob: c5e45b6357debb5adea2fdecfd6eb2c36488a2bf [file] [log] [blame]
PineaFan538d3752023-01-12 21:48:23 +00001import type { 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")
PineaFan538d3752023-01-12 21:48:23 +000011 // .setNameLocalizations({"ru": "name", "zh-CN": "nickname"})
PineaFan64486c42022-12-28 09:21:04 +000012 .setDescription("Changes a users nickname")
13 .addUserOption((option) => option.setName("user").setDescription("The user to change").setRequired(true))
14 .addStringOption((option) =>
15 option.setName("name").setDescription("The name to set | Leave blank to clear").setRequired(false)
16 );
17
pineafan32767212022-03-14 21:27:39 +000018
pineafan3a02ea32022-08-11 21:35:04 +010019const callback = async (interaction: CommandInteraction): Promise<unknown> => {
pineafan63fc5e22022-08-04 22:04:10 +010020 const { renderUser } = client.logger;
pineafan377794f2022-04-18 19:01:01 +010021 // TODO:[Modals] Replace this with a modal
pineafan02ba0232022-07-24 22:16:15 +010022 let notify = true;
23 let confirmation;
Skyler Greyad002172022-08-16 18:48:26 +010024 let timedOut = false;
25 let success = false;
26 while (!timedOut && !success) {
pineafan02ba0232022-07-24 22:16:15 +010027 confirmation = await new confirmationMessage(interaction)
28 .setEmoji("PUNISH.NICKNAME.RED")
29 .setTitle("Nickname")
Skyler Grey75ea9172022-08-06 10:22:23 +010030 .setDescription(
31 keyValueList({
32 user: renderUser(interaction.options.getUser("user")),
33 "new nickname": `${
Skyler Grey11236ba2022-08-08 21:13:33 +010034 interaction.options.getString("name") ? interaction.options.getString("name") : "*No nickname*"
Skyler Grey75ea9172022-08-06 10:22:23 +010035 }`
36 }) +
37 `The user **will${notify ? "" : " not"}** be notified\n\n` +
Skyler Grey11236ba2022-08-08 21:13:33 +010038 `Are you sure you want to ${interaction.options.getString("name") ? "change" : "clear"} <@!${
39 (interaction.options.getMember("user") as GuildMember).id
Skyler Grey75ea9172022-08-06 10:22:23 +010040 }>'s nickname?`
41 )
pineafan02ba0232022-07-24 22:16:15 +010042 .setColor("Danger")
Skyler Grey75ea9172022-08-06 10:22:23 +010043 .addCustomBoolean(
44 "notify",
45 "Notify user",
46 false,
47 null,
48 null,
PineaFana34d04b2023-01-03 22:05:42 +000049 null,
Skyler Grey75ea9172022-08-06 10:22:23 +010050 "ICONS.NOTIFY." + (notify ? "ON" : "OFF"),
51 notify
52 )
pineafan63fc5e22022-08-04 22:04:10 +010053 .send(interaction.options.getString("name") !== null);
Skyler Greyad002172022-08-16 18:48:26 +010054 if (confirmation.cancelled) timedOut = true;
55 else if (confirmation.success) success = true;
56 else if (confirmation.components) {
pineafan63fc5e22022-08-04 22:04:10 +010057 notify = confirmation.components.notify.active;
pineafan02ba0232022-07-24 22:16:15 +010058 }
59 }
Skyler Greyad002172022-08-16 18:48:26 +010060 if (timedOut) {
61 return await interaction.editReply({
Skyler Grey75ea9172022-08-06 10:22:23 +010062 embeds: [
63 new EmojiEmbed()
64 .setEmoji("PUNISH.NICKNAME.GREEN")
65 .setTitle("Nickname")
66 .setDescription("No changes were made")
67 .setStatus("Success")
68 ],
69 components: []
70 });
pineafan377794f2022-04-18 19:01:01 +010071 }
Skyler Greyad002172022-08-16 18:48:26 +010072 let dmd = false;
73 let dm;
74 try {
75 if (notify) {
76 dm = await (interaction.options.getMember("user") as GuildMember).send({
77 embeds: [
78 new EmojiEmbed()
79 .setEmoji("PUNISH.NICKNAME.RED")
80 .setTitle("Nickname changed")
81 .setDescription(
82 `Your nickname was ${interaction.options.getString("name") ? "changed" : "cleared"} in ${
83 interaction.guild.name
84 }.` +
85 (interaction.options.getString("name")
86 ? ` it is now: ${interaction.options.getString("name")}`
87 : "") +
88 "\n\n" +
89 (confirmation.components.appeal.response
90 ? `You can appeal this here: <#${confirmation.components.appeal.response}>`
91 : "")
92 )
93 .setStatus("Danger")
94 ]
95 });
96 dmd = true;
97 }
98 } catch {
99 dmd = false;
100 }
101 try {
102 const member = interaction.options.getMember("user") as GuildMember;
103 const before = member.nickname;
104 const nickname = interaction.options.getString("name");
105 member.setNickname(nickname ?? null, "Nucleus Nickname command");
106 await client.database.history.create(
107 "nickname",
108 interaction.guild.id,
109 member.user,
110 interaction.user,
111 null,
112 before,
113 nickname
114 );
115 const { log, NucleusColors, entry, renderUser, renderDelta } = client.logger;
116 const data = {
117 meta: {
118 type: "memberUpdate",
119 displayName: "Member Updated",
120 calculateType: "guildMemberUpdate",
121 color: NucleusColors.yellow,
122 emoji: "PUNISH.NICKNAME.YELLOW",
123 timestamp: new Date().getTime()
124 },
125 list: {
126 memberId: entry(member.id, `\`${member.id}\``),
127 before: entry(before, before ? before : "*None*"),
128 after: entry(nickname, nickname ? nickname : "*None*"),
129 updated: entry(new Date().getTime(), renderDelta(new Date().getTime())),
130 updatedBy: entry(interaction.user.id, renderUser(interaction.user))
131 },
132 hidden: {
133 guild: interaction.guild.id
134 }
135 };
136 log(data);
137 } catch {
138 await interaction.editReply({
139 embeds: [
140 new EmojiEmbed()
141 .setEmoji("PUNISH.NICKNAME.RED")
142 .setTitle("Nickname")
143 .setDescription("Something went wrong and the users nickname could not be changed.")
144 .setStatus("Danger")
145 ],
146 components: []
147 });
148 if (dmd) await dm.delete();
149 return;
150 }
151 const failed = !dmd && notify;
152 await interaction.editReply({
153 embeds: [
154 new EmojiEmbed()
155 .setEmoji(`PUNISH.NICKNAME.${failed ? "YELLOW" : "GREEN"}`)
156 .setTitle("Nickname")
157 .setDescription(
158 "The members nickname was changed" +
159 (failed ? ", but was not notified" : "") +
160 (confirmation.components.appeal.response
161 ? ` and an appeal ticket was opened in <#${confirmation.components.appeal.response}>`
162 : "")
163 )
164 .setStatus(failed ? "Warning" : "Success")
165 ],
166 components: []
167 });
pineafan63fc5e22022-08-04 22:04:10 +0100168};
pineafan32767212022-03-14 21:27:39 +0000169
pineafanbd02b4a2022-08-05 22:01:38 +0100170const check = (interaction: CommandInteraction) => {
Skyler Grey75ea9172022-08-06 10:22:23 +0100171 const member = interaction.member as GuildMember;
PineaFan1dee28f2023-01-16 22:09:07 +0000172 const me = interaction.guild!.members.me!;
Skyler Grey75ea9172022-08-06 10:22:23 +0100173 const apply = interaction.options.getMember("user") as GuildMember;
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;
PineaFan1dee28f2023-01-16 22:09:07 +0000177 if (!interaction.guild) return false;
pineafanc1c18792022-08-03 21:41:36 +0100178 // Do not allow any changing of the owner
pineafan3a02ea32022-08-11 21:35:04 +0100179 if (member.id === interaction.guild.ownerId) throw new Error("You cannot change the owner's nickname");
pineafan377794f2022-04-18 19:01:01 +0100180 // Check if Nucleus can change the nickname
pineafan3a02ea32022-08-11 21:35:04 +0100181 if (!(mePos > applyPos)) throw new Error("I do not have a role higher than that member");
pineafan377794f2022-04-18 19:01:01 +0100182 // Check if Nucleus has permission to change the nickname
PineaFan1dee28f2023-01-16 22:09:07 +0000183 if (!me.permissions.has("ManageNicknames")) throw new Error("I do not have the *Manage Nicknames* permission");
pineafan377794f2022-04-18 19:01:01 +0100184 // Allow the owner to change anyone's nickname
pineafan63fc5e22022-08-04 22:04:10 +0100185 if (member.id === interaction.guild.ownerId) return true;
pineafan377794f2022-04-18 19:01:01 +0100186 // Check if the user has manage_nicknames permission
PineaFan1dee28f2023-01-16 22:09:07 +0000187 if (!member.permissions.has("ManageNicknames"))
pineafan3a02ea32022-08-11 21:35:04 +0100188 throw new Error("You do not have the *Manage Nicknames* permission");
pineafane625d782022-05-09 18:04:32 +0100189 // Allow changing your own nickname
pineafan63fc5e22022-08-04 22:04:10 +0100190 if (member === apply) return true;
pineafan377794f2022-04-18 19:01:01 +0100191 // Check if the user is below on the role list
pineafan3a02ea32022-08-11 21:35:04 +0100192 if (!(memberPos > applyPos)) throw new Error("You do not have a role higher than that member");
pineafan377794f2022-04-18 19:01:01 +0100193 // Allow change
pineafan63fc5e22022-08-04 22:04:10 +0100194 return true;
195};
pineafan32767212022-03-14 21:27:39 +0000196
Skyler Grey75ea9172022-08-06 10:22:23 +0100197export { command, callback, check };