AppService.m 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825
  1. //
  2. // AppService.m
  3. // WildFireChat
  4. //
  5. // Created by Heavyrain Lee on 2019/10/22.
  6. // Copyright © 2019 WildFireChat. All rights reserved.
  7. //
  8. #import "AppService.h"
  9. #import <WFChatClient/WFCChatClient.h>
  10. #import "AFNetworking.h"
  11. #import "WFCConfig.h"
  12. #import "PCSessionViewController.h"
  13. #import <WFChatUIKit/WFChatUIKit.h>
  14. #import "SharePredefine.h"
  15. #import <WebKit/WebKit.h>
  16. static AppService *sharedSingleton = nil;
  17. #define WFC_APPSERVER_COOKIES @"WFC_APPSERVER_COOKIES"
  18. #define WFC_APPSERVER_AUTH_TOKEN @"WFC_APPSERVER_AUTH_TOKEN"
  19. #define AUTHORIZATION_HEADER @"authToken"
  20. @implementation AppService
  21. + (AppService *)sharedAppService {
  22. if (sharedSingleton == nil) {
  23. @synchronized (self) {
  24. if (sharedSingleton == nil) {
  25. sharedSingleton = [[AppService alloc] init];
  26. }
  27. }
  28. }
  29. return sharedSingleton;
  30. }
  31. - (void)loginWithMobile:(NSString *)mobile verifyCode:(NSString *)verifyCode success:(void(^)(NSString *userId, NSString *token, BOOL newUser, NSString *resetCode))successBlock error:(void(^)(int errCode, NSString *message))errorBlock {
  32. int platform = Platform_iOS;
  33. //如果使用pad端类型,这里平台改成pad类型,另外app_callback.mm文件中把平台也改成ipad,请搜索"iPad"
  34. //if(当前设备是iPad)
  35. //platform = Platform_iPad
  36. [self post:@"/login" data:@{@"mobile":mobile, @"code":verifyCode, @"clientId":[[WFCCNetworkService sharedInstance] getClientId], @"platform":@(platform)} isLogin:YES success:^(NSDictionary *dict) {
  37. if([dict[@"code"] intValue] == 0) {
  38. NSString *userId = dict[@"result"][@"userId"];
  39. NSString *token = dict[@"result"][@"token"];
  40. BOOL newUser = [dict[@"result"][@"register"] boolValue];
  41. NSString *resetCode = dict[@"result"][@"resetCode"];
  42. if(successBlock) successBlock(userId, token, newUser, resetCode);
  43. } else {
  44. if(errorBlock) errorBlock([dict[@"code"] intValue], dict[@"message"]);
  45. }
  46. } error:^(NSError * _Nonnull error) {
  47. if(errorBlock) errorBlock(-1, error.description);
  48. }];
  49. }
  50. - (void)loginWithMobile:(NSString *)mobile password:(NSString *)password success:(void(^)(NSString *userId, NSString *token, BOOL newUser))successBlock error:(void(^)(int errCode, NSString *message))errorBlock {
  51. int platform = Platform_iOS;
  52. //如果使用pad端类型,这里平台改成pad类型,另外app_callback.mm文件中把平台也改成ipad,请搜索"iPad"
  53. //if(当前设备是iPad)
  54. //platform = Platform_iPad
  55. [self post:@"/login_pwd" data:@{@"mobile":mobile, @"password":password, @"clientId":[[WFCCNetworkService sharedInstance] getClientId], @"platform":@(platform)} isLogin:YES success:^(NSDictionary *dict) {
  56. if([dict[@"code"] intValue] == 0) {
  57. NSString *userId = dict[@"result"][@"userId"];
  58. NSString *token = dict[@"result"][@"token"];
  59. BOOL newUser = [dict[@"result"][@"register"] boolValue];
  60. if(successBlock) successBlock(userId, token, newUser);
  61. } else {
  62. if(errorBlock) errorBlock([dict[@"code"] intValue], dict[@"message"]);
  63. }
  64. } error:^(NSError * _Nonnull error) {
  65. if(errorBlock) errorBlock(-1, error.description);
  66. }];
  67. }
  68. - (void)resetPassword:(NSString *)mobile code:(NSString *)code newPassword:(NSString *)newPassword success:(void(^)(void))successBlock error:(void(^)(int errCode, NSString *message))errorBlock {
  69. NSDictionary *data;
  70. if (mobile.length) {
  71. data = @{@"mobile":mobile, @"resetCode":code, @"newPassword":newPassword};
  72. } else {
  73. data = @{@"resetCode":code, @"newPassword":newPassword};
  74. }
  75. [self post:@"/reset_pwd" data:data isLogin:NO success:^(NSDictionary *dict) {
  76. if([dict[@"code"] intValue] == 0) {
  77. if(successBlock) successBlock();
  78. } else {
  79. if(errorBlock) errorBlock([dict[@"code"] intValue], dict[@"message"]);
  80. }
  81. } error:^(NSError * _Nonnull error) {
  82. if(errorBlock) errorBlock(-1, error.description);
  83. }];
  84. }
  85. - (void)changePassword:(NSString *)oldPassword newPassword:(NSString *)newPassword success:(void(^)(void))successBlock error:(void(^)(int errCode, NSString *message))errorBlock {
  86. [self post:@"/change_pwd" data:@{@"oldPassword":oldPassword, @"newPassword":newPassword} isLogin:NO success:^(NSDictionary *dict) {
  87. if([dict[@"code"] intValue] == 0) {
  88. if(successBlock) successBlock();
  89. } else {
  90. if(errorBlock) errorBlock([dict[@"code"] intValue], dict[@"message"]);
  91. }
  92. } error:^(NSError * _Nonnull error) {
  93. if(errorBlock) errorBlock(-1, error.description);
  94. }];
  95. }
  96. - (void)sendLoginCode:(NSString *)phoneNumber success:(void(^)(void))successBlock error:(void(^)(NSString *message))errorBlock {
  97. [self post:@"/send_code" data:@{@"mobile":phoneNumber} isLogin:NO success:^(NSDictionary *dict) {
  98. if([dict[@"code"] intValue] == 0) {
  99. if(successBlock) successBlock();
  100. } else {
  101. if(errorBlock) errorBlock(@"error");
  102. }
  103. } error:^(NSError * _Nonnull error) {
  104. if(errorBlock) errorBlock(error.localizedDescription);
  105. }];
  106. }
  107. - (void)sendResetCode:(NSString *)phoneNumber success:(void(^)(void))successBlock error:(void(^)(NSString *message))errorBlock {
  108. NSDictionary *data = @{};
  109. if (phoneNumber.length) {
  110. data = @{@"mobile":phoneNumber};
  111. }
  112. [self post:@"/send_reset_code" data:data isLogin:NO success:^(NSDictionary *dict) {
  113. if([dict[@"code"] intValue] == 0) {
  114. if(successBlock) successBlock();
  115. } else {
  116. if(errorBlock) errorBlock(@"error");
  117. }
  118. } error:^(NSError * _Nonnull error) {
  119. if(errorBlock) errorBlock(error.localizedDescription);
  120. }];
  121. }
  122. - (void)sendDestroyAccountCode:(void(^)(void))successBlock error:(void(^)(int errorCode, NSString *message))errorBlock {
  123. [self post:@"/send_destroy_code" data:nil isLogin:NO success:^(NSDictionary *dict) {
  124. if([dict[@"code"] intValue] == 0) {
  125. if(successBlock) successBlock();
  126. } else {
  127. if(errorBlock) errorBlock([dict[@"code"] intValue], @"error");
  128. }
  129. } error:^(NSError * _Nonnull error) {
  130. if(errorBlock) errorBlock(-1, error.localizedDescription);
  131. }];
  132. }
  133. - (void)destroyAccount:(NSString *)code success:(void(^)(void))successBlock error:(void(^)(int errorCode, NSString *message))errorBlock {
  134. [self post:@"/destroy" data:@{@"code":code} isLogin:NO success:^(NSDictionary *dict) {
  135. if([dict[@"code"] intValue] == 0) {
  136. if(successBlock) successBlock();
  137. } else {
  138. if(errorBlock) errorBlock([dict[@"code"] intValue], @"error");
  139. }
  140. } error:^(NSError * _Nonnull error) {
  141. if(errorBlock) errorBlock(-1, error.localizedDescription);
  142. }];
  143. }
  144. - (void)pcScaned:(NSString *)sessionId success:(void(^)(void))successBlock error:(void(^)(int errorCode, NSString *message))errorBlock {
  145. NSString *path = [NSString stringWithFormat:@"/scan_pc/%@", sessionId];
  146. [self post:path data:nil isLogin:NO success:^(NSDictionary *dict) {
  147. if([dict[@"code"] intValue] == 0) {
  148. if(successBlock) successBlock();
  149. } else {
  150. if(errorBlock) errorBlock([dict[@"code"] intValue], @"Network error");
  151. }
  152. } error:^(NSError * _Nonnull error) {
  153. if(errorBlock) errorBlock(-1, error.localizedDescription);
  154. }];
  155. }
  156. - (void)pcConfirmLogin:(NSString *)sessionId success:(void(^)(void))successBlock error:(void(^)(int errorCode, NSString *message))errorBlock {
  157. NSString *path = @"/confirm_pc";
  158. NSDictionary *param = @{@"token":sessionId, @"user_id":[WFCCNetworkService sharedInstance].userId, @"quick_login":@(1)};
  159. [self post:path data:param isLogin:NO success:^(NSDictionary *dict) {
  160. if([dict[@"code"] intValue] == 0) {
  161. if(successBlock) successBlock();
  162. } else {
  163. if(errorBlock) errorBlock([dict[@"code"] intValue], @"Network error");
  164. }
  165. } error:^(NSError * _Nonnull error) {
  166. if(errorBlock) errorBlock(-1, error.localizedDescription);
  167. }];
  168. }
  169. - (void)pcCancelLogin:(NSString *)sessionId success:(void(^)(void))successBlock error:(void(^)(int errorCode, NSString *message))errorBlock {
  170. NSString *path = @"/cancel_pc";
  171. NSDictionary *param = @{@"token":sessionId};
  172. [self post:path data:param isLogin:NO success:^(NSDictionary *dict) {
  173. if([dict[@"code"] intValue] == 0) {
  174. if(successBlock) successBlock();
  175. } else {
  176. if(errorBlock) errorBlock([dict[@"code"] intValue], @"Network error");
  177. }
  178. } error:^(NSError * _Nonnull error) {
  179. if(errorBlock) errorBlock(-1, error.localizedDescription);
  180. }];
  181. }
  182. - (void)getGroupAnnouncement:(NSString *)groupId
  183. success:(void(^)(WFCUGroupAnnouncement *))successBlock
  184. error:(void(^)(int error_code))errorBlock {
  185. if (successBlock) {
  186. NSData *data = [[NSUserDefaults standardUserDefaults] objectForKey:[NSString stringWithFormat:@"wfc_group_an_%@", groupId]];
  187. WFCUGroupAnnouncement *an = [[WFCUGroupAnnouncement alloc] init];
  188. an.data = data;
  189. an.groupId = groupId;
  190. successBlock(an);
  191. }
  192. NSString *path = @"/get_group_announcement";
  193. NSDictionary *param = @{@"groupId":groupId};
  194. [self post:path data:param isLogin:NO success:^(NSDictionary *dict) {
  195. if([dict[@"code"] intValue] == 0 || [dict[@"code"] intValue] == 12) {
  196. WFCUGroupAnnouncement *an = [[WFCUGroupAnnouncement alloc] init];
  197. an.groupId = groupId;
  198. if ([dict[@"code"] intValue] == 0) {
  199. an.author = dict[@"result"][@"author"];
  200. an.text = dict[@"result"][@"text"];
  201. an.timestamp = [dict[@"result"][@"timestamp"] longValue];
  202. }
  203. [[NSUserDefaults standardUserDefaults] setValue:an.data forKey:[NSString stringWithFormat:@"wfc_group_an_%@", groupId]];
  204. [[NSUserDefaults standardUserDefaults] synchronize];
  205. if(successBlock) successBlock(an);
  206. } else {
  207. if(errorBlock) errorBlock([dict[@"code"] intValue]);
  208. }
  209. } error:^(NSError * _Nonnull error) {
  210. if(errorBlock) errorBlock(-1);
  211. }];
  212. }
  213. - (void)updateGroup:(NSString *)groupId
  214. announcement:(NSString *)announcement
  215. success:(void(^)(long timestamp))successBlock
  216. error:(void(^)(int error_code))errorBlock {
  217. NSString *path = @"/put_group_announcement";
  218. NSDictionary *param = @{@"groupId":groupId, @"author":[WFCCNetworkService sharedInstance].userId, @"text":announcement};
  219. [self post:path data:param isLogin:NO success:^(NSDictionary *dict) {
  220. if([dict[@"code"] intValue] == 0) {
  221. WFCUGroupAnnouncement *an = [[WFCUGroupAnnouncement alloc] init];
  222. an.groupId = groupId;
  223. an.author = [WFCCNetworkService sharedInstance].userId;
  224. an.text = announcement;
  225. an.timestamp = [dict[@"result"][@"timestamp"] longValue];
  226. [[NSUserDefaults standardUserDefaults] setValue:an.data forKey:[NSString stringWithFormat:@"wfc_group_an_%@", groupId]];
  227. [[NSUserDefaults standardUserDefaults] synchronize];
  228. if(successBlock) successBlock(an.timestamp);
  229. } else {
  230. if(errorBlock) errorBlock([dict[@"code"] intValue]);
  231. }
  232. } error:^(NSError * _Nonnull error) {
  233. if(errorBlock) errorBlock(-1);
  234. }];
  235. }
  236. - (void)getGroupMembersForPortrait:(NSString *)groupId
  237. success:(void(^)(NSArray<NSDictionary<NSString *, NSString *> *> *groupMembers))successBlock
  238. error:(void(^)(int error_code))errorBlock {
  239. NSString *path = @"/group/members_for_portrait";
  240. [self post:path data:@{@"groupId":groupId} isLogin:NO success:^(NSDictionary *dict) {
  241. if([dict[@"code"] intValue] == 0) {
  242. if([dict[@"result"] isKindOfClass:NSArray.class]) {
  243. NSArray *arr = (NSArray *)dict[@"result"];
  244. if(successBlock) successBlock(arr);
  245. }
  246. } else {
  247. if(errorBlock) errorBlock([dict[@"code"] intValue]);
  248. }
  249. } error:^(NSError * _Nonnull error) {
  250. if(errorBlock) errorBlock(-1);
  251. }];
  252. }
  253. - (void)post:(NSString *)path data:(id)data isLogin:(BOOL)isLogin success:(void(^)(NSDictionary *dict))successBlock error:(void(^)(NSError * _Nonnull error))errorBlock {
  254. AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
  255. manager.requestSerializer = [AFJSONRequestSerializer serializer];
  256. manager.responseSerializer.acceptableContentTypes = [NSSet setWithObject:@"application/json"];
  257. //在调用其他接口时需要把cookie传给后台,也就是设置cookie的过程
  258. NSString *authToken = [self getAppServiceAuthToken];
  259. if(authToken.length) {
  260. [manager.requestSerializer setValue:authToken forHTTPHeaderField:AUTHORIZATION_HEADER];
  261. } else {
  262. NSData *cookiesdata = [self getAppServiceCookies];//url和登录时传的url 是同一个
  263. if([cookiesdata length]) {
  264. NSArray *cookies = [NSKeyedUnarchiver unarchiveObjectWithData:cookiesdata];
  265. NSHTTPCookie *cookie;
  266. for (cookie in cookies) {
  267. [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:cookie];
  268. }
  269. }
  270. }
  271. [manager POST:[APP_SERVER_ADDRESS stringByAppendingPathComponent:path]
  272. parameters:data
  273. progress:nil
  274. success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
  275. if(isLogin) { //鉴权信息
  276. NSString *appToken;
  277. if ([task.response isKindOfClass:[NSHTTPURLResponse class]]) {
  278. NSHTTPURLResponse *r = (NSHTTPURLResponse *)task.response;
  279. appToken = [r allHeaderFields][AUTHORIZATION_HEADER];
  280. }
  281. if(appToken.length) {
  282. [[NSUserDefaults standardUserDefaults] setObject:appToken forKey:WFC_APPSERVER_AUTH_TOKEN];
  283. } else {
  284. NSArray *cookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookiesForURL: [NSURL URLWithString:APP_SERVER_ADDRESS]];
  285. NSData *data = [NSKeyedArchiver archivedDataWithRootObject:cookies];
  286. [[NSUserDefaults standardUserDefaults] setObject:data forKey:WFC_APPSERVER_COOKIES];
  287. }
  288. }
  289. NSDictionary *dict = responseObject;
  290. dispatch_async(dispatch_get_main_queue(), ^{
  291. successBlock(dict);
  292. });
  293. }
  294. failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
  295. dispatch_async(dispatch_get_main_queue(), ^{
  296. errorBlock(error);
  297. });
  298. }];
  299. }
  300. - (void)uploadLogs:(void(^)(void))successBlock error:(void(^)(NSString *errorMsg))errorBlock {
  301. dispatch_async(dispatch_get_global_queue(0, 0), ^{
  302. NSMutableArray<NSString *> *logFiles = [[WFCCNetworkService getLogFilesPath] mutableCopy];
  303. NSMutableArray *uploadedFiles = [[[[NSUserDefaults standardUserDefaults] objectForKey:@"mars_uploaded_files"] sortedArrayUsingComparator:^NSComparisonResult(NSString *obj1, NSString *obj2) {
  304. return [obj1 compare:obj2];
  305. }] mutableCopy];
  306. //日志文件列表需要删除掉已上传记录,避免重复上传。
  307. //但需要上传最后一条已经上传日志,因为那个日志文件可能在上传之后继续写入了,所以需要继续上传
  308. if (uploadedFiles.count) {
  309. [uploadedFiles removeLastObject];
  310. } else {
  311. uploadedFiles = [[NSMutableArray alloc] init];
  312. }
  313. for (NSString *file in [logFiles copy]) {
  314. NSString *name = [file componentsSeparatedByString:@"/"].lastObject;
  315. if ([uploadedFiles containsObject:name]) {
  316. [logFiles removeObject:file];
  317. }
  318. }
  319. __block NSString *errorMsg = nil;
  320. for (NSString *logFile in logFiles) {
  321. AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
  322. manager.responseSerializer.acceptableContentTypes = [NSSet setWithObject:@"application/json"];
  323. NSString *url = [APP_SERVER_ADDRESS stringByAppendingFormat:@"/logs/%@/upload", [WFCCNetworkService sharedInstance].userId];
  324. dispatch_semaphore_t sema = dispatch_semaphore_create(0);
  325. __block BOOL success = NO;
  326. [manager POST:url parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> _Nonnull formData) {
  327. NSData *logData = [NSData dataWithContentsOfFile:logFile];
  328. if (!logData.length) {
  329. logData = [@"empty" dataUsingEncoding:NSUTF8StringEncoding];
  330. }
  331. NSString *fileName = [[NSURL URLWithString:logFile] lastPathComponent];
  332. [formData appendPartWithFileData:logData name:@"file" fileName:fileName mimeType:@"application/octet-stream"];
  333. } progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
  334. if ([responseObject isKindOfClass:[NSDictionary class]]) {
  335. NSDictionary *dict = (NSDictionary *)responseObject;
  336. if([dict[@"code"] intValue] == 0) {
  337. NSLog(@"上传成功");
  338. success = YES;
  339. NSString *name = [logFile componentsSeparatedByString:@"/"].lastObject;
  340. [uploadedFiles removeObject:name];
  341. [uploadedFiles addObject:name];
  342. [[NSUserDefaults standardUserDefaults] setObject:uploadedFiles forKey:@"mars_uploaded_files"];
  343. [[NSUserDefaults standardUserDefaults] synchronize];
  344. }
  345. }
  346. if (!success) {
  347. errorMsg = @"服务器响应错误";
  348. }
  349. dispatch_semaphore_signal(sema);
  350. } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
  351. NSLog(@"上传失败:%@", error);
  352. dispatch_semaphore_signal(sema);
  353. errorMsg = error.localizedFailureReason;
  354. }];
  355. dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
  356. if (!success) {
  357. errorBlock(errorMsg);
  358. return;
  359. }
  360. }
  361. successBlock();
  362. });
  363. }
  364. - (void)getMyPrivateConferenceId:(void(^)(NSString *conferenceId))successBlock error:(void(^)(int errorCode, NSString *message))errorBlock {
  365. [self post:@"/conference/get_my_id" data:nil isLogin:NO success:^(NSDictionary *dict) {
  366. int code = [dict[@"code"] intValue];
  367. if(code == 0) {
  368. NSString *conferenceId = dict[@"result"];
  369. successBlock(conferenceId);
  370. } else {
  371. errorBlock(code, dict[@"message"]);
  372. }
  373. } error:^(NSError * _Nonnull error) {
  374. errorBlock(-1, error.localizedDescription);
  375. }];
  376. }
  377. - (void)createConference:(WFZConferenceInfo *)conferenceInfo success:(void(^)(NSString *conferenceId))successBlock error:(void(^)(int errorCode, NSString *message))errorBlock {
  378. [self post:@"/conference/create" data:[conferenceInfo toDictionary] isLogin:NO success:^(NSDictionary *dict) {
  379. int code = [dict[@"code"] intValue];
  380. if(code == 0) {
  381. NSString *conferenceId = dict[@"result"];
  382. conferenceInfo.conferenceId = conferenceId;
  383. successBlock(conferenceId);
  384. } else {
  385. errorBlock(code, dict[@"message"]);
  386. }
  387. } error:^(NSError * _Nonnull error) {
  388. errorBlock(-1, error.localizedDescription);
  389. }];
  390. }
  391. - (void)updateConference:(WFZConferenceInfo *)conferenceInfo success:(void(^)(void))successBlock error:(void(^)(int errorCode, NSString *message))errorBlock {
  392. [self post:@"/conference/put_info" data:[conferenceInfo toDictionary] isLogin:NO success:^(NSDictionary *dict) {
  393. int code = [dict[@"code"] intValue];
  394. if(code == 0) {
  395. successBlock();
  396. } else {
  397. errorBlock(code, dict[@"message"]);
  398. }
  399. } error:^(NSError * _Nonnull error) {
  400. errorBlock(-1, error.localizedDescription);
  401. }];
  402. }
  403. - (void)recordConference:(NSString *)conferenceId record:(BOOL)record success:(void(^)(void))successBlock error:(void(^)(int errorCode, NSString *message))errorBlock {
  404. [self post:[NSString stringWithFormat:@"/conference/recording/%@", conferenceId] data:@{@"recording":@(record)} isLogin:NO success:^(NSDictionary *dict) {
  405. int code = [dict[@"code"] intValue];
  406. if(code == 0) {
  407. successBlock();
  408. } else {
  409. errorBlock(code, dict[@"message"]);
  410. }
  411. } error:^(NSError * _Nonnull error) {
  412. errorBlock(-1, error.localizedDescription);
  413. }];
  414. }
  415. - (void)focusConference:(NSString *)conferenceId userId:(NSString *)focusUserId success:(void(^)(void))successBlock error:(void(^)(int errorCode, NSString *message))errorBlock {
  416. [self post:[NSString stringWithFormat:@"/conference/focus/%@", conferenceId] data:@{@"userId":(focusUserId?focusUserId:@"")} isLogin:NO success:^(NSDictionary *dict) {
  417. int code = [dict[@"code"] intValue];
  418. if(code == 0) {
  419. successBlock();
  420. } else {
  421. errorBlock(code, dict[@"message"]);
  422. }
  423. } error:^(NSError * _Nonnull error) {
  424. errorBlock(-1, error.localizedDescription);
  425. }];
  426. }
  427. - (void)queryConferenceInfo:(NSString *)conferenceId password:(NSString *)password success:(void(^)(WFZConferenceInfo *conferenceInfo))successBlock error:(void(^)(int errorCode, NSString *message))errorBlock {
  428. NSDictionary *data;
  429. if(password.length) {
  430. data = @{@"conferenceId":conferenceId, @"password":password};
  431. } else {
  432. data = @{@"conferenceId":conferenceId};
  433. }
  434. [self post:@"/conference/info" data:data isLogin:NO success:^(NSDictionary *dict) {
  435. int code = [dict[@"code"] intValue];
  436. if(code == 0) {
  437. WFZConferenceInfo *info = [WFZConferenceInfo fromDictionary:dict[@"result"]];
  438. successBlock(info);
  439. } else {
  440. errorBlock(code, dict[@"message"]);
  441. }
  442. } error:^(NSError * _Nonnull error) {
  443. errorBlock(-1, error.localizedDescription);
  444. }];
  445. }
  446. - (void)destroyConference:(NSString *)conferenceId success:(void(^)(void))successBlock error:(void(^)(int errorCode, NSString *message))errorBlock {
  447. [self post:[NSString stringWithFormat:@"/conference/destroy/%@", conferenceId] data:nil isLogin:NO success:^(NSDictionary *dict) {
  448. int code = [dict[@"code"] intValue];
  449. if(code == 0) {
  450. [[NSNotificationCenter defaultCenter] postNotificationName:kCONFERENCE_DESTROYED object:nil];
  451. successBlock();
  452. } else {
  453. errorBlock(code, dict[@"message"]);
  454. }
  455. } error:^(NSError * _Nonnull error) {
  456. errorBlock(-1, error.localizedDescription);
  457. }];
  458. }
  459. - (void)favConference:(NSString *)conferenceId success:(void(^)(void))successBlock error:(void(^)(int errorCode, NSString *message))errorBlock {
  460. [self post:[NSString stringWithFormat:@"/conference/fav/%@", conferenceId] data:nil isLogin:NO success:^(NSDictionary *dict) {
  461. int code = [dict[@"code"] intValue];
  462. if(code == 0) {
  463. successBlock();
  464. } else {
  465. errorBlock(code, dict[@"message"]);
  466. }
  467. } error:^(NSError * _Nonnull error) {
  468. errorBlock(-1, error.localizedDescription);
  469. }];
  470. }
  471. - (void)unfavConference:(NSString *)conferenceId success:(void(^)(void))successBlock error:(void(^)(int errorCode, NSString *message))errorBlock {
  472. [self post:[NSString stringWithFormat:@"/conference/unfav/%@", conferenceId] data:nil isLogin:NO success:^(NSDictionary *dict) {
  473. int code = [dict[@"code"] intValue];
  474. if(code == 0) {
  475. successBlock();
  476. } else {
  477. errorBlock(code, dict[@"message"]);
  478. }
  479. } error:^(NSError * _Nonnull error) {
  480. errorBlock(-1, error.localizedDescription);
  481. }];
  482. }
  483. - (void)isFavConference:(NSString *)conferenceId success:(void(^)(BOOL isFav))successBlock error:(void(^)(int errorCode, NSString *message))errorBlock {
  484. [self post:[NSString stringWithFormat:@"/conference/is_fav/%@", conferenceId] data:nil isLogin:NO success:^(NSDictionary *dict) {
  485. int code = [dict[@"code"] intValue];
  486. if(code == 0) {
  487. successBlock(YES);
  488. } else if(code == 16) {
  489. successBlock(NO);
  490. } else {
  491. errorBlock(code, dict[@"message"]);
  492. }
  493. } error:^(NSError * _Nonnull error) {
  494. errorBlock(-1, error.localizedDescription);
  495. }];
  496. }
  497. - (void)getFavConferences:(void(^)(NSArray<WFZConferenceInfo *> *))successBlock error:(void(^)(int errorCode, NSString *message))errorBlock {
  498. [self post:@"/conference/fav_conferences" data:nil isLogin:NO success:^(NSDictionary *dict) {
  499. int code = [dict[@"code"] intValue];
  500. if(code == 0) {
  501. NSArray<NSDictionary *> *ls = dict[@"result"];
  502. NSMutableArray *output = [[NSMutableArray alloc] init];
  503. [ls enumerateObjectsUsingBlock:^(NSDictionary * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
  504. [output addObject:[WFZConferenceInfo fromDictionary:obj]];
  505. }];
  506. successBlock(output);
  507. } else {
  508. errorBlock(code, dict[@"message"]);
  509. }
  510. } error:^(NSError * _Nonnull error) {
  511. errorBlock(-1, error.localizedDescription);
  512. }];
  513. }
  514. - (void)changeName:(NSString *)newName success:(void(^)(void))successBlock error:(void(^)(int errorCode, NSString *message))errorBlock {
  515. [self post:@"/change_name" data:@{@"newName":newName} isLogin:NO success:^(NSDictionary *dict) {
  516. if([dict[@"code"] intValue] == 0) {
  517. if(successBlock) successBlock();
  518. } else {
  519. NSString *errmsg;
  520. if ([dict[@"code"] intValue] == 17) {
  521. errmsg = @"用户名已经存在";
  522. } else {
  523. errmsg = @"网络错误";
  524. }
  525. if(errorBlock) errorBlock([dict[@"code"] intValue], errmsg);
  526. }
  527. } error:^(NSError * _Nonnull error) {
  528. if(errorBlock) errorBlock(-1, error.localizedDescription);
  529. }];
  530. }
  531. - (void)showPCSessionViewController:(UIViewController *)baseController pcClient:(WFCCPCOnlineInfo *)clientInfo {
  532. PCSessionViewController *vc = [[PCSessionViewController alloc] init];
  533. vc.pcClientInfo = clientInfo;
  534. vc.hidesBottomBarWhenPushed = YES;
  535. [baseController.navigationController pushViewController:vc animated:YES];
  536. }
  537. - (void)addDevice:(NSString *)name
  538. deviceId:(NSString *)deviceId
  539. owner:(NSArray<NSString *> *)owners
  540. success:(void(^)(Device *device))successBlock
  541. error:(void(^)(int error_code))errorBlock {
  542. NSString *path = @"/things/add_device";
  543. NSDictionary *extraDict = @{@"name":name};
  544. NSData *jsonData = [NSJSONSerialization dataWithJSONObject:extraDict options:0 error:0];
  545. NSString *dataStr = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
  546. NSDictionary *param = @{@"deviceId":deviceId, @"owners":owners, @"extra":dataStr};
  547. [self post:path data:param isLogin:NO success:^(NSDictionary *dict) {
  548. if([dict[@"code"] intValue] == 0) {
  549. Device *device = [[Device alloc] init];
  550. device.deviceId = dict[@"deviceId"];
  551. device.name = name;
  552. device.token = dict[@"token"];
  553. device.secret = dict[@"secret"];
  554. device.owners = owners;
  555. if(successBlock) successBlock(device);
  556. } else {
  557. if(errorBlock) errorBlock([dict[@"code"] intValue]);
  558. }
  559. } error:^(NSError * _Nonnull error) {
  560. if(errorBlock) errorBlock(-1);
  561. }];
  562. }
  563. - (void)getMyDevices:(void(^)(NSArray<Device *> *devices))successBlock
  564. error:(void(^)(int error_code))errorBlock {
  565. NSString *path = @"/things/list_device";
  566. [self post:path data:nil isLogin:NO success:^(NSDictionary *dict) {
  567. if([dict[@"code"] intValue] == 0) {
  568. if ([dict[@"result"] isKindOfClass:[NSArray class]]) {
  569. NSMutableArray *output = [[NSMutableArray alloc] init];
  570. NSArray<NSDictionary *> *ds = (NSArray *)dict[@"result"];
  571. for (NSDictionary *d in ds) {
  572. Device *device = [[Device alloc] init];
  573. device.deviceId = [d objectForKey:@"deviceId"];
  574. device.secret = [d objectForKey:@"secret"];
  575. device.token = [d objectForKey:@"token"];
  576. device.owners = [d objectForKey:@"owners"];
  577. NSString *extra = d[@"extra"];
  578. if (extra.length) {
  579. NSData *jsonData = [extra dataUsingEncoding:NSUTF8StringEncoding];
  580. NSError *err;
  581. NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:jsonData
  582. options:NSJSONReadingMutableContainers
  583. error:&err];
  584. if(!err) {
  585. device.name = dic[@"name"];
  586. }
  587. }
  588. [output addObject:device];
  589. }
  590. if(successBlock) successBlock(output);
  591. } else {
  592. if(errorBlock) errorBlock(-1);
  593. }
  594. } else {
  595. if(errorBlock) errorBlock([dict[@"code"] intValue]);
  596. }
  597. } error:^(NSError * _Nonnull error) {
  598. if(errorBlock) errorBlock(-1);
  599. }];
  600. }
  601. - (void)delDevice:(NSString *)deviceId
  602. success:(void(^)(Device *device))successBlock
  603. error:(void(^)(int error_code))errorBlock {
  604. NSString *path = @"/things/del_device";
  605. NSDictionary *param = @{@"deviceId":deviceId};
  606. [self post:path data:param isLogin:NO success:^(NSDictionary *dict) {
  607. if([dict[@"code"] intValue] == 0) {
  608. if(successBlock) successBlock(nil);
  609. } else {
  610. errorBlock([dict[@"code"] intValue]);
  611. }
  612. } error:^(NSError * _Nonnull error) {
  613. if(errorBlock) errorBlock(-1);
  614. }];
  615. }
  616. - (void)getFavoriteItems:(int )startId
  617. count:(int)count
  618. success:(void(^)(NSArray<WFCUFavoriteItem *> *items, BOOL hasMore))successBlock
  619. error:(void(^)(int error_code))errorBlock {
  620. NSString *path = @"/fav/list";
  621. NSDictionary *param = @{@"id":@(startId), @"count":@(count)};
  622. [self post:path data:param isLogin:NO success:^(NSDictionary *dict) {
  623. if([dict[@"code"] intValue] == 0) {
  624. NSDictionary *result = dict[@"result"];
  625. BOOL hasMore = [result[@"hasMore"] boolValue];
  626. NSArray<NSDictionary *> *arrs = (NSArray *)result[@"items"];
  627. NSMutableArray<WFCUFavoriteItem *> *output = [[NSMutableArray alloc] init];
  628. for (NSDictionary *d in arrs) {
  629. WFCUFavoriteItem *item = [[WFCUFavoriteItem alloc] init];
  630. item.conversation = [WFCCConversation conversationWithType:[d[@"convType"] intValue] target:d[@"convTarget"] line:[d[@"convLine"] intValue]];
  631. item.favId = [d[@"id"] intValue];
  632. if(![d[@"messageUid"] isEqual:[NSNull null]])
  633. item.messageUid = [d[@"messageUid"] longLongValue];
  634. item.timestamp = [d[@"timestamp"] longLongValue];
  635. item.url = d[@"url"];
  636. item.favType = [d[@"type"] intValue];
  637. item.title = d[@"title"];
  638. item.data = d[@"data"];
  639. item.origin = d[@"origin"];
  640. item.thumbUrl = d[@"thumbUrl"];
  641. item.sender = d[@"sender"];
  642. [output addObject:item];
  643. }
  644. if(successBlock) successBlock(output, hasMore);
  645. } else {
  646. errorBlock([dict[@"code"] intValue]);
  647. }
  648. } error:^(NSError * _Nonnull error) {
  649. if(errorBlock) errorBlock(-1);
  650. }];
  651. }
  652. - (void)addFavoriteItem:(WFCUFavoriteItem *)item
  653. success:(void(^)(void))successBlock
  654. error:(void(^)(int error_code))errorBlock {
  655. NSString *path = @"/fav/add";
  656. NSDictionary *param = @{@"type":@(item.favType),
  657. @"messageUid":@(item.messageUid),
  658. @"convType":@(item.conversation.type),
  659. @"convLine":@(item.conversation.line),
  660. @"convTarget":item.conversation.target?item.conversation.target:@"",
  661. @"origin":item.origin?item.origin:@"",
  662. @"sender":item.sender?item.sender:@"",
  663. @"title":item.title?item.title:@"",
  664. @"url":item.url?item.url:@"",
  665. @"thumbUrl":item.thumbUrl?item.thumbUrl:@"",
  666. @"data":item.data?item.data:@""
  667. };
  668. [self post:path data:param isLogin:NO success:^(NSDictionary *dict) {
  669. if([dict[@"code"] intValue] == 0) {
  670. if(successBlock) successBlock();
  671. } else {
  672. if(errorBlock) errorBlock([dict[@"code"] intValue]);
  673. }
  674. } error:^(NSError * _Nonnull error) {
  675. if(errorBlock) errorBlock(-1);
  676. }];
  677. }
  678. - (void)removeFavoriteItem:(int)favId
  679. success:(void(^)(void))successBlock
  680. error:(void(^)(int error_code))errorBlock {
  681. NSString *path = [NSString stringWithFormat:@"/fav/del/%d", favId];
  682. [self post:path data:nil isLogin:NO success:^(NSDictionary *dict) {
  683. if([dict[@"code"] intValue] == 0) {
  684. if(successBlock) successBlock();
  685. } else {
  686. if(errorBlock) errorBlock([dict[@"code"] intValue]);
  687. }
  688. } error:^(NSError * _Nonnull error) {
  689. if(errorBlock) errorBlock(-1);
  690. }];
  691. }
  692. - (NSString *)userDefaultPortrait:(WFCCUserInfo *)userInfo {
  693. if(userInfo.portrait.length) {
  694. return userInfo.portrait;
  695. } else {
  696. return [APP_SERVER_ADDRESS stringByAppendingFormat:@"/avatar?name=%@", userInfo.displayName];
  697. }
  698. }
  699. - (NSString *)groupDefaultPortrait:(WFCCGroupInfo *)groupInfo memberInfos:(NSArray<WFCCUserInfo *> *)memberInfos {
  700. if(groupInfo.portrait.length) {
  701. return groupInfo.portrait;
  702. }
  703. NSMutableArray *reqMembers = [[NSMutableArray alloc] init];
  704. [memberInfos enumerateObjectsUsingBlock:^(WFCCUserInfo * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
  705. if(obj.portrait.length && [obj.portrait rangeOfString:APP_SERVER_ADDRESS].location == NSNotFound) {
  706. [reqMembers addObject:@{@"avatarUrl" : obj.portrait}];
  707. } else {
  708. [reqMembers addObject:@{@"name" : obj.displayName}];
  709. }
  710. }];
  711. NSDictionary *request = @{@"members" : reqMembers};
  712. NSError * err;
  713. NSData * jsonData = [NSJSONSerialization dataWithJSONObject:request options:0 error:&err];
  714. return [APP_SERVER_ADDRESS stringByAppendingFormat:@"/avatar/group?request=%@", [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]];
  715. }
  716. - (NSData *)getAppServiceCookies {
  717. return [[NSUserDefaults standardUserDefaults] objectForKey:WFC_APPSERVER_COOKIES];
  718. }
  719. - (NSString *)getAppServiceAuthToken {
  720. return [[NSUserDefaults standardUserDefaults] objectForKey:WFC_APPSERVER_AUTH_TOKEN];
  721. }
  722. - (void)clearAppServiceAuthInfos {
  723. [[NSUserDefaults standardUserDefaults] removeObjectForKey:WFC_APPSERVER_COOKIES];
  724. [[NSUserDefaults standardUserDefaults] removeObjectForKey:WFC_APPSERVER_AUTH_TOKEN];
  725. NSUserDefaults *sharedDefaults = [[NSUserDefaults alloc] initWithSuiteName:WFC_SHARE_APP_GROUP_ID];//此处id要与开发者中心创建时一致
  726. [sharedDefaults removeObjectForKey:WFC_SHARE_APPSERVICE_AUTH_TOKEN];
  727. NSArray<NSHTTPCookie *> *cookies = [[NSHTTPCookieStorage sharedCookieStorageForGroupContainerIdentifier:WFC_SHARE_APP_GROUP_ID] cookies];
  728. [cookies enumerateObjectsUsingBlock:^(NSHTTPCookie * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
  729. [[NSHTTPCookieStorage sharedCookieStorageForGroupContainerIdentifier:WFC_SHARE_APP_GROUP_ID] deleteCookie:obj];
  730. }];
  731. [[WKWebsiteDataStore defaultDataStore] fetchDataRecordsOfTypes:[WKWebsiteDataStore allWebsiteDataTypes] completionHandler:^(NSArray * __nonnull records) {
  732. for (WKWebsiteDataRecord *record in records) {
  733. [[WKWebsiteDataStore defaultDataStore] removeDataOfTypes:record.dataTypes forDataRecords:@[record] completionHandler:^{}];
  734. }
  735. }];
  736. }
  737. @end