diff options
author | John Smith <mrdoctorwho@helldev.net> | 2018-07-26 20:17:37 +0300 |
---|---|---|
committer | John Smith <mrdoctorwho@helldev.net> | 2018-07-26 20:17:37 +0300 |
commit | 368915900b27ae9eeac372bdda42184b0a9b5207 (patch) | |
tree | c93c766a2a1f7c49511e3767927b1ae8989424cd | |
parent | 55826a3503bf6ad5f70574a3125a34999ef0bb2d (diff) |
Completely rewrite the message reception algorithms (use execute.getMessagesBulk)
-rw-r--r-- | extensions/groupchats.py | 12 | ||||
-rw-r--r-- | gateway.py | 86 | ||||
-rw-r--r-- | js/getMessagesBulk.js | 4 | ||||
-rw-r--r-- | library/longpoll.py | 3 |
4 files changed, 70 insertions, 35 deletions
diff --git a/extensions/groupchats.py b/extensions/groupchats.py index 2f03633..37e9ea5 100644 --- a/extensions/groupchats.py +++ b/extensions/groupchats.py @@ -164,10 +164,14 @@ def handleOutgoingChatMessage(user, vkChat): members = user.vk.method("messages.getConversationMembers", {"peer_id": MIN_CHAT_ID + chatID}) members = members.get("items") chat_active = settings.get("active_ids") - for member in members: - if member["is_admin"]: - owner = member["member_id"] - break + if members: + for member in members: + if member["is_admin"]: + owner = member["member_id"] + break + else: + logger.warning("groupchats: unable to get members for groupchat: %s (%s)", chatID) + return None chat.init(owner, chatID, chatJID, settings["title"], time.time(), chat_active) if not chat.created: @@ -460,43 +460,74 @@ class VK(object): self.lists = self.method("friends.getLists") return self.lists - def getInnerConversation(self, conversation, messages, mid): - if isinstance(conversation, dict): - innerConversation = conversation.get("conversation") - if innerConversation: - peer = innerConversation["peer"]["id"] - peerMessageHistory = self.method("messages.getHistory", {"user_id": peer, "start_message_id": mid}) + @staticmethod + def getPeerIds(conversations): + """ + Returns a list of peer ids that exist in the given conversations + Args: + conversations: list of Conversations objects + Returns: + A list of peer id strings + """ + peers = [] + for conversation in conversations: + if isinstance(conversation, dict): + innerConversation = conversation.get("conversation") + if innerConversation: + peers.append(str(innerConversation["peer"]["id"])) + return peers + + def getMessagesBulk(self, peers, messages=None, count=20, mid=0): + """ + Recursively receives messages for all the conversations' peers + 25 is the maximum number of conversations we can receive in a single request + The sky is the limit! + Args: + peers: a list of peer ids (strings) + messages: a list of messages (used internally) + count: the number of messages to receive + uid: the last message id + Returns: + A list of VK Message objects + """ + messages = messages or [] + if peers: + parts = (peers[:25], peers[25:]) + users = ",".join(parts[0]) + response = self.method("execute.getMessagesBulk", {"users": users, "start_message_id": mid, "count": count}) or [] + for message in response: # skipping count-only reponses - if peerMessageHistory and len(peerMessageHistory) > 1: - messages.append(peerMessageHistory) + if len(message) > 1: + if isinstance(message, list): + first = message[0] + # removing the unread count + if isinstance(first, (int, long)): + message.remove(first) + messages.extend(message) + else: + # not sure if that's okay + # VK is totally unpredictable now + logger.warning("no response for execute.getMessagesBulk! Users: %s, mid: %s", users, mid) + return self.getMessagesBulk(parts[1], messages, count, mid) + return messages - def getMessages(self, count=5, mid=0, uid=0): + def getMessages(self, count=20, mid=0, uid=0): """ Gets the last messages list Args: count: the number of messages to receive mid: the last message id Returns: - The result of the messages.get method + A list of VK Message objects """ - if mid: - mid -= 20 # preventing message loss; receiving last 20 messages before the current one if uid == 0: - conversations = self.method("messages.getConversations", {"filters": "unread", "count": count}) + conversations = self.method("messages.getConversations", {"count": count}) else: conversations = {"unread_count": 1, "1": {"conversation": {"peer": {"id": uid}}}} - messages = [] - # what a horrible decision to have two different data types in the response? if isinstance(conversations, dict): - unreadCount = conversations.get("unread_count", 0) - if unreadCount > 0: - for conversationId in conversations: - conversation = conversations[conversationId] - self.getInnerConversation(conversation, messages, mid) - elif isinstance(conversations, list): - for conversation in conversations: - self.getInnerConversation(conversation, messages, mid) - return messages + conversations = conversations.values() + peers = VK.getPeerIds(conversations) + return self.getMessagesBulk(peers, count=count, mid=mid) # TODO: put this in the DB def getUserID(self): @@ -748,12 +779,11 @@ class User(object): date = 0 if not messages: messages = self.vk.getMessages(MAX_MESSAGES_PER_REQUEST, mid or self.lastMsgID, uid) - if not messages: # or not messages[0]: + if not messages: return None - messages = sorted([message[1] for message in messages], sortMsg) + messages = sorted(messages, sortMsg) for message in messages: - # If message wasn't sent by our user - # and not message["read_state"] + # check if message wasn't sent by our user if not message["out"]: Stats["msgin"] += 1 frm = message["uid"] diff --git a/js/getMessagesBulk.js b/js/getMessagesBulk.js index b1aaac1..765c978 100644 --- a/js/getMessagesBulk.js +++ b/js/getMessagesBulk.js @@ -1,13 +1,15 @@ +// Allows to receive conversations' logs for up to 25 users var users = Args.users.split(","); var startMessageId = Args.start_message_id; if (startMessageId == null) { startMessageId = 0; } var history = []; +var user; var length = users.length; while (length > 0) { var uid = users[length - 1]; - var userHistory = API.messages.getHistory({"user_id": uid, "start_message_id": startMessageId}); + var userHistory = API.messages.getHistory({"user_id":uid, "start_message_id": startMessageId, "count": Args.count}); history.push(userHistory); length = length - 1; } diff --git a/library/longpoll.py b/library/longpoll.py index e20b4f1..d75c822 100644 --- a/library/longpoll.py +++ b/library/longpoll.py @@ -110,8 +110,7 @@ def processPollResult(user, data): chat = (uid > MIN_CHAT_UID) # a groupchat always has uid > 2000000000 if not out: if not attachments and not chat: - message = [[1, - {"out": 0, "uid": uid, "mid": mid, "date": date, "body": body}]] + message = [{"out": 0, "uid": uid, "mid": mid, "date": date, "body": body}] utils.runThread(user.sendMessages, (False, message, mid, uid), "sendMessages-%s" % user.source) else: logger.warning( |