Refactor threads file structure
This commit is contained in:
@@ -27,10 +27,18 @@ from ._exception import (
|
||||
PleaseRefresh,
|
||||
)
|
||||
from ._session import Session
|
||||
from ._thread import ThreadLocation, ThreadABC, Thread
|
||||
from ._user import User, UserData, ActiveStatus
|
||||
from ._group import Group, GroupData
|
||||
from ._page import Page, PageData
|
||||
from ._threads import (
|
||||
ThreadLocation,
|
||||
ThreadABC,
|
||||
Thread,
|
||||
User,
|
||||
UserData,
|
||||
ActiveStatus,
|
||||
Group,
|
||||
GroupData,
|
||||
Page,
|
||||
PageData,
|
||||
)
|
||||
from ._message import EmojiSize, Mention, Message, MessageData
|
||||
from ._attachment import Attachment, UnsentMessage, ShareAttachment
|
||||
from ._sticker import Sticker
|
||||
|
@@ -2,17 +2,7 @@ import attr
|
||||
import datetime
|
||||
|
||||
from ._common import log, attrs_default
|
||||
from . import (
|
||||
_exception,
|
||||
_util,
|
||||
_graphql,
|
||||
_session,
|
||||
_user,
|
||||
_page,
|
||||
_group,
|
||||
_thread,
|
||||
_message,
|
||||
)
|
||||
from . import _exception, _util, _graphql, _session, _threads, _message
|
||||
|
||||
from typing import Sequence, Iterable, Tuple, Optional, Set
|
||||
|
||||
@@ -32,7 +22,7 @@ class Client:
|
||||
#: The session to use when making requests.
|
||||
session = attr.ib(type=_session.Session)
|
||||
|
||||
def fetch_users(self) -> Sequence[_user.UserData]:
|
||||
def fetch_users(self) -> Sequence[_threads.UserData]:
|
||||
"""Fetch users the client is currently chatting with.
|
||||
|
||||
This is very close to your friend list, with the follow differences:
|
||||
@@ -60,10 +50,10 @@ class Client:
|
||||
if data["type"] not in ["user", "friend"] or data["id"] in ["0", 0]:
|
||||
log.warning("Invalid user data %s", data)
|
||||
continue # Skip invalid users
|
||||
users.append(_user.UserData._from_all_fetch(self.session, data))
|
||||
users.append(_threads.UserData._from_all_fetch(self.session, data))
|
||||
return users
|
||||
|
||||
def search_for_users(self, name: str, limit: int) -> Iterable[_user.UserData]:
|
||||
def search_for_users(self, name: str, limit: int) -> Iterable[_threads.UserData]:
|
||||
"""Find and get users by their name.
|
||||
|
||||
The returned users are ordered by relevance.
|
||||
@@ -85,11 +75,11 @@ class Client:
|
||||
)
|
||||
|
||||
return (
|
||||
_user.UserData._from_graphql(self.session, node)
|
||||
_threads.UserData._from_graphql(self.session, node)
|
||||
for node in j[name]["users"]["nodes"]
|
||||
)
|
||||
|
||||
def search_for_pages(self, name: str, limit: int) -> Iterable[_page.PageData]:
|
||||
def search_for_pages(self, name: str, limit: int) -> Iterable[_threads.PageData]:
|
||||
"""Find and get pages by their name.
|
||||
|
||||
The returned pages are ordered by relevance.
|
||||
@@ -111,11 +101,11 @@ class Client:
|
||||
)
|
||||
|
||||
return (
|
||||
_page.PageData._from_graphql(self.session, node)
|
||||
_threads.PageData._from_graphql(self.session, node)
|
||||
for node in j[name]["pages"]["nodes"]
|
||||
)
|
||||
|
||||
def search_for_groups(self, name: str, limit: int) -> Iterable[_group.GroupData]:
|
||||
def search_for_groups(self, name: str, limit: int) -> Iterable[_threads.GroupData]:
|
||||
"""Find and get group threads by their name.
|
||||
|
||||
The returned groups are ordered by relevance.
|
||||
@@ -137,11 +127,11 @@ class Client:
|
||||
)
|
||||
|
||||
return (
|
||||
_group.GroupData._from_graphql(self.session, node)
|
||||
_threads.GroupData._from_graphql(self.session, node)
|
||||
for node in j["viewer"]["groups"]["nodes"]
|
||||
)
|
||||
|
||||
def search_for_threads(self, name: str, limit: int) -> Iterable[_thread.ThreadABC]:
|
||||
def search_for_threads(self, name: str, limit: int) -> Iterable[_threads.ThreadABC]:
|
||||
"""Find and get threads by their name.
|
||||
|
||||
The returned threads are ordered by relevance.
|
||||
@@ -165,12 +155,12 @@ class Client:
|
||||
|
||||
for node in j[name]["threads"]["nodes"]:
|
||||
if node["__typename"] == "User":
|
||||
yield _user.UserData._from_graphql(self.session, node)
|
||||
yield _threads.UserData._from_graphql(self.session, node)
|
||||
elif node["__typename"] == "MessageThread":
|
||||
# MessageThread => Group thread
|
||||
yield _group.GroupData._from_graphql(self.session, node)
|
||||
yield _threads.GroupData._from_graphql(self.session, node)
|
||||
elif node["__typename"] == "Page":
|
||||
yield _page.PageData._from_graphql(self.session, node)
|
||||
yield _threads.PageData._from_graphql(self.session, node)
|
||||
elif node["__typename"] == "Group":
|
||||
# We don't handle Facebook "Groups"
|
||||
pass
|
||||
@@ -189,17 +179,17 @@ class Client:
|
||||
for node in j["graphql_payload"]["message_threads"]:
|
||||
type_ = node["thread_type"]
|
||||
if type_ == "GROUP":
|
||||
thread = _group.Group(
|
||||
thread = _threads.Group(
|
||||
session=self.session, id=node["thread_key"]["thread_fbid"]
|
||||
)
|
||||
elif type_ == "ONE_TO_ONE":
|
||||
thread = _thread.Thread(
|
||||
thread = _threads.Thread(
|
||||
session=self.session, id=node["thread_key"]["other_user_id"]
|
||||
)
|
||||
# if True: # TODO: This check!
|
||||
# thread = _user.UserData._from_graphql(self.session, node)
|
||||
# thread = _threads.UserData._from_graphql(self.session, node)
|
||||
# else:
|
||||
# thread = _page.PageData._from_graphql(self.session, node)
|
||||
# thread = _threads.PageData._from_graphql(self.session, node)
|
||||
else:
|
||||
thread = None
|
||||
log.warning("Unknown thread type %s, data: %s", type_, node)
|
||||
@@ -213,7 +203,7 @@ class Client:
|
||||
|
||||
def search_messages(
|
||||
self, query: str, limit: Optional[int]
|
||||
) -> Iterable[Tuple[_thread.ThreadABC, int]]:
|
||||
) -> Iterable[Tuple[_threads.ThreadABC, int]]:
|
||||
"""Search for messages in all threads.
|
||||
|
||||
Intended to be used alongside `ThreadABC.search_messages`
|
||||
@@ -285,7 +275,7 @@ class Client:
|
||||
log.debug(entries)
|
||||
return entries
|
||||
|
||||
def fetch_thread_info(self, ids: Iterable[str]) -> Iterable[_thread.ThreadABC]:
|
||||
def fetch_thread_info(self, ids: Iterable[str]) -> Iterable[_threads.ThreadABC]:
|
||||
"""Fetch threads' info from IDs, unordered.
|
||||
|
||||
Warning:
|
||||
@@ -336,7 +326,7 @@ class Client:
|
||||
entry = entry["message_thread"]
|
||||
if entry.get("thread_type") == "GROUP":
|
||||
_id = entry["thread_key"]["thread_fbid"]
|
||||
yield _group.GroupData._from_graphql(self.session, entry)
|
||||
yield _threads.GroupData._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:
|
||||
@@ -345,9 +335,9 @@ class Client:
|
||||
)
|
||||
entry.update(pages_and_users[_id])
|
||||
if "first_name" in entry:
|
||||
yield _user.UserData._from_graphql(self.session, entry)
|
||||
yield _threads.UserData._from_graphql(self.session, entry)
|
||||
else:
|
||||
yield _page.PageData._from_graphql(self.session, entry)
|
||||
yield _threads.PageData._from_graphql(self.session, entry)
|
||||
else:
|
||||
raise _exception.ParseError("Unknown thread type", data=entry)
|
||||
|
||||
@@ -367,9 +357,9 @@ class Client:
|
||||
for node in j["viewer"]["message_threads"]["nodes"]:
|
||||
_type = node.get("thread_type")
|
||||
if _type == "GROUP":
|
||||
rtn.append(_group.GroupData._from_graphql(self.session, node))
|
||||
rtn.append(_threads.GroupData._from_graphql(self.session, node))
|
||||
elif _type == "ONE_TO_ONE":
|
||||
rtn.append(_user.UserData._from_thread_fetch(self.session, node))
|
||||
rtn.append(_threads.UserData._from_thread_fetch(self.session, node))
|
||||
else:
|
||||
rtn.append(None)
|
||||
log.warning("Unknown thread type: %s, data: %s", _type, node)
|
||||
@@ -378,8 +368,8 @@ class Client:
|
||||
def fetch_threads(
|
||||
self,
|
||||
limit: Optional[int],
|
||||
location: _thread.ThreadLocation = _thread.ThreadLocation.INBOX,
|
||||
) -> Iterable[_thread.ThreadABC]:
|
||||
location: _threads.ThreadLocation = _threads.ThreadLocation.INBOX,
|
||||
) -> Iterable[_threads.ThreadABC]:
|
||||
"""Fetch the client's thread list.
|
||||
|
||||
Args:
|
||||
@@ -422,7 +412,7 @@ class Client:
|
||||
if not before:
|
||||
raise ValueError("Too many unknown threads.")
|
||||
|
||||
def fetch_unread(self) -> Sequence[_thread.ThreadABC]:
|
||||
def fetch_unread(self) -> Sequence[_threads.ThreadABC]:
|
||||
"""Fetch unread threads.
|
||||
|
||||
Warning:
|
||||
@@ -439,13 +429,14 @@ class Client:
|
||||
result = j["unread_thread_fbids"][0]
|
||||
# TODO: Parse Pages?
|
||||
return [
|
||||
_group.Group(session=self.session, id=id_) for id_ in result["thread_fbids"]
|
||||
_threads.Group(session=self.session, id=id_)
|
||||
for id_ in result["thread_fbids"]
|
||||
] + [
|
||||
_user.User(session=self.session, id=id_)
|
||||
_threads.User(session=self.session, id=id_)
|
||||
for id_ in result["other_user_fbids"]
|
||||
]
|
||||
|
||||
def fetch_unseen(self) -> Sequence[_thread.ThreadABC]:
|
||||
def fetch_unseen(self) -> Sequence[_threads.ThreadABC]:
|
||||
"""Fetch unseen / new threads.
|
||||
|
||||
Warning:
|
||||
@@ -456,9 +447,10 @@ class Client:
|
||||
result = j["unseen_thread_fbids"][0]
|
||||
# TODO: Parse Pages?
|
||||
return [
|
||||
_group.Group(session=self.session, id=id_) for id_ in result["thread_fbids"]
|
||||
_threads.Group(session=self.session, id=id_)
|
||||
for id_ in result["thread_fbids"]
|
||||
] + [
|
||||
_user.User(session=self.session, id=id_)
|
||||
_threads.User(session=self.session, id=id_)
|
||||
for id_ in result["other_user_fbids"]
|
||||
]
|
||||
|
||||
@@ -529,7 +521,9 @@ class Client:
|
||||
|
||||
j = self.session._payload_post("/ajax/mercury/change_read_status.php", data)
|
||||
|
||||
def mark_as_read(self, threads: Iterable[_thread.ThreadABC], at: datetime.datetime):
|
||||
def mark_as_read(
|
||||
self, threads: Iterable[_threads.ThreadABC], at: datetime.datetime
|
||||
):
|
||||
"""Mark threads as read.
|
||||
|
||||
All messages inside the specified threads will be marked as read.
|
||||
@@ -541,7 +535,7 @@ class Client:
|
||||
return self._read_status(True, threads, at)
|
||||
|
||||
def mark_as_unread(
|
||||
self, threads: Iterable[_thread.ThreadABC], at: datetime.datetime
|
||||
self, threads: Iterable[_threads.ThreadABC], at: datetime.datetime
|
||||
):
|
||||
"""Mark threads as unread.
|
||||
|
||||
@@ -560,7 +554,7 @@ class Client:
|
||||
)
|
||||
|
||||
def move_threads(
|
||||
self, location: _thread.ThreadLocation, threads: Iterable[_thread.ThreadABC]
|
||||
self, location: _threads.ThreadLocation, threads: Iterable[_threads.ThreadABC]
|
||||
):
|
||||
"""Move threads to specified location.
|
||||
|
||||
@@ -568,10 +562,10 @@ class Client:
|
||||
location: INBOX, PENDING, ARCHIVED or OTHER
|
||||
threads: Threads to move
|
||||
"""
|
||||
if location == _thread.ThreadLocation.PENDING:
|
||||
location = _thread.ThreadLocation.OTHER
|
||||
if location == _threads.ThreadLocation.PENDING:
|
||||
location = _threads.ThreadLocation.OTHER
|
||||
|
||||
if location == _thread.ThreadLocation.ARCHIVED:
|
||||
if location == _threads.ThreadLocation.ARCHIVED:
|
||||
data_archive = {}
|
||||
data_unpin = {}
|
||||
for thread in threads:
|
||||
@@ -587,9 +581,9 @@ class Client:
|
||||
data = {}
|
||||
for i, thread in enumerate(threads):
|
||||
data["{}[{}]".format(location.name.lower(), i)] = thread.id
|
||||
j = self.session._payload_post("/ajax/mercury/move_thread.php", data)
|
||||
j = self.session._payload_post("/ajax/mercury/move_threads.php", data)
|
||||
|
||||
def delete_threads(self, threads: Iterable[_thread.ThreadABC]):
|
||||
def delete_threads(self, threads: Iterable[_threads.ThreadABC]):
|
||||
"""Bulk delete threads.
|
||||
|
||||
Args:
|
||||
@@ -608,7 +602,7 @@ class Client:
|
||||
"/ajax/mercury/change_pinned_status.php?dpr=1", data_unpin
|
||||
)
|
||||
j_delete = self.session._payload_post(
|
||||
"/ajax/mercury/delete_thread.php?dpr=1", data_delete
|
||||
"/ajax/mercury/delete_threads.php?dpr=1", data_delete
|
||||
)
|
||||
|
||||
def delete_messages(self, messages: Iterable[_message.Message]):
|
||||
|
@@ -6,7 +6,7 @@ from ._client_payload import *
|
||||
from ._delta_class import *
|
||||
from ._delta_type import *
|
||||
|
||||
from .. import _exception, _util, _user, _group, _thread
|
||||
from .. import _exception, _util, _threads
|
||||
|
||||
from typing import Mapping
|
||||
|
||||
@@ -20,15 +20,15 @@ class Typing(ThreadEvent):
|
||||
|
||||
@classmethod
|
||||
def _parse_orca(cls, session, data):
|
||||
author = _user.User(session=session, id=str(data["sender_fbid"]))
|
||||
author = _threads.User(session=session, id=str(data["sender_fbid"]))
|
||||
status = data["state"] == 1
|
||||
return cls(author=author, thread=author, status=status)
|
||||
|
||||
@classmethod
|
||||
def _parse(cls, session, data):
|
||||
# TODO: Rename this method
|
||||
author = _user.User(session=session, id=str(data["sender_fbid"]))
|
||||
thread = _group.Group(session=session, id=str(data["thread"]))
|
||||
author = _threads.User(session=session, id=str(data["sender_fbid"]))
|
||||
thread = _threads.Group(session=session, id=str(data["thread"]))
|
||||
status = data["state"] == 1
|
||||
return cls(author=author, thread=thread, status=status)
|
||||
|
||||
@@ -38,11 +38,11 @@ class FriendRequest(Event):
|
||||
"""Somebody sent a friend request."""
|
||||
|
||||
#: The user that sent the request
|
||||
author = attr.ib(type=_user.User)
|
||||
author = attr.ib(type="_threads.User")
|
||||
|
||||
@classmethod
|
||||
def _parse(cls, session, data):
|
||||
author = _user.User(session=session, id=str(data["from"]))
|
||||
author = _threads.User(session=session, id=str(data["from"]))
|
||||
return cls(author=author)
|
||||
|
||||
|
||||
@@ -56,14 +56,15 @@ class Presence(Event):
|
||||
# TODO: Document this better!
|
||||
|
||||
#: User ids mapped to their active status
|
||||
statuses = attr.ib(type=Mapping[str, _user.ActiveStatus])
|
||||
statuses = attr.ib(type=Mapping[str, _threads.ActiveStatus])
|
||||
#: ``True`` if the list is fully updated and ``False`` if it's partially updated
|
||||
full = attr.ib(type=bool)
|
||||
|
||||
@classmethod
|
||||
def _parse(cls, session, data):
|
||||
statuses = {
|
||||
str(d["u"]): _user.ActiveStatus._from_orca_presence(d) for d in data["list"]
|
||||
str(d["u"]): _threads.ActiveStatus._from_orca_presence(d)
|
||||
for d in data["list"]
|
||||
}
|
||||
return cls(statuses=statuses, full=data["list_type"] == "full")
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import attr
|
||||
import datetime
|
||||
from ._common import attrs_event, UnknownEvent, ThreadEvent
|
||||
from .. import _exception, _util, _user, _message
|
||||
from .. import _exception, _util, _threads, _message
|
||||
|
||||
from typing import Optional
|
||||
|
||||
@@ -25,7 +25,7 @@ class ReactionEvent(ThreadEvent):
|
||||
def _parse(cls, session, data):
|
||||
thread = cls._get_thread(session, data)
|
||||
return cls(
|
||||
author=_user.User(session=session, id=str(data["userId"])),
|
||||
author=_threads.User(session=session, id=str(data["userId"])),
|
||||
thread=thread,
|
||||
message=_message.Message(thread=thread, id=data["messageId"]),
|
||||
reaction=data["reaction"] if data["action"] == 0 else None,
|
||||
@@ -40,7 +40,7 @@ class UserStatusEvent(ThreadEvent):
|
||||
@classmethod
|
||||
def _parse(cls, session, data):
|
||||
return cls(
|
||||
author=_user.User(session=session, id=str(data["actorFbid"])),
|
||||
author=_threads.User(session=session, id=str(data["actorFbid"])),
|
||||
thread=cls._get_thread(session, data),
|
||||
blocked=not data["canViewerReply"],
|
||||
)
|
||||
@@ -59,7 +59,7 @@ class LiveLocationEvent(ThreadEvent):
|
||||
thread = cls._get_thread(session, data)
|
||||
for location_data in data["messageLiveLocations"]:
|
||||
message = _message.Message(thread=thread, id=data["messageId"])
|
||||
author = _user.User(session=session, id=str(location_data["senderId"]))
|
||||
author = _threads.User(session=session, id=str(location_data["senderId"]))
|
||||
location = _location.LiveLocationAttachment._from_pull(location_data)
|
||||
|
||||
return None
|
||||
@@ -78,7 +78,7 @@ class UnsendEvent(ThreadEvent):
|
||||
def _parse(cls, session, data):
|
||||
thread = cls._get_thread(session, data)
|
||||
return cls(
|
||||
author=_user.User(session=session, id=str(data["senderID"])),
|
||||
author=_threads.User(session=session, id=str(data["senderID"])),
|
||||
thread=thread,
|
||||
message=_message.Message(thread=thread, id=data["messageID"]),
|
||||
at=_util.millis_to_datetime(data["deletionTimestamp"]),
|
||||
@@ -99,7 +99,7 @@ class MessageReplyEvent(ThreadEvent):
|
||||
metadata = data["message"]["messageMetadata"]
|
||||
thread = cls._get_thread(session, metadata)
|
||||
return cls(
|
||||
author=_user.User(session=session, id=str(metadata["actorFbId"])),
|
||||
author=_threads.User(session=session, id=str(metadata["actorFbId"])),
|
||||
thread=thread,
|
||||
message=_message.MessageData._from_reply(thread, data["message"]),
|
||||
replied_to=_message.MessageData._from_reply(
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import attr
|
||||
import abc
|
||||
from .._common import kw_only
|
||||
from .. import _exception, _util, _thread, _group, _user, _message
|
||||
from .. import _exception, _util, _threads, _message
|
||||
|
||||
from typing import Any
|
||||
|
||||
@@ -38,9 +38,9 @@ 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]?
|
||||
author = attr.ib(type="_threads.User") # Or Union[User, Page]?
|
||||
#: Thread that the action was done in
|
||||
thread = attr.ib(type=_thread.ThreadABC)
|
||||
thread = attr.ib(type="_threads.ThreadABC")
|
||||
|
||||
@staticmethod
|
||||
def _get_thread(session, data):
|
||||
@@ -48,15 +48,15 @@ class ThreadEvent(Event):
|
||||
key = data["threadKey"]
|
||||
|
||||
if "threadFbId" in key:
|
||||
return _group.Group(session=session, id=str(key["threadFbId"]))
|
||||
return _threads.Group(session=session, id=str(key["threadFbId"]))
|
||||
elif "otherUserFbId" in key:
|
||||
return _user.User(session=session, id=str(key["otherUserFbId"]))
|
||||
return _threads.User(session=session, id=str(key["otherUserFbId"]))
|
||||
raise _exception.ParseError("Could not find thread data", data=data)
|
||||
|
||||
@staticmethod
|
||||
def _parse_metadata(session, data):
|
||||
metadata = data["messageMetadata"]
|
||||
author = _user.User(session=session, id=metadata["actorFbId"])
|
||||
author = _threads.User(session=session, id=metadata["actorFbId"])
|
||||
thread = ThreadEvent._get_thread(session, metadata)
|
||||
at = _util.millis_to_datetime(int(metadata["timestamp"]))
|
||||
return author, thread, at
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import attr
|
||||
import datetime
|
||||
from ._common import attrs_event, Event, UnknownEvent, ThreadEvent
|
||||
from .. import _util, _user, _group, _thread, _message
|
||||
from .. import _util, _threads, _message
|
||||
|
||||
from typing import Sequence, Optional
|
||||
|
||||
@@ -12,9 +12,9 @@ class PeopleAdded(ThreadEvent):
|
||||
|
||||
# TODO: Add message id
|
||||
|
||||
thread = attr.ib(type=_group.Group) # Set the correct type
|
||||
thread = attr.ib(type="_threads.Group") # Set the correct type
|
||||
#: The people who got added
|
||||
added = attr.ib(type=Sequence[_user.User])
|
||||
added = attr.ib(type=Sequence["_threads.User"])
|
||||
#: When the people were added
|
||||
at = attr.ib(type=datetime.datetime)
|
||||
|
||||
@@ -23,7 +23,7 @@ class PeopleAdded(ThreadEvent):
|
||||
author, thread, at = cls._parse_metadata(session, data)
|
||||
added = [
|
||||
# TODO: Parse user name
|
||||
_user.User(session=session, id=x["userFbId"])
|
||||
_threads.User(session=session, id=x["userFbId"])
|
||||
for x in data["addedParticipants"]
|
||||
]
|
||||
return cls(author=author, thread=thread, added=added, at=at)
|
||||
@@ -35,7 +35,7 @@ class PersonRemoved(ThreadEvent):
|
||||
|
||||
# TODO: Add message id
|
||||
|
||||
thread = attr.ib(type=_group.Group) # Set the correct type
|
||||
thread = attr.ib(type="_threads.Group") # Set the correct type
|
||||
#: Person who got removed
|
||||
removed = attr.ib(type=_message.Message)
|
||||
#: When the person were removed
|
||||
@@ -44,7 +44,7 @@ class PersonRemoved(ThreadEvent):
|
||||
@classmethod
|
||||
def _parse(cls, session, data):
|
||||
author, thread, at = cls._parse_metadata(session, data)
|
||||
removed = _user.User(session=session, id=data["leftParticipantFbId"])
|
||||
removed = _threads.User(session=session, id=data["leftParticipantFbId"])
|
||||
return cls(author=author, thread=thread, removed=removed, at=at)
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ class PersonRemoved(ThreadEvent):
|
||||
class TitleSet(ThreadEvent):
|
||||
"""Somebody changed a group's title."""
|
||||
|
||||
thread = attr.ib(type=_group.Group) # Set the correct type
|
||||
thread = attr.ib(type="_threads.Group") # Set the correct type
|
||||
#: The new title
|
||||
title = attr.ib(type=str)
|
||||
#: When the title was set
|
||||
@@ -77,7 +77,7 @@ class UnfetchedThreadEvent(Event):
|
||||
# TODO: Present this in a way that users can fetch the changed group photo easily
|
||||
|
||||
#: The thread the message was sent to
|
||||
thread = attr.ib(type=_thread.ThreadABC)
|
||||
thread = attr.ib(type="_threads.ThreadABC")
|
||||
#: The message
|
||||
message = attr.ib(type=Optional[_message.Message])
|
||||
|
||||
@@ -103,7 +103,7 @@ class MessagesDelivered(ThreadEvent):
|
||||
def _parse(cls, session, data):
|
||||
thread = cls._get_thread(session, data)
|
||||
if "actorFbId" in data:
|
||||
author = _user.User(session=session, id=data["actorFbId"])
|
||||
author = _threads.User(session=session, id=data["actorFbId"])
|
||||
else:
|
||||
author = thread
|
||||
messages = [_message.Message(thread=thread, id=x) for x in data["messageIds"]]
|
||||
@@ -116,22 +116,22 @@ class ThreadsRead(Event):
|
||||
"""Somebody marked threads as read/seen."""
|
||||
|
||||
#: The person who marked the threads as read
|
||||
author = attr.ib(type=_thread.ThreadABC)
|
||||
author = attr.ib(type="_threads.ThreadABC")
|
||||
#: The threads that were marked as read
|
||||
threads = attr.ib(type=Sequence[_thread.ThreadABC])
|
||||
threads = attr.ib(type=Sequence["_threads.ThreadABC"])
|
||||
#: When the threads were read
|
||||
at = attr.ib(type=datetime.datetime)
|
||||
|
||||
@classmethod
|
||||
def _parse_read_receipt(cls, session, data):
|
||||
author = _user.User(session=session, id=data["actorFbId"])
|
||||
author = _threads.User(session=session, id=data["actorFbId"])
|
||||
thread = ThreadEvent._get_thread(session, data)
|
||||
at = _util.millis_to_datetime(int(data["actionTimestampMs"]))
|
||||
return cls(author=author, threads=[thread], at=at)
|
||||
|
||||
@classmethod
|
||||
def _parse(cls, session, data):
|
||||
author = _user.User(session=session, id=session.user_id)
|
||||
author = _threads.User(session=session, id=session.user_id)
|
||||
threads = [
|
||||
ThreadEvent._get_thread(session, {"threadKey": x})
|
||||
for x in data["threadKeys"]
|
||||
@@ -169,14 +169,14 @@ class ThreadFolder(Event):
|
||||
# TODO: Finish this
|
||||
|
||||
#: The created thread
|
||||
thread = attr.ib(type=_thread.ThreadABC)
|
||||
thread = attr.ib(type="_threads.ThreadABC")
|
||||
#: The folder/location
|
||||
folder = attr.ib(type=_thread.ThreadLocation)
|
||||
folder = attr.ib(type=_threads.ThreadLocation)
|
||||
|
||||
@classmethod
|
||||
def _parse(cls, session, data):
|
||||
thread = ThreadEvent._get_thread(session, data)
|
||||
folder = _thread.ThreadLocation._parse(data["folder"])
|
||||
folder = _threads.ThreadLocation._parse(data["folder"])
|
||||
return cls(thread=thread, folder=folder)
|
||||
|
||||
|
||||
@@ -188,7 +188,7 @@ def parse_delta(session, data):
|
||||
return PersonRemoved._parse(session, data)
|
||||
elif class_ == "MarkFolderSeen":
|
||||
# TODO: Finish this
|
||||
folders = [_thread.ThreadLocation._parse(folder) for folder in data["folders"]]
|
||||
folders = [_threads.ThreadLocation._parse(folder) for folder in data["folders"]]
|
||||
at = _util.millis_to_datetime(int(data["timestamp"]))
|
||||
return None
|
||||
elif class_ == "ThreadName":
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import attr
|
||||
import datetime
|
||||
from ._common import attrs_event, Event, UnknownEvent, ThreadEvent
|
||||
from .. import _util, _user, _thread, _poll, _plan
|
||||
from .. import _util, _threads, _poll, _plan
|
||||
|
||||
from typing import Sequence, Optional
|
||||
|
||||
@@ -18,7 +18,7 @@ class ColorSet(ThreadEvent):
|
||||
@classmethod
|
||||
def _parse(cls, session, data):
|
||||
author, thread, at = cls._parse_metadata(session, data)
|
||||
color = _thread.ThreadABC._parse_color(data["untypedData"]["theme_color"])
|
||||
color = _threads.ThreadABC._parse_color(data["untypedData"]["theme_color"])
|
||||
return cls(author=author, thread=thread, color=color, at=at)
|
||||
|
||||
|
||||
@@ -52,7 +52,9 @@ class NicknameSet(ThreadEvent):
|
||||
@classmethod
|
||||
def _parse(cls, session, data):
|
||||
author, thread, at = cls._parse_metadata(session, data)
|
||||
subject = _user.User(session=session, id=data["untypedData"]["participant_id"])
|
||||
subject = _threads.User(
|
||||
session=session, id=data["untypedData"]["participant_id"]
|
||||
)
|
||||
nickname = data["untypedData"]["nickname"] or None # None if ""
|
||||
return cls(
|
||||
author=author, thread=thread, subject=subject, nickname=nickname, at=at
|
||||
@@ -64,14 +66,14 @@ class AdminsAdded(ThreadEvent):
|
||||
"""Somebody added admins to a group."""
|
||||
|
||||
#: The people that were set as admins
|
||||
added = attr.ib(type=Sequence[_user.User])
|
||||
added = attr.ib(type=Sequence["_threads.User"])
|
||||
#: When the admins were added
|
||||
at = attr.ib(type=datetime.datetime)
|
||||
|
||||
@classmethod
|
||||
def _parse(cls, session, data):
|
||||
author, thread, at = cls._parse_metadata(session, data)
|
||||
subject = _user.User(session=session, id=data["untypedData"]["TARGET_ID"])
|
||||
subject = _threads.User(session=session, id=data["untypedData"]["TARGET_ID"])
|
||||
return cls(author=author, thread=thread, added=[subject], at=at)
|
||||
|
||||
|
||||
@@ -80,14 +82,14 @@ class AdminsRemoved(ThreadEvent):
|
||||
"""Somebody removed admins from a group."""
|
||||
|
||||
#: The people that were removed as admins
|
||||
removed = attr.ib(type=Sequence[_user.User])
|
||||
removed = attr.ib(type=Sequence["_threads.User"])
|
||||
#: When the admins were removed
|
||||
at = attr.ib(type=datetime.datetime)
|
||||
|
||||
@classmethod
|
||||
def _parse(cls, session, data):
|
||||
author, thread, at = cls._parse_metadata(session, data)
|
||||
subject = _user.User(session=session, id=data["untypedData"]["TARGET_ID"])
|
||||
subject = _threads.User(session=session, id=data["untypedData"]["TARGET_ID"])
|
||||
return cls(author=author, thread=thread, removed=[subject], at=at)
|
||||
|
||||
|
||||
|
@@ -12,7 +12,7 @@ from . import (
|
||||
_file,
|
||||
_quick_reply,
|
||||
_sticker,
|
||||
_thread,
|
||||
_threads,
|
||||
)
|
||||
from typing import Optional, Mapping, Sequence
|
||||
|
||||
@@ -94,7 +94,7 @@ class Message:
|
||||
"""
|
||||
|
||||
#: The thread that this message belongs to.
|
||||
thread = attr.ib(type="_thread.ThreadABC")
|
||||
thread = attr.ib(type="_threads.ThreadABC")
|
||||
#: The message ID.
|
||||
id = attr.ib(converter=str, type=str)
|
||||
|
||||
|
4
fbchat/_threads/__init__.py
Normal file
4
fbchat/_threads/__init__.py
Normal file
@@ -0,0 +1,4 @@
|
||||
from ._abc import *
|
||||
from ._group import *
|
||||
from ._user import *
|
||||
from ._page import *
|
@@ -3,8 +3,17 @@ import attr
|
||||
import collections
|
||||
import datetime
|
||||
import enum
|
||||
from ._common import log, attrs_default, Image
|
||||
from . import _util, _exception, _session, _graphql, _attachment, _file, _plan, _message
|
||||
from .._common import log, attrs_default, Image
|
||||
from .. import (
|
||||
_util,
|
||||
_exception,
|
||||
_session,
|
||||
_graphql,
|
||||
_attachment,
|
||||
_file,
|
||||
_plan,
|
||||
_message,
|
||||
)
|
||||
from typing import MutableMapping, Mapping, Any, Iterable, Tuple, Optional
|
||||
|
||||
|
@@ -1,12 +1,14 @@
|
||||
import attr
|
||||
import datetime
|
||||
from ._common import attrs_default, Image
|
||||
from . import _util, _session, _graphql, _plan, _thread, _user
|
||||
from ._abc import ThreadABC
|
||||
from . import _user
|
||||
from .._common import attrs_default, Image
|
||||
from .. import _util, _session, _graphql, _plan
|
||||
from typing import Sequence, Iterable, Set, Mapping
|
||||
|
||||
|
||||
@attrs_default
|
||||
class Group(_thread.ThreadABC):
|
||||
class Group(ThreadABC):
|
||||
"""Represents a Facebook group. Implements `ThreadABC`.
|
||||
|
||||
Example:
|
||||
@@ -245,7 +247,7 @@ class GroupData(Group):
|
||||
|
||||
|
||||
@attrs_default
|
||||
class NewGroup(_thread.ThreadABC):
|
||||
class NewGroup(ThreadABC):
|
||||
"""Helper class to create new groups.
|
||||
|
||||
TODO: Complete this!
|
||||
@@ -256,7 +258,7 @@ class NewGroup(_thread.ThreadABC):
|
||||
#: The session to use when making requests.
|
||||
session = attr.ib(type=_session.Session)
|
||||
#: The users that should be added to the group.
|
||||
_users = attr.ib(type=Sequence[_user.User])
|
||||
_users = attr.ib(type=Sequence["_user.User"])
|
||||
|
||||
@property
|
||||
def id(self):
|
@@ -1,11 +1,12 @@
|
||||
import attr
|
||||
import datetime
|
||||
from ._common import attrs_default, Image
|
||||
from . import _session, _plan, _thread
|
||||
from ._abc import ThreadABC
|
||||
from .._common import attrs_default, Image
|
||||
from .. import _session, _plan
|
||||
|
||||
|
||||
@attrs_default
|
||||
class Page(_thread.ThreadABC):
|
||||
class Page(ThreadABC):
|
||||
"""Represents a Facebook page. Implements `ThreadABC`.
|
||||
|
||||
Example:
|
@@ -1,7 +1,8 @@
|
||||
import attr
|
||||
import datetime
|
||||
from ._common import log, attrs_default, Image
|
||||
from . import _util, _session, _plan, _thread
|
||||
from ._abc import ThreadABC
|
||||
from .._common import log, attrs_default, Image
|
||||
from .. import _util, _session, _plan
|
||||
|
||||
|
||||
GENDERS = {
|
||||
@@ -35,7 +36,7 @@ GENDERS = {
|
||||
|
||||
|
||||
@attrs_default
|
||||
class User(_thread.ThreadABC):
|
||||
class User(ThreadABC):
|
||||
"""Represents a Facebook user. Implements `ThreadABC`.
|
||||
|
||||
Example:
|
@@ -1,5 +1,5 @@
|
||||
import fbchat
|
||||
from fbchat._page import PageData
|
||||
from fbchat import PageData
|
||||
|
||||
|
||||
def test_page_from_graphql(session):
|
@@ -1,7 +1,7 @@
|
||||
import pytest
|
||||
import datetime
|
||||
import fbchat
|
||||
from fbchat._user import UserData, ActiveStatus
|
||||
from fbchat import UserData, ActiveStatus
|
||||
|
||||
|
||||
def test_user_from_graphql(session):
|
Reference in New Issue
Block a user