@@ -45,7 +45,7 @@ import { authFlow, checkAuthorization } from './auth';
4545import { downloadFile } from './downloadFile' ;
4646import { uploadFile } from './uploadFile' ;
4747
48- import { HttpStreamError } from '../extensions/HttpStream ' ;
48+ import { PermAuthKeyInvalidError } from '../errors/Common ' ;
4949import { generateRandomBigInt , sleep } from '../Helpers' ;
5050import RequestState from '../network/RequestState' ;
5151import Session from '../sessions/Abstract' ;
@@ -201,6 +201,9 @@ class TelegramClient {
201201 private _exportedSenderPromises : Record < number , Record < number , Promise < MTProtoSender > | undefined > > = { } ;
202202 private _exportedSenderRefCounter : Record < number , Record < number , number > > = { } ;
203203 private _waitingForAuthKey : Record < number , Promise < void > | undefined > = { } ;
204+ // Keyed by `dcId` for regular hosts and `-dcId` for media hosts, which only accept temporary keys created for them
205+ private _tempAuthKeys : Record < number , AuthKey | undefined > = { } ;
206+ private _tempAuthKeyPromises : Record < number , Promise < AuthKey > | undefined > = { } ;
204207 private _exportedSenderReleaseTimeouts : Record < number , Record < number , TimeoutId | undefined > > = { } ;
205208 private _loopStarted = false ;
206209 private _isSwitchingDc = false ;
@@ -310,6 +313,9 @@ class TelegramClient {
310313 autoReconnect : this . _autoReconnect ,
311314 connectTimeout : this . _timeout ,
312315 authKeyCallback : this . _authKeyCallback . bind ( this ) ,
316+ getTempAuthKey : this . _getTempAuthKey . bind ( this ) ,
317+ dropTempAuthKey : this . _dropTempAuthKey . bind ( this ) ,
318+ initConnection : this . _initWith ,
313319 updateCallback : this . _handleUpdate . bind ( this ) ,
314320 getShouldDebugExportedSenders : this . getShouldDebugExportedSenders . bind ( this ) ,
315321 isMainSender : true ,
@@ -369,6 +375,13 @@ class TelegramClient {
369375 this . defaultDcId , DC . ipAddress , this . _args . useWSS ? 443 : 80 , this . _args . isTestServerRequested ,
370376 ) ;
371377 }
378+
379+ const { dcId } = this . session ;
380+ if ( dcId in this . _tempAuthKeys ) {
381+ this . session . setTempAuthKey ( this . _tempAuthKeys [ dcId ] ) ;
382+ } else {
383+ this . _tempAuthKeys [ dcId ] = this . session . getTempAuthKey ( ) ;
384+ }
372385 }
373386
374387 setPingCallback ( callback : ( ) => Promise < void > ) {
@@ -535,7 +548,7 @@ class TelegramClient {
535548 // authKey's are associated with a server, which has now changed
536549 // so it's not valid anymore. Set to None to force recreating it.
537550 await this . _sender . authKey . setKey ( undefined ) ;
538- this . session . setAuthKey ( undefined ) ;
551+ this . _resetAuthKey ( newDc ) ;
539552 this . _isSwitchingDc = true ;
540553 this . disconnect ( ) ;
541554 this . _sender = undefined ;
@@ -546,12 +559,59 @@ class TelegramClient {
546559 this . session . setAuthKey ( authKey , dcId ) ;
547560 }
548561
562+ _resetAuthKey ( dcId : number ) {
563+ this . session . setAuthKey ( undefined , dcId ) ;
564+ this . _tempAuthKeyPromises [ dcId ] = undefined ;
565+ this . _tempAuthKeyPromises [ - dcId ] = undefined ;
566+ this . _setTempAuthKey ( dcId , undefined ) ;
567+ this . _setTempAuthKey ( - dcId , undefined ) ;
568+ }
569+
570+ _getTempAuthKey ( clusterId : number , create : ( ) => Promise < AuthKey > , isUsable : ( authKey : AuthKey ) => boolean ) {
571+ const pendingAuthKey = this . _tempAuthKeyPromises [ clusterId ] ;
572+ if ( pendingAuthKey ) return pendingAuthKey ;
573+
574+ const authKey = this . _tempAuthKeys [ clusterId ] ;
575+ if ( authKey && isUsable ( authKey ) ) return Promise . resolve ( authKey ) ;
576+
577+ let isReset = false ;
578+ const creationPromise = create ( ) ;
579+ const promise = creationPromise
580+ . then ( ( newAuthKey ) => {
581+ if ( this . _tempAuthKeyPromises [ clusterId ] !== promise ) {
582+ isReset = true ;
583+ throw new Error ( 'Temporary auth key was reset' ) ;
584+ }
585+
586+ this . _setTempAuthKey ( clusterId , newAuthKey ) ;
587+ return newAuthKey ;
588+ } )
589+ . finally ( ( ) => {
590+ if ( this . _tempAuthKeyPromises [ clusterId ] === promise ) this . _tempAuthKeyPromises [ clusterId ] = undefined ;
591+ } ) ;
592+ this . _tempAuthKeyPromises [ clusterId ] = promise ;
593+ // The creator's bound key remains usable when a reset invalidates the shared promise
594+ return promise . catch ( ( err : unknown ) => {
595+ if ( isReset ) return creationPromise ;
596+ throw err ;
597+ } ) ;
598+ }
599+
600+ _dropTempAuthKey ( clusterId : number , keyId : bigint ) {
601+ if ( this . _tempAuthKeys [ clusterId ] ?. keyId === keyId ) this . _setTempAuthKey ( clusterId , undefined ) ;
602+ }
603+
604+ _setTempAuthKey ( clusterId : number , authKey ?: AuthKey ) {
605+ this . _tempAuthKeys [ clusterId ] = authKey ;
606+ if ( clusterId === this . session . dcId ) this . session . setTempAuthKey ( authKey ) ;
607+ }
608+
549609 // endregion
550610 // export region
551611
552612 async _cleanupExportedSender ( dcId : number , index : number ) {
553613 if ( this . session . dcId !== dcId ) {
554- this . session . setAuthKey ( undefined , dcId ) ;
614+ this . _resetAuthKey ( dcId ) ;
555615 }
556616 // eslint-disable-next-line no-console
557617 if ( this . _shouldDebugExportedSenders ) console . log ( `🧹 Cleanup idx=${ index } dcId=${ dcId } ` ) ;
@@ -573,11 +633,10 @@ class TelegramClient {
573633 await this . _waitingForAuthKey [ dcId ] ;
574634
575635 const authKey = this . session . getAuthKey ( dcId ) ;
576- const replacementKey = authKey ?. getKey ( ) ;
577636
578- hasAuthKey = Boolean ( replacementKey ) ;
637+ hasAuthKey = Boolean ( authKey ?. getKey ( ) ) ;
579638 if ( hasAuthKey ) {
580- await sender . authKey . setKey ( replacementKey ) ;
639+ await sender . authKey . setKey ( authKey ) ;
581640 }
582641 } else {
583642 this . _waitingForAuthKey [ dcId ] = new Promise ( ( resolve ) => {
@@ -597,13 +656,15 @@ class TelegramClient {
597656 isTestServer : this . session . isTestServer ,
598657 // Premium DCs are not stable for obtaining auth keys, so need to we first connect to regular ones
599658 isPremium : hasAuthKey ? isPremium : false ,
659+ isMediaDc : hasAuthKey ,
600660 } ) , false , new this . _fallbackConnection ( {
601661 ip : dc . ipAddress ,
602662 port : dc . port ,
603663 dcId,
604664 loggers : this . _log ,
605665 isTestServer : this . session . isTestServer ,
606666 isPremium : hasAuthKey ? isPremium : false ,
667+ isMediaDc : hasAuthKey ,
607668 } ) ) ;
608669
609670 if ( this . session . dcId !== dcId && ! sender . _authenticated ) {
@@ -639,14 +700,13 @@ class TelegramClient {
639700
640701 return sender ;
641702 } catch ( err : any ) {
642- if ( err instanceof HttpStreamError && err . status === 404 && this . session . dcId !== dcId ) {
703+ if ( err instanceof PermAuthKeyInvalidError && this . session . dcId !== dcId ) {
643704 const pendingAuthKey = this . _waitingForAuthKey [ dcId ] ;
644705 if ( pendingAuthKey && ! firstConnectResolver ) {
645706 await pendingAuthKey ;
646707 const authKey = this . session . getAuthKey ( dcId ) ;
647- const replacementKey = authKey ?. getKey ( ) ;
648- if ( replacementKey && authKey !== sender . authKey ) {
649- await sender . authKey . setKey ( replacementKey ) ;
708+ if ( authKey ?. getKey ( ) && authKey !== sender . authKey ) {
709+ await sender . authKey . setKey ( authKey ) ;
650710 }
651711 hasAuthKey = Boolean ( sender . authKey . getKey ( ) ) ;
652712 } else if ( sender . authKey . getKey ( ) ) {
@@ -657,7 +717,7 @@ class TelegramClient {
657717 }
658718
659719 await sender . authKey . setKey ( undefined ) ;
660- this . session . setAuthKey ( undefined , dcId ) ;
720+ this . _resetAuthKey ( dcId ) ;
661721 sender . _authenticated = false ;
662722 hasAuthKey = false ;
663723 }
@@ -683,7 +743,7 @@ class TelegramClient {
683743
684744 await sleep ( 1000 ) ;
685745 sender . disconnect ( ) ;
686- if ( err instanceof HttpStreamError && err . status === 404 && this . session . dcId === dcId && hasAuthKey ) {
746+ if ( err instanceof PermAuthKeyInvalidError && this . session . dcId === dcId ) {
687747 throw err ;
688748 }
689749 }
@@ -814,6 +874,9 @@ class TelegramClient {
814874 autoReconnect : this . _autoReconnect ,
815875 connectTimeout : this . _timeout ,
816876 authKeyCallback : this . _authKeyCallback . bind ( this ) ,
877+ getTempAuthKey : this . _getTempAuthKey . bind ( this ) ,
878+ dropTempAuthKey : this . _dropTempAuthKey . bind ( this ) ,
879+ initConnection : this . _initWith ,
817880 isMainSender : dcId === this . session . dcId ,
818881 isExported : true ,
819882 updateCallback : this . _handleUpdate . bind ( this ) ,
0 commit comments