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: "https://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 sharp = require("sharp"); const { hastebin, lookupUser, formatTime, safeString, } = require("../lib/utils.js"); const {getNamesFromString} = require("../lib/unicode.js"); const GameData = require("../../data/games.json"); const avatar = new Command("avatar"); avatar.category = CATEGORY; avatar.helpText = "Get avatar of a user"; avatar.usage = ""; avatar.callback = async function (msg, line, [user], {server, guild}) { if (server || 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 (user) { const lookup = await lookupUser(msg, user); if ( lookup == "No results" || lookup == "Canceled" || lookup == "Request timed out" ) { return lookup; } else { let member = lookup; const guild = msg.channel.guild || hf.bot.guilds.get(msg.guildID); if (guild) { if (guild.members.has(lookup.id)) { member = guild.members.get(lookup.id); } else { const fetched = await guild.fetchMembers({ userIDs: [lookup.id], }); member = fetched[0]; } } const baseEmbed = { title: `Avatar for \`${member.username}#${member.discriminator}\``, }; const normalAvatar = member.user.avatar; const guildAvatar = member.avatar; const normalUrl = AVATAR_BASE + member.id + "/" + normalAvatar + "." + (normalAvatar.startsWith("a_") ? "gif?size=1024&_=.gif" : "png?size=1024"); const guildUrl = guildAvatar && "https://cdn.discordapp.com/guilds/" + guild.id + "/users/" + member.id + "/avatars/" + guildAvatar + "." + (guildAvatar.startsWith("a_") ? "gif?size=1024&_=.gif" : "png?size=1024"); baseEmbed.description = `[Normal avatar](${normalUrl})` + (guild && guildAvatar ? `\n[Guild avatar](${guildUrl})` : ""); baseEmbed.url = normalUrl; const guildEmbed = {...baseEmbed}; baseEmbed.image = {url: normalUrl}; guildEmbed.image = {url: guildUrl}; return { embeds: [baseEmbed, guildAvatar && guildEmbed].filter((x) => x != null), }; } } else { const guild = msg.channel.guild || hf.bot.guilds.get(msg.guildID); const baseEmbed = { title: `Avatar for \`${msg.author.username}#${msg.author.discriminator}\``, }; const normalAvatar = msg.author.avatar; const guildAvatar = msg.member?.avatar; const normalUrl = AVATAR_BASE + msg.author.id + "/" + normalAvatar + "." + (normalAvatar.startsWith("a_") ? "gif?size=1024&_=.gif" : "png?size=1024"); const guildUrl = guildAvatar && "https://cdn.discordapp.com/guilds/" + guild.id + "/users/" + msg.author.id + "/avatars/" + guildAvatar + "." + (guildAvatar.startsWith("a_") ? "gif?size=1024&_=.gif" : "png?size=1024"); baseEmbed.description = `[Normal avatar](${normalUrl})` + (guild && guildAvatar ? `\n[Guild avatar](${guildUrl})` : ""); baseEmbed.url = normalUrl; const guildEmbed = {...baseEmbed}; baseEmbed.image = {url: normalUrl}; guildEmbed.image = {url: guildUrl}; return { embeds: [baseEmbed, guildAvatar && guildEmbed].filter((x) => x != null), }; } }; 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, [user], {server, guild}) { let id = msg.author.id; if (server || 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 (user) { const lookup = await lookupUser(msg, user); if ( lookup == "No results" || lookup == "Canceled" || lookup == "Request timed out" ) { return lookup; } else { id = lookup.id; } } const userObj = await hf.bot.requestHandler.request( "GET", "/users/" + id, true ); if (!userObj.banner) return "This user does not have a banner."; const url = `${BANNER_BASE}${userObj.id}/${userObj.banner}.${ userObj.banner.startsWith("a_") ? "gif?size=1024&_=.gif" : "png?size=1024" }`; return { embeds: [ { title: `Banner for \`${userObj.username}#${userObj.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 || line == "") { return "No arguments passed."; } line = line.replace(/(https?:\/\/)?discord\.gg\//, ""); let bail = false; let error; let invite; try { invite = await hf.bot.requestHandler.request( "GET", `/invites/${line}?with_counts=true&with_expiration=true` ); } catch (err) { bail = true; error = err; } if (bail && error) { if (error.message.includes("Unknown Invite")) { return "Invite provided is not valid."; } else { return `:warning: Got error \`${safeString(error)}\``; } } 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: "\u200b", value: "\u200b", inline: true, }, { name: "Boosts", value: invite.guild.premium_subscription_count ?? 0, inline: true, }, { name: "Expires", value: invite.expires_at == null ? "Never" : ``, 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, }, invite.guild.welcome_screen && { name: "Welcome Screen", value: `"${ invite.guild.welcome_screen.description }"\n${invite.guild.welcome_screen.welcome_channels .map( (c) => `${ c.emoji_id ? `[:${c.emoji_name}:](${EMOTE_BASE}${c.emoji_id}.webp)` : c.emoji_name } ${c.description} \`(${c.channel_id})\`` ) .join("\n")}`, 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, }, ].filter((x) => !!x), 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 }.${ invite.guild.banner.startsWith("a_") ? "gif?size=1024" : "png?size=1024" })` : "" }`, 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, [snowflake], {twitter}) { const num = parseInt(snowflake); 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 \`${snowflake}\` is `; } 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", "", // leaked "SYSTEM", "HAS_UNREAD_URGENT_MESSAGES", "BUG_HUNTER_LEVEL_2", "UNDERAGE_DELETED", "VERIFIED_BOT", "VERIFIED_DEVELOPER", "CERTIFIED_MODERATOR", "BOT_HTTP_INTERACTIONS", "SPAMMER", "DISABLE_PREMIUM", "ACTIVE_DEVELOPER", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, "HIGH_GLOBAL_RATE_LIMIT", // start admin panel leak aug 2022 "DELETED", "DISABLED_SUSPICIOUS_ACTIVITY", "SELF_DELETED", "PREMIUM_DISCRIMINATOR", "USED_DESKTOP_CLIENT", "USED_WEB_CLIENT", "USED_MOBILE_CLIENT", "DISABLED", undefined, "VERIFIED_EMAIL", // end admin panel leak aug 2022 "QUARANTINED", undefined, undefined, undefined, undefined, undefined, "COLLABORATOR", "RESTRICTED_COLLABORATOR", ]; 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, [numOrMention], {id}) { const num = Number(numOrMention); if (/<@!?(\d+)>/.test(numOrMention) || !isNaN(id)) { const targetId = id || numOrMention.match(/<@!?(\d+)>/)?.[1]; if (!targetId) return "Got null ID."; const guild = msg.channel.guild || hf.bot.guilds.get(msg.guildID); let user = guild && (await guild.fetchMembers({userIDs: [targetId]})); 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]}\\:` : await getNamesFromString(line).then((name) => name.map((x) => x[1]).join(", ") ); 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.arrayBuffer()) .then((b) => Buffer.from(b)); 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); const charinfo = new Command("charinfo"); charinfo.category = CATEGORY; charinfo.helpText = "Get information about a set of characters."; charinfo.usage = "[characters]"; charinfo.addAlias("char"); charinfo.callback = async function (msg, line) { const names = await getNamesFromString(line); const chars = [...line]; const lines = names .map( ([code, name], index) => `\`\\u${code}\`: ${name} - ${chars[index]} - ` ) .join("\n"); if (lines.length > 2000) { return "Output too long: " + (await hastebin(lines)); } else { return lines; } }; hf.registerCommand(charinfo); const PRESENCE_ICONS = { desktop: { online: "<:desktop_online:1028887024670871552>", idle: "<:desktop_idle:1028887022938624033>", dnd: "<:desktop_dnd:1028887021848121364>", }, mobile: { online: "<:mobile_online:1028887017637036043>", idle: "<:mobile_idle:1028887019226669116>", dnd: "<:mobile_dnd:1028887020560449637>", }, web: { online: "<:web_online:1028887016353574962>", idle: "<:web_idle:1028887014579392592>", dnd: "<:web_dnd:1028887012855525486>", }, embedded: { online: "<:embedded_online:1028887010636726313>", idle: "<:embedded_idle:1028887009147760681>", dnd: "<:embedded_dnd:1028887008149516299>", }, }; const PRESENCE_TYPES = [ "Playing", "Streaming", "Listening to", "Watching", "", "Competing in", ]; const NOWPLAYING_BAR_LENGTH = 30; const presence = new Command("presence"); presence.category = CATEGORY; presence.helpText = "Get presences of a user."; presence.usage = ""; presence.addAlias("status"); presence.callback = async function (msg, line) { if (!msg.guildID) return "Can only be used in guilds."; let target; 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]; } target = member; } } } else { target = msg.member; } if (target) { if (!target.clientStatus) return `**${target.username}#${target.discriminator}** is offline.`; let icons = ""; for (const platform of Object.keys(target.clientStatus)) { const status = target.clientStatus[platform]; icons += (PRESENCE_ICONS[platform][status] ?? "") + " "; } const embeds = []; const files = []; for (const index in target.activities) { const activity = target.activities[index]; if (activity.type == 4) { const embed = {}; if (activity.emoji) { if (activity.emoji.id) { const url = `${EMOTE_BASE}${activity.emoji.id}.${ activity.emoji.animated ? "gif" : "png" }`; embed.author = { url, icon_url: url, name: activity.state ?? "\u200b", }; } else { embed.title = `${activity.emoji.name} ${activity.state ?? ""}`; } } else { embed.title = activity.state ?? ""; } embeds.push(embed); } else { const embed = { title: `${PRESENCE_TYPES[activity.type]} **${activity.name}**`, fields: [], }; const descLines = []; if (activity.type == 2) { if (activity.details) descLines.push(`**${activity.details}**`); if (activity.state) descLines.push(activity.state); if (activity.assets?.large_text) descLines.push(activity.assets.large_text); } else { if (activity.details) descLines.push(activity.details); if (activity.state) descLines.push(activity.state); } if (activity.timestamps) { if (activity.timestamps.start && !activity.timestamps.end) { descLines.push( formatTime(Date.now() - activity.timestamps.start) + " elapsed" ); } else if (!activity.timestamps.start && activity.timestamps.end) { descLines.push( formatTime(activity.timestamps.end - Date.now()) + " remaining" ); } else { const position = Date.now() - activity.timestamps.start; const length = activity.timestamps.end - activity.timestamps.start; const timeEnd = formatTime(length); const timePos = formatTime(position); const progress = activity.timestamps.start == activity.timestamps.end ? 1 : position / length; const barLength = Math.round(progress * NOWPLAYING_BAR_LENGTH); const bar = `\`[${"=".repeat(barLength)}${" ".repeat( NOWPLAYING_BAR_LENGTH - barLength )}]\``; const time = `\`${timePos}${" ".repeat( NOWPLAYING_BAR_LENGTH + 2 - timePos.length - timeEnd.length )}${timeEnd}\``; descLines.push(bar); descLines.push(time); } } if (activity.assets?.large_text && activity.type != 2) { embed.fields.push({ name: "Large Text", value: activity.assets.large_text, }); } if (activity.assets?.small_text) { embed.fields.push({ name: "Small Text", value: activity.assets.small_text, }); } embed.description = descLines.join("\n"); if (activity.assets) { if (activity.assets.large_image != null) { let largeUrl; if (activity.assets.large_image.startsWith("mp:")) { largeUrl = activity.assets.large_image.replace( "mp:", "https://media.discordapp.net/" ); } else if (activity.assets.large_image.startsWith("spotify:")) { largeUrl = activity.assets.large_image.replace( "spotify:", "https://i.scdn.co/image/" ); } else { largeUrl = `https://cdn.discordapp.com/app-assets/${activity.application_id}/${activity.assets.large_image}.png`; } let smallUrl; if (activity.assets.small_image != null) { if (activity.assets.small_image.startsWith("mp:")) { smallUrl = activity.assets.small_image.replace( "mp:", "https://media.discordapp.net/" ); } else { smallUrl = `https://cdn.discordapp.com/app-assets/${activity.application_id}/${activity.assets.small_image}.png`; } } const largeImage = await fetch(largeUrl) .then((res) => res.arrayBuffer()) .then((b) => Buffer.from(b)); const presenceImage = sharp(largeImage).resize(60, 60); if (smallUrl) { const smallImage = await fetch(smallUrl) .then((res) => res.arrayBuffer()) .then((b) => Buffer.from(b)); const smallImageBuffer = await sharp(smallImage) .resize(20, 20) .toBuffer(); presenceImage.composite([ { input: smallImageBuffer, gravity: "southeast", }, ]); } files.push({ contents: await presenceImage.toBuffer(), name: `${index}.png`, }); embed.thumbnail = { url: `attachment://${index}.png`, }; } else if ( !activity.assets.large_image && activity.assets.small_image != null ) { let smallUrl; if (activity.assets.small_image.startsWith("mp:")) { smallUrl = activity.assets.small_image.replace( "mp:", "https://media.discordapp.net/" ); } else { smallUrl = `https://cdn.discordapp.com/app-assets/${activity.application_id}/${activity.assets.small_image}.png`; } const smallImage = await fetch(smallUrl) .then((res) => res.arrayBuffer()) .then((b) => Buffer.from(b)); const presenceImage = await sharp(smallImage) .resize(60, 60) .toBuffer(); files.push({ contents: presenceImage, name: `${index}.png`, }); embed.thumbnail = { url: `attachment://${index}.png`, }; } } if ( activity.application_id && !activity.assets?.large_image && !activity.assets?.small_image ) { const game = GameData.find( (game) => game.id == activity.application_id ); if (game?.icon) { embed.thumbnail = { url: `https://cdn.discordapp.com/app-icons/${game.id}/${game.icon}.png?size=40&keep_aspect_ratio=false`, }; } } embeds.push(embed); } } return { content: `Presence for **${target.username}#${ target.discriminator }**: ${icons.trim()}`, embeds, files, }; } else { return ":warning: Could not get user???"; } }; hf.registerCommand(presence);