blob: 7e2902eea4366d35d7f378b003f490aed5c38def [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";
TheCodedProff86ba092023-01-27 17:10:07 -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);
Skyler Greyda16adf2023-03-05 10:22:12 +000032};
PineaFanc729e762023-01-02 22:11:34 +000033
Skyler Greyda16adf2023-03-05 10:22:12 +000034async function userAbout(
35 guild: Discord.Guild,
36 member: Discord.GuildMember,
37 interaction: Discord.CommandInteraction | Discord.ContextMenuCommandInteraction
38) {
39 await member.user.fetch();
40 await member.fetch();
PineaFanc729e762023-01-02 22:11:34 +000041 await interaction.reply({
42 embeds: LoadingEmbed,
43 fetchReply: true,
44 ephemeral: true
45 });
46 const { renderUser, renderDelta } = client.logger;
pineafan63fc5e22022-08-04 22:04:10 +010047 const flags: string[] = [];
Skyler Grey75ea9172022-08-06 10:22:23 +010048 if (
49 [
50 "438733159748599813", // Pinea
51 "317731855317336067", // Mini
52 "261900651230003201", // Coded
53 "511655498676699136" // Zan
54 ].includes(member.user.id)
55 ) {
56 flags.push("NUCLEUSDEVELOPER");
57 }
58 if (
59 (await client.guilds.cache.get("684492926528651336")?.members.fetch())
Skyler Grey11236ba2022-08-08 21:13:33 +010060 ?.filter((m: GuildMember) => m.roles.cache.has("760896837866749972"))
Skyler Grey75ea9172022-08-06 10:22:23 +010061 ?.map((m: GuildMember) => m.id)
62 .includes(member.user.id)
63 ) {
64 flags.push("CLICKSDEVELOPER");
65 }
Skyler Greyda16adf2023-03-05 10:22:12 +000066 if (member.user.flags) {
67 member.user.flags.toArray().map((flag) => {
68 flags.push(flag.toString());
69 });
70 }
71 if (member.user.bot) {
72 flags.push("BOT");
73 }
pineafan377794f2022-04-18 19:01:01 +010074 // Check if they are boosting the server
Skyler Greyda16adf2023-03-05 10:22:12 +000075 if (member.premiumSince) {
76 flags.push("BOOSTER");
77 }
PineaFanc729e762023-01-02 22:11:34 +000078 const nameReplacements: Record<string, string> = {
Skyler Grey75ea9172022-08-06 10:22:23 +010079 NUCLEUSDEVELOPER: "**Nucleus Developer**",
80 CLICKSDEVELOPER: "Clicks Developer",
Skyler Grey75ea9172022-08-06 10:22:23 +010081 BOT: "Bot",
PineaFanc729e762023-01-02 22:11:34 +000082 BOOSTER: "Server Booster",
83 HypeSquadOnlineHouse1: "Hypesquad Bravery",
84 HypeSquadOnlineHouse2: "Hypesquad Brilliance",
85 HypeSquadOnlineHouse3: "Hypesquad Balance",
86 Hypesquad: "Hypesquad Events",
87 PremiumEarlySupporter: "Early Supporter",
88 BugHunterLevel1: "Bug Hunter Level 1",
89 BugHunterLevel2: "Bug Hunter Level 2",
90 Partner: "Partnered Server Owner",
91 Staff: "Discord Staff",
PineaFana34d04b2023-01-03 22:05:42 +000092 VerifiedDeveloper: "Verified Bot Developer",
93 ActiveDeveloper: "Active Developer",
Skyler Greyda16adf2023-03-05 10:22:12 +000094 Quarantined:
95 "Quarantined [[What does this mean?]](https://support.discord.com/hc/en-us/articles/6461420677527)",
PineaFana34d04b2023-01-03 22:05:42 +000096 Spammer: "Likely Spammer"
PineaFanc729e762023-01-02 22:11:34 +000097 // CertifiedModerator
PineaFanc729e762023-01-02 22:11:34 +000098 // VerifiedBot
pineafan63fc5e22022-08-04 22:04:10 +010099 };
PineaFanc729e762023-01-02 22:11:34 +0000100 const members = await guild.members.fetch();
pineafan63fc5e22022-08-04 22:04:10 +0100101 const membersArray = [...members.values()];
Skyler Greyc634e2b2022-08-06 17:50:48 +0100102 membersArray.sort((a, b) => {
103 if (a.joinedTimestamp === null) return 1;
104 if (b.joinedTimestamp === null) return -1;
105 return a.joinedTimestamp - b.joinedTimestamp;
106 });
Skyler Grey75ea9172022-08-06 10:22:23 +0100107 const joinPos = membersArray.findIndex((m) => m.id === member.user.id);
pineafan377794f2022-04-18 19:01:01 +0100108
PineaFanc729e762023-01-02 22:11:34 +0000109 const roles = member.roles.cache.filter((r) => r.id !== guild.id).sort();
pineafan377794f2022-04-18 19:01:01 +0100110 let s = "";
111 let count = 0;
pineafan63fc5e22022-08-04 22:04:10 +0100112 let ended = false;
PineaFana34d04b2023-01-03 22:05:42 +0000113 for (const roleId of roles) {
114 const string = `<@&${roleId[1].id}>, `;
Skyler Grey75ea9172022-08-06 10:22:23 +0100115 if (s.length + string.length > 1000) {
pineafan63fc5e22022-08-04 22:04:10 +0100116 ended = true;
117 s += `and ${roles.size - count} more`;
Skyler Greyc634e2b2022-08-06 17:50:48 +0100118 break;
pineafan63fc5e22022-08-04 22:04:10 +0100119 }
Skyler Grey75ea9172022-08-06 10:22:23 +0100120 count++;
pineafan377794f2022-04-18 19:01:01 +0100121 s += string;
Skyler Greyc634e2b2022-08-06 17:50:48 +0100122 }
Skyler Grey75ea9172022-08-06 10:22:23 +0100123 if (s.length > 0 && !ended) s = s.slice(0, -2);
pineafan377794f2022-04-18 19:01:01 +0100124
pineafan63fc5e22022-08-04 22:04:10 +0100125 let perms = "";
PineaFanc729e762023-01-02 22:11:34 +0000126 const permsArray: Record<string, string> = {
127 Administrator: "Administrator",
128 ManageGuild: "Manage Server",
129 ManageRoles: "Manage Roles",
130 ManageChannels: "Manage Channels",
131 KickMembers: "Kick Members",
132 BanMembers: "Ban Members",
133 ModerateMembers: "Moderate Members",
134 ManageNicknames: "Manage Nicknames",
135 ManageWebhooks: "Manage Webhooks",
136 ManageMessages: "Manage Messages",
137 ViewAuditLog: "View Audit Log",
138 MentionEveryone: "Mention Everyone"
pineafan63fc5e22022-08-04 22:04:10 +0100139 };
Skyler Grey75ea9172022-08-06 10:22:23 +0100140 Object.keys(permsArray).map((perm) => {
PineaFanc729e762023-01-02 22:11:34 +0000141 const hasPerm = member.permissions.has(perm as PermissionResolvable);
Skyler Grey11236ba2022-08-08 21:13:33 +0100142 perms += `${getEmojiByName("CONTROL." + (hasPerm ? "TICK" : "CROSS"))} ${permsArray[perm]}\n`;
pineafan63fc5e22022-08-04 22:04:10 +0100143 });
pineafan377794f2022-04-18 19:01:01 +0100144
pineafanea063042022-05-19 19:08:44 +0100145 let selectPaneOpen = false;
146
pineafan63fc5e22022-08-04 22:04:10 +0100147 const embeds = [
pineafanea063042022-05-19 19:08:44 +0100148 new Embed()
Skyler Grey75ea9172022-08-06 10:22:23 +0100149 .setEmbed(
150 new EmojiEmbed()
151 .setTitle("User Info: General")
152 .setStatus("Success")
153 .setEmoji("MEMBER.JOIN")
154 .setDescription(
Skyler Greyda16adf2023-03-05 10:22:12 +0000155 flags
156 .map((flag) => {
157 if (nameReplacements[flag]) {
158 const emoji = getEmojiByName(`BADGES.${flag}`);
159 if (emoji) return emoji + " " + nameReplacements[flag] + "\n";
160 else return nameReplacements[flag] + "\n";
161 }
162 })
163 .join("") +
164 "\n" +
165 generateKeyValueList({
166 member: renderUser(member.user),
167 nickname: member.nickname ?? "*None set*",
168 id: `\`${member.id}\``,
169 "joined the server": renderDelta(member.joinedTimestamp!),
170 "joined discord": renderDelta(member.user.createdTimestamp),
171 "boost status": member.premiumSince
172 ? `Started boosting ${renderDelta(member.premiumSinceTimestamp!)}`
173 : "*Not boosting*",
174 "join position": `${joinPos + 1}`
175 })
Skyler Grey75ea9172022-08-06 10:22:23 +0100176 )
PineaFanc729e762023-01-02 22:11:34 +0000177 .setThumbnail(member.user.displayAvatarURL())
Skyler Grey75ea9172022-08-06 10:22:23 +0100178 )
179 .setTitle("General")
180 .setDescription("General information about the user")
181 .setPageId(0),
pineafanea063042022-05-19 19:08:44 +0100182 new Embed()
Skyler Grey75ea9172022-08-06 10:22:23 +0100183 .setEmbed(
184 new EmojiEmbed()
185 .setTitle("User Info: Roles")
186 .setStatus("Success")
187 .setEmoji("GUILD.ROLES.CREATE")
188 .setDescription(
189 generateKeyValueList({
190 member: renderUser(member.user),
191 id: `\`${member.id}\``,
TheCodedProf1f675042023-02-16 17:01:29 -0500192 roles: `${member.roles.cache.size - 1}`
Skyler Greyda16adf2023-03-05 10:22:12 +0000193 }) +
194 "\n" +
195 (s.length > 0 ? s : "*None*") +
196 "\n"
Skyler Grey75ea9172022-08-06 10:22:23 +0100197 )
Skyler Grey75ea9172022-08-06 10:22:23 +0100198 )
199 .setTitle("Roles")
200 .setDescription("Roles the user has")
201 .setPageId(1),
pineafanea063042022-05-19 19:08:44 +0100202 new Embed()
Skyler Grey75ea9172022-08-06 10:22:23 +0100203 .setEmbed(
204 new EmojiEmbed()
205 .setTitle("User Info: Key Permissions")
206 .setStatus("Success")
207 .setEmoji("GUILD.ROLES.CREATE")
208 .setDescription(
209 generateKeyValueList({
210 member: renderUser(member.user),
211 id: `\`${member.id}\``
212 }) +
213 "\n" +
214 perms
215 )
Skyler Grey75ea9172022-08-06 10:22:23 +0100216 )
217 .setTitle("Key Permissions")
218 .setDescription("Key permissions the user has")
219 .setPageId(2)
pineafan63fc5e22022-08-04 22:04:10 +0100220 ];
Skyler Greyda16adf2023-03-05 10:22:12 +0000221 if (member.user.bannerURL()) {
222 embeds[0]!.embed.setImage(member.user.bannerURL()!);
223 }
pineafan63fc5e22022-08-04 22:04:10 +0100224 let page = 0;
Skyler Greyad002172022-08-16 18:48:26 +0100225 let timedOut = false;
PineaFanc729e762023-01-02 22:11:34 +0000226 for (const embed of embeds) {
227 embed.embed.setDescription(embed.embed.description + "\n" + createPageIndicator(embeds.length, embed.pageId));
228 }
Skyler Greyad002172022-08-16 18:48:26 +0100229 while (!timedOut) {
PineaFanc729e762023-01-02 22:11:34 +0000230 const em = embeds[page]!.embed;
231
232 let selectPane: ActionRowBuilder<ButtonBuilder | StringSelectMenuBuilder>[] = [];
pineafanea063042022-05-19 19:08:44 +0100233
234 if (selectPaneOpen) {
PineaFanc729e762023-01-02 22:11:34 +0000235 const options: APISelectMenuOption[] = [];
Skyler Grey75ea9172022-08-06 10:22:23 +0100236 embeds.forEach((embed) => {
Skyler Greyad002172022-08-16 18:48:26 +0100237 options.push({
238 label: embed.title,
239 value: embed.pageId.toString(),
240 description: embed.description || ""
241 });
pineafan63fc5e22022-08-04 22:04:10 +0100242 });
Skyler Grey75ea9172022-08-06 10:22:23 +0100243 selectPane = [
PineaFanc729e762023-01-02 22:11:34 +0000244 new ActionRowBuilder<StringSelectMenuBuilder>().addComponents(
245 new Discord.StringSelectMenuBuilder()
Skyler Grey75ea9172022-08-06 10:22:23 +0100246 .addOptions(options)
247 .setCustomId("page")
248 .setMaxValues(1)
249 .setPlaceholder("Choose a page...")
PineaFanc729e762023-01-02 22:11:34 +0000250 )
Skyler Grey75ea9172022-08-06 10:22:23 +0100251 ];
pineafanea063042022-05-19 19:08:44 +0100252 }
PineaFanc729e762023-01-02 22:11:34 +0000253 const m = await interaction.editReply({
pineafan34369e62022-05-18 16:52:37 +0100254 embeds: [em],
Skyler Grey75ea9172022-08-06 10:22:23 +0100255 components: selectPane.concat([
PineaFanc729e762023-01-02 22:11:34 +0000256 new ActionRowBuilder<ButtonBuilder>().addComponents([
TheCodedProf21c08592022-09-13 14:14:43 -0400257 new ButtonBuilder()
Skyler Grey75ea9172022-08-06 10:22:23 +0100258 .setEmoji(getEmojiByName("CONTROL.LEFT", "id"))
TheCodedProf21c08592022-09-13 14:14:43 -0400259 .setStyle(ButtonStyle.Secondary)
Skyler Grey75ea9172022-08-06 10:22:23 +0100260 .setCustomId("left")
261 .setDisabled(page === 0),
TheCodedProf21c08592022-09-13 14:14:43 -0400262 new ButtonBuilder()
Skyler Grey75ea9172022-08-06 10:22:23 +0100263 .setEmoji(getEmojiByName("CONTROL.MENU", "id"))
TheCodedProf21c08592022-09-13 14:14:43 -0400264 .setStyle(selectPaneOpen ? ButtonStyle.Primary : ButtonStyle.Secondary)
Skyler Grey75ea9172022-08-06 10:22:23 +0100265 .setCustomId("select")
266 .setDisabled(false),
TheCodedProf21c08592022-09-13 14:14:43 -0400267 new ButtonBuilder()
Skyler Grey75ea9172022-08-06 10:22:23 +0100268 .setEmoji(getEmojiByName("CONTROL.RIGHT", "id"))
269 .setCustomId("right")
TheCodedProf21c08592022-09-13 14:14:43 -0400270 .setStyle(ButtonStyle.Secondary)
Skyler Greyad002172022-08-16 18:48:26 +0100271 .setDisabled(page === embeds.length - 1)
Skyler Grey75ea9172022-08-06 10:22:23 +0100272 ])
273 ])
pineafan63fc5e22022-08-04 22:04:10 +0100274 });
Skyler Grey1a67e182022-08-04 23:05:44 +0100275 let i: MessageComponentInteraction;
pineafan377794f2022-04-18 19:01:01 +0100276 try {
PineaFan0d06edc2023-01-17 22:10:31 +0000277 i = await m.awaitMessageComponent({
278 time: 300000,
Skyler Greyda16adf2023-03-05 10:22:12 +0000279 filter: (i) => {
280 return (
281 i.user.id === interaction.user.id &&
282 i.channel!.id === interaction.channel!.id &&
283 i.message.id === m.id
284 );
285 }
PineaFan0d06edc2023-01-17 22:10:31 +0000286 });
Skyler Grey75ea9172022-08-06 10:22:23 +0100287 } catch {
Skyler Greyad002172022-08-16 18:48:26 +0100288 timedOut = true;
289 continue;
Skyler Grey75ea9172022-08-06 10:22:23 +0100290 }
TheCodedProf267563a2023-01-21 17:00:57 -0500291 await i.deferUpdate();
PineaFanc729e762023-01-02 22:11:34 +0000292 if (i.customId === "left") {
pineafan377794f2022-04-18 19:01:01 +0100293 if (page > 0) page--;
pineafanea063042022-05-19 19:08:44 +0100294 selectPaneOpen = false;
PineaFanc729e762023-01-02 22:11:34 +0000295 } else if (i.customId === "right") {
pineafan377794f2022-04-18 19:01:01 +0100296 if (page < embeds.length - 1) page++;
pineafanea063042022-05-19 19:08:44 +0100297 selectPaneOpen = false;
PineaFanc729e762023-01-02 22:11:34 +0000298 } else if (i.customId === "select") {
pineafanea063042022-05-19 19:08:44 +0100299 selectPaneOpen = !selectPaneOpen;
PineaFanc729e762023-01-02 22:11:34 +0000300 } else if (i.customId === "page" && i.isStringSelectMenu()) {
301 page = parseInt(i.values[0]!);
pineafanea063042022-05-19 19:08:44 +0100302 selectPaneOpen = false;
pineafan377794f2022-04-18 19:01:01 +0100303 }
304 }
PineaFanc729e762023-01-02 22:11:34 +0000305 const em = embeds[page]!.embed;
306 em.setDescription(em.description + " | Message closed");
Skyler Grey75ea9172022-08-06 10:22:23 +0100307 await interaction.editReply({
308 embeds: [em],
Skyler Greyad002172022-08-16 18:48:26 +0100309 components: []
Skyler Grey75ea9172022-08-06 10:22:23 +0100310 });
Skyler Greyda16adf2023-03-05 10:22:12 +0000311}
pineafan4f164f32022-02-26 22:07:12 +0000312
pineafan4f164f32022-02-26 22:07:12 +0000313export { command };
314export { callback };
Skyler Greyda16adf2023-03-05 10:22:12 +0000315export { userAbout };