UNPKG

@sern/cli

Version:

Official CLI for @sern/handler

221 lines (220 loc) 7.97 kB
import { create } from './chunk-PAIOQOOR.js'; import { mkdir, writeFile, readdir } from 'fs/promises'; import { resolve, basename, posix } from 'node:path'; import { pathExistsSync } from 'find-up'; import assert from 'assert'; import { once } from 'node:events'; import { cyanBright, redBright, greenBright } from 'colorette'; import { inspect } from 'node:util'; import ora from 'ora'; async function* readPaths(dir, shouldDebug) { const files = await readdir(dir, { withFileTypes: true }); for (const file of files) { const fullPath = posix.join(dir, file.name); if (file.isDirectory()) { if (!file.name.startsWith("!")) { yield* readPaths(fullPath); } } else if (!file.name.startsWith("!")) { yield "file:///" + resolve(fullPath); } } } var [{ config, preloads, commandDir }] = await once(process, "message"); var { paths } = config; for (const preload of preloads) { console.log("preloading: ", preload); await import("file:///" + resolve(preload)); } var commandsPath = commandDir ? resolve(commandDir) : resolve(paths.base, paths.commands); var filePaths = readPaths(commandsPath); var modules = []; var PUBLISHABLE = 14; for await (const absPath of filePaths) { let mod = await import(absPath); let commandModule = mod.default; let config2 = mod.config; if ("default" in commandModule) { commandModule = commandModule.default; } if ((PUBLISHABLE & commandModule.type) != 0) { const filename = basename(absPath); const filenameNoExtension = filename.substring(0, filename.lastIndexOf(".")); commandModule.name ??= filenameNoExtension; commandModule.description ??= ""; commandModule.meta = { absPath }; commandModule.absPath = absPath; if (typeof config2 === "function") { config2 = config2(absPath, commandModule); } modules.push({ commandModule, config: config2 }); } } var cacheDir = resolve("./.sern"); if (!pathExistsSync(cacheDir)) { await mkdir(cacheDir); } var optionsTransformer = (ops) => { return ops.map((el) => { if ("command" in el) { const { command, ...rest2 } = el; return rest2; } return el; }); }; var intoApplicationType = (type) => { if (type === 3) { return 1; } return Math.log2(type); }; var makeDescription = (type, desc) => { if (type !== 1 && desc !== "") { console.warn("Found context menu that has non empty description field. Implictly publishing with empty description"); return ""; } return desc; }; var serialize = (permissions) => { if (typeof permissions === "bigint" || typeof permissions === "number") { return permissions.toString(); } if (Array.isArray(permissions)) { return permissions.reduce((acc, cur) => acc | cur, BigInt(0)).toString(); } return null; }; var makePublishData = ({ commandModule, config: config2 }) => { const applicationType = intoApplicationType(commandModule.type); return { data: { name: commandModule.name, type: applicationType, description: makeDescription(applicationType, commandModule.description), absPath: commandModule.absPath, options: optionsTransformer(commandModule?.options ?? []), dm_permission: config2?.dmPermission ?? false, default_member_permissions: serialize(config2?.defaultMemberPermissions), //@ts-ignore integration_types: (config2?.integrationTypes ?? ["Guild"]).map( (s) => { if (s === "Guild") { return "0"; } else if (s == "User") { return "1"; } else { throw Error("IntegrationType is not one of Guild (0) or User (1)"); } } ), //@ts-ignore contexts: config2?.contexts ?? void 0, name_localizations: commandModule.name_localizations, description_localizations: commandModule.description_localizations }, config: config2 }; }; var publishableData = modules.map(makePublishData); var token = process.env.token || process.env.DISCORD_TOKEN; assert(token, "Could not find a token for this bot in .env or commandline. Do you have DISCORD_TOKEN in env?"); var [globalCommands, guildedCommands] = publishableData.reduce( ([globals, guilded], module) => { const isPublishableGlobally = !module.config || !Array.isArray(module.config.guildIds); if (isPublishableGlobally) { return [[module, ...globals], guilded]; } return [globals, [module, ...guilded]]; }, [[], []] ); var spin = ora(`Publishing ${cyanBright("Global")} commands`); globalCommands.length && spin.start(); var rest = await create(token); var res = await rest.updateGlobal(globalCommands); var globalCommandsResponse; if (res.ok) { globalCommands.length && spin.succeed(`All ${cyanBright("Global")} commands published`); globalCommandsResponse = await res.json(); } else { spin.fail(`Failed to publish global commands [Code: ${redBright(res.status)}]`); console.error("Status Text ", res.statusText); switch (res.status) { case 400: { const validation_errors = await res.json(); console.error("errors:", inspect(validation_errors, { depth: Infinity })); console.error("Modules with validation errors:" + inspect(Object.keys(validation_errors.errors).map((idx) => globalCommands[idx]))); throw Error("400: Ensure your commands have proper fields and data with nothing left out"); } case 404: { console.error("errors:", inspect(await res.json(), { depth: Infinity })); throw Error("Forbidden 404. Is you application id and/or token correct?"); } case 429: { console.error("errors:", inspect(await res.json(), { depth: Infinity })); } break; default: { console.error("errors:", inspect(await res.json(), { depth: Infinity })); throw Error(res.status.toString() + " error"); } } } function associateGuildIdsWithData(data) { const guildIdMap = /* @__PURE__ */ new Map(); data.forEach((entry) => { const { data: data2, config: config2 } = entry; const { guildIds } = config2 || {}; if (guildIds) { guildIds.forEach((guildId) => { if (guildIdMap.has(guildId)) { guildIdMap.get(guildId)?.push(data2); } else { guildIdMap.set(guildId, [data2]); } }); } }); return guildIdMap; } var guildCommandMap = associateGuildIdsWithData(guildedCommands); var guildCommandMapResponse = /* @__PURE__ */ new Map(); for (const [guildId, array] of guildCommandMap.entries()) { const spin2 = ora(`[${cyanBright(guildId)}] Updating commands for guild`); spin2.start(); const response = await rest.putGuildCommands(guildId, array); const result = await response.json(); if (response.ok) { guildCommandMapResponse.set(guildId, result); spin2.succeed(`[${greenBright(guildId)}] Successfully updated commands for guild`); } else { spin2.fail(`[${redBright(guildId)}] Failed to update commands for guild, Reason: ${result.message}`); switch (response.status) { case 400: { console.error(inspect(result, { depth: Infinity })); console.error("Modules with validation errors:" + inspect(Object.keys(result.errors).map((idx) => array[idx]))); throw Error("400: Ensure your commands have proper fields and data and nothing left out"); } case 404: { console.error(inspect(result, { depth: Infinity })); throw Error("Forbidden 404. Is you application id and/or token correct?"); } case 429: { console.error(inspect(result, { depth: Infinity })); throw Error("Chill out homie, too many requests"); } } } } var remoteData = { global: globalCommandsResponse, ...Object.fromEntries(guildCommandMapResponse) }; await writeFile(resolve(cacheDir, "command-data-remote.json"), JSON.stringify(remoteData, null, 4), "utf8"); process.exit(0); //# sourceMappingURL=out.js.map //# sourceMappingURL=create-publish.js.map