UNPKG

xmppjs-chat-bot

Version:
211 lines 8.23 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Bot = void 0; const read_1 = require("./config/read"); const stanza_1 = require("./stanza"); const jid_1 = require("@xmpp/jid"); const xml_1 = __importDefault(require("@xmpp/xml")); const logger_1 = require("./logger"); const room_1 = require("./room"); const listen_1 = require("./config/listen"); const handlers_directory_1 = require("./handlers_directory"); require('./handlers'); class Bot { constructor(botName, xmpp, logger) { this.rooms = new Map(); this.dirListeners = new Map(); this.botName = botName; this.xmpp = xmpp; this.logger = (0, logger_1.wrapLogger)(botName, logger ?? new logger_1.DefaultLogger()); } static async loadsFromConfigFile(filepath) { const bot = await (0, read_1.getBotFromConfig)(filepath); return bot; } async connect() { this.xmpp.on('error', (err) => { this.logger.error(err); }); this.xmpp.on('offline', () => { this.logger.info(`${this.botName} is now offline.`); }); this.xmpp.on('stanza', (xmppElement) => { const stanza = stanza_1.Stanza.parseIncoming(xmppElement); if (!stanza) { this.logger.error('Failed to initiate a Stanza object from: ' + xmppElement.toString()); return; } this.logger.debug('stanza received: ' + stanza.toString()); if (!stanza.from) { return; } const roomJid = stanza.from.bare(); const room = this.rooms.get(roomJid.toString()); room?.receiveStanza(stanza); }); this.xmpp.on('online', (address) => { this.logger.debug('Online with address ' + address.toString()); this.address = address; this.rooms.forEach(room => { room.reset(); room.join(room.myNick ?? this.botName).then(() => { }, () => { }); }); }); await this.xmpp.start(); } async disconnect() { for (const [dir, callback] of this.dirListeners) { this.logger.debug('Stop listening the configuration directory ' + dir); callback(); } for (const [roomId, room] of this.rooms) { this.logger.debug(`Leaving room ${roomId}...`); await room.detachHandlers(); try { await room.part(); } catch (err) { this.logger.error(err); } } try { await this.xmpp.stop(); } catch (err) { this.logger.error(err); } } async waitOnline() { if (this.xmpp.status === 'online') { this.logger.debug('waitOnline: The bot is already online'); return Promise.resolve(); } this.logger.debug('waitOnline: The bot is not online, waiting...'); const p = new Promise(resolve => { this.xmpp.once('online', () => { this.logger.debug('waitOnline: online event triggered, waitOnline can resolve.'); resolve(); }); }); return p; } async sendStanza(type, attrs, ...children) { if (type !== 'iq') { attrs = Object.assign({ from: this.address?.toString() }, attrs); } const stanza = (0, xml_1.default)(type, attrs, ...children); this.logger.debug('stanza to emit: ' + stanza.toString()); await this.xmpp.send(stanza); } async joinRoom(local, domain, nick) { const roomJID = new jid_1.JID(local, domain); const roomJIDstr = roomJID.toString(); let room = this.rooms.get(roomJIDstr); if (!room) { room = new room_1.Room(this, roomJID); this.rooms.set(roomJIDstr, room); } this.logger.debug('Joining room ' + roomJID.toString()); await room.join(nick); return room; } async partRoom(local, mucDomain) { const roomJID = (new jid_1.JID(local, mucDomain)).toString(); const room = this.rooms.get(roomJID); if (!room) { return; } await room.detachHandlers(); await room.part(); this.rooms.delete(roomJID); } getAddress() { return this.address; } async loadRoomConfDir(dir) { if (this.dirListeners.has(dir)) { this.logger.error('There is already a listener for the dir ' + dir); return; } this.logger.info('Loading and listening conf directory ' + dir + '...'); const w = await (0, listen_1.listenRoomConfDir)(this.logger, dir, async (conf) => { this.logger.debug('(re)Loading a room configuration'); await this.loadRoomConf(conf); }); if (w) { this.dirListeners.set(dir, w); } else { this.logger.error('Failed loading conf directory ' + dir); } } async loadRoomConf(conf) { if (!conf) { return; } const enabled = !!(conf.enabled ?? true); const roomJID = (new jid_1.JID(conf.local, conf.domain)).toString(); this.logger.info('(re)Loading conf for room ' + roomJID + '...'); if (!enabled) { this.logger.debug('Room ' + roomJID + ' is disabled'); if (this.rooms.has(roomJID)) { this.logger.info('Room ' + roomJID + ' disabled, Must leave room ' + roomJID); await this.partRoom(conf.local, conf.domain); } else { this.logger.debug('Room ' + roomJID + ' was not loaded'); } return; } this.logger.debug('Room ' + roomJID + ' is enabled'); const nickname = conf.nick ?? this.botName; if (!this.rooms.has(roomJID)) { this.logger.info('Room enabled, Joining room ' + roomJID); await this.joinRoom(conf.local, conf.domain, nickname); } const room = this.rooms.get(roomJID); if (!room) { this.logger.error('Failed getting the freshly joined room'); return; } const currentNickname = room.myNick; if (currentNickname && nickname !== currentNickname) { this.logger.info('Changing nickname for room ' + roomJID); await room.changeNickname(nickname); } for (const handlerConf of (conf.handlers ?? [])) { const loadedHandler = room.getHandlerById(handlerConf.id); const handlerEnabled = !!(handlerConf.enabled ?? true); if (loadedHandler) { if (handlerEnabled) { this.logger.info('The handler ' + loadedHandler.id + ' was already loaded, reloading its configuration for room ' + roomJID); loadedHandler.loadOptions(handlerConf.options); } else { this.logger.info('The handler ' + loadedHandler.id + ' must be detached for room ' + roomJID); room.detachHandlerById(loadedHandler.id); } continue; } if (!handlerEnabled) { this.logger.debug('The handler ' + handlerConf.id + ' is disabled, and was not loaded for room ' + roomJID); continue; } const HandlerClass = handlers_directory_1.HandlersDirectory.singleton().getClass(handlerConf.type); if (!HandlerClass) { this.logger.error('Can\'t find class for handler type ' + handlerConf.type); continue; } this.logger.info('The handler ' + handlerConf.id + ' must be created and started for room ' + roomJID); const handler = new HandlerClass(handlerConf.id, room, handlerConf.options); await handler.start(); } } } exports.Bot = Bot; //# sourceMappingURL=bot.js.map