if (process.versions.node.split(".")[0] < 16) { console.error(`You are currently running Node.js version ${process.version}. esmBot requires Node.js version 16 or above. Please refer to step 3 of the setup guide.`); process.exit(1); } if (process.platform === "win32") { console.error("\x1b[1m\x1b[31m\x1b[40m" + `WINDOWS IS NOT OFFICIALLY SUPPORTED! Although there's a (very) slim chance of it working, multiple aspects of the bot are built with UNIX-like systems in mind and could break on Win32-based systems. If you want to run the bot on Windows, using Windows Subsystem for Linux is highly recommended. The bot will continue to run past this message in 5 seconds, but keep in mind that it could break at any time. Continue running at your own risk; alternatively, stop the bot using Ctrl+C and install WSL.` + "\x1b[0m"); Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 5000); } // load config from .env file import { resolve, dirname } from "path"; import { fileURLToPath } from "url"; import { config } from "dotenv"; config({ path: resolve(dirname(fileURLToPath(import.meta.url)), ".env") }); import { reloadImageConnections } from "./utils/image.js"; // main services import * as sdk from "matrix-js-sdk"; import pm2 from "pm2"; // some utils import { promises, readFileSync } from "fs"; import { logger } from "./utils/logger.js"; import { exec as baseExec } from "child_process"; import { promisify } from "util"; const exec = promisify(baseExec); // initialize command loader import { load } from "./utils/handler.js"; // command collections import { paths } from "./utils/collections.js"; // database stuff import database from "./utils/database.js"; // events import { parseThreshold } from "./utils/tempimages.js"; const { types } = JSON.parse(readFileSync(new URL("./config/commands.json", import.meta.url))); const esmBotVersion = JSON.parse(readFileSync(new URL("./package.json", import.meta.url))).version; process.env.ESMBOT_VER = esmBotVersion; async function* getFiles(dir) { const dirents = await promises.readdir(dir, { withFileTypes: true }); for (const dirent of dirents) { const name = dir + (dir.charAt(dir.length - 1) !== "/" ? "/" : "") + dirent.name; if (dirent.isDirectory()) { yield* getFiles(name); } else if (dirent.name.endsWith(".js")) { yield name; } } } async function init() { await exec("git rev-parse HEAD").then(output => output.stdout.substring(0, 7), () => "unknown commit").then(o => process.env.GIT_REV = o); console.log(` ████ ████▒▒▒▒ ████▒▒████▒▒ ████▒▒██████▒▒ ████▒▒██████████▒▒ ████▒▒████████████▒▒ ████▒▒██████████████▒▒ ████▒▒██████████████▒▒▒▒ ████▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ ████▒▒████████████▒▒██▒▒██▒▒ ████▒▒██████████▒▒████▒▒████▒▒ ████▒▒██████▒▒██████▒▒██████▒▒ ████▒▒████▒▒████████▒▒████████▒▒ ████▒▒▒▒██████████▒▒██████████▒▒ ████▒▒██████████▒▒██████████▒▒██ ████▒▒▒▒▒▒████▒▒████▒▒▒▒▒▒████ ████████▒▒▒▒▒▒▒▒▒▒████████ ██████████████████████ ██████████ mrmBot-matrix ${esmBotVersion} (${process.env.GIT_REV}) `); if (!types.classic && !types.application) { logger.error("Both classic and application commands are disabled! Please enable at least one command type in config/commands.json."); return process.exit(1); } if (database) { // database handling const dbResult = await database.upgrade(logger); if (dbResult === 1) return process.exit(1); } // process the threshold into bytes early if (process.env.TEMPDIR && process.env.THRESHOLD) { await parseThreshold(); } // register commands and their info logger.log("info", "Attempting to load commands..."); for await (const commandFile of getFiles(resolve(dirname(fileURLToPath(import.meta.url)), "./commands/"))) { logger.log("main", `Loading command from ${commandFile}...`); try { await load(null, commandFile); } catch (e) { logger.error(`Failed to register command from ${commandFile}: ${e}`); } } logger.log("info", "Finished loading commands."); if (database) { await database.setup(); } if (process.env.API_TYPE === "ws") await reloadImageConnections(); const myUserId = process.env.MATRIX_USERNAME; const myAccessToken = process.env.TOKEN; const matrixClient = sdk.createClient({ baseUrl: process.env.MATRIX_BASEURL, accessToken: myAccessToken, userId: myUserId, }); // register events logger.log("info", "Attempting to load events..."); const { default: event } = await import("./events/roommessage.js"); matrixClient.on("Room.timeline", event.bind(null,matrixClient)); matrixClient.on("RoomMember.membership", function (event, member) { try { // TODO - add .env var that disables owner check here let owners = process.env.OWNER.split(",") if (member.membership === "invite" && owners.includes(event.event.sender)) { matrixClient.joinRoom(member.roomId).then(function () { logger.log("info", `Auto-Joined ${member.roomId}`); }); } } catch { // no-op } }); logger.log("info", "Finished loading events."); matrixClient.startClient({ initialSyncLimit: 0, lazyLoadMembers: true }).then(() => logger.log("info", "Client started!")); } init();