import {BaseInteraction, Client} from "discord.js" import {config} from "dotenv" import {isAutocomplete, isChatInputCommand} from "../types/interactions.js" import {Commands} from "../commands/index.js" import {checkIsRestart, reportFailed, reportReady, reportStarted} from "../ipc/restart.js" import {defaultPresence} from "../defaultPresence.js" import {Pool} from "pg" import {Database, DatabaseImpl, makeTransact} from "../database" async function bot() { await checkIsRestart() config() const c = new Client({ intents: [], }) const p = new Pool({ application_name: "VoreRPG Bot", }) p.on("error", (err) => { console.log(err) }) async function cleanUp() { await p.end() c.destroy() } const db: Database = new DatabaseImpl({ query: p.query.bind(p), transact: makeTransact(p), }) const cmd = new Commands({users: db.users, cleanUp}) c.on("ready", async () => { try { await db.users.createBotOwnerAsAdmin(process.env.BOT_OWNER_ID || "") } catch (ex) { await reportFailed(c, ex) return } const app = c.application if (!app) { c.destroy() await reportFailed(c, "No application was given") return } else { try { cmd.setCache(await app.commands.set(cmd.definitions)) const g = await c.guilds.fetch() for (const guild of g.values()) { cmd.setCache(await app.commands.set(cmd.definitions, guild.id)) } } catch (ex) { c.destroy() await reportFailed(c, ex) return } } const user = c.user if (!user) { c.destroy() await reportFailed(c, "No user found") return } else { user.setPresence(defaultPresence) } try { await reportReady(c) } catch (ex) { console.log(ex) } }) c.on("error", async (ex) => { c.destroy() await reportFailed(c, ex) }) c.on("interactionCreate", async (ev: BaseInteraction) => { if (ev.client.user.presence.status !== "online") { if (ev.isRepliable()) { try { await ev.reply({ content: "Shhh... I'm sleeping!! Try again later.", ephemeral: true, }) } catch (ex) { console.log("failed sending busy reply", ex) } } return } if (isChatInputCommand(ev)) { try { await cmd.execute(ev) } catch (ex) { console.log("failed executing command", ev, ex) } if (!ev.replied) { console.log("never replied to command", ev) try { await ev.reply({ ephemeral: true, content: "Uuguuu... I can't think straight... try again later, 'kay?", }) } catch (ex) { console.log("failed sending error reply", ex) } } } else if (isAutocomplete(ev)) { try { await cmd.autocomplete(ev) } catch (ex) { console.log("failed autocompleting for command", ev, ex) } if (!ev.responded) { console.log("never autocompleted for command", ev) try { await ev.respond([]) } catch (ex) { console.log("failed sending error response", ex) } } } else if (ev.isRepliable()) { try { console.log("unknown command", ev) await ev.reply({ ephemeral: true, content: "Huuuuuuuh? ... I don't know what to do with that yet.", }) } catch (ex) { console.log("failed sending unknown command reply", ex) } } else { console.log("got an interaction but can't reply to it") } }) await reportStarted() await c.login(process.env.DISCORD_TOKEN || "") } bot().catch((ex) => { console.log("main thread failed", ex) })