import { PluginData } from "knub"; import { UtilityPluginType } from "../types"; import { embedPadding, formatNumber, memoize, MINUTES, resolveUser, trimLines } from "../../../utils"; import { CategoryChannel, EmbedOptions, Guild, RESTChannelInvite, TextChannel, VoiceChannel } from "eris"; import moment from "moment-timezone"; import humanizeDuration from "humanize-duration"; export async function serverInfo(pluginData: PluginData, serverId: string): Promise { const thisServer = serverId === pluginData.guild.id ? pluginData.guild : null; const [restGuild, guildPreview] = await Promise.all([ thisServer ? memoize(() => pluginData.client.getRESTGuild(serverId), `getRESTGuild_${serverId}`, 10 * MINUTES) : null, memoize( () => pluginData.client.getGuildPreview(serverId).catch(() => null), `getGuildPreview_${serverId}`, 10 * MINUTES, ), ]); if (!restGuild && !guildPreview) { return null; } const features = (restGuild || guildPreview).features; if (!thisServer && !features.includes("DISCOVERABLE")) { return null; } const embed: EmbedOptions = { fields: [], color: parseInt("6b80cf", 16), }; embed.thumbnail = { url: (guildPreview || restGuild).iconURL }; // BASIC INFORMATION const createdAt = moment((guildPreview || restGuild).createdAt); const serverAge = humanizeDuration(moment().valueOf() - createdAt.valueOf(), { largest: 2, round: true, }); const basicInformation = []; basicInformation.push(`Created: **${serverAge} ago** (${createdAt.format("YYYY-MM-DD[T]HH:mm:ss")})`); if (thisServer) { const owner = await resolveUser(pluginData.client, thisServer.ownerID); const ownerName = `${owner.username}#${owner.discriminator}`; basicInformation.push(`Owner: **${ownerName}** (${thisServer.ownerID})`); basicInformation.push(`Voice region: **${thisServer.region}**`); } if (features.length > 0) { basicInformation.push(`Features: ${features.join(", ")}`); } embed.fields.push({ name: `Server information - ${(guildPreview || restGuild).name}`, value: basicInformation.join("\n") + embedPadding, }); // MEMBER COUNTS const totalMembers = guildPreview?.approximateMemberCount || restGuild?.approximateMemberCount || restGuild?.memberCount || thisServer?.memberCount || thisServer?.members.size || 0; let onlineMemberCount = guildPreview?.approximatePresenceCount || restGuild?.approximatePresenceCount; if (onlineMemberCount == null && restGuild?.vanityURL) { // For servers with a vanity URL, we can also use the numbers from the invite for online count const invite = (await memoize( () => pluginData.client.getInvite(restGuild.vanityURL, true), `getInvite_${restGuild.vanityURL}`, 10 * MINUTES, )) as RESTChannelInvite; if (invite) { onlineMemberCount = invite.presenceCount; } } if (!onlineMemberCount && thisServer) { onlineMemberCount = thisServer.members.filter(m => m.status !== "offline").length; // Extremely inaccurate fallback } const offlineMemberCount = totalMembers - onlineMemberCount; let memberCountTotalLines = `Total: **${formatNumber(totalMembers)}**`; if (restGuild?.maxMembers) { memberCountTotalLines += `\nMax: **${formatNumber(restGuild.maxMembers)}**`; } let memberCountOnlineLines = `Online: **${formatNumber(onlineMemberCount)}**`; if (restGuild?.maxPresences) { memberCountOnlineLines += `\nMax online: **${formatNumber(restGuild.maxPresences)}**`; } embed.fields.push({ name: "Members", inline: true, value: trimLines(` ${memberCountTotalLines} ${memberCountOnlineLines} Offline: **${formatNumber(offlineMemberCount)}** `), }); // CHANNEL COUNTS if (thisServer) { const totalChannels = thisServer.channels.size; const categories = thisServer.channels.filter(channel => channel instanceof CategoryChannel); const textChannels = thisServer.channels.filter(channel => channel instanceof TextChannel); const voiceChannels = thisServer.channels.filter(channel => channel instanceof VoiceChannel); embed.fields.push({ name: "Channels", inline: true, value: trimLines(` Total: **${totalChannels}** / 500 Categories: **${categories.length}** Text: **${textChannels.length}** Voice: **${voiceChannels.length}** `) + embedPadding, }); } // OTHER STATS const otherStats = []; if (thisServer) { otherStats.push(`Roles: **${thisServer.roles.size}** / 250`); } if (restGuild) { const maxEmojis = { 0: 50, 1: 100, 2: 150, 3: 250, }[restGuild.premiumTier] || 50; otherStats.push(`Emojis: **${restGuild.emojis.length}** / ${maxEmojis}`); } else { otherStats.push(`Emojis: **${guildPreview.emojis.length}**`); } if (thisServer) { otherStats.push(`Boosts: **${thisServer.premiumSubscriptionCount ?? 0}** (level ${thisServer.premiumTier})`); } embed.fields.push({ name: "Other stats", inline: true, value: otherStats.join("\n") + embedPadding, }); if (!thisServer) { embed.footer = { text: "⚠️ Only showing publicly available information for this server", }; } return embed; }