diff --git a/packages/core/src/highlevel/updates/manager.ts b/packages/core/src/highlevel/updates/manager.ts index c79b3e5e..01c60aa5 100644 --- a/packages/core/src/highlevel/updates/manager.ts +++ b/packages/core/src/highlevel/updates/manager.ts @@ -140,6 +140,9 @@ export class UpdatesManager { private _onCatchingUp: (catchingUp: boolean) => void = () => {} + // eslint-disable-next-line @typescript-eslint/ban-types + private _channelPtsLimit: Extract + auth?: CurrentUserInfo | null // todo: do we need a local copy? keepAliveInterval?: NodeJS.Timeout @@ -160,6 +163,17 @@ export class UpdatesManager { this.log = client.log.create('updates') this.catchUpOnStart = params.catchUp ?? false this.noDispatchEnabled = !params.disableNoDispatch + + if (params.channelPtsLimit) { + if (typeof params.channelPtsLimit === 'function') { + this._channelPtsLimit = params.channelPtsLimit + } else { + const limit = params.channelPtsLimit + this._channelPtsLimit = () => limit + } + } else { + this._channelPtsLimit = () => (this.auth?.isBot ? 100000 : 100) + } } setHandler(handler: RawUpdateHandler): void { @@ -815,7 +829,7 @@ export class UpdatesManager { // to make TS happy let pts = _pts - let limit = this.auth?.isBot ? 100000 : 100 + let limit = this._channelPtsLimit(channelId) if (pts <= 0) { pts = 1 @@ -834,7 +848,11 @@ export class UpdatesManager { filter: { _: 'channelMessagesFilterEmpty' }, }) - if (diff.timeout) lastTimeout = diff.timeout + if (diff.timeout) { + lastTimeout = this.params.overrideOpenChatTimeout ? + this.params.overrideOpenChatTimeout(diff) : + diff.timeout + } if (diff._ === 'updates.channelDifferenceEmpty') { log.debug('getChannelDifference (cid = %d) returned channelDifferenceEmpty', channelId) @@ -848,25 +866,29 @@ export class UpdatesManager { pts = diff.dialog.pts! } - log.warn( - 'getChannelDifference (cid = %d) returned channelDifferenceTooLong. new pts: %d, recent msgs: %d', - channelId, - pts, - diff.messages.length, - ) - - diff.messages.forEach((message) => { - log.debug( - 'processing message %d (%s) from TooLong diff for channel %d', - message.id, - message._, + if (this.params.onChannelTooLong) { + this.params.onChannelTooLong(channelId, diff) + } else { + log.warn( + 'getChannelDifference (cid = %d) returned channelDifferenceTooLong. new pts: %d, recent msgs: %d', channelId, + pts, + diff.messages.length, ) - if (message._ === 'messageEmpty') return + diff.messages.forEach((message) => { + log.debug( + 'processing message %d (%s) from TooLong diff for channel %d', + message.id, + message._, + channelId, + ) - pendingUnorderedUpdates.pushBack(toPendingUpdate(messageToUpdate(message), peers, true)) - }) + if (message._ === 'messageEmpty') return + + pendingUnorderedUpdates.pushBack(toPendingUpdate(messageToUpdate(message), peers, true)) + }) + } break } diff --git a/packages/core/src/highlevel/updates/types.ts b/packages/core/src/highlevel/updates/types.ts index 95b688d2..aa37336d 100644 --- a/packages/core/src/highlevel/updates/types.ts +++ b/packages/core/src/highlevel/updates/types.ts @@ -13,7 +13,7 @@ import { PeersIndex } from '../types/peers/peers-index.js' export type RawUpdateHandler = (upd: tl.TypeUpdate, peers: PeersIndex) => void /** - * Parameters for {@link enableUpdatesProcessing} + * Parameters for the updates manager */ export interface UpdatesManagerParams { /** @@ -44,6 +44,44 @@ export interface UpdatesManagerParams { */ disableNoDispatch?: boolean + /** + * **ADVANCED** + * + * PTS limit for `getChannelDifference` requests (max. 100000). + * When there are more updates than this limit, the library will + * skip some of them. + * According to the [official docs](https://core.telegram.org/method/updates.getChannelDifference), + * "Ordinary (non-bot) users are supposed to pass `10-100`", so passing >100 + * for users may lead to issues. + * + * @default 100 for users, 100000 for bots + */ + channelPtsLimit?: number | ((channelId: number) => number) + + /** + * **ADVANCED** + * + * Whenever an `updates.channelDifferenceTooLong` is received, + * the library isn't able to efficiently handle it on its own, + * and will call this function for you to handle it instead. + * + * [See docs](https://core.telegram.org/constructor/updates.channelDifferenceTooLong) + */ + onChannelTooLong?: (channelId: number, update: tl.updates.RawChannelDifferenceTooLong) => void + + /** + * **ADVANCED** + * + * When `openChat` method is used on a client, the library will + * set up a timer to periodically fetch the new updates. + * By default, it will respect the value provided by the server, + * but it some cases you may want to override it (e.g. decrease it to + * poll more often and potentially get updates faster). + * + * The returned value is treated as seconds. + */ + overrideOpenChatTimeout?: (upd: tl.updates.TypeChannelDifference) => number + /** * Whether to catch up with missed updates when starting updates loop. *