{"version":3,"file":"stats.mjs","names":[],"sources":["../../src/modules/stats.ts"],"sourcesContent":["import {\n  type ChatInputCommandInteraction,\n  type Client,\n  EmbedBuilder,\n  type Guild,\n  time,\n} from 'discord.js'\nimport prettyMilliseconds from 'pretty-ms'\nimport { type SleetContext, SleetSlashCommand } from 'sleetcord'\n\n/**\n * Get some stats about the bot, for now this includes:\n *   - Guild count\n *   - Members count\n *   - Users cached\n *   - Channels\n *   - Emojis cached\n *   - Sleet modules loaded\n *   - Uptime of the bot\n *   - Creation time of the bot\n */\nexport const stats: SleetSlashCommand = new SleetSlashCommand(\n  {\n    name: 'stats',\n    description: 'Get some stats about the bot',\n  },\n  {\n    run: runStats,\n  },\n)\n\n/** Get the stats and display them */\nasync function runStats(this: SleetContext, interaction: ChatInputCommandInteraction) {\n  const { client } = interaction\n\n  /** The helper funcs work for both sharded and unsharded bots */\n  const [guildCount, memberCount, userCount, channelCount, emojis] = await Promise.all([\n    getGuildCount(client),\n    getMemberCount(client),\n    getUserCount(client),\n    getChannelCount(client),\n    getEmojiCount(client),\n  ])\n\n  const modules = this.sleet.modules.size\n  const uptime = client.readyAt\n  const created = client.user.createdAt\n\n  const embed = new EmbedBuilder().addFields([\n    { name: 'Guilds:', value: guildCount.toLocaleString(), inline: true },\n    { name: 'Members:', value: memberCount.toLocaleString(), inline: true },\n    {\n      name: 'Users Cached:',\n      value: userCount.toLocaleString(),\n      inline: true,\n    },\n    { name: 'Channels:', value: channelCount.toLocaleString(), inline: true },\n    { name: 'Emojis Cached:', value: emojis.toLocaleString(), inline: true },\n    {\n      name: 'Modules Loaded:',\n      value: modules.toLocaleString(),\n      inline: true,\n    },\n    { name: 'Uptime:', value: createTimestamps(uptime), inline: true },\n    { name: 'Created:', value: createTimestamps(created), inline: true },\n  ])\n\n  await interaction.reply({ embeds: [embed] })\n}\n\n/**\n * Sum up an array of numbers\n * @param counts The numbers to sum\n * @returns The sum of all the numbers\n */\nfunction sum(counts: number[]): number {\n  return counts.reduce((acc, count) => acc + count, 0)\n}\n\n/** A function that takes in the current client as context, and then should return some number */\ntype GetClientCount = (client: Client) => number\n\n/**\n * A way to get the count of *something* from the client that works for both sharded and unsharded clients\n * @param client The client to get a count for\n * @param getClientCount A function that uses the client to get a count\n * @returns A sum of the counts from all clients if sharded, the count of the current client if not\n */\nasync function getCount(client: Client, getClientCount: GetClientCount): Promise<number> {\n  if (client.shard) {\n    return client.shard.broadcastEval(getClientCount).then(sum)\n  }\n\n  return getClientCount(client)\n}\n\nasync function getGuildCount(client: Client): Promise<number> {\n  return getCount(client, (c) => c.guilds.cache.size)\n}\n\nconst sumMembers = (acc: number, guild: Guild) => acc + guild.memberCount\nasync function getMemberCount(client: Client): Promise<number> {\n  return getCount(client, (c) => c.guilds.cache.reduce(sumMembers, 0))\n}\n\nasync function getUserCount(client: Client): Promise<number> {\n  return getCount(client, (c) => c.users.cache.size)\n}\n\nasync function getChannelCount(client: Client): Promise<number> {\n  return getCount(client, (c) => c.channels.cache.size)\n}\n\nasync function getEmojiCount(client: Client): Promise<number> {\n  return getCount(client, (c) => c.emojis.cache.size)\n}\n\n/**\n * Formats a date into a few timestamp formats for display\n * @param date The time to create a timestamp for\n * @returns An \"x since\" formatted string, absolute discord timestamp, relative discord timestamp\n */\nfunction createTimestamps(date: Date | null): string {\n  if (!date) return 'Never'\n\n  const formatted = prettyMilliseconds(Date.now() - date.getTime(), {\n    verbose: true,\n  })\n\n  return `${formatted}\\n${time(date)}\\n${time(date, 'R')}`\n}\n"],"mappings":";;;;;;;;;;;;;;;AAqBA,MAAa,QAA2B,IAAI,kBAC1C;CACE,MAAM;CACN,aAAa;CACd,EACD,EACE,KAAK,UACN,CACF;;AAGD,eAAe,SAA6B,aAA0C;CACpF,MAAM,EAAE,WAAW;;CAGnB,MAAM,CAAC,YAAY,aAAa,WAAW,cAAc,UAAU,MAAM,QAAQ,IAAI;EACnF,cAAc,OAAO;EACrB,eAAe,OAAO;EACtB,aAAa,OAAO;EACpB,gBAAgB,OAAO;EACvB,cAAc,OAAO;EACtB,CAAC;CAEF,MAAM,UAAU,KAAK,MAAM,QAAQ;CACnC,MAAM,SAAS,OAAO;CACtB,MAAM,UAAU,OAAO,KAAK;CAE5B,MAAM,QAAQ,IAAI,cAAc,CAAC,UAAU;EACzC;GAAE,MAAM;GAAW,OAAO,WAAW,gBAAgB;GAAE,QAAQ;GAAM;EACrE;GAAE,MAAM;GAAY,OAAO,YAAY,gBAAgB;GAAE,QAAQ;GAAM;EACvE;GACE,MAAM;GACN,OAAO,UAAU,gBAAgB;GACjC,QAAQ;GACT;EACD;GAAE,MAAM;GAAa,OAAO,aAAa,gBAAgB;GAAE,QAAQ;GAAM;EACzE;GAAE,MAAM;GAAkB,OAAO,OAAO,gBAAgB;GAAE,QAAQ;GAAM;EACxE;GACE,MAAM;GACN,OAAO,QAAQ,gBAAgB;GAC/B,QAAQ;GACT;EACD;GAAE,MAAM;GAAW,OAAO,iBAAiB,OAAO;GAAE,QAAQ;GAAM;EAClE;GAAE,MAAM;GAAY,OAAO,iBAAiB,QAAQ;GAAE,QAAQ;GAAM;EACrE,CAAC;AAEF,OAAM,YAAY,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC;;;;;;;AAQ9C,SAAS,IAAI,QAA0B;AACrC,QAAO,OAAO,QAAQ,KAAK,UAAU,MAAM,OAAO,EAAE;;;;;;;;AAYtD,eAAe,SAAS,QAAgB,gBAAiD;AACvF,KAAI,OAAO,MACT,QAAO,OAAO,MAAM,cAAc,eAAe,CAAC,KAAK,IAAI;AAG7D,QAAO,eAAe,OAAO;;AAG/B,eAAe,cAAc,QAAiC;AAC5D,QAAO,SAAS,SAAS,MAAM,EAAE,OAAO,MAAM,KAAK;;AAGrD,MAAM,cAAc,KAAa,UAAiB,MAAM,MAAM;AAC9D,eAAe,eAAe,QAAiC;AAC7D,QAAO,SAAS,SAAS,MAAM,EAAE,OAAO,MAAM,OAAO,YAAY,EAAE,CAAC;;AAGtE,eAAe,aAAa,QAAiC;AAC3D,QAAO,SAAS,SAAS,MAAM,EAAE,MAAM,MAAM,KAAK;;AAGpD,eAAe,gBAAgB,QAAiC;AAC9D,QAAO,SAAS,SAAS,MAAM,EAAE,SAAS,MAAM,KAAK;;AAGvD,eAAe,cAAc,QAAiC;AAC5D,QAAO,SAAS,SAAS,MAAM,EAAE,OAAO,MAAM,KAAK;;;;;;;AAQrD,SAAS,iBAAiB,MAA2B;AACnD,KAAI,CAAC,KAAM,QAAO;AAMlB,QAAO,GAJW,mBAAmB,KAAK,KAAK,GAAG,KAAK,SAAS,EAAE,EAChE,SAAS,MACV,CAAC,CAEkB,IAAI,KAAK,KAAK,CAAC,IAAI,KAAK,MAAM,IAAI"}