blob: 0eb85809eb1d68a4aa7d14459a1dcaeb1135b6a5 [file] [log] [blame]
PineaFan0d06edc2023-01-17 22:10:31 +00001import { LoadingEmbed, Embed } from "../../utils/defaults.js";
Skyler Grey75ea9172022-08-06 10:22:23 +01002import Discord, {
3 CommandInteraction,
4 GuildMember,
TheCodedProf21c08592022-09-13 14:14:43 -04005 ActionRowBuilder,
TheCodedProf21c08592022-09-13 14:14:43 -04006 ButtonBuilder,
Skyler Grey75ea9172022-08-06 10:22:23 +01007 MessageComponentInteraction,
PineaFanc729e762023-01-02 22:11:34 +00008 ButtonStyle,
9 PermissionResolvable,
10 APISelectMenuOption,
11 StringSelectMenuBuilder
Skyler Grey75ea9172022-08-06 10:22:23 +010012} from "discord.js";
Samuel Shuert27bf3cd2023-03-03 15:51:25 -050013import type { SlashCommandSubcommandBuilder } from "discord.js";
pineafan4edb7762022-06-26 19:21:04 +010014import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
pineafan377794f2022-04-18 19:01:01 +010015import getEmojiByName from "../../utils/getEmojiByName.js";
16import generateKeyValueList from "../../utils/generateKeyValueList.js";
pineafan34369e62022-05-18 16:52:37 +010017import createPageIndicator from "../../utils/createPageIndicator.js";
pineafan63fc5e22022-08-04 22:04:10 +010018import client from "../../utils/client.js";
pineafan4f164f32022-02-26 22:07:12 +000019
20const command = (builder: SlashCommandSubcommandBuilder) =>
21 builder
pineafan63fc5e22022-08-04 22:04:10 +010022 .setName("about")
23 .setDescription("Shows info about a user")
Skyler Grey75ea9172022-08-06 10:22:23 +010024 .addUserOption((option) =>
Skyler Grey11236ba2022-08-08 21:13:33 +010025 option.setName("user").setDescription("The user to get info about | Default: Yourself")
Skyler Grey75ea9172022-08-06 10:22:23 +010026 );
pineafanea063042022-05-19 19:08:44 +010027
Skyler Grey1a67e182022-08-04 23:05:44 +010028const callback = async (interaction: CommandInteraction): Promise<void> => {
PineaFanc729e762023-01-02 22:11:34 +000029 const guild = interaction.guild!;
Skyler Grey11236ba2022-08-08 21:13:33 +010030 const member = (interaction.options.getMember("user") ?? interaction.member) as Discord.GuildMember;
PineaFanc729e762023-01-02 22:11:34 +000031 await userAbout(guild, member, interaction);
32}
33
34async function userAbout(guild: Discord.Guild, member: Discord.GuildMember, interaction: Discord.CommandInteraction | Discord.ContextMenuCommandInteraction) {
35 await member.user.fetch()
36 await member.fetch()
37 await interaction.reply({
38 embeds: LoadingEmbed,
39 fetchReply: true,
40 ephemeral: true
41 });
42 const { renderUser, renderDelta } = client.logger;
pineafan63fc5e22022-08-04 22:04:10 +010043 const flags: string[] = [];
Skyler Grey75ea9172022-08-06 10:22:23 +010044 if (
45 [
46 "438733159748599813", // Pinea
47 "317731855317336067", // Mini
48 "261900651230003201", // Coded
49 "511655498676699136" // Zan
50 ].includes(member.user.id)
51 ) {
52 flags.push("NUCLEUSDEVELOPER");
53 }
54 if (
55 (await client.guilds.cache.get("684492926528651336")?.members.fetch())
Skyler Grey11236ba2022-08-08 21:13:33 +010056 ?.filter((m: GuildMember) => m.roles.cache.has("760896837866749972"))
Skyler Grey75ea9172022-08-06 10:22:23 +010057 ?.map((m: GuildMember) => m.id)
58 .includes(member.user.id)
59 ) {
60 flags.push("CLICKSDEVELOPER");
61 }
PineaFanc729e762023-01-02 22:11:34 +000062 if (member.user.flags) { member.user.flags.toArray().map((flag) => { flags.push(flag.toString()); }); }
63 if (member.user.bot) { flags.push("BOT"); }
pineafan377794f2022-04-18 19:01:01 +010064 // Check if they are boosting the server
PineaFanc729e762023-01-02 22:11:34 +000065 if (member.premiumSince) { flags.push("BOOSTER"); }
66 const nameReplacements: Record<string, string> = {
Skyler Grey75ea9172022-08-06 10:22:23 +010067 NUCLEUSDEVELOPER: "**Nucleus Developer**",
68 CLICKSDEVELOPER: "Clicks Developer",
Skyler Grey75ea9172022-08-06 10:22:23 +010069 BOT: "Bot",
PineaFanc729e762023-01-02 22:11:34 +000070 BOOSTER: "Server Booster",
71 HypeSquadOnlineHouse1: "Hypesquad Bravery",
72 HypeSquadOnlineHouse2: "Hypesquad Brilliance",
73 HypeSquadOnlineHouse3: "Hypesquad Balance",
74 Hypesquad: "Hypesquad Events",
75 PremiumEarlySupporter: "Early Supporter",
76 BugHunterLevel1: "Bug Hunter Level 1",
77 BugHunterLevel2: "Bug Hunter Level 2",
78 Partner: "Partnered Server Owner",
79 Staff: "Discord Staff",
PineaFana34d04b2023-01-03 22:05:42 +000080 VerifiedDeveloper: "Verified Bot Developer",
81 ActiveDeveloper: "Active Developer",
PineaFan538d3752023-01-12 21:48:23 +000082 Quarantined: "Quarantined [[What does this mean?]](https://support.discord.com/hc/en-us/articles/6461420677527)",
PineaFana34d04b2023-01-03 22:05:42 +000083 Spammer: "Likely Spammer"
PineaFanc729e762023-01-02 22:11:34 +000084 // CertifiedModerator
PineaFanc729e762023-01-02 22:11:34 +000085 // VerifiedBot
pineafan63fc5e22022-08-04 22:04:10 +010086 };
PineaFanc729e762023-01-02 22:11:34 +000087 const members = await guild.members.fetch();
pineafan63fc5e22022-08-04 22:04:10 +010088 const membersArray = [...members.values()];
Skyler Greyc634e2b2022-08-06 17:50:48 +010089 membersArray.sort((a, b) => {
90 if (a.joinedTimestamp === null) return 1;
91 if (b.joinedTimestamp === null) return -1;
92 return a.joinedTimestamp - b.joinedTimestamp;
93 });
Skyler Grey75ea9172022-08-06 10:22:23 +010094 const joinPos = membersArray.findIndex((m) => m.id === member.user.id);
pineafan377794f2022-04-18 19:01:01 +010095
PineaFanc729e762023-01-02 22:11:34 +000096 const roles = member.roles.cache.filter((r) => r.id !== guild.id).sort();
pineafan377794f2022-04-18 19:01:01 +010097 let s = "";
98 let count = 0;
pineafan63fc5e22022-08-04 22:04:10 +010099 let ended = false;
PineaFana34d04b2023-01-03 22:05:42 +0000100 for (const roleId of roles) {
101 const string = `<@&${roleId[1].id}>, `;
Skyler Grey75ea9172022-08-06 10:22:23 +0100102 if (s.length + string.length > 1000) {
pineafan63fc5e22022-08-04 22:04:10 +0100103 ended = true;
104 s += `and ${roles.size - count} more`;
Skyler Greyc634e2b2022-08-06 17:50:48 +0100105 break;
pineafan63fc5e22022-08-04 22:04:10 +0100106 }
Skyler Grey75ea9172022-08-06 10:22:23 +0100107 count++;
pineafan377794f2022-04-18 19:01:01 +0100108 s += string;
Skyler Greyc634e2b2022-08-06 17:50:48 +0100109 }
Skyler Grey75ea9172022-08-06 10:22:23 +0100110 if (s.length > 0 && !ended) s = s.slice(0, -2);
pineafan377794f2022-04-18 19:01:01 +0100111
pineafan63fc5e22022-08-04 22:04:10 +0100112 let perms = "";
PineaFanc729e762023-01-02 22:11:34 +0000113 const permsArray: Record<string, string> = {
114 Administrator: "Administrator",
115 ManageGuild: "Manage Server",
116 ManageRoles: "Manage Roles",
117 ManageChannels: "Manage Channels",
118 KickMembers: "Kick Members",
119 BanMembers: "Ban Members",
120 ModerateMembers: "Moderate Members",
121 ManageNicknames: "Manage Nicknames",
122 ManageWebhooks: "Manage Webhooks",
123 ManageMessages: "Manage Messages",
124 ViewAuditLog: "View Audit Log",
125 MentionEveryone: "Mention Everyone"
pineafan63fc5e22022-08-04 22:04:10 +0100126 };
Skyler Grey75ea9172022-08-06 10:22:23 +0100127 Object.keys(permsArray).map((perm) => {
PineaFanc729e762023-01-02 22:11:34 +0000128 const hasPerm = member.permissions.has(perm as PermissionResolvable);
Skyler Grey11236ba2022-08-08 21:13:33 +0100129 perms += `${getEmojiByName("CONTROL." + (hasPerm ? "TICK" : "CROSS"))} ${permsArray[perm]}\n`;
pineafan63fc5e22022-08-04 22:04:10 +0100130 });
pineafan377794f2022-04-18 19:01:01 +0100131
pineafanea063042022-05-19 19:08:44 +0100132 let selectPaneOpen = false;
133
pineafan63fc5e22022-08-04 22:04:10 +0100134 const embeds = [
pineafanea063042022-05-19 19:08:44 +0100135 new Embed()
Skyler Grey75ea9172022-08-06 10:22:23 +0100136 .setEmbed(
137 new EmojiEmbed()
138 .setTitle("User Info: General")
139 .setStatus("Success")
140 .setEmoji("MEMBER.JOIN")
141 .setDescription(
PineaFanc729e762023-01-02 22:11:34 +0000142 flags.map((flag) => {
143 if (nameReplacements[flag]) {
144 const emoji = getEmojiByName(`BADGES.${flag}`)
145 if (emoji) return (emoji + " " + nameReplacements[flag] + "\n");
146 else return nameReplacements[flag] + "\n";
147 }
148 }).join("") + "\n" +
149 generateKeyValueList({
150 member: renderUser(member.user),
151 nickname: member.nickname ?? "*None set*",
152 id: `\`${member.id}\``,
153 "joined the server": renderDelta(member.joinedTimestamp!),
154 "joined discord": renderDelta(member.user.createdTimestamp),
155 "boost status": member.premiumSince
156 ? `Started boosting ${renderDelta(member.premiumSinceTimestamp!)}`
157 : "*Not boosting*",
158 "join position": `${joinPos + 1}`
159 })
Skyler Grey75ea9172022-08-06 10:22:23 +0100160 )
PineaFanc729e762023-01-02 22:11:34 +0000161 .setThumbnail(member.user.displayAvatarURL())
Skyler Grey75ea9172022-08-06 10:22:23 +0100162 )
163 .setTitle("General")
164 .setDescription("General information about the user")
165 .setPageId(0),
pineafanea063042022-05-19 19:08:44 +0100166 new Embed()
Skyler Grey75ea9172022-08-06 10:22:23 +0100167 .setEmbed(
168 new EmojiEmbed()
169 .setTitle("User Info: Roles")
170 .setStatus("Success")
171 .setEmoji("GUILD.ROLES.CREATE")
172 .setDescription(
173 generateKeyValueList({
174 member: renderUser(member.user),
175 id: `\`${member.id}\``,
Samuel Shuert27bf3cd2023-03-03 15:51:25 -0500176 roles: `${member.roles.cache.size - 1}`
177 }) + "\n" + (s.length > 0 ? s : "*None*") + "\n"
Skyler Grey75ea9172022-08-06 10:22:23 +0100178 )
Skyler Grey75ea9172022-08-06 10:22:23 +0100179 )
180 .setTitle("Roles")
181 .setDescription("Roles the user has")
182 .setPageId(1),
pineafanea063042022-05-19 19:08:44 +0100183 new Embed()
Skyler Grey75ea9172022-08-06 10:22:23 +0100184 .setEmbed(
185 new EmojiEmbed()
186 .setTitle("User Info: Key Permissions")
187 .setStatus("Success")
188 .setEmoji("GUILD.ROLES.CREATE")
189 .setDescription(
190 generateKeyValueList({
191 member: renderUser(member.user),
192 id: `\`${member.id}\``
193 }) +
194 "\n" +
195 perms
196 )
Skyler Grey75ea9172022-08-06 10:22:23 +0100197 )
198 .setTitle("Key Permissions")
199 .setDescription("Key permissions the user has")
200 .setPageId(2)
pineafan63fc5e22022-08-04 22:04:10 +0100201 ];
PineaFanc729e762023-01-02 22:11:34 +0000202 if (member.user.bannerURL() ) { embeds[0]!.embed.setImage(member.user.bannerURL()!); }
pineafan63fc5e22022-08-04 22:04:10 +0100203 let page = 0;
Skyler Greyad002172022-08-16 18:48:26 +0100204 let timedOut = false;
PineaFanc729e762023-01-02 22:11:34 +0000205 for (const embed of embeds) {
206 embed.embed.setDescription(embed.embed.description + "\n" + createPageIndicator(embeds.length, embed.pageId));
207 }
Skyler Greyad002172022-08-16 18:48:26 +0100208 while (!timedOut) {
PineaFanc729e762023-01-02 22:11:34 +0000209 const em = embeds[page]!.embed;
210
211 let selectPane: ActionRowBuilder<ButtonBuilder | StringSelectMenuBuilder>[] = [];
pineafanea063042022-05-19 19:08:44 +0100212
213 if (selectPaneOpen) {
PineaFanc729e762023-01-02 22:11:34 +0000214 const options: APISelectMenuOption[] = [];
Skyler Grey75ea9172022-08-06 10:22:23 +0100215 embeds.forEach((embed) => {
Skyler Greyad002172022-08-16 18:48:26 +0100216 options.push({
217 label: embed.title,
218 value: embed.pageId.toString(),
219 description: embed.description || ""
220 });
pineafan63fc5e22022-08-04 22:04:10 +0100221 });
Skyler Grey75ea9172022-08-06 10:22:23 +0100222 selectPane = [
PineaFanc729e762023-01-02 22:11:34 +0000223 new ActionRowBuilder<StringSelectMenuBuilder>().addComponents(
224 new Discord.StringSelectMenuBuilder()
Skyler Grey75ea9172022-08-06 10:22:23 +0100225 .addOptions(options)
226 .setCustomId("page")
227 .setMaxValues(1)
228 .setPlaceholder("Choose a page...")
PineaFanc729e762023-01-02 22:11:34 +0000229 )
Skyler Grey75ea9172022-08-06 10:22:23 +0100230 ];
pineafanea063042022-05-19 19:08:44 +0100231 }
PineaFanc729e762023-01-02 22:11:34 +0000232 const m = await interaction.editReply({
pineafan34369e62022-05-18 16:52:37 +0100233 embeds: [em],
Skyler Grey75ea9172022-08-06 10:22:23 +0100234 components: selectPane.concat([
PineaFanc729e762023-01-02 22:11:34 +0000235 new ActionRowBuilder<ButtonBuilder>().addComponents([
TheCodedProf21c08592022-09-13 14:14:43 -0400236 new ButtonBuilder()
Skyler Grey75ea9172022-08-06 10:22:23 +0100237 .setEmoji(getEmojiByName("CONTROL.LEFT", "id"))
TheCodedProf21c08592022-09-13 14:14:43 -0400238 .setStyle(ButtonStyle.Secondary)
Skyler Grey75ea9172022-08-06 10:22:23 +0100239 .setCustomId("left")
240 .setDisabled(page === 0),
TheCodedProf21c08592022-09-13 14:14:43 -0400241 new ButtonBuilder()
Skyler Grey75ea9172022-08-06 10:22:23 +0100242 .setEmoji(getEmojiByName("CONTROL.MENU", "id"))
TheCodedProf21c08592022-09-13 14:14:43 -0400243 .setStyle(selectPaneOpen ? ButtonStyle.Primary : ButtonStyle.Secondary)
Skyler Grey75ea9172022-08-06 10:22:23 +0100244 .setCustomId("select")
245 .setDisabled(false),
TheCodedProf21c08592022-09-13 14:14:43 -0400246 new ButtonBuilder()
Skyler Grey75ea9172022-08-06 10:22:23 +0100247 .setEmoji(getEmojiByName("CONTROL.RIGHT", "id"))
248 .setCustomId("right")
TheCodedProf21c08592022-09-13 14:14:43 -0400249 .setStyle(ButtonStyle.Secondary)
Skyler Greyad002172022-08-16 18:48:26 +0100250 .setDisabled(page === embeds.length - 1)
Skyler Grey75ea9172022-08-06 10:22:23 +0100251 ])
252 ])
pineafan63fc5e22022-08-04 22:04:10 +0100253 });
Skyler Grey1a67e182022-08-04 23:05:44 +0100254 let i: MessageComponentInteraction;
pineafan377794f2022-04-18 19:01:01 +0100255 try {
PineaFan0d06edc2023-01-17 22:10:31 +0000256 i = await m.awaitMessageComponent({
257 time: 300000,
Samuel Shuert27bf3cd2023-03-03 15:51:25 -0500258 filter: (i) => { return i.user.id === interaction.user.id && i.channel!.id === interaction.channel!.id && i.message.id === m.id }
PineaFan0d06edc2023-01-17 22:10:31 +0000259 });
Skyler Grey75ea9172022-08-06 10:22:23 +0100260 } catch {
Skyler Greyad002172022-08-16 18:48:26 +0100261 timedOut = true;
262 continue;
Skyler Grey75ea9172022-08-06 10:22:23 +0100263 }
Samuel Shuert27bf3cd2023-03-03 15:51:25 -0500264 await i.deferUpdate();
PineaFanc729e762023-01-02 22:11:34 +0000265 if (i.customId === "left") {
pineafan377794f2022-04-18 19:01:01 +0100266 if (page > 0) page--;
pineafanea063042022-05-19 19:08:44 +0100267 selectPaneOpen = false;
PineaFanc729e762023-01-02 22:11:34 +0000268 } else if (i.customId === "right") {
pineafan377794f2022-04-18 19:01:01 +0100269 if (page < embeds.length - 1) page++;
pineafanea063042022-05-19 19:08:44 +0100270 selectPaneOpen = false;
PineaFanc729e762023-01-02 22:11:34 +0000271 } else if (i.customId === "select") {
pineafanea063042022-05-19 19:08:44 +0100272 selectPaneOpen = !selectPaneOpen;
PineaFanc729e762023-01-02 22:11:34 +0000273 } else if (i.customId === "page" && i.isStringSelectMenu()) {
274 page = parseInt(i.values[0]!);
pineafanea063042022-05-19 19:08:44 +0100275 selectPaneOpen = false;
pineafan377794f2022-04-18 19:01:01 +0100276 }
277 }
PineaFanc729e762023-01-02 22:11:34 +0000278 const em = embeds[page]!.embed;
279 em.setDescription(em.description + " | Message closed");
Skyler Grey75ea9172022-08-06 10:22:23 +0100280 await interaction.editReply({
281 embeds: [em],
Skyler Greyad002172022-08-16 18:48:26 +0100282 components: []
Skyler Grey75ea9172022-08-06 10:22:23 +0100283 });
pineafan63fc5e22022-08-04 22:04:10 +0100284};
pineafan4f164f32022-02-26 22:07:12 +0000285
pineafan4f164f32022-02-26 22:07:12 +0000286export { command };
287export { callback };
PineaFanc729e762023-01-02 22:11:34 +0000288export { userAbout };