Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //
- // LETChatService.m
- // Lets
- //
- // Created by Surik Sarkisyan on 15.06.16.
- // Copyright © 2016 Lets. All rights reserved.
- //
- #import "LETChatService.h"
- #import "LETChatServiceDelegate.h"
- #import "LETPairUser.h"
- #import "LETChatSessionsCollector.h"
- #import "LETMappingServiceProtocol.h"
- #import "LETChatMessagesCollector.h"
- #import "LETChatSession.h"
- #import <XMLDictionary/XMLDictionary.h>
- #import <DateTools/NSDate+DateTools.h>
- typedef NS_ENUM(NSUInteger, LETOperationType)
- {
- LETOperationTypeUnknown = 0,
- LETOperationTypeCreateConnection = 1,
- LETOperationTypeSendMessage = 2,
- LETOperationTypeChatSessions = 3,
- LETOperationTypeChatHistory = 4,
- };
- static NSString *const kLETURLKey = @"url";
- static NSString *const kLETImageURLStringFormat = @"<image>%@</image>";
- static NSString *const kLETXMPPArchiveKey = @"urn:xmpp:archive";
- static NSString *const kLETXMPPListKey = @"list";
- static NSString *const kLETXMPPWithKey = @"with";
- static NSString *const kLETXMPPGetKey = @"get";
- static NSString *const kLETXMPPRSMKey = @"http://jabber.org/protocol/rsm";
- static NSString *const kLETXMPPShowKey = @"show";
- static NSString *const kLETXMPPChatKey = @"chat";
- static NSString *const kLETXMPPAvailableKey = @"Available";
- static NSString *const kLETXMPPStatusKey = @"status";
- static NSString *const kLETXMPPStartKey = @"start";
- static NSString *const kLETXMPPIQKey = @"iq";
- static NSString *const kLETXMPPRetrieveKey = @"retrieve";
- static NSString *const kLETXMPPIDKey = @"id";
- static NSString *const kLETXMPPTypeKey = @"type";
- static NSString *const kLETXMPPSetKey = @"set";
- static NSString *const kLETXMPPMaxKey = @"max";
- static NSString *const kLETXMPPImageKey = @"image";
- static NSString *const kLETImageUploadAPIMethod = @"photo/upload";
- static CGFloat const kLETStreamConnectionTimeOut = 10.;
- @interface LETChatService ()
- @property (nonatomic, strong) NSMutableArray<LETChatMessagesCollector *> *messagesCollectorsArray;
- @property (nonatomic, strong) LETChatSessionsCollector *sessionsCollector;
- @property (nonatomic, assign) NSInteger lastSessionIndex;
- @property (nonatomic, assign) NSInteger loadedMessagesCount;
- @property (nonatomic, copy) NSString *userID;
- @property (nonatomic, copy) NSString *pairUserID;
- @property (nonatomic, copy) NSString *password;
- @property (nonatomic, strong) NSNumber *neededHistoryMessagesCount;
- @property (nonatomic, assign) LETOperationType operationType;
- @end
- @implementation LETChatService
- #pragma mark - LETChatServiceProtocol
- - (void)createConnectionForUserWithID:(NSNumber *)userID password:(NSString *)password
- {
- self.userID = userID.stringValue;
- self.password = password;
- self.stream.myJID = [XMPPJID jidWithUser:self.userID domain:self.stream.hostName resource:nil];
- NSError *error = nil;
- self.operationType = LETOperationTypeCreateConnection;
- [self.reconnect activate:self.stream];
- if ( ![self.stream connectWithTimeout:kLETStreamConnectionTimeOut error:&error] )
- {
- if ( [self.delegate respondsToSelector:@selector(chatService:connectionDidCreatedWithSuccess:)] )
- {
- [self.delegate chatService:self connectionDidCreatedWithSuccess:NO];
- }
- }
- }
- - (void)sendMessage:(NSString *)text toUserWithID:(NSNumber *)userID
- {
- self.pairUserID = userID.stringValue;
- XMPPJID *jid = [XMPPJID jidWithUser:userID.stringValue domain:self.stream.hostName resource:nil];
- XMPPMessage *message = [XMPPMessage messageWithType:kLETXMPPChatKey to:jid];
- [message addBody:[text stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
- self.operationType = LETOperationTypeSendMessage;
- [self.stream sendElement:message];
- }
- - (void)sendImage:(UIImage *)image toUserWithID:(NSNumber *)userID
- {
- if ( !image )
- {
- return;
- }
- self.pairUserID = userID.stringValue;
- LETNetworkServiceSuccessBlock success = ^(NSURLSessionDataTask *task, id responseObject)
- {
- NSString *imageURLString = responseObject[kLETURLKey];
- if ( imageURLString.length )
- {
- XMPPJID *jid = [XMPPJID jidWithUser:userID.stringValue domain:self.stream.hostName resource:nil];
- XMPPMessage *message = [XMPPMessage messageWithType:kLETXMPPChatKey to:jid];
- [message addBody:[NSString stringWithFormat:kLETImageURLStringFormat, imageURLString]];
- self.operationType = LETOperationTypeSendMessage;
- [self.stream sendElement:message];
- }
- };
- LETNetworkServiceFailureBlock failure = ^(NSURLSessionDataTask *task, NSError *error)
- {
- NSLog(@"Handle error here");
- };
- [self.networkService POST:kLETImageUploadAPIMethod
- parameters:image
- success:success
- failure:failure];
- }
- #pragma mark - Helpers
- - (void)goOnline
- {
- XMPPPresence *presence = [XMPPPresence presence];
- NSXMLElement *show = [NSXMLElement elementWithName:kLETXMPPShowKey];
- NSXMLElement *status = [NSXMLElement elementWithName:kLETXMPPStatusKey];
- [show setStringValue:kLETXMPPChatKey];
- [status setStringValue:kLETXMPPAvailableKey];
- [presence addChild:show];
- [presence addChild:status];
- [self.stream sendElement:presence];
- }
- - (void)loadChatHistoryForUserWithID:(NSNumber *)userID messagesCount:(NSNumber *)messagesCount
- {
- if ( !!self.messagesCollectorsArray.count )
- {
- return;
- }
- self.neededHistoryMessagesCount = messagesCount;
- self.pairUserID = userID.stringValue;
- self.operationType = LETOperationTypeChatSessions;
- XMPPJID *withJID = [XMPPJID jidWithUser:userID.stringValue domain:self.stream.hostName resource:nil];
- DDXMLElement *query = [DDXMLElement elementWithName:kLETXMPPListKey xmlns:kLETXMPPArchiveKey];
- [query addAttributeWithName:kLETXMPPWithKey stringValue:[withJID full]];
- XMPPIQ *iQ = [XMPPIQ iqWithType:kLETXMPPGetKey];
- [iQ addAttributeWithName:kLETXMPPIDKey stringValue:self.userID];
- [iQ addChild:query];
- [self.stream sendElement:iQ];
- }
- - (void)loadEarlierMessagesWithUser:(NSNumber *)userID messagesCount:(NSNumber *)messagesCount
- {
- if ( !self.sessionsCollector || self.lastSessionIndex < 0 )
- {
- if ( [self.delegate respondsToSelector:@selector(noEarlierMessagesFromChatService:)] )
- {
- [self.delegate noEarlierMessagesFromChatService:self];
- }
- }
- else
- {
- LETChatSession *session = self.sessionsCollector.sesionsArray[self.lastSessionIndex];
- [self loadMessagesWithSessionStartTime:session.startDateString];
- }
- }
- - (void)loadMessagesWithSessionStartTime:(NSString *)start
- {
- self.operationType = LETOperationTypeChatHistory;
- XMPPJID *withJID = [XMPPJID jidWithUser:self.pairUserID domain:self.stream.hostName resource:nil];
- NSXMLElement *iq = [NSXMLElement elementWithName:kLETXMPPIQKey];
- [iq addAttributeWithName:kLETXMPPTypeKey stringValue:kLETXMPPGetKey];
- [iq addAttributeWithName:kLETXMPPIDKey stringValue:self.userID];
- NSXMLElement *retrieve = [NSXMLElement elementWithName:kLETXMPPRetrieveKey xmlns:kLETXMPPArchiveKey];
- [retrieve addAttributeWithName:kLETXMPPWithKey stringValue:[withJID full]];
- [retrieve addAttributeWithName:kLETXMPPStartKey stringValue:start];
- NSXMLElement *set = [NSXMLElement elementWithName:kLETXMPPSetKey xmlns:kLETXMPPRSMKey];
- [retrieve addChild:set];
- [iq addChild:retrieve];
- [self.stream sendElement:iq];
- }
- #pragma mark - XMPPStreamDelegate
- - (void)xmppStreamDidConnect:(XMPPStream *)sender
- {
- NSError *error = nil;
- if ( ![self.stream authenticateWithPassword:self.password error:&error] )
- {
- if ( [self.delegate respondsToSelector:@selector(chatService:connectionDidCreatedWithSuccess:)] )
- {
- [self.delegate chatService:self connectionDidCreatedWithSuccess:NO];
- }
- }
- }
- - (void)xmppStreamConnectDidTimeout:(XMPPStream *)sender
- {
- NSLog(@"Handle error here");
- }
- - (void)xmppStreamDidDisconnect:(XMPPStream *)sender withError:(NSError *)error
- {
- NSLog(@"Handle error here");
- }
- - (void)xmppStreamDidAuthenticate:(XMPPStream *)sender
- {
- [self goOnline];
- if ( [self.delegate respondsToSelector:@selector(chatService:connectionDidCreatedWithSuccess:)] )
- {
- [self.delegate chatService:self connectionDidCreatedWithSuccess:YES];
- }
- }
- - (void)xmppStream:(XMPPStream *)sender didNotAuthenticate:(DDXMLElement *)error
- {
- if ( [self.delegate respondsToSelector:@selector(chatService:connectionDidCreatedWithSuccess:)] )
- {
- [self.delegate chatService:self connectionDidCreatedWithSuccess:NO];
- }
- }
- - (void)xmppStream:(XMPPStream *)sender didReceiveMessage:(XMPPMessage *)message
- {
- NSString *text = [message body];
- if ( !text || [message isErrorMessage])
- {
- return;
- }
- if ( [self.delegate respondsToSelector:@selector(chatService:didReceiveMessage:)] )
- {
- text = [text stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
- [self.delegate chatService:self didReceiveMessage:text];
- }
- }
- - (void)xmppStream:(XMPPStream *)sender didSendMessage:(XMPPMessage *)message
- {
- if ( [self.delegate respondsToSelector:@selector(chatService:messageDidSendedWithSuccess:)] )
- {
- [self.delegate chatService:self messageDidSendedWithSuccess:YES];
- }
- }
- - (void)xmppStream:(XMPPStream *)sender didFailToSendMessage:(XMPPMessage *)message error:(NSError *)error
- {
- if ( [self.delegate respondsToSelector:@selector(chatService:messageDidSendedWithSuccess:)] )
- {
- [self.delegate chatService:self messageDidSendedWithSuccess:NO];
- }
- }
- - (void)xmppStream:(XMPPStream *)sender didReceiveError:(NSXMLElement *)error
- {
- if ( [self.delegate respondsToSelector:@selector(chatService:didReceiveError:)] )
- {
- [self.delegate chatService:self didReceiveError:nil];
- }
- }
- - (BOOL)xmppStream:(XMPPStream *)sender didReceiveIQ:(XMPPIQ *)iq
- {
- if ( self.operationType == LETOperationTypeChatSessions )
- {
- NSDictionary *iqDict = [NSDictionary dictionaryWithXMLString:[iq description]];
- self.sessionsCollector = [self.mappingService convertJSONDictionary:iqDict
- toObjectWithClass:[LETChatSessionsCollector class]
- objectMapping:[LETChatSessionsCollector chatSessionsCollectorJSONToObjectMapping]
- error:nil];
- if ( self.sessionsCollector.sesionsArray.count )
- {
- self.lastSessionIndex = self.sessionsCollector.sesionsArray.count - 1;
- LETChatSession *session = self.sessionsCollector.sesionsArray[self.lastSessionIndex];
- [self loadMessagesWithSessionStartTime:session.startDateString];
- }
- else if ( [self.delegate respondsToSelector:@selector(chatService:messagesDidLoad:forSessionIndex:)] )
- {
- [self.delegate chatService:self messagesDidLoad:nil forSessionIndex:self.lastSessionIndex];
- }
- }
- else if ( self.operationType == LETOperationTypeChatHistory )
- {
- self.lastSessionIndex--;
- NSDictionary *iqDict = [NSDictionary dictionaryWithXMLString:[iq description]];
- LETChatMessagesCollector *messagesCollector = [self.mappingService convertJSONDictionary:iqDict
- toObjectWithClass:[LETChatMessagesCollector class]
- objectMapping:[LETChatMessagesCollector chatMessagesCollectorJSONToObjectMapping]
- error:nil];
- [self.messagesCollectorsArray addObject:messagesCollector];
- self.loadedMessagesCount += messagesCollector.messagesCount;
- BOOL isMessagesNotEnough = self.loadedMessagesCount < self.neededHistoryMessagesCount.integerValue;
- BOOL isNotLastSessionIndex = self.lastSessionIndex >= 0;
- if ( isMessagesNotEnough && isNotLastSessionIndex )
- {
- LETChatSession *session = self.sessionsCollector.sesionsArray[self.lastSessionIndex];
- [self loadMessagesWithSessionStartTime:session.startDateString];
- }
- else if ( [self.delegate respondsToSelector:@selector(chatService:messagesDidLoad:forSessionIndex:)] )
- {
- self.loadedMessagesCount = 0;
- [self.delegate chatService:self messagesDidLoad:self.messagesCollectorsArray forSessionIndex:self.lastSessionIndex];
- }
- }
- return YES;
- }
- #pragma mark - Lazy Init
- - (NSMutableArray<LETChatMessagesCollector *> *)messagesCollectorsArray
- {
- if ( !_messagesCollectorsArray )
- {
- _messagesCollectorsArray = [NSMutableArray new];
- }
- return _messagesCollectorsArray;
- }
- @end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement