From 993c1653575372b732bc50b7143b25e000bbf19c Mon Sep 17 00:00:00 2001 From: Kacper Ziubryniewicz Date: Thu, 18 Apr 2019 20:25:25 +0200 Subject: [PATCH 1/6] Add forwarding attachments --- fbchat/_client.py | 15 +++++++++++++++ fbchat/_util.py | 1 + 2 files changed, 16 insertions(+) diff --git a/fbchat/_client.py b/fbchat/_client.py index 3c416ab5..65547f89 100644 --- a/fbchat/_client.py +++ b/fbchat/_client.py @@ -1715,6 +1715,21 @@ def sendLocalImage( thread_type=thread_type, ) + def forwardAttachment(self, attachment_id, thread_id=None): + """ + Forwards an attachment + + :param attachment_id: Attachment ID to forward + :param thread_id: User/Group ID to send to. See :ref:`intro_threads` + :raises: FBchatException if request failed + """ + thread_id, thread_type = self._getThread(thread_id, None) + data = { + "attachment_id": attachment_id, + "recipient_map[{}]".format(generateOfflineThreadingID()): thread_id, + } + j = self._post(self.req_url.FORWARD_ATTACHMENT, data, fix_request=True, as_json=True) + def createGroup(self, message, user_ids): """ Creates a group with the given ids diff --git a/fbchat/_util.py b/fbchat/_util.py index 87054426..7971a111 100644 --- a/fbchat/_util.py +++ b/fbchat/_util.py @@ -154,6 +154,7 @@ class ReqUrl(object): SEARCH_MESSAGES = "https://www.facebook.com/ajax/mercury/search_snippets.php?dpr=1" MARK_SPAM = "https://www.facebook.com/ajax/mercury/mark_spam.php?dpr=1" UNSEND = "https://www.facebook.com/messaging/unsend_message/?dpr=1" + FORWARD_ATTACHMENT = "https://www.facebook.com/mercury/attachments/forward/" pull_channel = 0 From 9284575c8810c07f09c047ca8db036cef496154a Mon Sep 17 00:00:00 2001 From: Kacper Ziubryniewicz Date: Thu, 18 Apr 2019 22:44:02 +0200 Subject: [PATCH 2/6] Lint --- fbchat/_client.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fbchat/_client.py b/fbchat/_client.py index 65547f89..1daa5292 100644 --- a/fbchat/_client.py +++ b/fbchat/_client.py @@ -1728,7 +1728,9 @@ def forwardAttachment(self, attachment_id, thread_id=None): "attachment_id": attachment_id, "recipient_map[{}]".format(generateOfflineThreadingID()): thread_id, } - j = self._post(self.req_url.FORWARD_ATTACHMENT, data, fix_request=True, as_json=True) + j = self._post( + self.req_url.FORWARD_ATTACHMENT, data, fix_request=True, as_json=True + ) def createGroup(self, message, user_ids): """ From 3f94c13b8e46634fe0223da8c9752c1bdaed786b Mon Sep 17 00:00:00 2001 From: Kacper Ziubryniewicz Date: Sun, 21 Apr 2019 20:35:40 +0200 Subject: [PATCH 3/6] Add handling other type of errors --- fbchat/_util.py | 47 ++++++++++++++++++++++++++--------------------- 1 file changed, 26 insertions(+), 21 deletions(-) diff --git a/fbchat/_util.py b/fbchat/_util.py index 7971a111..d71c40da 100644 --- a/fbchat/_util.py +++ b/fbchat/_util.py @@ -233,29 +233,34 @@ def generateOfflineThreadingID(): def check_json(j): - if j.get("error") is None: - return - if "errorDescription" in j: - # 'errorDescription' is in the users own language! + if j.get("payload") and j["payload"].get("error"): raise FBchatFacebookError( - "Error #{} when sending request: {}".format( - j["error"], j["errorDescription"] - ), - fb_error_code=j["error"], - fb_error_message=j["errorDescription"], - ) - elif "debug_info" in j["error"] and "code" in j["error"]: - raise FBchatFacebookError( - "Error #{} when sending request: {}".format( - j["error"]["code"], repr(j["error"]["debug_info"]) - ), - fb_error_code=j["error"]["code"], - fb_error_message=j["error"]["debug_info"], - ) - else: - raise FBchatFacebookError( - "Error {} when sending request".format(j["error"]), fb_error_code=j["error"] + "Error when sending request: {}".format(j["payload"]["error"]), + fb_error_code=None, + fb_error_message=j["payload"]["error"], ) + elif j.get("error"): + if "errorDescription" in j: + # 'errorDescription' is in the users own language! + raise FBchatFacebookError( + "Error #{} when sending request: {}".format( + j["error"], j["errorDescription"] + ), + fb_error_code=j["error"], + fb_error_message=j["errorDescription"], + ) + elif "debug_info" in j["error"] and "code" in j["error"]: + raise FBchatFacebookError( + "Error #{} when sending request: {}".format( + j["error"]["code"], repr(j["error"]["debug_info"]) + ), + fb_error_code=j["error"]["code"], + fb_error_message=j["error"]["debug_info"], + ) + else: + raise FBchatFacebookError( + "Error {} when sending request".format(j["error"]), fb_error_code=j["error"] + ) def check_request(r, as_json=True): From ab28df87d7d1333c56633d3986165466c25d2621 Mon Sep 17 00:00:00 2001 From: Kacper Ziubryniewicz Date: Sun, 21 Apr 2019 20:36:22 +0200 Subject: [PATCH 4/6] Lint --- fbchat/_util.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fbchat/_util.py b/fbchat/_util.py index d71c40da..d50bfc47 100644 --- a/fbchat/_util.py +++ b/fbchat/_util.py @@ -259,7 +259,8 @@ def check_json(j): ) else: raise FBchatFacebookError( - "Error {} when sending request".format(j["error"]), fb_error_code=j["error"] + "Error {} when sending request".format(j["error"]), + fb_error_code=j["error"], ) From 8b189b707683dc361fe33c34814b8be836d62bfa Mon Sep 17 00:00:00 2001 From: Kacper Ziubryniewicz Date: Wed, 24 Apr 2019 21:39:43 +0200 Subject: [PATCH 5/6] Add forwarded Message attribute --- fbchat/_client.py | 3 +++ fbchat/_graphql.py | 8 ++++++-- fbchat/_message.py | 2 ++ fbchat/_util.py | 6 ++++++ fbchat/utils.py | 1 + 5 files changed, 18 insertions(+), 2 deletions(-) diff --git a/fbchat/_client.py b/fbchat/_client.py index 1daa5292..03a4ce28 100644 --- a/fbchat/_client.py +++ b/fbchat/_client.py @@ -2985,6 +2985,7 @@ def getThreadIdAndThreadType(msg_metadata): sticker = None attachments = [] unsent = False + forwarded = False if delta.get("attachments"): try: for a in delta["attachments"]: @@ -3026,6 +3027,7 @@ def getThreadIdAndThreadType(msg_metadata): if metadata and metadata.get("tags"): emoji_size = get_emojisize_from_tags(metadata.get("tags")) + forwarded = get_forwarded_from_tags(metadata.get("tags")) message = Message( text=delta.get("body"), @@ -3039,6 +3041,7 @@ def getThreadIdAndThreadType(msg_metadata): message.timestamp = ts # message.reactions = {} message.unsent = unsent + message.forwarded = forwarded thread_id, thread_type = getThreadIdAndThreadType(metadata) self.onMessage( mid=mid, diff --git a/fbchat/_graphql.py b/fbchat/_graphql.py index 3c1bac89..87f336d9 100644 --- a/fbchat/_graphql.py +++ b/fbchat/_graphql.py @@ -359,6 +359,7 @@ def graphql_to_message(message): message["message_sender"] = {} if message.get("message") is None: message["message"] = {} + tags = message.get("tags_list") rtn = Message( text=message.get("message").get("text"), mentions=[ @@ -369,7 +370,7 @@ def graphql_to_message(message): ) for m in message.get("message").get("ranges", []) ], - emoji_size=get_emojisize_from_tags(message.get("tags_list")), + emoji_size=get_emojisize_from_tags(tags), sticker=graphql_to_sticker(message.get("sticker")), ) rtn.uid = str(message.get("message_id")) @@ -403,17 +404,19 @@ def graphql_to_message(message): rtn.attachments.append(attachment) if message.get("replied_to_message") is not None: rtn.replied_to = graphql_to_message(message["replied_to_message"]["message"]) + rtn.forwarded = get_forwarded_from_tags(tags) return rtn def graphql_to_message_reply(message): + tags = message["messageMetadata"].get("tags") 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")), + emoji_size=get_emojisize_from_tags(tags), ) metadata = message.get("messageMetadata", {}) rtn.uid = metadata.get("messageId") @@ -445,6 +448,7 @@ def graphql_to_message_reply(message): rtn.attachments.append(extensible_attachment) if attachment.get("sticker_attachment"): rtn.sticker = graphql_to_sticker(attachment["sticker_attachment"]) + rtn.forwarded = get_forwarded_from_tags(tags) return rtn diff --git a/fbchat/_message.py b/fbchat/_message.py index 32037782..a0630c6c 100644 --- a/fbchat/_message.py +++ b/fbchat/_message.py @@ -72,6 +72,8 @@ class Message(object): reply_to_id = attr.ib(None) #: Replied message replied_to = attr.ib(None, init=False) + #: Whether the message was forwarded + forwarded = attr.ib(False, init=False) @classmethod def formatMentions(cls, text, *args, **kwargs): diff --git a/fbchat/_util.py b/fbchat/_util.py index d50bfc47..15d6223e 100644 --- a/fbchat/_util.py +++ b/fbchat/_util.py @@ -316,6 +316,12 @@ def get_emojisize_from_tags(tags): return None +def get_forwarded_from_tags(tags): + if tags is None: + return False + return any(map(lambda tag: "forward" in tag or "copy" in tag, tags)) + + def require_list(list_): if isinstance(list_, list): return set(list_) diff --git a/fbchat/utils.py b/fbchat/utils.py index fedb1ea0..e58a7830 100644 --- a/fbchat/utils.py +++ b/fbchat/utils.py @@ -26,6 +26,7 @@ check_request, get_jsmods_require, get_emojisize_from_tags, + get_forwarded_from_tags, require_list, mimetype_to_key, get_files_from_urls, From c57f8b7f3176a71d5e578dacee0d7a475cb951db Mon Sep 17 00:00:00 2001 From: Kacper Ziubryniewicz Date: Wed, 24 Apr 2019 22:50:34 +0200 Subject: [PATCH 6/6] Remove `get_forwarded_from_tags` from utils.py --- fbchat/utils.py | 1 - 1 file changed, 1 deletion(-) diff --git a/fbchat/utils.py b/fbchat/utils.py index e58a7830..fedb1ea0 100644 --- a/fbchat/utils.py +++ b/fbchat/utils.py @@ -26,7 +26,6 @@ check_request, get_jsmods_require, get_emojisize_from_tags, - get_forwarded_from_tags, require_list, mimetype_to_key, get_files_from_urls,