"use strict";
// This file is part of HFS - Copyright 2021-2023, Massimo Melina <a@rejetto.com> - License https://www.gnu.org/licenses/gpl-3.0.txt
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.block = void 0;
exports.applyBlock = applyBlock;
exports.isBlocked = isBlocked;
exports.addBlock = addBlock;
const config_1 = require("./config");
const connections_1 = require("./connections");
const misc_1 = require("./misc");
const net_1 = require("net");
const lodash_1 = __importDefault(require("lodash"));
exports.block = (0, config_1.defineConfig)('block', [], rules => {
    const now = new Date();
    const ret = !Array.isArray(rules) ? []
        : (0, misc_1.onlyTruthy)(rules.map(rule => {
            rule.expire &&= new Date(rule.expire);
            return !rule.disabled && (rule.expire || now) >= now && (0, misc_1.makeNetMatcher)(rule.ip);
        }));
    // reapply new block to existing connections
    for (const { socket, ip } of (0, connections_1.getConnections)())
        applyBlock(socket, ip);
    return ret;
});
function applyBlock(socket, ip = (0, connections_1.normalizeIp)(socket.remoteAddress || '')) {
    if (ip && isBlocked(ip))
        return (0, connections_1.disconnect)(socket, 'block-ip');
}
function isBlocked(ip) {
    return exports.block.compiled().find(rule => rule(ip));
}
setInterval(() => {
    const now = new Date();
    const next = exports.block.get().filter(x => !x.expire || x.expire > now);
    const n = exports.block.get().length - next.length;
    if (!n)
        return;
    console.log("Blocking rules:", n, "expired");
    exports.block.set(next);
}, misc_1.MINUTE / 2);
function addBlock(rule, merge) {
    if ((0, net_1.isIP)(rule.ip) && isBlocked(rule.ip))
        return; // already
    exports.block.set(was => {
        const match = merge && lodash_1.default.matches(merge);
        const foundIdx = match ? lodash_1.default.findIndex(was, v => match(v) && !v.disabled) : -1;
        // in case the rule is disabled, and isBlocked returned false
        return foundIdx < 0 ? [...was, { ...merge, ...rule }] // add as new rule
            : was.map((x, i) => i === foundIdx ? { ...x, ...rule, ip: `${x.ip}|${rule.ip}` } : x);
    });
}
