aboutsummaryrefslogtreecommitdiff
path: root/src/commands/info
diff options
context:
space:
mode:
authorIRONM00N <64110067+IRONM00N@users.noreply.github.com>2021-07-14 21:22:09 -0400
committerIRONM00N <64110067+IRONM00N@users.noreply.github.com>2021-07-14 21:22:09 -0400
commit53d2b18f7f73d5696fb7cd86d1c164a790dfdcc3 (patch)
treef95f23aad382879b35860d4d3be3642068fac8a2 /src/commands/info
parenteaaae08aeee1fa16a4e1ad0b26fceb42885bfcde (diff)
downloadtanzanite-53d2b18f7f73d5696fb7cd86d1c164a790dfdcc3.tar.gz
tanzanite-53d2b18f7f73d5696fb7cd86d1c164a790dfdcc3.tar.bz2
tanzanite-53d2b18f7f73d5696fb7cd86d1c164a790dfdcc3.zip
started moving over some other commands
Diffstat (limited to 'src/commands/info')
-rw-r--r--src/commands/info/avatar.ts51
-rw-r--r--src/commands/info/botInfo.ts2
-rw-r--r--src/commands/info/color.ts42
-rw-r--r--src/commands/info/guildInfo.ts171
-rw-r--r--src/commands/info/help.ts6
-rw-r--r--src/commands/info/icon.ts34
-rw-r--r--src/commands/info/invite.ts33
-rw-r--r--src/commands/info/ping.ts4
-rw-r--r--src/commands/info/snowflakeInfo.ts151
-rw-r--r--src/commands/info/userInfo.ts160
10 files changed, 648 insertions, 6 deletions
diff --git a/src/commands/info/avatar.ts b/src/commands/info/avatar.ts
new file mode 100644
index 0000000..3d1776f
--- /dev/null
+++ b/src/commands/info/avatar.ts
@@ -0,0 +1,51 @@
+import { Constants } from 'discord-akairo';
+import { MessageEmbed, User } from 'discord.js';
+import { BushCommand, BushMessage, BushSlashMessage } from '../../lib';
+
+export default class AvatarCommand extends BushCommand {
+ constructor() {
+ super('avatar', {
+ aliases: ['avatar', 'av'],
+ category: 'info',
+ description: {
+ content: "A command to get a user's avatar",
+ usage: 'avatar [user]',
+ examples: 'avatar'
+ },
+ args: [
+ {
+ id: 'user',
+ type: Constants.ArgumentTypes.USER,
+ match: Constants.ArgumentMatches.PHRASE,
+ prompt: {
+ start: 'Who would you like to see the avatar of?',
+ retry: '{error} Choose a valid user.',
+ optional: true
+ }
+ }
+ ],
+ clientPermissions: ['SEND_MESSAGES', 'EMBED_LINKS'],
+ slash: true,
+ slashOptions: [
+ {
+ name: 'user',
+ description: 'The user you would like to find the avatar of.',
+ type: 'USER',
+ required: false
+ }
+ ]
+ });
+ }
+
+ async exec(message: BushMessage | BushSlashMessage, { user }: { user: User }): Promise<void> {
+ user = user ?? message.author;
+
+ const embed = new MessageEmbed()
+ .setTimestamp()
+ .setColor(this.client.util.colors.default)
+ .setTitle(user.tag)
+ .setImage(user.avatarURL({ size: 2048, format: 'png', dynamic: true }));
+
+ await message.util.reply({ embeds: [embed] });
+ }
+}
diff --git a/src/commands/info/botInfo.ts b/src/commands/info/botInfo.ts
index d5941b2..986bd01 100644
--- a/src/commands/info/botInfo.ts
+++ b/src/commands/info/botInfo.ts
@@ -4,7 +4,7 @@ import { MessageEmbed, version as discordJSVersion } from 'discord.js';
export default class BotInfoCommand extends BushCommand {
public constructor() {
super('botinfo', {
- aliases: ['botinfo'],
+ aliases: ['botinfo', 'stats'],
category: 'info',
description: {
content: 'Shows information about the bot',
diff --git a/src/commands/info/color.ts b/src/commands/info/color.ts
new file mode 100644
index 0000000..4db20e7
--- /dev/null
+++ b/src/commands/info/color.ts
@@ -0,0 +1,42 @@
+import { BushCommand, BushMessage, BushSlashMessage } from '@lib';
+import { Constants } from 'discord-akairo';
+import { ColorResolvable, MessageEmbed } from 'discord.js';
+
+export default class ColorCommand extends BushCommand {
+ public constructor() {
+ super('color', {
+ aliases: ['color'],
+ category: 'info',
+ description: {
+ content: 'See what color a hex code is.',
+ usage: 'color <color>',
+ examples: ['color #0000FF']
+ },
+ args: [
+ {
+ id: 'color',
+ type: /^#?(?<code>[0-9A-F]{6})$/i,
+ match: Constants.ArgumentMatches.PHRASE,
+ prompt: {
+ start: 'What color value would you like to see the color of',
+ retry: '{error} Choose a valid hex color code.'
+ }
+ }
+ ],
+ channel: 'guild',
+ clientPermissions: ['EMBED_LINKS', 'SEND_MESSAGES']
+ });
+ }
+
+ public async exec(
+ message: BushMessage | BushSlashMessage,
+ { color: { match } }: { color: { match: RegExpMatchArray; matches: RegExpMatchArray[] } }
+ ): Promise<unknown> {
+ const embed = new MessageEmbed()
+ .addField('Hex', match.groups.code, false)
+ .addField('RGB', this.client.util.hexToRgb(match.groups.code), false)
+ .setColor(match.groups.code as ColorResolvable);
+
+ return await message.util.reply({ embeds: [embed] });
+ }
+}
diff --git a/src/commands/info/guildInfo.ts b/src/commands/info/guildInfo.ts
new file mode 100644
index 0000000..a3e7405
--- /dev/null
+++ b/src/commands/info/guildInfo.ts
@@ -0,0 +1,171 @@
+import { Argument, Constants } from 'discord-akairo';
+import { Guild, GuildPreview, MessageEmbed, Snowflake, Vanity } from 'discord.js';
+import { BushCommand, BushMessage, BushSlashMessage } from '../../lib';
+
+// TODO: Implement regions and security
+export default class GuildInfoCommand extends BushCommand {
+ public constructor() {
+ super('guildInfo', {
+ aliases: ['guildinfo', 'serverinfo', 'guild', 'server', 'g'],
+ category: 'info',
+ description: {
+ content: 'Get info about a server.',
+ usage: 'guildinfo [guild]',
+ examples: ['guildinfo 516977525906341928']
+ },
+ args: [
+ {
+ id: 'guild',
+ type: Argument.union(Constants.ArgumentTypes.GUILD, Constants.ArgumentTypes.BIGINT),
+ match: Constants.ArgumentMatches.PHRASE,
+ prompt: {
+ start: 'What server would you like to find information about?',
+ retry: '{error} Choose a valid server to find information about.',
+ optional: true
+ }
+ }
+ ],
+ slash: true,
+ slashOptions: [
+ {
+ name: 'guild',
+ description: 'The id of the guild you would like to find information about.',
+ type: 'STRING',
+ required: false
+ }
+ ],
+ clientPermissions: ['EMBED_LINKS', 'SEND_MESSAGES'],
+ userPermissions: ['SEND_MESSAGES']
+ });
+ }
+
+ public async exec(message: BushMessage | BushSlashMessage, args: { guild: Guild | bigint | GuildPreview }): Promise<unknown> {
+ if (!args?.guild && !message.guild) {
+ return await message.util.reply(
+ `${this.client.util.emojis.error} You must either provide an server to provide info about or run this command in a server.`
+ );
+ }
+ let isPreview = false;
+ if (['bigint', 'number', 'string'].includes(typeof args?.guild)) {
+ const preview = await this.client.fetchGuildPreview(`${args.guild}` as Snowflake).catch(() => {});
+ if (preview) {
+ args.guild = preview;
+ isPreview = true;
+ } else {
+ return await message.util.reply(`${this.client.util.emojis.error} That guild is not discoverable or does not exist.`);
+ }
+ }
+ const guild: Guild | GuildPreview = (args?.guild as Guild | GuildPreview) || (message.guild as Guild);
+ const emojis: string[] = [];
+ const guildAbout: string[] = [];
+ // const guildSecurity = [];
+ if (['516977525906341928', '784597260465995796', '717176538717749358', '767448775450820639'].includes(guild.id))
+ emojis.push(this.client.consts.mappings.otherEmojis.BUSH_VERIFIED);
+
+ if (!isPreview && guild instanceof Guild) {
+ if (guild.premiumTier) emojis.push(this.client.consts.mappings.otherEmojis['BOOST_' + guild.premiumTier]);
+ await guild.fetch();
+ const channelTypes = [
+ `${this.client.consts.mappings.otherEmojis.TEXT} ${guild.channels.cache
+ .filter((channel) => channel.type === 'GUILD_TEXT')
+ .size.toLocaleString()}`,
+ `${this.client.consts.mappings.otherEmojis.NEWS} ${guild.channels.cache
+ .filter((channel) => channel.type === 'GUILD_NEWS')
+ .size.toLocaleString()}`,
+ `${this.client.consts.mappings.otherEmojis.VOICE} ${guild.channels.cache
+ .filter((channel) => channel.type === 'GUILD_VOICE')
+ .size.toLocaleString()}`,
+ `${this.client.consts.mappings.otherEmojis.STAGE} ${guild.channels.cache
+ .filter((channel) => channel.type === 'GUILD_STAGE_VOICE')
+ .size.toLocaleString()}`,
+ `${this.client.consts.mappings.otherEmojis.STORE} ${guild.channels.cache
+ .filter((channel) => channel.type === 'GUILD_STORE')
+ .size.toLocaleString()}`,
+ `${this.client.consts.mappings.otherEmojis.CATEGORY} ${guild.channels.cache
+ .filter((channel) => channel.type === 'GUILD_CATEGORY')
+ .size.toLocaleString()}`,
+ `${this.client.consts.mappings.otherEmojis.THREAD} ${guild.channels.cache
+ .filter((channel) =>
+ ['GUILD_NEWS_THREAD', 'GUILD_PUBLIC_THREAD', 'GUILD_PRIVATE_THREAD', 'GUILD_STAGE_VOICE'].includes(channel.type)
+ )
+ .size.toLocaleString()}`
+ ];
+
+ // TODO add guild regions
+ // const guildRegions = [];
+
+ guildAbout.push(
+ `**Owner:** ${guild.members.cache.get(guild.ownerId)?.user.tag}`,
+ `**Created** ${guild.createdAt.toLocaleString()}`,
+ `**Members:** ${guild.memberCount.toLocaleString()}`,
+ `**Online:** ${guild.approximatePresenceCount?.toLocaleString()}`,
+ `**Channels:** ${guild.channels.cache.size} (${channelTypes.join(', ')})`,
+ `**Emojis:** ${guild.emojis.cache.size.toLocaleString()}`
+ // `**Region:** ${guildRegions.join()}`
+ );
+ if (guild.premiumSubscriptionCount)
+ guildAbout.push(
+ `**Boosts:** Level ${guild.premiumTier.slice(0, 4)} with ${guild.premiumSubscriptionCount ?? 0} boosts`
+ );
+ if (guild.me?.permissions.has('MANAGE_GUILD') && guild.vanityURLCode) {
+ const vanityInfo: Vanity = await guild.fetchVanityData();
+ guildAbout.push(
+ `**Vanity URL:** discord.gg/${vanityInfo.code}`,
+ `**Vanity Uses:** ${vanityInfo.uses?.toLocaleString()}`
+ );
+ }
+
+ // guildSecurity.push;
+ } else {
+ guildAbout.push(
+ `**Members:** ${guild.approximateMemberCount?.toLocaleString()}`,
+ `**Online:** ${guild.approximatePresenceCount?.toLocaleString()}`,
+ `**Emojis:** ${(guild as GuildPreview).emojis.size}`
+ );
+ }
+
+ const guildFeatures = guild.features.sort((a, b) => {
+ const aWeight = this.client.consts.mappings.features[a]?.weight;
+ const bWeight = this.client.consts.mappings.features[b]?.weight;
+
+ if (aWeight != undefined && bWeight != undefined) {
+ return aWeight - bWeight;
+ } else if (aWeight == undefined) {
+ return 1;
+ } else if (bWeight == undefined) {
+ return -1;
+ }
+ });
+ if (guildFeatures.length) {
+ guildFeatures.forEach((feature) => {
+ if (this.client.consts.mappings.features[feature]?.emoji) {
+ emojis.push(`${this.client.consts.mappings.features[feature].emoji}`);
+ } else if (this.client.consts.mappings.features[feature]?.name) {
+ emojis.push(`\`${this.client.consts.mappings.features[feature].name}\``);
+ } else {
+ emojis.push(`\`${feature}\``);
+ }
+ });
+ }
+
+ if (guild.description) {
+ emojis.push(`\n\n${guild.description}`);
+ }
+
+ const guildInfoEmbed = new MessageEmbed()
+ .setTitle(guild.name)
+ .setColor(this.client.util.colors.default)
+ .addField('» About', guildAbout.join('\n'));
+ const guildIcon = guild.iconURL({ size: 2048, format: 'png', dynamic: true });
+ if (guildIcon) {
+ guildInfoEmbed.setThumbnail(guildIcon);
+ }
+ // if (!isPreview) {
+ // guildInfoEmbed.addField('» Security', guildSecurity.join('\n'));
+ // }
+ if (emojis) {
+ guildInfoEmbed.setDescription(emojis.join(' '));
+ }
+ return await message.util.reply({ embeds: [guildInfoEmbed] });
+ }
+}
diff --git a/src/commands/info/help.ts b/src/commands/info/help.ts
index e061453..0977c36 100644
--- a/src/commands/info/help.ts
+++ b/src/commands/info/help.ts
@@ -11,8 +11,6 @@ export default class HelpCommand extends BushCommand {
usage: 'help [command]',
examples: ['help prefix']
},
- clientPermissions: ['EMBED_LINKS'],
-
args: [
{
id: 'command',
@@ -38,7 +36,9 @@ export default class HelpCommand extends BushCommand {
type: 'STRING',
required: false
}
- ]
+ ],
+ clientPermissions: ['EMBED_LINKS', 'SEND_MESSAGES'],
+ userPermissions: ['SEND_MESSAGES']
});
}
diff --git a/src/commands/info/icon.ts b/src/commands/info/icon.ts
new file mode 100644
index 0000000..bd1cdf4
--- /dev/null
+++ b/src/commands/info/icon.ts
@@ -0,0 +1,34 @@
+import { MessageEmbed } from 'discord.js';
+import { BushCommand, BushMessage, BushSlashMessage } from '../../lib';
+
+export default class IconCommand extends BushCommand {
+ constructor() {
+ super('icon', {
+ aliases: ['icon', 'guildavatar', 'severicon', 'guildicon'],
+ category: 'info',
+ description: {
+ content: "A command to get the server's icon",
+ usage: 'icon',
+ examples: 'icon'
+ },
+ clientPermissions: ['SEND_MESSAGES', 'EMBED_LINKS'],
+ channel: 'guild',
+ slash: true
+ });
+ }
+
+ async exec(message: BushMessage | BushSlashMessage): Promise<void> {
+ const embed = new MessageEmbed()
+ .setTimestamp()
+ .setColor(this.client.util.colors.default)
+ .setImage(
+ message.guild?.iconURL({
+ size: 2048,
+ dynamic: true,
+ format: 'png'
+ })
+ )
+ .setTitle(message.guild.name);
+ await message.util.reply({ embeds: [embed] });
+ }
+}
diff --git a/src/commands/info/invite.ts b/src/commands/info/invite.ts
new file mode 100644
index 0000000..f53e930
--- /dev/null
+++ b/src/commands/info/invite.ts
@@ -0,0 +1,33 @@
+import { BushCommand, BushMessage, BushSlashMessage } from '@lib';
+import { MessageActionRow, MessageButton } from 'discord.js';
+
+export default class InviteCommand extends BushCommand {
+ public constructor() {
+ super('invite', {
+ aliases: ['invite'],
+ category: 'info',
+ description: {
+ content: 'Sends the bot invite link.',
+ usage: 'invite',
+ examples: ['invite']
+ },
+ ratelimit: 4,
+ cooldown: 4000,
+ clientPermissions: ['SEND_MESSAGES'],
+ slash: true
+ });
+ }
+
+ public async exec(message: BushMessage | BushSlashMessage): Promise<unknown> {
+ if (this.client.config.dev)
+ return await message.util.reply(`${this.client.util.emojis.error} The dev bot cannot be invited.`);
+ const ButtonRow = new MessageActionRow().addComponents(
+ new MessageButton({
+ style: 'LINK',
+ label: 'Invite Me',
+ url: `https://discord.com/api/oauth2/authorize?client_id=${this.client.user.id}&permissions=2147483647&scope=bot%20applications.commands`
+ })
+ );
+ return await message.util.reply({ components: [ButtonRow] });
+ }
+}
diff --git a/src/commands/info/ping.ts b/src/commands/info/ping.ts
index 59f475f..d1f406d 100644
--- a/src/commands/info/ping.ts
+++ b/src/commands/info/ping.ts
@@ -11,9 +11,9 @@ export default class PingCommand extends BushCommand {
usage: 'ping',
examples: ['ping']
},
+ slash: true,
clientPermissions: ['SEND_MESSAGES', 'EMBED_LINKS'],
- userPermissions: ['SEND_MESSAGES'],
- slash: true
+ userPermissions: ['SEND_MESSAGES']
});
}
diff --git a/src/commands/info/snowflakeInfo.ts b/src/commands/info/snowflakeInfo.ts
new file mode 100644
index 0000000..e234cc2
--- /dev/null
+++ b/src/commands/info/snowflakeInfo.ts
@@ -0,0 +1,151 @@
+import {
+ CategoryChannel,
+ Channel,
+ DeconstructedSnowflake,
+ DMChannel,
+ Emoji,
+ Guild,
+ MessageEmbed,
+ NewsChannel,
+ Role,
+ Snowflake,
+ SnowflakeUtil,
+ StageChannel,
+ TextChannel,
+ User,
+ VoiceChannel
+} from 'discord.js';
+import { BushCommand, BushMessage, BushSlashMessage } from '../../lib';
+
+export default class SnowflakeInfoCommand extends BushCommand {
+ public constructor() {
+ super('snowflake', {
+ aliases: ['snowflake', 'info', 'sf'],
+ category: 'info',
+ ratelimit: 4,
+ cooldown: 4000,
+ description: {
+ content: 'Provides information about the specified Snowflake.',
+ usage: 'snowflake <snowflake>',
+ examples: ['snowflake 322862723090219008']
+ },
+ args: [
+ {
+ id: 'snowflake',
+ type: 'bigint',
+ prompt: {
+ start: 'Enter the snowflake you would like to get information about.',
+ retry: '{error} Choose a valid snowflake.',
+ optional: false
+ }
+ }
+ ],
+ clientPermissions: ['EMBED_LINKS', 'SEND_MESSAGES'],
+ slash: true,
+ slashOptions: [
+ {
+ name: 'snowflake',
+ description: 'The snowflake you would like to get information about.',
+ type: 'STRING',
+ required: true
+ }
+ ]
+ });
+ }
+ public async exec(message: BushMessage | BushSlashMessage, args: { snowflake: bigint }): Promise<unknown> {
+ const snowflake = `${args.snowflake}` as Snowflake;
+ const snowflakeEmbed = new MessageEmbed().setTitle('Unknown :snowflake:').setColor(this.client.util.colors.default);
+
+ // Channel
+ if (this.client.channels.cache.has(snowflake)) {
+ const channel: Channel = this.client.channels.cache.get(snowflake);
+ const channelInfo = [`**Type:** ${channel.type}`];
+ if (['dm', 'group'].includes(channel.type)) {
+ const _channel = channel as DMChannel;
+ channelInfo.push(`**Recipient:** ${_channel.recipient.tag} (${_channel.recipient.id})`);
+ snowflakeEmbed.setTitle(`:snowflake: DM with ${(channel as DMChannel).recipient.tag} \`[Channel]\``);
+ } else if (
+ [
+ 'GUILD_CATEGORY',
+ 'GUILD_NEWS',
+ 'GUILD_TEXT',
+ 'GUILD_VOICE',
+ 'GUILD_STORE',
+ 'GUILD_STAGE_VOICE',
+ 'GUILD_NEWS_THREAD',
+ 'GUILD_PUBLIC_THREAD',
+ 'GUILD_PRIVATE_THREAD'
+ ].includes(channel.type)
+ ) {
+ const _channel = channel as TextChannel | VoiceChannel | NewsChannel | StageChannel | CategoryChannel | StageChannel;
+ channelInfo.push(
+ `**Channel Name:** <#${_channel.id}> (${_channel.name})`,
+ `**Channel's Server:** ${_channel.guild.name} (${_channel.guild.id})`
+ );
+ snowflakeEmbed.setTitle(`:snowflake: ${_channel.name} \`[Channel]\``);
+ }
+ snowflakeEmbed.addField('» Channel Info', channelInfo.join('\n'));
+ }
+
+ // Guild
+ else if (this.client.guilds.cache.has(snowflake)) {
+ const guild: Guild = this.client.guilds.cache.get(snowflake);
+ const guildInfo = [
+ `**Name:** ${guild.name}`,
+ `**Owner:** ${this.client.users.cache.get(guild.ownerId)?.tag || '¯\\_(ツ)_/¯'} (${guild.ownerId})`,
+ `**Members:** ${guild.memberCount?.toLocaleString()}`
+ ];
+ snowflakeEmbed.setThumbnail(guild.iconURL({ size: 2048, dynamic: true }));
+ snowflakeEmbed.addField('» Server Info', guildInfo.join('\n'));
+ snowflakeEmbed.setTitle(`:snowflake: ${guild.name} \`[Server]\``);
+ }
+
+ // User
+ else if (this.client.users.cache.has(snowflake)) {
+ const user: User = this.client.users.cache.get(snowflake);
+ const userInfo = [`**Name:** <@${user.id}> (${user.tag})`];
+ snowflakeEmbed.setThumbnail(user.avatarURL({ size: 2048, dynamic: true }));
+ snowflakeEmbed.addField('» User Info', userInfo.join('\n'));
+ snowflakeEmbed.setTitle(`:snowflake: ${user.tag} \`[User]\``);
+ }
+
+ // Emoji
+ else if (this.client.emojis.cache.has(snowflake)) {
+ const emoji: Emoji = this.client.emojis.cache.get(snowflake);
+ const emojiInfo = [`**Name:** ${emoji.name}`, `**Animated:** ${emoji.animated}`];
+ snowflakeEmbed.setThumbnail(emoji.url);
+ snowflakeEmbed.addField('» Emoji Info', emojiInfo.join('\n'));
+ snowflakeEmbed.setTitle(`:snowflake: ${emoji.name} \`[Emoji]\``);
+ }
+
+ // Role
+ else if (message.guild.roles.cache.has(snowflake)) {
+ const role: Role = message.guild.roles.cache.get(snowflake);
+ const roleInfo = [
+ `**Name:** <@&${role.id}> (${role.name})`,
+ `**Members:** ${role.members.size}`,
+ `**Hoisted:** ${role.hoist}`,
+ `**Managed:** ${role.managed}`,
+ `**Position:** ${role.position}`,
+ `**Hex Color:** ${role.hexColor}`
+ ];
+ if (role.color) snowflakeEmbed.setColor(role.color);
+ snowflakeEmbed.addField('» Role Info', roleInfo.join('\n'));
+ snowflakeEmbed.setTitle(`:snowflake: ${role.name} \`[Role]\``);
+ }
+
+ // SnowflakeInfo
+ const deconstructedSnowflake: DeconstructedSnowflake = SnowflakeUtil.deconstruct(snowflake);
+ const snowflakeInfo = [
+ `**Timestamp:** ${deconstructedSnowflake.timestamp}`,
+ `**Created:** ${deconstructedSnowflake.date.toLocaleString()}`,
+ `**Worker ID:** ${deconstructedSnowflake.workerId}`,
+ `**Process ID:** ${deconstructedSnowflake.processId}`,
+ `**Increment:** ${deconstructedSnowflake.increment}`
+ // `**Binary:** ${deconstructedSnowflake.binary}`
+ ];
+ snowflakeEmbed.addField('» Snowflake Info', snowflakeInfo.join('\n'));
+
+ return await message.util.reply({ embeds: [snowflakeEmbed] });
+ }
+}
diff --git a/src/commands/info/userInfo.ts b/src/commands/info/userInfo.ts
new file mode 100644
index 0000000..50756a6
--- /dev/null
+++ b/src/commands/info/userInfo.ts
@@ -0,0 +1,160 @@
+import { BushCommand, BushMessage, BushSlashMessage } from '@lib';
+import { GuildMember, MessageEmbed } from 'discord.js';
+import moment from 'moment';
+
+// TODO: Allow looking up a user not in the guild and not cached
+// TODO: Re-Implement Status Emojis
+// TODO: Add bot information
+export default class UserInfoCommand extends BushCommand {
+ public constructor() {
+ super('userinfo', {
+ aliases: ['userinfo', 'user', 'u'],
+ category: 'info',
+ description: {
+ usage: 'userinfo [user]',
+ examples: ['userinfo 322862723090219008'],
+ content: 'Gives information about a specified user.'
+ },
+ args: [
+ {
+ id: 'user',
+ type: 'member',
+ prompt: {
+ start: 'What user would you like to find information about?',
+ retry: '{error} Choose a valid user to find information about.',
+ optional: true
+ },
+ default: null
+ }
+ ],
+ slash: true,
+ slashOptions: [
+ {
+ name: 'user',
+ description: 'The user you would like to find information about.',
+ type: 'USER',
+ required: false
+ }
+ ],
+ clientPermissions: ['EMBED_LINKS', 'SEND_MESSAGES'],
+ userPermissions: ['SEND_MESSAGES']
+ });
+ }
+
+ public async exec(message: BushMessage | BushSlashMessage, args: { user: GuildMember }): Promise<unknown> {
+ const user = args?.user || message.member;
+ const emojis = [];
+ const superUsers = this.client.cache.global.superUsers;
+
+ const userEmbed: MessageEmbed = new MessageEmbed()
+ .setTitle(user.user.tag)
+ .setThumbnail(user.user.avatarURL({ size: 2048, format: 'png', dynamic: true }))
+ .setTimestamp();
+
+ // Flags
+ if (this.client.config.owners.includes(user.id)) emojis.push(this.client.consts.mappings.otherEmojis.DEVELOPER);
+ if (superUsers.includes(user.id)) emojis.push(this.client.consts.mappings.otherEmojis.SUPERUSER);
+ const flags = user.user.flags?.toArray();
+ if (flags) {
+ flags.forEach((f) => {
+ if (this.client.consts.mappings.userFlags[f]) {
+ emojis.push(this.client.consts.mappings.userFlags[f]);
+ } else emojis.push(f);
+ });
+ }
+
+ // Since discord bald I just guess if someone has nitro
+ if (
+ Number(user.user.discriminator) < 10 ||
+ this.client.consts.mappings.maybeNitroDiscrims.includes(user.user.discriminator) ||
+ user.user.displayAvatarURL({ dynamic: true })?.endsWith('.gif') ||
+ user.user.flags?.toArray().includes('PARTNERED_SERVER_OWNER')
+ ) {
+ emojis.push(this.client.consts.mappings.otherEmojis.NITRO);
+ }
+
+ if (message.guild.ownerId == user.id) emojis.push(this.client.consts.mappings.otherEmojis.OWNER);
+ else if (user.permissions.has('ADMINISTRATOR')) emojis.push(this.client.consts.mappings.otherEmojis.ADMIN);
+ if (user.premiumSinceTimestamp) emojis.push(this.client.consts.mappings.otherEmojis.BOOSTER);
+
+ const createdAt = user.user.createdAt.toLocaleString(),
+ createdAtDelta = moment(user.user.createdAt).diff(moment()).toLocaleString(),
+ joinedAt = user.joinedAt?.toLocaleString(),
+ joinedAtDelta = moment(user.joinedAt)?.diff(moment()).toLocaleString(),
+ premiumSince = user.premiumSince?.toLocaleString(),
+ premiumSinceDelta = moment(user.premiumSince)?.diff(moment()).toLocaleString();
+
+ // General Info
+ const generalInfo = [
+ `**Mention:** <@${user.id}>`,
+ `**ID:** ${user.id}`,
+ `**Created: **${createdAt} (${createdAtDelta} ago)`
+ ];
+ userEmbed.addField('» General Info', generalInfo.join('\n'));
+
+ // Server User Info
+ const serverUserInfo = [];
+ if (joinedAt)
+ serverUserInfo.push(
+ `**${message.guild.ownerId == user.id ? 'Created Server' : 'Joined'}: ** ${joinedAt} (${joinedAtDelta} ago)`
+ );
+ if (premiumSince) serverUserInfo.push(`**Boosting Since:** ${premiumSince} (${premiumSinceDelta} ago)`);
+ if (user.displayHexColor) serverUserInfo.push(`**Display Color:** ${user.displayHexColor}`);
+ if (user.id == '322862723090219008' && message.guild.id == this.client.consts.mappings.guilds.bush)
+ serverUserInfo.push(`**General Deletions:** 2`);
+ if (
+ ['384620942577369088', '496409778822709251'].includes(user.id) &&
+ message.guild.id == this.client.consts.mappings.guilds.bush
+ )
+ serverUserInfo.push(`**General Deletions:** 1`);
+ if (user.nickname) serverUserInfo.push(`**Nickname** ${user.nickname}`);
+ if (serverUserInfo.length)
+ userEmbed
+ .addField('» Server Info', serverUserInfo.join('\n'))
+ .setColor(user.displayColor || this.client.util.colors.default);
+
+ // User Presence Info
+ if (user.presence?.status || user.presence?.clientStatus || user.presence?.activities) {
+ let customStatus = '';
+ const activitiesNames = [];
+ if (user.presence.activities) {
+ user.presence.activities.forEach((a) => {
+ if (a.type == 'CUSTOM' && a.state) {
+ const emoji = `${a.emoji ? `${a.emoji.toString()} ` : ''}`;
+ customStatus = `${emoji}${a.state}`;
+ }
+ activitiesNames.push(`\`${a.name}\``);
+ });
+ }
+ let devices;
+ if (user.presence.clientStatus) devices = Object.keys(user.presence.clientStatus);
+ const presenceInfo = [];
+ if (user.presence.status) presenceInfo.push(`**Status:** ${user.presence.status}`);
+ if (devices)
+ presenceInfo.push(`**${devices.length - 1 ? 'Devices' : 'Device'}:** ${this.client.util.oxford(devices, 'and', '')}`);
+ if (activitiesNames.length)
+ presenceInfo.push(
+ `**Activit${activitiesNames.length - 1 ? 'ies' : 'y'}:** ${this.client.util.oxford(activitiesNames, 'and', '')}`
+ );
+ if (customStatus) presenceInfo.push(`**Custom Status:** ${customStatus}`);
+ userEmbed.addField('» Presence', presenceInfo.join('\n'));
+ }
+
+ // Important Perms
+ const perms = [];
+ if (user.permissions.has('ADMINISTRATOR') || message.guild.ownerId == user.id) {
+ perms.push('`Administrator`');
+ } else {
+ user.permissions.toArray(true).forEach((permission) => {
+ if (this.client.consts.mappings.permissions[permission]?.important) {
+ perms.push(`\`${this.client.consts.mappings.permissions[permission].name}\``);
+ }
+ });
+ }
+
+ if (perms.length) userEmbed.addField('» Important Perms', perms.join(' '));
+ if (emojis) userEmbed.setDescription(emojis.join(' '));
+
+ return await message.util.reply({ embeds: [userEmbed] });
+ }
+}