/[sudobot]/trunk/src/commands/information/ProfileCommand.ts
ViewVC logotype

Diff of /trunk/src/commands/information/ProfileCommand.ts

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 64 by rakin, Mon Jul 29 17:28:27 2024 UTC revision 551 by rakin, Mon Jul 29 17:30:46 2024 UTC
# Line 1  Line 1 
1  import { ColorResolvable, CommandInteraction, GuildMember, Message, User } from 'discord.js';  /**
2    * This file is part of SudoBot.
3    *
4    * Copyright (C) 2021-2022 OSN Inc.
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 { CommandInteraction, Guild, GuildMember, Message, Permissions, User, UserFlags } from 'discord.js';
21  import BaseCommand from '../../utils/structures/BaseCommand';  import BaseCommand from '../../utils/structures/BaseCommand';
22  import DiscordClient from '../../client/Client';  import DiscordClient from '../../client/Client';
23  import CommandOptions from '../../types/CommandOptions';  import CommandOptions from '../../types/CommandOptions';
24  import InteractionOptions from '../../types/InteractionOptions';  import InteractionOptions from '../../types/InteractionOptions';
25  import MessageEmbed from '../../client/MessageEmbed';  import MessageEmbed from '../../client/MessageEmbed';
 import e from 'express';  
 import getUser from '../../utils/getUser';  
26  import getMember from '../../utils/getMember';  import getMember from '../../utils/getMember';
27  import { timeSince } from '../../utils/util';  import { timeSince } from '../../utils/util';
28  import { roleMention } from '@discordjs/builders';  import { roleMention } from '@discordjs/builders';
29    
30    export const getUserBadges = (user: User) => {
31        const { FLAGS } = UserFlags;
32        
33        const badges = [];
34    
35        if (user.flags?.has(FLAGS.BUGHUNTER_LEVEL_1))
36            badges.push('Bughunter Level 1');
37        if (user.flags?.has(FLAGS.BUGHUNTER_LEVEL_2))
38            badges.push('Bughunter Level 2');
39        if (user.flags?.has(FLAGS.DISCORD_CERTIFIED_MODERATOR))
40            badges.push('Discord Certified Moderator');
41        if (user.flags?.has(FLAGS.DISCORD_EMPLOYEE))
42            badges.push('Discord Staff');
43        if (user.flags?.has(FLAGS.EARLY_SUPPORTER))
44            badges.push('Early Nitro Supporter');
45        if (user.flags?.has(FLAGS.EARLY_VERIFIED_BOT_DEVELOPER))
46            badges.push('Early Verified Bot Developer');
47        if (user.flags?.has(FLAGS.HOUSE_BALANCE))
48            badges.push('HypeSquad Balance');
49        if (user.flags?.has(FLAGS.HOUSE_BRILLIANCE))
50            badges.push('HypeSquad Brilliance');
51        if (user.flags?.has(FLAGS.HOUSE_BRAVERY))
52            badges.push('HypeSquad Bravery');
53        if (user.flags?.has(FLAGS.HYPESQUAD_EVENTS))
54            badges.push('HypeSquad Events');
55        if (user.flags?.has(FLAGS.PARTNERED_SERVER_OWNER))
56            badges.push('Partnered Server Owner');
57        if (user.flags?.has(FLAGS.BOT_HTTP_INTERACTIONS))
58            badges.push('Supports Interactions');
59        if (user.flags?.has(FLAGS.VERIFIED_BOT))
60            badges.push('Verified Bot');
61        
62        return badges.map(b => `🔵 ${b}`);
63    };
64    
65    export function getPermissionLevel({ permissions, guild, id }: { id: string, permissions: GuildMember["permissions"], guild: Guild }, string: boolean = false) {
66        if (guild.ownerId === id) {
67            return string ? "100" : 100;
68        }
69    
70        const allBits = Object.values(Permissions.FLAGS).length;
71        const array = permissions.toArray();
72    
73        if (array.includes('ADMINISTRATOR')) {
74            return string ? "100" : 100;
75        }
76    
77        const percentage = (array.length / allBits) * 100;
78    
79        return string ? percentage.toString() : percentage;
80    }
81    
82  export default class ProfileCommand extends BaseCommand {  export default class ProfileCommand extends BaseCommand {
83      supportsInteractions: boolean = true;      supportsInteractions: boolean = true;
84    
# Line 18  export default class ProfileCommand exte Line 87  export default class ProfileCommand exte
87      }      }
88    
89      async run(client: DiscordClient, msg: Message | CommandInteraction, options: CommandOptions | InteractionOptions) {      async run(client: DiscordClient, msg: Message | CommandInteraction, options: CommandOptions | InteractionOptions) {
90          let user: GuildMember | null = null;          let member: GuildMember | null = null;
91    
92          if (msg instanceof CommandInteraction && options.isInteraction) {          if (msg instanceof CommandInteraction && options.isInteraction) {
93              if (options.options.getMember('user'))              if (options.options.getMember('user'))
94                  user = <GuildMember> await options.options.getMember('user');                  member = <GuildMember> await options.options.getMember('user');
95              else              else
96                  user = <GuildMember> msg.member!;                  member = <GuildMember> msg.member!;
97          }          }
98          else if (msg instanceof Message && !options.isInteraction) {          else if (msg instanceof Message && !options.isInteraction) {
99              if (options.normalArgs[0]) {              if (options.normalArgs[0]) {
# Line 34  export default class ProfileCommand exte Line 103  export default class ProfileCommand exte
103                      if (!tempMember)                      if (!tempMember)
104                          throw new Error();                          throw new Error();
105                                            
106                      user = tempMember;                      member = tempMember;
107                  }                  }
108                  catch (e) {                  catch (e) {
109                      console.log(e);                                    console.log(e);              
# Line 51  export default class ProfileCommand exte Line 120  export default class ProfileCommand exte
120                  }                  }
121              }              }
122              else {              else {
123                  user = msg.member!;                  member = msg.member!;
124              }              }
125          }          }
126    
# Line 68  export default class ProfileCommand exte Line 137  export default class ProfileCommand exte
137              return s;              return s;
138          };              };    
139    
140          const statusText = '' + ((user?.presence?.clientStatus?.desktop ? 'Desktop (' + status(user?.presence?.clientStatus?.desktop) + ')\n' : '') + (user?.presence?.clientStatus?.web ? 'Web (' + status(user?.presence?.clientStatus?.web) + ')\n' : '') + (user?.presence?.clientStatus?.mobile ? 'Mobile (' + status(user?.presence?.clientStatus?.mobile) + ')' : ''));          const statusText = '' + ((member?.presence?.clientStatus?.desktop ? 'Desktop (' + status(member?.presence?.clientStatus?.desktop) + ')\n' : '') + (member?.presence?.clientStatus?.web ? 'Web (' + status(member?.presence?.clientStatus?.web) + ')\n' : '') + (member?.presence?.clientStatus?.mobile ? 'Mobile (' + status(member?.presence?.clientStatus?.mobile) + ')' : ''));
141          const state = user?.presence?.activities.find(a => a.type === 'CUSTOM')?.state;          // const state = user?.presence?.activities.find(a => a.type === 'CUSTOM')?.state;
142            let activities: string[] | string = [];
143    
144            if (member?.presence) {
145                for (const a of member?.presence?.activities.values()!) {
146                    console.log(a);
147                    
148                    if (a.type === 'CUSTOM') {
149                        activities.push(`${a.emoji ? `${a.emoji.toString()} ` : ''}${a.state}`);
150                    }
151                    else if (a.type === 'LISTENING') {
152                        if (a.name === 'Spotify') {
153                            const url = a.syncId ? `https://open.spotify.com/track/${a.syncId}` : null;
154                            activities.push(`:notes: Listening to **Spotify**: ${url ? '[' : '**'}${a.state?.replace(/\;/, ',')} - ${a.details}${url ? '](' + url + ')' : '**'}`);
155                            continue;
156                        }
157    
158                        activities.push(`:musical_note: Listening to **${a.name}**`);
159                    }
160                    else if (a.type === 'COMPETING') {
161                        activities.push(`:fire: Competing **${a.name}**`);
162                    }
163                    else if (a.type === 'PLAYING') {
164                        activities.push(`:video_game: Playing **${a.name}**`);
165                    }
166                    else if (a.type === 'STREAMING') {
167                        activities.push(`:video_camera: Streaming **${a.name}**`);
168                    }
169                    else if (a.type === 'WATCHING') {
170                        activities.push(`:tv: Watching **${a.name}**`);
171                    }
172                }
173            }
174    
175            activities = activities.join('\n');
176    
177            const allRoles = [...member!.roles.cache.values()].filter(role => role.id !== msg.guild!.id).sort((role1, role2) => {
178                return role2.position - role1.position;
179            });
180            const limit = 10;
181            const roles = (allRoles.length > limit ? allRoles.slice(0, limit) : allRoles).reduce((acc, value) => `${acc} ${roleMention(value.id)}`, '')!.trim()!;
182            const fields = [
183                {
184                    name: "Nickname",
185                    value: `${member!.nickname?.replace(/\*\<\>\@\_\~\|/g, '') ?? '*Nickname not set*'}`
186                },
187                {
188                    name: "Account Created",
189                    value: `${member!.user.createdAt.toLocaleDateString('en-US')} (${timeSince(member!.user.createdTimestamp)})`
190                },
191                {
192                    name: "Joined at",
193                    value: `${member!.joinedAt!.toLocaleDateString('en-US')} (${timeSince(member!.joinedTimestamp!)})`
194                },
195                {
196                    name: 'Active Devices',
197                    value: `${statusText === '' ? 'Offline/Invisible' : statusText}`
198                },
199                {
200                    name: 'Status',
201                    value: `${activities?.trim() === '' ? '*No status set*' : activities}`
202                },
203                {
204                    name: 'Roles',
205                    value: roles === '' ? '*No roles assigned*' : `${roles} ${allRoles.length > limit ? `**+ ${allRoles.length - limit} More**` : ''}`
206                }
207            ];
208    
209            const badges = getUserBadges(member!.user);
210    
211            if (badges.length > 0) {
212                fields.push({
213                    name: 'Badges',
214                    value: badges.join("\n")
215                });
216            }
217    
218            let banner: string | undefined;
219    
220            try {
221                await member?.user.fetch(true);
222                banner = member!.user!.bannerURL({ size: 4096 }) ?? undefined;
223            }
224            catch (e) {
225                console.log(e);
226            }
227    
228            console.log("Banner", banner, member!.user!.banner);
229    
230            let percentage = <string> getPermissionLevel(member!, true);
231            percentage = percentage.includes('.') ? percentage.substring(0, percentage.indexOf('.')) : percentage;
232    
233          await msg.reply({          await msg.reply({
234              embeds: [              embeds: [
235                  new MessageEmbed()                  new MessageEmbed({
236                  .setColor(user!.user!.hexAccentColor ? user!.user!.hexAccentColor! : '#007bff')                      image: {
237                            url: banner,
238                        }
239                    })
240                    .setColor(member!.user!.hexAccentColor ? member!.user!.hexAccentColor! : '#007bff')
241                  .setAuthor({                  .setAuthor({
242                      name: user?.user.tag!,                      name: member?.user.tag!,
243                      iconURL: user!.user.displayAvatarURL()                      iconURL: member!.user.displayAvatarURL()
244                  })                  })
245                  .setImage(user!.displayAvatarURL({                  .setThumbnail(member!.displayAvatarURL({
246                      size: 4096                      size: 4096
247                  }))                  }))
248                  .setURL(user!.displayAvatarURL({                  .setFields(fields)
249                      size: 4096                  .setFooter({
250                  }))                      text: `${member?.user.bot ? 'Bot' : 'User'} • ${member!.id} • Has ${percentage.toString()}% permissions`
251                  .setFields([                  })
                     {  
                         name: "ID",  
                         value: `${user!.id}`  
                     },  
                     {  
                         name: "Nickname",  
                         value: `${user!.nickname?.replace(/\*\<\>\@\_\~\|/g, '') ?? '*Nickname not set*'}`  
                     },  
                     {  
                         name: "Account Created",  
                         value: `${user!.user.createdAt.toLocaleDateString('en-US')} (${timeSince(user!.user.createdTimestamp)})`  
                     },  
                     {  
                         name: "Joined at",  
                         value: `${user!.joinedAt!.toLocaleDateString('en-US')} (${timeSince(user!.joinedTimestamp!)})`  
                     },  
                     {  
                         name: 'Active Devices',  
                         value: `${statusText === '' ? 'Offline/Invisible' : statusText}`  
                     },  
                     {  
                         name: 'Custom Status',  
                         value: `${state ?? '*No custom status set*'}`  
                     },  
                     {  
                         name: 'Roles',  
                         value: user?.roles.cache.filter(role => role.id !== msg.guild!.id).reduce((acc, value) => `${acc} ${roleMention(value.id)}`, '')!.trim()!  
                     }  
                 ])  
252              ]              ]
253          });          });
254      }      }

Legend:
Removed from v.64  
changed lines
  Added in v.551

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26