diff --git a/fbchat/_client.py b/fbchat/_client.py index a4a363d..8e0c8df 100644 --- a/fbchat/_client.py +++ b/fbchat/_client.py @@ -390,9 +390,9 @@ class Client(object): if "home" in r.url: return r - del (data["approvals_code"]) - del (data["submit[Submit Code]"]) - del (data["codes_submitted"]) + del data["approvals_code"] + del data["submit[Submit Code]"] + del data["codes_submitted"] data["name_action_selected"] = "save_device" data["submit[Continue]"] = "Continue" @@ -404,7 +404,7 @@ class Client(object): if "home" in r.url: return r - del (data["name_action_selected"]) + del data["name_action_selected"] log.info( "Starting Facebook checkup flow." ) # At this stage, we have dtsg, nh, submit[Continue] @@ -413,7 +413,7 @@ class Client(object): if "home" in r.url: return r - del (data["submit[Continue]"]) + del data["submit[Continue]"] data["submit[This was me]"] = "This Was Me" log.info( "Verifying login attempt." @@ -423,7 +423,7 @@ class Client(object): if "home" in r.url: return r - del (data["submit[This was me]"]) + del data["submit[This was me]"] data["submit[Continue]"] = "Continue" data["name_action_selected"] = "save_device" log.info( @@ -1084,7 +1084,7 @@ class Client(object): j = self.graphql_request( GraphQL( - doc_id="1386147188135407", + doc_id="1860982147341344", params={ "id": thread_id, "message_limit": limit, @@ -1379,6 +1379,9 @@ class Client(object): xmd["quick_replies"] = xmd["quick_replies"][0] data["platform_xmd"] = json.dumps(xmd) + if message.reply_to_id: + data["replied_to_message_id"] = message.reply_to_id + return data def _doSendRequest(self, data, get_thread_id=False): @@ -3037,6 +3040,24 @@ class Client(object): msg=m, ) + elif d.get("deltaMessageReply"): + i = d["deltaMessageReply"] + metadata = i["message"]["messageMetadata"] + thread_id, thread_type = getThreadIdAndThreadType(metadata) + message = graphql_to_message_reply(i["message"]) + message.replied_to = graphql_to_message_reply(i["repliedToMessage"]) + self.onMessage( + mid=message.uid, + author_id=message.author, + message=message.text, + message_object=message, + thread_id=thread_id, + thread_type=thread_type, + ts=message.timestamp, + metadata=metadata, + msg=m, + ) + # New message elif delta.get("class") == "NewMessage": mentions = [] diff --git a/fbchat/_graphql.py b/fbchat/_graphql.py index 4bf8cab..3c1bac8 100644 --- a/fbchat/_graphql.py +++ b/fbchat/_graphql.py @@ -401,6 +401,50 @@ def graphql_to_message(message): rtn.unsent = True elif attachment: rtn.attachments.append(attachment) + if message.get("replied_to_message") is not None: + rtn.replied_to = graphql_to_message(message["replied_to_message"]["message"]) + return rtn + + +def graphql_to_message_reply(message): + rtn = Message( + text=message.get("body"), + mentions=[ + Mention(m.get("i"), offset=m.get("o"), length=m.get("l")) + for m in json.loads(message.get("data", {}).get("prng", "[]")) + ], + emoji_size=get_emojisize_from_tags(message["messageMetadata"].get("tags")), + ) + metadata = message.get("messageMetadata", {}) + rtn.uid = metadata.get("messageId") + rtn.author = str(metadata.get("actorFbId")) + rtn.timestamp = metadata.get("timestamp") + rtn.unsent = False + if message.get("data", {}).get("platform_xmd"): + quick_replies = json.loads(message["data"]["platform_xmd"]).get("quick_replies") + if isinstance(quick_replies, list): + rtn.quick_replies = [graphql_to_quick_reply(q) for q in quick_replies] + elif isinstance(quick_replies, dict): + rtn.quick_replies = [ + graphql_to_quick_reply(quick_replies, is_response=True) + ] + if message.get("attachments") is not None: + for attachment in message["attachments"]: + attachment = json.loads(attachment["mercuryJSON"]) + if attachment.get("blob_attachment"): + rtn.attachments.append( + graphql_to_attachment(attachment["blob_attachment"]) + ) + if attachment.get("extensible_attachment"): + extensible_attachment = graphql_to_extensible_attachment( + attachment["extensible_attachment"] + ) + if isinstance(extensible_attachment, UnsentMessage): + rtn.unsent = True + else: + rtn.attachments.append(extensible_attachment) + if attachment.get("sticker_attachment"): + rtn.sticker = graphql_to_sticker(attachment["sticker_attachment"]) return rtn diff --git a/fbchat/_message.py b/fbchat/_message.py index 3f6f03d..3203778 100644 --- a/fbchat/_message.py +++ b/fbchat/_message.py @@ -68,6 +68,10 @@ class Message(object): quick_replies = attr.ib(factory=list, converter=lambda x: [] if x is None else x) #: Whether the message is unsent (deleted for everyone) unsent = attr.ib(False, init=False) + #: Message ID you want to reply to + reply_to_id = attr.ib(None) + #: Replied message + replied_to = attr.ib(None, init=False) @classmethod def formatMentions(cls, text, *args, **kwargs): diff --git a/fbchat/graphql.py b/fbchat/graphql.py index aeef27c..251e036 100644 --- a/fbchat/graphql.py +++ b/fbchat/graphql.py @@ -20,6 +20,7 @@ from ._graphql import ( graphql_to_plan, graphql_to_quick_reply, graphql_to_message, + graphql_to_message_reply, graphql_to_user, graphql_to_thread, graphql_to_group,