Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions fbchat/_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -1707,6 +1707,23 @@ 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(
Comment thread
madsmtm marked this conversation as resolved.
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
Expand Down
17 changes: 15 additions & 2 deletions fbchat/_message.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,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):
Expand Down Expand Up @@ -144,12 +146,19 @@ def formatMentions(cls, text, *args, **kwargs):
message = cls(text=result, mentions=mentions)
return message

@staticmethod
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))

@classmethod
def _from_graphql(cls, data):
if data.get("message_sender") is None:
data["message_sender"] = {}
if data.get("message") is None:
data["message"] = {}
tags = data.get("tags_list")
rtn = cls(
text=data["message"].get("text"),
mentions=[
Expand All @@ -160,7 +169,8 @@ def _from_graphql(cls, data):
)
for m in data["message"].get("ranges") or ()
],
emoji_size=EmojiSize._from_tags(data.get("tags_list")),
emoji_size=EmojiSize._from_tags(tags),
forwarded=cls._get_forwarded_from_tags(tags),
sticker=_sticker.Sticker._from_graphql(data.get("sticker")),
)
rtn.uid = str(data["message_id"])
Expand Down Expand Up @@ -203,13 +213,15 @@ def _from_graphql(cls, data):

@classmethod
def _from_reply(cls, data):
tags = data["messageMetadata"].get("tags")
rtn = cls(
text=data.get("body"),
mentions=[
Mention(m.get("i"), offset=m.get("o"), length=m.get("l"))
for m in json.loads(data.get("data", {}).get("prng", "[]"))
],
emoji_size=EmojiSize._from_tags(data["messageMetadata"].get("tags")),
emoji_size=EmojiSize._from_tags(tags),
forwarded=cls._get_forwarded_from_tags(tags),
)
metadata = data.get("messageMetadata", {})
rtn.uid = metadata.get("messageId")
Expand Down Expand Up @@ -311,6 +323,7 @@ def _from_pull(cls, data, mid=None, tags=None, author=None, timestamp=None):
)

rtn.emoji_size = EmojiSize._from_tags(tags)
rtn.forwarded = cls._get_forwarded_from_tags(tags)

return rtn

Expand Down
49 changes: 28 additions & 21 deletions fbchat/_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,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

Expand Down Expand Up @@ -192,29 +193,35 @@ 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):
Expand Down