/[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 453 - (show annotations)
Mon Jul 29 17:30:19 2024 UTC (8 months, 2 weeks ago) by rakin
File MIME type: application/typescript
File size: 9322 byte(s)
feat: make the spotify status song name clickable
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, GuildMember, Message, 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 default class ProfileCommand extends BaseCommand {
66 supportsInteractions: boolean = true;
67
68 constructor() {
69 super('profile', 'information', []);
70 }
71
72 async run(client: DiscordClient, msg: Message | CommandInteraction, options: CommandOptions | InteractionOptions) {
73 let user: GuildMember | null = null;
74
75 if (msg instanceof CommandInteraction && options.isInteraction) {
76 if (options.options.getMember('user'))
77 user = <GuildMember> await options.options.getMember('user');
78 else
79 user = <GuildMember> msg.member!;
80 }
81 else if (msg instanceof Message && !options.isInteraction) {
82 if (options.normalArgs[0]) {
83 try {
84 const tempMember = await getMember(msg, options);
85
86 if (!tempMember)
87 throw new Error();
88
89 user = tempMember;
90 }
91 catch (e) {
92 console.log(e);
93
94 await msg.reply({
95 embeds: [
96 new MessageEmbed()
97 .setColor('#f14a60')
98 .setDescription(':x: The user doesn\'t exist or not a member of this server.')
99 ]
100 });
101
102 return;
103 }
104 }
105 else {
106 user = msg.member!;
107 }
108 }
109
110 const status = (s: 'idle' | 'online' | 'dnd' | 'invisible' | null | undefined): string => {
111 if (s === 'idle')
112 return 'Idle';
113 else if (s === 'dnd')
114 return 'Do not disturb';
115 else if (s === 'online')
116 return 'Online';
117 else if (s === undefined || s === null || s === 'invisible')
118 return 'Offline/Invisible';
119
120 return s;
121 };
122
123 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) + ')' : ''));
124 // const state = user?.presence?.activities.find(a => a.type === 'CUSTOM')?.state;
125 let activities: string[] | string = [];
126
127 if (user?.presence) {
128 for (const a of user?.presence?.activities.values()!) {
129 console.log(a);
130
131 if (a.type === 'CUSTOM') {
132 activities.push(`${a.emoji ? `${a.emoji.toString()} ` : ''}${a.state}`);
133 }
134 else if (a.type === 'LISTENING') {
135 if (a.name === 'Spotify') {
136 const url = a.syncId ? `https://open.spotify.com/track/${a.syncId}` : null;
137 activities.push(`:notes: Listening to **Spotify**: ${url ? '[' : '**'}${a.state?.replace(/\;/, ',')} - ${a.details}${url ? '](' + url + ')' : '**'}`);
138 continue;
139 }
140
141 activities.push(`:musical_note: Listening to **${a.name}**`);
142 }
143 else if (a.type === 'COMPETING') {
144 activities.push(`:fire: Competing **${a.name}**`);
145 }
146 else if (a.type === 'PLAYING') {
147 activities.push(`:video_game: Playing **${a.name}**`);
148 }
149 else if (a.type === 'STREAMING') {
150 activities.push(`:video_camera: Streaming **${a.name}**`);
151 }
152 else if (a.type === 'WATCHING') {
153 activities.push(`:tv: Watching **${a.name}**`);
154 }
155 }
156 }
157
158 activities = activities.join('\n');
159
160 const allRoles = [...user!.roles.cache.values()].filter(role => role.id !== msg.guild!.id).sort((role1, role2) => {
161 return role2.position - role1.position;
162 });
163 const limit = 10;
164 const roles = (allRoles.length > limit ? allRoles.slice(0, limit) : allRoles).reduce((acc, value) => `${acc} ${roleMention(value.id)}`, '')!.trim()!;
165 const fields = [
166 {
167 name: "Nickname",
168 value: `${user!.nickname?.replace(/\*\<\>\@\_\~\|/g, '') ?? '*Nickname not set*'}`
169 },
170 {
171 name: "Account Created",
172 value: `${user!.user.createdAt.toLocaleDateString('en-US')} (${timeSince(user!.user.createdTimestamp)})`
173 },
174 {
175 name: "Joined at",
176 value: `${user!.joinedAt!.toLocaleDateString('en-US')} (${timeSince(user!.joinedTimestamp!)})`
177 },
178 {
179 name: 'Active Devices',
180 value: `${statusText === '' ? 'Offline/Invisible' : statusText}`
181 },
182 {
183 name: 'Status',
184 value: `${activities?.trim() === '' ? '*No status set*' : activities}`
185 },
186 {
187 name: 'Roles',
188 value: roles === '' ? '*No roles assigned*' : `${roles} ${allRoles.length > limit ? `**+ ${allRoles.length - limit} More**` : ''}`
189 }
190 ];
191
192 const badges = getUserBadges(user!.user);
193
194 if (badges.length > 0) {
195 fields.push({
196 name: 'Badges',
197 value: badges.join("\n")
198 });
199 }
200
201 let banner: string | undefined;
202
203 try {
204 await user?.user.fetch(true);
205 banner = user!.user!.bannerURL({ size: 4096 }) ?? undefined;
206 }
207 catch (e) {
208 console.log(e);
209 }
210
211 console.log("Banner", banner, user!.user!.banner);
212
213 await msg.reply({
214 embeds: [
215 new MessageEmbed({
216 image: {
217 url: banner,
218 }
219 })
220 .setColor(user!.user!.hexAccentColor ? user!.user!.hexAccentColor! : '#007bff')
221 .setAuthor({
222 name: user?.user.tag!,
223 iconURL: user!.user.displayAvatarURL()
224 })
225 .setThumbnail(user!.displayAvatarURL({
226 size: 4096
227 }))
228 .setFields(fields)
229 .setFooter({
230 text: `${user?.user.bot ? 'Bot' : 'User'} • ${user!.id}`
231 })
232 ]
233 });
234 }
235 }

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26