UNPKG

xmppjs-chat-bot

Version:
115 lines 4.64 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.HandlerNoDuplicate = void 0; const abstract_1 = require("./abstract"); const handlers_directory_1 = require("../handlers_directory"); const DEFAULT_DELAY_SECONDS = 60; const PRUNE_DELAY_SECONDS = 5 * 60; class HandlerNoDuplicate extends abstract_1.Handler { constructor(id, room, options) { super(id, room, options); this.userMessages = new Map(); this.delay ?? (this.delay = DEFAULT_DELAY_SECONDS * 1000); this.applyToModerators ?? (this.applyToModerators = false); this.roomMessageListener = (stanza, fromUser) => { try { this.roomMessage(stanza, fromUser); } catch (err) { if (err instanceof Error) { this.logger.error(err.name + ': ' + err.message); } else { this.logger.error(err); } } }; } loadOptions(options) { if (!options || typeof options !== 'object') { return; } if (('applyToModerators' in options) && (typeof options.applyToModerators === 'boolean')) { this.applyToModerators = options.applyToModerators; } if (('delay' in options) && (options.delay === undefined || (typeof options.delay === 'number'))) { const newDelay = (options.delay ?? DEFAULT_DELAY_SECONDS) * 1000; this.delay = newDelay; } if (('reason' in options) && (options.reason === undefined || (typeof options.reason === 'string'))) { this.reason = options.reason; } } roomMessage(stanza, fromUser) { let content = stanza.body(); if (!content) { return; } content = this.normalizeMessage(content); const userKey = stanza.occupantId() ?? fromUser.jid.toString(); let messages = this.userMessages.get(userKey); if (!messages) { messages = new Map(); this.userMessages.set(userKey, messages); } const lastSent = messages.get(content); const now = Date.now(); messages.set(content, now); if (!lastSent) { return; } const limit = now - this.delay; if (lastSent < limit) { return; } this.logger.debug(`user ${userKey} has already sent a similar messages at ${lastSent}, which is after ${limit}`); if (!this.applyToModerators && fromUser.isModerator()) { this.logger.debug(`Ignoring the no-duplicate rule, as the user ${userKey} is moderator.`); return; } this.room.moderateMessage(stanza, this.reason).catch((err) => { this.logger.error(err); }); } normalizeMessage(s) { return s.replace('\n', ' ').trim().replace(/\s\s+/g, ' ').toLocaleLowerCase(); } pruneUserMessages() { const timestamp = Date.now() - this.delay; const dateStr = (new Date(timestamp)).toISOString(); this.logger.debug(`Pruning user messages with timestamp older than ${timestamp.toString()} (<= ${dateStr})...`); this.userMessages.forEach((messages, userKey) => { this.logger.debug('Pruning user ' + userKey + ' messages...'); messages.forEach((msgTimestamp, content) => { if (msgTimestamp >= timestamp) { return; } this.logger.debug('Pruning a message sent at ' + msgTimestamp.toString()); messages.delete(content); }); if (messages.size === 0) { this.logger.debug(`User ${userKey} has no more message in their map, deleting it.`); this.userMessages.delete(userKey); } }); this.logger.debug('Prune is finished.'); } start() { this.room.on('room_message', this.roomMessageListener); if (this.pruneTimeout) { clearInterval(this.pruneTimeout); } this.pruneTimeout = setInterval(() => { this.pruneUserMessages(); }, PRUNE_DELAY_SECONDS * 1000); } stop() { this.room.off('room_message', this.roomMessageListener); if (this.pruneTimeout) { clearInterval(this.pruneTimeout); this.pruneTimeout = undefined; } this.userMessages.clear(); } } exports.HandlerNoDuplicate = HandlerNoDuplicate; handlers_directory_1.HandlersDirectory.singleton().register('no-duplicate', HandlerNoDuplicate); //# sourceMappingURL=no-duplicate.js.map