UNPKG

tgsnake

Version:

Telegram MTProto framework for nodejs.

348 lines (347 loc) 17.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.MainContext = void 0; const platform_node_js_1 = require("../platform.node.js"); const Composer_js_1 = require("./Composer.js"); const Logger_js_1 = require("./Logger.js"); const Update_js_1 = require("../TL/Updates/Update.js"); const Utilities_js_1 = require("../Utilities.js"); const index_js_1 = require("../Plugins/index.js"); const manager_js_1 = require("../Conversation/manager.js"); class MainContext extends Composer_js_1.Composer { _errorHandler = (error, update) => { Logger_js_1.Logger.error(`Snake error (${error.message}) when processing update :`); Logger_js_1.Logger.error(update); throw error; }; _plugin = new index_js_1.TgsnakeApi(); _localPtsChat = new Map(); _commonBox = new Map(); _conversation = new manager_js_1.ConversationManager(); constructor() { super(); this.use(this._conversation); } async handleUpdate(update, client) { if (!update) return false; if (this._plugin.getEventHandler('beforeParseUpdate').length) { Logger_js_1.Logger.debug(`Running ${this._plugin.getEventHandler('beforeParseUpdate').length} before parse update handler plugin.`); this._plugin.getEventHandler('beforeParseUpdate').forEach((plugin) => { try { return plugin({ client, update }); } catch (error) { Logger_js_1.Logger.error(`Failed to running plug-in (beforeParseUpdate) ${plugin.name}`, error); } }); } Logger_js_1.Logger.debug(`Receive update: ${update.className}`); this.use = () => { throw new Error(`bot.use is unavailable when bot running. so kill bot first then add bot.use in your source code then running again.`); }; if (this._plugin.getEventHandler('onParseUpdate').length) { Logger_js_1.Logger.debug(`Running ${this._plugin.getEventHandler('onParseUpdate').length} on parse update handler plugin, it will replace the default update parser.`); const parsed = []; this._plugin.getEventHandler('onParseUpdate').forEach(async (plugin) => { try { return parsed.push(...(await plugin({ client, update }))); } catch (error) { Logger_js_1.Logger.error(`Failed to running plug-in (onParseUpdate) ${plugin.name}`, error); } }); for (const _update of parsed) { try { await (0, Composer_js_1.run)(this.middleware(), _update); } catch (error) { return this._errorHandler(error, _update); } } } else { const parsed = await this.parseUpdate(update, client); for (const _update of parsed) { try { await (0, Composer_js_1.run)(this.middleware(), _update); } catch (error) { return this._errorHandler(error, _update); } } } if (this._plugin.getEventHandler('afterParseUpdate').length) { Logger_js_1.Logger.debug(`Running ${this._plugin.getEventHandler('afterParseUpdate').length} after parse update handler plugin.`); this._plugin.getEventHandler('afterParseUpdate').forEach((plugin) => { try { return plugin({ client, update }); } catch (error) { Logger_js_1.Logger.error(`Failed to running plug-in (afterParseUpdate) ${plugin.name}`, error); } }); } } async parseUpdate(update, client) { const parsedUpdate = []; if (update instanceof platform_node_js_1.Raw.Updates || update instanceof platform_node_js_1.Raw.UpdatesCombined) { const { updates, chats, users } = update; if ('seq' in update) { this._commonBox.set('seq', update.seq); this._commonBox.set('date', update.date); } for (const _update of updates) { if ('pts' in _update) { const _channelId = (0, Utilities_js_1.getChannelId)(_update); if (_channelId !== BigInt(0)) { this._localPtsChat.set(_channelId, [ _update.pts, Date.now(), client._options.experimental.syncTimeout ?? 30000, ]); } else { this._commonBox.set('pts', _update.pts); } } if ('qts' in _update) { this._commonBox.set('qts', _update.qts); } if (_update instanceof platform_node_js_1.Raw.UpdateChannelTooLong) { Logger_js_1.Logger.debug(`Got ${_update.className}`, _update); const _channelId = (0, Utilities_js_1.getChannelId)(_update); if (_channelId !== BigInt(0)) { Logger_js_1.Logger.debug(`Looping GetChannelDifference`); const execGetDiff = async () => { const _localPts = this._localPtsChat.get(_channelId); if (_localPts) { try { const diff = await client.api.invoke(new platform_node_js_1.Raw.updates.GetChannelDifference({ channel: await client._client.resolvePeer(_channelId), filter: new platform_node_js_1.Raw.ChannelMessagesFilterEmpty(), pts: _localPts[0], limit: 100, })); if (!diff) { Logger_js_1.Logger.error(`Failed to getChannelDifference cause: results undefined`); return; } if (diff instanceof platform_node_js_1.Raw.updates.ChannelDifferenceTooLong) { this._localPtsChat.set(_channelId, [ diff.dialog .pts, Date.now(), client._options.experimental.syncTimeout ?? 30000, ]); } else { this._localPtsChat.set(_channelId, [ diff.pts, Date.now(), client._options.experimental.syncTimeout ?? 30000, ]); } if (diff instanceof platform_node_js_1.Raw.updates.ChannelDifferenceEmpty) { Logger_js_1.Logger.debug(`Skipped getChannelDifference results due to empty difference`); } parsedUpdate.push(...(await this.processChannelDifference(client, diff))); if (!diff.final) { return execGetDiff(); } Logger_js_1.Logger.debug(`Escaping loop getChannelDifference`); } catch (error) { Logger_js_1.Logger.error(`Failed to getChannelDifference cause: error`, error); return; } } else { Logger_js_1.Logger.debug(`Escaping loop getChannelDifference due to no localPts`); return; } }; execGetDiff(); } else { Logger_js_1.Logger.debug(`Skipped update: ${_update.className}`); } } else if (_update instanceof platform_node_js_1.Raw.UpdatesTooLong) { Logger_js_1.Logger.debug(`Got ${_update.className}`, _update); } else { let _up = await Update_js_1.Update.parse(client, _update, chats, users); if (_up) parsedUpdate.push(_up); } } } else if (update instanceof platform_node_js_1.Raw.UpdateShortMessage || update instanceof platform_node_js_1.Raw.UpdateShortChatMessage) { const difference = await client.api.invoke(new platform_node_js_1.Raw.updates.GetDifference({ pts: update.pts - update.ptsCount, date: update.date, qts: -1, })); parsedUpdate.push(...(await this.processDifference(client, difference))); } else if (update instanceof platform_node_js_1.Raw.UpdateShort) { if (update.update instanceof platform_node_js_1.Raw.UpdateUserStatus) { if (update.update.userId === client._me.id && !client._me.bot) { if (update.update.status instanceof platform_node_js_1.Raw.UserStatusOffline && client._options.experimental.alwaysOnline) { await client._client.invoke(new platform_node_js_1.Raw.account.UpdateStatus({ offline: false })); } } } let _up = await Update_js_1.Update.parse(client, update.update, [], []); if (_up) parsedUpdate.push(_up); } parsedUpdate.push(update); return parsedUpdate; } syncChannelUpdate(client) { return async () => { if (client._options.experimental.alwaysSync) { for (const [channelId, ptsInfo] of this._localPtsChat) { if (Date.now() - ptsInfo[1] > (ptsInfo[2] ?? 30000)) { const parsedUpdate = []; Logger_js_1.Logger.debug(`Looping GetChannelDifference`); const execGetDiff = async () => { const _localPts = this._localPtsChat.get(channelId); if (_localPts) { try { const diff = await client.api.invoke(new platform_node_js_1.Raw.updates.GetChannelDifference({ channel: await client._client.resolvePeer(channelId), filter: new platform_node_js_1.Raw.ChannelMessagesFilterEmpty(), pts: _localPts[0], limit: 100, })); if (!diff) { Logger_js_1.Logger.error(`Failed to getChannelDifference cause: results undefined`); return; } if (diff instanceof platform_node_js_1.Raw.updates.ChannelDifferenceTooLong) { this._localPtsChat.set(channelId, [ diff.dialog .pts, Date.now(), client._options.experimental.syncTimeout ?? diff.timeout ?? 30000, ]); } else { this._localPtsChat.set(channelId, [ diff.pts, Date.now(), client._options.experimental.syncTimeout ?? diff.timeout ?? 30000, ]); } if (diff instanceof platform_node_js_1.Raw.updates.ChannelDifferenceEmpty) { Logger_js_1.Logger.debug(`Skipped getChannelDifference results due to empty difference`); } parsedUpdate.push(...(await this.processChannelDifference(client, diff))); if (!diff.final) { return execGetDiff(); } Logger_js_1.Logger.debug(`Escaping loop getChannelDifference`); } catch (error) { Logger_js_1.Logger.error(`Failed to getChannelDifference cause: error`, error); return; } } else { Logger_js_1.Logger.debug(`Escaping loop getChannelDifference due to no localPts`); return; } }; await execGetDiff(); for (const _update of parsedUpdate) { try { await (0, Composer_js_1.run)(this.middleware(), _update); } catch (error) { return this._errorHandler(error, _update); } } } } setTimeout(this.syncChannelUpdate(client), client._options.experimental.syncEvery); } }; } async processDifference(client, difference) { const parsedUpdate = []; if (difference instanceof platform_node_js_1.Raw.updates.Difference || difference instanceof platform_node_js_1.Raw.updates.DifferenceSlice) { const { newMessages, otherUpdates, chats, users } = difference; if (newMessages) { for (const newMessage of newMessages) { let _up = await Update_js_1.Update.parse(client, new platform_node_js_1.Raw.UpdateNewMessage({ message: newMessage, pts: 0, ptsCount: 0, }), chats, users); if (_up) parsedUpdate.push(_up); } } else if (otherUpdates) { for (const otherUpdate of otherUpdates) { let _up = await Update_js_1.Update.parse(client, otherUpdate, chats, users); if (_up) parsedUpdate.push(_up); } } } return parsedUpdate; } async processChannelDifference(client, difference) { const parsedUpdate = []; if (difference instanceof platform_node_js_1.Raw.updates.ChannelDifference) { const { newMessages, otherUpdates, chats, users } = difference; if (newMessages) { for (const newMessage of newMessages) { let _up = await Update_js_1.Update.parse(client, new platform_node_js_1.Raw.UpdateNewMessage({ message: newMessage, pts: 0, ptsCount: 0, }), chats, users); if (_up) parsedUpdate.push(_up); } } else if (otherUpdates) { for (const otherUpdate of otherUpdates) { let _up = await Update_js_1.Update.parse(client, otherUpdate, chats, users); if (_up) parsedUpdate.push(_up); } } } if (difference instanceof platform_node_js_1.Raw.updates.ChannelDifferenceTooLong) { const { messages, chats, users } = difference; if (messages) { for (const message of messages) { let _up = await Update_js_1.Update.parse(client, new platform_node_js_1.Raw.UpdateNewMessage({ message: message, pts: 0, ptsCount: 0, }), chats, users); if (_up) parsedUpdate.push(_up); } } } return parsedUpdate; } catch(errorHandler) { if (typeof errorHandler === 'function') { this._errorHandler = errorHandler; } return; } } exports.MainContext = MainContext;