summaryrefslogtreecommitdiff
path: root/Juick/API.m
diff options
context:
space:
mode:
Diffstat (limited to 'Juick/API.m')
-rw-r--r--Juick/API.m314
1 files changed, 314 insertions, 0 deletions
diff --git a/Juick/API.m b/Juick/API.m
new file mode 100644
index 0000000..4f57dc6
--- /dev/null
+++ b/Juick/API.m
@@ -0,0 +1,314 @@
+//
+// API.m
+// Juick
+//
+// Created by Vitaly Takmazov on 22/08/16.
+// Copyright © 2016 com.juick. All rights reserved.
+//
+#import "Message.h"
+#import "Chat.h"
+#import "API.h"
+
+@interface API ()
+@property(nonatomic, strong) NSOperationQueue *backgroundQueue;
+@property(nonatomic, strong) NSURL *baseURL;
+@property(nonatomic, strong) NSURLSession *urlSession;
+
+-(void) get:(NSString *)path params:(NSDictionary *)params callback:(void(^)(NSDictionary *, NSError *))callback;
+-(NSString *) authorizationHeader;
+
+@end
+
+@implementation API
+
+-(id)init {
+ if (self = [super init]) {
+ NSString *baseURLString = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"base_url"];
+ NSLog(@"Initializing with %@ base URL", baseURLString);
+ self.baseURL = [NSURL URLWithString:baseURLString];
+ self.backgroundQueue = [NSOperationQueue new];
+ self.urlSession = [NSURLSession sharedSession];
+ }
+ return self;
+}
+
+- (NSString *) authorizationHeader {
+ NSString *token = [[NSUserDefaults standardUserDefaults] stringForKey:@"token"];
+ if (token) {
+ return [NSString stringWithFormat:@"Juick %@", token];
+ }
+ return nil;
+}
+
+- (void)authenticateWithUser:(NSString *)username password:(NSString *)password callback:(void(^)(BOOL))completed {
+ NSURL *url = [NSURL URLWithString:@"me"relativeToURL:self.baseURL];
+ NSString *basicAuthString = [NSString stringWithFormat:@"Basic %@", [[[NSString stringWithFormat:@"%@:%@", username, password] dataUsingEncoding:NSUTF8StringEncoding] base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed]];
+
+ [self fetchDataWithURL:url data:nil boundary:nil authorizationHeader:basicAuthString callback:^(NSData *response, NSError *err) {
+ if (!err) {
+ NSError *jsonError;
+ NSDictionary *jsonData = [NSJSONSerialization JSONObjectWithData:response options:0 error:&jsonError];
+ if (!jsonError) {
+ User *me = [User fromJSON:jsonData];
+ [[NSUserDefaults standardUserDefaults] setValue:me.token forKeyPath:@"token"];
+ self.currentUser = me;
+ completed(YES);
+ }
+ }
+ completed(NO);
+ }];
+}
+
+- (void)signout {
+ self.currentUser = nil;
+ [[NSUserDefaults standardUserDefaults] removeObjectForKey:@"token"];
+}
+
+-(void) pullNextFromPath:(NSString *)path params:(NSDictionary *) params callback:(void(^)(NSArray<Message *> *, NSError *))callback {
+ [self get:path params:params callback:^(NSDictionary *response, NSError *error) {
+ NSMutableArray *messages = [NSMutableArray new];
+ if (!error) {
+ [((NSArray *)response) enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
+ [messages addObject:[Message fromJSON:obj]];
+ }];
+ }
+ callback(messages, error);
+ }];
+}
+
+- (void)me:(void (^)(User *, NSError *error))callback {
+ [self get:@"me" params:nil callback:^(NSDictionary *response, NSError *err) {
+ User *visitor;
+ if (!err) {
+ visitor = [User fromJSON:response];
+ self.currentUser = visitor;
+ }
+ callback(visitor, err);
+ }];
+}
+
+-(void) postMessage:(NSString *)text result:(void (^)(Message *, NSError *))callback {
+ [self post:@"post" params:@{
+ @"body": text
+ } callback:^(NSDictionary *response, NSError *err) {
+ Message *result;
+ if (!err) {
+ result = [Message fromJSON:response[@"newMessage"]];
+ }
+ callback(result, err);
+ }];
+}
+
+-(void) postReplyToThread:(NSNumber *)mid inReplyTo:(NSNumber *)rid text:(NSString *)text result:(void(^)(Message *, NSError *))callback {
+ [self post:@"comment" params:@{
+ @"mid": mid,
+ @"rid": [NSString stringWithFormat:@"%ld", [rid integerValue]],
+ @"body": text
+ } callback:^(NSDictionary *response, NSError *err) {
+ Message *reply;
+ if (!err) {
+ NSLog(@"Success!");
+ reply = [Message fromJSON:response];
+ }
+ callback(reply, err);
+ }];
+}
+
+-(void) postPMToUser:(NSString *)uname text:(NSString *)text result:(void (^)(NSError *))callback {
+ [self.backgroundQueue addOperationWithBlock:^{
+ [self post:@"pm" params:@{
+ @"uname": uname,
+ @"body": text
+ } callback:^(NSDictionary *response, NSError *err) {
+ callback(err);
+ }];
+ }];
+}
+
+-(void) fetchChats:(void (^)(NSArray *, NSError *))callback {
+ [self get:@"groups_pms" params:nil callback:^(NSDictionary *response, NSError *err) {
+ NSMutableArray *groups = [NSMutableArray new];
+ NSArray *pms = [response objectForKey:@"pms"];
+ [pms enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
+ [groups addObject:[Chat fromJSON:obj]];
+ }];
+ callback(groups, err);
+ }];
+}
+
+-(void) fetchChatWithUser:(NSString *)uname callback:(void (^)(NSArray *, NSError *))callback {
+ NSDictionary *params = @{@"uname": uname};
+ [self get:@"pm" params:params callback:^(NSDictionary *response, NSError *err) {
+ NSMutableArray *messages = [NSMutableArray new];
+ if (!err) {
+ NSArray *messagesList = (NSArray *)response;
+ [messagesList enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
+ [messages addObject:[Message fromJSON:obj]];
+ }];
+ }
+ callback(messages, err);
+ }];
+}
+
+-(void) authenticate:(void (^)(User *user, NSError *error))callback {
+ [self get:@"me" params:nil callback:^(NSDictionary *response, NSError *error) {
+ User *user;
+ if (!error) {
+ user = [User fromJSON:response];
+ }
+ callback(user, error);
+ }];
+}
+
+-(void) getUserByName:(NSString *) name callback:(void(^)(User *))callback {
+ NSDictionary *params = @{@"uname": name};
+ [self get:@"users" params:params callback:^(NSDictionary *response, NSError *err) {
+ if (!err) {
+ callback([User fromJSON:[(NSArray *)response firstObject]]);
+ } else {
+ callback(nil);
+ }
+ }];
+}
+
+-(void) refreshDeviceRegistration:(DeviceRegistration *)registrationData callback:(void (^)(BOOL))callback {
+ NSURL *notificationsUrl = [NSURL URLWithString:@"notifications" relativeToURL:self.baseURL];
+ NSError *error;
+ NSDictionary *token = [registrationData toJSON];
+ NSData *jsonData = [NSJSONSerialization dataWithJSONObject:@[token] options:kNilOptions error:&error];
+ [self fetchDataWithURL:notificationsUrl data:jsonData boundary:nil authorizationHeader:self.authorizationHeader callback:^(NSData *response, NSError *err) {
+ callback(!err);
+ }];
+}
+
+-(void) fetchDataWithURL:(NSURL *) url data:(NSData *)postData boundary:(NSString *)boundary authorizationHeader:(NSString *)header callback:(void(^)(NSData *, NSError *))callback {
+ NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
+ if (header) {
+ [request addValue:header forHTTPHeaderField:@"Authorization"];
+ }
+ if (boundary) {
+ request.HTTPMethod = @"POST";
+ request.HTTPBody = postData;
+ NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary];
+ [request setValue:contentType forHTTPHeaderField: @"Content-Type"];
+ } else if (postData) {
+ request.HTTPMethod = @"PUT";
+ request.HTTPBody = postData;
+ [request setValue:@"application/json" forHTTPHeaderField: @"Content-Type"];
+ } else {
+ request.HTTPMethod = @"GET";
+ }
+
+ NSURLSessionDataTask *task = [self.urlSession dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
+ if (error) {
+ [[NSOperationQueue mainQueue] addOperationWithBlock:^{
+ callback(nil, error);
+ }];
+ } else {
+ NSInteger statusCode = ((NSHTTPURLResponse *)response).statusCode;
+ if (!response || statusCode != 200) {
+ NSURL *url = request.URL;
+ NSError *err = [NSError errorWithDomain:@"JuickErrorDomain"
+ code:statusCode
+ userInfo:@{@"url": url.absoluteString}];
+ [[NSOperationQueue mainQueue] addOperationWithBlock:^{
+ callback(nil, err);
+ }];
+ } else {
+ [[NSOperationQueue mainQueue] addOperationWithBlock:^{
+ callback(data, error);
+ }];
+ }
+ }
+ }];
+ [self.backgroundQueue addOperationWithBlock:^{
+ [task resume];
+ }];
+}
+
+-(NSURL *) url:(NSURL *)url withParameters:(NSDictionary *)params {
+ NSURLComponents *parametersUrl = [NSURLComponents componentsWithURL:url resolvingAgainstBaseURL:YES];
+ NSMutableArray *items = [NSMutableArray array];
+ for (NSString * key in params) {
+ NSString *value = [NSString stringWithFormat:@"%@", params[key]];
+ [items addObject:[NSURLQueryItem queryItemWithName:key value:value]];
+ }
+ [parametersUrl setQueryItems:items];
+ return [parametersUrl URL];
+}
+
+-(NSData *) multipartData:(NSDictionary *)params withBoundary:(NSString *)boundary {
+ NSMutableData *body = [NSMutableData data];
+ for (NSString *key in params) {
+ [body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
+ [body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=%@\r\n\r\n", key] dataUsingEncoding:NSUTF8StringEncoding]];
+ [body appendData:[[NSString stringWithFormat:@"%@\r\n", params[key]] dataUsingEncoding:NSUTF8StringEncoding]];
+ }
+ [body appendData:[[NSString stringWithFormat:@"--%@--", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
+ return body;
+}
+
+-(void) get:(NSString *) path params:(NSDictionary *)params callback:(void(^)(NSDictionary *, NSError *))callback {
+ NSURL *url = [NSURL URLWithString:path relativeToURL:self.baseURL];
+ NSURL *requestUrl = params ? [self url:url withParameters:params] : url;
+ [self fetchDataWithURL:requestUrl data:nil boundary:nil authorizationHeader:self.authorizationHeader callback:^(NSData *data, NSError *err) {
+ if (err) {
+ callback(nil, err);
+ } else {
+ NSError *jsonError;
+ NSDictionary *jsonData = [NSJSONSerialization JSONObjectWithData:data options:0 error:&jsonError];
+ if (jsonError) {
+ callback(nil, jsonError);
+ } else {
+ callback(jsonData, nil);
+ }
+ }
+ }];
+}
+
+-(void) post:(NSString *) path params:(NSDictionary *)params callback:(void(^)(NSDictionary *, NSError *))callback {
+ NSURL *url = [NSURL URLWithString:path relativeToURL:self.baseURL];
+ NSString *boundary = [NSString stringWithFormat:@"Boundary-%@", [[NSUUID UUID] UUIDString]];
+ [self fetchDataWithURL:url data:[self multipartData:params withBoundary:boundary] boundary:boundary
+ authorizationHeader:self.authorizationHeader callback:^(NSData *data, NSError *err) {
+ if (!err) {
+ NSError *jsonError;
+ NSDictionary *jsonData = [NSJSONSerialization JSONObjectWithData:data options:0 error:&jsonError];
+ if (jsonError) {
+ callback(nil, jsonError);
+ } else {
+ callback(jsonData, nil);
+ }
+ } else {
+ callback(nil, err);
+ }
+ }];
+}
+
+-(void) fetchImageWithURL:(NSURL *) url callback:(void(^)(NSData *))callback {
+ [self fetchDataWithURL:url data:nil boundary:nil authorizationHeader:self.authorizationHeader callback:^(NSData *data, NSError *err) {
+ if (err) {
+ callback(nil);
+ } else {
+ callback(data);
+ }
+ }];
+}
+
++(NSString *) messagesUrl {
+ return @"messages";
+}
+
++(NSString *) discussionsUrl {
+ return @"messages/discussions";
+}
+
++(NSString *) threadUrl {
+ return @"thread";
+}
+
++(NSString *) feedUrl {
+ return @"home";
+}
+
+@end