feat(core): more customization in updates handling

This commit is contained in:
alina 🌸 2024-06-15 08:35:35 +03:00
parent 81f8ea9fd2
commit f5f825a3a6
Signed by: teidesu
SSH key fingerprint: SHA256:uNeCpw6aTSU4aIObXLvHfLkDa82HWH9EiOj9AXOIRpI
2 changed files with 78 additions and 18 deletions

View file

@ -140,6 +140,9 @@ export class UpdatesManager {
private _onCatchingUp: (catchingUp: boolean) => void = () => {} private _onCatchingUp: (catchingUp: boolean) => void = () => {}
// eslint-disable-next-line @typescript-eslint/ban-types
private _channelPtsLimit: Extract<UpdatesManagerParams['channelPtsLimit'], Function>
auth?: CurrentUserInfo | null // todo: do we need a local copy? auth?: CurrentUserInfo | null // todo: do we need a local copy?
keepAliveInterval?: NodeJS.Timeout keepAliveInterval?: NodeJS.Timeout
@ -160,6 +163,17 @@ export class UpdatesManager {
this.log = client.log.create('updates') this.log = client.log.create('updates')
this.catchUpOnStart = params.catchUp ?? false this.catchUpOnStart = params.catchUp ?? false
this.noDispatchEnabled = !params.disableNoDispatch 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 { setHandler(handler: RawUpdateHandler): void {
@ -815,7 +829,7 @@ export class UpdatesManager {
// to make TS happy // to make TS happy
let pts = _pts let pts = _pts
let limit = this.auth?.isBot ? 100000 : 100 let limit = this._channelPtsLimit(channelId)
if (pts <= 0) { if (pts <= 0) {
pts = 1 pts = 1
@ -834,7 +848,11 @@ export class UpdatesManager {
filter: { _: 'channelMessagesFilterEmpty' }, 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') { if (diff._ === 'updates.channelDifferenceEmpty') {
log.debug('getChannelDifference (cid = %d) returned channelDifferenceEmpty', channelId) log.debug('getChannelDifference (cid = %d) returned channelDifferenceEmpty', channelId)
@ -848,25 +866,29 @@ export class UpdatesManager {
pts = diff.dialog.pts! pts = diff.dialog.pts!
} }
log.warn( if (this.params.onChannelTooLong) {
'getChannelDifference (cid = %d) returned channelDifferenceTooLong. new pts: %d, recent msgs: %d', this.params.onChannelTooLong(channelId, diff)
channelId, } else {
pts, log.warn(
diff.messages.length, 'getChannelDifference (cid = %d) returned channelDifferenceTooLong. new pts: %d, recent msgs: %d',
)
diff.messages.forEach((message) => {
log.debug(
'processing message %d (%s) from TooLong diff for channel %d',
message.id,
message._,
channelId, 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 break
} }

View file

@ -13,7 +13,7 @@ import { PeersIndex } from '../types/peers/peers-index.js'
export type RawUpdateHandler = (upd: tl.TypeUpdate, peers: PeersIndex) => void export type RawUpdateHandler = (upd: tl.TypeUpdate, peers: PeersIndex) => void
/** /**
* Parameters for {@link enableUpdatesProcessing} * Parameters for the updates manager
*/ */
export interface UpdatesManagerParams { export interface UpdatesManagerParams {
/** /**
@ -44,6 +44,44 @@ export interface UpdatesManagerParams {
*/ */
disableNoDispatch?: boolean 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. * Whether to catch up with missed updates when starting updates loop.
* *