mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2026-04-07 13:47:54 +00:00
Fixes
fix localeWithStrings globally (#30)
Fix badge on zoomed devices. closes #9
Hide channel bottom panel closes #27
Another attempt to fix badge on some Zoomed devices
Force System Share sheet tg://sg/debug
fixes for device badge
New Crowdin updates (#34)
* New translations sglocalizable.strings (Chinese Traditional)
* New translations sglocalizable.strings (Chinese Simplified)
* New translations sglocalizable.strings (Chinese Traditional)
Fix input panel hidden on selection (#31)
* added if check for selectionState != nil
* same order of subnodes
Revert "Fix input panel hidden on selection (#31)"
This reverts commit e8a8bb1496.
Fix input panel for channels Closes #37
Quickly share links with system's share menu
force tabbar when editing
increase height for correct animation
New translations sglocalizable.strings (Ukrainian) (#38)
Hide Post Story button
Fix 10.15.1
Fix archive option for long-tap
Enable in-app Safari
Disable some unsupported purchases
disableDeleteChatSwipeOption + refactor restart alert
Hide bot in suggestions list
Fix merge v11.0
Fix exceptions for safari webview controller
New Crowdin updates (#47)
* New translations sglocalizable.strings (Romanian)
* New translations sglocalizable.strings (French)
* New translations sglocalizable.strings (Spanish)
* New translations sglocalizable.strings (Afrikaans)
* New translations sglocalizable.strings (Arabic)
* New translations sglocalizable.strings (Catalan)
* New translations sglocalizable.strings (Czech)
* New translations sglocalizable.strings (Danish)
* New translations sglocalizable.strings (German)
* New translations sglocalizable.strings (Greek)
* New translations sglocalizable.strings (Finnish)
* New translations sglocalizable.strings (Hebrew)
* New translations sglocalizable.strings (Hungarian)
* New translations sglocalizable.strings (Italian)
* New translations sglocalizable.strings (Japanese)
* New translations sglocalizable.strings (Korean)
* New translations sglocalizable.strings (Dutch)
* New translations sglocalizable.strings (Norwegian)
* New translations sglocalizable.strings (Polish)
* New translations sglocalizable.strings (Portuguese)
* New translations sglocalizable.strings (Serbian (Cyrillic))
* New translations sglocalizable.strings (Swedish)
* New translations sglocalizable.strings (Turkish)
* New translations sglocalizable.strings (Vietnamese)
* New translations sglocalizable.strings (Indonesian)
* New translations sglocalizable.strings (Hindi)
* New translations sglocalizable.strings (Uzbek)
New Crowdin updates (#49)
* New translations sglocalizable.strings (Arabic)
* New translations sglocalizable.strings (Arabic)
New translations sglocalizable.strings (Russian) (#51)
Call confirmation
WIP Settings search
Settings Search
Localize placeholder
Update AccountUtils.swift
mark mutual contact
Align back context action to left
New Crowdin updates (#54)
* New translations sglocalizable.strings (Chinese Simplified)
* New translations sglocalizable.strings (Chinese Traditional)
* New translations sglocalizable.strings (Ukrainian)
Independent Playground app for simulator
New translations sglocalizable.strings (Ukrainian) (#55)
Playground UIKit base and controllers
Inject SwiftUI view with overflow to AsyncDisplayKit
Launch Playgound project on simulator
Create .swiftformat
Move Playground to example
Update .swiftformat
Init SwiftUIViewController
wip
New translations sglocalizable.strings (Chinese Traditional) (#57)
Xcode 16 fixes
Fix
New translations sglocalizable.strings (Italian) (#59)
New translations sglocalizable.strings (Chinese Simplified) (#63)
Force disable CallKit integration due to missing NSE Entitlement
Fix merge
Fix whole chat translator
Sweetpad config
Bump version
11.3.1 fixes
Mutual contact placement fix
Disable Video PIP swipe
Update versions.json
Fix PIP crash
413 lines
20 KiB
Objective-C
413 lines
20 KiB
Objective-C
#import <MtProtoKit/MTBackupAddressSignals.h>
|
|
|
|
#import <MtProtoKit/MTSignal.h>
|
|
#import <MtProtoKit/MTAtomic.h>
|
|
#import <MtProtoKit/MTQueue.h>
|
|
#import <MtProtoKit/MTHttpRequestOperation.h>
|
|
#import <MtProtoKit/MTEncryption.h>
|
|
#import <MtProtoKit/MTRequestMessageService.h>
|
|
#import <MtProtoKit/MTRequest.h>
|
|
#import <MtProtoKit/MTContext.h>
|
|
#import <MtProtoKit/MTApiEnvironment.h>
|
|
#import <MtProtoKit/MTDatacenterAddress.h>
|
|
#import <MtProtoKit/MTDatacenterAddressSet.h>
|
|
#import <MtProtoKit/MTProto.h>
|
|
#import <MtProtoKit/MTSerialization.h>
|
|
#import <MtProtoKit/MTLogging.h>
|
|
#import <MtProtoKit/MTKeychain.h>
|
|
|
|
@interface MTTemporaryKeychain : NSObject<MTKeychain> {
|
|
NSMutableDictionary<NSString *, id> *_dict;
|
|
}
|
|
|
|
@end
|
|
|
|
@implementation MTTemporaryKeychain
|
|
|
|
- (instancetype)init {
|
|
self = [super init];
|
|
if (self != nil) {
|
|
_dict = [[NSMutableDictionary alloc] init];
|
|
}
|
|
return self;
|
|
}
|
|
|
|
- (NSString *)itemKeyForGroup:(NSString *)group key:(NSString *)key {
|
|
return [NSString stringWithFormat:@"%@:%@", group, key];
|
|
}
|
|
|
|
- (void)setObject:(id)object forKey:(NSString *)aKey group:(NSString *)group {
|
|
if (object == nil) {
|
|
return;
|
|
}
|
|
_dict[[self itemKeyForGroup:group key:aKey]] = object;
|
|
}
|
|
|
|
- (NSDictionary *)dictionaryForKey:(NSString *)aKey group:(NSString *)group {
|
|
id result = _dict[[self itemKeyForGroup:group key:aKey]];
|
|
if ([result isKindOfClass:[NSDictionary class]]) {
|
|
return result;
|
|
} else {
|
|
return nil;
|
|
}
|
|
}
|
|
|
|
- (NSNumber *)numberForKey:(NSString *)aKey group:(NSString *)group {
|
|
id result = _dict[[self itemKeyForGroup:group key:aKey]];
|
|
if ([result isKindOfClass:[NSNumber class]]) {
|
|
return result;
|
|
} else {
|
|
return nil;
|
|
}
|
|
}
|
|
|
|
- (void)removeObjectForKey:(NSString *)aKey group:(NSString *)group {
|
|
[_dict removeObjectForKey:[self itemKeyForGroup:group key:aKey]];
|
|
}
|
|
|
|
@end
|
|
|
|
static NSData *base64_decode(NSString *str) {
|
|
if ([NSData instancesRespondToSelector:@selector(initWithBase64EncodedString:options:)]) {
|
|
NSData *data = [[NSData alloc] initWithBase64EncodedString:str options:NSDataBase64DecodingIgnoreUnknownCharacters];
|
|
return data;
|
|
} else {
|
|
#pragma clang diagnostic push
|
|
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
|
return [[NSData alloc] initWithBase64Encoding:[str stringByReplacingOccurrencesOfString:@"[^A-Za-z0-9+/=]" withString:@"" options:NSRegularExpressionSearch range:NSMakeRange(0, [str length])]];
|
|
#pragma clang diagnostic pop
|
|
}
|
|
}
|
|
|
|
@implementation MTBackupAddressSignals
|
|
|
|
+ (bool)checkIpData:(MTBackupDatacenterData *)data timestamp:(int32_t)timestamp source:(NSString *)source {
|
|
if (data.timestamp >= timestamp + 60 * 20 || data.expirationDate <= timestamp - 60 * 20) {
|
|
if (MTLogEnabled()) {
|
|
MTLog(@"[Backup address fetch: backup config from %@ validity interval %d ... %d does not include current %d]", source, data.timestamp, data.expirationDate, timestamp);
|
|
}
|
|
return false;
|
|
} else {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
+ (MTSignal *)fetchBackupIpsResolveGoogle:(bool)isTesting phoneNumber:(NSString *)phoneNumber currentContext:(MTContext *)currentContext addressOverride:(NSString *)addressOverride {
|
|
NSArray *hosts = @[
|
|
@[@"dns.google.com", @""],
|
|
@[@"www.google.com", @"dns.google.com"],
|
|
];
|
|
|
|
id<EncryptionProvider> encryptionProvider = currentContext.encryptionProvider;
|
|
|
|
NSMutableArray *signals = [[NSMutableArray alloc] init];
|
|
for (NSArray *hostAndHostname in hosts) {
|
|
NSString *host = hostAndHostname[0];
|
|
NSString *hostName = hostAndHostname[1];
|
|
NSMutableDictionary *headers = [[NSMutableDictionary alloc] init];
|
|
if ([hostName length] != 0) {
|
|
headers[@"Host"] = hostName;
|
|
}
|
|
NSString *apvHost = @"apv3.stel.com";
|
|
if (addressOverride != nil) {
|
|
apvHost = addressOverride;
|
|
}
|
|
MTSignal *signal = [[[MTHttpRequestOperation dataForHttpUrl:[NSURL URLWithString:[NSString stringWithFormat:@"https://%@/resolve?name=%@&type=16&random_padding=%@", host, isTesting ? @"tapv3.stel.com" : apvHost, makeRandomPadding()]] headers:headers] mapToSignal:^MTSignal *(MTHttpResponse *response) {
|
|
NSString *dateHeader = response.headers[@"Date"];
|
|
if ([dateHeader isKindOfClass:[NSString class]]) {
|
|
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
|
|
NSLocale *usLocale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US"];
|
|
[formatter setLocale:usLocale];
|
|
[formatter setDateFormat:@"EEE',' dd' 'MMM' 'yyyy HH':'mm':'ss zzz"];
|
|
NSDate *date = [formatter dateFromString:dateHeader];
|
|
if (date != nil) {
|
|
double difference = [date timeIntervalSince1970] - [[NSDate date] timeIntervalSince1970];
|
|
[MTContext setFixedTimeDifference:(int32_t)difference];
|
|
}
|
|
}
|
|
|
|
NSData *data = response.data;
|
|
|
|
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
|
|
if ([dict respondsToSelector:@selector(objectForKey:)]) {
|
|
NSArray *answer = dict[@"Answer"];
|
|
NSMutableArray *strings = [[NSMutableArray alloc] init];
|
|
if ([answer respondsToSelector:@selector(objectAtIndex:)]) {
|
|
for (NSDictionary *value in answer) {
|
|
if ([value respondsToSelector:@selector(objectForKey:)]) {
|
|
NSString *part = value[@"data"];
|
|
if ([part respondsToSelector:@selector(characterAtIndex:)]) {
|
|
[strings addObject:part];
|
|
}
|
|
}
|
|
}
|
|
[strings sortUsingComparator:^NSComparisonResult(NSString *lhs, NSString *rhs) {
|
|
if (lhs.length > rhs.length) {
|
|
return NSOrderedAscending;
|
|
} else {
|
|
return NSOrderedDescending;
|
|
}
|
|
}];
|
|
|
|
NSString *finalString = @"";
|
|
for (NSString *string in strings) {
|
|
finalString = [finalString stringByAppendingString:[string stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"="]]];
|
|
}
|
|
|
|
NSData *result = base64_decode(finalString);
|
|
NSMutableData *finalData = [[NSMutableData alloc] initWithData:result];
|
|
[finalData setLength:256];
|
|
MTBackupDatacenterData *datacenterData = MTIPDataDecode(encryptionProvider, finalData, phoneNumber);
|
|
if (datacenterData != nil && [self checkIpData:datacenterData timestamp:(int32_t)[currentContext globalTime] source:@"resolveGoogle"]) {
|
|
return [MTSignal single:datacenterData];
|
|
}
|
|
}
|
|
}
|
|
return [MTSignal complete];
|
|
}] catch:^MTSignal *(__unused id error) {
|
|
return [MTSignal complete];
|
|
}];
|
|
if (signals.count != 0) {
|
|
signal = [signal delay:signals.count onQueue:[[MTQueue alloc] init]];
|
|
}
|
|
[signals addObject:signal];
|
|
}
|
|
|
|
return [[MTSignal mergeSignals:signals] take:1];
|
|
}
|
|
|
|
static NSString *makeRandomPadding() {
|
|
char validCharacters[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
|
|
int maxIndex = sizeof(validCharacters) - 1;
|
|
|
|
int minPadding = 13;
|
|
int maxPadding = 128;
|
|
int padding = minPadding + arc4random_uniform(maxPadding - minPadding);
|
|
NSMutableData *result = [[NSMutableData alloc] initWithLength:padding];
|
|
for (NSUInteger i = 0; i < result.length; i++) {
|
|
int index = arc4random_uniform(maxIndex);
|
|
assert(index >= 0 && index < maxIndex);
|
|
((uint8_t *)(result.mutableBytes))[i] = validCharacters[index];
|
|
}
|
|
NSString *string = [[NSString alloc] initWithData:result encoding:NSUTF8StringEncoding];
|
|
return string;
|
|
}
|
|
|
|
+ (MTSignal *)fetchBackupIpsResolveCloudflare:(bool)isTesting phoneNumber:(NSString *)phoneNumber currentContext:(MTContext *)currentContext addressOverride:(NSString *)addressOverride {
|
|
id<EncryptionProvider> encryptionProvider = currentContext.encryptionProvider;
|
|
|
|
NSArray *hosts = @[
|
|
@[@"mozilla.cloudflare-dns.com", @""],
|
|
];
|
|
|
|
NSMutableArray *signals = [[NSMutableArray alloc] init];
|
|
for (NSArray *hostAndHostname in hosts) {
|
|
NSString *host = hostAndHostname[0];
|
|
NSString *hostName = hostAndHostname[1];
|
|
NSMutableDictionary *headers = [[NSMutableDictionary alloc] init];
|
|
headers[@"accept"] = @"application/dns-json";
|
|
if ([hostName length] != 0) {
|
|
headers[@"Host"] = hostName;
|
|
}
|
|
NSString *apvHost = @"apv3.stel.com";
|
|
if (addressOverride != nil) {
|
|
apvHost = addressOverride;
|
|
}
|
|
MTSignal *signal = [[[MTHttpRequestOperation dataForHttpUrl:[NSURL URLWithString:[NSString stringWithFormat:@"https://%@/dns-query?name=%@&type=16&random_padding=%@", host, isTesting ? @"tapv3.stel.com" : apvHost, makeRandomPadding()]] headers:headers] mapToSignal:^MTSignal *(MTHttpResponse *response) {
|
|
NSString *dateHeader = response.headers[@"Date"];
|
|
if ([dateHeader isKindOfClass:[NSString class]]) {
|
|
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
|
|
NSLocale *usLocale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US"];
|
|
[formatter setLocale:usLocale];
|
|
[formatter setDateFormat:@"EEE',' dd' 'MMM' 'yyyy HH':'mm':'ss zzz"];
|
|
NSDate *date = [formatter dateFromString:dateHeader];
|
|
if (date != nil) {
|
|
double difference = [date timeIntervalSince1970] - [[NSDate date] timeIntervalSince1970];
|
|
[MTContext setFixedTimeDifference:(int32_t)difference];
|
|
}
|
|
}
|
|
|
|
NSData *data = response.data;
|
|
|
|
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
|
|
if ([dict respondsToSelector:@selector(objectForKey:)]) {
|
|
NSArray *answer = dict[@"Answer"];
|
|
NSMutableArray *strings = [[NSMutableArray alloc] init];
|
|
if ([answer respondsToSelector:@selector(objectAtIndex:)]) {
|
|
for (NSDictionary *value in answer) {
|
|
if ([value respondsToSelector:@selector(objectForKey:)]) {
|
|
NSString *part = value[@"data"];
|
|
if ([part respondsToSelector:@selector(characterAtIndex:)]) {
|
|
[strings addObject:part];
|
|
}
|
|
}
|
|
}
|
|
[strings sortUsingComparator:^NSComparisonResult(NSString *lhs, NSString *rhs) {
|
|
if (lhs.length > rhs.length) {
|
|
return NSOrderedAscending;
|
|
} else {
|
|
return NSOrderedDescending;
|
|
}
|
|
}];
|
|
|
|
NSString *finalString = @"";
|
|
for (NSString *string in strings) {
|
|
finalString = [finalString stringByAppendingString:[string stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"="]]];
|
|
}
|
|
|
|
NSData *result = base64_decode(finalString);
|
|
NSMutableData *finalData = [[NSMutableData alloc] initWithData:result];
|
|
[finalData setLength:256];
|
|
MTBackupDatacenterData *datacenterData = MTIPDataDecode(encryptionProvider, finalData, phoneNumber);
|
|
if (datacenterData != nil && [self checkIpData:datacenterData timestamp:(int32_t)[currentContext globalTime] source:@"resolveCloudflare"]) {
|
|
return [MTSignal single:datacenterData];
|
|
}
|
|
}
|
|
}
|
|
return [MTSignal complete];
|
|
}] catch:^MTSignal *(__unused id error) {
|
|
return [MTSignal complete];
|
|
}];
|
|
if (signals.count != 0) {
|
|
signal = [signal delay:signals.count onQueue:[[MTQueue alloc] init]];
|
|
}
|
|
[signals addObject:signal];
|
|
}
|
|
|
|
return [[MTSignal mergeSignals:signals] take:1];
|
|
}
|
|
|
|
MTAtomic *sharedFetchConfigKeychains() {
|
|
static MTAtomic *value = nil;
|
|
static dispatch_once_t onceToken;
|
|
dispatch_once(&onceToken, ^{
|
|
value = [[MTAtomic alloc] initWithValue:[[NSMutableDictionary alloc] init]];
|
|
});
|
|
return value;
|
|
}
|
|
|
|
+ (MTSignal *)fetchConfigFromAddress:(MTBackupDatacenterAddress *)address currentContext:(MTContext *)currentContext mainDatacenterId:(NSInteger)mainDatacenterId {
|
|
MTApiEnvironment *apiEnvironment = [currentContext.apiEnvironment copy];
|
|
|
|
apiEnvironment = [apiEnvironment withUpdatedSocksProxySettings:nil];
|
|
|
|
NSMutableDictionary *datacenterAddressOverrides = [[NSMutableDictionary alloc] init];
|
|
|
|
datacenterAddressOverrides[@(address.datacenterId)] = [[MTDatacenterAddress alloc] initWithIp:address.ip port:(uint16_t)address.port preferForMedia:false restrictToTcp:false cdn:false preferForProxy:false secret:address.secret];
|
|
apiEnvironment.datacenterAddressOverrides = datacenterAddressOverrides;
|
|
|
|
apiEnvironment.apiId = currentContext.apiEnvironment.apiId;
|
|
apiEnvironment.layer = currentContext.apiEnvironment.layer;
|
|
apiEnvironment = [apiEnvironment withUpdatedLangPackCode:currentContext.apiEnvironment.langPackCode];
|
|
apiEnvironment.disableUpdates = true;
|
|
apiEnvironment.langPack = currentContext.apiEnvironment.langPack;
|
|
|
|
MTContext *context = [[MTContext alloc] initWithSerialization:currentContext.serialization encryptionProvider:currentContext.encryptionProvider apiEnvironment:apiEnvironment isTestingEnvironment:currentContext.isTestingEnvironment useTempAuthKeys:false forceLocalDNS:currentContext.forceLocalDNS];
|
|
|
|
context.makeTcpConnectionInterface = currentContext.makeTcpConnectionInterface;
|
|
|
|
NSInteger authTokenMasterDatacenterId = 0;
|
|
NSNumber *requiredAuthToken = nil;
|
|
bool allowUnboundEphemeralKeys = true;
|
|
NSString *keychainKey = [NSString stringWithFormat:@"%d:%@:%d", (int)address.datacenterId, address.ip, (int)address.port];
|
|
MTTemporaryKeychain *tempKeychain = [sharedFetchConfigKeychains() with:^(NSMutableDictionary *dict) {
|
|
if (dict[keychainKey] != nil) {
|
|
return (MTTemporaryKeychain *)dict[keychainKey];
|
|
} else {
|
|
MTTemporaryKeychain *keychain = [[MTTemporaryKeychain alloc] init];
|
|
dict[keychainKey] = keychain;
|
|
return keychain;
|
|
}
|
|
}];
|
|
context.keychain = tempKeychain;
|
|
|
|
MTProto *mtProto = [[MTProto alloc] initWithContext:context datacenterId:address.datacenterId usageCalculationInfo:nil requiredAuthToken:requiredAuthToken authTokenMasterDatacenterId:authTokenMasterDatacenterId];
|
|
mtProto.useTempAuthKeys = true;
|
|
mtProto.allowUnboundEphemeralKeys = allowUnboundEphemeralKeys;
|
|
MTRequestMessageService *requestService = [[MTRequestMessageService alloc] initWithContext:context];
|
|
[mtProto addMessageService:requestService];
|
|
|
|
[mtProto resume];
|
|
|
|
MTRequest *request = [[MTRequest alloc] init];
|
|
|
|
NSData *getConfigData = nil;
|
|
MTRequestDatacenterAddressListParser responseParser = [currentContext.serialization requestDatacenterAddressWithData:&getConfigData];
|
|
[request setPayload:getConfigData metadata:@"getConfig" shortMetadata:@"getConfig" responseParser:responseParser];
|
|
|
|
__weak MTContext *weakCurrentContext = currentContext;
|
|
return [[MTSignal alloc] initWithGenerator:^id<MTDisposable>(MTSubscriber *subscriber) {
|
|
[request setCompleted:^(MTDatacenterAddressListData *result, __unused MTRequestResponseInfo *info, id error)
|
|
{
|
|
if (error == nil) {
|
|
__strong MTContext *strongCurrentContext = weakCurrentContext;
|
|
if (strongCurrentContext != nil) {
|
|
[result.addressList enumerateKeysAndObjectsUsingBlock:^(NSNumber *nDatacenterId, NSArray *list, __unused BOOL *stop) {
|
|
MTDatacenterAddressSet *addressSet = [[MTDatacenterAddressSet alloc] initWithAddressList:list];
|
|
|
|
MTDatacenterAddressSet *currentAddressSet = [context addressSetForDatacenterWithId:[nDatacenterId integerValue]];
|
|
|
|
if (currentAddressSet == nil || ![addressSet isEqual:currentAddressSet])
|
|
{
|
|
if (MTLogEnabled()) {
|
|
MTLog(@"[Backup address fetch: updating datacenter %d address set to %@]", [nDatacenterId intValue], addressSet);
|
|
}
|
|
|
|
[strongCurrentContext updateAddressSetForDatacenterWithId:[nDatacenterId integerValue] addressSet:addressSet forceUpdateSchemes:true];
|
|
[subscriber putNext:@true];
|
|
[subscriber putCompletion];
|
|
}
|
|
}];
|
|
}
|
|
} else {
|
|
[subscriber putCompletion];
|
|
}
|
|
}];
|
|
|
|
[requestService addRequest:request];
|
|
|
|
id requestId = request.internalId;
|
|
return [[MTBlockDisposable alloc] initWithBlock:^{
|
|
[requestService removeRequestByInternalId:requestId];
|
|
[mtProto pause];
|
|
}];
|
|
}];
|
|
}
|
|
|
|
+ (MTSignal * _Nonnull)fetchBackupIps:(bool)isTestingEnvironment currentContext:(MTContext * _Nonnull)currentContext additionalSource:(MTSignal * _Nullable)additionalSource phoneNumber:(NSString * _Nullable)phoneNumber mainDatacenterId:(NSInteger)mainDatacenterId {
|
|
NSMutableArray *signals = [[NSMutableArray alloc] init];
|
|
[signals addObject:[self fetchBackupIpsResolveGoogle:isTestingEnvironment phoneNumber:phoneNumber currentContext:currentContext addressOverride:currentContext.apiEnvironment.accessHostOverride]];
|
|
[signals addObject:[self fetchBackupIpsResolveCloudflare:isTestingEnvironment phoneNumber:phoneNumber currentContext:currentContext addressOverride:currentContext.apiEnvironment.accessHostOverride]];
|
|
if (additionalSource != nil) {
|
|
[signals addObject:[additionalSource mapToSignal:^MTSignal *(MTBackupDatacenterData *datacenterData) {
|
|
if (![datacenterData isKindOfClass:[MTBackupDatacenterData class]]) {
|
|
return [MTSignal complete];
|
|
}
|
|
if (datacenterData != nil && [self checkIpData:datacenterData timestamp:(int32_t)[currentContext globalTime] source:@"resolveExternal"]) {
|
|
return [MTSignal single:datacenterData];
|
|
} else {
|
|
return [MTSignal complete];
|
|
}
|
|
}]];
|
|
}
|
|
|
|
return [[[MTSignal mergeSignals:signals] take:1] mapToSignal:^MTSignal *(MTBackupDatacenterData *data) {
|
|
if (data != nil && data.addressList.count != 0) {
|
|
NSMutableArray *signals = [[NSMutableArray alloc] init];
|
|
NSTimeInterval delay = 0.0;
|
|
for (MTBackupDatacenterAddress *address in data.addressList) {
|
|
MTSignal *signal = [self fetchConfigFromAddress:address currentContext:currentContext mainDatacenterId:mainDatacenterId];
|
|
if (delay > DBL_EPSILON) {
|
|
signal = [signal delay:delay onQueue:[[MTQueue alloc] init]];
|
|
}
|
|
[signals addObject:signal];
|
|
delay += 5.0;
|
|
}
|
|
return [[MTSignal mergeSignals:signals] take:1];
|
|
}
|
|
return [MTSignal complete];
|
|
}];
|
|
}
|
|
|
|
@end
|