const Command = require("../lib/command.js"); const CATEGORY = "utility"; const ICON_BASE = "https://cdn.discordapp.com/icons/"; const AVATAR_BASE = "https://cdn.discordapp.com/avatars/"; const SPLASH_BASE = "https://cdn.discordapp.com/splashes/"; const BANNER_BASE = "https://cdn.discordapp.com/banners/"; const EMOTE_BASE = "https://cdn.discordapp.com/emojis/"; const STATUS_ICONS = { online: "<:online:493173082421461002>", idle: "<:idle:493173082006093836>", dnd: "<:dnd:493173082261815307>", offline: "<:offline:493173082253426688>", }; const EMOJI_SETS = { blobs: { prefix: "https://cdn.jsdelivr.net/gh/googlefonts/noto-emoji@e456654119cc3a5f9bebb7bbd00512456f983d2d/svg/emoji_u", sep: "_", suffix: ".svg", }, noto: { prefix: "gitcdn.xyz/repo/googlefonts/noto-emoji/master/svg/emoji_u", sep: "_", suffix: ".svg", }, twemoji: { prefix: "https://twemoji.maxcdn.com/v/latest/svg/", sep: "-", suffix: ".svg", }, mustd: { prefix: "https://cdn.jsdelivr.net/gh/Mstrodl/mutant-standard-mirror@0435227d9d8c0d6a346c8ae4c12b08a5cdc37041/emoji/", sep: "-", suffix: ".svg", }, apple: { prefix: "https://intrnl.github.io/assetsEmoji/AppleColor/emoji_u", sep: "_", suffix: ".png", }, facebook: { prefix: "https://intrnl.github.io/assetsEmoji/facebook/emoji_u", sep: "_", suffix: ".png", }, }; EMOJI_SETS["noto-old"] = EMOJI_SETS.blobs; EMOJI_SETS.mutant = EMOJI_SETS.mustd; EMOJI_SETS.mutstd = EMOJI_SETS.mustd; EMOJI_SETS.ms = EMOJI_SETS.mustd; EMOJI_SETS.twitter = EMOJI_SETS.twemoji; EMOJI_SETS.fb = EMOJI_SETS.facebook; const CUSTOM_EMOTE_REGEX = /<(?:\u200b|&)?(a)?:(\w+):(\d+)>/; const fetch = require("node-fetch"); const sharp = require("sharp"); const {lookupUser} = require("../lib/utils.js"); const {getNamesFromString} = require("../lib/unicode.js"); const avatar = new Command("avatar"); avatar.category = CATEGORY; avatar.helpText = "Get avatar of a user"; avatar.usage = ""; avatar.callback = async function (msg, line) { if (line == "--server" || line == "--guild") { if (!msg.guildID) { return "`--server/--guild` can only be used within guilds."; } else { const guild = msg.channel.guild || hf.bot.guilds.get(msg.guildID); const url = `${ICON_BASE}${guild.id}/${guild.icon}.${ guild.icon.startsWith("a_") ? "gif?size=1024&_=.gif" : "png?size=1024" }`; return { embeds: [ { title: "Server Icon", url, image: { url, }, }, ], }; } } else if (line) { const user = await lookupUser(msg, line); if ( user == "No results" || user == "Canceled" || user == "Request timed out" ) { return user; } else { let member = user; const guild = msg.channel.guild || hf.bot.guilds.get(msg.guildID); if (guild) { if (guild.members.has(user.id)) { member = guild.members.get(user.id); } else { const fetched = await guild.fetchMembers({ userIDs: [user.id], }); member = fetched[0]; } } const avatar = member.avatar || member.user.avatar; const url = guild && member.avatar ? `https://cdn.discordapp.com/guilds/${guild.id}/users/${ member.id }/avatars/${member.avatar}.${ member.avatar.startsWith("a_") ? "gif?size=1024&_=.gif" : "png?size=1024" }` : `${AVATAR_BASE}${member.id}/${avatar}.${ avatar.startsWith("a_") ? "gif?size=1024&_=.gif" : "png?size=1024" }`; return { embeds: [ { title: `Avatar for \`${member.username}#${member.discriminator}\``, url, image: { url, }, }, ], }; } } else { const guild = msg.channel.guild || hf.bot.guilds.get(msg.guildID); const avatar = msg.member.avatar || msg.author.avatar; const url = msg.member.avatar ? `https://cdn.discordapp.com/guilds/${guild.id}/users/${ msg.member.id }/avatars/${msg.member.avatar}.${ msg.member.avatar.startsWith("a_") ? "gif?size=1024&_=.gif" : "png?size=1024" }` : `${AVATAR_BASE}${msg.author.id}/${avatar}.${ avatar.startsWith("a_") ? "gif?size=1024&_=.gif" : "png?size=1024" }`; return { embeds: [ { title: `Avatar for \`${msg.author.username}#${msg.author.discriminator}\``, url, image: { url, }, }, ], }; } }; hf.registerCommand(avatar); const banner = new Command("banner"); banner.category = CATEGORY; banner.helpText = "Get banner of a user"; banner.usage = ""; banner.callback = async function (msg, line) { let id = msg.author.id; if (line == "--server" || line == "--guild") { if (!msg.guildID) { return "`--server/--guild` can only be used within guilds."; } else { const guild = msg.channel.guild || hf.bot.guilds.get(msg.guildID); if (!guild.banner) return "This guild does not have a banner."; const url = `${BANNER_BASE}${guild.id}/${guild.banner}.${ guild.banner.startsWith("a_") ? "gif?size=1024&_=.gif" : "png?size=1024" }`; return { embeds: [ { title: "Server Banner", url, image: { url, }, }, ], }; } } else if (line) { const lookup = await lookupUser(msg, line); if ( lookup == "No results" || lookup == "Canceled" || lookup == "Request timed out" ) { return lookup; } else { id = lookup.id; } } const user = await hf.bot.requestHandler.request("GET", "/users/" + id, true); if (!user.banner) return "This user does not have a banner."; const url = `${BANNER_BASE}${user.id}/${user.banner}.${ user.banner.startsWith("a_") ? "gif?size=1024&_=.gif" : "png?size=1024" }`; return { embeds: [ { title: `Banner for \`${user.username}#${user.discriminator}\``, url, image: { url, }, }, ], }; }; hf.registerCommand(banner); const lookupinvite = new Command("lookupinvite"); lookupinvite.category = CATEGORY; lookupinvite.helpText = "Lookup an invite"; lookupinvite.usage = ""; lookupinvite.addAlias("linvite"); lookupinvite.callback = async function (msg, line) { if (!line) { return "No arguments passed."; } line = line.replace(/(https?:\/\/)?discord\.gg\//, ""); const invite = await hf.bot.requestHandler.request( "GET", "/invites/" + line + "?with_counts=1" ); if (!invite) return ":warning: No data returned."; if (invite.message) { if (invite.message == "Unknown Invite") { return "Invite provided is not valid."; } else { return `:warning: Got error \`${invite.code}: "${invite.message}"\``; } } else { const embed = { title: `Invite Info: \`${invite.code}\``, description: invite.description, fields: [ { name: "Guild", value: `**${invite.guild.name}** (${invite.guild.id})`, inline: true, }, { name: "Channel", value: `**${invite.channel.name}** (${invite.channel.id})`, inline: true, }, { name: "Member Count", value: `${STATUS_ICONS.online}${invite.approximate_presence_count} online\t\t${STATUS_ICONS.offline}${invite.approximate_member_count} members`, inline: false, }, { name: "Features", value: invite.guild.features.length > 0 ? invite.guild.features .map((feature) => feature .split("_") .map((x) => x[0] + x.substring(1).toLowerCase()) .join(" ") ) .join(", ") : "None", inline: false, }, ], thumbnail: { url: invite.guild.icon && `${ICON_BASE}${invite.guild.id}/${invite.guild.icon}.${ invite.guild.icon.startsWith("a_") ? "gif?size=1024&_=.gif" : "png?size=1024" }`, }, }; if (invite.inviter) { embed.fields.push({ name: "Inviter", value: `**${invite.inviter.username}#${invite.inviter.discriminator}** (${invite.inviter.id})`, inline: true, }); } if (invite.guild.icon || invite.guild.splash || invite.guild.banner) { embed.fields.push({ name: "\u200b", value: `${ invite.guild.icon ? `[Icon](${ICON_BASE}${invite.guild.id}/${invite.guild.icon}.${ invite.guild.icon.startsWith("a_") ? "gif?size=1024" : "png?size=1024" })` : "" }${ invite.guild.splash ? `${invite.guild.icon ? " | " : ""}[Splash](${SPLASH_BASE}${ invite.guild.id }/${invite.guild.splash}.png?size=2048)` : "" }${ invite.guild.banner ? `${ invite.guild.icon || invite.guild.splash ? " | " : "" }[Banner](${BANNER_BASE}${invite.guild.id}/${ invite.guild.banner }.png?size=2048)` : "" }`, inline: false, }); } if (invite.guild.splash) { embed.image = { url: `${SPLASH_BASE}${invite.guild.id}/${invite.guild.splash}.png?size=256`, }; } return {embed}; } }; hf.registerCommand(lookupinvite); const snowflake = new Command("snowflake"); snowflake.category = CATEGORY; snowflake.helpText = "Converts a snowflake ID into readable time."; snowflake.usage = "<--twitter> [snowflake]"; snowflake.callback = function (msg, line) { let twitter = false; if (line.startsWith("--twitter")) { twitter = true; line.replace("--twitter ", ""); } const num = parseInt(line); if (!isNaN(num)) { let binary = num.toString(2); binary = "0".repeat(64 - binary.length) + binary; const timestamp = parseInt(binary.substr(0, 42), 2) + (twitter ? 1288834974657 : 1420070400000); return `The timestamp for \`${line}\` is ${new Date( timestamp ).toUTCString()}`; } else { return "Argument provided is not a number."; } }; hf.registerCommand(snowflake); const USER_FLAGS = [ "STAFF", "PARTNER", "HYPESQUAD", "BUG_HUNTER_LEVEL_1", "MFA_SMS", "PREMIUM_PROMO_DISMISSED", "HYPESQUAD_ONLINE_HOUSE_1", "HYPESQUAD_ONLINE_HOUSE_2", "HYPESQUAD_ONLINE_HOUSE_3", "PREMIUM_EARLY_SUPPORTER", "TEAM_PSEUDO_USER", "", "SYSTEM", "HAS_UNREAD_URGENT_MESSAGES", "BUG_HUNTER_LEVEL_2", "UNDERAGE_DELETED", "VERIFIED_BOT", "VERIFIED_DEVELOPER", "CERTIFIED_MODERATOR", "BOT_HTTP_INTERACTIONS", "SPAMMER", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, "", ]; function flagFromInt(int) { const bits = int.toString(2); const splitBits = bits.split("").reverse(); const reassignedBits = {}; for (const shift in splitBits) { reassignedBits[shift] = splitBits[shift]; } const flags = Object.keys(reassignedBits).filter( (bit) => reassignedBits[bit] == 1 ); let out = ""; for (const flag of flags) { out += (USER_FLAGS[flag] || "") + ` (1 << ${flag}, ${1n << BigInt(flag)})\n`; } return out; } const flagdump = new Command("flagdump"); flagdump.category = CATEGORY; flagdump.helpText = "Dumps Discord user flags."; flagdump.usage = "[flags or user mention]"; flagdump.callback = async function (msg, line) { const num = parseInt(line); if (/<@!?([0-9]*)>/.test(line)) { const id = line.match(/<@?!([0-9]*)>/)[1]; const guild = msg.channel.guild || hf.bot.guilds.get(msg.guildID); let user = guild && (await guild.fetchMembers({userIDs: [id]})); if (!user || !user[0]) { user = hf.bot.users.get(id); } else { user = user[0].user; } if (!user) { return "User not cached."; } else { return `\`${user.username}#${ user.discriminator }\`'s public flags:\n\`\`\`${flagFromInt(user.publicFlags)}\`\`\``; } } else if (!isNaN(num)) { return `\`\`\`\n${flagFromInt(num)}\`\`\``; } else { return `\`${msg.author.username}#${ msg.author.discriminator }\`'s public flags:\n\`\`\`${flagFromInt(msg.author.publicFlags)}\`\`\``; } }; hf.registerCommand(flagdump); const emojiNames = []; fetch("https://unpkg.com/emoji.json/emoji.json") .then((res) => res.json()) .then((body) => body.map( (emoji) => (emojiNames[emoji.char] = emoji.name.replace(/ /g, "_")) ) ); const jumbo = new Command("jumbo"); jumbo.category = CATEGORY; jumbo.helpText = "Gets the raw image of an emoji."; jumbo.usage = ""; jumbo.addAlias("e"); jumbo.addAlias("emote"); jumbo.addAlias("emoji"); jumbo.callback = async function (msg, line) { if (CUSTOM_EMOTE_REGEX.test(line)) { const [_, animatedFlag, name, id] = line.match(CUSTOM_EMOTE_REGEX); const animated = animatedFlag === "a"; return { embeds: [ { title: `:${name}: - \`${id}\``, url: `${EMOTE_BASE}${id}.${animated ? "gif" : "png"}?v=1`, image: { url: `${EMOTE_BASE}${id}.${animated ? "gif" : "png"}?v=1`, }, }, ], }; } else { let setName = "twemoji"; for (const set in EMOJI_SETS) { if (line.startsWith(`--${set} `)) { setName = set; line = line.replace(`--${set} `, ""); } } const set = EMOJI_SETS[setName]; const emoji = Array.from(line) .map((char) => char.codePointAt().toString(16)) .join(set.sep); const url = set.prefix + emoji + set.suffix; const name = emojiNames[line] ? `\\:${emojiNames[line]}\\:` : getNamesFromString(line)[0][1]; const statusCode = await fetch(url, {method: "HEAD"}).then( (res) => res.status ); if (statusCode !== 200) { return "Emoji not found. The emoji set chosen might not have this emote as an image."; } if (set.suffix == ".svg") { const svg = await fetch(url).then((res) => res.buffer()); const converted = await sharp(svg, {density: 2400}) .resize(1024) .toBuffer(); return { embeds: [ { title: `${name} (${emoji.toUpperCase().replace(/[-_]/g, ", ")})`, url, image: { url: "attachment://emoji.png", }, }, ], file: { file: converted, name: "emoji.png", }, }; } else { return { embeds: [ { title: `${name} (${emoji.toUpperCase().replace(/[-_]/g, ", ")})`, url, image: { url, }, }, ], }; } } }; hf.registerCommand(jumbo);