From f30b3d012eee085141eaeb990599470a17c7f513 Mon Sep 17 00:00:00 2001 From: Cynthia Foxwell Date: Sun, 8 Oct 2023 15:52:34 -0600 Subject: [PATCH] utility: add guildinfo --- src/modules/utility.js | 355 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 349 insertions(+), 6 deletions(-) diff --git a/src/modules/utility.js b/src/modules/utility.js index 3aeb4cc..fc6e978 100644 --- a/src/modules/utility.js +++ b/src/modules/utility.js @@ -4,6 +4,7 @@ const CATEGORY = "utility"; // {{{ imports const sharp = require("sharp"); +const {Constants, VoiceChannel} = require("@projectdysnomia/dysnomia"); const { formatTime, @@ -36,6 +37,7 @@ const EMOTE_BASE = CDN + "emojis/"; const CHANNEL_ICON_BASE = CDN + "channel-icons/"; const APP_ICON_BASE = CDN + "app-icons/"; const APP_ASSET_BASE = CDN + "app-assets/"; +const DISCOVERY_SPLASH_BASE = CDN + "discovery-splashes/"; const DEFAULT_GROUP_DM_AVATARS = [ "/assets/ee9275c5a437f7dc7f9430ba95f12ebd.png", @@ -321,6 +323,30 @@ const GUILD_FEATURES = { WELCOME_SCREEN_ENABLED: {icon: "\u{1f44b}"}, }; +const GUILD_VERIFICATION_LEVELS = [ + "None", + "Low", + "Medium", + "(╯°□°)╯︵ ┻━┻ (High)", + "┻━┻ ミヽ(ಠ益ಠ)ノ彡┻━┻ (Very High/Phone)", +]; +const GUILD_CONTENT_FILTER = [ + "Disabled", + "Members without roles", + "All members", +]; + +const CHANNEL_TYPE_NAMES = { + 0: "text", + 2: "voice", + 4: "category", + 5: "announcement", + 13: "stage", + 14: "hub directory", + 15: "forum", + 16: "media", +}; + const EMOJI_SETS = { blobs: { prefix: @@ -589,7 +615,7 @@ banner.callback = async function (msg, line, [user], {server, guild}) { 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" + guild.banner.startsWith("a_") ? "gif?size=4096&_=.gif" : "png?size=4096" }`; return { embeds: [ @@ -646,6 +672,8 @@ lookupinvite.category = CATEGORY; lookupinvite.helpText = "Lookup an invite"; lookupinvite.usage = ""; lookupinvite.addAlias("linvite"); +lookupinvite.addAlias("iinfo"); +lookupinvite.addAlias("ii"); lookupinvite.callback = async function (msg, line) { if (!line || line == "") { return "No arguments passed."; @@ -756,7 +784,7 @@ lookupinvite.callback = async function (msg, line) { inline: false, }, { - name: "Features", + name: `Features (${features.length})`, value: features.length > 0 ? features.slice(0, Math.ceil(features.length / 2)).join("\n") @@ -1659,16 +1687,34 @@ appinfo.callback = async function (msg, line) { }](${APP_ASSET_BASE}${app.id}/${asset.id}.png)` ); - const left = + let left = "- " + mappedAssets.slice(0, Math.ceil(mappedAssets.length / 2)).join("\n- "); - const right = + let right = "- " + mappedAssets .slice(Math.ceil(mappedAssets.length / 2), mappedAssets.length) .join("\n- "); - if (left.length < 1024 && right.length < 1024) { + if (left.length > 1024 || right.length > 1024) { + const linklessAssets = assets.map((asset) => + asset.name.length > 32 + ? asset.name.substring(0, 32) + "\u2026" + : asset.name + ); + left = + "- " + + linklessAssets + .slice(0, Math.ceil(linklessAssets.length / 2)) + .join("\n- "); + right = + "- " + + linklessAssets + .slice(Math.ceil(linklessAssets.length / 2), linklessAssets.length) + .join("\n- "); + } + + if (left.length <= 1024 && right.length <= 1024) { embed.fields.push({ name: `Assets (${assets.length})`, value: left, @@ -1688,7 +1734,7 @@ appinfo.callback = async function (msg, line) { : asset.name ) .join(", "); - if (assetList.length < 1024) { + if (assetList.length <= 1024) { embed.fields.push({ name: `Assets (${assets.length})`, value: assetList, @@ -1715,4 +1761,301 @@ appinfo.callback = async function (msg, line) { }; hf.registerCommand(appinfo); +const guildinfo = new Command("guildinfo"); +guildinfo.category = CATEGORY; +guildinfo.helpText = "Get information on a guild"; +guildinfo.usage = ""; +guildinfo.addAlias("ginfo"); +guildinfo.addAlias("gi"); +guildinfo.addAlias("serverinfo"); +guildinfo.addAlias("sinfo"); +guildinfo.addAlias("si"); +guildinfo.callback = async function (msg, line) { + let _guild; + if (!line || line == "") { + if (!msg.guildID) return "Not in a guild."; + _guild = {source: "local", data: msg.channel.guild}; + } else { + if (!SNOWFLAKE_REGEX.test(line)) return "Not a snowflake."; + _guild = getGuild(line); + } + + const guild = _guild.data; + switch (_guild.source) { + case "local": { + const roles = Array.from(guild.roles.values()); + const defaultRole = roles.find((role) => role.name == "@everyone"); + + const channelTypeCounts = {}; + let nsfwChannels = 0; + let hiddenChannels = 0; + for (const channel of guild.channels.values()) { + if (!channelTypeCounts[channel.type]) + channelTypeCounts[channel.type] = 0; + channelTypeCounts[channel.type]++; + + if (channel.nsfw) nsfwChannels++; + + const defaultPermissions = channel.permissionOverwrites.get( + defaultRole.id + ); + if ( + defaultPermissions && + (channel instanceof VoiceChannel + ? !defaultPermissions.has(Constants.Permissions.voiceConnect) + : !defaultPermissions.has(Constants.Permissions.viewChannel)) + ) { + hiddenChannels++; + } + } + + const embed = { + title: guild.name, + description: guild.description ?? "*No description.*", + fields: [ + { + name: "Created", + value: ``, + inline: true, + }, + { + name: "Max Members", + value: guild.maxMembers, + inline: true, + }, + { + name: "Max Video Channel Users", + value: `Normal: ${guild.maxVideoChannelUsers}\nStage: ${guild.maxStageVideoChannelUsers}`, + inline: true, + }, + { + name: "Verification Level", + value: GUILD_VERIFICATION_LEVELS[guild.verificationLevel], + inline: true, + }, + { + name: "Explicit Content Filter Level", + value: GUILD_CONTENT_FILTER[guild.explicitContentFilter], + inline: true, + }, + { + name: "Moderation 2FA", + value: guild.mfaLevel == 0 ? "Off" : "On", + inline: true, + }, + { + name: "Boost Status", + value: `**Level ${guild.premiumTier}**, ${guild.premiumSubscriptionCount} Boosts`, + inline: true, + }, + { + name: "Locale", + value: guild.preferredLocale, + inline: true, + }, + { + name: "Default Notifications", + value: + guild.defaultNotifications == 0 + ? "All Messages" + : "Only Mentions", + inline: true, + }, + { + name: `Channels (${guild.channels.size})`, + value: + Object.entries(channelTypeCounts) + .map(([type, count]) => `${count} ${CHANNEL_TYPE_NAMES[type]}`) + .join(", ") + + `\n\n${nsfwChannels} age restricted, ${hiddenChannels} hidden`, + inline: true, + }, + { + name: `Roles (${guild.roles.size})`, + value: `${roles.filter((role) => role.managed).length} managed, ${ + roles.filter((role) => role.tags?.guild_connections).length + } linked, ${ + roles.filter((role) => role.tags?.integration_id != null).length + } integration`, + inline: true, + }, + { + name: `Emotes (${guild.emojis.length})`, + value: `${ + guild.emojis.filter((e) => e.animated).length + } animated, ${ + guild.emojis.filter((e) => e.managed).length + } managed\n${ + guild.emojis.filter((e) => !e.available).length + } unavailable`, + inline: true, + }, + { + name: `Stickers (${guild.stickers.length})`, + value: `${ + guild.stickers.filter((s) => s.format_type == 1).length + } PNG, ${ + guild.stickers.filter((s) => s.format_type == 2).length + } APNG, ${ + guild.stickers.filter((s) => s.format_type == 4).length + } GIF, ${ + guild.stickers.filter((s) => s.format_type == 3).length + } Lottie\n${ + guild.stickers.filter((s) => !s.available).length + } unavailable`, + inline: true, + }, + ], + }; + + if (guild.icon) { + embed.thumbnail = { + url: `${ICON_BASE}${guild.id}/${guild.icon}.${ + guild.icon.startsWith("a_") + ? "gif?size=1024&_=.gif" + : "png?size=1024" + }`, + }; + } + + if (guild.ownerID) { + embed.fields.push({ + name: "Owner", + value: `<@${guild.ownerID}>`, + inline: true, + }); + } + + if (guild.vanityURL) { + embed.fields.push({ + name: "Vanity URL", + value: `https://discord.gg/${guild.vanityURL}`, + inline: true, + }); + } + + if (guild.systemChannelID) { + embed.fields.push({ + name: "System Messages Channel", + value: `#${guild.channels.get(guild.systemChannelID).name} (\`${ + guild.systemChannelID + }\`)`, + inline: true, + }); + } + if (guild.rulesChannelID) { + embed.fields.push({ + name: "Rules Channel", + value: `#${guild.channels.get(guild.rulesChannelID).name} (\`${ + guild.rulesChannelID + }\`)`, + inline: true, + }); + } + if (guild.publicUpdatesChannelID) { + embed.fields.push({ + name: "Community Updates Channel", + value: `#${ + guild.channels.get(guild.publicUpdatesChannelID).name + } (\`${guild.publicUpdatesChannelID}\`)`, + inline: true, + }); + } + if (guild.safetyAlertsChannelID) { + embed.fields.push({ + name: "Safety Alerts Channel", + value: `#${guild.channels.get(guild.safetyAlertsChannelID).name} (\`${ + guild.safetyAlertsChannelID + }\`)`, + inline: true, + }); + } + + const members = Array.from(guild.members.values()); + const online = members.filter( + (member) => member.status != "offline" + ).length; + const bots = members.filter((member) => member.bot); + const verfifiedBots = members.filter( + (member) => member.bot && (member.user.flags & 65536) != 0 + ); + embed.fields.push({ + name: "Member Count", + value: `<:online:1152111668856361010>${online} online\t\t<:offline:1152111682886316042>${guild.memberCount} members\n<:boat:546212361472835584> ${bots}, \u2713 ${verfifiedBots}`, + inline: false, + }); + + const features = 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(" ")) + ); + + embed.fields.push({ + name: `Features (${features.length})`, + value: + features.length > 0 + ? features.slice(0, Math.ceil(features.length / 2)).join("\n") + : "None", + inline: true, + }); + if (features.length > 1) + embed.fields.push({ + name: "\u200b", + value: features + .slice(Math.ceil(features.length / 2), features.length) + .join("\n"), + inline: true, + }); + + const images = []; + if (guild.icon) { + images.push(`[Icon](${embed.thumbnail.url})`); + } + if (guild.banner) { + images.push( + `[Banner](${BANNER_BASE}${guild.id}/${guild.banner}.png?size=4096)` + ); + } + if (guild.splash) { + images.push( + `[Invite Splash](${SPLASH_BASE}${guild.id}/${guild.splash}.png?size=4096)` + ); + } + if (guild.discoverySplash) { + images.push( + `[Discovery Splash](${DISCOVERY_SPLASH_BASE}${guild.id}/${guild.discoverySplash}.png?size=4096)` + ); + } + + if (images.length > 0) { + embed.fields.push({ + name: "\u200b", + value: images.join(" | "), + inline: false, + }); + } + + return embed; + } + case "preview": { + return "TODO: guild from preview"; + } + case "discovery": { + return "TODO: guild from discovery"; + } + case "widget": { + return "TODO: guild from widget"; + } + default: + return "Guild not found."; + } +}; +hf.registerCommand(guildinfo); + // }}}