rashi-discord-bot-lib
Version:
🚀 Powerful Discord bot framework with built-in database, event handling, and utilities
161 lines • 6.86 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.BotStarter = void 0;
const update_1 = require("../utils/update");
const EventLoader_1 = require("./EventLoader");
const CommandLoader_1 = require("./CommandLoader");
const DatabaseManager_1 = require("./DatabaseManager");
const Logger_1 = require("../utils/Logger");
const FileWatcher_1 = require("../utils/FileWatcher");
const mongo_1 = require("../utils/mongo");
const BotStatistics_1 = require("../utils/BotStatistics");
const commandGuards_1 = require("../utils/commandGuards");
const MongoCooldownManager_1 = require("../utils/MongoCooldownManager");
const i18n_1 = require("../i18n");
const verse_1 = require("../utils/verse");
const { version: localVersion } = require("../../package.json");
class BotStarter {
logger = new Logger_1.Logger();
eventLoader = new EventLoader_1.EventLoader(this.logger);
commandLoader = new CommandLoader_1.CommandLoader(this.logger);
databaseManager = new DatabaseManager_1.DatabaseManager(this.logger);
statistics = new BotStatistics_1.BotStatistics(this.logger);
fileWatcher;
async start(client, options) {
this.validateOptions(options);
await (0, i18n_1.initializeI18n)();
if (options.bot.logs?.terminal)
this.logger.enableTerminalLogs();
if (options.bot.logs?.devLogs?.enable)
await this.setupDevLogs(options.bot.logs.devLogs);
const { versedb, mongodb } = await this.databaseManager.initialize(options.bot.Database);
if (versedb)
(0, verse_1.setVerseDb)(versedb);
if (mongodb)
(0, mongo_1.setDb)(mongodb);
// --- Cooldowns ---
let cooldowns;
if (mongodb) {
const mongoManager = new MongoCooldownManager_1.MongoCooldownManager("cooldowns");
await mongoManager.connect();
cooldowns = mongoManager;
}
else if (versedb) {
cooldowns = new commandGuards_1.CooldownManager({ type: "verse", instance: versedb });
}
else {
throw new Error("No valid cooldown backend found (VerseDB or MongoDB required).");
}
if ("connect" in cooldowns && typeof cooldowns.connect === "function") {
await cooldowns.connect();
}
this.commandLoader.setCooldowns(cooldowns);
// --- Load Events & Commands ---
const eventSize = await this.eventLoader.loadEvents(client, options.events.path, options.events.recursive || false, options.events.eventBlacklist || []);
const { slashSize, prefixSize } = await this.commandLoader.loadCommands(client, options.commands);
this.statistics.setLoadedEvents(eventSize);
this.statistics.setLoadedCommands(slashSize, prefixSize);
this.statistics.initialize(client);
this.commandLoader.setStatistics(this.statistics);
if (options.anticrash?.enable)
this.setupAntiCrash(options.anticrash);
await this.loginBot(client, options.bot.token);
if (options.bot.BotInfo)
await this.setupBotInfo(client, options.bot.BotInfo);
await (0, update_1.checkUpdate)("rashi-discord-bot-lib", localVersion, options.bot.logs?.updates?.webhookURL, options.bot.logs?.updates?.mentionId ?? options.bot.BotInfo?.ownerId ?? "");
// --- Database stats ---
const stores = [];
let singleDbStats;
if (versedb) {
const stats = await versedb.getStats().catch(() => null);
if (stats) {
singleDbStats = {
adapter: stats.adapter,
keys: stats.keys,
size: stats.size,
};
stores.push({ name: "VerseDB", status: "connected", ...stats });
}
}
if (mongodb) {
let info;
try {
const cols = await mongodb.listCollections().toArray();
info = `collections: ${cols.length}`;
}
catch { }
stores.push({
name: "MongoDB",
adapter: "mongo",
status: "connected",
info,
});
if (!singleDbStats)
singleDbStats = { adapter: "mongo", keys: 0 };
}
if (singleDbStats)
this.statistics.setDatabaseStats(singleDbStats);
this.statistics.setDatabaseStores(stores);
await this.displayComprehensiveStats(client, options.bot, versedb);
return {
client,
versedb,
mongodb,
slashSize,
prefixSize,
eventSize,
getDb: mongodb ? () => mongodb : undefined,
db: versedb,
statistics: this.statistics,
};
}
validateOptions(options) {
if (!options.bot?.token)
throw new Error("Bot token is required");
if (!options.events?.path)
throw new Error("Events path is required");
if (!options.bot.Database)
throw new Error("Database configuration is required");
}
async setupDevLogs(devLogs) {
if (!devLogs.pathToWatch || !devLogs.webhookURL)
throw new Error("Development logs require pathToWatch and webhookURL");
this.fileWatcher = new FileWatcher_1.FileWatcher(devLogs.pathToWatch, devLogs.webhookURL, devLogs.mention, this.logger);
await this.fileWatcher.start();
}
async loginBot(client, token) {
await client.login(token);
}
async displayComprehensiveStats(client, botOptions, versedb) {
const statsOptions = { BotInfo: botOptions.BotInfo };
await this.statistics.loadDatabaseStatsFrom(versedb);
await this.statistics.generateTableStats(client, statsOptions);
}
async setupBotInfo(client, info) {
this.logger.info(`Bot info setup: ${info?.ownerId ?? "Brak właściciela"}`);
}
setupAntiCrash(anticrash) {
process.on("unhandledRejection", async (reason, promise) => {
this.statistics.trackError();
this.logger.error("Unhandled Rejection at:", { promise, reason });
});
process.on("uncaughtException", async (error) => {
this.statistics.trackError();
this.logger.error("Uncaught Exception:", error);
});
this.logger.info("Anti-crash protection enabled");
}
async shutdown() {
this.logger.info("Gracefully shutting down...");
(0, mongo_1.setDb)(null);
if (this.fileWatcher)
await this.fileWatcher.stop();
await this.databaseManager.disconnect();
this.logger.info("Shutdown complete");
}
getStatistics() {
return this.statistics;
}
}
exports.BotStarter = BotStarter;
//# sourceMappingURL=BotStarter.js.map