2
0

AppService.m 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  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. static AppService *sharedSingleton = nil;
  14. @implementation AppService
  15. + (AppService *)sharedAppService {
  16. if (sharedSingleton == nil) {
  17. @synchronized (self) {
  18. if (sharedSingleton == nil) {
  19. sharedSingleton = [[AppService alloc] init];
  20. }
  21. }
  22. }
  23. return sharedSingleton;
  24. }
  25. - (void)login:(NSString *)user password:(NSString *)password success:(void(^)(NSString *userId, NSString *token, BOOL newUser))successBlock error:(void(^)(int errCode, NSString *message))errorBlock {
  26. [self post:@"/login" data:@{@"mobile":user, @"code":password, @"clientId":[[WFCCNetworkService sharedInstance] getClientId], @"platform":@(Platform_iOS)} success:^(NSDictionary *dict) {
  27. if([dict[@"code"] intValue] == 0) {
  28. NSString *userId = dict[@"result"][@"userId"];
  29. NSString *token = dict[@"result"][@"token"];
  30. BOOL newUser = [dict[@"result"][@"register"] boolValue];
  31. successBlock(userId, token, newUser);
  32. } else {
  33. errorBlock([dict[@"code"] intValue], dict[@"message"]);
  34. }
  35. } error:^(NSError * _Nonnull error) {
  36. errorBlock(-1, error.description);
  37. }];
  38. }
  39. - (void)sendCode:(NSString *)phoneNumber success:(void(^)(void))successBlock error:(void(^)(NSString *message))errorBlock {
  40. [self post:@"/send_code" data:@{@"mobile":phoneNumber} success:^(NSDictionary *dict) {
  41. if([dict[@"code"] intValue] == 0) {
  42. successBlock();
  43. } else {
  44. errorBlock(@"error");
  45. }
  46. } error:^(NSError * _Nonnull error) {
  47. errorBlock(error.localizedDescription);
  48. }];
  49. }
  50. - (void)pcScaned:(NSString *)sessionId success:(void(^)(void))successBlock error:(void(^)(int errorCode, NSString *message))errorBlock {
  51. NSString *path = [NSString stringWithFormat:@"/scan_pc/%@", sessionId];
  52. [self post:path data:nil success:^(NSDictionary *dict) {
  53. if([dict[@"code"] intValue] == 0) {
  54. successBlock();
  55. } else {
  56. errorBlock([dict[@"code"] intValue], @"Network error");
  57. }
  58. } error:^(NSError * _Nonnull error) {
  59. errorBlock(-1, error.localizedDescription);
  60. }];
  61. }
  62. - (void)pcConfirmLogin:(NSString *)sessionId success:(void(^)(void))successBlock error:(void(^)(int errorCode, NSString *message))errorBlock {
  63. NSString *path = @"/confirm_pc";
  64. NSDictionary *param = @{@"im_token":@"", @"token":sessionId, @"user_id":[WFCCNetworkService sharedInstance].userId};
  65. [self post:path data:param success:^(NSDictionary *dict) {
  66. if([dict[@"code"] intValue] == 0) {
  67. successBlock();
  68. } else {
  69. errorBlock([dict[@"code"] intValue], @"Network error");
  70. }
  71. } error:^(NSError * _Nonnull error) {
  72. errorBlock(-1, error.localizedDescription);
  73. }];
  74. }
  75. - (void)getGroupAnnouncement:(NSString *)groupId
  76. success:(void(^)(WFCUGroupAnnouncement *))successBlock
  77. error:(void(^)(int error_code))errorBlock {
  78. if (successBlock) {
  79. NSData *data = [[NSUserDefaults standardUserDefaults] objectForKey:[NSString stringWithFormat:@"wfc_group_an_%@", groupId]];
  80. WFCUGroupAnnouncement *an = [[WFCUGroupAnnouncement alloc] init];
  81. an.data = data;
  82. an.groupId = groupId;
  83. successBlock(an);
  84. }
  85. NSString *path = @"/get_group_announcement";
  86. NSDictionary *param = @{@"groupId":groupId};
  87. [self post:path data:param success:^(NSDictionary *dict) {
  88. if([dict[@"code"] intValue] == 0 || [dict[@"code"] intValue] == 12) {
  89. WFCUGroupAnnouncement *an = [[WFCUGroupAnnouncement alloc] init];
  90. an.groupId = groupId;
  91. if ([dict[@"code"] intValue] == 0) {
  92. an.author = dict[@"result"][@"author"];
  93. an.text = dict[@"result"][@"text"];
  94. an.timestamp = [dict[@"result"][@"timestamp"] longValue];
  95. }
  96. [[NSUserDefaults standardUserDefaults] setValue:an.data forKey:[NSString stringWithFormat:@"wfc_group_an_%@", groupId]];
  97. [[NSUserDefaults standardUserDefaults] synchronize];
  98. successBlock(an);
  99. } else {
  100. errorBlock([dict[@"code"] intValue]);
  101. }
  102. } error:^(NSError * _Nonnull error) {
  103. errorBlock(-1);
  104. }];
  105. }
  106. - (void)updateGroup:(NSString *)groupId
  107. announcement:(NSString *)announcement
  108. success:(void(^)(long timestamp))successBlock
  109. error:(void(^)(int error_code))errorBlock {
  110. NSString *path = @"/put_group_announcement";
  111. NSDictionary *param = @{@"groupId":groupId, @"author":[WFCCNetworkService sharedInstance].userId, @"text":announcement};
  112. [self post:path data:param success:^(NSDictionary *dict) {
  113. if([dict[@"code"] intValue] == 0) {
  114. WFCUGroupAnnouncement *an = [[WFCUGroupAnnouncement alloc] init];
  115. an.groupId = groupId;
  116. an.author = [WFCCNetworkService sharedInstance].userId;
  117. an.text = announcement;
  118. an.timestamp = [dict[@"result"][@"timestamp"] longValue];
  119. [[NSUserDefaults standardUserDefaults] setValue:an.data forKey:[NSString stringWithFormat:@"wfc_group_an_%@", groupId]];
  120. [[NSUserDefaults standardUserDefaults] synchronize];
  121. successBlock(an.timestamp);
  122. } else {
  123. errorBlock([dict[@"code"] intValue]);
  124. }
  125. } error:^(NSError * _Nonnull error) {
  126. errorBlock(-1);
  127. }];
  128. }
  129. - (void)post:(NSString *)path data:(id)data success:(void(^)(NSDictionary *dict))successBlock error:(void(^)(NSError * _Nonnull error))errorBlock {
  130. AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
  131. manager.requestSerializer = [AFJSONRequestSerializer serializer];
  132. manager.responseSerializer.acceptableContentTypes = [NSSet setWithObject:@"application/json"];
  133. //在调用其他接口时需要把cookie传给后台,也就是设置cookie的过程
  134. NSData *cookiesdata = [[NSUserDefaults standardUserDefaults] objectForKey:@"WFC_APPSERVER_COOKIES"];//url和登陆时传的url 是同一个
  135. if([cookiesdata length]) {
  136. NSArray *cookies = [NSKeyedUnarchiver unarchiveObjectWithData:cookiesdata];
  137. NSHTTPCookie *cookie;
  138. for (cookie in cookies) {
  139. [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:cookie];
  140. }
  141. }
  142. [manager POST:[APP_SERVER_ADDRESS stringByAppendingPathComponent:path]
  143. parameters:data
  144. progress:nil
  145. success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
  146. //Save cookies
  147. NSArray *cookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookiesForURL: [NSURL URLWithString:APP_SERVER_ADDRESS]];
  148. NSData *data = [NSKeyedArchiver archivedDataWithRootObject:cookies];
  149. [[NSUserDefaults standardUserDefaults] setObject:data forKey:@"WFC_APPSERVER_COOKIES"];
  150. NSDictionary *dict = responseObject;
  151. dispatch_async(dispatch_get_main_queue(), ^{
  152. successBlock(dict);
  153. });
  154. }
  155. failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
  156. dispatch_async(dispatch_get_main_queue(), ^{
  157. errorBlock(error);
  158. });
  159. }];
  160. }
  161. - (void)uploadLogs:(void(^)(void))successBlock error:(void(^)(NSString *errorMsg))errorBlock {
  162. dispatch_async(dispatch_get_global_queue(0, 0), ^{
  163. NSMutableArray<NSString *> *logFiles = [[WFCCNetworkService getLogFilesPath] mutableCopy];
  164. NSMutableArray *uploadedFiles = [[[[NSUserDefaults standardUserDefaults] objectForKey:@"mars_uploaded_files"] sortedArrayUsingComparator:^NSComparisonResult(NSString *obj1, NSString *obj2) {
  165. return [obj1 compare:obj2];
  166. }] mutableCopy];
  167. //日志文件列表需要删除掉已上传记录,避免重复上传。
  168. //但需要上传最后一条已经上传日志,因为那个日志文件可能在上传之后继续写入了,所以需要继续上传
  169. if (uploadedFiles.count) {
  170. [uploadedFiles removeLastObject];
  171. }
  172. for (NSString *file in [logFiles copy]) {
  173. NSString *name = [file componentsSeparatedByString:@"/"].lastObject;
  174. if ([uploadedFiles containsObject:name]) {
  175. [logFiles removeObject:file];
  176. }
  177. }
  178. __block NSString *errorMsg = nil;
  179. for (NSString *logFile in logFiles) {
  180. AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
  181. manager.responseSerializer.acceptableContentTypes = [NSSet setWithObject:@"application/json"];
  182. NSString *url = [APP_SERVER_ADDRESS stringByAppendingFormat:@"/logs/%@/upload", [WFCCNetworkService sharedInstance].userId];
  183. dispatch_semaphore_t sema = dispatch_semaphore_create(0);
  184. __block BOOL success = NO;
  185. [manager POST:url parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> _Nonnull formData) {
  186. NSData *logData = [NSData dataWithContentsOfFile:logFile];
  187. if (!logData.length) {
  188. logData = [@"empty" dataUsingEncoding:NSUTF8StringEncoding];
  189. }
  190. NSString *fileName = [[NSURL URLWithString:logFile] lastPathComponent];
  191. [formData appendPartWithFileData:logData name:@"file" fileName:fileName mimeType:@"application/octet-stream"];
  192. } progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
  193. if ([responseObject isKindOfClass:[NSDictionary class]]) {
  194. NSDictionary *dict = (NSDictionary *)responseObject;
  195. if([dict[@"code"] intValue] == 0) {
  196. NSLog(@"上传成功");
  197. success = YES;
  198. NSString *name = [logFile componentsSeparatedByString:@"/"].lastObject;
  199. [uploadedFiles removeObject:name];
  200. [uploadedFiles addObject:name];
  201. [[NSUserDefaults standardUserDefaults] setObject:uploadedFiles forKey:@"mars_uploaded_files"];
  202. [[NSUserDefaults standardUserDefaults] synchronize];
  203. }
  204. }
  205. if (!success) {
  206. errorMsg = @"服务器响应错误";
  207. }
  208. dispatch_semaphore_signal(sema);
  209. } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
  210. NSLog(@"上传失败:%@", error);
  211. dispatch_semaphore_signal(sema);
  212. errorMsg = error.localizedFailureReason;
  213. }];
  214. dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
  215. if (!success) {
  216. errorBlock(errorMsg);
  217. return;
  218. }
  219. }
  220. successBlock();
  221. });
  222. }
  223. - (void)showPCSessionViewController:(UIViewController *)baseController pcClient:(WFCCPCOnlineInfo *)clientInfo {
  224. PCSessionViewController *vc = [[PCSessionViewController alloc] init];
  225. vc.pcClientInfo = clientInfo;
  226. [baseController.navigationController pushViewController:vc animated:YES];
  227. }
  228. - (void)addDevice:(NSString *)name
  229. deviceId:(NSString *)deviceId
  230. owner:(NSArray<NSString *> *)owners
  231. success:(void(^)(Device *device))successBlock
  232. error:(void(^)(int error_code))errorBlock {
  233. NSString *path = @"/things/add_device";
  234. NSDictionary *extraDict = @{@"name":name};
  235. NSData *jsonData = [NSJSONSerialization dataWithJSONObject:extraDict options:0 error:0];
  236. NSString *dataStr = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
  237. NSDictionary *param = @{@"deviceId":deviceId, @"owners":owners, @"extra":dataStr};
  238. [self post:path data:param success:^(NSDictionary *dict) {
  239. if([dict[@"code"] intValue] == 0) {
  240. successBlock(nil);
  241. } else {
  242. errorBlock([dict[@"code"] intValue]);
  243. }
  244. } error:^(NSError * _Nonnull error) {
  245. errorBlock(-1);
  246. }];
  247. }
  248. - (void)getMyDevices:(void(^)(NSArray<Device *> *devices))successBlock
  249. error:(void(^)(int error_code))errorBlock {
  250. NSString *path = @"/things/list_device";
  251. [self post:path data:nil success:^(NSDictionary *dict) {
  252. if([dict[@"code"] intValue] == 0) {
  253. if ([dict[@"result"] isKindOfClass:[NSArray class]]) {
  254. NSMutableArray *output = [[NSMutableArray alloc] init];
  255. NSArray<NSDictionary *> *ds = (NSArray *)dict[@"result"];
  256. for (NSDictionary *d in ds) {
  257. Device *device = [[Device alloc] init];
  258. device.deviceId = [d objectForKey:@"deviceId"];
  259. device.secret = [d objectForKey:@"secret"];
  260. device.token = [d objectForKey:@"token"];
  261. device.owners = [d objectForKey:@"owners"];
  262. NSString *extra = d[@"extra"];
  263. if (extra.length) {
  264. NSData *jsonData = [extra dataUsingEncoding:NSUTF8StringEncoding];
  265. NSError *err;
  266. NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:jsonData
  267. options:NSJSONReadingMutableContainers
  268. error:&err];
  269. if(!err) {
  270. device.name = dic[@"name"];
  271. }
  272. }
  273. [output addObject:device];
  274. }
  275. successBlock(output);
  276. } else {
  277. errorBlock(-1);
  278. }
  279. } else {
  280. errorBlock([dict[@"code"] intValue]);
  281. }
  282. } error:^(NSError * _Nonnull error) {
  283. errorBlock(-1);
  284. }];
  285. }
  286. @end