Add ThreadABC helper, that'll contain functions that threads can call
This commit is contained in:
@@ -14,7 +14,7 @@ from . import _core, _util
|
|||||||
from ._core import Image
|
from ._core import Image
|
||||||
from ._exception import FBchatException, FBchatFacebookError
|
from ._exception import FBchatException, FBchatFacebookError
|
||||||
from ._session import Session
|
from ._session import Session
|
||||||
from ._thread import ThreadType, ThreadLocation, ThreadColor, Thread
|
from ._thread import ThreadType, ThreadLocation, ThreadColor, ThreadABC, Thread
|
||||||
from ._user import TypingStatus, User, ActiveStatus
|
from ._user import TypingStatus, User, ActiveStatus
|
||||||
from ._group import Group
|
from ._group import Group
|
||||||
from ._page import Page
|
from ._page import Page
|
||||||
|
@@ -108,11 +108,6 @@ class Client:
|
|||||||
FETCH METHODS
|
FETCH METHODS
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def _forced_fetch(self, thread_id, mid):
|
|
||||||
params = {"thread_and_message_id": {"thread_id": thread_id, "message_id": mid}}
|
|
||||||
(j,) = self.graphql_requests(_graphql.from_doc_id("1768656253222505", params))
|
|
||||||
return j
|
|
||||||
|
|
||||||
def fetch_threads(self, thread_location, before=None, after=None, limit=None):
|
def fetch_threads(self, thread_location, before=None, after=None, limit=None):
|
||||||
"""Fetch all threads in ``thread_location``.
|
"""Fetch all threads in ``thread_location``.
|
||||||
|
|
||||||
@@ -1820,7 +1815,8 @@ class Client:
|
|||||||
self.on_unknown_messsage_type(msg=m)
|
self.on_unknown_messsage_type(msg=m)
|
||||||
else:
|
else:
|
||||||
thread_id = str(delta["threadKey"]["threadFbId"])
|
thread_id = str(delta["threadKey"]["threadFbId"])
|
||||||
fetch_info = self._forced_fetch(thread_id, mid)
|
thread = Thread(session=self.session, id=thread_id)
|
||||||
|
fetch_info = thread._forced_fetch(mid)
|
||||||
fetch_data = fetch_info["message"]
|
fetch_data = fetch_info["message"]
|
||||||
author_id = fetch_data["message_sender"]["id"]
|
author_id = fetch_data["message_sender"]["id"]
|
||||||
at = _util.millis_to_datetime(int(fetch_data["timestamp_precise"]))
|
at = _util.millis_to_datetime(int(fetch_data["timestamp_precise"]))
|
||||||
|
@@ -1,13 +1,12 @@
|
|||||||
import attr
|
import attr
|
||||||
from ._core import attrs_default, Image
|
from ._core import attrs_default, Image
|
||||||
from . import _util, _session, _plan
|
from . import _util, _session, _plan, _thread
|
||||||
from ._thread import Thread
|
|
||||||
from typing import Iterable
|
from typing import Iterable
|
||||||
|
|
||||||
|
|
||||||
@attrs_default
|
@attrs_default
|
||||||
class Group(Thread):
|
class Group(_thread.ThreadABC):
|
||||||
"""Represents a Facebook group. Inherits `Thread`."""
|
"""Represents a Facebook group. Implements `ThreadABC`."""
|
||||||
|
|
||||||
#: The session to use when making requests.
|
#: The session to use when making requests.
|
||||||
session = attr.ib(type=_session.Session)
|
session = attr.ib(type=_session.Session)
|
||||||
|
@@ -1,12 +1,11 @@
|
|||||||
import attr
|
import attr
|
||||||
from ._core import attrs_default, Image
|
from ._core import attrs_default, Image
|
||||||
from . import _session, _plan
|
from . import _session, _plan, _thread
|
||||||
from ._thread import Thread
|
|
||||||
|
|
||||||
|
|
||||||
@attrs_default
|
@attrs_default
|
||||||
class Page(Thread):
|
class Page(_thread.ThreadABC):
|
||||||
"""Represents a Facebook page. Inherits `Thread`."""
|
"""Represents a Facebook page. Implements `ThreadABC`."""
|
||||||
|
|
||||||
#: The session to use when making requests.
|
#: The session to use when making requests.
|
||||||
session = attr.ib(type=_session.Session)
|
session = attr.ib(type=_session.Session)
|
||||||
@@ -33,6 +32,9 @@ class Page(Thread):
|
|||||||
#: The page's category
|
#: The page's category
|
||||||
category = attr.ib(None)
|
category = attr.ib(None)
|
||||||
|
|
||||||
|
def _to_send_data(self):
|
||||||
|
return {"other_user_fbid": self.id}
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _from_graphql(cls, session, data):
|
def _from_graphql(cls, session, data):
|
||||||
if data.get("profile_picture") is None:
|
if data.get("profile_picture") is None:
|
||||||
|
@@ -1,6 +1,8 @@
|
|||||||
|
import abc
|
||||||
import attr
|
import attr
|
||||||
from ._core import attrs_default, Enum, Image
|
from ._core import attrs_default, Enum, Image
|
||||||
from . import _session
|
from . import _session
|
||||||
|
from typing import MutableMapping, Any
|
||||||
|
|
||||||
|
|
||||||
class ThreadType(Enum):
|
class ThreadType(Enum):
|
||||||
@@ -68,17 +70,39 @@ class ThreadColor(Enum):
|
|||||||
return cls._extend_if_invalid(value)
|
return cls._extend_if_invalid(value)
|
||||||
|
|
||||||
|
|
||||||
@attrs_default
|
class ThreadABC(metaclass=abc.ABCMeta):
|
||||||
class Thread:
|
"""Implemented by thread-like classes.
|
||||||
"""Represents a Facebook thread."""
|
|
||||||
|
|
||||||
#: The session to use when making requests.
|
This is private to implement.
|
||||||
session = attr.ib(type=_session.Session)
|
"""
|
||||||
#: The unique identifier of the thread.
|
|
||||||
id = attr.ib(converter=str)
|
@property
|
||||||
|
@abc.abstractmethod
|
||||||
|
def session(self) -> _session.Session:
|
||||||
|
"""The session to use when making requests."""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
@property
|
||||||
|
@abc.abstractmethod
|
||||||
|
def id(self) -> str:
|
||||||
|
"""The unique identifier of the thread."""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def _to_send_data(self) -> MutableMapping[str, str]:
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def _forced_fetch(self, message_id: str) -> dict:
|
||||||
|
params = {
|
||||||
|
"thread_and_message_id": {"thread_id": self.id, "message_id": message_id}
|
||||||
|
}
|
||||||
|
(j,) = self.session._graphql_requests(
|
||||||
|
_graphql.from_doc_id("1768656253222505", params)
|
||||||
|
)
|
||||||
|
return j
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _parse_customization_info(data):
|
def _parse_customization_info(data: Any) -> MutableMapping[str, Any]:
|
||||||
if data is None or data.get("customization_info") is None:
|
if data is None or data.get("customization_info") is None:
|
||||||
return {}
|
return {}
|
||||||
info = data["customization_info"]
|
info = data["customization_info"]
|
||||||
@@ -110,6 +134,24 @@ class Thread:
|
|||||||
rtn["own_nickname"] = pc[1].get("nickname")
|
rtn["own_nickname"] = pc[1].get("nickname")
|
||||||
return rtn
|
return rtn
|
||||||
|
|
||||||
|
|
||||||
|
@attrs_default
|
||||||
|
class Thread(ThreadABC):
|
||||||
|
"""Represents a Facebook thread, where the actual type is unknown.
|
||||||
|
|
||||||
|
Implements parts of `ThreadABC`, call the method to figure out if your use case is
|
||||||
|
supported. Otherwise, you'll have to use an `User`/`Group`/`Page` object.
|
||||||
|
|
||||||
|
Note: This list may change in minor versions!
|
||||||
|
"""
|
||||||
|
|
||||||
|
#: The session to use when making requests.
|
||||||
|
session = attr.ib(type=_session.Session)
|
||||||
|
#: The unique identifier of the thread.
|
||||||
|
id = attr.ib(converter=str)
|
||||||
|
|
||||||
def _to_send_data(self):
|
def _to_send_data(self):
|
||||||
# TODO: Only implement this in subclasses
|
raise NotImplementedError(
|
||||||
return {"other_user_fbid": self.id}
|
"The method you called is not supported on raw Thread objects."
|
||||||
|
" Please use an appropriate User/Group/Page object instead!"
|
||||||
|
)
|
||||||
|
@@ -1,7 +1,6 @@
|
|||||||
import attr
|
import attr
|
||||||
from ._core import attrs_default, Enum, Image
|
from ._core import attrs_default, Enum, Image
|
||||||
from . import _util, _session, _plan
|
from . import _util, _session, _plan, _thread
|
||||||
from ._thread import Thread
|
|
||||||
|
|
||||||
|
|
||||||
GENDERS = {
|
GENDERS = {
|
||||||
@@ -42,8 +41,8 @@ class TypingStatus(Enum):
|
|||||||
|
|
||||||
|
|
||||||
@attrs_default
|
@attrs_default
|
||||||
class User(Thread):
|
class User(_thread.ThreadABC):
|
||||||
"""Represents a Facebook user. Inherits `Thread`."""
|
"""Represents a Facebook user. Implements `ThreadABC`."""
|
||||||
|
|
||||||
#: The session to use when making requests.
|
#: The session to use when making requests.
|
||||||
session = attr.ib(type=_session.Session)
|
session = attr.ib(type=_session.Session)
|
||||||
@@ -80,6 +79,9 @@ class User(Thread):
|
|||||||
#: The default emoji
|
#: The default emoji
|
||||||
emoji = attr.ib(None)
|
emoji = attr.ib(None)
|
||||||
|
|
||||||
|
def _to_send_data(self):
|
||||||
|
return {"other_user_fbid": self.id}
|
||||||
|
|
||||||
def confirm_friend_request(self):
|
def confirm_friend_request(self):
|
||||||
"""Confirm a friend request, adding the user to your friend list."""
|
"""Confirm a friend request, adding the user to your friend list."""
|
||||||
data = {"to_friend": self.id, "action": "confirm"}
|
data = {"to_friend": self.id, "action": "confirm"}
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import pytest
|
import pytest
|
||||||
import fbchat
|
import fbchat
|
||||||
from fbchat._thread import ThreadType, ThreadColor, Thread
|
from fbchat import ThreadType, ThreadColor, ThreadABC, Thread
|
||||||
|
|
||||||
|
|
||||||
def test_thread_type_to_class():
|
def test_thread_type_to_class():
|
||||||
@@ -19,8 +19,8 @@ def test_thread_color_from_graphql():
|
|||||||
|
|
||||||
|
|
||||||
def test_thread_parse_customization_info_empty():
|
def test_thread_parse_customization_info_empty():
|
||||||
assert {} == Thread._parse_customization_info(None)
|
assert {} == ThreadABC._parse_customization_info(None)
|
||||||
assert {} == Thread._parse_customization_info({"customization_info": None})
|
assert {} == ThreadABC._parse_customization_info({"customization_info": None})
|
||||||
|
|
||||||
|
|
||||||
def test_thread_parse_customization_info_group():
|
def test_thread_parse_customization_info_group():
|
||||||
@@ -43,7 +43,7 @@ def test_thread_parse_customization_info_group():
|
|||||||
"color": ThreadColor.BRILLIANT_ROSE,
|
"color": ThreadColor.BRILLIANT_ROSE,
|
||||||
"nicknames": {"123456789": "A", "987654321": "B"},
|
"nicknames": {"123456789": "A", "987654321": "B"},
|
||||||
}
|
}
|
||||||
assert expected == Thread._parse_customization_info(data)
|
assert expected == ThreadABC._parse_customization_info(data)
|
||||||
|
|
||||||
|
|
||||||
def test_thread_parse_customization_info_user():
|
def test_thread_parse_customization_info_user():
|
||||||
@@ -62,4 +62,9 @@ def test_thread_parse_customization_info_user():
|
|||||||
# ... Other irrelevant fields
|
# ... Other irrelevant fields
|
||||||
}
|
}
|
||||||
expected = {"emoji": None, "color": None, "own_nickname": "A", "nickname": "B"}
|
expected = {"emoji": None, "color": None, "own_nickname": "A", "nickname": "B"}
|
||||||
assert expected == Thread._parse_customization_info(data)
|
assert expected == ThreadABC._parse_customization_info(data)
|
||||||
|
|
||||||
|
|
||||||
|
def test_thread_create_and_implements_thread_abc(session):
|
||||||
|
thread = Thread(session=session, id="123")
|
||||||
|
assert thread._parse_customization_info
|
||||||
|
Reference in New Issue
Block a user