const Express = require('express'), BodyParser = require("body-parser"), MethodOverride = require("method-override"), App = Express(), cors = require("cors"), Helmet = require("helmet"), Showdown = require("showdown"); module.exports = class API { constructor(bot) { this.ESMBot = bot; } initialize() { let allowedOrigins = ["http://localhost:4200", "https://www.esmbot.com", "https://esmbot.com"]; App.use(cors({ origin: (origin, callback) => { if (allowedOrigins.includes(origin) || !origin) { callback(null, true); } else { callback(new Error('Not allowed by CORS')); } }, credentials: true })); App.use(Helmet()); App.enable("trust proxy"); App.use(BodyParser.text({ type: '*/*' })); App.use(MethodOverride("X-HTTP-Method-Override")); App.get("/", this.index.bind(this)); /////////////////////////////////////////////////////////////////////////// var router = Express.Router(); router.use(function (req, res, next) { next(); }); router.get("/v2", (req, res) => { res.json({ message: "Hmm..." }) }); router.route("/v2/commands").get(this.getCommands.bind(this)); router.route("/v2/commands/info").get(this.getCommandsInfo.bind(this)); router.route("/v2/status").post(this.setBotStatus.bind(this)); router.route("/v2/maintenance").post(this.setBotMaintenance.bind(this)); router.route("/v2/send_message").post(this.sendMessage.bind(this)); router.route("/v2/update_server").post(this.updateServer.bind(this)); router.route("/v2/log").post(this.log.bind(this)); /////////////////////////////////////////////////////////////////////////// App.use("/", router); App.listen(this.ESMBot.config.API_SERVER_PORT); this.ESMBot.logger.success(`ESM API is initialized`); } index(req, res) { res.redirect('https://www.esmbot.com'); } async getCommands(req, res) { if (req.headers.authorization !== `Bearer ${this.ESMBot.config.API_TOKEN}`) { return res.json({ code: "0", message: "401 Unauthorized" }); } let converter = new Showdown.Converter(); let commands = {}; for (let name in this.ESMBot.commands) { let command = new(this.ESMBot.commands[name])(this.ESMBot); if ( this.ESMBot.util.isEmpty(command.information) || command.information.category == null || ["", "administrative", "development"].includes(command.information.category) ) continue; let description = converter.makeHtml((command.information.help)).replace(/<p>/g, "").replace(/<\/p>/g, "").replace(/\n/g, "<br>"); let info = { isPremium: false, description: description, params: command.information.params }; if (commands[this.ESMBot.util.titleize(command.information.category)]) { commands[this.ESMBot.util.titleize(command.information.category)][`${this.ESMBot.config.COMMAND_SYMBOL}${name}`] = info; } else { commands[this.ESMBot.util.titleize(command.information.category)] = {}; commands[this.ESMBot.util.titleize(command.information.category)][`${this.ESMBot.config.COMMAND_SYMBOL}${name}`] = info; } } return res.json({ commands: commands }); } async getCommandsInfo(req, res) { if (req.headers.authorization !== `Bearer ${this.ESMBot.config.API_TOKEN}`) { return res.json({ code: "0", message: "401 Unauthorized" }); } let converter = new Showdown.Converter(); let commands = {}; for (let name in this.ESMBot.commands) { let command = new(this.ESMBot.commands[name])(this.ESMBot); if ( this.ESMBot.util.isEmpty(command.information) || command.information.category == null || ["", "administrative", "development"].includes(command.information.category) || this.ESMBot.util.isEmpty(command.configuration) ) continue; let info = { configuration: command.configuration, description: converter.makeHtml(command.information.help.split("\n")[0]).replace(/<p>/g, "").replace(/<\/p>/g, "") } if (commands[this.ESMBot.util.titleize(command.information.category)]) { commands[this.ESMBot.util.titleize(command.information.category)][name] = info; } else { commands[this.ESMBot.util.titleize(command.information.category)] = {}; commands[this.ESMBot.util.titleize(command.information.category)][name] = info; } } return res.json({ commands: commands }); } async setBotStatus(req, res) { if (req.headers.authorization !== `Bearer ${this.ESMBot.config.API_TOKEN}`) { return res.json({ code: "0", message: "401 Unauthorized" }); } this.ESMBot.setPresence(this.ESMBot); return res.json({ status: 202 }); } async setBotMaintenance(req, res) { if (req.headers.authorization !== `Bearer ${this.ESMBot.config.API_TOKEN}`) { return res.json({ code: "0", message: "401 Unauthorized" }); } this.ESMBot.setMaintenance(); return res.json({ status: 202 }); } async sendMessage(req, res) { if (req.headers.authorization !== `Bearer ${this.ESMBot.config.API_TOKEN}`) { return res.json({ code: "0", message: "401 Unauthorized" }); } let body = JSON.parse(req.body); this.ESMBot.send(body.channel, body.message); return res.json({ status: 202 }); } async updateServer(req, res) { if (req.headers.authorization !== `Bearer ${this.ESMBot.config.API_TOKEN}`) { return res.json({ code: "0", message: "401 Unauthorized" }); } let body = JSON.parse(req.body); let command = new(this.ESMBot.commands["update_server_settings"])(this.ESMBot); command.params = body; command.fromDiscord(); res.json({ status: 202 }); } async log(req, res) { if (req.headers.authorization !== `Bearer ${this.ESMBot.config.API_TOKEN}`) { return res.json({ code: "0", message: "401 Unauthorized" }); } let body = JSON.parse(req.body); switch (body.type) { case "info": this.ESMBot.logger.info(body.message); break; case "success": this.ESMBot.logger.success(body.message); break; case "warn": this.ESMBot.logger.warn(body.message); break; case "error": this.ESMBot.logger.error(body.message); break; case "debug": this.ESMBot.logger.debug(body.message); break; case "trace": this.ESMBot.logger.trace(body.message); break; case "api": this.ESMBot.logger.api(body.message); break; case "registrations": this.ESMBot.logger.registrations(body.message); break; default: this.ESMBot.logger.info(body.message); break; } res.json({ status: 202 }); } }