import { Api } from "../tl" ; import { RequestIter } from "../requestIter" ; import { TelegramClient , utils } from "../index" ; import { Dialog } from "../tl/custom/dialog" ; import { DateLike , EntityLike } from "../define" ; import { TotalList } from "../Helpers" ; import bigInt from "big-integer" ; import { LogLevel } from "../extensions/Logger" ; const _MAX_CHUNK_SIZE = 100 ; param { Api . TypePeer } peer param { number } messageId return { [ number , number ] } function _dialogMessageKey ( peer , messageId ) { return ( "" + [ peer instanceof Api . PeerChannel ? peer . channelId : undefined , messageId , ] ) ; } export interface DialogsIterInterface { offsetDate : number ; offsetId : number ; offsetPeer : Api . TypePeer ; ignorePinned : boolean ; ignoreMigrated : boolean ; folder : number ; } export class _DialogsIter extends RequestIter { private request ? : Api . messages . GetDialogs ; private seen ? : Set < any > ; private offsetDate ? : number ; private ignoreMigrated ? : boolean ; async _init ( { offsetDate , offsetId , offsetPeer , ignorePinned , ignoreMigrated , folder , } ) { this . request = new Api . messages . GetDialogs ( { offsetDate , offsetId , offsetPeer , limit : 1 , hash : bigInt . zero , excludePinned : ignorePinned , folderId : folder , } ) ; if ( this . limit <= 0 ) { const dialogs = await this . client . invoke ( this . request ) ; if ( "count" in dialogs ) { this . total = dialogs . count ; } else { this . total = dialogs . dialogs . length ; } return true ; } this . seen = new Set ( ) ; this . offsetDate = offsetDate ; this . ignoreMigrated = ignoreMigrated ; } [ Symbol . asyncIterator ] ( ) { return super [ Symbol . asyncIterator ] ( ) ; } async _loadNextChunk ( ) { if ( ! this . request || ! this . seen || ! this . buffer ) { return ; } this . request . limit = Math . min ( this . left , _MAX_CHUNK_SIZE ) ; const r = await this . client . invoke ( this . request ) ; if ( r instanceof Api . messages . DialogsNotModified ) { return ; } if ( "count" in r ) { this . total = r . count ; } else { this . total = r . dialogs . length ; } const entities = new Map < string , Api . TypeUser | Api . TypeChat > ( ) ; const messages = new Map < string , Api . Message > ( ) ; for ( const entity of [ ... r . users , ... r . chats ] ) { if ( entity instanceof Api . UserEmpty || entity instanceof Api . ChatEmpty ) { continue ; } entities . set ( utils . getPeerId ( entity ) , entity ) ; } for ( const m of r . messages ) { let message = m as unknown as Api . Message ; try { message . _finishInit ( this . client , entities , undefined ) ; } catch ( e ) { this . client . _log . error ( "Got error while trying to finish init message with id " + m . id ) ; if ( this . client . _log . canSend ( LogLevel . ERROR ) ) { console . error ( e ) ; } } messages . set ( _dialogMessageKey ( message . peerId ! , message . id ) , message ) ; } for ( const d of r . dialogs ) { if ( d instanceof Api . DialogFolder ) { continue ; } const message = messages . get ( _dialogMessageKey ( d . peer , d . topMessage ) ) ; if ( this . offsetDate != undefined ) { const date = message ?. date ! ; if ( date == undefined || date > this . offsetDate ) { continue ; } } const peerId = utils . getPeerId ( d . peer ) ; if ( ! this . seen . has ( peerId ) ) { this . seen . add ( peerId ) ; if ( ! entities . has ( peerId ) ) { continue ; } const cd = new Dialog ( this . client , d , entities , message ) ; if ( ! this . ignoreMigrated || ( cd . entity != undefined && "migratedTo" in cd . entity ) ) { this . buffer . push ( cd ) ; } } } if ( r . dialogs . length < this . request . limit || ! ( r instanceof Api . messages . DialogsSlice ) ) { return true ; } let lastMessage ; for ( let dialog of r . dialogs . reverse ( ) ) { lastMessage = messages . get ( _dialogMessageKey ( dialog . peer , dialog . topMessage ) ) ; if ( lastMessage ) { break ; } } this . request . excludePinned = true ; this . request . offsetId = lastMessage ? lastMessage . id : 0 ; this . request . offsetDate = lastMessage ? lastMessage . date ! : 0 ; this . request . offsetPeer = this . buffer [ this . buffer . length - 1 ] . inputEntity ; } } /** interface for iterating and getting dialogs. */ export interface IterDialogsParams { /**  How many dialogs to be retrieved as maximum. Can be set to undefined to retrieve all dialogs.<br/>
     * Note that this may take whole minutes if you have hundreds of dialogs, as Telegram will tell the library to slow down through a FloodWaitError.*/ limit ? : number ; /** The offset date of last message of dialog to be used. */ offsetDate ? : DateLike ; /** The message ID to be used as offset. */ offsetId ? : number ; /** offset Peer to be used (defaults to Empty = no offset) */ offsetPeer ? : EntityLike ; /** Whether pinned dialogs should be ignored or not. When set to true, these won't be yielded at all. */ ignorePinned ? : boolean ; /**  Whether Chat that have migratedTo a Supergroup should be included or not.<br/>
     * By default all the chats in your dialogs are returned, but setting this to True will ignore (i.e. skip) them in the same way official applications do.*/ ignoreMigrated ? : boolean ; /** The folder from which the dialogs should be retrieved.<br/>
     * If left unspecified, all dialogs (including those from folders) will be returned.<br/>
     * If set to 0, all dialogs that don't belong to any folder will be returned.<br/>
     * If set to a folder number like 1, only those from said folder will be returned.<br/>
     * By default Telegram assigns the folder ID 1 to archived chats, so you should use that if you need to fetch the archived dialogs.<br/> */ folder ? : number ; /**  Alias for folder. If unspecified, all will be returned, false implies `folder:0` and True implies `folder:1`.*/ archived ? : boolean ; } hidden export function iterDialogs ( client , { limit = undefined , offsetDate = undefined , offsetId = 0 , offsetPeer = new Api . InputPeerEmpty ( ) , ignorePinned = false , ignoreMigrated = false , folder = undefined , archived = undefined , } ) { if ( archived != undefined ) { folder = archived ? 1 : 0 ; } return new _DialogsIter ( client , limit , { } , { offsetDate , offsetId , offsetPeer , ignorePinned , ignoreMigrated , folder , } ) ; } hidden export async function getDialogs ( client , params ) { return ( await client . iterDialogs ( params ) . collect ( ) ) as TotalList < Dialog > ; }