From 0531a9e4826de6fec133ab3bd04a159cd4514d0d Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Wed, 8 Jan 2020 23:07:13 +0100 Subject: [PATCH] Add session attribute to Group/User/Page/Thread --- fbchat/_client.py | 35 +++++++++++++++++++++++------------ fbchat/_group.py | 9 +++++++-- fbchat/_page.py | 9 +++++++-- fbchat/_thread.py | 3 +++ fbchat/_user.py | 15 +++++++++++---- tests/conftest.py | 5 +++++ tests/test_group.py | 5 +++-- tests/test_page.py | 5 +++-- tests/test_user.py | 15 +++++++++------ 9 files changed, 71 insertions(+), 30 deletions(-) diff --git a/fbchat/_client.py b/fbchat/_client.py index e5fa3d8..2f0b78a 100644 --- a/fbchat/_client.py +++ b/fbchat/_client.py @@ -61,6 +61,10 @@ class Client: self._buddylist = dict() self._session = session + @property + def session(self): + return self._session + """ INTERNAL REQUEST METHODS """ @@ -214,7 +218,7 @@ class Client: if data["id"] in ["0", 0]: # Skip invalid users continue - users.append(User._from_all_fetch(data)) + users.append(User._from_all_fetch(self.session, data)) return users def search_for_users(self, name, limit=10): @@ -233,7 +237,9 @@ class Client: params = {"search": name, "limit": limit} (j,) = self.graphql_requests(_graphql.from_query(_graphql.SEARCH_USER, params)) - return [User._from_graphql(node) for node in j[name]["users"]["nodes"]] + return [ + User._from_graphql(self.session, node) for node in j[name]["users"]["nodes"] + ] def search_for_pages(self, name, limit=10): """Find and get pages by their name. @@ -250,7 +256,9 @@ class Client: params = {"search": name, "limit": limit} (j,) = self.graphql_requests(_graphql.from_query(_graphql.SEARCH_PAGE, params)) - return [Page._from_graphql(node) for node in j[name]["pages"]["nodes"]] + return [ + Page._from_graphql(self.session, node) for node in j[name]["pages"]["nodes"] + ] def search_for_groups(self, name, limit=10): """Find and get group threads by their name. @@ -268,7 +276,10 @@ class Client: params = {"search": name, "limit": limit} (j,) = self.graphql_requests(_graphql.from_query(_graphql.SEARCH_GROUP, params)) - return [Group._from_graphql(node) for node in j["viewer"]["groups"]["nodes"]] + return [ + Group._from_graphql(self.session, node) + for node in j["viewer"]["groups"]["nodes"] + ] def search_for_threads(self, name, limit=10): """Find and get threads by their name. @@ -291,12 +302,12 @@ class Client: rtn = [] for node in j[name]["threads"]["nodes"]: if node["__typename"] == "User": - rtn.append(User._from_graphql(node)) + rtn.append(User._from_graphql(self.session, node)) elif node["__typename"] == "MessageThread": # MessageThread => Group thread - rtn.append(Group._from_graphql(node)) + rtn.append(Group._from_graphql(self.session, node)) elif node["__typename"] == "Page": - rtn.append(Page._from_graphql(node)) + rtn.append(Page._from_graphql(self.session, node)) elif node["__typename"] == "Group": # We don't handle Facebook "Groups" pass @@ -551,16 +562,16 @@ class Client: entry = entry["message_thread"] if entry.get("thread_type") == "GROUP": _id = entry["thread_key"]["thread_fbid"] - rtn[_id] = Group._from_graphql(entry) + rtn[_id] = Group._from_graphql(self.session, entry) elif entry.get("thread_type") == "ONE_TO_ONE": _id = entry["thread_key"]["other_user_id"] if pages_and_users.get(_id) is None: raise FBchatException("Could not fetch thread {}".format(_id)) entry.update(pages_and_users[_id]) if entry["type"] == ThreadType.USER: - rtn[_id] = User._from_graphql(entry) + rtn[_id] = User._from_graphql(self.session, entry) else: - rtn[_id] = Page._from_graphql(entry) + rtn[_id] = Page._from_graphql(self.session, entry) else: raise FBchatException( "{} had an unknown thread type: {}".format(thread_ids[i], entry) @@ -641,9 +652,9 @@ class Client: for node in j["viewer"]["message_threads"]["nodes"]: _type = node.get("thread_type") if _type == "GROUP": - rtn.append(Group._from_graphql(node)) + rtn.append(Group._from_graphql(self.session, node)) elif _type == "ONE_TO_ONE": - rtn.append(User._from_thread_fetch(node)) + rtn.append(User._from_thread_fetch(self.session, node)) else: raise FBchatException( "Unknown thread type: {}, with data: {}".format(_type, node) diff --git a/fbchat/_group.py b/fbchat/_group.py index 8412f5d..e0c347a 100644 --- a/fbchat/_group.py +++ b/fbchat/_group.py @@ -1,6 +1,6 @@ import attr from ._core import attrs_default, Image -from . import _util, _plan +from . import _util, _session, _plan from ._thread import ThreadType, Thread @@ -10,6 +10,10 @@ class Group(Thread): type = ThreadType.GROUP + #: The session to use when making requests. + session = attr.ib(type=_session.Session) + #: The group's unique identifier. + id = attr.ib(converter=str) #: The group's picture photo = attr.ib(None) #: The name of the group @@ -38,7 +42,7 @@ class Group(Thread): join_link = attr.ib(None) @classmethod - def _from_graphql(cls, data): + def _from_graphql(cls, session, data): if data.get("image") is None: data["image"] = {} c_info = cls._parse_customization_info(data) @@ -52,6 +56,7 @@ class Group(Thread): plan = _plan.Plan._from_graphql(data["event_reminders"]["nodes"][0]) return cls( + session=session, id=data["thread_key"]["thread_fbid"], participants=set( [ diff --git a/fbchat/_page.py b/fbchat/_page.py index cc434bd..b2601a4 100644 --- a/fbchat/_page.py +++ b/fbchat/_page.py @@ -1,6 +1,6 @@ import attr from ._core import attrs_default, Image -from . import _plan +from . import _session, _plan from ._thread import ThreadType, Thread @@ -10,6 +10,10 @@ class Page(Thread): type = ThreadType.PAGE + #: The session to use when making requests. + session = attr.ib(type=_session.Session) + #: The unique identifier of the page. + id = attr.ib(converter=str) #: The page's picture photo = attr.ib(None) #: The name of the page @@ -32,7 +36,7 @@ class Page(Thread): category = attr.ib(None) @classmethod - def _from_graphql(cls, data): + def _from_graphql(cls, session, data): if data.get("profile_picture") is None: data["profile_picture"] = {} if data.get("city") is None: @@ -42,6 +46,7 @@ class Page(Thread): plan = _plan.Plan._from_graphql(data["event_reminders"]["nodes"][0]) return cls( + session=session, id=data["id"], url=data.get("url"), city=data.get("city").get("name"), diff --git a/fbchat/_thread.py b/fbchat/_thread.py index 4f4bd74..7c3796e 100644 --- a/fbchat/_thread.py +++ b/fbchat/_thread.py @@ -1,5 +1,6 @@ import attr from ._core import attrs_default, Enum, Image +from . import _session class ThreadType(Enum): @@ -71,6 +72,8 @@ class ThreadColor(Enum): class Thread: """Represents a Facebook thread.""" + #: The session to use when making requests. + session = attr.ib(type=_session.Session) #: The unique identifier of the thread. id = attr.ib(converter=str) #: Specifies the type of thread. Can be used a ``thread_type``. See :ref:`intro_threads` for more info diff --git a/fbchat/_user.py b/fbchat/_user.py index e4fe483..da35652 100644 --- a/fbchat/_user.py +++ b/fbchat/_user.py @@ -1,6 +1,6 @@ import attr from ._core import attrs_default, Enum, Image -from . import _util, _plan +from . import _util, _session, _plan from ._thread import ThreadType, Thread @@ -47,6 +47,10 @@ class User(Thread): type = ThreadType.USER + #: The session to use when making requests. + session = attr.ib(type=_session.Session) + #: The user's unique identifier. + id = attr.ib(converter=str) #: The user's picture photo = attr.ib(None) #: The name of the user @@ -79,7 +83,7 @@ class User(Thread): emoji = attr.ib(None) @classmethod - def _from_graphql(cls, data): + def _from_graphql(cls, session, data): if data.get("profile_picture") is None: data["profile_picture"] = {} c_info = cls._parse_customization_info(data) @@ -88,6 +92,7 @@ class User(Thread): plan = _plan.Plan._from_graphql(data["event_reminders"]["nodes"][0]) return cls( + session=session, id=data["id"], url=data.get("url"), first_name=data.get("first_name"), @@ -106,7 +111,7 @@ class User(Thread): ) @classmethod - def _from_thread_fetch(cls, data): + def _from_thread_fetch(cls, session, data): if data.get("big_image_src") is None: data["big_image_src"] = {} c_info = cls._parse_customization_info(data) @@ -133,6 +138,7 @@ class User(Thread): plan = _plan.Plan._from_graphql(data["event_reminders"]["nodes"][0]) return cls( + session=session, id=user["id"], url=user.get("url"), name=user.get("name"), @@ -152,8 +158,9 @@ class User(Thread): ) @classmethod - def _from_all_fetch(cls, data): + def _from_all_fetch(cls, session, data): return cls( + session=session, id=data["id"], first_name=data.get("firstName"), url=data.get("uri"), diff --git a/tests/conftest.py b/tests/conftest.py index 122d148..d3978b0 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -6,6 +6,11 @@ from contextlib import contextmanager from fbchat import ThreadType, Message, Mention +@pytest.fixture(scope="session") +def session(): + return object() # TODO: Add a mocked session + + @pytest.fixture(scope="session") def user(client2): return {"id": client2.id, "type": ThreadType.USER} diff --git a/tests/test_group.py b/tests/test_group.py index d1c69eb..c014e1d 100644 --- a/tests/test_group.py +++ b/tests/test_group.py @@ -1,7 +1,7 @@ from fbchat._group import Group -def test_group_from_graphql(): +def test_group_from_graphql(session): data = { "name": "Group ABC", "thread_key": {"thread_fbid": "11223344"}, @@ -26,6 +26,7 @@ def test_group_from_graphql(): "event_reminders": {"nodes": []}, } assert Group( + session=session, id="11223344", photo=None, name="Group ABC", @@ -40,4 +41,4 @@ def test_group_from_graphql(): approval_mode=False, approval_requests=set(), join_link="", - ) == Group._from_graphql(data) + ) == Group._from_graphql(session, data) diff --git a/tests/test_page.py b/tests/test_page.py index 0ff6051..2bcacdf 100644 --- a/tests/test_page.py +++ b/tests/test_page.py @@ -2,7 +2,7 @@ import fbchat from fbchat._page import Page -def test_page_from_graphql(): +def test_page_from_graphql(session): data = { "id": "123456", "name": "Some school", @@ -12,10 +12,11 @@ def test_page_from_graphql(): "city": None, } assert Page( + session=session, id="123456", photo=fbchat.Image(url="https://scontent-arn2-1.xx.fbcdn.net/v/..."), name="Some school", url="https://www.facebook.com/some-school/", city=None, category="SCHOOL", - ) == Page._from_graphql(data) + ) == Page._from_graphql(session, data) diff --git a/tests/test_user.py b/tests/test_user.py index a3a7319..a154bcd 100644 --- a/tests/test_user.py +++ b/tests/test_user.py @@ -4,7 +4,7 @@ import fbchat from fbchat._user import User, ActiveStatus -def test_user_from_graphql(): +def test_user_from_graphql(session): data = { "id": "1234", "name": "Abc Def Ghi", @@ -17,6 +17,7 @@ def test_user_from_graphql(): "viewer_affinity": 0.4560002, } assert User( + session=session, id="1234", photo=fbchat.Image(url="https://scontent-arn2-1.xx.fbcdn.net/v/..."), name="Abc Def Ghi", @@ -25,10 +26,10 @@ def test_user_from_graphql(): last_name="Ghi", is_friend=True, gender="female_singular", - ) == User._from_graphql(data) + ) == User._from_graphql(session, data) -def test_user_from_thread_fetch(): +def test_user_from_thread_fetch(session): data = { "thread_key": {"thread_fbid": None, "other_user_id": "1234"}, "name": None, @@ -137,6 +138,7 @@ def test_user_from_thread_fetch(): "delivery_receipts": ..., } assert User( + session=session, id="1234", photo=fbchat.Image(url="https://scontent-arn2-1.xx.fbcdn.net/v/..."), name="Abc Def Ghi", @@ -151,10 +153,10 @@ def test_user_from_thread_fetch(): own_nickname="B", color=None, emoji=None, - ) == User._from_thread_fetch(data) + ) == User._from_thread_fetch(session, data) -def test_user_from_all_fetch(): +def test_user_from_all_fetch(session): data = { "id": "1234", "name": "Abc Def Ghi", @@ -175,6 +177,7 @@ def test_user_from_all_fetch(): "is_blocked": False, } assert User( + session=session, id="1234", photo=fbchat.Image(url="https://scontent-arn2-1.xx.fbcdn.net/v/..."), name="Abc Def Ghi", @@ -182,7 +185,7 @@ def test_user_from_all_fetch(): first_name="Abc", is_friend=True, gender="female_singular", - ) == User._from_all_fetch(data) + ) == User._from_all_fetch(session, data) @pytest.mark.skip(reason="can't gather test data, the pulling is broken")