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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 551 - (show annotations)
Mon Jul 29 17:30:46 2024 UTC (8 months, 1 week ago) by rakin
File MIME type: application/typescript
File size: 10171 byte(s)
feat(profile): show permission percentage (#118)
1 /**
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';
22 import DiscordClient from '../../client/Client';
23 import CommandOptions from '../../types/CommandOptions';
24 import InteractionOptions from '../../types/InteractionOptions';
25 import MessageEmbed from '../../client/MessageEmbed';
26 import getMember from '../../utils/getMember';
27 import { timeSince } from '../../utils/util';
28 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 {
83 supportsInteractions: boolean = true;
84
85 constructor() {
86 super('profile', 'information', []);
87 }
88
89 async run(client: DiscordClient, msg: Message | CommandInteraction, options: CommandOptions | InteractionOptions) {
90 let member: GuildMember | null = null;
91
92 if (msg instanceof CommandInteraction && options.isInteraction) {
93 if (options.options.getMember('user'))
94 member = <GuildMember> await options.options.getMember('user');
95 else
96 member = <GuildMember> msg.member!;
97 }
98 else if (msg instanceof Message && !options.isInteraction) {
99 if (options.normalArgs[0]) {
100 try {
101 const tempMember = await getMember(msg, options);
102
103 if (!tempMember)
104 throw new Error();
105
106 member = tempMember;
107 }
108 catch (e) {
109 console.log(e);
110
111 await msg.reply({
112 embeds: [
113 new MessageEmbed()
114 .setColor('#f14a60')
115 .setDescription(':x: The user doesn\'t exist or not a member of this server.')
116 ]
117 });
118
119 return;
120 }
121 }
122 else {
123 member = msg.member!;
124 }
125 }
126
127 const status = (s: 'idle' | 'online' | 'dnd' | 'invisible' | null | undefined): string => {
128 if (s === 'idle')
129 return 'Idle';
130 else if (s === 'dnd')
131 return 'Do not disturb';
132 else if (s === 'online')
133 return 'Online';
134 else if (s === undefined || s === null || s === 'invisible')
135 return 'Offline/Invisible';
136
137 return s;
138 };
139
140 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;
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({
234 embeds: [
235 new MessageEmbed({
236 image: {
237 url: banner,
238 }
239 })
240 .setColor(member!.user!.hexAccentColor ? member!.user!.hexAccentColor! : '#007bff')
241 .setAuthor({
242 name: member?.user.tag!,
243 iconURL: member!.user.displayAvatarURL()
244 })
245 .setThumbnail(member!.displayAvatarURL({
246 size: 4096
247 }))
248 .setFields(fields)
249 .setFooter({
250 text: `${member?.user.bot ? 'Bot' : 'User'} • ${member!.id} • Has ${percentage.toString()}% permissions`
251 })
252 ]
253 });
254 }
255 }

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26