const { Command } = require('../../../../interfaces'); const similarity = require('similarity'); const { Util, Emojis } = require('../../../../../util'); const Constants = { Badges: { DISCORD_EMPLOYEE: Emojis['discord-staff'], DISCORD_PARTNER: Emojis['discord-partner'], HYPESQUAD_EVENTS: Emojis['hypesquad-events'], BUGHUNTER_LEVEL_1: Emojis['bughunter'], //eslint-disable-line dot-notation BUGHUNTER_LEVEL_2: Emojis['bughunter-gold'], HOUSE_BRAVERY: Emojis['hypesquad-bravery'], HOUSE_BRILLIANCE: Emojis['hypesquad-brilliance'], HOUSE_BALANCE: Emojis['hypesquad-balance'], EARLY_SUPPORTER: Emojis['early-supporter'], VERIFIED_DEVELOPER: Emojis['bot-developer'] } }; class UserCommand extends Command { constructor(client) { super(client, { name: 'user', module: 'information', description: 'Display information about user.', guildOnly: true, aliases: [ 'userinfo', 'whois' ], arguments: [ { name: 'search', type: 'STRING', types: ['FLAG', 'VERBAL'], required: true }, { name: 'discriminator', aliases: [ 'discrim', 'disc' ], type: 'BOOLEAN', types: ['FLAG'] } ], clientPermissions: ['SEND_MESSAGES', 'EMBED_LINKS'] }); this.client = client; } async execute(message, { params, args }) { let response = ''; if(args.search && args.search.value.length > 1) { const key = args.search.value; let count = 0; const keyFilterMember = (m) => m.nickname && (m.nickname.toLowerCase().includes(key) || similarity(m.nickname.toLowerCase(), key) > 0.75 && Math.abs(m.nickname.length - key.length) < 3) || m.user.username.toLowerCase().includes(key) || similarity(m.user.username.toLowerCase(), key) > 0.75 && Math.abs(m.user.username.length - key.length) < 3; const discrimFilterMember = (m) => m.user.discriminator === key; const keyFilterUser = (u) => u.username.toLowerCase().includes(key) || similarity(u.username, key) > 0.75 && Math.abs(u.username.length - key.length) < 3; const discrimFilterUser = (u) => u.discriminator === key; const members = message.guild.members.cache.filter(args.discriminator ? discrimFilterMember : keyFilterMember); const users = this.client.users.cache.filter(args.discriminator ? discrimFilterUser : keyFilterUser).filter((u) => !members.has(u.id)); if (!users.size && !members.size) return message.formattedRespond('C_USER_SEARCH_404'); for(const [ id, member ] of members) { response += `${Util.escapeMarkdown(member.user.tag)} ${member.nickname ? `- ${Util.escapeMarkdown(member.nickname)}` : ''} [${id}] <:members:741721081261588589>\n`; count++; if(response.length > 1900) break; } if (response.length < 1900) for (const [id, user] of users) { response += `${Util.escapeMarkdown(user.tag)} [${id}]\n`; count++; if (response.length > 1900) break; } response = { description: response, title: message.format('C_USER_SEARCH_TITLE', { key }), color: 0x0088cc, footer: { text: message.format('C_USER_SEARCH_FOOTER', { matches: members.size + users.size, count }) } }; } else { let user = null; if (params.length > 0) { user = await this.client.resolver.resolveUser(params.join(' ')); if (!user) return message.formattedRespond('C_USER_404'); } else user = message.author; const member = await message.guild.members.fetch(user.id).catch((error) => {}); //eslint-disable-line const { activities } = user.presence; const flags = user.flags || await user.fetchFlags(); const badges = flags.toArray().filter((f) => Constants.Badges[f]) .map((f) => Constants.Badges[f]); response = { author: { name: Util.escapeMarkdown(user.tag) // icon_url: user.displayAvatarURL() //eslint-disable-line camelcase }, description: response, thumbnail: { url: user.displayAvatarURL({ dynamic: true }) || user.defaultAvatarURL }, fields: [], footer: { text: `• User ID: ${user.id}` } }; const activity = activities.reduce((acc, curr) => { if (acc.length) acc += `\n`; if (curr.emoji) acc += ` `; if (curr.type !== 'CUSTOM_STATUS') acc += `${curr.name}\n`; if (curr.state) acc += curr.state; return acc; }, ''); const userField = { name: message.format('C_USER_DATA_NAME'), value: message.format('C_USER_DATA', { id: user.id, bot: user.bot ? ` ${Emojis.bot}` : '', created: user.createdAt.toDateString(), status: user.presence.status, // eslint-disable-next-line no-nested-ternary activity, //activity: activities.length > 0 ? activities[0].type === 'CUSTOM_STATUS' ? `${activities[0].name}: ${activities[0].state || 'emoji'}` : activities[0].name : 'Nothing', globalActivity: user.lastMessage ? user.lastMessage.createdAt.toDateString() : 'N/A' }) }; if(badges.length > 0) { userField.value += `\n${message.format('C_USER_BADGES', { badges: badges.join(' ') })}`; } response.fields.push(userField); if (member) { const memberField = { name: message.format('C_USER_MEMBER_NAME'), value: message.format('C_USER_MEMBER', { nickname: member.nickname ? member.nickname : 'N/A', joined: member.joinedAt ? member.joinedAt.toDateString() : 'N/A', serverActivity: member.lastMessage ? member.lastMessage.createdAt.toDateString() : 'N/A' }) }; const roles = member.roles.cache.filter((r) => r.name !== '@everyone').sort((a, b) => b.rawPosition - a.rawPosition); const maxRoles = 30; if(roles.size > 0) { memberField.value += `\n${message.format('C_USER_MEMBER_ROLES', { roles: roles.size > maxRoles ? `${roles.slice(0, maxRoles).map((r) => `<@&${r.id}>`).join(' ')} \`...${maxRoles-roles.size} more roles\`` : roles.map((r) => `<@&${r.id}>`).join(' ') })}`; } response.fields.push(memberField); // let counter = 0; // if (roles.size) response.fields.push({ // name: message.format('C_USER_ROLES_TITLE'), // value: roles.map((r) => { // const str = `<@&${r.id}>`; // counter += str.length; // return counter <= 950 ? str : ''; // }).join(' ') // }); const highestColouredRole = member.roles.cache.filter((role) => role.color !== 0).sort((a, b) => b.rawPosition - a.rawPosition).first(); if (highestColouredRole) response.color = highestColouredRole.color; } } return message.embed(response); } } module.exports = UserCommand;