diff --git a/fbchat/__init__.py b/fbchat/__init__.py index 13dd54e..6c769d9 100644 --- a/fbchat/__init__.py +++ b/fbchat/__init__.py @@ -42,6 +42,8 @@ from ._quick_reply import ( from ._poll import Poll, PollOption from ._plan import GuestStatus, Plan, PlanData +from ._event_common import Event, UnknownEvent, ThreadEvent + from ._client import Client __title__ = "fbchat" diff --git a/fbchat/_client.py b/fbchat/_client.py index f3c3d05..eee243a 100644 --- a/fbchat/_client.py +++ b/fbchat/_client.py @@ -13,6 +13,7 @@ from . import ( _group, _thread, _message, + _event_common, ) from ._thread import ThreadLocation @@ -1194,6 +1195,10 @@ class Client: EVENTS """ + def on_event(self, event: _event_common.Event): + """Called when the client is listening, and an event happens.""" + log.info("Got event: %s", event) + def on_message( self, mid=None, diff --git a/fbchat/_event_common.py b/fbchat/_event_common.py new file mode 100644 index 0000000..5da21c4 --- /dev/null +++ b/fbchat/_event_common.py @@ -0,0 +1,50 @@ +import attr +import abc +from ._core import kw_only +from . import _exception, _thread, _group, _user, _message + +#: Default attrs settings for events +attrs_event = attr.s(slots=True, kw_only=kw_only, frozen=True) + + +@attrs_event +class Event(metaclass=abc.ABCMeta): + """Base class for all events.""" + + @classmethod + @abc.abstractmethod + def _parse(cls, session, data): + raise NotImplementedError + + +@attrs_event +class UnknownEvent(Event): + """Represent an unknown event.""" + + #: The unknown data. This cannot be relied on, it's only for debugging purposes. + data = attr.ib() + + @classmethod + def _parse(cls, session, data): + raise NotImplementedError + + +@attrs_event +class ThreadEvent(Event): + """Represent an event that was done by a user/page in a thread.""" + + #: The person who did the action + author = attr.ib(type=_user.User) # Or Union[User, Page]? + #: Thread that the action was done in + thread = attr.ib(type=_thread.ThreadABC) + + @staticmethod + def _get_thread(session, data): + # TODO: Handle pages? Is it even possible? + key = data["threadKey"] + + if "threadFbId" in key: + return _group.Group(session=session, id=str(key["threadFbId"])) + elif "otherUserFbId" in key: + return _user.User(session=session, id=str(key["otherUserFbId"])) + raise _exception.ParseError("Could not find thread data", data=data) diff --git a/tests/test_event_common.py b/tests/test_event_common.py new file mode 100644 index 0000000..2b462f9 --- /dev/null +++ b/tests/test_event_common.py @@ -0,0 +1,57 @@ +import pytest +from fbchat import Group, User, ParseError, ThreadEvent + + +def test_thread_event_get_thread_group1(session): + data = { + "threadKey": {"threadFbId": 1234}, + "messageId": "mid.$gAAT4Sw1WSGh14A3MOFvrsiDvr3Yc", + "offlineThreadingId": "6623583531508397596", + "actorFbId": 4321, + "timestamp": 1500000000000, + "tags": [ + "inbox", + "sent", + "tq", + "blindly_apply_message_folder", + "source:messenger:web", + ], + } + assert Group(session=session, id="1234") == ThreadEvent._get_thread(session, data) + + +def test_thread_event_get_thread_group2(session): + data = { + "actorFbId": "4321", + "folderId": {"systemFolderId": "INBOX"}, + "messageId": "mid.$XYZ", + "offlineThreadingId": "112233445566", + "skipBumpThread": False, + "tags": ["source:messenger:web"], + "threadKey": {"threadFbId": "1234"}, + "threadReadStateEffect": "KEEP_AS_IS", + "timestamp": "1500000000000", + } + assert Group(session=session, id="1234") == ThreadEvent._get_thread(session, data) + + +def test_thread_event_get_thread_user(session): + data = { + "actorFbId": "4321", + "folderId": {"systemFolderId": "INBOX"}, + "messageId": "mid.$XYZ", + "offlineThreadingId": "112233445566", + "skipBumpThread": False, + "skipSnippetUpdate": False, + "tags": ["source:messenger:web"], + "threadKey": {"otherUserFbId": "1234"}, + "threadReadStateEffect": "KEEP_AS_IS", + "timestamp": "1500000000000", + } + assert User(session=session, id="1234") == ThreadEvent._get_thread(session, data) + + +def test_thread_event_get_thread_unknown(session): + data = {"threadKey": {"abc": "1234"}} + with pytest.raises(ParseError, match="Could not find thread data"): + ThreadEvent._get_thread(session, data)