123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327 |
- /**
- * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
- * SPDX-License-Identifier: GPL-3.0-or-later
- */
- #import "NCAPIController.h"
- @import NextcloudKit;
- #import <SDWebImage/SDWebImageManager.h>
- #import <SDWebImageSVGKitDefine.h>
- #import <SDWebImage/SDImageCache.h>
- #import "CCCertificate.h"
- #import "NCAppBranding.h"
- #import "NCDatabaseManager.h"
- #import "NCKeyChainController.h"
- #import "NotificationCenterNotifications.h"
- #import "NextcloudTalk-Swift.h"
- NSInteger const APIv1 = 1;
- NSInteger const APIv2 = 2;
- NSInteger const APIv3 = 3;
- NSInteger const APIv4 = 4;
- NSString * const kDavEndpoint = @"/remote.php/dav";
- NSString * const kNCOCSAPIVersion = @"/ocs/v2.php";
- NSString * const kNCSpreedAPIVersionBase = @"/apps/spreed/api/v";
- NSInteger const kReceivedChatMessagesLimit = 100;
- @interface NCAPIController () <NSURLSessionTaskDelegate, NSURLSessionDelegate, NKCommonDelegate>
- @property (nonatomic, strong) NCAPISessionManager *defaultAPISessionManager;
- @end
- @implementation NCAPIController
- + (NCAPIController *)sharedInstance
- {
- static dispatch_once_t once;
- static NCAPIController *sharedInstance;
- dispatch_once(&once, ^{
- sharedInstance = [[self alloc] init];
- });
- return sharedInstance;
- }
- - (id)init
- {
- self = [super init];
- if (self) {
- [self initSessionManagers];
- [self initImageDownloaders];
- }
-
- return self;
- }
- - (void)initSessionManagers
- {
- NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
- configuration.HTTPCookieStorage = nil;
- _defaultAPISessionManager = [[NCAPISessionManager alloc] initWithConfiguration:configuration];
-
- _apiSessionManagers = [NSMutableDictionary new];
- _longPollingApiSessionManagers = [NSMutableDictionary new];
-
- for (TalkAccount *account in [[NCDatabaseManager sharedInstance] allAccounts]) {
- [self createAPISessionManagerForAccount:account];
- }
- }
- - (void)createAPISessionManagerForAccount:(TalkAccount *)account
- {
- NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
- NSHTTPCookieStorage *cookieStorage = [NSHTTPCookieStorage sharedCookieStorageForGroupContainerIdentifier:account.accountId];
- configuration.HTTPCookieStorage = cookieStorage;
- NCAPISessionManager *apiSessionManager = [[NCAPISessionManager alloc] initWithConfiguration:configuration];
- [apiSessionManager.requestSerializer setValue:[self authHeaderForAccount:account] forHTTPHeaderField:@"Authorization"];
- // As we can run max. 30s in the background, the default timeout should be lower than 30 to avoid being killed by the OS
- [apiSessionManager.requestSerializer setTimeoutInterval:25];
- [_apiSessionManagers setObject:apiSessionManager forKey:account.accountId];
- configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
- cookieStorage = [NSHTTPCookieStorage sharedCookieStorageForGroupContainerIdentifier:account.accountId];
- configuration.HTTPCookieStorage = cookieStorage;
- apiSessionManager = [[NCAPISessionManager alloc] initWithConfiguration:configuration];
- [apiSessionManager.requestSerializer setValue:[self authHeaderForAccount:account] forHTTPHeaderField:@"Authorization"];
- [_longPollingApiSessionManagers setObject:apiSessionManager forKey:account.accountId];
- }
- - (void)setupNCCommunicationForAccount:(TalkAccount *)account
- {
- ServerCapabilities *serverCapabilities = [[NCDatabaseManager sharedInstance] serverCapabilitiesForAccountId:account.accountId];
- NSString *userToken = [[NCKeyChainController sharedInstance] tokenForAccountId:account.accountId];
- NSString *userAgent = [NSString stringWithFormat:@"Mozilla/5.0 (iOS) Nextcloud-Talk v%@", [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"]];
- [[NextcloudKit shared] setupWithAccount:account.accountId user:account.user userId:account.userId password:userToken urlBase:account.server userAgent:userAgent nextcloudVersion:serverCapabilities.versionMajor delegate:self];
- }
- - (void)initImageDownloaders
- {
- _imageDownloader = [[AFImageDownloader alloc]
- initWithSessionManager:[NCImageSessionManager shared]
- downloadPrioritization:AFImageDownloadPrioritizationFIFO
- maximumActiveDownloads:4
- imageCache:[[AFAutoPurgingImageCache alloc] init]];
-
- _imageDownloaderNoCache = [[AFImageDownloader alloc]
- initWithSessionManager:[NCImageSessionManager shared]
- downloadPrioritization:AFImageDownloadPrioritizationFIFO
- maximumActiveDownloads:4
- imageCache:nil];
- // By default SDWebImageDownloader defaults to 6 concurrent downloads (see SDWebImageDownloaderConfig)
- // Make sure we support download SVGs with SDImageDownloader
- [[SDImageCodersManager sharedManager] addCoder:[SDImageSVGKCoder sharedCoder]];
- // Make sure we support self-signed certificates we trusted before
- [[SDWebImageDownloader sharedDownloader].config setOperationClass:[NCWebImageDownloaderOperation class]];
- // Try to remove legacy avatar cache in app group
- NSURL *legacyCacheURL = [[[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:groupIdentifier] URLByAppendingPathComponent:@"AvatarCache"];
- if (legacyCacheURL != nil) {
- [[NSFileManager defaultManager] removeItemAtURL:legacyCacheURL error:nil];
- }
- // Limit the cache size to 100 MB and prevent uploading to iCloud
- // Don't set the path to an app group in order to prevent crashes
- [SDImageCache sharedImageCache].config.shouldDisableiCloud = YES;
- [SDImageCache sharedImageCache].config.maxDiskSize = 100 * 1024 * 1024;
- NSString *userAgent = [NSString stringWithFormat:@"Mozilla/5.0 (iOS) Nextcloud-Talk v%@",
- [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"]];
- [[SDWebImageDownloader sharedDownloader] setValue:userAgent forHTTPHeaderField:@"User-Agent"];
- }
- - (NSString *)authHeaderForAccount:(TalkAccount *)account
- {
- NSString *userTokenString = [NSString stringWithFormat:@"%@:%@", account.user, [[NCKeyChainController sharedInstance] tokenForAccountId:account.accountId]];
- NSData *data = [userTokenString dataUsingEncoding:NSUTF8StringEncoding];
- NSString *base64Encoded = [data base64EncodedStringWithOptions:0];
-
- return [[NSString alloc]initWithFormat:@"Basic %@",base64Encoded];
- }
- - (SDWebImageDownloaderRequestModifier *)getRequestModifierForAccount:(TalkAccount *)account
- {
- NSMutableDictionary *headerDictionary = [[NSMutableDictionary alloc] init];
- [headerDictionary setObject:[self authHeaderForAccount:account] forKey:@"Authorization"];
- return [[SDWebImageDownloaderRequestModifier alloc] initWithHeaders:headerDictionary];
- }
- - (NSInteger)conversationAPIVersionForAccount:(TalkAccount *)account
- {
- NSInteger conversationAPIVersion = APIv1;
- if ([[NCDatabaseManager sharedInstance] serverHasTalkCapability:kCapabilityChatReadStatus forAccountId:account.accountId]) {
- conversationAPIVersion = APIv3;
- }
- if ([[NCDatabaseManager sharedInstance] serverHasTalkCapability:kCapabilityConversationV4 forAccountId:account.accountId]) {
- conversationAPIVersion = APIv4;
- }
-
- return conversationAPIVersion;
- }
- - (NSInteger)callAPIVersionForAccount:(TalkAccount *)account
- {
- return [self conversationAPIVersionForAccount:account];
- }
- - (NSInteger)chatAPIVersionForAccount:(TalkAccount *)account
- {
- return APIv1;
- }
- - (NSInteger)reactionsAPIVersionForAccount:(TalkAccount *)account
- {
- return APIv1;
- }
- - (NSInteger)pollsAPIVersionForAccount:(TalkAccount *)account
- {
- return APIv1;
- }
- - (NSInteger)breakoutRoomsAPIVersionForAccount:(TalkAccount *)account
- {
- return APIv1;
- }
- - (NSInteger)federationAPIVersionForAccount:(TalkAccount *)account
- {
- return APIv1;
- }
- - (NSInteger)banAPIVersionForAccount:(TalkAccount *)account
- {
- return APIv1;
- }
- - (NSInteger)signalingAPIVersionForAccount:(TalkAccount *)account
- {
- NSInteger signalingAPIVersion = APIv1;
- if ([[NCDatabaseManager sharedInstance] serverHasTalkCapability:kCapabilitySIPSupport forAccountId:account.accountId]) {
- signalingAPIVersion = APIv2;
- }
- if ([[NCDatabaseManager sharedInstance] serverHasTalkCapability:kCapabilitySignalingV3 forAccountId:account.accountId]) {
- signalingAPIVersion = APIv3;
- }
-
- return signalingAPIVersion;
- }
- - (NSString *)filesPathForAccount:(TalkAccount *)account
- {
- return [NSString stringWithFormat:@"%@/files/%@", kDavEndpoint, account.userId];
- }
- - (NSString *)getRequestURLForEndpoint:(NSString *)endpoint withAPIVersion:(NSInteger)apiVersion forAccount:(TalkAccount *)account
- {
- return [NSString stringWithFormat:@"%@%@%@%ld/%@", account.server, kNCOCSAPIVersion, kNCSpreedAPIVersionBase, (long)apiVersion, endpoint];
- }
- #pragma mark - Contacts Controller
- - (NSURLSessionDataTask *)searchContactsForAccount:(TalkAccount *)account withPhoneNumbers:(NSDictionary *)phoneNumbers andCompletionBlock:(GetContactsWithPhoneNumbersCompletionBlock)block
- {
- NSString *URLString = [NSString stringWithFormat:@"%@/ocs/v2.php/cloud/users/search/by-phone", account.server];
- NSString *location = [[NSLocale currentLocale] countryCode];
- NSDictionary *parameters = @{@"location" : location,
- @"search" : phoneNumbers};
-
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager POST:URLString parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- NSDictionary *responseContacts = [[responseObject objectForKey:@"ocs"] objectForKey:@"data"];
- if (block) {
- block(responseContacts, nil);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- // NSInteger statusCode = [self getResponseStatusCode:task.response];
- // Ignore status code for now https://github.com/nextcloud/server/pull/26679
- // [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- block(nil, error);
- }
- }];
-
- return task;
- }
- - (NSURLSessionDataTask *)getContactsForAccount:(TalkAccount *)account forRoom:(NSString *)room groupRoom:(BOOL)groupRoom withSearchParam:(NSString *)search andCompletionBlock:(GetContactsCompletionBlock)block
- {
- NSMutableArray *shareTypes = [[NSMutableArray alloc] initWithObjects:@(NCShareTypeUser), nil];
- if (groupRoom && [[NCDatabaseManager sharedInstance] serverHasTalkCapability:kCapabilityInviteGroupsAndMails]) {
- [shareTypes addObject:@(NCShareTypeGroup)];
- [shareTypes addObject:@(NCShareTypeEmail)];
- if ([[NCDatabaseManager sharedInstance] serverHasTalkCapability:kCapabilityCirclesSupport]) {
- [shareTypes addObject:@(NCShareTypeCircle)];
- }
- if ([[NCDatabaseManager sharedInstance] serverCanInviteFederatedUsersforAccountId:account.accountId]) {
- [shareTypes addObject:@(NCShareTypeRemote)];
- }
- }
-
- NSString *URLString = [NSString stringWithFormat:@"%@%@/core/autocomplete/get", account.server, kNCOCSAPIVersion];
- NSDictionary *parameters = @{@"format" : @"json",
- @"search" : search ? search : @"",
- @"limit" : @"50",
- @"itemType" : @"call",
- @"itemId" : room ? room : @"new",
- @"shareTypes" : shareTypes
- };
-
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager GET:URLString parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- NSArray *responseContacts = [[responseObject objectForKey:@"ocs"] objectForKey:@"data"];
- NSMutableArray *users = [[NSMutableArray alloc] initWithCapacity:responseContacts.count];
- for (NSDictionary *user in responseContacts) {
- NCUser *ncUser = [NCUser userWithDictionary:user];
- TalkAccount *activeAccount = [[NCDatabaseManager sharedInstance] activeAccount];
- if (ncUser && !([ncUser.userId isEqualToString:activeAccount.userId] && [ncUser.source isEqualToString:kParticipantTypeUser])) {
- [users addObject:ncUser];
- }
- }
- NSMutableDictionary *indexedContacts = [NCUser indexedUsersFromUsersArray:users];
- NSArray *indexes = [[indexedContacts allKeys] sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)];
- if (block) {
- block(indexes, indexedContacts, users, nil);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- block(nil, nil, nil, error);
- }
- }];
-
- return task;
- }
- #pragma mark - Rooms Controller
- - (NSURLSessionDataTask *)makeRoomPublic:(NSString *)token forAccount:(TalkAccount *)account withCompletionBlock:(MakeRoomPublicCompletionBlock)block
- {
- NSString *encodedToken = [token stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
- NSString *endpoint = [NSString stringWithFormat:@"room/%@/public", encodedToken];
- NSInteger conversationAPIVersion = [self conversationAPIVersionForAccount:account];
- NSString *URLString = [self getRequestURLForEndpoint:endpoint withAPIVersion:conversationAPIVersion forAccount:account];
-
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager POST:URLString parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- if (block) {
- block(nil);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- block(error);
- }
- }];
-
- return task;
- }
- - (NSURLSessionDataTask *)makeRoomPrivate:(NSString *)token forAccount:(TalkAccount *)account withCompletionBlock:(MakeRoomPrivateCompletionBlock)block
- {
- NSString *encodedToken = [token stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
- NSString *endpoint = [NSString stringWithFormat:@"room/%@/public", encodedToken];
- NSInteger conversationAPIVersion = [self conversationAPIVersionForAccount:account];
- NSString *URLString = [self getRequestURLForEndpoint:endpoint withAPIVersion:conversationAPIVersion forAccount:account];
-
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager DELETE:URLString parameters:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- if (block) {
- block(nil);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- block(error);
- }
- }];
-
- return task;
- }
- - (NSURLSessionDataTask *)deleteRoom:(NSString *)token forAccount:(TalkAccount *)account withCompletionBlock:(DeleteRoomCompletionBlock)block
- {
- NSString *encodedToken = [token stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
- NSString *endpoint = [NSString stringWithFormat:@"room/%@", encodedToken];
- NSInteger conversationAPIVersion = [self conversationAPIVersionForAccount:account];
- NSString *URLString = [self getRequestURLForEndpoint:endpoint withAPIVersion:conversationAPIVersion forAccount:account];
-
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager DELETE:URLString parameters:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- if (block) {
- block(nil);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- block(error);
- }
- }];
-
- return task;
- }
- - (NSURLSessionDataTask *)setPassword:(NSString *)password toRoom:(NSString *)token forAccount:(TalkAccount *)account withCompletionBlock:(SetPasswordCompletionBlock)block
- {
- NSString *encodedToken = [token stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
- NSString *endpoint = [NSString stringWithFormat:@"room/%@/password", encodedToken];
- NSInteger conversationAPIVersion = [self conversationAPIVersionForAccount:account];
- NSString *URLString = [self getRequestURLForEndpoint:endpoint withAPIVersion:conversationAPIVersion forAccount:account];
- NSDictionary *parameters = @{@"password" : password};
-
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager PUT:URLString parameters:parameters success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- if (block) {
- block(nil, nil);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- if (statusCode == 400) {
- NSData *errorData = (NSData *)error.userInfo[AFNetworkingOperationFailingURLResponseDataErrorKey];
- NSDictionary *jsonData = [NSJSONSerialization JSONObjectWithData:errorData
- options:0
- error:&error];
-
- // message is already translated server-side
- NSString *errorDescription = [[[jsonData objectForKey:@"ocs"] objectForKey:@"data"] objectForKey:@"message"];
- block(error, errorDescription);
- } else {
- block(error, nil);
- }
- }
- }];
-
- return task;
- }
- - (NSURLSessionDataTask *)joinRoom:(NSString *)token forAccount:(TalkAccount *)account withCompletionBlock:(JoinRoomCompletionBlock)block
- {
- NSString *encodedToken = [token stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
- NSString *endpoint = [NSString stringWithFormat:@"room/%@/participants/active", encodedToken];
- NSInteger conversationAPIVersion = [self conversationAPIVersionForAccount:account];
- NSString *URLString = [self getRequestURLForEndpoint:endpoint withAPIVersion:conversationAPIVersion forAccount:account];
-
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager POST:URLString parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- NSDictionary *dataDictionary = [[responseObject objectForKey:@"ocs"] objectForKey:@"data"];
- NSString *sessionId = [dataDictionary objectForKey:@"sessionId"];
- NSHTTPURLResponse *response = ((NSHTTPURLResponse *)[task response]);
- NSDictionary *headers = [self getResponseHeaders:response];
- [self checkProxyResponseHeaders:headers forAccount:account forRoom:token];
- // Room object is returned only since Talk 11
- NCRoom *room = nil;
- if ([[NCDatabaseManager sharedInstance] serverHasTalkCapability:kCapabilityListableRooms forAccountId:account.accountId]) {
- room = [NCRoom roomWithDictionary:dataDictionary andAccountId:account.accountId];
- }
- if (block) {
- block(sessionId, room, nil, 0, nil);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- NSDictionary *errorDict = [[[self getFailureResponseObjectFromError:error] objectForKey:@"ocs"] objectForKey:@"data"];
- NSString *statusReason = nil;
- // Depending on the error, an empty array instead of a dictionary is returned by the server
- if (errorDict && [errorDict isKindOfClass:[NSDictionary class]]) {
- statusReason = [errorDict objectForKey:@"error"];
- }
- if (block) {
- block(nil, nil, error, statusCode, statusReason);
- }
- }];
-
- return task;
- }
- - (NSURLSessionDataTask *)exitRoom:(NSString *)token forAccount:(TalkAccount *)account withCompletionBlock:(ExitRoomCompletionBlock)block
- {
- NSString *encodedToken = [token stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
- NSString *endpoint = [NSString stringWithFormat:@"room/%@/participants/active", encodedToken];
- NSInteger conversationAPIVersion = [self conversationAPIVersionForAccount:account];
- NSString *URLString = [self getRequestURLForEndpoint:endpoint withAPIVersion:conversationAPIVersion forAccount:account];
-
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager DELETE:URLString parameters:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- if (block) {
- block(nil);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- block(error);
- }
- }];
-
- return task;
- }
- - (NSURLSessionDataTask *)addRoomToFavorites:(NSString *)token forAccount:(TalkAccount *)account withCompletionBlock:(FavoriteRoomCompletionBlock)block
- {
- NSString *encodedToken = [token stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
- NSString *endpoint = [NSString stringWithFormat:@"room/%@/favorite", encodedToken];
- NSInteger conversationAPIVersion = [self conversationAPIVersionForAccount:account];
- NSString *URLString = [self getRequestURLForEndpoint:endpoint withAPIVersion:conversationAPIVersion forAccount:account];
-
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager POST:URLString parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- if (block) {
- block(nil);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- block(error);
- }
- }];
-
- return task;
- }
- - (NSURLSessionDataTask *)removeRoomFromFavorites:(NSString *)token forAccount:(TalkAccount *)account withCompletionBlock:(FavoriteRoomCompletionBlock)block
- {
- NSString *encodedToken = [token stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
- NSString *endpoint = [NSString stringWithFormat:@"room/%@/favorite", encodedToken];
- NSInteger conversationAPIVersion = [self conversationAPIVersionForAccount:account];
- NSString *URLString = [self getRequestURLForEndpoint:endpoint withAPIVersion:conversationAPIVersion forAccount:account];
-
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager DELETE:URLString parameters:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- if (block) {
- block(nil);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- block(error);
- }
- }];
-
- return task;
- }
- - (NSURLSessionDataTask *)setNotificationLevel:(NCRoomNotificationLevel)level forRoom:(NSString *)token forAccount:(TalkAccount *)account withCompletionBlock:(NotificationLevelCompletionBlock)block
- {
- NSString *encodedToken = [token stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
- NSString *endpoint = [NSString stringWithFormat:@"room/%@/notify", encodedToken];
- NSInteger conversationAPIVersion = [self conversationAPIVersionForAccount:account];
- NSString *URLString = [self getRequestURLForEndpoint:endpoint withAPIVersion:conversationAPIVersion forAccount:account];
- NSDictionary *parameters = @{@"level" : @(level)};
-
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager POST:URLString parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- if (block) {
- block(nil);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- block(error);
- }
- }];
-
- return task;
- }
- - (NSURLSessionDataTask *)setCallNotificationEnabled:(BOOL)enabled forRoom:(NSString *)token forAccount:(TalkAccount *)account withCompletionBlock:(NotificationLevelCompletionBlock)block
- {
- NSString *encodedToken = [token stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
- NSString *endpoint = [NSString stringWithFormat:@"room/%@/notify-calls", encodedToken];
- NSInteger conversationAPIVersion = [self conversationAPIVersionForAccount:account];
- NSString *URLString = [self getRequestURLForEndpoint:endpoint withAPIVersion:conversationAPIVersion forAccount:account];
- NSDictionary *parameters = @{@"level" : @(enabled)};
-
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager POST:URLString parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- if (block) {
- block(nil);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- block(error);
- }
- }];
-
- return task;
- }
- - (NSURLSessionDataTask *)setReadOnlyState:(NCRoomReadOnlyState)state forRoom:(NSString *)token forAccount:(TalkAccount *)account withCompletionBlock:(ReadOnlyCompletionBlock)block
- {
- NSString *encodedToken = [token stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
- NSString *endpoint = [NSString stringWithFormat:@"room/%@/read-only", encodedToken];
- NSInteger conversationAPIVersion = [self conversationAPIVersionForAccount:account];
- NSString *URLString = [self getRequestURLForEndpoint:endpoint withAPIVersion:conversationAPIVersion forAccount:account];
- NSDictionary *parameters = @{@"state" : @(state)};
-
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager PUT:URLString parameters:parameters success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- if (block) {
- block(nil);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- block(error);
- }
- }];
-
- return task;
- }
- - (NSURLSessionDataTask *)setLobbyState:(NCRoomLobbyState)state withTimer:(NSInteger)timer forRoom:(NSString *)token forAccount:(TalkAccount *)account withCompletionBlock:(SetLobbyStateCompletionBlock)block
- {
- NSString *encodedToken = [token stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
- NSString *endpoint = [NSString stringWithFormat:@"room/%@/webinary/lobby", encodedToken];
- NSInteger conversationAPIVersion = [self conversationAPIVersionForAccount:account];
- if (conversationAPIVersion >= APIv4) {
- endpoint = [NSString stringWithFormat:@"room/%@/webinar/lobby", encodedToken];
- }
- NSString *URLString = [self getRequestURLForEndpoint:endpoint withAPIVersion:conversationAPIVersion forAccount:account];
- NSMutableDictionary *parameters = [NSMutableDictionary new];
- [parameters setObject:@(state) forKey:@"state"];
- if (timer > 0) {
- [parameters setObject:@(timer) forKey:@"timer"];
- }
-
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager PUT:URLString parameters:parameters success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- if (block) {
- block(nil);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- block(error);
- }
- }];
-
- return task;
- }
- - (NSURLSessionDataTask *)setSIPState:(NCRoomSIPState)state forRoom:(NSString *)token forAccount:(TalkAccount *)account withCompletionBlock:(SetSIPStateCompletionBlock)block
- {
- NSString *encodedToken = [token stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
- NSString *endpoint = [NSString stringWithFormat:@"room/%@/webinar/sip", encodedToken];
- NSInteger conversationAPIVersion = [self conversationAPIVersionForAccount:account];
- NSString *URLString = [self getRequestURLForEndpoint:endpoint withAPIVersion:conversationAPIVersion forAccount:account];
- NSDictionary *parameters = @{@"state" : @(state)};
-
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager PUT:URLString parameters:parameters success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- if (block) {
- block(nil);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- block(error);
- }
- }];
-
- return task;
- }
- - (NSURLSessionDataTask *)setListableScope:(NCRoomListableScope)scope forRoom:(NSString *)token forAccount:(TalkAccount *)account withCompletionBlock:(ListableCompletionBlock)block
- {
- NSString *encodedToken = [token stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
- NSString *endpoint = [NSString stringWithFormat:@"room/%@/listable", encodedToken];
- NSInteger conversationAPIVersion = [self conversationAPIVersionForAccount:account];
- NSString *URLString = [self getRequestURLForEndpoint:endpoint withAPIVersion:conversationAPIVersion forAccount:account];
- NSDictionary *parameters = @{@"scope" : @(scope)};
-
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager PUT:URLString parameters:parameters success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- if (block) {
- block(nil);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- block(error);
- }
- }];
-
- return task;
- }
- - (NSURLSessionDataTask *)setMessageExpiration:(NCMessageExpiration)messageExpiration forRoom:(NSString *)token forAccount:(TalkAccount *)account withCompletionBlock:(MessageExpirationCompletionBlock)block
- {
- NSString *encodedToken = [token stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
- NSString *endpoint = [NSString stringWithFormat:@"room/%@/message-expiration", encodedToken];
- NSInteger conversationAPIVersion = [self conversationAPIVersionForAccount:account];
- NSString *URLString = [self getRequestURLForEndpoint:endpoint withAPIVersion:conversationAPIVersion forAccount:account];
- NSDictionary *parameters = @{@"seconds" : @(messageExpiration)};
-
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager POST:URLString parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- if (block) {
- block(nil);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- block(error);
- }
- }];
-
- return task;
- }
- #pragma mark - Breakout Rooms Controller
- - (NSURLSessionDataTask *)requestAssistanceInRoom:(NSString *)token forAccount:(TalkAccount *)account withCompletionBlock:(RequestAssistanceCompletionBlock)block
- {
- NSString *encodedToken = [token stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
- NSString *endpoint = [NSString stringWithFormat:@"breakout-rooms/%@/request-assistance", encodedToken];
- NSInteger breakoutRoomsAPIVersion = [self breakoutRoomsAPIVersionForAccount:account];
- NSString *URLString = [self getRequestURLForEndpoint:endpoint withAPIVersion:breakoutRoomsAPIVersion forAccount:account];
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager POST:URLString parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- if (block) {
- block(nil);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- block(error);
- }
- }];
- return task;
- }
- - (NSURLSessionDataTask *)stopRequestingAssistanceInRoom:(NSString *)token forAccount:(TalkAccount *)account withCompletionBlock:(RequestAssistanceCompletionBlock)block
- {
- NSString *encodedToken = [token stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
- NSString *endpoint = [NSString stringWithFormat:@"breakout-rooms/%@/request-assistance", encodedToken];
- NSInteger breakoutRoomsAPIVersion = [self breakoutRoomsAPIVersionForAccount:account];
- NSString *URLString = [self getRequestURLForEndpoint:endpoint withAPIVersion:breakoutRoomsAPIVersion forAccount:account];
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager DELETE:URLString parameters:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- if (block) {
- block(nil);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- block(error);
- }
- }];
- return task;
- }
- #pragma mark - Participants Controller
- - (NSURLSessionDataTask *)getParticipantsFromRoom:(NSString *)token forAccount:(TalkAccount *)account withCompletionBlock:(GetParticipantsFromRoomCompletionBlock)block
- {
- NSString *encodedToken = [token stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
- NSString *endpoint = [NSString stringWithFormat:@"room/%@/participants", encodedToken];
- NSInteger conversationAPIVersion = [self conversationAPIVersionForAccount:account];
- NSString *URLString = [self getRequestURLForEndpoint:endpoint withAPIVersion:conversationAPIVersion forAccount:account];
- ServerCapabilities *serverCapabilities = [[NCDatabaseManager sharedInstance] serverCapabilitiesForAccountId:account.accountId];
- if (serverCapabilities.userStatus) {
- URLString = [URLString stringByAppendingString:@"?includeStatus=true"];
- }
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager GET:URLString parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- NSArray *responseParticipants = [[responseObject objectForKey:@"ocs"] objectForKey:@"data"];
- NSMutableArray *participants = [[NSMutableArray alloc] initWithCapacity:responseParticipants.count];
- for (NSDictionary *participantDict in responseParticipants) {
- NCRoomParticipant *participant = [NCRoomParticipant participantWithDictionary:participantDict];
- [participants addObject:participant];
- }
-
- // Sort participants by:
- // - Participants before groups
- // - Online status
- // - In call
- // - Type (moderators before normal participants)
- // - Alphabetic
- NSSortDescriptor *alphabeticSorting = [[NSSortDescriptor alloc] initWithKey:@"displayName" ascending:YES selector:@selector(localizedCaseInsensitiveCompare:)];
- NSSortDescriptor *customSorting = [NSSortDescriptor sortDescriptorWithKey:@"" ascending:YES comparator:^NSComparisonResult(id _Nonnull obj1, id _Nonnull obj2) {
- NCRoomParticipant *first = (NCRoomParticipant*)obj1;
- NCRoomParticipant *second = (NCRoomParticipant*)obj2;
-
- BOOL group1 = first.isGroup;
- BOOL group2 = second.isGroup;
- if (group1 != group2) {
- return group1 - group2;
- }
-
- BOOL online1 = !first.isOffline;
- BOOL online2 = !second.isOffline;
- if (online1 != online2) {
- return online2 - online1;
- }
-
- BOOL inCall1 = first.inCall > 0;
- BOOL inCall2 = second.inCall > 0;
- if (inCall1 != inCall2) {
- return inCall2 - inCall1;
- }
-
- BOOL moderator1 = first.canModerate;
- BOOL moderator2 = second.canModerate;
- if (moderator1 != moderator2) {
- return moderator2 - moderator1;
- }
-
- return NSOrderedSame;
- }];
- NSArray *descriptors = [NSArray arrayWithObjects:customSorting, alphabeticSorting, nil];
- [participants sortUsingDescriptors:descriptors];
-
- if (block) {
- block(participants, nil);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- block(nil, error);
- }
- }];
-
- return task;
- }
- - (NSURLSessionDataTask *)addParticipant:(NSString *)participant ofType:(NSString *)type toRoom:(NSString *)token forAccount:(TalkAccount *)account withCompletionBlock:(ParticipantModificationCompletionBlock)block
- {
- NSString *encodedToken = [token stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
- NSString *endpoint = [NSString stringWithFormat:@"room/%@/participants", encodedToken];
- NSInteger conversationAPIVersion = [self conversationAPIVersionForAccount:account];
- NSString *URLString = [self getRequestURLForEndpoint:endpoint withAPIVersion:conversationAPIVersion forAccount:account];
- NSMutableDictionary *parameters = [NSMutableDictionary new];
- [parameters setObject:participant forKey:@"newParticipant"];
- if (type && ![type isEqualToString:@""]) {
- [parameters setObject:type forKey:@"source"];
- }
-
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager POST:URLString parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- if (block) {
- block(nil);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- block(error);
- }
- }];
-
- return task;
- }
- - (NSURLSessionDataTask *)removeAttendee:(NSInteger)attendeeId fromRoom:(NSString *)token forAccount:(TalkAccount *)account withCompletionBlock:(ParticipantModificationCompletionBlock)block
- {
- NSString *encodedToken = [token stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
- NSString *endpoint = [NSString stringWithFormat:@"room/%@/attendees", encodedToken];
- NSInteger conversationAPIVersion = [self conversationAPIVersionForAccount:account];
- NSString *URLString = [self getRequestURLForEndpoint:endpoint withAPIVersion:conversationAPIVersion forAccount:account];
- NSDictionary *parameters = @{@"attendeeId" : @(attendeeId)};
-
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager DELETE:URLString parameters:parameters success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- if (block) {
- block(nil);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- block(error);
- }
- }];
-
- return task;
- }
- - (NSURLSessionDataTask *)removeParticipant:(NSString *)user fromRoom:(NSString *)token forAccount:(TalkAccount *)account withCompletionBlock:(ParticipantModificationCompletionBlock)block
- {
- NSString *encodedToken = [token stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
- NSString *endpoint = [NSString stringWithFormat:@"room/%@/participants", encodedToken];
- NSInteger conversationAPIVersion = [self conversationAPIVersionForAccount:account];
- NSString *URLString = [self getRequestURLForEndpoint:endpoint withAPIVersion:conversationAPIVersion forAccount:account];
- NSDictionary *parameters = @{@"participant" : user};
-
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager DELETE:URLString parameters:parameters success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- if (block) {
- block(nil);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- block(error);
- }
- }];
-
- return task;
- }
- - (NSURLSessionDataTask *)removeGuest:(NSString *)guest fromRoom:(NSString *)token forAccount:(TalkAccount *)account withCompletionBlock:(ParticipantModificationCompletionBlock)block
- {
- NSString *encodedToken = [token stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
- NSString *endpoint = [NSString stringWithFormat:@"room/%@/participants/guests", encodedToken];
- NSInteger conversationAPIVersion = [self conversationAPIVersionForAccount:account];
- NSString *URLString = [self getRequestURLForEndpoint:endpoint withAPIVersion:conversationAPIVersion forAccount:account];
- NSDictionary *parameters = @{@"participant" : guest};
-
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager DELETE:URLString parameters:parameters success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- if (block) {
- block(nil);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- block(error);
- }
- }];
-
- return task;
- }
- - (NSURLSessionDataTask *)removeSelfFromRoom:(NSString *)token forAccount:(TalkAccount *)account withCompletionBlock:(LeaveRoomCompletionBlock)block
- {
- NSString *encodedToken = [token stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
- NSString *endpoint = [NSString stringWithFormat:@"room/%@/participants/self", encodedToken];
- NSInteger conversationAPIVersion = [self conversationAPIVersionForAccount:account];
- NSString *URLString = [self getRequestURLForEndpoint:endpoint withAPIVersion:conversationAPIVersion forAccount:account];
-
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager DELETE:URLString parameters:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- if (block) {
- block(0, nil);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- block(statusCode, error);
- }
- }];
-
- return task;
- }
- - (NSURLSessionDataTask *)promoteParticipant:(NSString *)user toModeratorOfRoom:(NSString *)token forAccount:(TalkAccount *)account withCompletionBlock:(ParticipantModificationCompletionBlock)block
- {
- NSString *encodedToken = [token stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
- NSString *endpoint = [NSString stringWithFormat:@"room/%@/moderators", encodedToken];
- NSInteger conversationAPIVersion = [self conversationAPIVersionForAccount:account];
- NSString *URLString = [self getRequestURLForEndpoint:endpoint withAPIVersion:conversationAPIVersion forAccount:account];
- NSDictionary *parameters = @{@"participant" : user};
- if (conversationAPIVersion >= APIv3) {
- parameters = @{@"attendeeId" : user};
- }
-
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager POST:URLString parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- if (block) {
- block(nil);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- block(error);
- }
- }];
-
- return task;
- }
- - (NSURLSessionDataTask *)demoteModerator:(NSString *)moderator toParticipantOfRoom:(NSString *)token forAccount:(TalkAccount *)account withCompletionBlock:(ParticipantModificationCompletionBlock)block
- {
- NSString *encodedToken = [token stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
- NSString *endpoint = [NSString stringWithFormat:@"room/%@/moderators", encodedToken];
- NSInteger conversationAPIVersion = [self conversationAPIVersionForAccount:account];
- NSString *URLString = [self getRequestURLForEndpoint:endpoint withAPIVersion:conversationAPIVersion forAccount:account];
- NSDictionary *parameters = @{@"participant" : moderator};
- if (conversationAPIVersion >= APIv3) {
- parameters = @{@"attendeeId" : moderator};
- }
-
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager DELETE:URLString parameters:parameters success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- if (block) {
- block(nil);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- block(error);
- }
- }];
-
- return task;
- }
- - (NSURLSessionDataTask *)resendInvitationToParticipant:(NSString *)participant inRoom:(NSString *)token forAccount:(TalkAccount *)account withCompletionBlock:(ParticipantModificationCompletionBlock)block
- {
- NSString *encodedToken = [token stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
- NSString *endpoint = [NSString stringWithFormat:@"room/%@/participants/resend-invitations", encodedToken];
- NSInteger conversationAPIVersion = [self conversationAPIVersionForAccount:account];
- NSString *URLString = [self getRequestURLForEndpoint:endpoint withAPIVersion:conversationAPIVersion forAccount:account];
- NSDictionary *parameters = nil;
- if (participant) {
- parameters = @{@"attendeeId" : participant};
- }
-
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager POST:URLString parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- if (block) {
- block(nil);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- block(error);
- }
- }];
-
- return task;
- }
- #pragma mark - Call Controller
- - (NSURLSessionDataTask *)getPeersForCall:(NSString *)token forAccount:(TalkAccount *)account withCompletionBlock:(GetPeersForCallCompletionBlock)block
- {
- NSString *encodedToken = [token stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
- NSString *endpoint = [NSString stringWithFormat:@"call/%@", encodedToken];
- NSInteger callAPIVersion = [self callAPIVersionForAccount:account];
- NSString *URLString = [self getRequestURLForEndpoint:endpoint withAPIVersion:callAPIVersion forAccount:account];
-
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager GET:URLString parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- NSArray *responsePeers = [[responseObject objectForKey:@"ocs"] objectForKey:@"data"];
- NSMutableArray *peers = [[NSMutableArray alloc] initWithArray:responsePeers];
- if (block) {
- block(peers, nil, 0);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- block(nil, error, statusCode);
- }
- }];
-
- return task;
- }
- - (NSURLSessionDataTask *)joinCall:(NSString *)token withCallFlags:(NSInteger)flags silently:(BOOL)silently recordingConsent:(BOOL)recordingConsent forAccount:(TalkAccount *)account withCompletionBlock:(JoinCallCompletionBlock)block
- {
- NSString *encodedToken = [token stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
- NSString *endpoint = [NSString stringWithFormat:@"call/%@", encodedToken];
- NSInteger callAPIVersion = [self callAPIVersionForAccount:account];
- NSString *URLString = [self getRequestURLForEndpoint:endpoint withAPIVersion:callAPIVersion forAccount:account];
- NSMutableDictionary *parameters = [NSMutableDictionary new];
- [parameters setObject:@(flags) forKey:@"flags"];
- [parameters setObject:@(recordingConsent) forKey:@"recordingConsent"];
- if (silently) {
- [parameters setObject:@(silently) forKey:@"silent"];
- }
-
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager POST:URLString parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- if (block) {
- block(nil, 0);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- block(error, statusCode);
- }
- }];
-
- return task;
- }
- - (NSURLSessionDataTask *)leaveCall:(NSString *)token forAllParticipants:(BOOL)allParticipants forAccount:(TalkAccount *)account withCompletionBlock:(LeaveCallCompletionBlock)block
- {
- NSString *encodedToken = [token stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
- NSString *endpoint = [NSString stringWithFormat:@"call/%@", encodedToken];
- NSInteger callAPIVersion = [self callAPIVersionForAccount:account];
- NSString *URLString = [self getRequestURLForEndpoint:endpoint withAPIVersion:callAPIVersion forAccount:account];
- NSMutableDictionary *parameters = [[NSMutableDictionary alloc] init];
- if (allParticipants) {
- [parameters setObject:@(1) forKey:@"all"];
- }
-
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager DELETE:URLString parameters:parameters success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- if (block) {
- block(nil);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- block(error);
- }
- }];
-
- return task;
- }
- - (NSURLSessionDataTask *)sendCallNotificationToParticipant:(NSString *)participant inRoom:(NSString *)token forAccount:(TalkAccount *)account withCompletionBlock:(ParticipantModificationCompletionBlock)block
- {
- NSString *encodedToken = [token stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
- NSString *endpoint = [NSString stringWithFormat:@"/call/%@/ring/%@", encodedToken, participant];
- NSInteger callAPIVersion = [self callAPIVersionForAccount:account];
- NSString *URLString = [self getRequestURLForEndpoint:endpoint withAPIVersion:callAPIVersion forAccount:account];
- NSDictionary *parameters = nil;
- if (participant) {
- parameters = @{@"attendeeId" : participant};
- }
-
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager POST:URLString parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- if (block) {
- block(nil);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- block(error);
- }
- }];
-
- return task;
- }
- #pragma mark - Chat Controller
- - (NSURLSessionDataTask *)receiveChatMessagesOfRoom:(NSString *)token fromLastMessageId:(NSInteger)messageId history:(BOOL)history includeLastMessage:(BOOL)include timeout:(BOOL)timeout lastCommonReadMessage:(NSInteger)lastCommonReadMessage setReadMarker:(BOOL)setReadMarker markNotificationsAsRead:(BOOL)markNotificationsAsRead forAccount:(TalkAccount *)account withCompletionBlock:(GetChatMessagesCompletionBlock)block
- {
- NSString *encodedToken = [token stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
- NSString *endpoint = [NSString stringWithFormat:@"chat/%@", encodedToken];
- NSInteger chatAPIVersion = [self chatAPIVersionForAccount:account];
- NSString *URLString = [self getRequestURLForEndpoint:endpoint withAPIVersion:chatAPIVersion forAccount:account];
- NSDictionary *parameters = @{@"lookIntoFuture" : history ? @(0) : @(1),
- @"limit" : @(kReceivedChatMessagesLimit),
- @"timeout" : timeout ? @(30) : @(0),
- @"lastKnownMessageId" : @(messageId),
- @"lastCommonReadId" : @(lastCommonReadMessage),
- @"setReadMarker" : setReadMarker ? @(1) : @(0),
- @"includeLastKnown" : include ? @(1) : @(0),
- @"markNotificationsAsRead" : markNotificationsAsRead ? @(1) : @(0)};
-
- NCAPISessionManager *apiSessionManager;
- if (timeout) {
- apiSessionManager = [_longPollingApiSessionManagers objectForKey:account.accountId];
- } else {
- apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- }
- NSURLSessionDataTask *task = [apiSessionManager GET:URLString parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- NSArray *responseMessages = [[responseObject objectForKey:@"ocs"] objectForKey:@"data"];
- // Get X-Chat-Last-Given and X-Chat-Last-Common-Read headers
- NSHTTPURLResponse *response = ((NSHTTPURLResponse *)[task response]);
- NSDictionary *headers = [response allHeaderFields];
- NSString *lastKnowMessageHeader = [headers objectForKey:@"X-Chat-Last-Given"];
- NSInteger lastKnownMessage = -1;
- if (lastKnowMessageHeader) {
- lastKnownMessage = [lastKnowMessageHeader integerValue];
- }
- NSString *lastCommonReadMessageHeader = [headers objectForKey:@"X-Chat-Last-Common-Read"];
- NSInteger lastCommonReadMessage = -1;
- if (lastCommonReadMessageHeader) {
- lastCommonReadMessage = [lastCommonReadMessageHeader integerValue];
- }
-
- if (block) {
- block(responseMessages, lastKnownMessage, lastCommonReadMessage, nil, 0);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- block(nil, -1, -1, error, statusCode);
- }
- }];
-
- return task;
- }
- - (NSURLSessionDataTask *)sendChatMessage:(NSString *)message toRoom:(NSString *)token displayName:(NSString *)displayName replyTo:(NSInteger)replyTo referenceId:(NSString *)referenceId silently:(BOOL)silently forAccount:(TalkAccount *)account withCompletionBlock:(SendChatMessagesCompletionBlock)block
- {
- NSString *encodedToken = [token stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
- NSString *endpoint = [NSString stringWithFormat:@"chat/%@", encodedToken];
- NSInteger chatAPIVersion = [self chatAPIVersionForAccount:account];
- NSString *URLString = [self getRequestURLForEndpoint:endpoint withAPIVersion:chatAPIVersion forAccount:account];
- NSMutableDictionary *parameters = [NSMutableDictionary new];
- [parameters setObject:message forKey:@"message"];
- if (replyTo > -1) {
- [parameters setObject:@(replyTo) forKey:@"replyTo"];
- }
- if (referenceId) {
- [parameters setObject:referenceId forKey:@"referenceId"];
- }
- if (silently) {
- [parameters setObject:@(silently) forKey:@"silent"];
- }
-
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- // Workaround: When sendChatMessage is called from Share Extension session managers are not initialized.
- if (!apiSessionManager) {
- [self initSessionManagers];
- apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- }
- NSURLSessionDataTask *task = [apiSessionManager POST:URLString parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- if (block) {
- block(nil);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- block(error);
- }
- }];
-
- return task;
- }
- - (NSURLSessionDataTask *)deleteChatMessageInRoom:(NSString *)token withMessageId:(NSInteger)messageId forAccount:(TalkAccount *)account withCompletionBlock:(DeleteChatMessageCompletionBlock)block
- {
- NSString *encodedToken = [token stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
- NSString *endpoint = [NSString stringWithFormat:@"chat/%@/%ld", encodedToken, (long)messageId];
- NSInteger chatAPIVersion = [self chatAPIVersionForAccount:account];
- NSString *URLString = [self getRequestURLForEndpoint:endpoint withAPIVersion:chatAPIVersion forAccount:account];
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager DELETE:URLString parameters:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- NSDictionary *messageDict = [[responseObject objectForKey:@"ocs"] objectForKey:@"data"];
- if (block) {
- NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)task.response;
- block(messageDict, nil, httpResponse.statusCode);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- block(nil, error, statusCode);
- }
- }];
-
- return task;
- }
- - (NSURLSessionDataTask *)editChatMessageInRoom:(NSString *)token withMessageId:(NSInteger)messageId withMessage:(NSString *)message forAccount:(TalkAccount *)account withCompletionBlock:(EditChatMessageCompletionBlock)block
- {
- NSString *encodedToken = [token stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
- NSString *endpoint = [NSString stringWithFormat:@"chat/%@/%ld", encodedToken, (long)messageId];
- NSInteger chatAPIVersion = [self chatAPIVersionForAccount:account];
- NSString *URLString = [self getRequestURLForEndpoint:endpoint withAPIVersion:chatAPIVersion forAccount:account];
- NSMutableDictionary *parameters = [NSMutableDictionary new];
- [parameters setObject:message forKey:@"message"];
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager PUT:URLString parameters:parameters success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- NSDictionary *messageDict = [[responseObject objectForKey:@"ocs"] objectForKey:@"data"];
- if (block) {
- NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)task.response;
- block(messageDict, nil, httpResponse.statusCode);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- block(nil, error, statusCode);
- }
- }];
- return task;
- }
- - (NSURLSessionDataTask *)clearChatHistoryInRoom:(NSString *)token forAccount:(TalkAccount *)account withCompletionBlock:(ClearChatHistoryCompletionBlock)block
- {
- NSString *encodedToken = [token stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
- NSString *endpoint = [NSString stringWithFormat:@"chat/%@", encodedToken];
- NSInteger chatAPIVersion = [self chatAPIVersionForAccount:account];
- NSString *URLString = [self getRequestURLForEndpoint:endpoint withAPIVersion:chatAPIVersion forAccount:account];
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager DELETE:URLString parameters:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- NSDictionary *messageDict = [[responseObject objectForKey:@"ocs"] objectForKey:@"data"];
- if (block) {
- NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)task.response;
- block(messageDict, nil, httpResponse.statusCode);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- block(nil, error, statusCode);
- }
- }];
-
- return task;
- }
- - (NSURLSessionDataTask *)shareRichObject:(NSDictionary *)richObject inRoom:(NSString *)token forAccount:(TalkAccount *)account withCompletionBlock:(SendChatMessagesCompletionBlock)block
- {
- NSString *encodedToken = [token stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
- NSString *endpoint = [NSString stringWithFormat:@"chat/%@/share", encodedToken];
- NSInteger chatAPIVersion = [self chatAPIVersionForAccount:account];
- NSString *URLString = [self getRequestURLForEndpoint:endpoint withAPIVersion:chatAPIVersion forAccount:account];
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager POST:URLString parameters:richObject progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- if (block) {
- block(nil);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- block(error);
- }
- }];
-
- return task;
- }
- - (NSURLSessionDataTask *)setChatReadMarker:(NSInteger)lastReadMessage inRoom:(NSString *)token forAccount:(TalkAccount *)account withCompletionBlock:(SendChatMessagesCompletionBlock)block
- {
- NSString *encodedToken = [token stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
- NSString *endpoint = [NSString stringWithFormat:@"chat/%@/read", encodedToken];
- NSInteger chatAPIVersion = [self chatAPIVersionForAccount:account];
- NSString *URLString = [self getRequestURLForEndpoint:endpoint withAPIVersion:chatAPIVersion forAccount:account];
- NSDictionary *parameters = nil;
- if (lastReadMessage > 0) {
- parameters = @{@"lastReadMessage" : @(lastReadMessage)};
- }
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager POST:URLString parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- if (block) {
- block(nil);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- block(error);
- }
- }];
-
- return task;
- }
- - (NSURLSessionDataTask *)markChatAsUnreadInRoom:(NSString *)token forAccount:(TalkAccount *)account withCompletionBlock:(SendChatMessagesCompletionBlock)block
- {
- NSString *encodedToken = [token stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
- NSString *endpoint = [NSString stringWithFormat:@"chat/%@/read", encodedToken];
- NSInteger chatAPIVersion = [self chatAPIVersionForAccount:account];
- NSString *URLString = [self getRequestURLForEndpoint:endpoint withAPIVersion:chatAPIVersion forAccount:account];
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager DELETE:URLString parameters:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- if (block) {
- block(nil);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- block(error);
- }
- }];
-
- return task;
- }
- - (NSURLSessionDataTask *)getSharedItemsOverviewInRoom:(NSString *)token withLimit:(NSInteger)limit forAccount:(TalkAccount *)account withCompletionBlock:(GetSharedItemsOverviewCompletionBlock)block
- {
- NSString *encodedToken = [token stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
- NSString *endpoint = [NSString stringWithFormat:@"chat/%@/share/overview", encodedToken];
- NSInteger chatAPIVersion = [self chatAPIVersionForAccount:account];
- NSString *URLString = [self getRequestURLForEndpoint:endpoint withAPIVersion:chatAPIVersion forAccount:account];
- NSMutableDictionary *parameters = [NSMutableDictionary new];
- if (limit > -1) {
- [parameters setObject:@(limit) forKey:@"limit"];
- }
-
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager GET:URLString parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- NSDictionary *responseSharedItems = [[responseObject objectForKey:@"ocs"] objectForKey:@"data"];
- // Create dictionary [String: [NCChatMessage]]
- NSMutableDictionary *sharedItems = [NSMutableDictionary new];
- for (NSString *key in responseSharedItems.allKeys) {
- NSArray *responseMessages = [responseSharedItems objectForKey:key];
- NSMutableArray *messages = [NSMutableArray new];
- for (NSDictionary *messageDict in responseMessages) {
- NCChatMessage *message = [NCChatMessage messageWithDictionary:messageDict];
- if (message) {
- [messages addObject:message];
- }
- }
- [sharedItems setObject:messages forKey:key];
- }
-
- if (block) {
- block(sharedItems, nil, 0);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- block(nil, error, statusCode);
- }
- }];
-
- return task;
- }
- - (NSURLSessionDataTask *)getSharedItemsOfType:(NSString *)objectType fromLastMessageId:(NSInteger)messageId withLimit:(NSInteger)limit inRoom:(NSString *)token forAccount:(TalkAccount *)account withCompletionBlock:(GetSharedItemsCompletionBlock)block
- {
- NSString *encodedToken = [token stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
- NSString *endpoint = [NSString stringWithFormat:@"chat/%@/share", encodedToken];
- NSInteger chatAPIVersion = [self chatAPIVersionForAccount:account];
- NSString *URLString = [self getRequestURLForEndpoint:endpoint withAPIVersion:chatAPIVersion forAccount:account];
- NSMutableDictionary *parameters = [NSMutableDictionary new];
- [parameters setObject:objectType forKey:@"objectType"];
- if (messageId > -1) {
- [parameters setObject:@(messageId) forKey:@"lastKnownMessageId"];
- }
- if (limit > -1) {
- [parameters setObject:@(limit) forKey:@"limit"];
- }
-
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager GET:URLString parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- id responseData = [[responseObject objectForKey:@"ocs"] objectForKey:@"data"];
- // Create array [NCChatMessage]
- NSMutableArray *sharedItems = [NSMutableArray new];
- if ([responseData isKindOfClass:[NSDictionary class]]) {
- NSDictionary *responseSharedItems = responseData;
- for (NSDictionary *messageDict in responseSharedItems.allValues) {
- NCChatMessage *message = [NCChatMessage messageWithDictionary:messageDict];
- [sharedItems addObject:message];
- }
- }
- // Get X-Chat-Last-Given
- NSHTTPURLResponse *response = ((NSHTTPURLResponse *)[task response]);
- NSDictionary *headers = [response allHeaderFields];
- NSString *lastKnowMessageHeader = [headers objectForKey:@"X-Chat-Last-Given"];
- NSInteger lastKnownMessage = -1;
- if (lastKnowMessageHeader) {
- lastKnownMessage = [lastKnowMessageHeader integerValue];
- }
-
- if (block) {
- block(sharedItems, lastKnownMessage, nil, 0);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- block(nil, -1, error, statusCode);
- }
- }];
-
- return task;
- }
- - (NSURLSessionDataTask *)getMessageContextInRoom:(NSString *)token forMessageId:(NSInteger)messageId withLimit:(NSInteger)limit forAccount:(TalkAccount *)account withCompletionBlock:(GetMessageContextInRoomCompletionBlock)block
- {
- NSString *encodedToken = [token stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
- NSString *endpoint = [NSString stringWithFormat:@"chat/%@/%ld/context", encodedToken, (long)messageId];
- NSInteger chatAPIVersion = [self chatAPIVersionForAccount:account];
- NSString *URLString = [self getRequestURLForEndpoint:endpoint withAPIVersion:chatAPIVersion forAccount:account];
- NSMutableDictionary *parameters = [[NSMutableDictionary alloc] init];
- if (limit && limit > 0) {
- // Limit is optional server-side and defaults to 50, maximum is 100
- [parameters setObject:@(limit) forKey:@"limit"];
- }
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager GET:URLString parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- NSArray *responseMessages = [[responseObject objectForKey:@"ocs"] objectForKey:@"data"];
- if (block) {
- block(responseMessages, nil, 0);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- block(nil, error, statusCode);
- }
- }];
- return task;
- }
- #pragma mark - Translations Controller
- - (NSURLSessionDataTask *)getAvailableTranslationsForAccount:(TalkAccount *)account withCompletionBlock:(GetTranslationsCompletionBlock)block
- {
- NSString *URLString = [NSString stringWithFormat:@"%@/ocs/v2.php/translation/languages", account.server];
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager GET:URLString parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- NSDictionary *translationDict = [[responseObject objectForKey:@"ocs"] objectForKey:@"data"];
- if (block) {
- NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)task.response;
- NSArray *translations = [[NCDatabaseManager sharedInstance] translationsFromTranslationsArray:[translationDict objectForKey:@"languages"]];
- BOOL languageDetection = [translationDict objectForKey:@"languageDetection"];
- block(translations, languageDetection, nil, httpResponse.statusCode);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- block(@[], NO, error, statusCode);
- }
- }];
- return task;
- }
- - (NSURLSessionDataTask *)translateMessage:(NSString *)message from:(NSString *)from to:(NSString *)to forAccount:(TalkAccount *)account withCompletionBlock:(MessageTranslationCompletionBlock)block
- {
- NSString *URLString = [NSString stringWithFormat:@"%@/ocs/v2.php/translation/translate", account.server];
- NSMutableDictionary *parameters = [NSMutableDictionary new];
- [parameters setValue:message forKey:@"text"];
- [parameters setValue:to forKey:@"toLanguage"];
- if (from.length > 0) {
- [parameters setValue:from forKey:@"fromLanguage"];
- }
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager POST:URLString parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- NSDictionary *translationDict = [[responseObject objectForKey:@"ocs"] objectForKey:@"data"];
- if (block) {
- NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)task.response;
- block(translationDict, nil, httpResponse.statusCode);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- NSDictionary *failureDict = [[[self getFailureResponseObjectFromError:error] objectForKey:@"ocs"] objectForKey:@"data"];
- if (block) {
- block(failureDict, error, statusCode);
- }
- }];
- return task;
- }
- #pragma mark - Reactions Controller
- - (NSURLSessionDataTask *)addReaction:(NSString *)reaction toMessage:(NSInteger)messageId inRoom:(NSString *)token forAccount:(TalkAccount *)account withCompletionBlock:(MessageReactionCompletionBlock)block
- {
- NSString *encodedToken = [token stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
- NSString *endpoint = [NSString stringWithFormat:@"reaction/%@/%ld", encodedToken, (long)messageId];
- NSInteger reactionsAPIVersion = [self reactionsAPIVersionForAccount:account];
- NSString *URLString = [self getRequestURLForEndpoint:endpoint withAPIVersion:reactionsAPIVersion forAccount:account];
- NSDictionary *parameters = @{@"reaction" : reaction};
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager POST:URLString parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- NSDictionary *reactionsDict = [[responseObject objectForKey:@"ocs"] objectForKey:@"data"];
- if (block) {
- NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)task.response;
- // When there are no elements, the server returns an empty array instead of an empty dictionary
- if (![reactionsDict isKindOfClass:[NSDictionary class]]) {
- block(@{}, nil, httpResponse.statusCode);
- } else {
- block(reactionsDict, nil, httpResponse.statusCode);
- }
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- block(nil, error, statusCode);
- }
- }];
-
- return task;
- }
- - (NSURLSessionDataTask *)removeReaction:(NSString *)reaction fromMessage:(NSInteger)messageId inRoom:(NSString *)token forAccount:(TalkAccount *)account withCompletionBlock:(MessageReactionCompletionBlock)block
- {
- NSString *encodedToken = [token stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
- NSString *endpoint = [NSString stringWithFormat:@"reaction/%@/%ld", encodedToken, (long)messageId];
- NSInteger reactionsAPIVersion = [self reactionsAPIVersionForAccount:account];
- NSString *URLString = [self getRequestURLForEndpoint:endpoint withAPIVersion:reactionsAPIVersion forAccount:account];
- NSDictionary *parameters = @{@"reaction" : reaction};
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager DELETE:URLString parameters:parameters success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- NSDictionary *reactionsDict = [[responseObject objectForKey:@"ocs"] objectForKey:@"data"];
- if (block) {
- NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)task.response;
- // When there are no elements, the server returns an empty array instead of an empty dictionary
- if (![reactionsDict isKindOfClass:[NSDictionary class]]) {
- block(@{}, nil, httpResponse.statusCode);
- } else {
- block(reactionsDict, nil, httpResponse.statusCode);
- }
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- block(nil, error, statusCode);
- }
- }];
-
- return task;
- }
- - (NSURLSessionDataTask *)getReactions:(NSString *)reaction fromMessage:(NSInteger)messageId inRoom:(NSString *)token forAccount:(TalkAccount *)account withCompletionBlock:(MessageReactionCompletionBlock)block
- {
- NSString *encodedToken = [token stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
- NSString *endpoint = [NSString stringWithFormat:@"reaction/%@/%ld", encodedToken, (long)messageId];
- NSInteger reactionsAPIVersion = [self reactionsAPIVersionForAccount:account];
- NSString *URLString = [self getRequestURLForEndpoint:endpoint withAPIVersion:reactionsAPIVersion forAccount:account];
- NSDictionary *parameters = nil;
- if (reaction) {
- parameters = @{@"reaction" : reaction};
- }
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager GET:URLString parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- NSDictionary *reactionsDict = [[responseObject objectForKey:@"ocs"] objectForKey:@"data"];
- if (block) {
- NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)task.response;
- // When there are no elements, the server returns an empty array instead of an empty dictionary
- if (![reactionsDict isKindOfClass:[NSDictionary class]]) {
- block(@{}, nil, httpResponse.statusCode);
- } else {
- block(reactionsDict, nil, httpResponse.statusCode);
- }
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- block(nil, error, statusCode);
- }
- }];
-
- return task;
- }
- #pragma mark - Polls Controller
- - (NSURLSessionDataTask *)createPollWithQuestion:(NSString *)question options:(NSArray *)options resultMode:(NCPollResultMode)resultMode maxVotes:(NSInteger)maxVotes inRoom:(NSString *)token forAccount:(TalkAccount *)account withCompletionBlock:(PollCompletionBlock)block
- {
- NSString *encodedToken = [token stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
- NSString *endpoint = [NSString stringWithFormat:@"poll/%@", encodedToken];
- NSInteger pollsAPIVersion = [self pollsAPIVersionForAccount:account];
- NSString *URLString = [self getRequestURLForEndpoint:endpoint withAPIVersion:pollsAPIVersion forAccount:account];
- NSDictionary *parameters = @{@"question" : question,
- @"options" : options,
- @"resultMode" : @(resultMode),
- @"maxVotes" : @(maxVotes)
- };
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager POST:URLString parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- NSDictionary *pollDict = [[responseObject objectForKey:@"ocs"] objectForKey:@"data"];
- NCPoll *poll = [NCPoll initWithPollDictionary:pollDict];
- if (block) {
- NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)task.response;
- block(poll, nil, httpResponse.statusCode);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- block(nil, error, statusCode);
- }
- }];
-
- return task;
- }
- - (NSURLSessionDataTask *)getPollWithId:(NSInteger)pollId inRoom:(NSString *)token forAccount:(TalkAccount *)account withCompletionBlock:(PollCompletionBlock)block
- {
- NSString *encodedToken = [token stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
- NSString *endpoint = [NSString stringWithFormat:@"poll/%@/%ld", encodedToken, (long)pollId];
- NSInteger pollsAPIVersion = [self pollsAPIVersionForAccount:account];
- NSString *URLString = [self getRequestURLForEndpoint:endpoint withAPIVersion:pollsAPIVersion forAccount:account];
-
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager GET:URLString parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- NSDictionary *pollDict = [[responseObject objectForKey:@"ocs"] objectForKey:@"data"];
- NCPoll *poll = [NCPoll initWithPollDictionary:pollDict];
- if (block) {
- NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)task.response;
- block(poll, nil, httpResponse.statusCode);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- block(nil, error, statusCode);
- }
- }];
-
- return task;
- }
- - (NSURLSessionDataTask *)voteOnPollWithId:(NSInteger)pollId inRoom:(NSString *)token withOptions:(NSArray *)options forAccount:(TalkAccount *)account withCompletionBlock:(PollCompletionBlock)block
- {
- NSString *encodedToken = [token stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
- NSString *endpoint = [NSString stringWithFormat:@"poll/%@/%ld", encodedToken, (long)pollId];
- NSInteger pollsAPIVersion = [self pollsAPIVersionForAccount:account];
- NSString *URLString = [self getRequestURLForEndpoint:endpoint withAPIVersion:pollsAPIVersion forAccount:account];
- NSDictionary *parameters = @{@"optionIds" : options};
-
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager POST:URLString parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- NSDictionary *pollDict = [[responseObject objectForKey:@"ocs"] objectForKey:@"data"];
- NCPoll *poll = [NCPoll initWithPollDictionary:pollDict];
- if (block) {
- NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)task.response;
- block(poll, nil, httpResponse.statusCode);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- block(nil, error, statusCode);
- }
- }];
-
- return task;
- }
- - (NSURLSessionDataTask *)closePollWithId:(NSInteger)pollId inRoom:(NSString *)token forAccount:(TalkAccount *)account withCompletionBlock:(PollCompletionBlock)block
- {
- NSString *encodedToken = [token stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
- NSString *endpoint = [NSString stringWithFormat:@"poll/%@/%ld", encodedToken, (long)pollId];
- NSInteger pollsAPIVersion = [self pollsAPIVersionForAccount:account];
- NSString *URLString = [self getRequestURLForEndpoint:endpoint withAPIVersion:pollsAPIVersion forAccount:account];
-
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager DELETE:URLString parameters:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- NSDictionary *pollDict = [[responseObject objectForKey:@"ocs"] objectForKey:@"data"];
- NCPoll *poll = [NCPoll initWithPollDictionary:pollDict];
- if (block) {
- NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)task.response;
- block(poll, nil, httpResponse.statusCode);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- block(nil, error, statusCode);
- }
- }];
-
- return task;
- }
- #pragma mark - Signaling Controller
- - (NSURLSessionDataTask *)sendSignalingMessages:(NSString *)messages toRoom:(NSString *)token forAccount:(TalkAccount *)account withCompletionBlock:(SendSignalingMessagesCompletionBlock)block;
- {
- NSString *encodedToken = [token stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
- NSString *endpoint = (token) ? [NSString stringWithFormat:@"signaling/%@", encodedToken] : @"signaling";
- NSInteger signalingAPIVersion = [self signalingAPIVersionForAccount:account];
- NSString *URLString = [self getRequestURLForEndpoint:endpoint withAPIVersion:signalingAPIVersion forAccount:account];
- NSDictionary *parameters = @{@"messages" : messages};
-
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager POST:URLString parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- if (block) {
- block(nil);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- block(error);
- }
- }];
-
- return task;
- }
- - (NSURLSessionDataTask *)pullSignalingMessagesFromRoom:(NSString *)token forAccount:(TalkAccount *)account withCompletionBlock:(PullSignalingMessagesCompletionBlock)block
- {
- NSString *encodedToken = [token stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
- NSString *endpoint = (token) ? [NSString stringWithFormat:@"signaling/%@", encodedToken] : @"signaling";
- NSInteger signalingAPIVersion = [self signalingAPIVersionForAccount:account];
- NSString *URLString = [self getRequestURLForEndpoint:endpoint withAPIVersion:signalingAPIVersion forAccount:account];
-
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager GET:URLString
- parameters:nil progress:nil
- success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- NSDictionary *responseDict = responseObject;
- if (block) {
- block(responseDict, nil);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- block(nil, error);
- }
- }];
-
- return task;
- }
- - (NSString *)authenticationBackendUrlForAccount:(TalkAccount *)account
- {
- NSString *endpoint = @"signaling/backend";
- NSInteger signalingAPIVersion = [self signalingAPIVersionForAccount:account];
- return [self getRequestURLForEndpoint:endpoint withAPIVersion:signalingAPIVersion forAccount:account];
- }
- #pragma mark - Settings
- - (NSURLSessionDataTask *)setReadStatusPrivacySettingEnabled:(BOOL)enabled forAccount:(TalkAccount *)account withCompletionBlock:(SetReadStatusPrivacySettingCompletionBlock)block
- {
- NSString *URLString = [self getRequestURLForEndpoint:@"settings/user" withAPIVersion:APIv1 forAccount:account];
- NSDictionary *parameters = @{@"key" : @"read_status_privacy",
- @"value" : @(enabled)};
-
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager POST:URLString parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- if (block) {
- block(nil);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- block(error);
- }
- }];
-
- return task;
- }
- - (NSURLSessionDataTask *)setTypingPrivacySettingEnabled:(BOOL)enabled forAccount:(TalkAccount *)account withCompletionBlock:(SetTypingPrivacySettingCompletionBlock)block
- {
- NSString *URLString = [self getRequestURLForEndpoint:@"settings/user" withAPIVersion:APIv1 forAccount:account];
- NSDictionary *parameters = @{@"key" : @"typing_privacy",
- @"value" : @(enabled)};
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager POST:URLString parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- if (block) {
- block(nil);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- block(error);
- }
- }];
- return task;
- }
- #pragma mark - Files
- - (void)readFolderForAccount:(TalkAccount *)account atPath:(NSString *)path depth:(NSString *)depth withCompletionBlock:(ReadFolderCompletionBlock)block
- {
- [self setupNCCommunicationForAccount:account];
- NSString *serverUrlString = [NSString stringWithFormat:@"%@%@/%@", account.server, [self filesPathForAccount:account], path ? path : @""];
- // We don't need all properties, so we limit the request to the needed ones to reduce size and processing time
- NSString *body = @"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\
- <d:propfind xmlns:d=\"DAV:\" xmlns:oc=\"http://owncloud.org/ns\" xmlns:nc=\"http://nextcloud.org/ns\">\
- <d:prop>\
- <d:getlastmodified />\
- <d:getcontenttype />\
- <d:resourcetype />\
- <fileid xmlns=\"http://owncloud.org/ns\"/>\
- <is-encrypted xmlns=\"http://nextcloud.org/ns\"/>\
- <has-preview xmlns=\"http://nextcloud.org/ns\"/>\
- </d:prop>\
- </d:propfind>";
- NKRequestOptions *options = [[NKRequestOptions alloc] initWithEndpoint:nil customHeader:nil customUserAgent:nil contentType:nil e2eToken:nil timeout:60 queue:dispatch_get_main_queue()];
- [[NextcloudKit shared] readFileOrFolderWithServerUrlFileName:serverUrlString depth:depth showHiddenFiles:NO includeHiddenFiles:@[] requestBody:[body dataUsingEncoding:NSUTF8StringEncoding] options:options completion:^(NSString *account, NSArray<NKFile *> *files, NSData *responseDates, NKError *error) {
- if (error.errorCode == 0 && block) {
- block(files, nil);
- } else if (block) {
- NSError *nsError = [NSError errorWithDomain:NSURLErrorDomain code:error.errorCode userInfo:nil];
- block(nil, nsError);
- }
- }];
- }
- - (void)shareFileOrFolderForAccount:(TalkAccount *)account atPath:(NSString *)path toRoom:(NSString *)token talkMetaData:(NSDictionary *)talkMetaData withCompletionBlock:(ShareFileOrFolderCompletionBlock)block
- {
- NSString *URLString = [NSString stringWithFormat:@"%@/ocs/v2.php/apps/files_sharing/api/v1/shares", account.server];
-
- NSMutableDictionary *parameters = [NSMutableDictionary new];
- [parameters setObject:path forKey:@"path"];
- [parameters setObject:@(10) forKey:@"shareType"];
- [parameters setObject:token forKey:@"shareWith"];
-
- if (talkMetaData) {
- NSError *error = nil;
- NSData *jsonData = [NSJSONSerialization dataWithJSONObject:talkMetaData
- options:0
- error:&error];
- if (error) {
- NSLog(@"Error serializing JSON: %@", error);
- } else {
- [parameters setObject:[[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding] forKey:@"talkMetaData"];
- }
- }
-
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- // Workaround: When shareFileOrFolderForAccount is called from Share Extension session managers are not initialized.
- if (!apiSessionManager) {
- [self initSessionManagers];
- apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- }
- [apiSessionManager POST:URLString parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- if (block) {
- block(nil);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)task.response;
- // Do not return error when re-sharing a file or folder.
- if (httpResponse.statusCode == 403 && block) {
- block(nil);
- } else if (block) {
- block(error);
- }
- }];
- }
- - (void)getFileByFileId:(TalkAccount *)account fileId:(NSString *)fileId withCompletionBlock:(GetFileByFileIdCompletionBlock)block
- {
- [self setupNCCommunicationForAccount:account];
-
- NSString *body = @"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\
- <d:searchrequest xmlns:d=\"DAV:\" xmlns:oc=\"http://nextcloud.com/ns\">\
- <d:basicsearch>\
- <d:select>\
- <d:prop>\
- <d:displayname />\
- <d:getcontenttype />\
- <d:resourcetype />\
- <d:getcontentlength />\
- <d:getlastmodified />\
- <d:creationdate />\
- <d:getetag />\
- <d:quota-used-bytes />\
- <d:quota-available-bytes />\
- <oc:permissions xmlns:oc=\"http://owncloud.org/ns\" />\
- <oc:id xmlns:oc=\"http://owncloud.org/ns\" />\
- <oc:size xmlns:oc=\"http://owncloud.org/ns\" />\
- <oc:favorite xmlns:oc=\"http://owncloud.org/ns\" />\
- </d:prop>\
- </d:select>\
- <d:from>\
- <d:scope>\
- <d:href>/files/%@</d:href>\
- <d:depth>infinity</d:depth>\
- </d:scope>\
- </d:from>\
- <d:where>\
- <d:eq>\
- <d:prop>\
- <oc:fileid xmlns:oc=\"http://owncloud.org/ns\" />\
- </d:prop>\
- <d:literal>%@</d:literal>\
- </d:eq>\
- </d:where>\
- <d:orderby />\
- </d:basicsearch>\
- </d:searchrequest>";
-
- NSString *bodyRequest = [NSString stringWithFormat:body, account.userId, fileId];
- NKRequestOptions *options = [[NKRequestOptions alloc] initWithEndpoint:nil customHeader:nil customUserAgent:nil contentType:nil e2eToken:nil timeout:60 queue:dispatch_get_main_queue()];
- [[NextcloudKit shared] searchBodyRequestWithServerUrl:account.server requestBody:bodyRequest showHiddenFiles:YES includeHiddenFiles:@[] options:options completion:^(NSString *account, NSArray<NKFile *> *files, NSData *data, NKError *error) {
- if (block) {
- if ([files count] > 0) {
- block([files objectAtIndex:0], error.errorCode, error.errorDescription);
- } else {
- block(nil, error.errorCode, error.errorDescription);
- }
- }
- }];
- }
- - (void)uniqueNameForFileUploadWithName:(NSString *)fileName originalName:(BOOL)isOriginalName forAccount:(TalkAccount *)account withCompletionBlock:(GetFileUniqueNameCompletionBlock)block
- {
- [self setupNCCommunicationForAccount:account];
-
- NSString *fileServerPath = [self serverFilePathForFileName:fileName andAccountId:account.accountId];
- NSString *fileServerURL = [self serverFileURLForFilePath:fileServerPath andAccountId:account.accountId];
- NKRequestOptions *options = [[NKRequestOptions alloc] initWithEndpoint:nil customHeader:nil customUserAgent:nil contentType:nil e2eToken:nil timeout:60 queue:dispatch_get_main_queue()];
- [[NextcloudKit shared] readFileOrFolderWithServerUrlFileName:fileServerURL depth:@"0" showHiddenFiles:NO includeHiddenFiles:@[] requestBody:nil options:options completion:^(NSString *accountId, NSArray<NKFile *> *files, NSData *data, NKError *error) {
- // File already exists
- if (error.errorCode == 0 && files.count == 1) {
- NSString *alternativeName = [self alternativeNameForFileName:fileName original:isOriginalName];
- [self uniqueNameForFileUploadWithName:alternativeName originalName:NO forAccount:account withCompletionBlock:block];
- // File does not exist
- } else if (error.errorCode == 404) {
- if (block) {
- block(fileServerURL, fileServerPath, 0, nil);
- }
- } else {
- NSLog(@"Error checking file name: %@", error.errorDescription);
- if (block) {
- block(nil, nil, error.errorCode, error.errorDescription);
- }
- }
- }];
- }
- - (void)checkOrCreateAttachmentFolderForAccount:(TalkAccount *)account withCompletionBlock:(CheckAttachmentFolderCompletionBlock)block
- {
- [self setupNCCommunicationForAccount:account];
-
- NSString *attachmentFolderServerURL = [self attachmentFolderServerURLForAccountId:account.accountId];
- NKRequestOptions *options = [[NKRequestOptions alloc] initWithEndpoint:nil customHeader:nil customUserAgent:nil contentType:nil e2eToken:nil timeout:60 queue:dispatch_get_main_queue()];
- [[NextcloudKit shared] readFileOrFolderWithServerUrlFileName:attachmentFolderServerURL depth:@"0" showHiddenFiles:NO includeHiddenFiles:@[] requestBody:nil options:options completion:^(NSString *accountId, NSArray<NKFile *> *files, NSData *data, NKError *error) {
- // Attachment folder do not exist
- if (error.errorCode == 404) {
- [[NextcloudKit shared] createFolderWithServerUrlFileName:attachmentFolderServerURL options:options completion:^(NSString *accountId, NSString *ocId, NSDate *data, NKError *error) {
- if (block) {
- block(error.errorCode == 0, error.errorCode);
- }
- }];
- } else {
- NSLog(@"Error checking attachment folder: %@", error.errorDescription);
- if (block) {
- block(NO, error.errorCode);
- }
- }
- }];
- }
- - (NSString *)serverFilePathForFileName:(NSString *)fileName andAccountId:(NSString *)accountId;
- {
- ServerCapabilities *serverCapabilities = [[NCDatabaseManager sharedInstance] serverCapabilitiesForAccountId:accountId];
- NSString *attachmentsFolder = serverCapabilities.attachmentsFolder ? serverCapabilities.attachmentsFolder : @"";
- return [NSString stringWithFormat:@"%@/%@", attachmentsFolder, fileName];
- }
- - (NSString *)attachmentFolderServerURLForAccountId:(NSString *)accountId;
- {
- TalkAccount *account = [[NCDatabaseManager sharedInstance] talkAccountForAccountId:accountId];
- ServerCapabilities *serverCapabilities = [[NCDatabaseManager sharedInstance] serverCapabilitiesForAccountId:accountId];
- NSString *attachmentsFolder = serverCapabilities.attachmentsFolder ? serverCapabilities.attachmentsFolder : @"";
- return [NSString stringWithFormat:@"%@%@%@", account.server, [self filesPathForAccount:account], attachmentsFolder];
- }
- - (NSString *)serverFileURLForFilePath:(NSString *)filePath andAccountId:(NSString *)accountId;
- {
- TalkAccount *account = [[NCDatabaseManager sharedInstance] talkAccountForAccountId:accountId];
- return [NSString stringWithFormat:@"%@%@%@", account.server, [self filesPathForAccount:account], filePath];
- }
- - (NSString *)alternativeNameForFileName:(NSString *)fileName original:(BOOL)isOriginal
- {
- NSString *extension = [fileName pathExtension];
- NSString *nameWithoutExtension = [fileName stringByDeletingPathExtension];
- NSString *alternativeName = nameWithoutExtension;
- NSString *newSuffix = @" (1)";
-
- if (!isOriginal) {
- // Check if the name ends with ` (n)`
- NSError *error = nil;
- NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@" \\((\\d+)\\)$" options:NSRegularExpressionCaseInsensitive error:&error];
- NSTextCheckingResult *match = [regex firstMatchInString:nameWithoutExtension options:0 range:NSMakeRange(0, nameWithoutExtension.length)];
- if ([match numberOfRanges] > 1) {
- NSRange suffixRange = [match rangeAtIndex: 0];
- NSInteger suffixNumber = [[nameWithoutExtension substringWithRange:[match rangeAtIndex: 1]] intValue];
- newSuffix = [NSString stringWithFormat:@" (%ld)", suffixNumber + 1];
- alternativeName = [nameWithoutExtension stringByReplacingCharactersInRange:suffixRange withString:@""];
- }
- }
-
- alternativeName = [alternativeName stringByAppendingString:newSuffix];
- alternativeName = [alternativeName stringByAppendingPathExtension:extension];
-
- return alternativeName;
- }
- #pragma mark - User avatars
- - (SDWebImageCombinedOperation *)getUserAvatarForUser:(NSString *)userId usingAccount:(TalkAccount *)account withStyle:(UIUserInterfaceStyle)style withCompletionBlock:(GetUserAvatarImageForUserCompletionBlock)block
- {
- return [self getUserAvatarForUser:userId usingAccount:account withStyle:style ignoreCache:NO withCompletionBlock:block];
- }
- - (SDWebImageCombinedOperation *)getUserAvatarForUser:(NSString *)userId usingAccount:(TalkAccount *)account withStyle:(UIUserInterfaceStyle)style ignoreCache:(BOOL)ignoreCache withCompletionBlock:(GetUserAvatarImageForUserCompletionBlock)block
- {
- NSString *encodedUser = [userId stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
- ServerCapabilities *serverCapabilities = [[NCDatabaseManager sharedInstance] serverCapabilitiesForAccountId:account.accountId];
- // Since https://github.com/nextcloud/server/pull/31010 we can only request avatars in 64px or 512px
- // As we never request lower than 96px, we always get 512px anyway
- long avatarSize = 512;
- NSString *urlString = [NSString stringWithFormat:@"%@/index.php/avatar/%@/%ld", account.server, encodedUser, avatarSize];
- if (style == UIUserInterfaceStyleDark && serverCapabilities.versionMajor >= 25) {
- urlString = [NSString stringWithFormat:@"%@/dark", urlString];
- }
- NSURL *url = [NSURL URLWithString:urlString];
- SDWebImageOptions options = SDWebImageRetryFailed;
- if (ignoreCache) {
- // In case we want to ignore our local caches, we can't provide SDWebImageRefreshCached, as this will
- // always use NSURLCache and could still return a cached value here
- options |= SDWebImageFromLoaderOnly;
- } else {
- // We want to refresh our cache when the NSURLCache determines that the resource is not fresh anymore
- // see: https://github.com/SDWebImage/SDWebImage/wiki/Common-Problems#handle-image-refresh
- // Could be removed when all conversations have a avatarVersion, see https://github.com/nextcloud/spreed/issues/9320
- options |= SDWebImageRefreshCached;
- }
- SDWebImageDownloaderRequestModifier *requestModifier = [self getRequestModifierForAccount:account];
- return [[SDWebImageManager sharedManager] loadImageWithURL:url options:options context:@{SDWebImageContextDownloadRequestModifier : requestModifier} progress:nil completed:^(UIImage * _Nullable image, NSData * _Nullable data, NSError * _Nullable error, SDImageCacheType cacheType, BOOL finished, NSURL * _Nullable imageURL) {
- if (error) {
- // When the request was cancelled before completing, we expect no completion handler to be called
- if (block && error.code != SDWebImageErrorCancelled) {
- block(nil, error);
- }
- return;
- }
- if (image && block) {
- block(image, nil);
- }
- }];
- }
- - (SDWebImageCombinedOperation *)getFederatedUserAvatarForUser:(NSString *)userId inRoom:(NSString *)token usingAccount:(TalkAccount *)account withStyle:(UIUserInterfaceStyle)style withCompletionBlock:(GetFederatedUserAvatarImageForUserCompletionBlock)block
- {
- NSString *encodedToken = @"new";
- if (token.length > 0) {
- encodedToken = [token stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
- }
- NSString *endpoint = [NSString stringWithFormat:@"proxy/%@/user-avatar/512", encodedToken];
- if (style == UIUserInterfaceStyleDark) {
- endpoint = [NSString stringWithFormat:@"%@/dark", endpoint];
- }
- NSString *encodedUserId = [userId stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
- endpoint = [NSString stringWithFormat:@"%@?cloudId=%@", endpoint, encodedUserId];
- NSInteger avatarAPIVersion = 1;
- NSString *urlString = [self getRequestURLForEndpoint:endpoint withAPIVersion:avatarAPIVersion forAccount:account];
- NSURL *url = [NSURL URLWithString:urlString];
- // See getAvatarForRoom for explanation
- SDWebImageOptions options = SDWebImageRetryFailed | SDWebImageRefreshCached | SDWebImageQueryDiskDataSync;
- SDWebImageDownloaderRequestModifier *requestModifier = [self getRequestModifierForAccount:account];
- // Make sure we get at least a 120x120 image when retrieving an SVG with SVGKit
- SDWebImageContext *context = @{
- SDWebImageContextDownloadRequestModifier : requestModifier,
- SDWebImageContextImageThumbnailPixelSize : @(CGSizeMake(120, 120))
- };
- return [[SDWebImageManager sharedManager] loadImageWithURL:url options:options context:context progress:nil completed:^(UIImage * _Nullable image, NSData * _Nullable data, NSError * _Nullable error, SDImageCacheType cacheType, BOOL finished, NSURL * _Nullable imageURL) {
- if (error) {
- // When the request was cancelled before completing, we expect no completion handler to be called
- if (block && error.code != SDWebImageErrorCancelled) {
- block(nil, error);
- }
- return;
- }
- if (image && block) {
- block(image, nil);
- }
- }];
- }
- #pragma mark - Conversation avatars
- - (SDWebImageCombinedOperation *)getAvatarForRoom:(NCRoom *)room withStyle:(UIUserInterfaceStyle)style withCompletionBlock:(GetAvatarForConversationWithImageCompletionBlock)block
- {
- TalkAccount *account = [[NCDatabaseManager sharedInstance] talkAccountForAccountId:room.accountId];
- NSString *encodedToken = [room.token stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
- NSString *endpoint = [NSString stringWithFormat:@"room/%@/avatar", encodedToken];
- if (style == UIUserInterfaceStyleDark) {
- endpoint = [NSString stringWithFormat:@"%@/dark", endpoint];
- }
- // For non-one-to-one conversation we do have a valid avatarVersion which we can use to cache the avatar
- // For one-to-one conversations we rely on the caching that is specified by the server via cache-control header
- if (room.type != kNCRoomTypeOneToOne) {
- endpoint = [NSString stringWithFormat:@"%@?avatarVersion=%@", endpoint, room.avatarVersion];
- }
- NSInteger avatarAPIVersion = 1;
- NSString *urlString = [self getRequestURLForEndpoint:endpoint withAPIVersion:avatarAPIVersion forAccount:account];
- NSURL *url = [NSURL URLWithString:urlString];
- /*
- SDWebImageRetryFailed: By default SDWebImage blacklists URLs that failed to load and does not try to
- load these URLs again, but we want to retry these.
- Also see https://github.com/SDWebImage/SDWebImage/wiki/Common-Problems#handle-image-refresh
- SDWebImageRefreshCached: By default the cache-control header returned by the webserver is ignored and
- images are cached forever. With this parameter we let NSURLCache determine
- if a resource needs to be reloaded from the server again.
- Could be removed if this endpoint returns an avatar version for all calls.
- Also see https://github.com/nextcloud/spreed/issues/9320
- SDWebImageQueryDiskDataSync: SDImage loads data from the disk cache on a separate (async) queue. This leads
- to 2 problems: 1. It can cause some flickering on a reload, 2. It causes UIImage methods
- being called to leak memory. This is noticeable in NSE with a tight memory constraint.
- SVG images rendered to UIImage with SVGKit will leak data and make NSE crash.
- */
- SDWebImageOptions options = SDWebImageRetryFailed | SDWebImageQueryDiskDataSync;
- SDWebImageDownloaderRequestModifier *requestModifier = [self getRequestModifierForAccount:account];
- // Since we do not have a valid avatarVersion for one-to-one conversations, we need to rely on the
- // cache-control header by the server and therefore on NSURLCache
- // Note: There seems to be an issue with NSURLCache to correctly cache URLs that contain a query parameter
- // so it's currently only suiteable for one-to-ones that don't have a correct avatarVersion anyway
- if (room.type == kNCRoomTypeOneToOne) {
- options |= SDWebImageRefreshCached;
- }
- // Make sure we get at least a 120x120 image when retrieving an SVG with SVGKit
- SDWebImageContext *context = @{
- SDWebImageContextDownloadRequestModifier : requestModifier,
- SDWebImageContextImageThumbnailPixelSize : @(CGSizeMake(120, 120))
- };
-
- return [[SDWebImageManager sharedManager] loadImageWithURL:url options:options context:context progress:nil completed:^(UIImage * _Nullable image, NSData * _Nullable data, NSError * _Nullable error, SDImageCacheType cacheType, BOOL finished, NSURL * _Nullable imageURL) {
- if (error) {
- // When the request was cancelled before completing, we expect no completion handler to be called
- if (block && error.code != SDWebImageErrorCancelled) {
- block(nil, error);
- }
- return;
- }
- if (image && block) {
- block(image, nil);
- }
- }];
- }
- - (NSURLSessionDataTask *)setAvatarForRoom:(NCRoom *)room withImage:(UIImage *)image withCompletionBlock:(SetAvatarForConversationWithImageCompletionBlock)block
- {
- TalkAccount *account = [[NCDatabaseManager sharedInstance] talkAccountForAccountId:room.accountId];
- return [self setAvatarForRoomWithToken:room.token image:image account:account withCompletionBlock:block];
- }
- - (NSURLSessionDataTask *)setAvatarForRoomWithToken:(NSString *)token image:(UIImage *)image account:(TalkAccount *)account withCompletionBlock:(SetAvatarForConversationWithImageCompletionBlock)block
- {
- NSString *encodedToken = [token stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
- NSString *endpoint = [NSString stringWithFormat:@"room/%@/avatar", encodedToken];
- NSInteger avatarAPIVersion = 1;
- NSString *URLString = [self getRequestURLForEndpoint:endpoint withAPIVersion:avatarAPIVersion forAccount:account];
- NSData *imageData = UIImageJPEGRepresentation(image, 0.7);
- if (!imageData) {
- if (block) {
- NSError *error = [NSError errorWithDomain:NSCocoaErrorDomain code:0 userInfo:nil];
- block(error);
- }
- return nil;
- }
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager POST:URLString parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
- [formData appendPartWithFileData:imageData name:@"file" fileName:@"avatar.jpg" mimeType:@"image/jpeg"];
- } progress:nil success:^(NSURLSessionDataTask *task, id responseObject) {
- if (block) {
- block(nil);
- }
- } failure:^(NSURLSessionDataTask *task, NSError *error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- block(error);
- }
- }];
- return task;
- }
- - (NSURLSessionDataTask *)setEmojiAvatarForRoom:(NCRoom *)room withEmoji:(NSString *)emoji andColor:(NSString *)color withCompletionBlock:(SetAvatarForConversationWithImageCompletionBlock)block
- {
- TalkAccount *account = [[NCDatabaseManager sharedInstance] talkAccountForAccountId:room.accountId];
- return [self setEmojiAvatarForRoomWithToken:room.token withEmoji:emoji andColor:color account:account withCompletionBlock:block];
- }
- - (NSURLSessionDataTask *)setEmojiAvatarForRoomWithToken:(NSString *)token withEmoji:(NSString *)emoji andColor:(NSString *)color account:(TalkAccount *)account withCompletionBlock:(SetAvatarForConversationWithImageCompletionBlock)block
- {
- NSString *encodedToken = [token stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
- NSString *endpoint = [NSString stringWithFormat:@"room/%@/avatar/emoji", encodedToken];
- NSInteger avatarAPIVersion = 1;
- NSString *URLString = [self getRequestURLForEndpoint:endpoint withAPIVersion:avatarAPIVersion forAccount:account];
- NSMutableDictionary *parameters = [NSMutableDictionary new];
- [parameters setValue:emoji forKey:@"emoji"];
- color = [color stringByReplacingOccurrencesOfString:@"#" withString:@""];
- if (color.length > 0) {
- [parameters setValue:color forKey:@"color"];
- }
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager POST:URLString parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- if (block) {
- block(nil);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- block(error);
- }
- }];
- return task;
- }
- - (NSURLSessionDataTask *)removeAvatarForRoom:(NCRoom *)room withCompletionBlock:(RemoveAvatarForConversationWithImageCompletionBlock)block
- {
- TalkAccount *account = [[NCDatabaseManager sharedInstance] talkAccountForAccountId:room.accountId];
- NSString *encodedToken = [room.token stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
- NSString *endpoint = [NSString stringWithFormat:@"room/%@/avatar", encodedToken];
- NSInteger avatarAPIVersion = 1;
- NSString *URLString = [self getRequestURLForEndpoint:endpoint withAPIVersion:avatarAPIVersion forAccount:account];
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager DELETE:URLString parameters:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- if (block) {
- block(nil);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- block(error);
- }
- }];
- return task;
- }
- #pragma mark - User actions
- - (NSURLSessionDataTask *)getUserActionsForUser:(NSString *)userId usingAccount:(TalkAccount *)account withCompletionBlock:(GetUserActionsCompletionBlock)block
- {
- NSString *encodedUser = [userId stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
- NSString *URLString = [NSString stringWithFormat:@"%@/ocs/v2.php/hovercard/v1/%@", account.server, encodedUser];
- NSDictionary *parameters = @{@"format" : @"json"};
-
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager GET:URLString parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- NSDictionary *actions = [[responseObject objectForKey:@"ocs"] objectForKey:@"data"];
- if (block) {
- block(actions, nil);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- block(nil, error);
- }
- }];
-
- return task;
- }
- #pragma mark - File previews
- - (NSURLRequest *)createPreviewRequestForFile:(NSString *)fileId width:(NSInteger)width height:(NSInteger)height usingAccount:(TalkAccount *)account
- {
- NSString *urlString = [NSString stringWithFormat:@"%@/index.php/core/preview?fileId=%@&x=%ld&y=%ld&forceIcon=1", account.server, fileId, (long)width, (long)height];
- NSMutableURLRequest *previewRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:urlString] cachePolicy:NSURLRequestReturnCacheDataElseLoad timeoutInterval:60];
- [previewRequest setValue:[self authHeaderForAccount:account] forHTTPHeaderField:@"Authorization"];
- return previewRequest;
- }
- - (NSURLRequest *)createPreviewRequestForFile:(NSString *)fileId withMaxHeight:(NSInteger) height usingAccount:(TalkAccount *)account
- {
- NSString *urlString = [NSString stringWithFormat:@"%@/index.php/core/preview?fileId=%@&x=-1&y=%ld&a=1&forceIcon=1", account.server, fileId, (long)height];
-
- NSMutableURLRequest *previewRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:urlString] cachePolicy:NSURLRequestReturnCacheDataElseLoad timeoutInterval:60];
- [previewRequest setValue:[self authHeaderForAccount:account] forHTTPHeaderField:@"Authorization"];
- return previewRequest;
- }
- #pragma mark - User profile
- - (NSURLSessionDataTask *)getUserProfileForAccount:(TalkAccount *)account withCompletionBlock:(GetUserProfileCompletionBlock)block
- {
- NSString *URLString = [NSString stringWithFormat:@"%@/ocs/v2.php/cloud/user", account.server];
- NSDictionary *parameters = @{@"format" : @"json"};
-
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager GET:URLString parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- NSDictionary *profile = [[responseObject objectForKey:@"ocs"] objectForKey:@"data"];
- if (block) {
- block(profile, nil);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- block(nil, error);
- }
- }];
-
- return task;
- }
- - (NSURLSessionDataTask *)getUserProfileEditableFieldsForAccount:(TalkAccount *)account withCompletionBlock:(GetUserProfileEditableFieldsCompletionBlock)block
- {
- NSString *URLString = [NSString stringWithFormat:@"%@/ocs/v2.php/cloud/user/fields", account.server];
- NSDictionary *parameters = @{@"format" : @"json"};
-
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager GET:URLString parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- NSArray *editableFields = [[responseObject objectForKey:@"ocs"] objectForKey:@"data"];
- if (block) {
- block(editableFields, nil);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- block(nil, error);
- }
- }];
-
- return task;
- }
- - (NSURLSessionDataTask *)setUserProfileField:(NSString *)field withValue:(NSString*)value forAccount:(TalkAccount *)account withCompletionBlock:(SetUserProfileFieldCompletionBlock)block
- {
- NSString *URLString = [NSString stringWithFormat:@"%@/ocs/v2.php/cloud/users/%@", account.server, account.userId];
- NSDictionary *parameters = @{@"format" : @"json",
- @"key" : field,
- @"value" : value};
-
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager PUT:URLString parameters:parameters success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- if (block) {
- block(nil, 0);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- // Ignore status code for now https://github.com/nextcloud/server/pull/26679
- // [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- block(error, statusCode);
- }
- }];
-
- return task;
- }
- - (NSURLSessionDataTask *)setUserProfileImage:(UIImage *)image forAccount:(TalkAccount *)account withCompletionBlock:(SetUserProfileFieldCompletionBlock)block
- {
- NSString *URLString = [NSString stringWithFormat:@"%@/ocs/v2.php/apps/spreed/temp-user-avatar", account.server];
- NSData *imageData= UIImageJPEGRepresentation(image, 0.7);
-
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager POST:URLString parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
- [formData appendPartWithFileData:imageData name:@"files[]" fileName:@"avatar.jpg" mimeType:@"image/jpeg"];
- } progress:nil success:^(NSURLSessionDataTask *task, id responseObject) {
- if (block) {
- block(nil, 0);
- }
- } failure:^(NSURLSessionDataTask *task, NSError *error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- block(error, statusCode);
- }
- }];
-
- return task;
- }
- - (NSURLSessionDataTask *)removeUserProfileImageForAccount:(TalkAccount *)account withCompletionBlock:(SetUserProfileFieldCompletionBlock)block
- {
- NSString *URLString = [NSString stringWithFormat:@"%@/ocs/v2.php/apps/spreed/temp-user-avatar", account.server];
-
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager DELETE:URLString parameters:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- if (block) {
- block(nil, 0);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- block(error, statusCode);
- }
- }];
-
- return task;
- }
- - (void)saveProfileImageForAccount:(TalkAccount *)account
- {
- [self getAndStoreProfileImageForAccount:account withStyle:UIUserInterfaceStyleLight];
- }
- - (void)getAndStoreProfileImageForAccount:(TalkAccount *)account withStyle:(UIUserInterfaceStyle)style
- {
- __block SDWebImageCombinedOperation *operation;
- // When getting our own profile image, we need to ignore any cache to always get the latest version
- operation = [self getUserAvatarForUser:account.userId usingAccount:account withStyle:style ignoreCache:YES withCompletionBlock:^(UIImage *image, NSError *error) {
- SDWebImageDownloadToken *token = operation.loaderOperation;
- if (![token isKindOfClass:[SDWebImageDownloadToken class]]) {
- return;
- }
- NSURLResponse *response = token.response;
- NSDictionary *headers = ((NSHTTPURLResponse *)response).allHeaderFields;
-
- RLMRealm *realm = [RLMRealm defaultRealm];
- [realm beginWriteTransaction];
- NSPredicate *query = [NSPredicate predicateWithFormat:@"accountId = %@", account.accountId];
- TalkAccount *managedAccount = [TalkAccount objectsWithPredicate:query].firstObject;
- managedAccount.hasCustomAvatar = [[headers objectForKey:@"X-NC-IsCustomAvatar"] boolValue];
- [realm commitWriteTransaction];
- NSData *pngData = UIImagePNGRepresentation(image);
- NSString *documentsPath = [[[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:groupIdentifier] path];
- NSString *fileName;
- if (style == UIUserInterfaceStyleDark) {
- fileName = [NSString stringWithFormat:@"%@-%@-dark.png", account.userId, [[NSURL URLWithString:account.server] host]];
- } else {
- fileName = [NSString stringWithFormat:@"%@-%@.png", account.userId, [[NSURL URLWithString:account.server] host]];
- }
- NSString *filePath = [documentsPath stringByAppendingPathComponent:fileName];
- [pngData writeToFile:filePath atomically:YES];
- ServerCapabilities *serverCapabilities = [[NCDatabaseManager sharedInstance] serverCapabilitiesForAccountId:account.accountId];
- if (style == UIUserInterfaceStyleLight && !managedAccount.hasCustomAvatar && serverCapabilities.versionMajor >= 25) {
- [self getAndStoreProfileImageForAccount:account withStyle:UIUserInterfaceStyleDark];
- return;
- }
- [[NSNotificationCenter defaultCenter] postNotificationName:NCUserProfileImageUpdatedNotification object:self userInfo:nil];
- }];
- }
- - (UIImage *)userProfileImageForAccount:(TalkAccount *)account withStyle:(UIUserInterfaceStyle)style
- {
- NSFileManager *fileManager = [NSFileManager defaultManager];
- NSString *documentsPath = [[fileManager containerURLForSecurityApplicationGroupIdentifier:groupIdentifier] path];
- ServerCapabilities *serverCapabilities = [[NCDatabaseManager sharedInstance] serverCapabilitiesForAccountId:account.accountId];
- NSString *fileName;
- if (style == UIUserInterfaceStyleDark && !account.hasCustomAvatar && serverCapabilities.versionMajor >= 25) {
- fileName = [NSString stringWithFormat:@"%@-%@-dark.png", account.userId, [[NSURL URLWithString:account.server] host]];
- } else {
- fileName = [NSString stringWithFormat:@"%@-%@.png", account.userId, [[NSURL URLWithString:account.server] host]];
- }
- NSString *filePath = [documentsPath stringByAppendingPathComponent:fileName];
-
- // Migrate to app group directory
- NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
- NSString *oldDocumentsPath = [paths objectAtIndex:0];
- NSString *oldPath = [oldDocumentsPath stringByAppendingPathComponent:fileName];
- if ([fileManager fileExistsAtPath:oldPath]) {
- NSError *error = nil;
- [fileManager moveItemAtPath:oldPath toPath:filePath error:&error];
- NSLog(@"Migrating profile picture. Error: %@", error);
- }
-
- return [UIImage imageWithContentsOfFile:filePath];
- }
- - (void)removeProfileImageForAccount:(TalkAccount *)account
- {
- NSFileManager *fileManager = [NSFileManager defaultManager];
- NSString *documentsPath = [[fileManager containerURLForSecurityApplicationGroupIdentifier:groupIdentifier] path];
- NSString *fileName = [NSString stringWithFormat:@"%@-%@.png", account.userId, [[NSURL URLWithString:account.server] host]];
- NSString *filePath = [documentsPath stringByAppendingPathComponent:fileName];
- [[NSFileManager defaultManager] removeItemAtPath:filePath error:nil];
- fileName = [NSString stringWithFormat:@"%@-%@-dark.png", account.userId, [[NSURL URLWithString:account.server] host]];
- filePath = [documentsPath stringByAppendingPathComponent:fileName];
- [[NSFileManager defaultManager] removeItemAtPath:filePath error:nil];
- // Legacy
- NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
- NSString *oldDocumentsPath = [paths objectAtIndex:0];
- NSString *oldPath = [oldDocumentsPath stringByAppendingPathComponent:fileName];
- [[NSFileManager defaultManager] removeItemAtPath:oldPath error:nil];
- }
- #pragma mark - User Status
- - (NSURLSessionDataTask *)getUserStatusForAccount:(TalkAccount *)account withCompletionBlock:(GetUserStatusCompletionBlock)block
- {
- NSString *URLString = [NSString stringWithFormat:@"%@/ocs/v2.php/apps/user_status/api/v1/user_status", account.server];
-
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager GET:URLString parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- NSDictionary *userStatus = [[responseObject objectForKey:@"ocs"] objectForKey:@"data"];
- if (block) {
- block(userStatus, nil);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- block(nil, error);
- }
- }];
-
- return task;
- }
- - (NSURLSessionDataTask *)setUserStatus:(NSString *)status forAccount:(TalkAccount *)account withCompletionBlock:(SetUserStatusCompletionBlock)block
- {
- NSString *URLString = [NSString stringWithFormat:@"%@/ocs/v2.php/apps/user_status/api/v1/user_status/status", account.server];
- NSDictionary *parameters = @{@"statusType" : status};
-
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager PUT:URLString parameters:parameters success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- if (block) {
- block(nil);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- block(error);
- }
- }];
-
- return task;
- }
- #pragma mark - App Store info
- - (NSURLSessionDataTask *)getAppStoreAppIdWithCompletionBlock:(GetAppIdCompletionBlock)block
- {
- NSString *URLString = [NSString stringWithFormat:@"http://itunes.apple.com/lookup?bundleId=%@", bundleIdentifier];
- NSURLSessionDataTask *task = [_defaultAPISessionManager GET:URLString parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- NSString *appId = nil;
- NSArray *results = [responseObject objectForKey:@"results"];
- if (results.count > 0) {
- NSDictionary *appInfo = [results objectAtIndex:0];
- appId = [[appInfo objectForKey:@"trackId"] stringValue];
- }
- if (block) {
- block(appId, nil);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- if (block) {
- block(nil, error);
- }
- }];
- return task;
- }
- #pragma mark - Server capabilities
- - (NSURLSessionDataTask *)getServerCapabilitiesForServer:(NSString *)server withCompletionBlock:(GetServerCapabilitiesCompletionBlock)block
- {
- NSString *URLString = [NSString stringWithFormat:@"%@/ocs/v1.php/cloud/capabilities", server];
- NSDictionary *parameters = @{@"format" : @"json"};
-
- NSURLSessionDataTask *task = [_defaultAPISessionManager GET:URLString parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- NSDictionary *capabilities = [[responseObject objectForKey:@"ocs"] objectForKey:@"data"];
- if (block) {
- block(capabilities, nil);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- if (block) {
- block(nil, error);
- }
- }];
-
- return task;
- }
- - (NSURLSessionDataTask *)getServerCapabilitiesForAccount:(TalkAccount *)account withCompletionBlock:(GetServerCapabilitiesCompletionBlock)block
- {
- NSString *URLString = [NSString stringWithFormat:@"%@/ocs/v1.php/cloud/capabilities", account.server];
- NSDictionary *parameters = @{@"format" : @"json"};
-
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager GET:URLString parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- NSDictionary *capabilities = [[responseObject objectForKey:@"ocs"] objectForKey:@"data"];
- if (block) {
- block(capabilities, nil);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- block(nil, error);
- }
- }];
-
- return task;
- }
- #pragma mark - Server notifications
- - (NSURLSessionDataTask *)getServerNotification:(NSInteger)notificationId forAccount:(TalkAccount *)account withCompletionBlock:(GetServerNotificationCompletionBlock)block
- {
- NSString *URLString = [NSString stringWithFormat:@"%@/ocs/v2.php/apps/notifications/api/v2/notifications/%ld", account.server, (long)notificationId];
-
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- // Workaround: Just in case session managers are not initialized when called from NotificationService extension.
- if (!apiSessionManager) {
- [self initSessionManagers];
- apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- }
- NSURLSessionDataTask *task = [apiSessionManager GET:URLString parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- NSDictionary *notification = [[responseObject objectForKey:@"ocs"] objectForKey:@"data"];
- if (block) {
- block(notification, nil, 0);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- block(nil, error, statusCode);
- }
- }];
-
- return task;
- }
- - (NSURLSessionDataTask *)getServerNotificationsForAccount:(TalkAccount *)account withLastETag:(NSString *)lastETag withCompletionBlock:(GetServerNotificationsCompletionBlock)block
- {
- NSString *URLString = [NSString stringWithFormat:@"%@/ocs/v2.php/apps/notifications/api/v2/notifications", account.server];
- NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:URLString]];
- [request setValue:@"application/json" forHTTPHeaderField:@"Accept"];
- if (lastETag) {
- [request addValue:lastETag forHTTPHeaderField:@"If-None-Match"];
- }
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager dataTaskWithRequest:request completionHandler:^(NSURLResponse * _Nonnull response, id _Nullable responseObject, NSError * _Nullable error) {
- if (!error) {
- NSArray *notifications = [[responseObject objectForKey:@"ocs"] objectForKey:@"data"];
- NSDictionary *headers = [self getResponseHeaders:response];
- if (block) {
- block(notifications, [headers objectForKey:@"ETag"], [headers objectForKey:@"x-nextcloud-user-status"], nil);
- }
- } else {
- if (block) {
- block(nil, nil, nil, error);
- }
- }
- }];
- [task resume];
- return task;
- }
- - (void)executeNotificationAction:(NCNotificationAction *)action forAccount:(TalkAccount *)account withCompletionBlock:(ExecuteNotificationActionCompletionBlock)block
- {
- void (^success)(NSURLSessionDataTask *task, id responseObject) = ^void(NSURLSessionDataTask *task, id responseObject) {
- if (block) {
- block(nil);
- }
- };
- void (^failure)(NSURLSessionDataTask *task, NSError *error) = ^void(NSURLSessionDataTask *task, NSError *error) {
- if (block) {
- block(error);
- }
- };
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- if (action.actionType == NCNotificationActionTypeKNotificationActionTypeGet) {
- [apiSessionManager GET:action.actionLink parameters:nil progress:nil success:success failure:failure];
- } else if (action.actionType == NCNotificationActionTypeKNotificationActionTypePut) {
- [apiSessionManager PUT:action.actionLink parameters:nil success:success failure:failure];
- } else if (action.actionType == NCNotificationActionTypeKNotificationActionTypePost) {
- [apiSessionManager POST:action.actionLink parameters:nil progress:nil success:success failure:failure];
- } else if (action.actionType == NCNotificationActionTypeKNotificationActionTypeDelete) {
- [apiSessionManager DELETE:action.actionLink parameters:nil success:success failure:failure];
-
- } else {
- NSLog(@"Trying to execute non-supported notification action type");
- if (block) {
- NSError *error = [NSError errorWithDomain:NSCocoaErrorDomain code:0 userInfo:nil];
- block(error);
- }
- }
- }
- - (NSURLSessionDataTask *)checkNotificationExistance:(NSArray *)notificationIds forAccount:(TalkAccount *)account withCompletionBlock:(CheckNotificationExistanceBlock)block
- {
- NSString *URLString = [NSString stringWithFormat:@"%@/ocs/v2.php/apps/notifications/api/v2/notifications/exists", account.server];
- NSDictionary *parameters = @{
- @"ids" : notificationIds,
- };
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager POST:URLString parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- NSArray *responseArray = [[responseObject objectForKey:@"ocs"] objectForKey:@"data"];
- if (block) {
- block(responseArray, nil);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- block(nil, error);
- }
- }];
- return task;
- }
- #pragma mark - Push Notifications
- - (NSURLSessionDataTask *)subscribeAccount:(TalkAccount *)account withPublicKey:(NSData *)publicKey toNextcloudServerWithCompletionBlock:(SubscribeToNextcloudServerCompletionBlock)block
- {
- NSString *URLString = [NSString stringWithFormat:@"%@/ocs/v2.php/apps/notifications/api/v2/push", account.server];
- NSString *devicePublicKey = [[NSString alloc] initWithData:publicKey encoding:NSUTF8StringEncoding];
- NSDictionary *parameters = @{@"pushTokenHash" : [[NCKeyChainController sharedInstance] pushTokenSHA512],
- @"devicePublicKey" : devicePublicKey,
- @"proxyServer" : pushNotificationServer
- };
-
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager POST:URLString parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- NSDictionary *responseDict = [[responseObject objectForKey:@"ocs"] objectForKey:@"data"];
- if (block) {
- block(responseDict, nil);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- block(nil, error);
- }
- }];
-
- return task;
- }
- - (NSURLSessionDataTask *)unsubscribeAccount:(TalkAccount *)account fromNextcloudServerWithCompletionBlock:(UnsubscribeToNextcloudServerCompletionBlock)block
- {
- NSString *URLString = [NSString stringWithFormat:@"%@/ocs/v2.php/apps/notifications/api/v2/push", account.server];
-
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager DELETE:URLString parameters:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- if (block) {
- block(nil);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- block(error);
- }
- }];
-
- return task;
- }
- - (NSURLSessionDataTask *)subscribeAccount:(TalkAccount *)account toPushServerWithCompletionBlock:(SubscribeToPushProxyCompletionBlock)block
- {
- NSString *URLString = [NSString stringWithFormat:@"%@/devices", pushNotificationServer];
- NSDictionary *parameters = @{@"pushToken" : [[NCKeyChainController sharedInstance] combinedPushToken],
- @"deviceIdentifier" : account.deviceIdentifier,
- @"deviceIdentifierSignature" : account.deviceSignature,
- @"userPublicKey" : account.userPublicKey
- };
- NSURLSessionDataTask *task = [[NCPushProxySessionManager shared] POST:URLString parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- if (block) {
- block(nil);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- if (block) {
- block(error);
- }
- }];
-
- return task;
- }
- - (NSURLSessionDataTask *)unsubscribeAccount:(TalkAccount *)account fromPushServerWithCompletionBlock:(UnsubscribeToPushProxyCompletionBlock)block
- {
- NSString *URLString = [NSString stringWithFormat:@"%@/devices", pushNotificationServer];
- NSDictionary *parameters = @{@"deviceIdentifier" : account.deviceIdentifier,
- @"deviceIdentifierSignature" : account.deviceSignature,
- @"userPublicKey" : account.userPublicKey
- };
- NSURLSessionDataTask *task = [[NCPushProxySessionManager shared] DELETE:URLString parameters:parameters success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- if (block) {
- block(nil);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- if (block) {
- block(error);
- }
- }];
-
- return task;
- }
- #pragma mark - Reference handling
- - (NSURLSessionDataTask *)getReferenceForUrlString:(NSString *)url forAccount:(TalkAccount *)account withCompletionBlock:(GetReferenceForUrlStringCompletionBlock)block
- {
- NSString *URLString = [NSString stringWithFormat:@"%@/ocs/v2.php/references/resolve", account.server];
- NSDictionary *parameters = @{@"reference" : url};
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager GET:URLString parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- NSDictionary *responseReferences = [[[responseObject objectForKey:@"ocs"] objectForKey:@"data"] objectForKey:@"references"];
- if (block) {
- // When there's no data, the server returns an empty array instead of a dictionary
- // Also we don't want to have a dictionary with NSNull values in it
- if (![responseReferences isKindOfClass:[NSDictionary class]] || [[responseReferences objectForKey:url] isKindOfClass:[NSNull class]]) {
- block(@{}, nil);
- } else {
- block(responseReferences, nil);
- }
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- if (block) {
- block(nil, error);
- }
- }];
- return task;
- }
- - (NSURLRequest *)createReferenceThumbnailRequestForUrl:(NSString *)url
- {
- NSMutableURLRequest *thumbnailRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url] cachePolicy:NSURLRequestReturnCacheDataElseLoad timeoutInterval:60];
- return thumbnailRequest;
- }
- #pragma - Recording
- - (NSURLSessionDataTask *)startRecording:(NSString *)token forAccount:(TalkAccount *)account withCompletionBlock:(StartRecordingCompletionBlock)block
- {
- NSString *encodedToken = [token stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
- NSString *endpoint = [NSString stringWithFormat:@"recording/%@", encodedToken];
- NSString *URLString = [self getRequestURLForEndpoint:endpoint withAPIVersion:1 forAccount:account];
- // Status 1 -> Video recording
- // Status 2 -> Audio recording (not supported for now)
- NSDictionary *parameters = @{
- @"status" : @(1)
- };
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager POST:URLString parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- if (block) {
- block(nil);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- block(error);
- }
- }];
- return task;
- }
- - (NSURLSessionDataTask *)stopRecording:(NSString *)token forAccount:(TalkAccount *)account withCompletionBlock:(StopRecordingCompletionBlock)block
- {
- NSString *encodedToken = [token stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
- NSString *endpoint = [NSString stringWithFormat:@"recording/%@", encodedToken];
- NSString *URLString = [self getRequestURLForEndpoint:endpoint withAPIVersion:1 forAccount:account];
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager DELETE:URLString parameters:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- if (block) {
- block(nil);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- block(error);
- }
- }];
- return task;
- }
- - (NSURLSessionDataTask *)dismissStoredRecordingNotificationWithTimestamp:(NSString *)timestamp forRoom:(NSString *)token forAccount:(TalkAccount *)account withCompletionBlock:(DismissStoredRecordingNotificationCompletionBlock)block
- {
- NSString *encodedToken = [token stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
- NSString *endpoint = [NSString stringWithFormat:@"recording/%@/notification", encodedToken];
- NSString *URLString = [self getRequestURLForEndpoint:endpoint withAPIVersion:1 forAccount:account];
- NSDictionary *parameters = @{
- @"timestamp" : timestamp
- };
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager DELETE:URLString parameters:parameters success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- if (block) {
- block(nil);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- block(error);
- }
- }];
- return task;
- }
- - (NSURLSessionDataTask *)shareStoredRecordingWithTimestamp:(NSString *)timestamp withFileId:(NSString *)fileId forRoom:(NSString *)token forAccount:(TalkAccount *)account withCompletionBlock:(ShareStoredRecordingCompletionBlock)block
- {
- NSString *encodedToken = [token stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
- NSString *endpoint = [NSString stringWithFormat:@"recording/%@/share-chat", encodedToken];
- NSString *URLString = [self getRequestURLForEndpoint:endpoint withAPIVersion:1 forAccount:account];
- NSDictionary *parameters = @{
- @"timestamp" : timestamp,
- @"fileId" : fileId
- };
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager POST:URLString parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- if (block) {
- block(nil);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- block(error);
- }
- }];
- return task;
- }
- #pragma mark - Remind me later
- - (NSURLSessionDataTask *)setReminderForMessage:(NCChatMessage *)message withTimestamp:(NSString *)timestamp withCompletionBlock:(SetReminderForMessage)block
- {
- TalkAccount *account = [[NCDatabaseManager sharedInstance] talkAccountForAccountId:message.accountId];
- NSInteger chatAPIVersion = [self chatAPIVersionForAccount:account];
- NSString *encodedToken = [message.token stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
- NSString *endpoint = [NSString stringWithFormat:@"chat/%@/%ld/reminder", encodedToken, (long)message.messageId];
- NSString *URLString = [self getRequestURLForEndpoint:endpoint withAPIVersion:chatAPIVersion forAccount:account];
- NSDictionary *parameters = @{
- @"timestamp" : timestamp
- };
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager POST:URLString parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- if (block) {
- block(nil);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- block(error);
- }
- }];
- return task;
- }
- - (NSURLSessionDataTask *)deleteReminderForMessage:(NCChatMessage *)message withCompletionBlock:(DeleteReminderForMessage)block
- {
- TalkAccount *account = [[NCDatabaseManager sharedInstance] talkAccountForAccountId:message.accountId];
- NSInteger chatAPIVersion = [self chatAPIVersionForAccount:account];
- NSString *encodedToken = [message.token stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
- NSString *endpoint = [NSString stringWithFormat:@"chat/%@/%ld/reminder", encodedToken, (long)message.messageId];
- NSString *URLString = [self getRequestURLForEndpoint:endpoint withAPIVersion:chatAPIVersion forAccount:account];
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager DELETE:URLString parameters:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- if (block) {
- block(nil);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- block(error);
- }
- }];
- return task;
- }
- - (NSURLSessionDataTask *)getReminderForMessage:(NCChatMessage *)message withCompletionBlock:(GetReminderForMessage)block
- {
- TalkAccount *account = [[NCDatabaseManager sharedInstance] talkAccountForAccountId:message.accountId];
- NSInteger chatAPIVersion = [self chatAPIVersionForAccount:account];
- NSString *encodedToken = [message.token stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
- NSString *endpoint = [NSString stringWithFormat:@"chat/%@/%ld/reminder", encodedToken, (long)message.messageId];
- NSString *URLString = [self getRequestURLForEndpoint:endpoint withAPIVersion:chatAPIVersion forAccount:account];
- NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
- NSURLSessionDataTask *task = [apiSessionManager GET:URLString parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
- if (block) {
- NSDictionary *responseDict = [[responseObject objectForKey:@"ocs"] objectForKey:@"data"];
- block(responseDict, nil);
- }
- } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
- NSInteger statusCode = [self getResponseStatusCode:task.response];
- [self checkResponseStatusCode:statusCode forAccount:account];
- if (block) {
- block(nil, error);
- }
- }];
- return task;
- }
- #pragma mark - Error handling
- - (NSInteger)getResponseStatusCode:(NSURLResponse *)response
- {
- NSInteger statusCode = 0;
- if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
- NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
- statusCode = httpResponse.statusCode;
- }
- return statusCode;
- }
- - (NSDictionary *)getFailureResponseObjectFromError:(NSError *)error
- {
- NSDictionary *responseDict = @{};
- NSString* errorResponse = [[NSString alloc] initWithData:(NSData *)error.userInfo[AFNetworkingOperationFailingURLResponseDataErrorKey] encoding:NSUTF8StringEncoding];
- if (errorResponse.length == 0) {
- return nil;
- }
- NSData *data = [errorResponse dataUsingEncoding:NSUTF8StringEncoding];
- if (data) {
- NSError* error;
- NSDictionary* jsonData = [NSJSONSerialization JSONObjectWithData:data
- options:0
- error:&error];
- if (jsonData) {
- responseDict = jsonData;
- } else {
- NSLog(@"Error retrieving failure response object JSON data: %@", error);
- }
- }
- return responseDict;
- }
- - (void)checkResponseStatusCode:(NSInteger)statusCode forAccount:(TalkAccount *)account
- {
- if (statusCode == 401) {
- // App token has been revoked
- NSDictionary *userInfo = [NSDictionary dictionaryWithObject:account.accountId forKey:@"accountId"];
- [[NSNotificationCenter defaultCenter] postNotificationName:NCTokenRevokedResponseReceivedNotification
- object:self
- userInfo:userInfo];
- } else if (statusCode == 426) {
- // Upgrade required
- NSDictionary *userInfo = [NSDictionary dictionaryWithObject:account.accountId forKey:@"accountId"];
- [[NSNotificationCenter defaultCenter] postNotificationName:NCUpgradeRequiredResponseReceivedNotification
- object:self
- userInfo:userInfo];
- } else if (statusCode == 503) {
- // Server is in maintenance mode
- NSDictionary *userInfo = [NSDictionary dictionaryWithObject:account.accountId forKey:@"accountId"];
- [[NSNotificationCenter defaultCenter] postNotificationName:NCServerMaintenanceModeNotification
- object:self
- userInfo:userInfo];
- }
- }
- #pragma mark - Header handling
- - (NSDictionary *)getResponseHeaders:(NSURLResponse *)response
- {
- if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
- NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
- return [httpResponse allHeaderFields];
- }
-
- return nil;
- }
- - (void)checkResponseHeaders:(NSDictionary *)headers forAccount:(TalkAccount *)account
- {
- NSString *modifiedSince = [headers objectForKey:@"X-Nextcloud-Talk-Modified-Before"];
- NSString *configurationHash = [headers objectForKey:@"X-Nextcloud-Talk-Hash"];
-
- if (modifiedSince.length > 0) {
- [[NCDatabaseManager sharedInstance] updateLastModifiedSinceForAccountId:account.accountId with:modifiedSince];
- }
- if (!configurationHash) {
- return;
- }
-
- if (![configurationHash isEqualToString:account.lastReceivedConfigurationHash]) {
- if (account.lastReceivedConfigurationHash) {
- // We previously stored a configuration hash which now changed -> Update settings and capabilities
- NSMutableDictionary *userInfo = [[NSMutableDictionary alloc] init];
- [userInfo setObject:account.accountId forKey:@"accountId"];
- [userInfo setObject:configurationHash forKey:@"configurationHash"];
-
- [[NSNotificationCenter defaultCenter] postNotificationName:NCTalkConfigurationHashChangedNotification
- object:self
- userInfo:userInfo];
- } else {
- [[NCDatabaseManager sharedInstance] updateTalkConfigurationHashForAccountId:account.accountId withHash:configurationHash];
- }
- }
- }
- - (void)checkProxyResponseHeaders:(NSDictionary *)headers forAccount:(TalkAccount *)account forRoom:(NSString *)token
- {
- NSString *proxyHash = [headers objectForKey:@"X-Nextcloud-Talk-Proxy-Hash"];
- if (!proxyHash) {
- return;
- }
- NSPredicate *query = [NSPredicate predicateWithFormat:@"token = %@ AND accountId = %@", token, account.accountId];
- NCRoom *managedRoom = [NCRoom objectsWithPredicate:query].firstObject;
- if (!managedRoom) {
- // The room is not known to us locally, don't try to fetch room capabilities
- return;
- }
- FederatedCapabilities *federatedCapabilities = [[NCDatabaseManager sharedInstance] federatedCapabilitiesForAccountId:managedRoom.accountId remoteServer:managedRoom.remoteServer roomToken:managedRoom.token];
- if ([proxyHash isEqualToString:managedRoom.lastReceivedProxyHash] && federatedCapabilities != nil) {
- // The proxy hash is equal to our last known proxy hash and we are also able to retrieve capabilities locally -> skip fetching capabilities
- return;
- }
- [self getRoomCapabilitiesFor:account.accountId token:token completionBlock:^(NSDictionary<NSString *,id> * _Nullable capabilities, NSString * _Nullable proxyHash) {
- if (capabilities && proxyHash) {
- [[NCDatabaseManager sharedInstance] setFederatedCapabilities:capabilities forAccountId:account.accountId remoteServer:managedRoom.remoteServer roomToken:token withProxyHash:proxyHash];
- }
- }];
- }
- #pragma mark - NKCommon Delegate
- - (void)authenticationChallenge:(NSURLSession *)session didReceive:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler
- {
- // The pinnning check
- if ([[CCCertificate sharedManager] checkTrustedChallenge:challenge]) {
- completionHandler(NSURLSessionAuthChallengeUseCredential, [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]);
- } else {
- completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil);
- }
- }
- @end
- #pragma mark - OCURLSessionManager
- @implementation OCURLSessionManager
- - (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler
- {
- // The pinnning check
- if ([[CCCertificate sharedManager] checkTrustedChallenge:challenge]) {
- completionHandler(NSURLSessionAuthChallengeUseCredential, [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]);
- } else {
- completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil);
- }
- }
- @end
|