"use strict";
// SPDX-FileCopyrightText: 2025 Gnuxie <Gnuxie@protonmail.com>
//
// SPDX-License-Identifier: Apache-2.0
Object.defineProperty(exports, "__esModule", { value: true });
exports.TimelineRedactionQueue = void 0;
const typescript_result_1 = require("@gnuxie/typescript-result");
const matrix_basic_types_1 = require("@the-draupnir-project/matrix-basic-types");
const matrix_protection_suite_1 = require("matrix-protection-suite");
const log = new matrix_protection_suite_1.Logger("TimelineRedactionQueue");
class TimelineRedactionQueue {
    roomMessages;
    roomEventRedacter;
    limit;
    batchProcessor = this.processBatch.bind(this);
    queue = new matrix_protection_suite_1.KeyedBatchQueue(this.batchProcessor);
    constructor(roomMessages, roomEventRedacter, 
    // FIXME: We really should have a way of adding a limit to the batch enqueue operation...
    // It doesn't really seem possible though. Unless the maximum limit anyone enqueues is chosen.
    // Yeah that sounds like how it would have to work. Meanwhile, it doesn't really matter since
    // the current behaviour is constrained to 1000.
    limit = 1000) {
        this.roomMessages = roomMessages;
        this.roomEventRedacter = roomEventRedacter;
        this.limit = limit;
        // nothing to do.
    }
    async processBatch(roomID, userIDs) {
        const globUserIDs = userIDs.filter((userID) => userID.includes("*") || userID.includes("?"));
        const globsToTest = globUserIDs.map((userID) => new matrix_basic_types_1.MatrixGlob(userID));
        const isGlobInUsers = globsToTest.length !== 0;
        const usersToTest = userIDs.filter((userID) => !globUserIDs.includes(userID));
        const paginator = this.roomMessages.toRoomMessagesIterator(roomID, {
            direction: "backwards",
            limit: this.limit,
            ...(isGlobInUsers ? {} : { filter: { senders: userIDs } }),
        });
        const eventsToRedact = [];
        const paginationResult = await paginator.forEachItem({
            forEachItemCB: (event) => {
                if (
                // Always add users when there are no globs, since events are filtered by sender.
                !isGlobInUsers ||
                    usersToTest.includes(event.sender) ||
                    globsToTest.some((glob) => glob.test(event.sender))) {
                    eventsToRedact.push(event.event_id);
                }
            },
            totalItemLimit: this.limit,
        });
        if ((0, typescript_result_1.isError)(paginationResult)) {
            return paginationResult.elaborate(`Failed to paginate /messages in ${roomID} to begin redaction`);
        }
        // TODO: It would be good if we had a way of throttling these requests
        // per draupnir and in general but y'know.
        for (const eventID of eventsToRedact) {
            const redactResult = await this.roomEventRedacter.redactEvent(roomID, eventID);
            if ((0, typescript_result_1.isError)(redactResult)) {
                log.error(`Error while trying to redact messages for in ${roomID}:`, eventID, redactResult.error);
            }
        }
        return (0, typescript_result_1.Ok)(undefined);
    }
    async enqueueRedaction(userID, roomID) {
        return await this.queue.enqueue(roomID, userID);
    }
}
exports.TimelineRedactionQueue = TimelineRedactionQueue;
//# sourceMappingURL=TimelineRedactionQueue.js.map