|
|
@ -40,6 +40,7 @@ import rootScope from '../rootScope'; |
|
|
|
/// #if MTPROTO_AUTO
|
|
|
|
/// #if MTPROTO_AUTO
|
|
|
|
import transportController from './transports/controller'; |
|
|
|
import transportController from './transports/controller'; |
|
|
|
import MTTransport from './transports/transport'; |
|
|
|
import MTTransport from './transports/transport'; |
|
|
|
|
|
|
|
import { pause } from '../../helpers/schedulers/pause'; |
|
|
|
/// #endif
|
|
|
|
/// #endif
|
|
|
|
|
|
|
|
|
|
|
|
/* var networker = apiManager.cachedNetworkers.websocket.upload[2]; |
|
|
|
/* var networker = apiManager.cachedNetworkers.websocket.upload[2]; |
|
|
@ -407,7 +408,7 @@ export class ApiManager { |
|
|
|
}); |
|
|
|
}); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private changeNetworkerTransport(networker: MTPNetworker, transport: MTTransport) { |
|
|
|
private changeNetworkerTransport(networker: MTPNetworker, transport?: MTTransport) { |
|
|
|
const oldTransport = networker.transport; |
|
|
|
const oldTransport = networker.transport; |
|
|
|
if(oldTransport) { |
|
|
|
if(oldTransport) { |
|
|
|
DcConfigurator.removeTransport(dcConfigurator.chosenServers, oldTransport); |
|
|
|
DcConfigurator.removeTransport(dcConfigurator.chosenServers, oldTransport); |
|
|
@ -434,6 +435,7 @@ export class ApiManager { |
|
|
|
this.log('networker drain', networker.dcId); |
|
|
|
this.log('networker drain', networker.dcId); |
|
|
|
|
|
|
|
|
|
|
|
networker.onDrain = undefined; |
|
|
|
networker.onDrain = undefined; |
|
|
|
|
|
|
|
this.changeNetworkerTransport(networker); |
|
|
|
networker.destroy(); |
|
|
|
networker.destroy(); |
|
|
|
networkerFactory.removeNetworker(networker); |
|
|
|
networkerFactory.removeNetworker(networker); |
|
|
|
DcConfigurator.removeTransport(this.cachedNetworkers, networker); |
|
|
|
DcConfigurator.removeTransport(this.cachedNetworkers, networker); |
|
|
@ -475,22 +477,20 @@ export class ApiManager { |
|
|
|
}); |
|
|
|
}); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const rejectPromise = (error: ApiError) => { |
|
|
|
const rejectPromise = async(error: ApiError) => { |
|
|
|
if(!error) { |
|
|
|
if(!error) { |
|
|
|
error = {type: 'ERROR_EMPTY'}; |
|
|
|
error = {type: 'ERROR_EMPTY'}; |
|
|
|
} else if(!isObject(error)) { |
|
|
|
} else if(!isObject(error)) { |
|
|
|
error = {message: error}; |
|
|
|
error = {message: error}; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
deferred.reject(error); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if((error.code === 401 && error.type === 'SESSION_REVOKED') || |
|
|
|
if((error.code === 401 && error.type === 'SESSION_REVOKED') || |
|
|
|
(error.code === 406 && error.type === 'AUTH_KEY_DUPLICATED')) { |
|
|
|
(error.code === 406 && error.type === 'AUTH_KEY_DUPLICATED')) { |
|
|
|
this.logOut(); |
|
|
|
this.logOut(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if(options.ignoreErrors) { |
|
|
|
if(options.ignoreErrors) { |
|
|
|
return; |
|
|
|
throw error; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if(error.code === 406) { |
|
|
|
if(error.code === 406) { |
|
|
@ -512,13 +512,15 @@ export class ApiManager { |
|
|
|
} |
|
|
|
} |
|
|
|
}, 100); |
|
|
|
}, 100); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
throw error; |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
let dcId: DcId; |
|
|
|
let dcId: DcId; |
|
|
|
|
|
|
|
|
|
|
|
let cachedNetworker: MTPNetworker; |
|
|
|
let cachedNetworker: MTPNetworker; |
|
|
|
let stack = (new Error()).stack || 'empty stack'; |
|
|
|
let stack = (new Error()).stack || 'empty stack'; |
|
|
|
const performRequest = (networker: MTPNetworker) => { |
|
|
|
const performRequest = (): Promise<any> => { |
|
|
|
if(afterMessageId) { |
|
|
|
if(afterMessageId) { |
|
|
|
const after = this.afterMessageTempIds[afterMessageId]; |
|
|
|
const after = this.afterMessageTempIds[afterMessageId]; |
|
|
|
if(after) { |
|
|
|
if(after) { |
|
|
@ -526,7 +528,7 @@ export class ApiManager { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const promise = (cachedNetworker = networker).wrapApiCall(method, params, options); |
|
|
|
const promise = cachedNetworker.wrapApiCall(method, params, options); |
|
|
|
|
|
|
|
|
|
|
|
if(prepareTempMessageId) { |
|
|
|
if(prepareTempMessageId) { |
|
|
|
this.afterMessageTempIds[prepareTempMessageId] = { |
|
|
|
this.afterMessageTempIds[prepareTempMessageId] = { |
|
|
@ -535,7 +537,7 @@ export class ApiManager { |
|
|
|
}; |
|
|
|
}; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return promise.then(deferred.resolve, (error: ApiError) => { |
|
|
|
return promise.catch((error: ApiError) => { |
|
|
|
//if(!options.ignoreErrors) {
|
|
|
|
//if(!options.ignoreErrors) {
|
|
|
|
if(error.type !== 'FILE_REFERENCE_EXPIRED'/* && error.type !== 'MSG_WAIT_FAILED' */) { |
|
|
|
if(error.type !== 'FILE_REFERENCE_EXPIRED'/* && error.type !== 'MSG_WAIT_FAILED' */) { |
|
|
|
this.log.error('Error', error.code, error.type, this.baseDcId, dcId, method, params); |
|
|
|
this.log.error('Error', error.code, error.type, this.baseDcId, dcId, method, params); |
|
|
@ -548,7 +550,7 @@ export class ApiManager { |
|
|
|
//this.telegramMeNotify(false);
|
|
|
|
//this.telegramMeNotify(false);
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
rejectPromise(error); |
|
|
|
throw error; |
|
|
|
} else if(error.code === 401 && this.baseDcId && dcId !== this.baseDcId) { |
|
|
|
} else if(error.code === 401 && this.baseDcId && dcId !== this.baseDcId) { |
|
|
|
if(this.cachedExportPromise[dcId] === undefined) { |
|
|
|
if(this.cachedExportPromise[dcId] === undefined) { |
|
|
|
const promise = new Promise((exportResolve, exportReject) => { |
|
|
|
const promise = new Promise((exportResolve, exportReject) => { |
|
|
@ -563,10 +565,7 @@ export class ApiManager { |
|
|
|
this.cachedExportPromise[dcId] = promise; |
|
|
|
this.cachedExportPromise[dcId] = promise; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
this.cachedExportPromise[dcId].then(() => { |
|
|
|
return this.cachedExportPromise[dcId].then(() => performRequest()); |
|
|
|
//(cachedNetworker = networker).wrapApiCall(method, params, options).then(deferred.resolve, rejectPromise);
|
|
|
|
|
|
|
|
this.invokeApi(method, params, options).then(deferred.resolve, rejectPromise); |
|
|
|
|
|
|
|
}, rejectPromise); |
|
|
|
|
|
|
|
} else if(error.code === 303) { |
|
|
|
} else if(error.code === 303) { |
|
|
|
const newDcId = +error.type.match(/^(PHONE_MIGRATE_|NETWORK_MIGRATE_|USER_MIGRATE_)(\d+)/)[2] as DcId; |
|
|
|
const newDcId = +error.type.match(/^(PHONE_MIGRATE_|NETWORK_MIGRATE_|USER_MIGRATE_)(\d+)/)[2] as DcId; |
|
|
|
if(newDcId !== dcId) { |
|
|
|
if(newDcId !== dcId) { |
|
|
@ -576,70 +575,70 @@ export class ApiManager { |
|
|
|
this.setBaseDcId(newDcId); |
|
|
|
this.setBaseDcId(newDcId); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
this.getNetworker(newDcId, options).then((networker) => { |
|
|
|
return this.invokeApi(method, params, options); |
|
|
|
networker.wrapApiCall(method, params, options).then(deferred.resolve, rejectPromise); |
|
|
|
|
|
|
|
}, rejectPromise); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} else if(error.code === 400 && error.type.indexOf('FILE_MIGRATE') === 0) { |
|
|
|
} else if(error.code === 400 && error.type.indexOf('FILE_MIGRATE') === 0) { |
|
|
|
const newDcId = +error.type.match(/^(FILE_MIGRATE_)(\d+)/)[2] as DcId; |
|
|
|
const newDcId = +error.type.match(/^(FILE_MIGRATE_)(\d+)/)[2] as DcId; |
|
|
|
if(newDcId !== dcId) { |
|
|
|
if(newDcId !== dcId) { |
|
|
|
this.getNetworker(newDcId, options).then((networker) => { |
|
|
|
options.dcId = newDcId; |
|
|
|
networker.wrapApiCall(method, params, options).then(deferred.resolve, rejectPromise); |
|
|
|
return this.invokeApi(method, params, options); |
|
|
|
}, rejectPromise); |
|
|
|
|
|
|
|
} else { |
|
|
|
} else { |
|
|
|
rejectPromise(error); |
|
|
|
throw error; |
|
|
|
} |
|
|
|
} |
|
|
|
} else if(error.code === 400 && error.type === 'CONNECTION_NOT_INITED') { |
|
|
|
} else if(error.code === 400 && error.type === 'CONNECTION_NOT_INITED') { |
|
|
|
networkerFactory.unsetConnectionInited(); |
|
|
|
networkerFactory.unsetConnectionInited(); |
|
|
|
performRequest(cachedNetworker); |
|
|
|
return performRequest(); |
|
|
|
} else if(!options.rawError && error.code === 420) { |
|
|
|
} else if(!options.rawError && error.code === 420) { |
|
|
|
const waitTime = +error.type.match(/^FLOOD_WAIT_(\d+)/)[1] || 1; |
|
|
|
const waitTime = +error.type.match(/^FLOOD_WAIT_(\d+)/)[1] || 1; |
|
|
|
|
|
|
|
|
|
|
|
if(waitTime > (options.floodMaxTimeout !== undefined ? options.floodMaxTimeout : 60) && !options.prepareTempMessageId) { |
|
|
|
if(waitTime > (options.floodMaxTimeout !== undefined ? options.floodMaxTimeout : 60) && !options.prepareTempMessageId) { |
|
|
|
return rejectPromise(error); |
|
|
|
throw error; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
setTimeout(() => { |
|
|
|
return pause(waitTime/* (waitTime + 5) */ * 1000).then(() => performRequest()); |
|
|
|
performRequest(cachedNetworker); |
|
|
|
|
|
|
|
}, waitTime/* (waitTime + 5) */ * 1000); // 03.02.2020
|
|
|
|
|
|
|
|
} else if(!options.rawError && ['MSG_WAIT_FAILED', 'MSG_WAIT_TIMEOUT'].includes(error.type)) { |
|
|
|
} else if(!options.rawError && ['MSG_WAIT_FAILED', 'MSG_WAIT_TIMEOUT'].includes(error.type)) { |
|
|
|
const after = this.afterMessageTempIds[afterMessageId]; |
|
|
|
const after = this.afterMessageTempIds[afterMessageId]; |
|
|
|
|
|
|
|
|
|
|
|
afterMessageId = undefined; |
|
|
|
afterMessageId = undefined; |
|
|
|
delete options.afterMessageId; |
|
|
|
delete options.afterMessageId; |
|
|
|
|
|
|
|
|
|
|
|
if(after) after.promise.then(() => performRequest(cachedNetworker)); |
|
|
|
if(after) return after.promise.then(() => performRequest()); |
|
|
|
else performRequest(cachedNetworker); |
|
|
|
else return performRequest(); |
|
|
|
} else if(!options.rawError && error.code === 500) { |
|
|
|
} else if(!options.rawError && error.code === 500) { |
|
|
|
const now = Date.now(); |
|
|
|
const now = Date.now(); |
|
|
|
if(options.stopTime) { |
|
|
|
if(options.stopTime) { |
|
|
|
if(now >= options.stopTime) { |
|
|
|
if(now >= options.stopTime) { |
|
|
|
return rejectPromise(error); |
|
|
|
throw error; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
options.waitTime = options.waitTime ? Math.min(60, options.waitTime * 1.5) : 1; |
|
|
|
options.waitTime = options.waitTime ? Math.min(60, options.waitTime * 1.5) : 1; |
|
|
|
setTimeout(() => { |
|
|
|
return pause(options.waitTime * 1000).then(() => performRequest()); |
|
|
|
performRequest(cachedNetworker); |
|
|
|
|
|
|
|
}, options.waitTime * 1000); |
|
|
|
|
|
|
|
} else if(error.type === 'UNKNOWN') { |
|
|
|
} else if(error.type === 'UNKNOWN') { |
|
|
|
setTimeout(() => { |
|
|
|
return pause(1000).then(() => performRequest()); |
|
|
|
performRequest(cachedNetworker); |
|
|
|
|
|
|
|
}, 1000); |
|
|
|
|
|
|
|
} else { |
|
|
|
} else { |
|
|
|
rejectPromise(error); |
|
|
|
throw error; |
|
|
|
} |
|
|
|
} |
|
|
|
}); |
|
|
|
}); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let p: Promise<MTPNetworker>; |
|
|
|
if(dcId = (options.dcId || this.baseDcId)) { |
|
|
|
if(dcId = (options.dcId || this.baseDcId)) { |
|
|
|
this.getNetworker(dcId, options).then(performRequest, rejectPromise); |
|
|
|
p = this.getNetworker(dcId, options); |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
this.getBaseDcId().then(baseDcId => { |
|
|
|
p = this.getBaseDcId().then((baseDcId) => this.getNetworker(dcId = baseDcId, options)); |
|
|
|
this.getNetworker(dcId = baseDcId, options).then(performRequest, rejectPromise); |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
p.then((networker) => { |
|
|
|
|
|
|
|
cachedNetworker = networker; |
|
|
|
|
|
|
|
const promise = performRequest(); |
|
|
|
|
|
|
|
cachedNetworker.attachPromise(deferred, options as MTMessage); |
|
|
|
|
|
|
|
return promise; |
|
|
|
|
|
|
|
}) |
|
|
|
|
|
|
|
.then(deferred.resolve) |
|
|
|
|
|
|
|
.catch(rejectPromise) |
|
|
|
|
|
|
|
.catch(deferred.reject); |
|
|
|
|
|
|
|
|
|
|
|
return deferred; |
|
|
|
return deferred; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|