Stop mutating models
This commit is contained in:
@@ -43,8 +43,19 @@ class ShareAttachment(Attachment):
|
||||
def _from_graphql(cls, data):
|
||||
from . import _file
|
||||
|
||||
image = None
|
||||
original_image_url = None
|
||||
media = data.get("media")
|
||||
if media and media.get("image"):
|
||||
image = Image._from_uri(media["image"])
|
||||
original_image_url = (
|
||||
_util.get_url_parameter(image.url, "url")
|
||||
if "/safe_image.php" in image.url
|
||||
else image.url
|
||||
)
|
||||
|
||||
url = data.get("url")
|
||||
rtn = cls(
|
||||
return cls(
|
||||
uid=data.get("deduplication_key"),
|
||||
author=data["target"]["actors"][0]["id"]
|
||||
if data["target"].get("actors")
|
||||
@@ -58,18 +69,10 @@ class ShareAttachment(Attachment):
|
||||
if data.get("description")
|
||||
else None,
|
||||
source=data["source"].get("text") if data.get("source") else None,
|
||||
image=image,
|
||||
original_image_url=original_image_url,
|
||||
attachments=[
|
||||
_file.graphql_to_subattachment(attachment)
|
||||
for attachment in data.get("subattachments")
|
||||
],
|
||||
)
|
||||
media = data.get("media")
|
||||
if media and media.get("image"):
|
||||
image = media["image"]
|
||||
rtn.image = Image._from_uri(image)
|
||||
rtn.original_image_url = (
|
||||
_util.get_url_parameter(rtn.image.url, "url")
|
||||
if "/safe_image.php" in rtn.image.url
|
||||
else rtn.image.url
|
||||
)
|
||||
return rtn
|
||||
|
@@ -686,22 +686,14 @@ class Client:
|
||||
if j.get("message_thread") is None:
|
||||
raise FBchatException("Could not fetch thread {}: {}".format(thread_id, j))
|
||||
|
||||
read_receipts = j["message_thread"]["read_receipts"]["nodes"]
|
||||
|
||||
messages = [
|
||||
Message._from_graphql(message)
|
||||
Message._from_graphql(message, read_receipts)
|
||||
for message in j["message_thread"]["messages"]["nodes"]
|
||||
]
|
||||
messages.reverse()
|
||||
|
||||
read_receipts = j["message_thread"]["read_receipts"]["nodes"]
|
||||
|
||||
for message in messages:
|
||||
for receipt in read_receipts:
|
||||
if (
|
||||
_util.millis_to_datetime(int(receipt["watermark"]))
|
||||
>= message.created_at
|
||||
):
|
||||
message.read_by.append(receipt["actor"]["id"])
|
||||
|
||||
return messages
|
||||
|
||||
def fetch_thread_list(
|
||||
@@ -1009,11 +1001,16 @@ class Client:
|
||||
Raises:
|
||||
FBchatException: If request failed
|
||||
"""
|
||||
quick_reply.is_response = True
|
||||
if isinstance(quick_reply, QuickReplyText):
|
||||
return self.send(
|
||||
Message(text=quick_reply.title, quick_replies=[quick_reply])
|
||||
new = QuickReplyText(
|
||||
payload=quick_reply.payload,
|
||||
external_payload=quick_reply.external_payload,
|
||||
data=quick_reply.data,
|
||||
is_response=True,
|
||||
title=quick_reply.title,
|
||||
image_url=quick_reply.image_url,
|
||||
)
|
||||
return self.send(Message(text=quick_reply.title, quick_replies=[new]))
|
||||
elif isinstance(quick_reply, QuickReplyLocation):
|
||||
if not isinstance(payload, LocationAttachment):
|
||||
raise TypeError(
|
||||
@@ -1023,17 +1020,23 @@ class Client:
|
||||
payload, thread_id=thread_id, thread_type=thread_type
|
||||
)
|
||||
elif isinstance(quick_reply, QuickReplyEmail):
|
||||
if not payload:
|
||||
payload = self.get_emails()[0]
|
||||
quick_reply.external_payload = quick_reply.payload
|
||||
quick_reply.payload = payload
|
||||
return self.send(Message(text=payload, quick_replies=[quick_reply]))
|
||||
new = QuickReplyEmail(
|
||||
payload=payload if payload else self.get_emails()[0],
|
||||
external_payload=quick_reply.payload,
|
||||
data=quick_reply.data,
|
||||
is_response=True,
|
||||
image_url=quick_reply.image_url,
|
||||
)
|
||||
return self.send(Message(text=payload, quick_replies=[new]))
|
||||
elif isinstance(quick_reply, QuickReplyPhoneNumber):
|
||||
if not payload:
|
||||
payload = self.get_phone_numbers()[0]
|
||||
quick_reply.external_payload = quick_reply.payload
|
||||
quick_reply.payload = payload
|
||||
return self.send(Message(text=payload, quick_replies=[quick_reply]))
|
||||
new = QuickReplyPhoneNumber(
|
||||
payload=payload if payload else self.get_phone_numbers()[0],
|
||||
external_payload=quick_reply.payload,
|
||||
data=quick_reply.data,
|
||||
is_response=True,
|
||||
image_url=quick_reply.image_url,
|
||||
)
|
||||
return self.send(Message(text=payload, quick_replies=[new]))
|
||||
|
||||
def unsend(self, mid):
|
||||
"""Unsend message by it's ID (removes it for everyone).
|
||||
@@ -2533,9 +2536,8 @@ class Client:
|
||||
i = d["deltaMessageReply"]
|
||||
metadata = i["message"]["messageMetadata"]
|
||||
thread_id, thread_type = get_thread_id_and_thread_type(metadata)
|
||||
message = Message._from_reply(i["message"])
|
||||
message.replied_to = Message._from_reply(i["repliedToMessage"])
|
||||
message.reply_to_id = message.replied_to.uid
|
||||
replied_to = Message._from_reply(i["repliedToMessage"])
|
||||
message = Message._from_reply(i["message"], replied_to)
|
||||
self.on_message(
|
||||
mid=message.uid,
|
||||
author_id=message.author,
|
||||
|
@@ -18,9 +18,10 @@ class FileAttachment(Attachment):
|
||||
is_malicious = attr.ib(None)
|
||||
|
||||
@classmethod
|
||||
def _from_graphql(cls, data):
|
||||
def _from_graphql(cls, data, size=None):
|
||||
return cls(
|
||||
url=data.get("url"),
|
||||
size=size,
|
||||
name=data.get("filename"),
|
||||
is_malicious=data.get("is_malicious"),
|
||||
uid=data.get("message_file_fbid"),
|
||||
@@ -130,8 +131,9 @@ class VideoAttachment(Attachment):
|
||||
large_image = attr.ib(None)
|
||||
|
||||
@classmethod
|
||||
def _from_graphql(cls, data):
|
||||
def _from_graphql(cls, data, size=None):
|
||||
return cls(
|
||||
size=size,
|
||||
width=data.get("original_dimensions", {}).get("width"),
|
||||
height=data.get("original_dimensions", {}).get("height"),
|
||||
duration=_util.millis_to_timedelta(data.get("playable_duration_in_ms")),
|
||||
@@ -165,16 +167,16 @@ class VideoAttachment(Attachment):
|
||||
)
|
||||
|
||||
|
||||
def graphql_to_attachment(data):
|
||||
def graphql_to_attachment(data, size=None):
|
||||
_type = data["__typename"]
|
||||
if _type in ["MessageImage", "MessageAnimatedImage"]:
|
||||
return ImageAttachment._from_graphql(data)
|
||||
elif _type == "MessageVideo":
|
||||
return VideoAttachment._from_graphql(data)
|
||||
return VideoAttachment._from_graphql(data, size=size)
|
||||
elif _type == "MessageAudio":
|
||||
return AudioAttachment._from_graphql(data)
|
||||
elif _type == "MessageFile":
|
||||
return FileAttachment._from_graphql(data)
|
||||
return FileAttachment._from_graphql(data, size=size)
|
||||
|
||||
return Attachment(uid=data.get("legacy_attachment_id"))
|
||||
|
||||
|
@@ -31,17 +31,17 @@ class LocationAttachment(Attachment):
|
||||
address = None
|
||||
except ValueError:
|
||||
latitude, longitude = None, None
|
||||
rtn = cls(
|
||||
|
||||
return cls(
|
||||
uid=int(data["deduplication_key"]),
|
||||
latitude=latitude,
|
||||
longitude=longitude,
|
||||
image=Image._from_uri_or_none(data["media"].get("image"))
|
||||
if data.get("media")
|
||||
else None,
|
||||
url=url,
|
||||
address=address,
|
||||
)
|
||||
media = data.get("media")
|
||||
if media and media.get("image"):
|
||||
rtn.image = Image._from_uri(media["image"])
|
||||
rtn.url = url
|
||||
return rtn
|
||||
|
||||
|
||||
@attr.s
|
||||
@@ -73,7 +73,13 @@ class LiveLocationAttachment(LocationAttachment):
|
||||
@classmethod
|
||||
def _from_graphql(cls, data):
|
||||
target = data["target"]
|
||||
rtn = cls(
|
||||
|
||||
image = None
|
||||
media = data.get("media")
|
||||
if media and media.get("image"):
|
||||
image = Image._from_uri(media["image"])
|
||||
|
||||
return cls(
|
||||
uid=int(target["live_location_id"]),
|
||||
latitude=target["coordinate"]["latitude"]
|
||||
if target.get("coordinate")
|
||||
@@ -81,12 +87,9 @@ class LiveLocationAttachment(LocationAttachment):
|
||||
longitude=target["coordinate"]["longitude"]
|
||||
if target.get("coordinate")
|
||||
else None,
|
||||
image=image,
|
||||
url=data.get("url"),
|
||||
name=data["title_with_entities"]["text"],
|
||||
expires_at=_util.seconds_to_datetime(target.get("expiration_time")),
|
||||
is_expired=target.get("is_expired"),
|
||||
)
|
||||
media = data.get("media")
|
||||
if media and media.get("image"):
|
||||
rtn.image = Image._from_uri(media["image"])
|
||||
rtn.url = data.get("url")
|
||||
return rtn
|
||||
|
@@ -139,8 +139,7 @@ class Message:
|
||||
)
|
||||
offset += len(name)
|
||||
|
||||
message = cls(text=result, mentions=mentions)
|
||||
return message
|
||||
return cls(text=result, mentions=mentions)
|
||||
|
||||
@staticmethod
|
||||
def _get_forwarded_from_tags(tags):
|
||||
@@ -197,14 +196,43 @@ class Message:
|
||||
|
||||
return data
|
||||
|
||||
@staticmethod
|
||||
def _parse_quick_replies(data):
|
||||
if data:
|
||||
data = json.loads(data).get("quick_replies")
|
||||
if isinstance(data, list):
|
||||
return [_quick_reply.graphql_to_quick_reply(q) for q in data]
|
||||
elif isinstance(data, dict):
|
||||
return [_quick_reply.graphql_to_quick_reply(data, is_response=True)]
|
||||
return []
|
||||
|
||||
@classmethod
|
||||
def _from_graphql(cls, data):
|
||||
def _from_graphql(cls, data, read_receipts=None):
|
||||
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(
|
||||
|
||||
created_at = _util.millis_to_datetime(int(data.get("timestamp_precise")))
|
||||
|
||||
attachments = [
|
||||
_file.graphql_to_attachment(attachment)
|
||||
for attachment in data["blob_attachments"] or ()
|
||||
]
|
||||
unsent = False
|
||||
if data.get("extensible_attachment") is not None:
|
||||
attachment = graphql_to_extensible_attachment(data["extensible_attachment"])
|
||||
if isinstance(attachment, _attachment.UnsentMessage):
|
||||
unsent = True
|
||||
elif attachment:
|
||||
attachments.append(attachment)
|
||||
|
||||
replied_to = None
|
||||
if data.get("replied_to_message"):
|
||||
replied_to = cls._from_graphql(data["replied_to_message"]["message"])
|
||||
|
||||
return cls(
|
||||
text=data["message"].get("text"),
|
||||
mentions=[
|
||||
Mention(
|
||||
@@ -215,81 +243,40 @@ class Message:
|
||||
for m in data["message"].get("ranges") or ()
|
||||
],
|
||||
emoji_size=EmojiSize._from_tags(tags),
|
||||
sticker=_sticker.Sticker._from_graphql(data.get("sticker")),
|
||||
)
|
||||
rtn.forwarded = cls._get_forwarded_from_tags(tags)
|
||||
rtn.uid = str(data["message_id"])
|
||||
rtn.author = str(data["message_sender"]["id"])
|
||||
rtn.created_at = _util.millis_to_datetime(int(data.get("timestamp_precise")))
|
||||
rtn.unsent = False
|
||||
if data.get("unread") is not None:
|
||||
rtn.is_read = not data["unread"]
|
||||
rtn.reactions = {
|
||||
uid=str(data["message_id"]),
|
||||
author=str(data["message_sender"]["id"]),
|
||||
created_at=created_at,
|
||||
is_read=not data["unread"] if data.get("unread") is not None else None,
|
||||
read_by=[
|
||||
receipt["actor"]["id"]
|
||||
for receipt in read_receipts or ()
|
||||
if _util.millis_to_datetime(int(receipt["watermark"])) >= created_at
|
||||
],
|
||||
reactions={
|
||||
str(r["user"]["id"]): MessageReaction._extend_if_invalid(r["reaction"])
|
||||
for r in data["message_reactions"]
|
||||
}
|
||||
if data.get("blob_attachments") is not None:
|
||||
rtn.attachments = [
|
||||
_file.graphql_to_attachment(attachment)
|
||||
for attachment in data["blob_attachments"]
|
||||
]
|
||||
if data.get("platform_xmd_encoded"):
|
||||
quick_replies = json.loads(data["platform_xmd_encoded"]).get(
|
||||
"quick_replies"
|
||||
},
|
||||
sticker=_sticker.Sticker._from_graphql(data.get("sticker")),
|
||||
attachments=attachments,
|
||||
quick_replies=cls._parse_quick_replies(data.get("platform_xmd_encoded")),
|
||||
unsent=unsent,
|
||||
reply_to_id=replied_to.uid if replied_to else None,
|
||||
replied_to=replied_to,
|
||||
forwarded=cls._get_forwarded_from_tags(tags),
|
||||
)
|
||||
if isinstance(quick_replies, list):
|
||||
rtn.quick_replies = [
|
||||
_quick_reply.graphql_to_quick_reply(q) for q in quick_replies
|
||||
]
|
||||
elif isinstance(quick_replies, dict):
|
||||
rtn.quick_replies = [
|
||||
_quick_reply.graphql_to_quick_reply(quick_replies, is_response=True)
|
||||
]
|
||||
if data.get("extensible_attachment") is not None:
|
||||
attachment = graphql_to_extensible_attachment(data["extensible_attachment"])
|
||||
if isinstance(attachment, _attachment.UnsentMessage):
|
||||
rtn.unsent = True
|
||||
elif attachment:
|
||||
rtn.attachments.append(attachment)
|
||||
if data.get("replied_to_message") is not None:
|
||||
rtn.replied_to = cls._from_graphql(data["replied_to_message"]["message"])
|
||||
rtn.reply_to_id = rtn.replied_to.uid
|
||||
return rtn
|
||||
|
||||
@classmethod
|
||||
def _from_reply(cls, data):
|
||||
def _from_reply(cls, data, replied_to=None):
|
||||
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(tags),
|
||||
)
|
||||
metadata = data.get("messageMetadata", {})
|
||||
rtn.forwarded = cls._get_forwarded_from_tags(tags)
|
||||
rtn.uid = metadata.get("messageId")
|
||||
rtn.author = str(metadata.get("actorFbId"))
|
||||
rtn.created_at = _util.millis_to_datetime(metadata.get("timestamp"))
|
||||
rtn.unsent = False
|
||||
if data.get("data", {}).get("platform_xmd"):
|
||||
quick_replies = json.loads(data["data"]["platform_xmd"]).get(
|
||||
"quick_replies"
|
||||
)
|
||||
if isinstance(quick_replies, list):
|
||||
rtn.quick_replies = [
|
||||
_quick_reply.graphql_to_quick_reply(q) for q in quick_replies
|
||||
]
|
||||
elif isinstance(quick_replies, dict):
|
||||
rtn.quick_replies = [
|
||||
_quick_reply.graphql_to_quick_reply(quick_replies, is_response=True)
|
||||
]
|
||||
if data.get("attachments") is not None:
|
||||
for attachment in data["attachments"]:
|
||||
|
||||
attachments = []
|
||||
unsent = False
|
||||
sticker = None
|
||||
for attachment in data.get("attachments") or ():
|
||||
attachment = json.loads(attachment["mercuryJSON"])
|
||||
if attachment.get("blob_attachment"):
|
||||
rtn.attachments.append(
|
||||
attachments.append(
|
||||
_file.graphql_to_attachment(attachment["blob_attachment"])
|
||||
)
|
||||
if attachment.get("extensible_attachment"):
|
||||
@@ -297,25 +284,39 @@ class Message:
|
||||
attachment["extensible_attachment"]
|
||||
)
|
||||
if isinstance(extensible_attachment, _attachment.UnsentMessage):
|
||||
rtn.unsent = True
|
||||
unsent = True
|
||||
else:
|
||||
rtn.attachments.append(extensible_attachment)
|
||||
attachments.append(extensible_attachment)
|
||||
if attachment.get("sticker_attachment"):
|
||||
rtn.sticker = _sticker.Sticker._from_graphql(
|
||||
sticker = _sticker.Sticker._from_graphql(
|
||||
attachment["sticker_attachment"]
|
||||
)
|
||||
return rtn
|
||||
|
||||
return 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(tags),
|
||||
uid=metadata.get("messageId"),
|
||||
author=str(metadata.get("actorFbId")),
|
||||
created_at=_util.millis_to_datetime(metadata.get("timestamp")),
|
||||
sticker=sticker,
|
||||
attachments=attachments,
|
||||
quick_replies=cls._parse_quick_replies(data.get("platform_xmd_encoded")),
|
||||
unsent=unsent,
|
||||
reply_to_id=replied_to.uid if replied_to else None,
|
||||
replied_to=replied_to,
|
||||
forwarded=cls._get_forwarded_from_tags(tags),
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def _from_pull(cls, data, mid=None, tags=None, author=None, created_at=None):
|
||||
rtn = cls(text=data.get("body"))
|
||||
rtn.uid = mid
|
||||
rtn.author = author
|
||||
rtn.created_at = created_at
|
||||
|
||||
mentions = []
|
||||
if data.get("data") and data["data"].get("prng"):
|
||||
try:
|
||||
rtn.mentions = [
|
||||
mentions = [
|
||||
Mention(
|
||||
str(mention.get("i")),
|
||||
offset=mention.get("o"),
|
||||
@@ -326,28 +327,22 @@ class Message:
|
||||
except Exception:
|
||||
log.exception("An exception occured while reading attachments")
|
||||
|
||||
if data.get("attachments"):
|
||||
attachments = []
|
||||
unsent = False
|
||||
sticker = None
|
||||
try:
|
||||
for a in data["attachments"]:
|
||||
for a in data.get("attachments") or ():
|
||||
mercury = a["mercury"]
|
||||
if mercury.get("blob_attachment"):
|
||||
image_metadata = a.get("imageMetadata", {})
|
||||
attach_type = mercury["blob_attachment"]["__typename"]
|
||||
attachment = _file.graphql_to_attachment(
|
||||
mercury["blob_attachment"]
|
||||
mercury["blob_attachment"], a["fileSize"]
|
||||
)
|
||||
|
||||
if attach_type in [
|
||||
"MessageFile",
|
||||
"MessageVideo",
|
||||
"MessageAudio",
|
||||
]:
|
||||
# TODO: Add more data here for audio files
|
||||
attachment.size = int(a["fileSize"])
|
||||
rtn.attachments.append(attachment)
|
||||
attachments.append(attachment)
|
||||
|
||||
elif mercury.get("sticker_attachment"):
|
||||
rtn.sticker = _sticker.Sticker._from_graphql(
|
||||
sticker = _sticker.Sticker._from_graphql(
|
||||
mercury["sticker_attachment"]
|
||||
)
|
||||
|
||||
@@ -356,9 +351,9 @@ class Message:
|
||||
mercury["extensible_attachment"]
|
||||
)
|
||||
if isinstance(attachment, _attachment.UnsentMessage):
|
||||
rtn.unsent = True
|
||||
unsent = True
|
||||
elif attachment:
|
||||
rtn.attachments.append(attachment)
|
||||
attachments.append(attachment)
|
||||
|
||||
except Exception:
|
||||
log.exception(
|
||||
@@ -367,9 +362,18 @@ class Message:
|
||||
)
|
||||
)
|
||||
|
||||
rtn.emoji_size = EmojiSize._from_tags(tags)
|
||||
rtn.forwarded = cls._get_forwarded_from_tags(tags)
|
||||
return rtn
|
||||
return cls(
|
||||
text=data.get("body"),
|
||||
mentions=mentions,
|
||||
emoji_size=EmojiSize._from_tags(tags),
|
||||
uid=mid,
|
||||
author=author,
|
||||
created_at=created_at,
|
||||
sticker=sticker,
|
||||
attachments=attachments,
|
||||
unsent=unsent,
|
||||
forwarded=cls._get_forwarded_from_tags(tags),
|
||||
)
|
||||
|
||||
|
||||
def graphql_to_extensible_attachment(data):
|
||||
|
@@ -58,44 +58,41 @@ class Plan:
|
||||
|
||||
@classmethod
|
||||
def _from_pull(cls, data):
|
||||
rtn = cls(
|
||||
return cls(
|
||||
uid=data.get("event_id"),
|
||||
time=_util.seconds_to_datetime(int(data.get("event_time"))),
|
||||
title=data.get("event_title"),
|
||||
location=data.get("event_location_name"),
|
||||
location_id=data.get("event_location_id"),
|
||||
)
|
||||
rtn.uid = data.get("event_id")
|
||||
rtn.author_id = data.get("event_creator_id")
|
||||
rtn.guests = {
|
||||
author_id=data.get("event_creator_id"),
|
||||
guests={
|
||||
x["node"]["id"]: GuestStatus[x["guest_list_state"]]
|
||||
for x in json.loads(data["guest_state_list"])
|
||||
}
|
||||
return rtn
|
||||
},
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def _from_fetch(cls, data):
|
||||
rtn = cls(
|
||||
return cls(
|
||||
uid=data.get("oid"),
|
||||
time=_util.seconds_to_datetime(data.get("event_time")),
|
||||
title=data.get("title"),
|
||||
location=data.get("location_name"),
|
||||
location_id=str(data["location_id"]) if data.get("location_id") else None,
|
||||
author_id=data.get("creator_id"),
|
||||
guests={id_: GuestStatus[s] for id_, s in data["event_members"].items()},
|
||||
)
|
||||
rtn.uid = data.get("oid")
|
||||
rtn.author_id = data.get("creator_id")
|
||||
rtn.guests = {id_: GuestStatus[s] for id_, s in data["event_members"].items()}
|
||||
return rtn
|
||||
|
||||
@classmethod
|
||||
def _from_graphql(cls, data):
|
||||
rtn = cls(
|
||||
return cls(
|
||||
uid=data.get("id"),
|
||||
time=_util.seconds_to_datetime(data.get("time")),
|
||||
title=data.get("event_title"),
|
||||
location=data.get("location_name"),
|
||||
)
|
||||
rtn.uid = data.get("id")
|
||||
rtn.author_id = data["lightweight_event_creator"].get("id")
|
||||
rtn.guests = {
|
||||
author_id=data["lightweight_event_creator"].get("id"),
|
||||
guests={
|
||||
x["node"]["id"]: GuestStatus[x["guest_list_state"]]
|
||||
for x in data["event_reminder_members"]["edges"]
|
||||
}
|
||||
return rtn
|
||||
},
|
||||
)
|
||||
|
@@ -9,7 +9,7 @@ class QuickReply:
|
||||
#: Payload of the quick reply
|
||||
payload = attr.ib(None)
|
||||
#: External payload for responses
|
||||
external_payload = attr.ib(None, init=False)
|
||||
external_payload = attr.ib(None)
|
||||
#: Additional data
|
||||
data = attr.ib(None)
|
||||
#: Whether it's a response for a quick reply
|
||||
|
@@ -33,17 +33,20 @@ class Sticker(Attachment):
|
||||
def _from_graphql(cls, data):
|
||||
if not data:
|
||||
return None
|
||||
self = cls(uid=data["id"])
|
||||
if data.get("pack"):
|
||||
self.pack = data["pack"].get("id")
|
||||
if data.get("sprite_image"):
|
||||
self.is_animated = True
|
||||
self.medium_sprite_image = data["sprite_image"].get("uri")
|
||||
self.large_sprite_image = data["sprite_image_2x"].get("uri")
|
||||
self.frames_per_row = data.get("frames_per_row")
|
||||
self.frames_per_col = data.get("frames_per_column")
|
||||
self.frame_rate = data.get("frame_rate")
|
||||
self.image = Image._from_url_or_none(data)
|
||||
if data.get("label"):
|
||||
self.label = data["label"]
|
||||
return self
|
||||
|
||||
return cls(
|
||||
uid=data["id"],
|
||||
pack=data["pack"].get("id") if data.get("pack") else None,
|
||||
is_animated=bool(data.get("sprite_image")),
|
||||
medium_sprite_image=data["sprite_image"].get("uri")
|
||||
if data.get("sprite_image")
|
||||
else None,
|
||||
large_sprite_image=data["sprite_image_2x"].get("uri")
|
||||
if data.get("sprite_image_2x")
|
||||
else None,
|
||||
frames_per_row=data.get("frames_per_row"),
|
||||
frames_per_col=data.get("frames_per_column"),
|
||||
frame_rate=data.get("frame_rate"),
|
||||
image=Image._from_url_or_none(data),
|
||||
label=data["label"] if data.get("label") else None,
|
||||
)
|
||||
|
@@ -3,13 +3,16 @@ from fbchat._plan import GuestStatus, Plan
|
||||
|
||||
|
||||
def test_plan_properties():
|
||||
plan = Plan(time=..., title=...)
|
||||
plan.guests = {
|
||||
plan = Plan(
|
||||
time=...,
|
||||
title=...,
|
||||
guests={
|
||||
"1234": GuestStatus.INVITED,
|
||||
"2345": GuestStatus.INVITED,
|
||||
"3456": GuestStatus.GOING,
|
||||
"4567": GuestStatus.DECLINED,
|
||||
}
|
||||
},
|
||||
)
|
||||
assert set(plan.invited) == {"1234", "2345"}
|
||||
assert plan.going == ["3456"]
|
||||
assert plan.declined == ["4567"]
|
||||
@@ -32,19 +35,18 @@ def test_plan_from_pull():
|
||||
'{"guest_list_state":"GOING","node":{"id":"4567"}}]'
|
||||
),
|
||||
}
|
||||
plan = Plan(
|
||||
assert Plan(
|
||||
uid="1111",
|
||||
time=datetime.datetime(2017, 7, 14, 2, 40, tzinfo=datetime.timezone.utc),
|
||||
title="abc",
|
||||
)
|
||||
plan.uid = "1111"
|
||||
plan.author_id = "1234"
|
||||
plan.guests = {
|
||||
author_id="1234",
|
||||
guests={
|
||||
"1234": GuestStatus.INVITED,
|
||||
"2356": GuestStatus.INVITED,
|
||||
"3456": GuestStatus.DECLINED,
|
||||
"4567": GuestStatus.GOING,
|
||||
}
|
||||
assert plan == Plan._from_pull(data)
|
||||
},
|
||||
) == Plan._from_pull(data)
|
||||
|
||||
|
||||
def test_plan_from_fetch():
|
||||
@@ -90,21 +92,20 @@ def test_plan_from_fetch():
|
||||
"4567": "GOING",
|
||||
},
|
||||
}
|
||||
plan = Plan(
|
||||
assert Plan(
|
||||
uid=1111,
|
||||
time=datetime.datetime(2017, 7, 14, 2, 40, tzinfo=datetime.timezone.utc),
|
||||
title="abc",
|
||||
location="",
|
||||
location_id="",
|
||||
)
|
||||
plan.uid = 1111
|
||||
plan.author_id = 1234
|
||||
plan.guests = {
|
||||
author_id=1234,
|
||||
guests={
|
||||
"1234": GuestStatus.INVITED,
|
||||
"2356": GuestStatus.INVITED,
|
||||
"3456": GuestStatus.DECLINED,
|
||||
"4567": GuestStatus.GOING,
|
||||
}
|
||||
assert plan == Plan._from_fetch(data)
|
||||
},
|
||||
) == Plan._from_fetch(data)
|
||||
|
||||
|
||||
def test_plan_from_graphql():
|
||||
@@ -133,18 +134,17 @@ def test_plan_from_graphql():
|
||||
]
|
||||
},
|
||||
}
|
||||
plan = Plan(
|
||||
assert Plan(
|
||||
time=datetime.datetime(2017, 7, 14, 2, 40, tzinfo=datetime.timezone.utc),
|
||||
title="abc",
|
||||
location="",
|
||||
location_id="",
|
||||
)
|
||||
plan.uid = "1111"
|
||||
plan.author_id = "1234"
|
||||
plan.guests = {
|
||||
uid="1111",
|
||||
author_id="1234",
|
||||
guests={
|
||||
"1234": GuestStatus.INVITED,
|
||||
"2356": GuestStatus.INVITED,
|
||||
"3456": GuestStatus.DECLINED,
|
||||
"4567": GuestStatus.GOING,
|
||||
}
|
||||
assert plan == Plan._from_graphql(data)
|
||||
},
|
||||
) == Plan._from_graphql(data)
|
||||
|
@@ -16,11 +16,9 @@ def test_from_graphql_normal():
|
||||
uid="369239383222810",
|
||||
pack="227877430692340",
|
||||
is_animated=False,
|
||||
medium_sprite_image=None,
|
||||
large_sprite_image=None,
|
||||
frames_per_row=None,
|
||||
frames_per_col=None,
|
||||
frame_rate=None,
|
||||
frames_per_row=1,
|
||||
frames_per_col=1,
|
||||
frame_rate=83,
|
||||
image=fbchat.Image(
|
||||
url="https://scontent-arn2-1.xx.fbcdn.net/v/redacted.png",
|
||||
width=274,
|
||||
|
Reference in New Issue
Block a user