blob: 129359f26d9f3348e3b836c7a952bfc9c0459996 [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> => {
Skyler Greyc634e2b2022-08-06 17:50:48 +010058 if (!interaction.guild) return;
pineafan63fc5e22022-08-04 22:04:10 +010059 const { renderUser, renderDelta } = client.logger;
Skyler Greyc634e2b2022-08-06 17:50:48 +010060 const member = (interaction.options.getMember("user") ??
Skyler Grey75ea9172022-08-06 10:22:23 +010061 interaction.member) as Discord.GuildMember;
pineafan63fc5e22022-08-04 22:04:10 +010062 const flags: string[] = [];
Skyler Grey75ea9172022-08-06 10:22:23 +010063 if (
64 [
65 "438733159748599813", // Pinea
66 "317731855317336067", // Mini
67 "261900651230003201", // Coded
68 "511655498676699136" // Zan
69 ].includes(member.user.id)
70 ) {
71 flags.push("NUCLEUSDEVELOPER");
72 }
73 if (
74 (await client.guilds.cache.get("684492926528651336")?.members.fetch())
75 ?.filter((m: GuildMember) =>
76 m.roles.cache.has("760896837866749972")
77 )
78 ?.map((m: GuildMember) => m.id)
79 .includes(member.user.id)
80 ) {
81 flags.push("CLICKSDEVELOPER");
82 }
83 member.user.flags.toArray().map((flag) => {
pineafan63fc5e22022-08-04 22:04:10 +010084 flags.push(flag.toString());
85 });
Skyler Grey75ea9172022-08-06 10:22:23 +010086 if (member.user.bot) {
87 flags.push("BOT");
88 }
pineafan377794f2022-04-18 19:01:01 +010089 // Check if they are boosting the server
Skyler Grey75ea9172022-08-06 10:22:23 +010090 if (member.premiumSince) {
91 flags.push("BOOSTER");
92 }
pineafan63fc5e22022-08-04 22:04:10 +010093 const nameReplacements = {
Skyler Grey75ea9172022-08-06 10:22:23 +010094 NUCLEUSDEVELOPER: "**Nucleus Developer**",
95 CLICKSDEVELOPER: "Clicks Developer",
96 HOUSE_BRAVERY: "Hypesquad Bravery",
97 HOUSE_BRILLIANCE: "Hypesquad Brilliance",
98 HOUSE_BALANCE: "Hypesquad Balance",
99 HYPESQUAD_EVENTS: "Hypesquad Events",
100 EARLY_SUPPORTER: "Early Supporter",
101 BUGHUNTER_LEVEL_1: "Bug Hunter Level 1",
102 BUGHUNTER_LEVEL_2: "Bug Hunter Level 2",
103 PARTNERED_SERVER_OWNER: "Partnered Server Owner",
104 DISCORD_EMPLOYEE: "Discord Staff",
105 EARLY_VERIFIED_BOT_DEVELOPER: "Verified Bot Developer",
106 BOT: "Bot",
107 BOOSTER: "Server Booster"
pineafan63fc5e22022-08-04 22:04:10 +0100108 };
109 const members = await interaction.guild.members.fetch();
110 const membersArray = [...members.values()];
Skyler Greyc634e2b2022-08-06 17:50:48 +0100111 membersArray.sort((a, b) => {
112 if (a.joinedTimestamp === null) return 1;
113 if (b.joinedTimestamp === null) return -1;
114 return a.joinedTimestamp - b.joinedTimestamp;
115 });
Skyler Grey75ea9172022-08-06 10:22:23 +0100116 const joinPos = membersArray.findIndex((m) => m.id === member.user.id);
pineafan377794f2022-04-18 19:01:01 +0100117
Skyler Grey75ea9172022-08-06 10:22:23 +0100118 const roles = member.roles.cache
Skyler Greyc634e2b2022-08-06 17:50:48 +0100119 .filter((r) => r.id !== interaction.guild!.id)
Skyler Grey75ea9172022-08-06 10:22:23 +0100120 .sort();
pineafan377794f2022-04-18 19:01:01 +0100121 let s = "";
122 let count = 0;
pineafan63fc5e22022-08-04 22:04:10 +0100123 let ended = false;
Skyler Greyc634e2b2022-08-06 17:50:48 +0100124 for (const roleId in roles) {
125 const string = `<@&${roleId}>, `;
Skyler Grey75ea9172022-08-06 10:22:23 +0100126 if (s.length + string.length > 1000) {
pineafan63fc5e22022-08-04 22:04:10 +0100127 ended = true;
128 s += `and ${roles.size - count} more`;
Skyler Greyc634e2b2022-08-06 17:50:48 +0100129 break;
pineafan63fc5e22022-08-04 22:04:10 +0100130 }
Skyler Grey75ea9172022-08-06 10:22:23 +0100131 count++;
pineafan377794f2022-04-18 19:01:01 +0100132 s += string;
Skyler Greyc634e2b2022-08-06 17:50:48 +0100133 }
Skyler Grey75ea9172022-08-06 10:22:23 +0100134 if (s.length > 0 && !ended) s = s.slice(0, -2);
pineafan377794f2022-04-18 19:01:01 +0100135
pineafan63fc5e22022-08-04 22:04:10 +0100136 let perms = "";
137 const permsArray = {
Skyler Grey75ea9172022-08-06 10:22:23 +0100138 ADMINISTRATOR: "Administrator",
139 MANAGE_GUILD: "Manage Server",
140 MANAGE_ROLES: "Manage Roles",
141 MANAGE_CHANNELS: "Manage Channels",
142 KICK_MEMBERS: "Kick Members",
143 BAN_MEMBERS: "Ban Members",
144 MODERATE_MEMBERS: "Moderate Members",
145 MANAGE_NICKNAMES: "Manage Nicknames",
146 MANAGE_WEBHOOKS: "Manage Webhooks",
147 MANAGE_MESSAGES: "Manage Messages",
148 VIEW_AUDIT_LOG: "View Audit Log",
149 MENTION_EVERYONE: "Mention Everyone"
pineafan63fc5e22022-08-04 22:04:10 +0100150 };
Skyler Grey75ea9172022-08-06 10:22:23 +0100151 Object.keys(permsArray).map((perm) => {
152 const hasPerm = member.permissions.has(
153 perm as Discord.PermissionString
154 );
155 perms += `${getEmojiByName(
156 "CONTROL." + (hasPerm ? "TICK" : "CROSS")
157 )} ${permsArray[perm]}\n`;
pineafan63fc5e22022-08-04 22:04:10 +0100158 });
pineafan377794f2022-04-18 19:01:01 +0100159
pineafanea063042022-05-19 19:08:44 +0100160 let selectPaneOpen = false;
161
pineafan63fc5e22022-08-04 22:04:10 +0100162 const embeds = [
pineafanea063042022-05-19 19:08:44 +0100163 new Embed()
Skyler Grey75ea9172022-08-06 10:22:23 +0100164 .setEmbed(
165 new EmojiEmbed()
166 .setTitle("User Info: General")
167 .setStatus("Success")
168 .setEmoji("MEMBER.JOIN")
169 .setDescription(
170 flags
171 .map((flag) => {
172 if (nameReplacements[flag]) {
173 return (
174 getEmojiByName(`BADGES.${flag}`) +
175 " " +
176 nameReplacements[flag]
177 );
178 }
179 })
180 .join("\n") +
181 "\n\n" +
182 generateKeyValueList({
183 member: renderUser(member.user),
184 nickname: member.nickname || "*None set*",
185 id: `\`${member.id}\``,
186 "joined the server": renderDelta(
187 member.joinedTimestamp
188 ),
189 "joined discord": renderDelta(
190 member.user.createdTimestamp
191 ),
192 "boost status": member.premiumSince
193 ? `Started boosting ${renderDelta(
194 member.premiumSinceTimestamp
195 )}`
196 : "*Not boosting*",
197 "join position": `${joinPos + 1}`
198 })
199 )
200 .setThumbnail(
201 member.user.displayAvatarURL({ dynamic: true })
202 )
203 .setImage(
204 (await member.user.fetch()).bannerURL({ format: "gif" })
205 )
206 )
207 .setTitle("General")
208 .setDescription("General information about the user")
209 .setPageId(0),
pineafanea063042022-05-19 19:08:44 +0100210 new Embed()
Skyler Grey75ea9172022-08-06 10:22:23 +0100211 .setEmbed(
212 new EmojiEmbed()
213 .setTitle("User Info: Roles")
214 .setStatus("Success")
215 .setEmoji("GUILD.ROLES.CREATE")
216 .setDescription(
217 generateKeyValueList({
218 member: renderUser(member.user),
219 id: `\`${member.id}\``,
220 roles: `${member.roles.cache.size - 1}`
221 }) +
222 "\n" +
223 (s.length > 0 ? s : "*None*") +
224 "\n"
225 )
226 .setThumbnail(
227 member.user.displayAvatarURL({ dynamic: true })
228 )
229 )
230 .setTitle("Roles")
231 .setDescription("Roles the user has")
232 .setPageId(1),
pineafanea063042022-05-19 19:08:44 +0100233 new Embed()
Skyler Grey75ea9172022-08-06 10:22:23 +0100234 .setEmbed(
235 new EmojiEmbed()
236 .setTitle("User Info: Key Permissions")
237 .setStatus("Success")
238 .setEmoji("GUILD.ROLES.CREATE")
239 .setDescription(
240 generateKeyValueList({
241 member: renderUser(member.user),
242 id: `\`${member.id}\``
243 }) +
244 "\n" +
245 perms
246 )
247 .setThumbnail(
248 member.user.displayAvatarURL({ dynamic: true })
249 )
250 )
251 .setTitle("Key Permissions")
252 .setDescription("Key permissions the user has")
253 .setPageId(2)
pineafan63fc5e22022-08-04 22:04:10 +0100254 ];
Skyler Grey75ea9172022-08-06 10:22:23 +0100255 const m = (await interaction.reply({
256 embeds: LoadingEmbed,
257 fetchReply: true,
258 ephemeral: true
259 })) as Message;
pineafan63fc5e22022-08-04 22:04:10 +0100260 let page = 0;
261 let breakReason = "";
pineafan377794f2022-04-18 19:01:01 +0100262 while (true) {
pineafan63fc5e22022-08-04 22:04:10 +0100263 const em = new Discord.MessageEmbed(embeds[page].embed);
Skyler Grey75ea9172022-08-06 10:22:23 +0100264 em.setDescription(
265 em.description + "\n" + createPageIndicator(embeds.length, page)
266 );
pineafan63fc5e22022-08-04 22:04:10 +0100267 let selectPane = [];
pineafanea063042022-05-19 19:08:44 +0100268
269 if (selectPaneOpen) {
pineafan63fc5e22022-08-04 22:04:10 +0100270 const options = [];
Skyler Grey75ea9172022-08-06 10:22:23 +0100271 embeds.forEach((embed) => {
272 options.push(
273 new SelectMenuOption({
274 label: embed.title,
275 value: embed.pageId.toString(),
276 description: embed.description || ""
277 })
278 );
pineafan63fc5e22022-08-04 22:04:10 +0100279 });
Skyler Grey75ea9172022-08-06 10:22:23 +0100280 selectPane = [
281 new MessageActionRow().addComponents([
282 new Discord.MessageSelectMenu()
283 .addOptions(options)
284 .setCustomId("page")
285 .setMaxValues(1)
286 .setPlaceholder("Choose a page...")
287 ])
288 ];
pineafanea063042022-05-19 19:08:44 +0100289 }
pineafan377794f2022-04-18 19:01:01 +0100290 await interaction.editReply({
pineafan34369e62022-05-18 16:52:37 +0100291 embeds: [em],
Skyler Grey75ea9172022-08-06 10:22:23 +0100292 components: selectPane.concat([
293 new MessageActionRow().addComponents([
294 new MessageButton()
295 .setEmoji(getEmojiByName("CONTROL.LEFT", "id"))
296 .setStyle("SECONDARY")
297 .setCustomId("left")
298 .setDisabled(page === 0),
299 new MessageButton()
300 .setEmoji(getEmojiByName("CONTROL.MENU", "id"))
301 .setStyle(selectPaneOpen ? "PRIMARY" : "SECONDARY")
302 .setCustomId("select")
303 .setDisabled(false),
304 new MessageButton()
305 .setEmoji(getEmojiByName("CONTROL.RIGHT", "id"))
306 .setCustomId("right")
307 .setStyle("SECONDARY")
308 .setDisabled(page === embeds.length - 1),
309 new MessageButton()
310 .setEmoji(getEmojiByName("CONTROL.CROSS", "id"))
311 .setCustomId("close")
312 .setStyle("DANGER")
313 ])
314 ])
pineafan63fc5e22022-08-04 22:04:10 +0100315 });
Skyler Grey1a67e182022-08-04 23:05:44 +0100316 let i: MessageComponentInteraction;
pineafan377794f2022-04-18 19:01:01 +0100317 try {
Skyler Grey75ea9172022-08-06 10:22:23 +0100318 i = await m.awaitMessageComponent({ time: 300000 });
319 } catch {
320 breakReason = "Message timed out";
321 break;
322 }
pineafan63fc5e22022-08-04 22:04:10 +0100323 i.deferUpdate();
Skyler Grey1a67e182022-08-04 23:05:44 +0100324 if ((i.component as MessageActionRowComponent).customId === "left") {
pineafan377794f2022-04-18 19:01:01 +0100325 if (page > 0) page--;
pineafanea063042022-05-19 19:08:44 +0100326 selectPaneOpen = false;
Skyler Grey75ea9172022-08-06 10:22:23 +0100327 } else if (
328 (i.component as MessageActionRowComponent).customId === "right"
329 ) {
pineafan377794f2022-04-18 19:01:01 +0100330 if (page < embeds.length - 1) page++;
pineafanea063042022-05-19 19:08:44 +0100331 selectPaneOpen = false;
Skyler Grey75ea9172022-08-06 10:22:23 +0100332 } else if (
333 (i.component as MessageActionRowComponent).customId === "select"
334 ) {
pineafanea063042022-05-19 19:08:44 +0100335 selectPaneOpen = !selectPaneOpen;
Skyler Grey75ea9172022-08-06 10:22:23 +0100336 } else if (
337 (i.component as MessageActionRowComponent).customId === "close"
338 ) {
pineafan167bde32022-05-19 19:33:46 +0100339 breakReason = "Message closed";
pineafan377794f2022-04-18 19:01:01 +0100340 break;
Skyler Grey75ea9172022-08-06 10:22:23 +0100341 } else if (
342 (i.component as MessageActionRowComponent).customId === "page"
343 ) {
Skyler Grey1a67e182022-08-04 23:05:44 +0100344 page = parseInt((i as SelectMenuInteraction).values[0]);
pineafanea063042022-05-19 19:08:44 +0100345 selectPaneOpen = false;
pineafan377794f2022-04-18 19:01:01 +0100346 } else {
pineafan167bde32022-05-19 19:33:46 +0100347 breakReason = "Message closed";
pineafan377794f2022-04-18 19:01:01 +0100348 break;
349 }
350 }
pineafan63fc5e22022-08-04 22:04:10 +0100351 const em = new Discord.MessageEmbed(embeds[page].embed);
Skyler Grey75ea9172022-08-06 10:22:23 +0100352 em.setDescription(
353 em.description +
354 "\n" +
355 createPageIndicator(embeds.length, page) +
356 " | " +
357 breakReason
358 );
359 await interaction.editReply({
360 embeds: [em],
361 components: [
362 new MessageActionRow().addComponents([
363 new MessageButton()
364 .setEmoji(getEmojiByName("CONTROL.LEFT", "id"))
365 .setStyle("SECONDARY")
366 .setCustomId("left")
367 .setDisabled(true),
368 new MessageButton()
369 .setEmoji(getEmojiByName("CONTROL.MENU", "id"))
370 .setStyle("SECONDARY")
371 .setCustomId("select")
372 .setDisabled(true),
373 new MessageButton()
374 .setEmoji(getEmojiByName("CONTROL.RIGHT", "id"))
375 .setCustomId("right")
376 .setStyle("SECONDARY")
377 .setDisabled(true),
378 new MessageButton()
379 .setEmoji(getEmojiByName("CONTROL.CROSS", "id"))
380 .setCustomId("close")
381 .setStyle("DANGER")
382 .setDisabled(true)
383 ])
384 ]
385 });
pineafan63fc5e22022-08-04 22:04:10 +0100386};
pineafan4f164f32022-02-26 22:07:12 +0000387
Skyler Grey1a67e182022-08-04 23:05:44 +0100388const check = () => {
pineafan4f164f32022-02-26 22:07:12 +0000389 return true;
pineafan63fc5e22022-08-04 22:04:10 +0100390};
pineafan4f164f32022-02-26 22:07:12 +0000391
392export { command };
393export { callback };
Skyler Grey1a67e182022-08-04 23:05:44 +0100394export { check };