"use strict";
// Copyright 2025 Gnuxie <Gnuxie@protonmail.com>
//
// SPDX-License-Identifier: Apache-2.0
Object.defineProperty(exports, "__esModule", { value: true });
exports.InvalidEventProtection = void 0;
const typebox_1 = require("@sinclair/typebox");
const matrix_protection_suite_1 = require("matrix-protection-suite");
const LeakyBucket_1 = require("../queues/LeakyBucket");
const interface_manager_1 = require("@the-draupnir-project/interface-manager");
const mps_interface_adaptor_1 = require("@the-draupnir-project/mps-interface-adaptor");
const log = new matrix_protection_suite_1.Logger("InvalidEventProtection");
const InvalidEventProtectionSettings = typebox_1.Type.Object({
    warningText: typebox_1.Type.String({
        description: "The reason to use to notify the user after redacting their infringing message.",
        default: "You have sent an invalid event that could cause problems in some Matrix clients, so we have had to redact it.",
    }),
}, {
    title: "InvalidEventProtectionSettings",
});
class InvalidEventProtection extends matrix_protection_suite_1.AbstractProtection {
    warningText;
    roomMessageSender;
    managentRoomID;
    eventConsequences;
    userConsequences;
    consequenceBucket = new LeakyBucket_1.LazyLeakyBucket(1, 30 * 60_000 // half an hour will do
    );
    constructor(description, lifetime, capabilities, protectedRoomsSet, warningText, roomMessageSender, managentRoomID) {
        super(description, lifetime, capabilities, protectedRoomsSet, {});
        this.warningText = warningText;
        this.roomMessageSender = roomMessageSender;
        this.managentRoomID = managentRoomID;
        this.eventConsequences = capabilities.eventConsequences;
        this.userConsequences = capabilities.userConsequences;
    }
    async redactEventWithMixin(event) {
        const redactResult = await this.eventConsequences.consequenceForEvent(event.sourceEvent.room_id, event.sourceEvent.event_id, "invalid event mixin");
        if ((0, matrix_protection_suite_1.isError)(redactResult)) {
            log.error(`Failed to redact and event sent by ${event.sourceEvent.sender} in ${event.sourceEvent.room_id}`, redactResult.error);
        }
        const managementRoomSendResult = await (0, mps_interface_adaptor_1.sendMatrixEventsFromDeadDocument)(this.roomMessageSender, this.managentRoomID, interface_manager_1.DeadDocumentJSX.JSXFactory("root", null,
            interface_manager_1.DeadDocumentJSX.JSXFactory("details", null,
                interface_manager_1.DeadDocumentJSX.JSXFactory("summary", null,
                    "Copy of invalid event content from ",
                    event.sourceEvent.sender),
                interface_manager_1.DeadDocumentJSX.JSXFactory("pre", null, JSON.stringify(event.sourceEvent.content)))), {});
        if ((0, matrix_protection_suite_1.isError)(managementRoomSendResult)) {
            log.error("Failed to send redacted event details to the management room", managementRoomSendResult.error);
        }
    }
    async sendWarning(event) {
        const result = await (0, mps_interface_adaptor_1.sendMatrixEventsFromDeadDocument)(this.roomMessageSender, event.sourceEvent.room_id, interface_manager_1.DeadDocumentJSX.JSXFactory("root", null,
            (0, mps_interface_adaptor_1.renderMentionPill)(event.sourceEvent.sender, event.sourceEvent.sender),
            " ",
            this.warningText), { replyToEvent: event.sourceEvent });
        if ((0, matrix_protection_suite_1.isError)(result)) {
            log.error("Unable to warn the user", event.sourceEvent.sender, result.error);
        }
    }
    async banUser(event) {
        const banResult = await this.userConsequences.consequenceForUserInRoom(event.sourceEvent.room_id, event.sourceEvent.sender, "Sending invalid events");
        if ((0, matrix_protection_suite_1.isError)(banResult)) {
            log.error("Unable to ban the sender of invalid events", event.sourceEvent.sender, event.sourceEvent.room_id, banResult.error);
        }
    }
    handleProtectionDisable() {
        this.consequenceBucket.stop();
    }
    handleTimelineEventMixins(_room, event) {
        if (!event.mixins.some((mixin) => mixin.isErroneous)) {
            return;
        }
        const infractions = this.consequenceBucket.getTokenCount(event.sourceEvent.sender);
        if (infractions > 0) {
            void (0, matrix_protection_suite_1.Task)(this.banUser(event), { log });
        }
        else {
            void (0, matrix_protection_suite_1.Task)(this.sendWarning(event), { log });
        }
        this.consequenceBucket.addToken(event.sourceEvent.sender);
        void (0, matrix_protection_suite_1.Task)(this.redactEventWithMixin(event), { log });
    }
}
exports.InvalidEventProtection = InvalidEventProtection;
(0, matrix_protection_suite_1.describeProtection)({
    name: "InvalidEventProtection",
    description: `Protect the room against malicious events or evasion of other protections.`,
    capabilityInterfaces: {
        eventConsequences: "EventConsequences",
        userConsequences: "UserConsequences",
    },
    defaultCapabilities: {
        eventConsequences: "StandardEventConsequences",
        userConsequences: "StandardUserConsequences",
    },
    configSchema: InvalidEventProtectionSettings,
    factory: async (decription, lifetime, protectedRoomsSet, draupnir, capabilitySet, settings) => (0, matrix_protection_suite_1.allocateProtection)(lifetime, new InvalidEventProtection(decription, lifetime, capabilitySet, protectedRoomsSet, settings.warningText, draupnir.clientPlatform.toRoomMessageSender(), draupnir.managementRoomID)),
});
//# sourceMappingURL=InvalidEventProtection.js.map