UNPKG

dograma

Version:

NodeJS/Browser MTProto API Telegram client library,

129 lines (117 loc) 3.86 kB
import { MessageContainer } from "../tl/core"; import { TLMessage } from "../tl/core"; import { BinaryWriter } from "./BinaryWriter"; import type { MTProtoState } from "../network/MTProtoState"; import type { RequestState } from "../network/RequestState"; export class MessagePacker { private _state: MTProtoState; private _pendingStates: RequestState[]; private _queue: any[]; private _ready: Promise<unknown>; private setReady: ((value?: any) => void) | undefined; private _log: any; constructor(state: MTProtoState, logger: any) { this._state = state; this._queue = []; this._pendingStates = []; this._ready = new Promise((resolve) => { this.setReady = resolve; }); this._log = logger; } values() { return this._queue; } append(state: RequestState) { this._queue.push(state); if (this.setReady) { this.setReady(true); } } extend(states: RequestState[]) { for (const state of states) { this.append(state); } } async get() { if (!this._queue.length) { this._ready = new Promise((resolve) => { this.setReady = resolve; }); await this._ready; } let data; let buffer = new BinaryWriter(Buffer.alloc(0)); const batch = []; let size = 0; while ( this._queue.length && batch.length <= MessageContainer.MAXIMUM_LENGTH ) { const state = this._queue.shift(); size += state.data.length + TLMessage.SIZE_OVERHEAD; if (size <= MessageContainer.MAXIMUM_SIZE) { let afterId; if (state.after) { afterId = state.after.msgId; } state.msgId = await this._state.writeDataAsMessage( buffer, state.data, state.request.classType === "request", afterId ); this._log.debug( `Assigned msgId = ${state.msgId} to ${ state.request.className || state.request.constructor.name }` ); batch.push(state); continue; } if (batch.length) { this._queue.unshift(state); break; } this._log.warn( `Message payload for ${ state.request.className || state.request.constructor.name } is too long ${state.data.length} and cannot be sent` ); state.promise.reject("Request Payload is too big"); size = 0; } if (!batch.length) { return null; } if (batch.length > 1) { const b = Buffer.alloc(8); b.writeUInt32LE(MessageContainer.CONSTRUCTOR_ID, 0); b.writeInt32LE(batch.length, 4); data = Buffer.concat([b, buffer.getValue()]); buffer = new BinaryWriter(Buffer.alloc(0)); const containerId = await this._state.writeDataAsMessage( buffer, data, false ); for (const s of batch) { s.containerId = containerId; } } data = buffer.getValue(); return { batch, data }; } rejectAll() { this._pendingStates.forEach((requestState) => { requestState.reject( new Error( "Disconnect (caused from " + requestState?.request?.className + ")" ) ); }); } }