{"action":"created","comment":{"url":"https://api.github.com/repos/easemob/easeui_ios/pulls/comments/53894537","id":53894537,"diff_hunk":"@@ -0,0 +1,585 @@\n+//\n+//  EaseMessageAppreciationHelper.m\n+//  EaseUI\n+//\n+//  Created by dujiepeng on 16/1/25.\n+//  Copyright © 2016年 easemob. All rights reserved.\n+//\n+\n+#import \"EaseMessageAppreciationHelper.h\"\n+\n+/** @brief 消息回撤处理完成的通知 */\n+#define KEM_REVOKERELOAD_NOTIFICATION      @\"em_revokeReload_notification\"\n+/** @brief 待发送消息撤销的CMD消息action */\n+#define KEMMESSAGE_REVOKE                  @\"em_revoke\"\n+/** @brief 消息回撤cmd扩展字段,对应的value值为待撤销消息id */\n+#define KEMMESSAGE_REVOKE_MESSAGEID        @\"em_revoke_messageId\"\n+/** @brief 撤销消息时间间隔，单位:ms */\n+#define REVOKE_TIMEINTERVAL      60 * 2 * 1000\n+\n+\n+/** @brief 阅后即焚消息处理完成的通知 */\n+#define KEM_AFTERREADRELOAD_NOTIFICATION   @\"em_afterReadReload_notification\"\n+/** @brief 阅后即焚消息扩展字段 */\n+#define KEMMESSAGE_READFIRE                @\"em_readFire\"\n+/** @brief 已读阅后即焚消息在NSUserDefaults保存的key前缀 */\n+#define KEM_READFIRE_PREFIX                @\"readFirePrefix\"\n+/** @brief NSUserDefaults中保存当前已阅读但未发送ack回执的阅后即焚消息信息 */\n+#define NEED_REMOVE_MESSAGE_DIC            @\"em_needRemoveMessages\"\n+/** @brief NSUserDefaults中保存当前阅读的阅后即焚消息信息 */\n+#define NEED_REMOVE_CURRENT_MESSAGE        @\"em_needRemoveCurrnetMessage\"\n+//需要发送ack的阅后即焚消息信息在NSUserDefaults中的存放key\n+#define UserDefaultKey(username) [[KEM_READFIRE_PREFIX stringByAppendingString:@\"_\"] stringByAppendingString:username]\n+\n+\n+@interface MessageRevokeManager()<IChatManagerDelegate>\n+\n+@property (nonatomic, assign) id<IChatManager> chatManager;\n+\n+@end\n+\n+@implementation MessageRevokeManager\n+{\n+    dispatch_queue_t _queue;\n+}\n+\n++ (MessageRevokeManager *)sharedInstance{\n+    static MessageRevokeManager *manager = nil;\n+    static dispatch_once_t onceToken;\n+    dispatch_once(&onceToken, ^{\n+        manager = [[MessageRevokeManager alloc] init];\n+    });\n+    \n+    return manager;\n+}\n+\n+- (instancetype)init\n+{\n+    self = [super init];\n+    if (self)\n+    {\n+        _queue = dispatch_queue_create(\"com.revokeMessage\", DISPATCH_QUEUE_SERIAL);\n+        [self.chatManager addDelegate:self delegateQueue:nil];\n+    }\n+    return self;\n+}\n+\n+#pragma mark - IChatManagerDelegate\n+\n+- (void)didReceiveCmdMessage:(EMMessage *)cmdMessage\n+{\n+    NSArray *removeMessages = [[self revokeMessages:@[cmdMessage]] mutableCopy];\n+    [[NSNotificationCenter defaultCenter] postNotificationName:KEM_REVOKERELOAD_NOTIFICATION object:removeMessages];\n+}\n+\n+- (void)didReceiveOfflineCmdMessages:(NSArray *)offlineCmdMessages\n+{\n+    NSArray *removeMessages = [[self revokeMessages:offlineCmdMessages] mutableCopy];\n+    [[NSNotificationCenter defaultCenter] postNotificationName:KEM_REVOKERELOAD_NOTIFICATION object:removeMessages];\n+}\n+\n+#pragma mark - public\n+\n+/**\n+ * 注册消息回撤完成后UI更新通知\n+ *\n+ */\n+- (void)registerNotification:(id)observer selector:(SEL)action\n+{\n+    [[NSNotificationCenter defaultCenter] addObserver:observer\n+                                             selector:action\n+                                                 name:KEM_REVOKERELOAD_NOTIFICATION object:nil];\n+}\n+\n+/**\n+ * 释放消息回撤完成后UI更新通知\n+ *\n+ */\n+- (void)removeNotification:(id)observer\n+{\n+    [[NSNotificationCenter defaultCenter] removeObserver:observer\n+                                                    name:KEM_REVOKERELOAD_NOTIFICATION object:nil];\n+}\n+\n+/**\n+ * 发送回撤cmd消息\n+ *\n+ * @param aChatter 对应会话的chatter\n+ * @param aMessageId 待撤销消息的id\n+ */\n++ (void)sendRevokeMessageToChatter:(NSString *)aChatter\n+                         messageId:(NSString *)aMessageId\n+                  conversationType:(EMConversationType)conversationType\n+{\n+    EMChatCommand *command = [[EMChatCommand alloc] init];\n+    command.cmd = KEMMESSAGE_REVOKE;\n+    EMCommandMessageBody *body = [[EMCommandMessageBody alloc] initWithChatObject:command];\n+    EMMessage *msg = [[EMMessage alloc] initWithReceiver:aChatter\n+                                                  bodies:@[body]];\n+    msg.messageType = [MessageRevokeManager messageType:conversationType];\n+    msg.ext = @{KEMMESSAGE_REVOKE_MESSAGEID:aMessageId};\n+    [[EaseMob sharedInstance].chatManager asyncSendMessage:msg\n+                                                  progress:nil];\n+}\n+\n+/**\n+ * 判断消息是否是消息回撤cmd消息\n+ *\n+ * @param message 待验证消息对象\n+ * @return 返回验证结果，YES代表此消息为消息撤销的cmd消息\n+ */\n++ (BOOL)isRevokeCMDMessage:(EMMessage *)aMessage\n+{\n+    EMCommandMessageBody *body = (EMCommandMessageBody *)[aMessage.messageBodies firstObject];\n+    if (!body)\n+    {\n+        return NO;\n+    }\n+    return [body.action isEqualToString:KEMMESSAGE_REVOKE];\n+}\n+\n+// 得到要回撤的消息id\n++ (NSString *)needRevokeMessageId:(EMMessage *)aMessage\n+{\n+    NSString *messageId = aMessage.ext[KEMMESSAGE_REVOKE_MESSAGEID];\n+    return messageId;\n+}\n+\n+/**\n+ * 验证消息是否符合撤销原则(如2分钟内发送)\n+ *\n+ * @param model 待验证消息\n+ * @return 判断结果, YES代表可以撤销\n+ */\n++ (BOOL)canRevokeMessage:(EMMessage *)message\n+{\n+    //接收者不执行撤销\n+    if ([message.to isEqualToString:[MessageRevokeManager sharedInstance].account]) {\n+        return NO;\n+    }\n+    //长连接断开\n+    if (![[MessageRevokeManager sharedInstance].chatManager isConnected])\n+    {\n+        return NO;\n+    }\n+    BOOL isCanrevoke = NO;\n+    //检验是否可以撤销\n+    long long timestamp = message.timestamp;\n+    long long nowtimestamp = (long long)[[NSDate date] timeIntervalSince1970] * 1000;\n+    isCanrevoke = (nowtimestamp - timestamp) <= REVOKE_TIMEINTERVAL;\n+    return isCanrevoke;\n+}\n+\n+#pragma mark - private\n+\n+/**\n+ * 获取消息类型\n+ *\n+ * @param conversationType 会话类型\n+ * @return 对应消息类型\n+ */\n++ (EMMessageType)messageType:(EMConversationType)conversationType\n+{\n+    EMMessageType type = eMessageTypeChat;\n+    switch (conversationType)\n+    {\n+        case eConversationTypeChat:\n+            type = eMessageTypeChat;\n+            break;\n+        case eConversationTypeGroupChat:\n+            type = eMessageTypeGroupChat;\n+            break;\n+        case eConversationTypeChatRoom:\n+            type = eMessageTypeChatRoom;\n+            break;\n+        default:\n+            break;\n+    }\n+    return type;\n+}\n+\n+/**\n+ * 获取cmd消息，处理消息撤销\n+ *\n+ * @param cmdMessages 接收的cmd消息\n+ * @return 返回被删除的消息\n+ */\n+- (NSArray *)revokeMessages:(NSArray *)cmdMessages\n+{\n+    NSMutableArray *removeMessages = [NSMutableArray array];//被删除的消息，通知返回页面，前台决定是否添加提示语\n+    for (EMMessage *cmdMessage in cmdMessages)\n+    {\n+        if (![MessageRevokeManager isRevokeCMDMessage:cmdMessage])\n+        {\n+            //不是撤销cmd\n+            continue;\n+        }\n+        EMConversation *conversation = [[EaseMob sharedInstance].chatManager conversationForChatter:cmdMessage.conversationChatter conversationType:(EMConversationType)cmdMessage.messageType];\n+        \n+        EMMessage *message = [conversation loadMessageWithId:[MessageRevokeManager needRevokeMessageId:cmdMessage]];\n+        if (!message)\n+        {\n+            continue;\n+        }\n+        if ([conversation removeMessageWithId:message.messageId])\n+        {\n+            [removeMessages addObject:message];\n+        }\n+        if (!conversation.latestMessage)\n+        {\n+            [self.chatManager removeConversationByChatter:conversation.chatter\n+                                           deleteMessages:NO\n+                                              append2Chat:YES];\n+        }\n+    }\n+    return removeMessages;\n+}\n+\n+#pragma mark - getter\n+\n+- (NSString *)account\n+{\n+    return [[[EaseMob sharedInstance].chatManager loginInfo] objectForKey:kSDKUsername];\n+}\n+\n+- (id<IChatManager>)chatManager\n+{\n+    return [EaseMob sharedInstance].chatManager;\n+}\n+\n+@end\n+\n+@interface RemoveAfterReadManager () <IChatManagerDelegate>{\n+    dispatch_queue_t _queue;\n+}\n+@property (nonatomic, assign) id<IChatManager> chatManager;\n+@property (nonatomic, strong) NSDictionary *infoDic;\n+@property (nonatomic, strong) NSString *account;\n+@end\n+\n+@implementation RemoveAfterReadManager\n+\n++ (RemoveAfterReadManager *)sharedInstance{\n+    static RemoveAfterReadManager *manager = nil;\n+    static dispatch_once_t onceToken;\n+    dispatch_once(&onceToken, ^{\n+        manager = [[RemoveAfterReadManager alloc] init];\n+    });\n+    \n+    return manager;\n+}\n+\n+- (instancetype)init{\n+    if (self = [super init]) {\n+        _queue = dispatch_queue_create(\"com.removeafterread\", DISPATCH_QUEUE_SERIAL);\n+        [self.chatManager addDelegate:self delegateQueue:nil];\n+        [self addMessageToNeedRemoveDic:[self currentMsg]];\n+        [self sendAllNeedRemoveMessage];\n+    }\n+    \n+    return self;\n+}\n+\n+#pragma mark - IChatManagerDelegate\n+\n+- (void)didAutoReconnectFinishedWithError:(NSError *)error{\n+    if (!error) {\n+        [self sendAllNeedRemoveMessage];\n+    }\n+}\n+\n+- (void)didAutoLoginWithInfo:(NSDictionary *)loginInfo\n+                       error:(EMError *)error{\n+    if (!error) {\n+        [self sendAllNeedRemoveMessage];\n+    }\n+}\n+\n+-(void)didLogoffWithError:(EMError *)error{\n+    if (!error) {\n+        self.infoDic = nil;\n+        self.account = nil;\n+    }\n+}\n+\n+- (void)didReceiveHasReadResponse:(EMReceipt *)resp\n+{\n+    [self fireMessagesFromData:resp];\n+}\n+\n+#pragma mark - private\n+\n+/**\n+ * 为指定消息发送已读回执，并把此消息在NSUserDefaults记录\n+ *\n+ * @param aMessage 已读的阅后即焚消息\n+ *\n+ */\n+- (void)sendRemoveMessageAction:(EMMessage *)aMessage{\n+    dispatch_sync(_queue, ^{\n+        if ([self isConnected]) {\n+            [self.chatManager sendReadAckForMessage:aMessage];\n+            NSUserDefaults *userDefault = [NSUserDefaults standardUserDefaults];\n+            NSMutableDictionary *dic = [[userDefault objectForKey:UserDefaultKey(self.account)] mutableCopy];\n+            if (!dic) {\n+                dic = [[NSMutableDictionary alloc] init];\n+            }\n+            [dic removeObjectForKey:NEED_REMOVE_CURRENT_MESSAGE];\n+            [userDefault setObject:dic forKey:UserDefaultKey(self.account)];\n+            [self clearCurrentMsg];\n+        }else {\n+            [self addMessageToNeedRemoveDic:@[aMessage.conversationChatter,aMessage.messageId]];\n+        }\n+    });\n+}\n+\n+/**\n+ * 为NSUserDefaults记录的已读阅后即焚消息发送ack回执，并删除该消息\n+ *\n+ */\n+- (void)sendAllNeedRemoveMessage{\n+    dispatch_sync(_queue, ^{\n+        if ([self isConnected]) {\n+            for (NSString *chatter in [self.needRemoveDic allKeys]) {\n+                EMConversation *conversation = [self.chatManager\n+                                                conversationForChatter:chatter\n+                                                conversationType:eConversationTypeChat];\n+                \n+                NSArray *msgs = [conversation loadMessagesWithIds:self.needRemoveDic[chatter]];\n+                for (EMMessage *msg in msgs) {\n+                    [self.chatManager sendReadAckForMessage:msg];\n+                    [conversation removeMessage:msg];\n+                }\n+                if (!conversation.latestMessage)\n+                {\n+                    [self.chatManager removeConversationByChatter:conversation.chatter\n+                                                   deleteMessages:NO\n+                                                      append2Chat:YES];\n+                }\n+            }\n+            [self clearNeedRemoveDic];\n+        }\n+    });\n+}\n+\n+/**\n+ * 将指定消息信息加入到待发送ack阅后即焚消息字典中\n+ *\n+ * @param msg 指定的消息信息，数组长度为2，第一个元素为消息所在会话的chatter，第二个元素为消息id\n+ *\n+ */\n+- (void)addMessageToNeedRemoveDic:(NSArray *)msg","path":"EaseUI/EaseUI/EMUIKit/Helper/EaseMessageAppreciationHelper.m","position":371,"original_position":371,"commit_id":"b0a3c7e002791bf365898513843c0a512710750d","original_commit_id":"b0a3c7e002791bf365898513843c0a512710750d","user":{"login":"Neil-Cao","id":9793953,"avatar_url":"https://avatars.githubusercontent.com/u/9793953?v=3","gravatar_id":"","url":"https://api.github.com/users/Neil-Cao","html_url":"https://github.com/Neil-Cao","followers_url":"https://api.github.com/users/Neil-Cao/followers","following_url":"https://api.github.com/users/Neil-Cao/following{/other_user}","gists_url":"https://api.github.com/users/Neil-Cao/gists{/gist_id}","starred_url":"https://api.github.com/users/Neil-Cao/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Neil-Cao/subscriptions","organizations_url":"https://api.github.com/users/Neil-Cao/orgs","repos_url":"https://api.github.com/users/Neil-Cao/repos","events_url":"https://api.github.com/users/Neil-Cao/events{/privacy}","received_events_url":"https://api.github.com/users/Neil-Cao/received_events","type":"User","site_admin":false},"body":"参数数组msg里到底存的是什么？调用时[self addMessageToNeedRemoveDic:@[message.conversationChatter,message.messageId]]","created_at":"2016-02-24T05:02:09Z","updated_at":"2016-02-24T05:02:09Z","html_url":"https://github.com/easemob/easeui_ios/pull/12#discussion_r53894537","pull_request_url":"https://api.github.com/repos/easemob/easeui_ios/pulls/12","_links":{"self":{"href":"https://api.github.com/repos/easemob/easeui_ios/pulls/comments/53894537"},"html":{"href":"https://github.com/easemob/easeui_ios/pull/12#discussion_r53894537"},"pull_request":{"href":"https://api.github.com/repos/easemob/easeui_ios/pulls/12"}}},"pull_request":{"url":"https://api.github.com/repos/easemob/easeui_ios/pulls/12","id":59331734,"html_url":"https://github.com/easemob/easeui_ios/pull/12","diff_url":"https://github.com/easemob/easeui_ios/pull/12.diff","patch_url":"https://github.com/easemob/easeui_ios/pull/12.patch","issue_url":"https://api.github.com/repos/easemob/easeui_ios/issues/12","number":12,"state":"open","locked":false,"title":"easeUI 消息回撤、阅后即焚commit","user":{"login":"wyuzhang","id":16917238,"avatar_url":"https://avatars.githubusercontent.com/u/16917238?v=3","gravatar_id":"","url":"https://api.github.com/users/wyuzhang","html_url":"https://github.com/wyuzhang","followers_url":"https://api.github.com/users/wyuzhang/followers","following_url":"https://api.github.com/users/wyuzhang/following{/other_user}","gists_url":"https://api.github.com/users/wyuzhang/gists{/gist_id}","starred_url":"https://api.github.com/users/wyuzhang/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/wyuzhang/subscriptions","organizations_url":"https://api.github.com/users/wyuzhang/orgs","repos_url":"https://api.github.com/users/wyuzhang/repos","events_url":"https://api.github.com/users/wyuzhang/events{/privacy}","received_events_url":"https://api.github.com/users/wyuzhang/received_events","type":"User","site_admin":false},"body":"easeUI 消息回撤、阅后即焚commit","created_at":"2016-02-15T08:12:54Z","updated_at":"2016-02-24T05:02:09Z","closed_at":null,"merged_at":null,"merge_commit_sha":"3add3b7f78bb483ab9a3205da41ef8831eb66917","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/easemob/easeui_ios/pulls/12/commits","review_comments_url":"https://api.github.com/repos/easemob/easeui_ios/pulls/12/comments","review_comment_url":"https://api.github.com/repos/easemob/easeui_ios/pulls/comments{/number}","comments_url":"https://api.github.com/repos/easemob/easeui_ios/issues/12/comments","statuses_url":"https://api.github.com/repos/easemob/easeui_ios/statuses/b0a3c7e002791bf365898513843c0a512710750d","head":{"label":"wyuzhang:dev","ref":"dev","sha":"b0a3c7e002791bf365898513843c0a512710750d","user":{"login":"wyuzhang","id":16917238,"avatar_url":"https://avatars.githubusercontent.com/u/16917238?v=3","gravatar_id":"","url":"https://api.github.com/users/wyuzhang","html_url":"https://github.com/wyuzhang","followers_url":"https://api.github.com/users/wyuzhang/followers","following_url":"https://api.github.com/users/wyuzhang/following{/other_user}","gists_url":"https://api.github.com/users/wyuzhang/gists{/gist_id}","starred_url":"https://api.github.com/users/wyuzhang/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/wyuzhang/subscriptions","organizations_url":"https://api.github.com/users/wyuzhang/orgs","repos_url":"https://api.github.com/users/wyuzhang/repos","events_url":"https://api.github.com/users/wyuzhang/events{/privacy}","received_events_url":"https://api.github.com/users/wyuzhang/received_events","type":"User","site_admin":false},"repo":{"id":51728024,"name":"easeui_ios","full_name":"wyuzhang/easeui_ios","owner":{"login":"wyuzhang","id":16917238,"avatar_url":"https://avatars.githubusercontent.com/u/16917238?v=3","gravatar_id":"","url":"https://api.github.com/users/wyuzhang","html_url":"https://github.com/wyuzhang","followers_url":"https://api.github.com/users/wyuzhang/followers","following_url":"https://api.github.com/users/wyuzhang/following{/other_user}","gists_url":"https://api.github.com/users/wyuzhang/gists{/gist_id}","starred_url":"https://api.github.com/users/wyuzhang/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/wyuzhang/subscriptions","organizations_url":"https://api.github.com/users/wyuzhang/orgs","repos_url":"https://api.github.com/users/wyuzhang/repos","events_url":"https://api.github.com/users/wyuzhang/events{/privacy}","received_events_url":"https://api.github.com/users/wyuzhang/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/wyuzhang/easeui_ios","description":"","fork":true,"url":"https://api.github.com/repos/wyuzhang/easeui_ios","forks_url":"https://api.github.com/repos/wyuzhang/easeui_ios/forks","keys_url":"https://api.github.com/repos/wyuzhang/easeui_ios/keys{/key_id}","collaborators_url":"https://api.github.com/repos/wyuzhang/easeui_ios/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/wyuzhang/easeui_ios/teams","hooks_url":"https://api.github.com/repos/wyuzhang/easeui_ios/hooks","issue_events_url":"https://api.github.com/repos/wyuzhang/easeui_ios/issues/events{/number}","events_url":"https://api.github.com/repos/wyuzhang/easeui_ios/events","assignees_url":"https://api.github.com/repos/wyuzhang/easeui_ios/assignees{/user}","branches_url":"https://api.github.com/repos/wyuzhang/easeui_ios/branches{/branch}","tags_url":"https://api.github.com/repos/wyuzhang/easeui_ios/tags","blobs_url":"https://api.github.com/repos/wyuzhang/easeui_ios/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/wyuzhang/easeui_ios/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/wyuzhang/easeui_ios/git/refs{/sha}","trees_url":"https://api.github.com/repos/wyuzhang/easeui_ios/git/trees{/sha}","statuses_url":"https://api.github.com/repos/wyuzhang/easeui_ios/statuses/{sha}","languages_url":"https://api.github.com/repos/wyuzhang/easeui_ios/languages","stargazers_url":"https://api.github.com/repos/wyuzhang/easeui_ios/stargazers","contributors_url":"https://api.github.com/repos/wyuzhang/easeui_ios/contributors","subscribers_url":"https://api.github.com/repos/wyuzhang/easeui_ios/subscribers","subscription_url":"https://api.github.com/repos/wyuzhang/easeui_ios/subscription","commits_url":"https://api.github.com/repos/wyuzhang/easeui_ios/commits{/sha}","git_commits_url":"https://api.github.com/repos/wyuzhang/easeui_ios/git/commits{/sha}","comments_url":"https://api.github.com/repos/wyuzhang/easeui_ios/comments{/number}","issue_comment_url":"https://api.github.com/repos/wyuzhang/easeui_ios/issues/comments{/number}","contents_url":"https://api.github.com/repos/wyuzhang/easeui_ios/contents/{+path}","compare_url":"https://api.github.com/repos/wyuzhang/easeui_ios/compare/{base}...{head}","merges_url":"https://api.github.com/repos/wyuzhang/easeui_ios/merges","archive_url":"https://api.github.com/repos/wyuzhang/easeui_ios/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/wyuzhang/easeui_ios/downloads","issues_url":"https://api.github.com/repos/wyuzhang/easeui_ios/issues{/number}","pulls_url":"https://api.github.com/repos/wyuzhang/easeui_ios/pulls{/number}","milestones_url":"https://api.github.com/repos/wyuzhang/easeui_ios/milestones{/number}","notifications_url":"https://api.github.com/repos/wyuzhang/easeui_ios/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/wyuzhang/easeui_ios/labels{/name}","releases_url":"https://api.github.com/repos/wyuzhang/easeui_ios/releases{/id}","deployments_url":"https://api.github.com/repos/wyuzhang/easeui_ios/deployments","created_at":"2016-02-15T03:21:03Z","updated_at":"2016-02-15T03:21:04Z","pushed_at":"2016-02-15T07:40:53Z","git_url":"git://github.com/wyuzhang/easeui_ios.git","ssh_url":"git@github.com:wyuzhang/easeui_ios.git","clone_url":"https://github.com/wyuzhang/easeui_ios.git","svn_url":"https://github.com/wyuzhang/easeui_ios","homepage":null,"size":3577,"stargazers_count":0,"watchers_count":0,"language":"Objective-C","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"easemob:dev","ref":"dev","sha":"853516532bee4f2b0fc9ea3735e7505872318b9c","user":{"login":"easemob","id":2704962,"avatar_url":"https://avatars.githubusercontent.com/u/2704962?v=3","gravatar_id":"","url":"https://api.github.com/users/easemob","html_url":"https://github.com/easemob","followers_url":"https://api.github.com/users/easemob/followers","following_url":"https://api.github.com/users/easemob/following{/other_user}","gists_url":"https://api.github.com/users/easemob/gists{/gist_id}","starred_url":"https://api.github.com/users/easemob/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/easemob/subscriptions","organizations_url":"https://api.github.com/users/easemob/orgs","repos_url":"https://api.github.com/users/easemob/repos","events_url":"https://api.github.com/users/easemob/events{/privacy}","received_events_url":"https://api.github.com/users/easemob/received_events","type":"Organization","site_admin":false},"repo":{"id":42239230,"name":"easeui_ios","full_name":"easemob/easeui_ios","owner":{"login":"easemob","id":2704962,"avatar_url":"https://avatars.githubusercontent.com/u/2704962?v=3","gravatar_id":"","url":"https://api.github.com/users/easemob","html_url":"https://github.com/easemob","followers_url":"https://api.github.com/users/easemob/followers","following_url":"https://api.github.com/users/easemob/following{/other_user}","gists_url":"https://api.github.com/users/easemob/gists{/gist_id}","starred_url":"https://api.github.com/users/easemob/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/easemob/subscriptions","organizations_url":"https://api.github.com/users/easemob/orgs","repos_url":"https://api.github.com/users/easemob/repos","events_url":"https://api.github.com/users/easemob/events{/privacy}","received_events_url":"https://api.github.com/users/easemob/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/easemob/easeui_ios","description":"","fork":false,"url":"https://api.github.com/repos/easemob/easeui_ios","forks_url":"https://api.github.com/repos/easemob/easeui_ios/forks","keys_url":"https://api.github.com/repos/easemob/easeui_ios/keys{/key_id}","collaborators_url":"https://api.github.com/repos/easemob/easeui_ios/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/easemob/easeui_ios/teams","hooks_url":"https://api.github.com/repos/easemob/easeui_ios/hooks","issue_events_url":"https://api.github.com/repos/easemob/easeui_ios/issues/events{/number}","events_url":"https://api.github.com/repos/easemob/easeui_ios/events","assignees_url":"https://api.github.com/repos/easemob/easeui_ios/assignees{/user}","branches_url":"https://api.github.com/repos/easemob/easeui_ios/branches{/branch}","tags_url":"https://api.github.com/repos/easemob/easeui_ios/tags","blobs_url":"https://api.github.com/repos/easemob/easeui_ios/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/easemob/easeui_ios/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/easemob/easeui_ios/git/refs{/sha}","trees_url":"https://api.github.com/repos/easemob/easeui_ios/git/trees{/sha}","statuses_url":"https://api.github.com/repos/easemob/easeui_ios/statuses/{sha}","languages_url":"https://api.github.com/repos/easemob/easeui_ios/languages","stargazers_url":"https://api.github.com/repos/easemob/easeui_ios/stargazers","contributors_url":"https://api.github.com/repos/easemob/easeui_ios/contributors","subscribers_url":"https://api.github.com/repos/easemob/easeui_ios/subscribers","subscription_url":"https://api.github.com/repos/easemob/easeui_ios/subscription","commits_url":"https://api.github.com/repos/easemob/easeui_ios/commits{/sha}","git_commits_url":"https://api.github.com/repos/easemob/easeui_ios/git/commits{/sha}","comments_url":"https://api.github.com/repos/easemob/easeui_ios/comments{/number}","issue_comment_url":"https://api.github.com/repos/easemob/easeui_ios/issues/comments{/number}","contents_url":"https://api.github.com/repos/easemob/easeui_ios/contents/{+path}","compare_url":"https://api.github.com/repos/easemob/easeui_ios/compare/{base}...{head}","merges_url":"https://api.github.com/repos/easemob/easeui_ios/merges","archive_url":"https://api.github.com/repos/easemob/easeui_ios/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/easemob/easeui_ios/downloads","issues_url":"https://api.github.com/repos/easemob/easeui_ios/issues{/number}","pulls_url":"https://api.github.com/repos/easemob/easeui_ios/pulls{/number}","milestones_url":"https://api.github.com/repos/easemob/easeui_ios/milestones{/number}","notifications_url":"https://api.github.com/repos/easemob/easeui_ios/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/easemob/easeui_ios/labels{/name}","releases_url":"https://api.github.com/repos/easemob/easeui_ios/releases{/id}","deployments_url":"https://api.github.com/repos/easemob/easeui_ios/deployments","created_at":"2015-09-10T10:58:13Z","updated_at":"2016-02-22T03:38:01Z","pushed_at":"2016-02-22T03:48:40Z","git_url":"git://github.com/easemob/easeui_ios.git","ssh_url":"git@github.com:easemob/easeui_ios.git","clone_url":"https://github.com/easemob/easeui_ios.git","svn_url":"https://github.com/easemob/easeui_ios","homepage":null,"size":7195,"stargazers_count":11,"watchers_count":11,"language":"Objective-C","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":9,"mirror_url":null,"open_issues_count":6,"forks":9,"open_issues":6,"watchers":11,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/easemob/easeui_ios/pulls/12"},"html":{"href":"https://github.com/easemob/easeui_ios/pull/12"},"issue":{"href":"https://api.github.com/repos/easemob/easeui_ios/issues/12"},"comments":{"href":"https://api.github.com/repos/easemob/easeui_ios/issues/12/comments"},"review_comments":{"href":"https://api.github.com/repos/easemob/easeui_ios/pulls/12/comments"},"review_comment":{"href":"https://api.github.com/repos/easemob/easeui_ios/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/easemob/easeui_ios/pulls/12/commits"},"statuses":{"href":"https://api.github.com/repos/easemob/easeui_ios/statuses/b0a3c7e002791bf365898513843c0a512710750d"}}}}