blob: 5f096ae005c9da68a4576d103731b957e5588ec4 [file] [log] [blame]
pineafan63fc5e22022-08-04 22:04:10 +01001import { LoadingEmbed } from "./../../utils/defaultEmbeds.js";
Skyler Grey75ea9172022-08-06 10:22:23 +01002import Discord, {
3 CommandInteraction,
4 GuildMember,
5 Message,
6 MessageActionRow,
7 MessageActionRowComponent,
8 MessageButton,
9 MessageComponentInteraction,
10 SelectMenuInteraction
11} from "discord.js";
12import {
13 SelectMenuOption,
14 SlashCommandSubcommandBuilder
15} from "@discordjs/builders";
pineafan4edb7762022-06-26 19:21:04 +010016import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
pineafan377794f2022-04-18 19:01:01 +010017import getEmojiByName from "../../utils/getEmojiByName.js";
18import generateKeyValueList from "../../utils/generateKeyValueList.js";
pineafan34369e62022-05-18 16:52:37 +010019import createPageIndicator from "../../utils/createPageIndicator.js";
pineafan63fc5e22022-08-04 22:04:10 +010020import client from "../../utils/client.js";
pineafan4f164f32022-02-26 22:07:12 +000021
22const command = (builder: SlashCommandSubcommandBuilder) =>
23 builder
pineafan63fc5e22022-08-04 22:04:10 +010024 .setName("about")
25 .setDescription("Shows info about a user")
Skyler Grey75ea9172022-08-06 10:22:23 +010026 .addUserOption((option) =>
27 option
28 .setName("user")
29 .setDescription(
30 "The user to get info about | Default: Yourself"
31 )
32 );
pineafanea063042022-05-19 19:08:44 +010033
34class Embed {
35 embed: Discord.MessageEmbed;
36 title: string;
pineafan63fc5e22022-08-04 22:04:10 +010037 description = "";
38 pageId = 0;
Skyler Grey75ea9172022-08-06 10:22:23 +010039 setEmbed(embed: Discord.MessageEmbed) {
40 this.embed = embed;
41 return this;
42 }
43 setTitle(title: string) {
44 this.title = title;
45 return this;
46 }
47 setDescription(description: string) {
48 this.description = description;
49 return this;
50 }
51 setPageId(pageId: number) {
52 this.pageId = pageId;
53 return this;
54 }
pineafanea063042022-05-19 19:08:44 +010055}
56
Skyler Grey1a67e182022-08-04 23:05:44 +010057const callback = async (interaction: CommandInteraction): Promise<void> => {
pineafan63fc5e22022-08-04 22:04:10 +010058 const { renderUser, renderDelta } = client.logger;
Skyler Grey75ea9172022-08-06 10:22:23 +010059 const member = (interaction.options.getMember("user") ||
60 interaction.member) as Discord.GuildMember;
pineafan63fc5e22022-08-04 22:04:10 +010061 const flags: string[] = [];
Skyler Grey75ea9172022-08-06 10:22:23 +010062 if (
63 [
64 "438733159748599813", // Pinea
65 "317731855317336067", // Mini
66 "261900651230003201", // Coded
67 "511655498676699136" // Zan
68 ].includes(member.user.id)
69 ) {
70 flags.push("NUCLEUSDEVELOPER");
71 }
72 if (
73 (await client.guilds.cache.get("684492926528651336")?.members.fetch())
74 ?.filter((m: GuildMember) =>
75 m.roles.cache.has("760896837866749972")
76 )
77 ?.map((m: GuildMember) => m.id)
78 .includes(member.user.id)
79 ) {
80 flags.push("CLICKSDEVELOPER");
81 }
82 member.user.flags.toArray().map((flag) => {
pineafan63fc5e22022-08-04 22:04:10 +010083 flags.push(flag.toString());
84 });
Skyler Grey75ea9172022-08-06 10:22:23 +010085 if (member.user.bot) {
86 flags.push("BOT");
87 }
pineafan377794f2022-04-18 19:01:01 +010088 // Check if they are boosting the server
Skyler Grey75ea9172022-08-06 10:22:23 +010089 if (member.premiumSince) {
90 flags.push("BOOSTER");
91 }
pineafan63fc5e22022-08-04 22:04:10 +010092 const nameReplacements = {
Skyler Grey75ea9172022-08-06 10:22:23 +010093 NUCLEUSDEVELOPER: "**Nucleus Developer**",
94 CLICKSDEVELOPER: "Clicks Developer",
95 HOUSE_BRAVERY: "Hypesquad Bravery",
96 HOUSE_BRILLIANCE: "Hypesquad Brilliance",
97 HOUSE_BALANCE: "Hypesquad Balance",
98 HYPESQUAD_EVENTS: "Hypesquad Events",
99 EARLY_SUPPORTER: "Early Supporter",
100 BUGHUNTER_LEVEL_1: "Bug Hunter Level 1",
101 BUGHUNTER_LEVEL_2: "Bug Hunter Level 2",
102 PARTNERED_SERVER_OWNER: "Partnered Server Owner",
103 DISCORD_EMPLOYEE: "Discord Staff",
104 EARLY_VERIFIED_BOT_DEVELOPER: "Verified Bot Developer",
105 BOT: "Bot",
106 BOOSTER: "Server Booster"
pineafan63fc5e22022-08-04 22:04:10 +0100107 };
108 const members = await interaction.guild.members.fetch();
109 const membersArray = [...members.values()];
110 membersArray.sort((a, b) => a.joinedTimestamp - b.joinedTimestamp);
Skyler Grey75ea9172022-08-06 10:22:23 +0100111 const joinPos = membersArray.findIndex((m) => m.id === member.user.id);
pineafan377794f2022-04-18 19:01:01 +0100112
Skyler Grey75ea9172022-08-06 10:22:23 +0100113 const roles = member.roles.cache
114 .filter((r) => r.id !== interaction.guild.id)
115 .sort();
pineafan377794f2022-04-18 19:01:01 +0100116 let s = "";
117 let count = 0;
pineafan63fc5e22022-08-04 22:04:10 +0100118 let ended = false;
Skyler Grey75ea9172022-08-06 10:22:23 +0100119 roles.map((item) => {
pineafan377794f2022-04-18 19:01:01 +0100120 if (ended) return;
pineafan63fc5e22022-08-04 22:04:10 +0100121 const string = `<@&${item.id}>, `;
Skyler Grey75ea9172022-08-06 10:22:23 +0100122 if (s.length + string.length > 1000) {
pineafan63fc5e22022-08-04 22:04:10 +0100123 ended = true;
124 s += `and ${roles.size - count} more`;
125 return;
126 }
Skyler Grey75ea9172022-08-06 10:22:23 +0100127 count++;
pineafan377794f2022-04-18 19:01:01 +0100128 s += string;
pineafan63fc5e22022-08-04 22:04:10 +0100129 });
Skyler Grey75ea9172022-08-06 10:22:23 +0100130 if (s.length > 0 && !ended) s = s.slice(0, -2);
pineafan377794f2022-04-18 19:01:01 +0100131
pineafan63fc5e22022-08-04 22:04:10 +0100132 let perms = "";
133 const permsArray = {
Skyler Grey75ea9172022-08-06 10:22:23 +0100134 ADMINISTRATOR: "Administrator",
135 MANAGE_GUILD: "Manage Server",
136 MANAGE_ROLES: "Manage Roles",
137 MANAGE_CHANNELS: "Manage Channels",
138 KICK_MEMBERS: "Kick Members",
139 BAN_MEMBERS: "Ban Members",
140 MODERATE_MEMBERS: "Moderate Members",
141 MANAGE_NICKNAMES: "Manage Nicknames",
142 MANAGE_WEBHOOKS: "Manage Webhooks",
143 MANAGE_MESSAGES: "Manage Messages",
144 VIEW_AUDIT_LOG: "View Audit Log",
145 MENTION_EVERYONE: "Mention Everyone"
pineafan63fc5e22022-08-04 22:04:10 +0100146 };
Skyler Grey75ea9172022-08-06 10:22:23 +0100147 Object.keys(permsArray).map((perm) => {
148 const hasPerm = member.permissions.has(
149 perm as Discord.PermissionString
150 );
151 perms += `${getEmojiByName(
152 "CONTROL." + (hasPerm ? "TICK" : "CROSS")
153 )} ${permsArray[perm]}\n`;
pineafan63fc5e22022-08-04 22:04:10 +0100154 });
pineafan377794f2022-04-18 19:01:01 +0100155
pineafanea063042022-05-19 19:08:44 +0100156 let selectPaneOpen = false;
157
pineafan63fc5e22022-08-04 22:04:10 +0100158 const embeds = [
pineafanea063042022-05-19 19:08:44 +0100159 new Embed()
Skyler Grey75ea9172022-08-06 10:22:23 +0100160 .setEmbed(
161 new EmojiEmbed()
162 .setTitle("User Info: General")
163 .setStatus("Success")
164 .setEmoji("MEMBER.JOIN")
165 .setDescription(
166 flags
167 .map((flag) => {
168 if (nameReplacements[flag]) {
169 return (
170 getEmojiByName(`BADGES.${flag}`) +
171 " " +
172 nameReplacements[flag]
173 );
174 }
175 })
176 .join("\n") +
177 "\n\n" +
178 generateKeyValueList({
179 member: renderUser(member.user),
180 nickname: member.nickname || "*None set*",
181 id: `\`${member.id}\``,
182 "joined the server": renderDelta(
183 member.joinedTimestamp
184 ),
185 "joined discord": renderDelta(
186 member.user.createdTimestamp
187 ),
188 "boost status": member.premiumSince
189 ? `Started boosting ${renderDelta(
190 member.premiumSinceTimestamp
191 )}`
192 : "*Not boosting*",
193 "join position": `${joinPos + 1}`
194 })
195 )
196 .setThumbnail(
197 member.user.displayAvatarURL({ dynamic: true })
198 )
199 .setImage(
200 (await member.user.fetch()).bannerURL({ format: "gif" })
201 )
202 )
203 .setTitle("General")
204 .setDescription("General information about the user")
205 .setPageId(0),
pineafanea063042022-05-19 19:08:44 +0100206 new Embed()
Skyler Grey75ea9172022-08-06 10:22:23 +0100207 .setEmbed(
208 new EmojiEmbed()
209 .setTitle("User Info: Roles")
210 .setStatus("Success")
211 .setEmoji("GUILD.ROLES.CREATE")
212 .setDescription(
213 generateKeyValueList({
214 member: renderUser(member.user),
215 id: `\`${member.id}\``,
216 roles: `${member.roles.cache.size - 1}`
217 }) +
218 "\n" +
219 (s.length > 0 ? s : "*None*") +
220 "\n"
221 )
222 .setThumbnail(
223 member.user.displayAvatarURL({ dynamic: true })
224 )
225 )
226 .setTitle("Roles")
227 .setDescription("Roles the user has")
228 .setPageId(1),
pineafanea063042022-05-19 19:08:44 +0100229 new Embed()
Skyler Grey75ea9172022-08-06 10:22:23 +0100230 .setEmbed(
231 new EmojiEmbed()
232 .setTitle("User Info: Key Permissions")
233 .setStatus("Success")
234 .setEmoji("GUILD.ROLES.CREATE")
235 .setDescription(
236 generateKeyValueList({
237 member: renderUser(member.user),
238 id: `\`${member.id}\``
239 }) +
240 "\n" +
241 perms
242 )
243 .setThumbnail(
244 member.user.displayAvatarURL({ dynamic: true })
245 )
246 )
247 .setTitle("Key Permissions")
248 .setDescription("Key permissions the user has")
249 .setPageId(2)
pineafan63fc5e22022-08-04 22:04:10 +0100250 ];
Skyler Grey75ea9172022-08-06 10:22:23 +0100251 const m = (await interaction.reply({
252 embeds: LoadingEmbed,
253 fetchReply: true,
254 ephemeral: true
255 })) as Message;
pineafan63fc5e22022-08-04 22:04:10 +0100256 let page = 0;
257 let breakReason = "";
pineafan377794f2022-04-18 19:01:01 +0100258 while (true) {
pineafan63fc5e22022-08-04 22:04:10 +0100259 const em = new Discord.MessageEmbed(embeds[page].embed);
Skyler Grey75ea9172022-08-06 10:22:23 +0100260 em.setDescription(
261 em.description + "\n" + createPageIndicator(embeds.length, page)
262 );
pineafan63fc5e22022-08-04 22:04:10 +0100263 let selectPane = [];
pineafanea063042022-05-19 19:08:44 +0100264
265 if (selectPaneOpen) {
pineafan63fc5e22022-08-04 22:04:10 +0100266 const options = [];
Skyler Grey75ea9172022-08-06 10:22:23 +0100267 embeds.forEach((embed) => {
268 options.push(
269 new SelectMenuOption({
270 label: embed.title,
271 value: embed.pageId.toString(),
272 description: embed.description || ""
273 })
274 );
pineafan63fc5e22022-08-04 22:04:10 +0100275 });
Skyler Grey75ea9172022-08-06 10:22:23 +0100276 selectPane = [
277 new MessageActionRow().addComponents([
278 new Discord.MessageSelectMenu()
279 .addOptions(options)
280 .setCustomId("page")
281 .setMaxValues(1)
282 .setPlaceholder("Choose a page...")
283 ])
284 ];
pineafanea063042022-05-19 19:08:44 +0100285 }
pineafan377794f2022-04-18 19:01:01 +0100286 await interaction.editReply({
pineafan34369e62022-05-18 16:52:37 +0100287 embeds: [em],
Skyler Grey75ea9172022-08-06 10:22:23 +0100288 components: selectPane.concat([
289 new MessageActionRow().addComponents([
290 new MessageButton()
291 .setEmoji(getEmojiByName("CONTROL.LEFT", "id"))
292 .setStyle("SECONDARY")
293 .setCustomId("left")
294 .setDisabled(page === 0),
295 new MessageButton()
296 .setEmoji(getEmojiByName("CONTROL.MENU", "id"))
297 .setStyle(selectPaneOpen ? "PRIMARY" : "SECONDARY")
298 .setCustomId("select")
299 .setDisabled(false),
300 new MessageButton()
301 .setEmoji(getEmojiByName("CONTROL.RIGHT", "id"))
302 .setCustomId("right")
303 .setStyle("SECONDARY")
304 .setDisabled(page === embeds.length - 1),
305 new MessageButton()
306 .setEmoji(getEmojiByName("CONTROL.CROSS", "id"))
307 .setCustomId("close")
308 .setStyle("DANGER")
309 ])
310 ])
pineafan63fc5e22022-08-04 22:04:10 +0100311 });
Skyler Grey1a67e182022-08-04 23:05:44 +0100312 let i: MessageComponentInteraction;
pineafan377794f2022-04-18 19:01:01 +0100313 try {
Skyler Grey75ea9172022-08-06 10:22:23 +0100314 i = await m.awaitMessageComponent({ time: 300000 });
315 } catch {
316 breakReason = "Message timed out";
317 break;
318 }
pineafan63fc5e22022-08-04 22:04:10 +0100319 i.deferUpdate();
Skyler Grey1a67e182022-08-04 23:05:44 +0100320 if ((i.component as MessageActionRowComponent).customId === "left") {
pineafan377794f2022-04-18 19:01:01 +0100321 if (page > 0) page--;
pineafanea063042022-05-19 19:08:44 +0100322 selectPaneOpen = false;
Skyler Grey75ea9172022-08-06 10:22:23 +0100323 } else if (
324 (i.component as MessageActionRowComponent).customId === "right"
325 ) {
pineafan377794f2022-04-18 19:01:01 +0100326 if (page < embeds.length - 1) page++;
pineafanea063042022-05-19 19:08:44 +0100327 selectPaneOpen = false;
Skyler Grey75ea9172022-08-06 10:22:23 +0100328 } else if (
329 (i.component as MessageActionRowComponent).customId === "select"
330 ) {
pineafanea063042022-05-19 19:08:44 +0100331 selectPaneOpen = !selectPaneOpen;
Skyler Grey75ea9172022-08-06 10:22:23 +0100332 } else if (
333 (i.component as MessageActionRowComponent).customId === "close"
334 ) {
pineafan167bde32022-05-19 19:33:46 +0100335 breakReason = "Message closed";
pineafan377794f2022-04-18 19:01:01 +0100336 break;
Skyler Grey75ea9172022-08-06 10:22:23 +0100337 } else if (
338 (i.component as MessageActionRowComponent).customId === "page"
339 ) {
Skyler Grey1a67e182022-08-04 23:05:44 +0100340 page = parseInt((i as SelectMenuInteraction).values[0]);
pineafanea063042022-05-19 19:08:44 +0100341 selectPaneOpen = false;
pineafan377794f2022-04-18 19:01:01 +0100342 } else {
pineafan167bde32022-05-19 19:33:46 +0100343 breakReason = "Message closed";
pineafan377794f2022-04-18 19:01:01 +0100344 break;
345 }
346 }
pineafan63fc5e22022-08-04 22:04:10 +0100347 const em = new Discord.MessageEmbed(embeds[page].embed);
Skyler Grey75ea9172022-08-06 10:22:23 +0100348 em.setDescription(
349 em.description +
350 "\n" +
351 createPageIndicator(embeds.length, page) +
352 " | " +
353 breakReason
354 );
355 await interaction.editReply({
356 embeds: [em],
357 components: [
358 new MessageActionRow().addComponents([
359 new MessageButton()
360 .setEmoji(getEmojiByName("CONTROL.LEFT", "id"))
361 .setStyle("SECONDARY")
362 .setCustomId("left")
363 .setDisabled(true),
364 new MessageButton()
365 .setEmoji(getEmojiByName("CONTROL.MENU", "id"))
366 .setStyle("SECONDARY")
367 .setCustomId("select")
368 .setDisabled(true),
369 new MessageButton()
370 .setEmoji(getEmojiByName("CONTROL.RIGHT", "id"))
371 .setCustomId("right")
372 .setStyle("SECONDARY")
373 .setDisabled(true),
374 new MessageButton()
375 .setEmoji(getEmojiByName("CONTROL.CROSS", "id"))
376 .setCustomId("close")
377 .setStyle("DANGER")
378 .setDisabled(true)
379 ])
380 ]
381 });
pineafan63fc5e22022-08-04 22:04:10 +0100382};
pineafan4f164f32022-02-26 22:07:12 +0000383
Skyler Grey1a67e182022-08-04 23:05:44 +0100384const check = () => {
pineafan4f164f32022-02-26 22:07:12 +0000385 return true;
pineafan63fc5e22022-08-04 22:04:10 +0100386};
pineafan4f164f32022-02-26 22:07:12 +0000387
388export { command };
389export { callback };
Skyler Grey1a67e182022-08-04 23:05:44 +0100390export { check };