Files
SupportBot/Structures/BotStartup.js
T
2026-08-10 20:15:00 +01:00

201 lines
5.5 KiB
JavaScript

const Discord = require("discord.js");
const configStore = require("./ConfigStore.js");
const {
getPrimaryGuild,
syncGuildHealth,
} = require("./GuildManager.js");
const ACTIVITY_TYPES = {
PLAYING: Discord.ActivityType.Playing,
WATCHING: Discord.ActivityType.Watching,
LISTENING: Discord.ActivityType.Listening,
COMPETING: Discord.ActivityType.Competing,
STREAMING: Discord.ActivityType.Streaming,
};
function applyPresence(client) {
if (!client?.user) return;
const activity = configStore.supportbot?.Activity;
const typeKey = activity?.Type?.toUpperCase();
const type = ACTIVITY_TYPES[typeKey] ?? Discord.ActivityType.Playing;
const name = activity?.Status || "Online";
const activityPayload = { name, type };
if (typeKey === "STREAMING" && activity?.StreamingURL) {
activityPayload.url = activity.StreamingURL;
}
client.user.setPresence({
activities: [activityPayload],
status: "online",
});
}
const c = {
reset: "\x1b[0m",
gray: "\x1b[90m",
green: "\x1b[32m",
yellow: "\x1b[33m",
bold: "\x1b[1m",
white: "\x1b[37m",
};
function line() {
console.log(
`${c.gray}────────────────────────────────────────────────────────${c.reset}`,
);
}
function section(title) {
console.log(`\n${c.green}${title}${c.reset}`);
console.log(`${c.gray}${"-".repeat(title.length)}${c.reset}`);
}
function info(label, value) {
console.log(`${c.gray}${label.padEnd(14)}${c.reset} ${value}`);
}
function status(label, ok, details = "") {
const icon = ok ? `${c.green}✓${c.reset}` : `${c.yellow}!${c.reset}`;
console.log(` ${icon} ${label}${details ? ` (${details})` : ""}`);
}
async function logStartup(client, options = {}) {
const { clearConsole = true } = options;
const supportbot = configStore.supportbot;
if (clearConsole) {
console.clear();
}
const botName = supportbot?.General?.Name || "SupportBot";
const botVersion = supportbot?.SupportBot_Version || "Unknown";
const { getBotInviteUrl } = require("./BotInvite.js");
const inviteUrl = getBotInviteUrl(client.user.id);
line();
console.log(`${c.bold}${c.green}SupportBot${c.reset}`);
console.log(`${c.gray}Emerald Services${c.reset}`);
line();
section("System");
info("Bot Name", botName);
info("Version", botVersion);
info("Node.js", process.version);
info("Discord.js", `v${Discord.version}`);
const db = require("./Database.js");
const dbInfo = db.getDatabaseInfo ? db.getDatabaseInfo() : null;
if (dbInfo) {
const dbDisplay = dbInfo.type === "mysql"
? `${dbInfo.driver} (${dbInfo.host}:${dbInfo.port}/${dbInfo.database})`
: `${dbInfo.driver} (${dbInfo.file})`;
info("Database", dbDisplay);
}
info("Logged in as", client.user.tag);
info("Guilds", `${client.guilds.cache.size}`);
section("Links");
info("Docs", "https://emerald-services.gitbook.io/");
info("Discord", "https://dsc.gg/emerald-dev");
if (configStore.api?.API?.Enabled) {
const port = configStore.api?.API?.Port || 3000;
info("Dashboard", `http://localhost:${port}`);
}
info("Invite", inviteUrl);
console.log("");
}
function checkSetup() {
const { isSetupComplete } = require("./DashboardSetup.js");
if (!isSetupComplete()) {
const port = configStore.api?.API?.Port || 25575;
section("Setup Required");
status("Onboarding setup incomplete", false, `http://localhost:${port}/setup`);
console.log("");
}
}
async function checkConfigs(client) {
const supportbot = configStore.supportbot;
const health = syncGuildHealth(client);
if (health.status !== "ok") {
section("Guild");
status("Guild setup", false, health.message || health.status);
console.log("");
}
const guild = getPrimaryGuild(client);
if (!guild) return;
section("Config Check");
const roles = [
supportbot?.Roles?.StaffMember?.Admin,
supportbot?.Roles?.StaffMember?.Staff,
supportbot?.Roles?.AutoRole?.Role,
].filter(Boolean);
const channels = [supportbot?.Ticket?.TicketHome].filter(Boolean);
const [roleResults, channelResults] = await Promise.all([
Promise.all(roles.map((role) => client.getRole(role, guild))),
Promise.all(channels.map((channel) => client.getChannel(channel, guild))),
]);
const missingRoles = roles.filter((_, i) => !roleResults[i]);
const missingChannels = channels.filter((_, i) => !channelResults[i]);
if (!missingRoles.length && !missingChannels.length) {
status("All configurations validated successfully", true);
} else {
if (missingRoles.length) {
status("Missing roles", false, missingRoles.join(", "));
}
if (missingChannels.length) {
status("Missing channels", false, missingChannels.join(", "));
}
}
console.log("");
}
function logSlashCommandsRegistered(client) {
const guild = getPrimaryGuild(client);
if (!guild) return;
console.log(
`\n${c.green}✓${c.reset} ${c.white}Slash Commands Registered${c.reset} ${c.gray}for ${guild.name}${c.reset}`,
);
}
/**
* Same work as Events/ready.js — safe to call after config reload reconnects.
*/
async function runBotReady(client, options = {}) {
const { clearConsole = true, logCommands = false } = options;
syncGuildHealth(client);
applyPresence(client);
await logStartup(client, { clearConsole });
await checkConfigs(client);
if (logCommands) {
logSlashCommandsRegistered(client);
}
checkSetup();
}
module.exports = {
applyPresence,
logStartup,
checkConfigs,
logSlashCommandsRegistered,
runBotReady,
};