Add Image model

This commit is contained in:
Mads Marquart
2019-10-28 11:21:46 +01:00
parent 074c271fb8
commit 637ea97ffe
16 changed files with 207 additions and 276 deletions

View File

@@ -11,6 +11,7 @@ _logging.getLogger(__name__).addHandler(_logging.NullHandler())
# The order of these is somewhat significant, e.g. User has to be imported after Thread!
from . import _core, _util
from ._core import Image
from ._exception import FBchatException, FBchatFacebookError
from ._thread import ThreadType, ThreadLocation, ThreadColor, Thread
from ._user import TypingStatus, User, ActiveStatus

View File

@@ -1,4 +1,5 @@
import attr
from ._core import Image
from . import _util
@@ -31,14 +32,10 @@ class ShareAttachment(Attachment):
description = attr.ib(None)
#: Name of the source
source = attr.ib(None)
#: URL of the attachment image
image_url = attr.ib(None)
#: The attached image
image = attr.ib(None)
#: URL of the original image if Facebook uses ``safe_image``
original_image_url = attr.ib(None)
#: Width of the image
image_width = attr.ib(None)
#: Height of the image
image_height = attr.ib(None)
#: List of additional attachments
attachments = attr.ib(factory=list, converter=lambda x: [] if x is None else x)
@@ -72,12 +69,10 @@ class ShareAttachment(Attachment):
media = data.get("media")
if media and media.get("image"):
image = media["image"]
rtn.image_url = image.get("uri")
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
_util.get_url_parameter(rtn.image.url, "url")
if "/safe_image.php" in rtn.image.url
else rtn.image.url
)
rtn.image_width = image.get("width")
rtn.image_height = image.get("height")
return rtn

View File

@@ -1,3 +1,4 @@
import attr
import logging
import aenum
@@ -21,3 +22,45 @@ class Enum(aenum.Enum):
)
aenum.extend_enum(cls, "UNKNOWN_{}".format(value).upper(), value)
return cls(value)
@attr.s(frozen=True, slots=True) # TODO: Add kw_only=True
class Image:
#: URL to the image
url = attr.ib(type=str)
#: Width of the image
width = attr.ib(None, type=int)
#: Height of the image
height = attr.ib(None, type=int)
@classmethod
def _from_uri(cls, data):
return cls(
url=data["uri"],
width=int(data["width"]) if data.get("width") else None,
height=int(data["height"]) if data.get("height") else None,
)
@classmethod
def _from_url(cls, data):
return cls(
url=data["url"],
width=int(data["width"]) if data.get("width") else None,
height=int(data["height"]) if data.get("height") else None,
)
@classmethod
def _from_uri_or_none(cls, data):
if data is None:
return None
if data.get("uri") is None:
return None
return cls._from_uri(data)
@classmethod
def _from_url_or_none(cls, data):
if data is None:
return None
if data.get("url") is None:
return None
return cls._from_url(data)

View File

@@ -1,4 +1,5 @@
import attr
from ._core import Image
from . import _util
from ._attachment import Attachment
@@ -55,7 +56,7 @@ class AudioAttachment(Attachment):
)
@attr.s(init=False)
@attr.s
class ImageAttachment(Attachment):
"""Represents an image that has been sent as a Facebook attachment.
@@ -73,70 +74,14 @@ class ImageAttachment(Attachment):
#: Whether the image is animated
is_animated = attr.ib(None)
#: URL to a thumbnail of the image
thumbnail_url = attr.ib(None)
#: URL to a medium preview of the image
preview_url = attr.ib(None)
#: Width of the medium preview image
preview_width = attr.ib(None)
#: Height of the medium preview image
preview_height = attr.ib(None)
#: URL to a large preview of the image
large_preview_url = attr.ib(None)
#: Width of the large preview image
large_preview_width = attr.ib(None)
#: Height of the large preview image
large_preview_height = attr.ib(None)
#: URL to an animated preview of the image (e.g. for GIFs)
animated_preview_url = attr.ib(None)
#: Width of the animated preview image
animated_preview_width = attr.ib(None)
#: Height of the animated preview image
animated_preview_height = attr.ib(None)
def __init__(
self,
original_extension=None,
width=None,
height=None,
is_animated=None,
thumbnail_url=None,
preview=None,
large_preview=None,
animated_preview=None,
**kwargs
):
super(ImageAttachment, self).__init__(**kwargs)
self.original_extension = original_extension
if width is not None:
width = int(width)
self.width = width
if height is not None:
height = int(height)
self.height = height
self.is_animated = is_animated
self.thumbnail_url = thumbnail_url
if preview is None:
preview = {}
self.preview_url = preview.get("uri")
self.preview_width = preview.get("width")
self.preview_height = preview.get("height")
if large_preview is None:
large_preview = {}
self.large_preview_url = large_preview.get("uri")
self.large_preview_width = large_preview.get("width")
self.large_preview_height = large_preview.get("height")
if animated_preview is None:
animated_preview = {}
self.animated_preview_url = animated_preview.get("uri")
self.animated_preview_width = animated_preview.get("width")
self.animated_preview_height = animated_preview.get("height")
#: A thumbnail of the image
thumbnail = attr.ib(None)
#: A medium preview of the image
preview = attr.ib(None)
#: A large preview of the image
large_preview = attr.ib(None)
#: An animated preview of the image (e.g. for GIFs)
animated_preview = attr.ib(None)
@classmethod
def _from_graphql(cls, data):
@@ -146,10 +91,12 @@ class ImageAttachment(Attachment):
width=data.get("original_dimensions", {}).get("width"),
height=data.get("original_dimensions", {}).get("height"),
is_animated=data["__typename"] == "MessageAnimatedImage",
thumbnail_url=data.get("thumbnail", {}).get("uri"),
preview=data.get("preview") or data.get("preview_image"),
large_preview=data.get("large_preview"),
animated_preview=data.get("animated_image"),
thumbnail=Image._from_uri_or_none(data.get("thumbnail")),
preview=Image._from_uri_or_none(
data.get("preview") or data.get("preview_image")
),
large_preview=Image._from_uri_or_none(data.get("large_preview")),
animated_preview=Image._from_uri_or_none(data.get("animated_image")),
uid=data.get("legacy_attachment_id"),
)
@@ -159,14 +106,14 @@ class ImageAttachment(Attachment):
return cls(
width=data["original_dimensions"].get("x"),
height=data["original_dimensions"].get("y"),
thumbnail_url=data["image"].get("uri"),
large_preview=data["image2"],
preview=data["image1"],
thumbnail=Image._from_uri_or_none(data["image"]),
large_preview=Image._from_uri(data["image2"]),
preview=Image._from_uri(data["image1"]),
uid=data["legacy_attachment_id"],
)
@attr.s(init=False)
@attr.s
class VideoAttachment(Attachment):
"""Represents a video that has been sent as a Facebook attachment."""
@@ -181,63 +128,12 @@ class VideoAttachment(Attachment):
#: URL to very compressed preview video
preview_url = attr.ib(None)
#: URL to a small preview image of the video
small_image_url = attr.ib(None)
#: Width of the small preview image
small_image_width = attr.ib(None)
#: Height of the small preview image
small_image_height = attr.ib(None)
#: URL to a medium preview image of the video
medium_image_url = attr.ib(None)
#: Width of the medium preview image
medium_image_width = attr.ib(None)
#: Height of the medium preview image
medium_image_height = attr.ib(None)
#: URL to a large preview image of the video
large_image_url = attr.ib(None)
#: Width of the large preview image
large_image_width = attr.ib(None)
#: Height of the large preview image
large_image_height = attr.ib(None)
def __init__(
self,
size=None,
width=None,
height=None,
duration=None,
preview_url=None,
small_image=None,
medium_image=None,
large_image=None,
**kwargs
):
super(VideoAttachment, self).__init__(**kwargs)
self.size = size
self.width = width
self.height = height
self.duration = duration
self.preview_url = preview_url
if small_image is None:
small_image = {}
self.small_image_url = small_image.get("uri")
self.small_image_width = small_image.get("width")
self.small_image_height = small_image.get("height")
if medium_image is None:
medium_image = {}
self.medium_image_url = medium_image.get("uri")
self.medium_image_width = medium_image.get("width")
self.medium_image_height = medium_image.get("height")
if large_image is None:
large_image = {}
self.large_image_url = large_image.get("uri")
self.large_image_width = large_image.get("width")
self.large_image_height = large_image.get("height")
#: A small preview image of the video
small_image = attr.ib(None)
#: A medium preview image of the video
medium_image = attr.ib(None)
#: A large preview image of the video
large_image = attr.ib(None)
@classmethod
def _from_graphql(cls, data):
@@ -246,9 +142,9 @@ class VideoAttachment(Attachment):
height=data.get("original_dimensions", {}).get("height"),
duration=_util.millis_to_timedelta(data.get("playable_duration_in_ms")),
preview_url=data.get("playable_url"),
small_image=data.get("chat_image"),
medium_image=data.get("inbox_image"),
large_image=data.get("large_image"),
small_image=Image._from_uri_or_none(data.get("chat_image")),
medium_image=Image._from_uri_or_none(data.get("inbox_image")),
large_image=Image._from_uri_or_none(data.get("large_image")),
uid=data.get("legacy_attachment_id"),
)
@@ -258,7 +154,7 @@ class VideoAttachment(Attachment):
return cls(
duration=_util.millis_to_timedelta(media.get("playable_duration_in_ms")),
preview_url=media.get("playable_url"),
medium_image=media.get("image"),
medium_image=Image._from_uri_or_none(media.get("image")),
uid=data["target"].get("video_id"),
)
@@ -268,9 +164,9 @@ class VideoAttachment(Attachment):
return cls(
width=data["original_dimensions"].get("x"),
height=data["original_dimensions"].get("y"),
small_image=data["image"],
medium_image=data["image1"],
large_image=data["image2"],
small_image=Image._from_uri(data["image"]),
medium_image=Image._from_uri(data["image1"]),
large_image=Image._from_uri(data["image2"]),
uid=data["legacy_attachment_id"],
)

View File

@@ -1,4 +1,5 @@
import attr
from ._core import Image
from . import _util, _plan
from ._thread import ThreadType, Thread
@@ -64,7 +65,7 @@ class Group(Thread):
if data.get("group_approval_queue")
else None,
join_link=data["joinable_mode"].get("link"),
photo=data["image"].get("uri"),
photo=Image._from_uri_or_none(data["image"]),
name=data.get("name"),
message_count=data.get("messages_count"),
last_active=last_active,

View File

@@ -1,4 +1,5 @@
import attr
from ._core import Image
from ._attachment import Attachment
from . import _util
@@ -14,12 +15,8 @@ class LocationAttachment(Attachment):
latitude = attr.ib(None)
#: Longitude of the location
longitude = attr.ib(None)
#: URL of image showing the map of the location
image_url = attr.ib(None, init=False)
#: Width of the image
image_width = attr.ib(None, init=False)
#: Height of the image
image_height = attr.ib(None, init=False)
#: Image showing the map of the location
image = attr.ib(None, init=False)
#: URL to Bing maps with the location
url = attr.ib(None, init=False)
# Address of the location
@@ -45,10 +42,7 @@ class LocationAttachment(Attachment):
)
media = data.get("media")
if media and media.get("image"):
image = media["image"]
rtn.image_url = image.get("uri")
rtn.image_width = image.get("width")
rtn.image_height = image.get("height")
rtn.image = Image._from_uri(media["image"])
rtn.url = url
return rtn
@@ -96,9 +90,6 @@ class LiveLocationAttachment(LocationAttachment):
)
media = data.get("media")
if media and media.get("image"):
image = media["image"]
rtn.image_url = image.get("uri")
rtn.image_width = image.get("width")
rtn.image_height = image.get("height")
rtn.image = Image._from_uri(media["image"])
rtn.url = data.get("url")
return rtn

View File

@@ -1,4 +1,5 @@
import attr
from ._core import Image
from . import _plan
from ._thread import ThreadType, Thread
@@ -35,7 +36,7 @@ class Page(Thread):
url=data.get("url"),
city=data.get("city").get("name"),
category=data.get("category_type"),
photo=data["profile_picture"].get("uri"),
photo=Image._from_uri(data["profile_picture"]),
name=data.get("name"),
message_count=data.get("messages_count"),
plan=plan,

View File

@@ -1,4 +1,5 @@
import attr
from ._core import Image
from ._attachment import Attachment
@@ -23,12 +24,8 @@ class Sticker(Attachment):
#: The frame rate the spritemap is intended to be played in
frame_rate = attr.ib(None)
#: URL to the sticker's image
url = attr.ib(None)
#: Width of the sticker
width = attr.ib(None)
#: Height of the sticker
height = attr.ib(None)
#: The sticker's image
image = attr.ib(None)
#: The sticker's label/name
label = attr.ib(None)
@@ -46,9 +43,7 @@ class Sticker(Attachment):
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.url = data.get("url")
self.width = data.get("width")
self.height = data.get("height")
self.image = Image._from_url_or_none(data)
if data.get("label"):
self.label = data["label"]
return self

View File

@@ -1,5 +1,5 @@
import attr
from ._core import Enum
from ._core import Enum, Image
class ThreadType(Enum):
@@ -75,7 +75,7 @@ class Thread:
uid = attr.ib(converter=str)
#: Specifies the type of thread. Can be used a ``thread_type``. See :ref:`intro_threads` for more info
type = None
#: A URL to the thread's picture
#: The thread's picture
photo = attr.ib(None)
#: The name of the thread
name = attr.ib(None)

View File

@@ -1,5 +1,5 @@
import attr
from ._core import Enum
from ._core import Enum, Image
from . import _util, _plan
from ._thread import ThreadType, Thread
@@ -89,7 +89,7 @@ class User(Thread):
color=c_info.get("color"),
emoji=c_info.get("emoji"),
own_nickname=c_info.get("own_nickname"),
photo=data["profile_picture"].get("uri"),
photo=Image._from_uri(data["profile_picture"]),
name=data.get("name"),
message_count=data.get("messages_count"),
plan=plan,
@@ -135,7 +135,7 @@ class User(Thread):
color=c_info.get("color"),
emoji=c_info.get("emoji"),
own_nickname=c_info.get("own_nickname"),
photo=user["big_image_src"].get("uri"),
photo=Image._from_uri(user["big_image_src"]),
message_count=data.get("messages_count"),
last_active=last_active,
plan=plan,
@@ -147,7 +147,7 @@ class User(Thread):
data["id"],
first_name=data.get("firstName"),
url=data.get("uri"),
photo=data.get("thumbSrc"),
photo=Image(url=data.get("thumbSrc")),
name=data.get("name"),
is_friend=data.get("is_friend"),
gender=GENDERS.get(data.get("gender")),