tgsnake
Version:
Telegram MTProto framework for nodejs.
348 lines (347 loc) • 17.6 kB
JavaScript
;
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;