"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.killBridge = exports.runBridge = exports.generateRegistration = void 0;
const bluebird_1 = __importDefault(require("bluebird"));
const nedb_1 = __importDefault(require("nedb"));
const extend_1 = __importDefault(require("extend"));
const http_1 = __importDefault(require("http"));
const https_1 = __importDefault(require("https"));
const matrix_appservice_bridge_1 = require("matrix-appservice-bridge");
const IrcBridge_1 = require("./bridge/IrcBridge");
const IrcServer_1 = require("./irc/IrcServer");
const Ident_1 = __importDefault(require("./irc/Ident"));
const logging = __importStar(require("./logging"));
const Sentry = __importStar(require("@sentry/node"));
const log = logging.get("main");
// We set this to 1000 by default now to set a default, and to ensure we're the first
// one to load the libraries in. Later on in runBridge we actually define the real limit.
http_1.default.globalAgent.maxSockets = 1000;
https_1.default.globalAgent.maxSockets = 1000;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
process.on("unhandledRejection", (reason) => {
    let reasonStr = "No reason given";
    if (reason && reason.stack) {
        reasonStr = reason.stack;
    }
    else if (typeof (reason) === "string") {
        reasonStr = reason;
    }
    log.error(reasonStr);
});
const _toServer = (domain, serverConfig, homeserverDomain) => {
    // set server config defaults
    return new IrcServer_1.IrcServer(domain, (0, extend_1.default)(true, IrcServer_1.IrcServer.DEFAULT_CONFIG, serverConfig), homeserverDomain);
};
function generateRegistration(reg, config) {
    let asToken;
    if (!reg.getSenderLocalpart()) {
        reg.setSenderLocalpart(IrcBridge_1.IrcBridge.DEFAULT_LOCALPART);
    }
    reg.setId(matrix_appservice_bridge_1.AppServiceRegistration.generateToken());
    reg.setHomeserverToken(matrix_appservice_bridge_1.AppServiceRegistration.generateToken());
    reg.setAppServiceToken(asToken || matrix_appservice_bridge_1.AppServiceRegistration.generateToken());
    // Disable rate limiting to allow large numbers of requests when many IRC users
    // connect, for example on startup.
    reg.setRateLimited(false);
    // Needed to detect activity of users on the bridge.
    reg.pushEphemeral = true;
    // Set protocols to IRC, so that the bridge appears in the list of
    // thirdparty protocols
    reg.setProtocols(["irc"]);
    const serverDomains = Object.keys(config.ircService.servers);
    serverDomains.sort().forEach(function (domain) {
        const server = _toServer(domain, config.ircService.servers[domain], config.homeserver.domain);
        server.getHardCodedRoomIds().sort().forEach(function (roomId) {
            reg.addRegexPattern("rooms", roomId, false);
        });
        // add an alias pattern for servers who want aliases exposed.
        if (server.createsDynamicAliases()) {
            reg.addRegexPattern("aliases", server.getAliasRegex(), true);
        }
        reg.addRegexPattern("users", server.getUserRegex(), true);
    });
    return reg;
}
exports.generateRegistration = generateRegistration;
async function runBridge(port, config, reg, testOpts = { isDBInMemory: false }) {
    if (config.sentry && config.sentry.enabled && config.sentry.dsn) {
        log.info("Sentry ENABLED");
        Sentry.init({
            dsn: config.sentry.dsn,
            release: "0.35.1",
            environment: config.sentry.environment,
            serverName: config.sentry.serverName,
        });
        Sentry.configureScope((scope) => {
            const firstNetwork = Object.keys(config.ircService.servers)[0];
            scope.setTag("irc_network", firstNetwork);
        });
    }
    // configure global stuff for the process
    if (config.ircService.logging) {
        logging.configure(config.ircService.logging);
        logging.setUncaughtExceptionLogger(log);
    }
    if (config.ircService.ident && config.ircService.ident.enabled) {
        Ident_1.default.configure(config.ircService.ident);
        Ident_1.default.run();
    }
    const maxSockets = config.advanced?.maxHttpSockets ?? 1000;
    // eslint-disable-next-line @typescript-eslint/no-var-requires
    require("http").globalAgent.maxSockets = maxSockets;
    // eslint-disable-next-line @typescript-eslint/no-var-requires
    require("https").globalAgent.maxSockets = maxSockets;
    // run the bridge
    const ircBridge = new IrcBridge_1.IrcBridge(config, reg, testOpts);
    const engine = config.database ? config.database.engine : "nedb";
    // Use in-memory DBs
    if (testOpts.isDBInMemory) {
        ircBridge.getAppServiceBridge().opts.roomStore = new matrix_appservice_bridge_1.RoomBridgeStore(new nedb_1.default());
        ircBridge.getAppServiceBridge().opts.userStore = new matrix_appservice_bridge_1.UserBridgeStore(new nedb_1.default());
    }
    else if (engine === "postgres") {
        // Do nothing
    }
    else if (engine !== "nedb") {
        throw Error("Invalid database configuration");
    }
    await ircBridge.run(port);
    Sentry.captureMessage("Bridge has started", Sentry.Severity.Info);
    return ircBridge;
}
exports.runBridge = runBridge;
function killBridge(ircBridge, reason) {
    if (!ircBridge) {
        log.info('killBridge(): No bridge running');
        return bluebird_1.default.resolve();
    }
    const logReason = reason || "(unknown reason)";
    log.info('Killing bridge: ' + logReason);
    return ircBridge.kill(reason);
}
exports.killBridge = killBridge;
//# sourceMappingURL=main.js.map