Add Image model
This commit is contained in:
@@ -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!
|
# The order of these is somewhat significant, e.g. User has to be imported after Thread!
|
||||||
from . import _core, _util
|
from . import _core, _util
|
||||||
|
from ._core import Image
|
||||||
from ._exception import FBchatException, FBchatFacebookError
|
from ._exception import FBchatException, FBchatFacebookError
|
||||||
from ._thread import ThreadType, ThreadLocation, ThreadColor, Thread
|
from ._thread import ThreadType, ThreadLocation, ThreadColor, Thread
|
||||||
from ._user import TypingStatus, User, ActiveStatus
|
from ._user import TypingStatus, User, ActiveStatus
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
import attr
|
import attr
|
||||||
|
from ._core import Image
|
||||||
from . import _util
|
from . import _util
|
||||||
|
|
||||||
|
|
||||||
@@ -31,14 +32,10 @@ class ShareAttachment(Attachment):
|
|||||||
description = attr.ib(None)
|
description = attr.ib(None)
|
||||||
#: Name of the source
|
#: Name of the source
|
||||||
source = attr.ib(None)
|
source = attr.ib(None)
|
||||||
#: URL of the attachment image
|
#: The attached image
|
||||||
image_url = attr.ib(None)
|
image = attr.ib(None)
|
||||||
#: URL of the original image if Facebook uses ``safe_image``
|
#: URL of the original image if Facebook uses ``safe_image``
|
||||||
original_image_url = attr.ib(None)
|
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
|
#: List of additional attachments
|
||||||
attachments = attr.ib(factory=list, converter=lambda x: [] if x is None else x)
|
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")
|
media = data.get("media")
|
||||||
if media and media.get("image"):
|
if media and media.get("image"):
|
||||||
image = media["image"]
|
image = media["image"]
|
||||||
rtn.image_url = image.get("uri")
|
rtn.image = Image._from_uri(image)
|
||||||
rtn.original_image_url = (
|
rtn.original_image_url = (
|
||||||
_util.get_url_parameter(rtn.image_url, "url")
|
_util.get_url_parameter(rtn.image.url, "url")
|
||||||
if "/safe_image.php" in rtn.image_url
|
if "/safe_image.php" in rtn.image.url
|
||||||
else rtn.image_url
|
else rtn.image.url
|
||||||
)
|
)
|
||||||
rtn.image_width = image.get("width")
|
|
||||||
rtn.image_height = image.get("height")
|
|
||||||
return rtn
|
return rtn
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
import attr
|
||||||
import logging
|
import logging
|
||||||
import aenum
|
import aenum
|
||||||
|
|
||||||
@@ -21,3 +22,45 @@ class Enum(aenum.Enum):
|
|||||||
)
|
)
|
||||||
aenum.extend_enum(cls, "UNKNOWN_{}".format(value).upper(), value)
|
aenum.extend_enum(cls, "UNKNOWN_{}".format(value).upper(), value)
|
||||||
return cls(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)
|
||||||
|
170
fbchat/_file.py
170
fbchat/_file.py
@@ -1,4 +1,5 @@
|
|||||||
import attr
|
import attr
|
||||||
|
from ._core import Image
|
||||||
from . import _util
|
from . import _util
|
||||||
from ._attachment import Attachment
|
from ._attachment import Attachment
|
||||||
|
|
||||||
@@ -55,7 +56,7 @@ class AudioAttachment(Attachment):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@attr.s(init=False)
|
@attr.s
|
||||||
class ImageAttachment(Attachment):
|
class ImageAttachment(Attachment):
|
||||||
"""Represents an image that has been sent as a Facebook attachment.
|
"""Represents an image that has been sent as a Facebook attachment.
|
||||||
|
|
||||||
@@ -73,70 +74,14 @@ class ImageAttachment(Attachment):
|
|||||||
#: Whether the image is animated
|
#: Whether the image is animated
|
||||||
is_animated = attr.ib(None)
|
is_animated = attr.ib(None)
|
||||||
|
|
||||||
#: URL to a thumbnail of the image
|
#: A thumbnail of the image
|
||||||
thumbnail_url = attr.ib(None)
|
thumbnail = attr.ib(None)
|
||||||
|
#: A medium preview of the image
|
||||||
#: URL to a medium preview of the image
|
preview = attr.ib(None)
|
||||||
preview_url = attr.ib(None)
|
#: A large preview of the image
|
||||||
#: Width of the medium preview image
|
large_preview = attr.ib(None)
|
||||||
preview_width = attr.ib(None)
|
#: An animated preview of the image (e.g. for GIFs)
|
||||||
#: Height of the medium preview image
|
animated_preview = attr.ib(None)
|
||||||
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")
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _from_graphql(cls, data):
|
def _from_graphql(cls, data):
|
||||||
@@ -146,10 +91,12 @@ class ImageAttachment(Attachment):
|
|||||||
width=data.get("original_dimensions", {}).get("width"),
|
width=data.get("original_dimensions", {}).get("width"),
|
||||||
height=data.get("original_dimensions", {}).get("height"),
|
height=data.get("original_dimensions", {}).get("height"),
|
||||||
is_animated=data["__typename"] == "MessageAnimatedImage",
|
is_animated=data["__typename"] == "MessageAnimatedImage",
|
||||||
thumbnail_url=data.get("thumbnail", {}).get("uri"),
|
thumbnail=Image._from_uri_or_none(data.get("thumbnail")),
|
||||||
preview=data.get("preview") or data.get("preview_image"),
|
preview=Image._from_uri_or_none(
|
||||||
large_preview=data.get("large_preview"),
|
data.get("preview") or data.get("preview_image")
|
||||||
animated_preview=data.get("animated_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"),
|
uid=data.get("legacy_attachment_id"),
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -159,14 +106,14 @@ class ImageAttachment(Attachment):
|
|||||||
return cls(
|
return cls(
|
||||||
width=data["original_dimensions"].get("x"),
|
width=data["original_dimensions"].get("x"),
|
||||||
height=data["original_dimensions"].get("y"),
|
height=data["original_dimensions"].get("y"),
|
||||||
thumbnail_url=data["image"].get("uri"),
|
thumbnail=Image._from_uri_or_none(data["image"]),
|
||||||
large_preview=data["image2"],
|
large_preview=Image._from_uri(data["image2"]),
|
||||||
preview=data["image1"],
|
preview=Image._from_uri(data["image1"]),
|
||||||
uid=data["legacy_attachment_id"],
|
uid=data["legacy_attachment_id"],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@attr.s(init=False)
|
@attr.s
|
||||||
class VideoAttachment(Attachment):
|
class VideoAttachment(Attachment):
|
||||||
"""Represents a video that has been sent as a Facebook 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
|
#: URL to very compressed preview video
|
||||||
preview_url = attr.ib(None)
|
preview_url = attr.ib(None)
|
||||||
|
|
||||||
#: URL to a small preview image of the video
|
#: A small preview image of the video
|
||||||
small_image_url = attr.ib(None)
|
small_image = attr.ib(None)
|
||||||
#: Width of the small preview image
|
#: A medium preview image of the video
|
||||||
small_image_width = attr.ib(None)
|
medium_image = attr.ib(None)
|
||||||
#: Height of the small preview image
|
#: A large preview image of the video
|
||||||
small_image_height = attr.ib(None)
|
large_image = 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")
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _from_graphql(cls, data):
|
def _from_graphql(cls, data):
|
||||||
@@ -246,9 +142,9 @@ class VideoAttachment(Attachment):
|
|||||||
height=data.get("original_dimensions", {}).get("height"),
|
height=data.get("original_dimensions", {}).get("height"),
|
||||||
duration=_util.millis_to_timedelta(data.get("playable_duration_in_ms")),
|
duration=_util.millis_to_timedelta(data.get("playable_duration_in_ms")),
|
||||||
preview_url=data.get("playable_url"),
|
preview_url=data.get("playable_url"),
|
||||||
small_image=data.get("chat_image"),
|
small_image=Image._from_uri_or_none(data.get("chat_image")),
|
||||||
medium_image=data.get("inbox_image"),
|
medium_image=Image._from_uri_or_none(data.get("inbox_image")),
|
||||||
large_image=data.get("large_image"),
|
large_image=Image._from_uri_or_none(data.get("large_image")),
|
||||||
uid=data.get("legacy_attachment_id"),
|
uid=data.get("legacy_attachment_id"),
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -258,7 +154,7 @@ class VideoAttachment(Attachment):
|
|||||||
return cls(
|
return cls(
|
||||||
duration=_util.millis_to_timedelta(media.get("playable_duration_in_ms")),
|
duration=_util.millis_to_timedelta(media.get("playable_duration_in_ms")),
|
||||||
preview_url=media.get("playable_url"),
|
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"),
|
uid=data["target"].get("video_id"),
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -268,9 +164,9 @@ class VideoAttachment(Attachment):
|
|||||||
return cls(
|
return cls(
|
||||||
width=data["original_dimensions"].get("x"),
|
width=data["original_dimensions"].get("x"),
|
||||||
height=data["original_dimensions"].get("y"),
|
height=data["original_dimensions"].get("y"),
|
||||||
small_image=data["image"],
|
small_image=Image._from_uri(data["image"]),
|
||||||
medium_image=data["image1"],
|
medium_image=Image._from_uri(data["image1"]),
|
||||||
large_image=data["image2"],
|
large_image=Image._from_uri(data["image2"]),
|
||||||
uid=data["legacy_attachment_id"],
|
uid=data["legacy_attachment_id"],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
import attr
|
import attr
|
||||||
|
from ._core import Image
|
||||||
from . import _util, _plan
|
from . import _util, _plan
|
||||||
from ._thread import ThreadType, Thread
|
from ._thread import ThreadType, Thread
|
||||||
|
|
||||||
@@ -64,7 +65,7 @@ class Group(Thread):
|
|||||||
if data.get("group_approval_queue")
|
if data.get("group_approval_queue")
|
||||||
else None,
|
else None,
|
||||||
join_link=data["joinable_mode"].get("link"),
|
join_link=data["joinable_mode"].get("link"),
|
||||||
photo=data["image"].get("uri"),
|
photo=Image._from_uri_or_none(data["image"]),
|
||||||
name=data.get("name"),
|
name=data.get("name"),
|
||||||
message_count=data.get("messages_count"),
|
message_count=data.get("messages_count"),
|
||||||
last_active=last_active,
|
last_active=last_active,
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
import attr
|
import attr
|
||||||
|
from ._core import Image
|
||||||
from ._attachment import Attachment
|
from ._attachment import Attachment
|
||||||
from . import _util
|
from . import _util
|
||||||
|
|
||||||
@@ -14,12 +15,8 @@ class LocationAttachment(Attachment):
|
|||||||
latitude = attr.ib(None)
|
latitude = attr.ib(None)
|
||||||
#: Longitude of the location
|
#: Longitude of the location
|
||||||
longitude = attr.ib(None)
|
longitude = attr.ib(None)
|
||||||
#: URL of image showing the map of the location
|
#: Image showing the map of the location
|
||||||
image_url = attr.ib(None, init=False)
|
image = 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)
|
|
||||||
#: URL to Bing maps with the location
|
#: URL to Bing maps with the location
|
||||||
url = attr.ib(None, init=False)
|
url = attr.ib(None, init=False)
|
||||||
# Address of the location
|
# Address of the location
|
||||||
@@ -45,10 +42,7 @@ class LocationAttachment(Attachment):
|
|||||||
)
|
)
|
||||||
media = data.get("media")
|
media = data.get("media")
|
||||||
if media and media.get("image"):
|
if media and media.get("image"):
|
||||||
image = media["image"]
|
rtn.image = Image._from_uri(media["image"])
|
||||||
rtn.image_url = image.get("uri")
|
|
||||||
rtn.image_width = image.get("width")
|
|
||||||
rtn.image_height = image.get("height")
|
|
||||||
rtn.url = url
|
rtn.url = url
|
||||||
return rtn
|
return rtn
|
||||||
|
|
||||||
@@ -96,9 +90,6 @@ class LiveLocationAttachment(LocationAttachment):
|
|||||||
)
|
)
|
||||||
media = data.get("media")
|
media = data.get("media")
|
||||||
if media and media.get("image"):
|
if media and media.get("image"):
|
||||||
image = media["image"]
|
rtn.image = Image._from_uri(media["image"])
|
||||||
rtn.image_url = image.get("uri")
|
|
||||||
rtn.image_width = image.get("width")
|
|
||||||
rtn.image_height = image.get("height")
|
|
||||||
rtn.url = data.get("url")
|
rtn.url = data.get("url")
|
||||||
return rtn
|
return rtn
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
import attr
|
import attr
|
||||||
|
from ._core import Image
|
||||||
from . import _plan
|
from . import _plan
|
||||||
from ._thread import ThreadType, Thread
|
from ._thread import ThreadType, Thread
|
||||||
|
|
||||||
@@ -35,7 +36,7 @@ class Page(Thread):
|
|||||||
url=data.get("url"),
|
url=data.get("url"),
|
||||||
city=data.get("city").get("name"),
|
city=data.get("city").get("name"),
|
||||||
category=data.get("category_type"),
|
category=data.get("category_type"),
|
||||||
photo=data["profile_picture"].get("uri"),
|
photo=Image._from_uri(data["profile_picture"]),
|
||||||
name=data.get("name"),
|
name=data.get("name"),
|
||||||
message_count=data.get("messages_count"),
|
message_count=data.get("messages_count"),
|
||||||
plan=plan,
|
plan=plan,
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
import attr
|
import attr
|
||||||
|
from ._core import Image
|
||||||
from ._attachment import Attachment
|
from ._attachment import Attachment
|
||||||
|
|
||||||
|
|
||||||
@@ -23,12 +24,8 @@ class Sticker(Attachment):
|
|||||||
#: The frame rate the spritemap is intended to be played in
|
#: The frame rate the spritemap is intended to be played in
|
||||||
frame_rate = attr.ib(None)
|
frame_rate = attr.ib(None)
|
||||||
|
|
||||||
#: URL to the sticker's image
|
#: The sticker's image
|
||||||
url = attr.ib(None)
|
image = attr.ib(None)
|
||||||
#: Width of the sticker
|
|
||||||
width = attr.ib(None)
|
|
||||||
#: Height of the sticker
|
|
||||||
height = attr.ib(None)
|
|
||||||
#: The sticker's label/name
|
#: The sticker's label/name
|
||||||
label = attr.ib(None)
|
label = attr.ib(None)
|
||||||
|
|
||||||
@@ -46,9 +43,7 @@ class Sticker(Attachment):
|
|||||||
self.frames_per_row = data.get("frames_per_row")
|
self.frames_per_row = data.get("frames_per_row")
|
||||||
self.frames_per_col = data.get("frames_per_column")
|
self.frames_per_col = data.get("frames_per_column")
|
||||||
self.frame_rate = data.get("frame_rate")
|
self.frame_rate = data.get("frame_rate")
|
||||||
self.url = data.get("url")
|
self.image = Image._from_url_or_none(data)
|
||||||
self.width = data.get("width")
|
|
||||||
self.height = data.get("height")
|
|
||||||
if data.get("label"):
|
if data.get("label"):
|
||||||
self.label = data["label"]
|
self.label = data["label"]
|
||||||
return self
|
return self
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import attr
|
import attr
|
||||||
from ._core import Enum
|
from ._core import Enum, Image
|
||||||
|
|
||||||
|
|
||||||
class ThreadType(Enum):
|
class ThreadType(Enum):
|
||||||
@@ -75,7 +75,7 @@ class Thread:
|
|||||||
uid = attr.ib(converter=str)
|
uid = attr.ib(converter=str)
|
||||||
#: Specifies the type of thread. Can be used a ``thread_type``. See :ref:`intro_threads` for more info
|
#: Specifies the type of thread. Can be used a ``thread_type``. See :ref:`intro_threads` for more info
|
||||||
type = None
|
type = None
|
||||||
#: A URL to the thread's picture
|
#: The thread's picture
|
||||||
photo = attr.ib(None)
|
photo = attr.ib(None)
|
||||||
#: The name of the thread
|
#: The name of the thread
|
||||||
name = attr.ib(None)
|
name = attr.ib(None)
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import attr
|
import attr
|
||||||
from ._core import Enum
|
from ._core import Enum, Image
|
||||||
from . import _util, _plan
|
from . import _util, _plan
|
||||||
from ._thread import ThreadType, Thread
|
from ._thread import ThreadType, Thread
|
||||||
|
|
||||||
@@ -89,7 +89,7 @@ class User(Thread):
|
|||||||
color=c_info.get("color"),
|
color=c_info.get("color"),
|
||||||
emoji=c_info.get("emoji"),
|
emoji=c_info.get("emoji"),
|
||||||
own_nickname=c_info.get("own_nickname"),
|
own_nickname=c_info.get("own_nickname"),
|
||||||
photo=data["profile_picture"].get("uri"),
|
photo=Image._from_uri(data["profile_picture"]),
|
||||||
name=data.get("name"),
|
name=data.get("name"),
|
||||||
message_count=data.get("messages_count"),
|
message_count=data.get("messages_count"),
|
||||||
plan=plan,
|
plan=plan,
|
||||||
@@ -135,7 +135,7 @@ class User(Thread):
|
|||||||
color=c_info.get("color"),
|
color=c_info.get("color"),
|
||||||
emoji=c_info.get("emoji"),
|
emoji=c_info.get("emoji"),
|
||||||
own_nickname=c_info.get("own_nickname"),
|
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"),
|
message_count=data.get("messages_count"),
|
||||||
last_active=last_active,
|
last_active=last_active,
|
||||||
plan=plan,
|
plan=plan,
|
||||||
@@ -147,7 +147,7 @@ class User(Thread):
|
|||||||
data["id"],
|
data["id"],
|
||||||
first_name=data.get("firstName"),
|
first_name=data.get("firstName"),
|
||||||
url=data.get("uri"),
|
url=data.get("uri"),
|
||||||
photo=data.get("thumbSrc"),
|
photo=Image(url=data.get("thumbSrc")),
|
||||||
name=data.get("name"),
|
name=data.get("name"),
|
||||||
is_friend=data.get("is_friend"),
|
is_friend=data.get("is_friend"),
|
||||||
gender=GENDERS.get(data.get("gender")),
|
gender=GENDERS.get(data.get("gender")),
|
||||||
|
@@ -72,10 +72,8 @@ def test_share_from_graphql_link():
|
|||||||
title="a.com",
|
title="a.com",
|
||||||
description="",
|
description="",
|
||||||
source="a.com",
|
source="a.com",
|
||||||
image_url=None,
|
image=None,
|
||||||
original_image_url=None,
|
original_image_url=None,
|
||||||
image_width=None,
|
|
||||||
image_height=None,
|
|
||||||
attachments=[],
|
attachments=[],
|
||||||
uid="ee.mid.$xyz",
|
uid="ee.mid.$xyz",
|
||||||
) == ShareAttachment._from_graphql(data)
|
) == ShareAttachment._from_graphql(data)
|
||||||
@@ -125,10 +123,10 @@ def test_share_from_graphql_link_with_image():
|
|||||||
" Share photos and videos, send messages and get updates."
|
" Share photos and videos, send messages and get updates."
|
||||||
),
|
),
|
||||||
source=None,
|
source=None,
|
||||||
image_url="https://www.facebook.com/rsrc.php/v3/x.png",
|
image=fbchat.Image(
|
||||||
|
url="https://www.facebook.com/rsrc.php/v3/x.png", width=325, height=325
|
||||||
|
),
|
||||||
original_image_url="https://www.facebook.com/rsrc.php/v3/x.png",
|
original_image_url="https://www.facebook.com/rsrc.php/v3/x.png",
|
||||||
image_width=325,
|
|
||||||
image_height=325,
|
|
||||||
attachments=[],
|
attachments=[],
|
||||||
uid="deadbeef123",
|
uid="deadbeef123",
|
||||||
) == ShareAttachment._from_graphql(data)
|
) == ShareAttachment._from_graphql(data)
|
||||||
@@ -187,14 +185,14 @@ def test_share_from_graphql_video():
|
|||||||
" Subscribe to the official Rick As..."
|
" Subscribe to the official Rick As..."
|
||||||
),
|
),
|
||||||
source="youtube.com",
|
source="youtube.com",
|
||||||
image_url=(
|
image=fbchat.Image(
|
||||||
"https://external-arn2-1.xx.fbcdn.net/safe_image.php?d=xyz123"
|
url="https://external-arn2-1.xx.fbcdn.net/safe_image.php?d=xyz123"
|
||||||
"&w=960&h=540&url=https%3A%2F%2Fi.ytimg.com%2Fvi%2FdQw4w9WgXcQ"
|
"&w=960&h=540&url=https%3A%2F%2Fi.ytimg.com%2Fvi%2FdQw4w9WgXcQ"
|
||||||
"%2Fmaxresdefault.jpg&sx=0&sy=0&sw=1280&sh=720&_nc_hash=abc123"
|
"%2Fmaxresdefault.jpg&sx=0&sy=0&sw=1280&sh=720&_nc_hash=abc123",
|
||||||
|
width=960,
|
||||||
|
height=540,
|
||||||
),
|
),
|
||||||
original_image_url="https://i.ytimg.com/vi/dQw4w9WgXcQ/maxresdefault.jpg",
|
original_image_url="https://i.ytimg.com/vi/dQw4w9WgXcQ/maxresdefault.jpg",
|
||||||
image_width=960,
|
|
||||||
image_height=540,
|
|
||||||
attachments=[],
|
attachments=[],
|
||||||
uid="ee.mid.$gAAT4Sw1WSGhzQ9uRWVtEpZHZ8ZPV",
|
uid="ee.mid.$gAAT4Sw1WSGhzQ9uRWVtEpZHZ8ZPV",
|
||||||
) == ShareAttachment._from_graphql(data)
|
) == ShareAttachment._from_graphql(data)
|
||||||
@@ -310,10 +308,12 @@ def test_share_with_image_subattachment():
|
|||||||
title="",
|
title="",
|
||||||
description="Abc",
|
description="Abc",
|
||||||
source="Def",
|
source="Def",
|
||||||
image_url="https://scontent-arn2-1.xx.fbcdn.net/v/t1.0-9/1.jpg",
|
image=fbchat.Image(
|
||||||
|
url="https://scontent-arn2-1.xx.fbcdn.net/v/t1.0-9/1.jpg",
|
||||||
|
width=720,
|
||||||
|
height=960,
|
||||||
|
),
|
||||||
original_image_url="https://scontent-arn2-1.xx.fbcdn.net/v/t1.0-9/1.jpg",
|
original_image_url="https://scontent-arn2-1.xx.fbcdn.net/v/t1.0-9/1.jpg",
|
||||||
image_width=720,
|
|
||||||
image_height=960,
|
|
||||||
attachments=[None],
|
attachments=[None],
|
||||||
uid="deadbeef123",
|
uid="deadbeef123",
|
||||||
) == ShareAttachment._from_graphql(data)
|
) == ShareAttachment._from_graphql(data)
|
||||||
@@ -436,20 +436,22 @@ def test_share_with_video_subattachment():
|
|||||||
title="",
|
title="",
|
||||||
description="Abc",
|
description="Abc",
|
||||||
source="Def",
|
source="Def",
|
||||||
image_url="https://scontent-arn2-1.xx.fbcdn.net/v/t15.5256-10/p180x540/1.jpg",
|
image=fbchat.Image(
|
||||||
|
url="https://scontent-arn2-1.xx.fbcdn.net/v/t15.5256-10/p180x540/1.jpg",
|
||||||
|
width=960,
|
||||||
|
height=540,
|
||||||
|
),
|
||||||
original_image_url="https://scontent-arn2-1.xx.fbcdn.net/v/t15.5256-10/p180x540/1.jpg",
|
original_image_url="https://scontent-arn2-1.xx.fbcdn.net/v/t15.5256-10/p180x540/1.jpg",
|
||||||
image_width=960,
|
|
||||||
image_height=540,
|
|
||||||
attachments=[
|
attachments=[
|
||||||
fbchat.VideoAttachment(
|
fbchat.VideoAttachment(
|
||||||
uid="2222",
|
uid="2222",
|
||||||
duration=datetime.timedelta(seconds=24, microseconds=469000),
|
duration=datetime.timedelta(seconds=24, microseconds=469000),
|
||||||
preview_url="https://video-arn2-1.xx.fbcdn.net/v/t42.9040-2/vid.mp4",
|
preview_url="https://video-arn2-1.xx.fbcdn.net/v/t42.9040-2/vid.mp4",
|
||||||
medium_image={
|
medium_image=fbchat.Image(
|
||||||
"uri": "https://scontent-arn2-1.xx.fbcdn.net/v/t15.5256-10/p180x540/1.jpg",
|
url="https://scontent-arn2-1.xx.fbcdn.net/v/t15.5256-10/p180x540/1.jpg",
|
||||||
"width": 960,
|
width=960,
|
||||||
"height": 540,
|
height=540,
|
||||||
},
|
),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
uid="deadbeef123",
|
uid="deadbeef123",
|
||||||
|
@@ -33,17 +33,17 @@ def test_imageattachment_from_list():
|
|||||||
uid="1234",
|
uid="1234",
|
||||||
width=2833,
|
width=2833,
|
||||||
height=1367,
|
height=1367,
|
||||||
thumbnail_url="https://scontent-arn2-1.xx.fbcdn.net/v/s261x260/1.jpg",
|
thumbnail=fbchat.Image(
|
||||||
preview={
|
url="https://scontent-arn2-1.xx.fbcdn.net/v/s261x260/1.jpg"
|
||||||
"uri": "https://scontent-arn2-1.xx.fbcdn.net/v/2.jpg",
|
),
|
||||||
"width": 960,
|
preview=fbchat.Image(
|
||||||
"height": 463,
|
url="https://scontent-arn2-1.xx.fbcdn.net/v/2.jpg", width=960, height=463
|
||||||
},
|
),
|
||||||
large_preview={
|
large_preview=fbchat.Image(
|
||||||
"uri": "https://scontent-arn2-1.xx.fbcdn.net/v/s2048x2048/3.jpg",
|
url="https://scontent-arn2-1.xx.fbcdn.net/v/s2048x2048/3.jpg",
|
||||||
"width": 2048,
|
width=2048,
|
||||||
"height": 988,
|
height=988,
|
||||||
},
|
),
|
||||||
) == ImageAttachment._from_list({"node": data})
|
) == ImageAttachment._from_list({"node": data})
|
||||||
|
|
||||||
|
|
||||||
@@ -71,19 +71,19 @@ def test_videoattachment_from_list():
|
|||||||
uid="1234",
|
uid="1234",
|
||||||
width=640,
|
width=640,
|
||||||
height=368,
|
height=368,
|
||||||
small_image={
|
small_image=fbchat.Image(
|
||||||
"uri": "https://scontent-arn2-1.xx.fbcdn.net/v/t15.3394-10/p261x260/1.jpg"
|
url="https://scontent-arn2-1.xx.fbcdn.net/v/t15.3394-10/p261x260/1.jpg"
|
||||||
},
|
),
|
||||||
medium_image={
|
medium_image=fbchat.Image(
|
||||||
"uri": "https://scontent-arn2-1.xx.fbcdn.net/v/t15.3394-10/2.jpg",
|
url="https://scontent-arn2-1.xx.fbcdn.net/v/t15.3394-10/2.jpg",
|
||||||
"width": 640,
|
width=640,
|
||||||
"height": 368,
|
height=368,
|
||||||
},
|
),
|
||||||
large_image={
|
large_image=fbchat.Image(
|
||||||
"uri": "https://scontent-arn2-1.xx.fbcdn.net/v/t15.3394-10/3.jpg",
|
url="https://scontent-arn2-1.xx.fbcdn.net/v/t15.3394-10/3.jpg",
|
||||||
"width": 640,
|
width=640,
|
||||||
"height": 368,
|
height=368,
|
||||||
},
|
),
|
||||||
) == VideoAttachment._from_list({"node": data})
|
) == VideoAttachment._from_list({"node": data})
|
||||||
|
|
||||||
|
|
||||||
@@ -170,17 +170,15 @@ def test_graphql_to_attachment_image1():
|
|||||||
width=None,
|
width=None,
|
||||||
height=None,
|
height=None,
|
||||||
is_animated=False,
|
is_animated=False,
|
||||||
thumbnail_url="https://scontent-arn2-1.xx.fbcdn.net/v/p50x50/3.png",
|
thumbnail=fbchat.Image(
|
||||||
preview={
|
url="https://scontent-arn2-1.xx.fbcdn.net/v/p50x50/3.png"
|
||||||
"uri": "https://scontent-arn2-1.xx.fbcdn.net/v/1.png",
|
),
|
||||||
"width": 128,
|
preview=fbchat.Image(
|
||||||
"height": 128,
|
url="https://scontent-arn2-1.xx.fbcdn.net/v/1.png", width=128, height=128
|
||||||
},
|
),
|
||||||
large_preview={
|
large_preview=fbchat.Image(
|
||||||
"uri": "https://scontent-arn2-1.xx.fbcdn.net/v/2.png",
|
url="https://scontent-arn2-1.xx.fbcdn.net/v/2.png", width=128, height=128
|
||||||
"width": 128,
|
),
|
||||||
"height": 128,
|
|
||||||
},
|
|
||||||
) == graphql_to_attachment(data)
|
) == graphql_to_attachment(data)
|
||||||
|
|
||||||
|
|
||||||
@@ -209,12 +207,12 @@ def test_graphql_to_attachment_image2():
|
|||||||
width=None,
|
width=None,
|
||||||
height=None,
|
height=None,
|
||||||
is_animated=True,
|
is_animated=True,
|
||||||
preview={"uri": "https://cdn.fbsbx.com/v/1.gif", "width": 128, "height": 128},
|
preview=fbchat.Image(
|
||||||
animated_preview={
|
url="https://cdn.fbsbx.com/v/1.gif", width=128, height=128
|
||||||
"uri": "https://cdn.fbsbx.com/v/1.gif",
|
),
|
||||||
"width": 128,
|
animated_preview=fbchat.Image(
|
||||||
"height": 128,
|
url="https://cdn.fbsbx.com/v/1.gif", width=128, height=128
|
||||||
},
|
),
|
||||||
) == graphql_to_attachment(data)
|
) == graphql_to_attachment(data)
|
||||||
|
|
||||||
|
|
||||||
@@ -251,21 +249,19 @@ def test_graphql_to_attachment_video():
|
|||||||
height=None,
|
height=None,
|
||||||
duration=datetime.timedelta(seconds=6),
|
duration=datetime.timedelta(seconds=6),
|
||||||
preview_url="https://video-arn2-1.xx.fbcdn.net/v/video-4321.mp4",
|
preview_url="https://video-arn2-1.xx.fbcdn.net/v/video-4321.mp4",
|
||||||
small_image={
|
small_image=fbchat.Image(
|
||||||
"uri": "https://scontent-arn2-1.xx.fbcdn.net/v/s168x128/1.jpg",
|
url="https://scontent-arn2-1.xx.fbcdn.net/v/s168x128/1.jpg",
|
||||||
"width": 168,
|
width=168,
|
||||||
"height": 96,
|
height=96,
|
||||||
},
|
),
|
||||||
medium_image={
|
medium_image=fbchat.Image(
|
||||||
"uri": "https://scontent-arn2-1.xx.fbcdn.net/v/p261x260/3.jpg",
|
url="https://scontent-arn2-1.xx.fbcdn.net/v/p261x260/3.jpg",
|
||||||
"width": 452,
|
width=452,
|
||||||
"height": 260,
|
height=260,
|
||||||
},
|
),
|
||||||
large_image={
|
large_image=fbchat.Image(
|
||||||
"uri": "https://scontent-arn2-1.xx.fbcdn.net/v/2.jpg",
|
url="https://scontent-arn2-1.xx.fbcdn.net/v/2.jpg", width=640, height=368
|
||||||
"width": 640,
|
),
|
||||||
"height": 368,
|
|
||||||
},
|
|
||||||
) == graphql_to_attachment(data)
|
) == graphql_to_attachment(data)
|
||||||
|
|
||||||
|
|
||||||
@@ -350,9 +346,9 @@ def test_graphql_to_subattachment_video():
|
|||||||
uid="1234",
|
uid="1234",
|
||||||
duration=datetime.timedelta(seconds=24, microseconds=469000),
|
duration=datetime.timedelta(seconds=24, microseconds=469000),
|
||||||
preview_url="https://video-arn2-1.xx.fbcdn.net/v/t42.9040-2/vid.mp4",
|
preview_url="https://video-arn2-1.xx.fbcdn.net/v/t42.9040-2/vid.mp4",
|
||||||
medium_image={
|
medium_image=fbchat.Image(
|
||||||
"uri": "https://scontent-arn2-1.xx.fbcdn.net/v/t15.5256-10/p180x540/1.jpg",
|
url="https://scontent-arn2-1.xx.fbcdn.net/v/t15.5256-10/p180x540/1.jpg",
|
||||||
"width": 960,
|
width=960,
|
||||||
"height": 540,
|
height=540,
|
||||||
},
|
),
|
||||||
) == graphql_to_subattachment(data)
|
) == graphql_to_subattachment(data)
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
import pytest
|
import pytest
|
||||||
import datetime
|
import datetime
|
||||||
|
import fbchat
|
||||||
from fbchat._location import LocationAttachment, LiveLocationAttachment
|
from fbchat._location import LocationAttachment, LiveLocationAttachment
|
||||||
|
|
||||||
|
|
||||||
@@ -34,9 +35,11 @@ def test_location_attachment_from_graphql():
|
|||||||
"subattachments": [],
|
"subattachments": [],
|
||||||
}
|
}
|
||||||
expected = LocationAttachment(latitude=55.4, longitude=12.4322, uid=400828513928715)
|
expected = LocationAttachment(latitude=55.4, longitude=12.4322, uid=400828513928715)
|
||||||
expected.image_url = "https://external-arn2-1.xx.fbcdn.net/static_map.php?v=1020&osm_provider=2&size=545x280&zoom=15&markers=55.40000000%2C12.43220000&language=en"
|
expected.image = fbchat.Image(
|
||||||
expected.image_width = 545
|
url="https://external-arn2-1.xx.fbcdn.net/static_map.php?v=1020&osm_provider=2&size=545x280&zoom=15&markers=55.40000000%2C12.43220000&language=en",
|
||||||
expected.image_height = 280
|
width=545,
|
||||||
|
height=280,
|
||||||
|
)
|
||||||
expected.url = "https://l.facebook.com/l.php?u=https%3A%2F%2Fwww.bing.com%2Fmaps%2Fdefault.aspx%3Fv%3D2%26pc%3DFACEBK%26mid%3D8100%26where1%3D55.4%252C%2B12.4322%26FORM%3DFBKPL1%26mkt%3Den-GB&h=a&s=1"
|
expected.url = "https://l.facebook.com/l.php?u=https%3A%2F%2Fwww.bing.com%2Fmaps%2Fdefault.aspx%3Fv%3D2%26pc%3DFACEBK%26mid%3D8100%26where1%3D55.4%252C%2B12.4322%26FORM%3DFBKPL1%26mkt%3Den-GB&h=a&s=1"
|
||||||
assert expected == LocationAttachment._from_graphql(data)
|
assert expected == LocationAttachment._from_graphql(data)
|
||||||
|
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
import fbchat
|
||||||
from fbchat._page import Page
|
from fbchat._page import Page
|
||||||
|
|
||||||
|
|
||||||
@@ -12,7 +13,7 @@ def test_page_from_graphql():
|
|||||||
}
|
}
|
||||||
assert Page(
|
assert Page(
|
||||||
uid="123456",
|
uid="123456",
|
||||||
photo="https://scontent-arn2-1.xx.fbcdn.net/v/...",
|
photo=fbchat.Image(url="https://scontent-arn2-1.xx.fbcdn.net/v/..."),
|
||||||
name="Some school",
|
name="Some school",
|
||||||
url="https://www.facebook.com/some-school/",
|
url="https://www.facebook.com/some-school/",
|
||||||
city=None,
|
city=None,
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
import pytest
|
import pytest
|
||||||
|
import fbchat
|
||||||
from fbchat._sticker import Sticker
|
from fbchat._sticker import Sticker
|
||||||
|
|
||||||
|
|
||||||
@@ -20,9 +21,11 @@ def test_from_graphql_normal():
|
|||||||
frames_per_row=None,
|
frames_per_row=None,
|
||||||
frames_per_col=None,
|
frames_per_col=None,
|
||||||
frame_rate=None,
|
frame_rate=None,
|
||||||
|
image=fbchat.Image(
|
||||||
url="https://scontent-arn2-1.xx.fbcdn.net/v/redacted.png",
|
url="https://scontent-arn2-1.xx.fbcdn.net/v/redacted.png",
|
||||||
width=274,
|
width=274,
|
||||||
height=274,
|
height=274,
|
||||||
|
),
|
||||||
label="Like, thumbs up",
|
label="Like, thumbs up",
|
||||||
) == Sticker._from_graphql(
|
) == Sticker._from_graphql(
|
||||||
{
|
{
|
||||||
@@ -54,9 +57,11 @@ def test_from_graphql_animated():
|
|||||||
frames_per_row=2,
|
frames_per_row=2,
|
||||||
frames_per_col=2,
|
frames_per_col=2,
|
||||||
frame_rate=142,
|
frame_rate=142,
|
||||||
|
image=fbchat.Image(
|
||||||
url="https://scontent-arn2-1.fbcdn.net/v/redacted1.png",
|
url="https://scontent-arn2-1.fbcdn.net/v/redacted1.png",
|
||||||
width=240,
|
width=240,
|
||||||
height=293,
|
height=293,
|
||||||
|
),
|
||||||
label="Love, cat with heart",
|
label="Love, cat with heart",
|
||||||
) == Sticker._from_graphql(
|
) == Sticker._from_graphql(
|
||||||
{
|
{
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
import pytest
|
import pytest
|
||||||
import datetime
|
import datetime
|
||||||
|
import fbchat
|
||||||
from fbchat._user import User, ActiveStatus
|
from fbchat._user import User, ActiveStatus
|
||||||
|
|
||||||
|
|
||||||
@@ -17,7 +18,7 @@ def test_user_from_graphql():
|
|||||||
}
|
}
|
||||||
assert User(
|
assert User(
|
||||||
uid="1234",
|
uid="1234",
|
||||||
photo="https://scontent-arn2-1.xx.fbcdn.net/v/...",
|
photo=fbchat.Image(url="https://scontent-arn2-1.xx.fbcdn.net/v/..."),
|
||||||
name="Abc Def Ghi",
|
name="Abc Def Ghi",
|
||||||
url="https://www.facebook.com/profile.php?id=1234",
|
url="https://www.facebook.com/profile.php?id=1234",
|
||||||
first_name="Abc",
|
first_name="Abc",
|
||||||
@@ -137,7 +138,7 @@ def test_user_from_thread_fetch():
|
|||||||
}
|
}
|
||||||
assert User(
|
assert User(
|
||||||
uid="1234",
|
uid="1234",
|
||||||
photo="https://scontent-arn2-1.xx.fbcdn.net/v/...",
|
photo=fbchat.Image(url="https://scontent-arn2-1.xx.fbcdn.net/v/..."),
|
||||||
name="Abc Def Ghi",
|
name="Abc Def Ghi",
|
||||||
last_active=datetime.datetime(2017, 7, 14, 2, 40, tzinfo=datetime.timezone.utc),
|
last_active=datetime.datetime(2017, 7, 14, 2, 40, tzinfo=datetime.timezone.utc),
|
||||||
message_count=1111,
|
message_count=1111,
|
||||||
@@ -175,7 +176,7 @@ def test_user_from_all_fetch():
|
|||||||
}
|
}
|
||||||
assert User(
|
assert User(
|
||||||
uid="1234",
|
uid="1234",
|
||||||
photo="https://scontent-arn2-1.xx.fbcdn.net/v/...",
|
photo=fbchat.Image(url="https://scontent-arn2-1.xx.fbcdn.net/v/..."),
|
||||||
name="Abc Def Ghi",
|
name="Abc Def Ghi",
|
||||||
url="https://www.facebook.com/profile.php?id=1234",
|
url="https://www.facebook.com/profile.php?id=1234",
|
||||||
first_name="Abc",
|
first_name="Abc",
|
||||||
|
Reference in New Issue
Block a user