HiddenPhox/src/modules/utility.js

1314 lines
39 KiB
JavaScript

const Command = require("../lib/command.js");
const CATEGORY = "utility";
// {{{ imports
const sharp = require("sharp");
const {
formatTime,
hastebin,
lookupUser,
formatUsername,
safeString,
} = require("../lib/utils.js");
const {getNamesFromString} = require("../lib/unicode.js");
const GameData = require("../../data/games.json");
const EmojiData = require("../../data/emoji.json");
const EMOJI_NAMES = [];
for (const emoji of EmojiData) {
EMOJI_NAMES[emoji.char] = emoji.name.replace(/ /g, "_");
}
// }}}
// {{{ constants
const CDN = "https://cdn.discordapp.com/";
const ICON_BASE = CDN + "icons/";
const AVATAR_BASE = CDN + "avatars/";
const SPLASH_BASE = CDN + "splashes/";
const BANNER_BASE = CDN + "banners/";
const EMOTE_BASE = CDN + "emojis/";
const CHANNEL_ICON_BASE = CDN + "channel-icons/";
const DEFAULT_GROUP_DM_AVATARS = [
"/assets/ee9275c5a437f7dc7f9430ba95f12ebd.png",
"/assets/9baf45aac2a0ec2e2dab288333acb9d9.png",
"/assets/7ba11ffb1900fa2b088cb31324242047.png",
"/assets/f90fca70610c4898bc57b58bce92f587.png",
"/assets/e2779af34b8d9126b77420e5f09213ce.png",
"/assets/c6851bd0b03f1cca5a8c1e720ea6ea17.png",
"/assets/f7e38ac976a2a696161c923502a8345b.png",
"/assets/3cb840d03313467838d658bbec801fcd.png",
];
const CUSTOM_EMOTE_REGEX = /<(?:\u200b|&)?(a)?:(\w+):(\d+)>/;
const NOWPLAYING_BAR_LENGTH = 30;
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:1104972136730345552>",
idle: "<:web_idle:1104972138735218729>",
dnd: "<:web_dnd:1104972140685570150>",
},
embedded: {
online: "<:embedded_online:1104972131265167411>",
idle: "<:embedded_idle:1104972132687024189>",
dnd: "<:embedded_dnd:1104972134964543518>",
},
};
const PRESENCE_TYPES = [
"Playing",
"Streaming",
"Listening to",
"Watching",
"Custom Status",
"Competing in",
];
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",
"<Internal Application (Partner, etc) Flag>", // 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",
];
// https://discord-userdoccers.vercel.app/resources/guild#guild-features
const GUILD_FEATURES = {
ACTIVITIES_ALPHA: {icon: "\u{1f680}"},
ACTIVITIES_EMPLOYEE: {icon: "\u{1f680}"},
ACTIVITIES_INTERNAL_DEV: {icon: "\u{1f680}"},
ANIMATED_BANNER: {icon: "\u{1f39e}"},
ANIMATED_ICON: {icon: "\u{1f39e}"},
APPLICATION_COMMAND_PERMISSIONS_V2: {icon: "\u2699\ufe0f"},
AUTO_MODERATION: {icon: "\u{1f6e1}"},
AUTOMOD_TRIGGER_KEYWORD_FILTER: {icon: "\u{1f6e1}"},
AUTOMOD_TRIGGER_ML_SPAM_FILTER: {icon: "\u{1f6e1}"},
AUTOMOD_TRIGGER_SPAM_LINK_FILTER: {icon: "\u{1f6e1}"},
AUTOMOD_TRIGGER_USER_PROFILE: {icon: "\u{1faaa}"},
BANNER: {icon: "\u{1f5bc}"},
BFG: {icon: "\u{1f388}", name: "BFG"},
BOOSTING_TIERS_EXPERIMENT_MEDIUM_GUILD: {icon: "\u{1f48e}"},
BOOSTING_TIERS_EXPERIMENT_SMALL_GUILD: {icon: "\u{1f48e}"},
BOT_DEVELOPER_EARLY_ACCESS: {icon: "\u{1f9ea}"},
BURST_REACTIONS: {icon: "\u2728", name: "Super Reactions"},
CHANNEL_BANNER: {icon: "\u{1f5bc}"},
CHANNEL_ICON_EMOJIS_GENERATED: {icon: "\u{1f603}"},
CHANNEL_HIGHLIGHTS: {icon: "\u{1f5c3}"},
CHANNEL_HIGHLIGHTS_DISABLED: {icon: "\u{1f6ab}"},
CLYDE_DISABLED: {icon: "\u{1f6ab}"},
CLYDE_ENABLED: {icon: "\u{1f916}"},
CLYDE_EXPERIMENT_ENABLED: {icon: "\u{1f9ea}"},
COMMERCE: {icon: "\u{1f6cd}"},
COMMUNITY: {icon: "\u{1f3d8}"},
COMMUNITY_CANARY: {icon: "\u{1f9ea}"},
COMMUNITY_EXP_LARGE_GATED: {icon: "\u{1f3d8}"},
COMMUNITY_EXP_LARGE_UNGATED: {icon: "\u{1f3d8}"},
COMMUNITY_EXP_MEDIUM: {icon: "\u{1f3d8}"},
CREATOR_ACCEPTED_NEW_TERMS: {icon: "\u2611\ufe0f"},
CREATOR_MONETIZABLE: {icon: "\u{1f4b0}"},
CREATOR_MONETIZABLE_DISABLED: {icon: "\u{1f6ab}"},
CREATOR_MONETIZABLE_PENDING_NEW_OWNER_ONBOARDING: {icon: "\u{1f4b1}"},
CREATOR_MONETIZABLE_PROVISIONAL: {icon: "\u{1f4b0}"},
CREATOR_MONETIZABLE_RESTRICTED: {icon: "\u26d4"},
CREATOR_MONETIZABLE_WHITEGLOVE: {icon: "\u{1f9ea}"},
CREATOR_MONETIZATION_APPLICATION_ALLOWLIST: {icon: "\u{1f4dc}"},
CREATOR_STORE_PAGE: {icon: "\u{1f6d2}"},
DEVELOPER_SUPPORT_SERVER: {icon: "\u2754"},
DISCOVERABLE: {icon: "\u{1f9ed}"},
DISCOVERABLE_DISABLED: {icon: "\u{1f6ab}"},
ENABLED_DISCOVERABLE_BEFORE: {icon: "\u{1f9ed}"},
EXPOSED_TO_ACTIVITIES_WTP_EXPERIMENT: {icon: "\u{1f9ea}"},
EXPOSED_TO_BOOSTING_TIERS_EXPERIMENT: {icon: "\u{1f9ea}"},
FEATURABLE: {icon: "\u{1f9ed}"},
FORCE_RELAY: {icon: "\u{1f4fb}"},
GUESTS_ENABLED: {icon: "\u{1f465}"},
GUILD_AUTOMOD_DEFAULT_LIST: {icon: "\u{1f6e1}"},
GUILD_COMMUNICATION_DISABLED_GUILDS: {icon: "\u{1f6d1}"},
GUILD_HOME_DEPRECATION_OVERRIDE: {icon: "\u{1f3da}"},
GUILD_HOME_OVERRIDE: {icon: "\u{1f3e0}"},
GUILD_HOME_TEST: {icon: "\u{1f9ea}"},
GUILD_MEMBER_VERIFICATION_EXPERIMENT: {icon: "\u{1f9ea}"},
GUILD_ONBOARDING: {icon: "\u{1f5f3}"},
GUILD_ONBOARDING_ADMIN_ONLY: {icon: "\u{1f5f3}"},
GUILD_ONBOARDING_EVER_ENABLED: {icon: "\u{1f5f3}"},
GUILD_ONBOARDING_HAS_PROMPTS: {icon: "\u{1f5f3}"},
GUILD_PRODUCTS: {icon: "\u{1f6cd}"},
GUILD_ROLE_SUBSCRIPTIONS: {icon: "\u{1f4b3}"},
GUILD_ROLE_SUBSCRIPTION_PURCHASE_FEEDBACK_LOOP: {icon: "\u{1f4b3}"},
GUILD_ROLE_SUBSCRIPTION_TIER_TEMPLATE: {icon: "\u{1f4b3}"},
GUILD_ROLE_SUBSCRIPTION_TRIALS: {icon: "\u{1f4b3}"},
GUILD_SERVER_GUIDE: {icon: "\u{1f9ae}"},
GUILD_WEB_PAGE_VANITY_URL: {icon: "\u{1f4c4}"},
HAD_EARLY_ACTIVITIES_ACCESS: {icon: "\u{1f680}"},
HAS_DIRECTORY_ENTRY: {icon: "\u{1faa7}"},
HIDE_FROM_EXPERIMENT_UI: {icon: "\u{1f9ea}"},
HUB: {icon: "\u{1f3eb}"},
INCREASED_THREAD_LIMIT: {icon: "\u{1f9f5}"},
INTERNAL_EMPLOYEE_ONLY: {icon: "\u{1f6e0}"},
INVITE_SPLASH: {icon: "\u{1f5bc}"},
INVITES_DISABLED: {icon: "\u26d4"},
LINKED_TO_HUB: {icon: "\u{1f3eb}"},
LURKABLE: {icon: "\u{1f441}"},
MARKETPLACES_CONNECTION_ROLES: {icon: "\u{1f517}"},
MEDIA_CHANNEL_ALPHA: {icon: "\u{1f5bc}"},
MEMBER_LIST_DISABLED: {icon: "\u{1f6ab}"},
MEMBER_PROFILES: {icon: "\u{1faaa}"},
MEMBER_SAFETY_PAGE_ROLLOUT: {icon: "\u{1f6e1}"},
MEMBER_VERIFICATION_GATE_ENABLED: {icon: "\u{1f6e1}"},
MEMBER_VERIFICATION_MANUAL_APPROVAL: {icon: "\u2705"},
MOBILE_WEB_ROLE_SUBSCRIPTION_PURCHASE_PAGE: {icon: "\u{1f4b3}"},
MONETIZATION_ENABLED: {icon: "\u{1f4b0}"},
MORE_EMOJI: {icon: "\u{1f603}"},
MORE_STICKERS: {icon: "\u{1f5bc}"},
NEWS: {icon: "\u{1f4f0}"},
NEW_THREAD_PERMISSIONS: {icon: "\u{1f9f5}"},
NON_COMMUNITY_RAID_ALERTS: {icon: "\u{1f6a8}"},
PARTNERED: {icon: "\u267e\ufe0f"},
PREMIUM_TIER_3_OVERRIDE: {icon: "\u{1f48e}"},
PREVIEW_ENABLED: {icon: "\u{1f441}"},
PRIVATE_THREADS: {icon: "\u{1f9f5}"},
PRODUCTS_AVAILABLE_FOR_PURCHASE: {icon: "\u{1f6cd}"},
PUBLIC: {icon: "\u{1f9ed}"},
PUBLIC_DISABLED: {icon: "\u{1f6ab}"},
RAID_ALERTS_DISABLED: {icon: "\u{1f6ab}"},
RAID_ALERTS_ENABLED: {icon: "\u{1f6a8}"},
RELAY_ENABLED: {icon: "\u{1f4fb}"},
RESTRICT_SPAM_RISK_GUILDS: {icon: "\u{1f6d1}"},
ROLE_ICONS: {icon: "\u{1f3f7}"},
ROLE_SUBSCRIPTIONS_AVAILABLE_FOR_PURCHASE: {icon: "\u{1f4b3}"},
ROLE_SUBSCRIPTIONS_ENABLED: {icon: "\u{1f4b3}"},
ROLE_SUBSCRIPTIONS_ENABLED_FOR_PURCHASE: {icon: "\u{1f4b3}"},
SEVEN_DAY_THREAD_ARCHIVE: {icon: "\u{1f9f5}"},
SHARD: {icon: "\u{1f4a0}"},
SHARED_CANVAS_FRIENDS_AND_FAMILY_TEST: {icon: "\u{1f58c}"},
SOUNDBOARD: {icon: "\u{1f50a}"},
SUMMARIES_ENABLED: {icon: "\u{1f4da}"},
SUMMARIES_ENABLED_GA: {
icon: "\u{1f4da}",
name: "Summaries Enabled (General Access)",
},
SUMMARIES_DISABLED_BY_USER: {icon: "\u26d4"},
SUMMARIES_ENABLED_BY_USER: {icon: "\u{1f4da}"},
SUMMARIES_LONG_LOOKBACK: {icon: "\u{1f5c2}"},
STAFF_LEVEL_COLLABORATOR_REQUIRED: {icon: "\u{1f6e0}"},
STAFF_LEVEL_RESTRICTED_COLLABORATOR_REQUIRED: {icon: "\u{1f6e0}"},
TEXT_IN_STAGE_ENABLED: {icon: "\u{1f5e8}"},
TEXT_IN_VOICE_ENABLED: {icon: "\u{1f5e8}"},
THREADS_ENABLED_TESTING: {icon: "\u{1f9f5}"},
THREADS_ENABLED: {icon: "\u{1f9f5}"},
THREAD_DEFAULT_AUTO_ARCHIVE_DURATION: {icon: "\u{1f9f5}"},
THREADS_ONLY_CHANNEL: {icon: "\u{1f5e8}", name: "Forum Channels"},
THREE_DAY_THREAD_ARCHIVE: {icon: "\u{1f9f5}"},
TICKETED_EVENTS_ENABLED: {icon: "\u{1f39f}"},
TICKETING_ENABLED: {icon: "\u{1f39f}"},
VANITY_URL: {icon: "\u{1f517}"},
VERIFIED: {icon: "\u2b50"},
VIP_REGIONS: {icon: "\u{1f399}"},
VOICE_CHANNEL_EFFECTS: {icon: "\u2728"},
VOICE_IN_THREADS: {icon: "\u{1f399}"},
WELCOME_SCREEN_ENABLED: {icon: "\u{1f44b}"},
};
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;
// }}}
// {{{ commands
const avatar = new Command("avatar");
avatar.category = CATEGORY;
avatar.helpText = "Get avatar of a user";
avatar.usage = "<user>";
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 \`${formatUsername(member)}\``,
};
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 \`${formatUsername(msg.author)}\``,
};
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 = "<user>";
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 \`${formatUsername(userObj)}\``,
url,
image: {
url,
},
},
],
};
};
hf.registerCommand(banner);
const lookupinvite = new Command("lookupinvite");
lookupinvite.category = CATEGORY;
lookupinvite.helpText = "Lookup an invite";
lookupinvite.usage = "<invite code>";
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: [],
};
const expires = {
name: "Expires",
value:
invite.expires_at == null
? "Never"
: `<t:${Math.floor(new Date(invite.expires_at).getTime() / 1000)}>`,
inline: true,
};
const inviter = invite.inviter
? {
name: "Inviter",
value: `**${formatUsername(invite.inviter)}** (${invite.inviter.id})`,
inline: false,
}
: null;
const features = invite.guild.features.sort().map(
(feature) =>
(GUILD_FEATURES[feature]?.icon ?? "\u2753") +
" " +
(GUILD_FEATURES[feature]?.name ??
feature
.split("_")
.map((x) => x[0] + x.substring(1).toLowerCase())
.join(" "))
);
if (invite.type == 0) {
embed.fields.push(
...[
{
name: "Guild",
value: `**${invite.guild.name}** (${invite.guild.id})`,
inline: true,
},
{
name: "Channel",
value: `**${invite.channel.name}** (${invite.channel.id})`,
inline: true,
},
{
name: "Boosts",
value: invite.guild.premium_subscription_count ?? 0,
inline: true,
},
expires,
{
name: "Member Count",
value: `<:online:1152111668856361010>${invite.approximate_presence_count} online\t\t<:offline:1152111682886316042>${invite.approximate_member_count} members`,
inline: false,
},
inviter,
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:
features.length > 0
? features.slice(0, Math.ceil(features.length / 2)).join("\n")
: "None",
inline: true,
},
features.length > 1
? {
name: "\u200b",
value: features
.slice(Math.ceil(features.length / 2), features.length)
.join("\n"),
inline: true,
}
: null,
].filter((x) => !!x)
);
embed.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.guild &&
(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`,
};
}
} else if (invite.type == 1) {
embed.title += " (Group DM)";
embed.fields.push(
...[
{
name: "Channel",
value: `**${
invite.channel.name ??
invite.channel.recipients
.map((member) => member.username)
.join(", ")
}** (${invite.channel.id})`,
inline: false,
},
{
name: "Member Count",
value: `<:offline:1152111682886316042>${invite.approximate_member_count} members`,
inline: true,
},
expires,
invite.channel.name != null && {
name: "Recipients",
value: invite.channel.recipients
.map((member) => member.username)
.join(", "),
inline: false,
},
inviter,
].filter((x) => !!x)
);
const groupIcon = invite.channel.icon
? `${CHANNEL_ICON_BASE}${invite.channel.id}/${invite.channel.icon}.${
invite.channel.icon.startsWith("a_")
? "gif?size=1024&_=.gif"
: "png?size=1024"
}`
: "https://discord.com" +
DEFAULT_GROUP_DM_AVATARS[
(Math.floor(Number(invite.channel.id) / Math.pow(2, 22)) +
1420070400000) %
DEFAULT_GROUP_DM_AVATARS.length
];
embed.thumbnail = {
url: groupIcon,
};
embed.fields.push({
name: "\u200b",
value: `[Icon](${groupIcon})`,
inline: false,
});
} else if (invite.type == 2) {
embed.title += " (Friend)";
embed.fields.push(expires, inviter);
const avatarURL =
invite.inviter?.avatar &&
`${AVATAR_BASE}${invite.inviter.id}/${invite.inviter.avatar}.${
invite.inviter.avatar.startsWith("a_")
? "gif?size=1024&_=.gif"
: "png?size=1024"
}`;
if (avatarURL) {
embed.thumbnail = {
url: avatarURL,
};
embed.fields.push({
name: "\u200b",
value: `[Avatar](${avatarURL})`,
inline: false,
});
}
} else {
return `Unhandled invite type: \`${invite.type}\``;
}
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 <t:${Math.floor(
timestamp / 1000
)}:F>`;
} else {
return "Argument provided is not a number.";
}
};
hf.registerCommand(snowflake);
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] || "<Undocumented 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, list}) {
const num = Number(numOrMention);
if (list) {
let allFlags = 0n;
for (const index in USER_FLAGS) {
if (USER_FLAGS[index] == undefined) continue;
allFlags += 1n << BigInt(index);
}
return `All flags:\n\`\`\`${flagFromInt(allFlags)}\`\`\``;
} else 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 `\`${formatUsername(user)}\`'s public flags:\n\`\`\`${flagFromInt(
user.publicFlags
)}\`\`\``;
}
} else if (!isNaN(num)) {
return `\`\`\`\n${flagFromInt(num)}\`\`\``;
} else {
return `\`${formatUsername(
msg.author
)}\`'s public flags:\n\`\`\`${flagFromInt(msg.author.publicFlags)}\`\`\``;
}
};
hf.registerCommand(flagdump);
const jumbo = new Command("jumbo");
jumbo.category = CATEGORY;
jumbo.helpText = "Gets the raw image of an emoji.";
jumbo.usage = "<emoji>";
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 = EMOJI_NAMES[line]
? `\\:${EMOJI_NAMES[line]}\\:`
: await getNamesFromString(line).then((name) =>
name.map((x) => x[1]).join(", ")
);
const emojiFound = await fetch(url, {method: "HEAD"}).then((res) => res.ok);
if (emojiFound) {
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]} - <http://www.fileformat.info/info/unicode/char/${code}>`
)
.join("\n");
if (lines.length > 2000) {
return "Output too long: " + (await hastebin(lines));
} else {
return lines;
}
};
hf.registerCommand(charinfo);
const presence = new Command("presence");
presence.category = CATEGORY;
presence.helpText = "Get presences of a user.";
presence.usage = "<user>";
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 `**${formatUsername(target)}** is offline.`;
const icons = [];
for (const platform of Object.keys(target.clientStatus)) {
const status = target.clientStatus[platform];
if (status == "offline") continue;
icons.push(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) {
let details = activity.details;
if (activity.name == "Spotify" && activity.sync_id) {
details = `[${details}](https://open.spotify.com/track/${activity.sync_id})`;
}
descLines.push(`**${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) {
let stateLine = activity.state;
if (activity.party?.size) {
stateLine += ` (${activity.party.size[0]} of ${activity.party.size[1]})`;
}
descLines.push(stateLine);
}
}
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 if (
activity.timestamps.start != null &&
activity.timestamps.end != null
) {
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 = position >= length ? 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 **${formatUsername(target)}**: ${icons.join(" ")}`,
embeds,
files,
};
} else {
return ":warning: Could not get user???";
}
};
hf.registerCommand(presence);
const POMELO_REGEX = /^[a-z0-9._]{1,32}$/;
const pomelo = new Command("pomelo");
pomelo.category = CATEGORY;
pomelo.helpText = "Check to see if a username is taken or not";
pomelo.usage = "[username] <...username>";
pomelo.callback = async function (msg, line) {
if (!line || line === "") return "Arguments required.";
const usernames = line.toLowerCase().split(" ");
if (usernames.length == 1) {
const name = usernames[0];
if (name.length > 32 || !POMELO_REGEX.test(name))
return {reaction: "\u{1f6ab}"};
const res = await hf.bot.requestHandler.request(
"POST",
"/unique-username/username-attempt-unauthed",
false,
{username: name}
);
return {reaction: res.taken ? "\u274c" : "\u2705"};
} else {
const lines = [];
for (const name of usernames) {
if (name.length > 32 || !POMELO_REGEX.test(name)) {
lines.push(`\u{1f6ab} \`${name}\``);
} else {
try {
const res = await hf.bot.requestHandler.request(
"POST",
"/unique-username/username-attempt-unauthed",
false,
{username: name}
);
lines.push(`${res.taken ? "\u274c" : "\u2705"} \`${name}\``);
} catch {
lines.push(`\u26a0\ufe0f \`${name}\``);
}
}
}
return lines.join("\n");
}
};
hf.registerCommand(pomelo);
// }}}