/[sudobot]/branches/6.x/src/commands/information/ProfileCommand.ts
ViewVC logotype

Annotation of /branches/6.x/src/commands/information/ProfileCommand.ts

Parent Directory Parent Directory | Revision Log Revision Log


Revision 577 - (hide annotations)
Mon Jul 29 18:52:37 2024 UTC (8 months ago) by rakinar2
File MIME type: application/typescript
File size: 12040 byte(s)
chore: add old version archive branches (2.x to 9.x-dev)
1 rakinar2 577 /**
2     * This file is part of SudoBot.
3     *
4     * Copyright (C) 2021-2023 OSN Developers.
5     *
6     * SudoBot is free software; you can redistribute it and/or modify it
7     * under the terms of the GNU Affero General Public License as published by
8     * the Free Software Foundation, either version 3 of the License, or
9     * (at your option) any later version.
10     *
11     * SudoBot is distributed in the hope that it will be useful, but
12     * WITHOUT ANY WARRANTY; without even the implied warranty of
13     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14     * GNU Affero General Public License for more details.
15     *
16     * You should have received a copy of the GNU Affero General Public License
17     * along with SudoBot. If not, see <https://www.gnu.org/licenses/>.
18     */
19    
20     import { formatDistanceToNowStrict } from "date-fns";
21     import {
22     APIEmbedField,
23     ActivityType,
24     EmbedBuilder,
25     Emoji,
26     Guild,
27     GuildMember,
28     PermissionFlagsBits,
29     Role,
30     SlashCommandBuilder,
31     User,
32     roleMention
33     } from "discord.js";
34     import Client from "../../core/Client";
35     import Command, { AnyCommandContext, ArgumentType, CommandMessage, CommandReturn, ValidationRule } from "../../core/Command";
36     import { log, logError } from "../../utils/logger";
37     import { getUserBadges } from "../../utils/user";
38     import { getEmoji } from "../../utils/utils";
39    
40     const status = (s: "idle" | "online" | "dnd" | "invisible" | null | undefined): string => {
41     if (s === "idle") return "Idle";
42     else if (s === "dnd") return "Do not disturb";
43     else if (s === "online") return "Online";
44     else if (s === undefined || s === null || s === "invisible") return "Offline/Invisible";
45    
46     return s;
47     };
48    
49     const statusEmoji = (client: Client, s: "idle" | "online" | "dnd" | "invisible" | null | undefined): string => {
50     if (s === "idle") return getEmoji(client, "idle");
51     else if (s === "dnd") return getEmoji(client, "dnd");
52     else if (s === "online") return getEmoji(client, "online");
53     else if (s === undefined || s === null || s === "invisible") return getEmoji(client, "invisible");
54    
55     return s;
56     };
57    
58     const getStatusText = (client: Client, member: GuildMember) =>
59     "" +
60     ((member?.presence?.clientStatus?.desktop
61     ? statusEmoji(client, member?.presence?.clientStatus?.desktop) +
62     " Desktop (" +
63     status(member?.presence?.clientStatus?.desktop) +
64     ")\n"
65     : "") +
66     (member?.presence?.clientStatus?.web
67     ? statusEmoji(client, member?.presence?.clientStatus?.web) +
68     " Web (" +
69     status(member?.presence?.clientStatus?.web) +
70     ")\n"
71     : "") +
72     (member?.presence?.clientStatus?.mobile
73     ? statusEmoji(client, member?.presence?.clientStatus?.mobile) +
74     " Mobile (" +
75     status(member?.presence?.clientStatus?.mobile) +
76     ")"
77     : ""));
78    
79     export function getPermissionLevel(
80     { permissions, guild, id }: { id: string; permissions: GuildMember["permissions"]; guild: Guild },
81     string: boolean = false
82     ) {
83     if (guild.ownerId === id) {
84     return string ? "100" : 100;
85     }
86    
87     const allBits = Object.keys(PermissionFlagsBits).length;
88     const array = permissions.toArray();
89    
90     if (array.includes("Administrator")) {
91     return string ? "100" : 100;
92     }
93    
94     const percentage = Math.round((array.length / allBits) * 100);
95     return string ? percentage.toString() : percentage;
96     }
97    
98     export default class ProfileCommand extends Command {
99     public readonly name = "profile";
100     public readonly validationRules: ValidationRule[] = [
101     {
102     types: [ArgumentType.Member, ArgumentType.User],
103     name: "member",
104     optional: true,
105     errors: {
106     "type:invalid": "Invalid user given!",
107     "entity:null": "That user could not be found!",
108     },
109     entity: {
110     notNull: true
111     },
112     }
113     ];
114     public readonly aliases = ["userprofile", "userinfo"];
115     public readonly permissions = [];
116    
117     public readonly description = "Shows your or someone else's profile.";
118     public readonly slashCommandBuilder = new SlashCommandBuilder().addUserOption(option =>
119     option.setName("member").setDescription("The target member or user")
120     );
121    
122     private isAvailableEmoji({ id, identifier }: Emoji) {
123     for (const [, guild] of this.client.guilds.cache) {
124     const emoji = guild.emojis.cache.find(e => e.id === id || e.identifier === identifier);
125    
126     if (emoji) {
127     return true;
128     }
129     }
130    
131     return false;
132     }
133    
134     private isGuildMember(member: GuildMember | User | null): member is GuildMember {
135     return member instanceof GuildMember;
136     }
137    
138     async execute(message: CommandMessage, context: AnyCommandContext): Promise<CommandReturn> {
139     await this.deferIfInteraction(message);
140    
141     const member: GuildMember | User | null =
142     (context.isLegacy
143     ? context.parsedNamedArgs.member
144     : context.options.getMember("member") ?? context.options.getUser("member", true)) ?? message.member;
145    
146     if (!member) {
147     await this.error(message, "Could not resolve that member!");
148     return;
149     }
150    
151     const isMember = this.isGuildMember(member);
152     const user = isMember ? (member.user! as User) : member;
153     const activities: string[] = [];
154    
155     if (isMember && member?.presence) {
156     for (const a of member?.presence?.activities.values()!) {
157     log(a);
158    
159     if (a.type === ActivityType.Custom) {
160     activities.push(
161     `${a.emoji && this.isAvailableEmoji(a.emoji) ? `${a.emoji.toString()}` : ":small_blue_diamond:"} ${
162     a.state
163     }`
164     );
165     } else if (a.type === ActivityType.Listening) {
166     if (a.name === "Spotify") {
167     const url = a.url ? `${a.url}` : null;
168     activities.push(
169     `${this.emoji("spotify")} Listening to **Spotify**: ${url ? "[" : "__"}${a.state?.split(/\;/)[0]} - ${
170     a.details
171     }${url ? "](" + url + ")" : "__"}`
172     );
173     continue;
174     }
175    
176     activities.push(`:musical_note: Listening to **${a.name}**`);
177     } else if (a.type === ActivityType.Competing) {
178     activities.push(`:fire: Competing **${a.name}**`);
179     } else if (a.type === ActivityType.Playing) {
180     activities.push(`:video_game: Playing **${a.name}**`);
181     } else if (a.type === ActivityType.Streaming) {
182     activities.push(`:video_camera: Streaming **${a.name}**`);
183     } else if (a.type === ActivityType.Watching) {
184     activities.push(`:tv: Watching **${a.name}**`);
185     }
186     }
187     }
188    
189     const allRoles = isMember
190     ? [...member!.roles.cache.values()]
191     .filter(role => role.id !== message.guildId!)
192     .sort((role1, role2) => {
193     return role2.position - role1.position;
194     })
195     : null;
196     const limit = 10;
197     const roles = (isMember ? (allRoles!.length > limit ? allRoles!.slice(0, limit) : allRoles) : ([] as Role[]))!
198     .reduce((acc, value) => `${acc} ${roleMention(value.id)}`, "")!
199     .trim()!;
200     const statusText = isMember ? getStatusText(this.client, member!) : null;
201    
202     const fields: APIEmbedField[] = [
203     ...(isMember
204     ? [
205     {
206     name: "Nickname",
207     value: `${member!.nickname?.replace(/\*\<\>\@\_\~\|/g, "") ?? "*Nickname is not set*"}`
208     }
209     ]
210     : []),
211     {
212     name: "Display Name",
213     value: `${user!.displayName?.replace(/\*\<\>\@\_\~\|/g, "") ?? "*Display name is not set*"}`
214     },
215     {
216     name: "Account Created",
217     value: `${user.createdAt.toLocaleDateString("en-US")} (${formatDistanceToNowStrict(user.createdTimestamp, {
218     addSuffix: true
219     })})`,
220     inline: true
221     },
222     ...(isMember
223     ? [
224     {
225     name: "Joined at",
226     value: `${member!.joinedAt!.toLocaleDateString("en-US")} (${formatDistanceToNowStrict(
227     member!.joinedTimestamp!,
228     {
229     addSuffix: true
230     }
231     )})`,
232     inline: true
233     },
234     {
235     name: "Active Devices",
236     value: `${statusText === "" ? `${this.emoji("invisible")} Offline/Invisible` : statusText}`
237     },
238     {
239     name: "Status",
240     value: `${activities.length === 0 ? "*No status set*" : activities.join("\n")}`
241     },
242     {
243     name: "Roles",
244     value:
245     roles === ""
246     ? "*No roles assigned*"
247     : `${roles} ${allRoles!.length > limit ? `**+ ${allRoles!.length - limit} More**` : ""}`
248     }
249     ]
250     : [])
251     ];
252    
253     const badges = getUserBadges(this.client, user);
254    
255     if (badges.length > 0) {
256     fields.push({
257     name: "Badges",
258     value: badges.join("\n")
259     });
260     }
261    
262     let banner: string | undefined;
263    
264     try {
265     await user.fetch(true);
266     banner = user!.bannerURL({ size: 4096, forceStatic: false }) ?? undefined;
267     } catch (e) {
268     logError(e);
269     }
270    
271     log("Banner", banner, user!.banner);
272    
273     let permissionPercentage = 0;
274    
275     if (isMember) {
276     if (this.client.permissionManager.usesLevelBasedMode(member.guild.id)) {
277     permissionPercentage = (await this.client.permissionManager.getManager(member.guild.id)).getPermissionLevel(
278     member
279     );
280     } else {
281     permissionPercentage =
282     message.guild!.ownerId === user.id || (isMember && member.permissions.has("Administrator"))
283     ? 100
284     : (getPermissionLevel(member, false) as number);
285     }
286     }
287    
288     await this.deferredReply(message, {
289     embeds: [
290     new EmbedBuilder({
291     image: banner
292     ? {
293     url: banner
294     }
295     : undefined
296     })
297     .setColor(user!.hexAccentColor ? user!.hexAccentColor! : "#007bff")
298     .setAuthor({
299     name: user.tag!,
300     iconURL: user.displayAvatarURL()
301     })
302     .setThumbnail(
303     (isMember ? member : user).displayAvatarURL({
304     size: 4096,
305     forceStatic: false
306     })
307     )
308     .setFields(fields)
309     .setFooter({
310     text:
311     `${user.bot ? "Bot" : "User"} • ${member!.id}` +
312     (isMember ? ` • Has ${permissionPercentage}% permissions` : "")
313     })
314     ]
315     });
316     }
317     }

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26