{"version":3,"file":"info.mjs","names":["discordJSVersion"],"sources":["../../src/modules/info.ts"],"sourcesContent":["import * as os from 'node:os'\n\nimport {\n  type ChatInputCommandInteraction,\n  type Client,\n  version as discordJSVersion,\n  EmbedBuilder,\n  type Guild,\n  type Invite,\n  Team,\n  User,\n} from 'discord.js'\nimport { formatUser, SleetSlashCommand } from 'sleetcord'\n\nimport { notNullish } from '../utils/functions.ts'\n\n/**\n * Get some info about the bot, currently includes:\n *   - Owner\n *   - Version (Node/d.js)\n *   - CPU Load Average\n *   - Memory Usage\n *   - Bot Guild\n *   - Approximate Guild Count\n */\nexport const info: SleetSlashCommand = new SleetSlashCommand(\n  {\n    name: 'info',\n    description: 'Get info about the bot',\n  },\n  {\n    run: runInfo,\n  },\n)\n\n/** os.loadavg() \"Returns an array containing the 1, 5, and 15 minute load averages.\" */\nconst cpuLoadIntervals = [1, 5, 15]\n\nlet CACHED_INVITE: Invite | null = null\n\nasync function runInfo(interaction: ChatInputCommandInteraction) {\n  const { client } = interaction\n\n  const embed = new EmbedBuilder()\n\n  const owner = formatOwner(client)\n  const versionInfo = `Node ${process.version}\\ndiscord.js v${discordJSVersion}`\n  const cpuString = os\n    .loadavg()\n    .map((v, i) => `${cpuLoadIntervals[i]}m: ${v.toFixed(2)}%`)\n    .join(', ')\n\n  const totalMem = os.totalmem()\n  const usedMem = os.totalmem() - os.freemem()\n  const usedMemPercent = ((usedMem / totalMem) * 100).toFixed(2)\n  const memoryString = `${formatBytes(usedMem)} / ${formatBytes(totalMem)} (${usedMemPercent}%)`\n\n  const approximateGuildCount =\n    client.application.approximateGuildCount?.toLocaleString() ?? 'Unknown'\n\n  const botGuild = client.application.guild\n\n  const botGuildInvite = botGuild ? await ensureInviteFor(botGuild, CACHED_INVITE) : null\n\n  if (CACHED_INVITE == null && botGuildInvite) {\n    CACHED_INVITE = botGuildInvite\n  }\n\n  const botGuildInfo =\n    botGuild === null\n      ? 'Unknown'\n      : `${botGuild.name} (${botGuild.id}) ${\n          botGuildInvite ? `[[Invite]](${botGuildInvite.url})` : ''\n        }`\n\n  embed.addFields([\n    { name: 'Owner', value: owner, inline: true },\n    { name: 'Using', value: versionInfo, inline: true },\n    { name: ' ', value: ' ' },\n    { name: 'CPU Load Average', value: cpuString, inline: true },\n    { name: 'Memory Usage', value: memoryString, inline: true },\n    { name: ' ', value: ' ' },\n    { name: 'Bot Guild', value: botGuildInfo, inline: true },\n    { name: 'Approximate Guilds', value: approximateGuildCount, inline: true },\n  ])\n\n  if (client.shard) {\n    embed.addFields([\n      {\n        name: 'Shard',\n        value: `IDs: ${client.shard.ids.join(', ')} (${client.shard.count} total)`,\n      },\n    ])\n  }\n\n  await interaction.reply({\n    embeds: [embed],\n  })\n}\n\nconst k = 1000\nconst sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']\n\n/**\n * Formats a number of bytes into a format like `512.00 MB`, using the \"best-fit\" unit size\n * @param bytes The bytes to format\n * @param decimals The number of decimals to show\n * @returns A string representation of the byte size, with the appropriate unit\n */\nfunction formatBytes(bytes: number, decimals = 2): string {\n  if (bytes === 0) return '0 B'\n  const i = Math.floor(Math.log(bytes) / Math.log(k))\n  return `${Number.parseFloat((bytes / k ** i).toFixed(decimals + 1))} ${sizes[i]}`\n}\n\n/**\n * Formats the owner details into a string, dealing with teams appropriately\n * @param interaction The client to pull information from\n * @returns A string representation of the owner details\n */\nfunction formatOwner(client: Client<true>): string {\n  const { owner } = client.application\n\n  if (owner instanceof User) {\n    return formatUser(owner)\n  }\n\n  if (owner instanceof Team) {\n    return `Team: ${owner.name} (Owned by ${\n      owner.owner ? formatUser(owner.owner.user) : '<Unknown>'\n    })`\n  }\n\n  return '<Unknown>'\n}\n\nasync function ensureInviteFor(guild: Guild, cachedInvite: Invite | null): Promise<Invite | null> {\n  if (cachedInvite === null) {\n    const channels = await guild.channels.fetch()\n    const firstChannel =\n      channels.find((c) => c !== null && c.id === guild.rulesChannelId) ??\n      channels\n        .filter(notNullish)\n        .sorted((a, b) => a.rawPosition - b.rawPosition)\n        .find((c) => 'createInvite' in c)\n\n    if (firstChannel === undefined) {\n      return null\n    }\n\n    if ('createInvite' in firstChannel) {\n      CACHED_INVITE = await firstChannel.createInvite({\n        maxAge: 0,\n        maxUses: 0,\n        temporary: false,\n        unique: false,\n      })\n\n      return CACHED_INVITE\n    }\n  }\n\n  return cachedInvite\n}\n"],"mappings":"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"}