Merge pull request #502 from carpedm20/remove-enums
Remove extraneous enums
This commit is contained in:
@@ -28,8 +28,6 @@ Messages
|
|||||||
.. autoclass:: Mention
|
.. autoclass:: Mention
|
||||||
.. autoclass:: EmojiSize(Enum)
|
.. autoclass:: EmojiSize(Enum)
|
||||||
:undoc-members:
|
:undoc-members:
|
||||||
.. autoclass:: MessageReaction(Enum)
|
|
||||||
:undoc-members:
|
|
||||||
|
|
||||||
Exceptions
|
Exceptions
|
||||||
----------
|
----------
|
||||||
@@ -56,11 +54,7 @@ Miscellaneous
|
|||||||
|
|
||||||
.. autoclass:: ThreadLocation(Enum)
|
.. autoclass:: ThreadLocation(Enum)
|
||||||
:undoc-members:
|
:undoc-members:
|
||||||
.. autoclass:: ThreadColor(Enum)
|
|
||||||
:undoc-members:
|
|
||||||
.. autoclass:: ActiveStatus()
|
.. autoclass:: ActiveStatus()
|
||||||
.. autoclass:: TypingStatus(Enum)
|
|
||||||
:undoc-members:
|
|
||||||
|
|
||||||
.. autoclass:: QuickReply
|
.. autoclass:: QuickReply
|
||||||
.. autoclass:: QuickReplyText
|
.. autoclass:: QuickReplyText
|
||||||
|
@@ -70,8 +70,8 @@ corresponds to the ID of a single user, and the ID of a group respectively::
|
|||||||
Some functions don't require a thread type, so in these cases you just provide the thread ID::
|
Some functions don't require a thread type, so in these cases you just provide the thread ID::
|
||||||
|
|
||||||
thread = fbchat.Thread(session=session, id="<user-or-group-id>")
|
thread = fbchat.Thread(session=session, id="<user-or-group-id>")
|
||||||
thread.set_color(ThreadColor.BILOBA_FLOWER)
|
thread.set_color("#a695c7")
|
||||||
thread.set_color(ThreadColor.MESSENGER_BLUE)
|
thread.set_color("#67b868")
|
||||||
|
|
||||||
|
|
||||||
.. _intro_message_ids:
|
.. _intro_message_ids:
|
||||||
@@ -82,12 +82,10 @@ Message IDs
|
|||||||
Every message you send on Facebook has a unique ID, and every action you do in a thread,
|
Every message you send on Facebook has a unique ID, and every action you do in a thread,
|
||||||
like changing a nickname or adding a person, has a unique ID too.
|
like changing a nickname or adding a person, has a unique ID too.
|
||||||
|
|
||||||
Some of ``fbchat``'s functions require these ID's, like `Client.react_to_message`,
|
|
||||||
and some of then provide this ID, like `Client.send`.
|
|
||||||
This snippet shows how to send a message, and then use the returned ID to react to that message with a 😍 emoji::
|
This snippet shows how to send a message, and then use the returned ID to react to that message with a 😍 emoji::
|
||||||
|
|
||||||
message_id = thread.send(Message(text='message'))
|
message = thread.send_text("A message!")
|
||||||
client.react_to_message(message_id, MessageReaction.LOVE)
|
message.react("😍")
|
||||||
|
|
||||||
|
|
||||||
.. _intro_interacting:
|
.. _intro_interacting:
|
||||||
|
@@ -54,8 +54,8 @@ thread.set_nickname(fbchat.User(session=session, id="<user id>"), "<new nickname
|
|||||||
# Will set the typing status of the thread
|
# Will set the typing status of the thread
|
||||||
thread.start_typing()
|
thread.start_typing()
|
||||||
|
|
||||||
# Will change the thread color to `MESSENGER_BLUE`
|
# Will change the thread color to #0084ff
|
||||||
thread.set_color(fbchat.ThreadColor.MESSENGER_BLUE)
|
thread.set_color("#0084ff")
|
||||||
|
|
||||||
# Will change the thread emoji to `👍`
|
# Will change the thread emoji to `👍`
|
||||||
thread.set_emoji("👍")
|
thread.set_emoji("👍")
|
||||||
@@ -63,4 +63,4 @@ thread.set_emoji("👍")
|
|||||||
message = fbchat.Message(session=session, id="<message id>")
|
message = fbchat.Message(session=session, id="<message id>")
|
||||||
|
|
||||||
# Will react to a message with a 😍 emoji
|
# Will react to a message with a 😍 emoji
|
||||||
message.react(fbchat.MessageReaction.LOVE)
|
message.react("😍")
|
||||||
|
@@ -4,7 +4,7 @@ import fbchat
|
|||||||
old_thread_id = "1234567890"
|
old_thread_id = "1234567890"
|
||||||
|
|
||||||
# Change these to match your liking
|
# Change these to match your liking
|
||||||
old_color = fbchat.ThreadColor.MESSENGER_BLUE
|
old_color = "#0084ff"
|
||||||
old_emoji = "👍"
|
old_emoji = "👍"
|
||||||
old_title = "Old group chat name"
|
old_title = "Old group chat name"
|
||||||
old_nicknames = {
|
old_nicknames = {
|
||||||
|
@@ -14,11 +14,11 @@ 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 ThreadLocation, ThreadColor, ThreadABC, Thread
|
from ._thread import ThreadLocation, ThreadABC, Thread
|
||||||
from ._user import TypingStatus, User, UserData, ActiveStatus
|
from ._user import User, UserData, ActiveStatus
|
||||||
from ._group import Group, GroupData
|
from ._group import Group, GroupData
|
||||||
from ._page import Page, PageData
|
from ._page import Page, PageData
|
||||||
from ._message import EmojiSize, MessageReaction, Mention, Message
|
from ._message import EmojiSize, Mention, Message
|
||||||
from ._attachment import Attachment, UnsentMessage, ShareAttachment
|
from ._attachment import Attachment, UnsentMessage, ShareAttachment
|
||||||
from ._sticker import Sticker
|
from ._sticker import Sticker
|
||||||
from ._location import LocationAttachment, LiveLocationAttachment
|
from ._location import LocationAttachment, LiveLocationAttachment
|
||||||
|
@@ -6,11 +6,11 @@ from ._core import log
|
|||||||
from . import _util, _graphql, _session
|
from . import _util, _graphql, _session
|
||||||
|
|
||||||
from ._exception import FBchatException, FBchatFacebookError
|
from ._exception import FBchatException, FBchatFacebookError
|
||||||
from ._thread import ThreadLocation, ThreadColor
|
from ._thread import ThreadLocation
|
||||||
from ._user import TypingStatus, User, UserData, ActiveStatus
|
from ._user import User, UserData, ActiveStatus
|
||||||
from ._group import Group, GroupData
|
from ._group import Group, GroupData
|
||||||
from ._page import Page, PageData
|
from ._page import Page, PageData
|
||||||
from ._message import EmojiSize, MessageReaction, Mention, Message
|
from ._message import EmojiSize, Mention, Message
|
||||||
from ._attachment import Attachment
|
from ._attachment import Attachment
|
||||||
from ._sticker import Sticker
|
from ._sticker import Sticker
|
||||||
from ._location import LocationAttachment, LiveLocationAttachment
|
from ._location import LocationAttachment, LiveLocationAttachment
|
||||||
@@ -947,12 +947,11 @@ class Client:
|
|||||||
|
|
||||||
# Color change
|
# Color change
|
||||||
elif delta_type == "change_thread_theme":
|
elif delta_type == "change_thread_theme":
|
||||||
new_color = ThreadColor._from_graphql(delta["untypedData"]["theme_color"])
|
|
||||||
thread = get_thread(metadata)
|
thread = get_thread(metadata)
|
||||||
self.on_color_change(
|
self.on_color_change(
|
||||||
mid=mid,
|
mid=mid,
|
||||||
author_id=author_id,
|
author_id=author_id,
|
||||||
new_color=new_color,
|
new_color=ThreadABC._parse_color(delta["untypedData"]["theme_color"]),
|
||||||
thread=get_thread(metadata),
|
thread=get_thread(metadata),
|
||||||
at=at,
|
at=at,
|
||||||
metadata=metadata,
|
metadata=metadata,
|
||||||
@@ -1259,14 +1258,11 @@ class Client:
|
|||||||
i = d["deltaMessageReaction"]
|
i = d["deltaMessageReaction"]
|
||||||
mid = i["messageId"]
|
mid = i["messageId"]
|
||||||
author_id = str(i["userId"])
|
author_id = str(i["userId"])
|
||||||
reaction = (
|
|
||||||
MessageReaction(i["reaction"]) if i.get("reaction") else None
|
|
||||||
)
|
|
||||||
add_reaction = not bool(i["action"])
|
add_reaction = not bool(i["action"])
|
||||||
if add_reaction:
|
if add_reaction:
|
||||||
self.on_reaction_added(
|
self.on_reaction_added(
|
||||||
mid=mid,
|
mid=mid,
|
||||||
reaction=reaction,
|
reaction=i.get("reaction"),
|
||||||
author_id=author_id,
|
author_id=author_id,
|
||||||
thread=get_thread(metadata),
|
thread=get_thread(metadata),
|
||||||
at=at,
|
at=at,
|
||||||
@@ -1405,9 +1401,8 @@ class Client:
|
|||||||
else:
|
else:
|
||||||
thread_id = author_id
|
thread_id = author_id
|
||||||
thread = User(session=self.session, id=thread_id)
|
thread = User(session=self.session, id=thread_id)
|
||||||
typing_status = TypingStatus(m.get("st"))
|
|
||||||
self.on_typing(
|
self.on_typing(
|
||||||
author_id=author_id, status=typing_status, thread=thread,
|
author_id=author_id, status=m["st"] == 1, thread=thread
|
||||||
)
|
)
|
||||||
|
|
||||||
# Delivered
|
# Delivered
|
||||||
@@ -1569,7 +1564,7 @@ class Client:
|
|||||||
Args:
|
Args:
|
||||||
mid: The action ID
|
mid: The action ID
|
||||||
author_id: The ID of the person who changed the color
|
author_id: The ID of the person who changed the color
|
||||||
new_color (ThreadColor): The new color
|
new_color: The new color. Not limited to the ones in `ThreadABC.set_color`
|
||||||
thread: Thread that the action was sent to. See :ref:`intro_threads`
|
thread: Thread that the action was sent to. See :ref:`intro_threads`
|
||||||
at (datetime.datetime): When the action was executed
|
at (datetime.datetime): When the action was executed
|
||||||
metadata: Extra metadata about the action
|
metadata: Extra metadata about the action
|
||||||
@@ -1816,7 +1811,7 @@ class Client:
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
author_id: The ID of the person who sent the action
|
author_id: The ID of the person who sent the action
|
||||||
status (TypingStatus): The typing status
|
is_typing: ``True`` if the user started typing, ``False`` if they stopped.
|
||||||
thread: Thread that the action was sent to. See :ref:`intro_threads`
|
thread: Thread that the action was sent to. See :ref:`intro_threads`
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
@@ -1855,7 +1850,7 @@ class Client:
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
mid: Message ID, that user reacted to
|
mid: Message ID, that user reacted to
|
||||||
reaction (MessageReaction): Reaction
|
reaction: The added reaction. Not limited to the ones in `Message.react`
|
||||||
add_reaction: Whether user added or removed reaction
|
add_reaction: Whether user added or removed reaction
|
||||||
author_id: The ID of the person who reacted to the message
|
author_id: The ID of the person who reacted to the message
|
||||||
thread: Thread that the action was sent to. See :ref:`intro_threads`
|
thread: Thread that the action was sent to. See :ref:`intro_threads`
|
||||||
@@ -1863,7 +1858,7 @@ class Client:
|
|||||||
"""
|
"""
|
||||||
log.info(
|
log.info(
|
||||||
"{} reacted to message {} with {} in {}".format(
|
"{} reacted to message {} with {} in {}".format(
|
||||||
author_id, mid, reaction.name, thread
|
author_id, mid, reaction, thread
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -1,7 +1,6 @@
|
|||||||
import sys
|
import sys
|
||||||
import attr
|
import attr
|
||||||
import logging
|
import logging
|
||||||
import aenum
|
|
||||||
|
|
||||||
log = logging.getLogger("fbchat")
|
log = logging.getLogger("fbchat")
|
||||||
|
|
||||||
@@ -12,25 +11,6 @@ kw_only = sys.version_info[:2] > (3, 5)
|
|||||||
attrs_default = attr.s(slots=True, kw_only=kw_only)
|
attrs_default = attr.s(slots=True, kw_only=kw_only)
|
||||||
|
|
||||||
|
|
||||||
class Enum(aenum.Enum):
|
|
||||||
"""Used internally to support enumerations"""
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
# For documentation:
|
|
||||||
return "{}.{}".format(type(self).__name__, self.name)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def _extend_if_invalid(cls, value):
|
|
||||||
try:
|
|
||||||
return cls(value)
|
|
||||||
except ValueError:
|
|
||||||
log.warning(
|
|
||||||
"Failed parsing {.__name__}({!r}). Extending enum.".format(cls, value)
|
|
||||||
)
|
|
||||||
aenum.extend_enum(cls, "UNKNOWN_{}".format(value).upper(), value)
|
|
||||||
return cls(value)
|
|
||||||
|
|
||||||
|
|
||||||
# Frozen, so that it can be used in sets
|
# Frozen, so that it can be used in sets
|
||||||
@attr.s(frozen=True, slots=True, kw_only=kw_only)
|
@attr.s(frozen=True, slots=True, kw_only=kw_only)
|
||||||
class Image:
|
class Image:
|
||||||
|
@@ -150,7 +150,7 @@ class GroupData(Group):
|
|||||||
participants = attr.ib(factory=set)
|
participants = attr.ib(factory=set)
|
||||||
#: A dictionary, containing user nicknames mapped to their IDs
|
#: A dictionary, containing user nicknames mapped to their IDs
|
||||||
nicknames = attr.ib(factory=dict)
|
nicknames = attr.ib(factory=dict)
|
||||||
#: A `ThreadColor`. The groups's message color
|
#: The groups's message color
|
||||||
color = attr.ib(None)
|
color = attr.ib(None)
|
||||||
#: The groups's default emoji
|
#: The groups's default emoji
|
||||||
emoji = attr.ib(None)
|
emoji = attr.ib(None)
|
||||||
@@ -189,8 +189,8 @@ class GroupData(Group):
|
|||||||
]
|
]
|
||||||
),
|
),
|
||||||
nicknames=c_info.get("nicknames"),
|
nicknames=c_info.get("nicknames"),
|
||||||
color=c_info.get("color"),
|
color=c_info["color"],
|
||||||
emoji=c_info.get("emoji"),
|
emoji=c_info["emoji"],
|
||||||
admins=set([node.get("id") for node in data.get("thread_admins")]),
|
admins=set([node.get("id") for node in data.get("thread_admins")]),
|
||||||
approval_mode=bool(data.get("approval_mode"))
|
approval_mode=bool(data.get("approval_mode"))
|
||||||
if data.get("approval_mode") is not None
|
if data.get("approval_mode") is not None
|
||||||
|
@@ -1,11 +1,12 @@
|
|||||||
import attr
|
import attr
|
||||||
|
import enum
|
||||||
from string import Formatter
|
from string import Formatter
|
||||||
from ._core import log, attrs_default, Enum
|
from ._core import log, attrs_default
|
||||||
from . import _util, _session, _attachment, _location, _file, _quick_reply, _sticker
|
from . import _util, _session, _attachment, _location, _file, _quick_reply, _sticker
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
|
|
||||||
class EmojiSize(Enum):
|
class EmojiSize(enum.Enum):
|
||||||
"""Used to specify the size of a sent emoji."""
|
"""Used to specify the size of a sent emoji."""
|
||||||
|
|
||||||
LARGE = "369239383222810"
|
LARGE = "369239383222810"
|
||||||
@@ -29,19 +30,6 @@ class EmojiSize(Enum):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
class MessageReaction(Enum):
|
|
||||||
"""Used to specify a message reaction."""
|
|
||||||
|
|
||||||
HEART = "❤"
|
|
||||||
LOVE = "😍"
|
|
||||||
SMILE = "😆"
|
|
||||||
WOW = "😮"
|
|
||||||
SAD = "😢"
|
|
||||||
ANGRY = "😠"
|
|
||||||
YES = "👍"
|
|
||||||
NO = "👎"
|
|
||||||
|
|
||||||
|
|
||||||
@attrs_default
|
@attrs_default
|
||||||
class Mention:
|
class Mention:
|
||||||
"""Represents a ``@mention``."""
|
"""Represents a ``@mention``."""
|
||||||
@@ -74,6 +62,9 @@ class Mention:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SENDABLE_REACTIONS = ("❤", "😍", "😆", "😮", "😢", "😠", "👍", "👎")
|
||||||
|
|
||||||
|
|
||||||
@attrs_default
|
@attrs_default
|
||||||
class Message:
|
class Message:
|
||||||
"""Represents a Facebook message."""
|
"""Represents a Facebook message."""
|
||||||
@@ -93,18 +84,26 @@ class Message:
|
|||||||
data = {"message_id": self.id}
|
data = {"message_id": self.id}
|
||||||
j = self.session._payload_post("/messaging/unsend_message/?dpr=1", data)
|
j = self.session._payload_post("/messaging/unsend_message/?dpr=1", data)
|
||||||
|
|
||||||
def react(self, reaction: Optional[MessageReaction]):
|
def react(self, reaction: Optional[str]):
|
||||||
"""React to the message, or removes reaction.
|
"""React to the message, or removes reaction.
|
||||||
|
|
||||||
|
Currently, you can use "❤", "😍", "😆", "😮", "😢", "😠", "👍" or "👎". It
|
||||||
|
should be possible to add support for more, but we haven't figured that out yet.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
reaction: Reaction emoji to use, if ``None`` removes reaction
|
reaction: Reaction emoji to use, or if ``None``, removes reaction.
|
||||||
"""
|
"""
|
||||||
|
if reaction and reaction not in SENDABLE_REACTIONS:
|
||||||
|
raise ValueError(
|
||||||
|
"Invalid reaction! Please use one of: {}".format(SENDABLE_REACTIONS)
|
||||||
|
)
|
||||||
|
|
||||||
data = {
|
data = {
|
||||||
"action": "ADD_REACTION" if reaction else "REMOVE_REACTION",
|
"action": "ADD_REACTION" if reaction else "REMOVE_REACTION",
|
||||||
"client_mutation_id": "1",
|
"client_mutation_id": "1",
|
||||||
"actor_id": self.session.user_id,
|
"actor_id": self.session.user_id,
|
||||||
"message_id": self.id,
|
"message_id": self.id,
|
||||||
"reaction": reaction.value if reaction else None,
|
"reaction": reaction,
|
||||||
}
|
}
|
||||||
data = {
|
data = {
|
||||||
"doc_id": 1491398900900362,
|
"doc_id": 1491398900900362,
|
||||||
@@ -190,7 +189,7 @@ class MessageData(Message):
|
|||||||
is_read = attr.ib(None)
|
is_read = attr.ib(None)
|
||||||
#: A list of people IDs who read the message, works only with `Client.fetch_thread_messages`
|
#: A list of people IDs who read the message, works only with `Client.fetch_thread_messages`
|
||||||
read_by = attr.ib(factory=list)
|
read_by = attr.ib(factory=list)
|
||||||
#: A dictionary with user's IDs as keys, and their `MessageReaction` as values
|
#: A dictionary with user's IDs as keys, and their reaction as values
|
||||||
reactions = attr.ib(factory=dict)
|
reactions = attr.ib(factory=dict)
|
||||||
#: A `Sticker`
|
#: A `Sticker`
|
||||||
sticker = attr.ib(None)
|
sticker = attr.ib(None)
|
||||||
@@ -266,8 +265,7 @@ class MessageData(Message):
|
|||||||
if _util.millis_to_datetime(int(receipt["watermark"])) >= created_at
|
if _util.millis_to_datetime(int(receipt["watermark"])) >= created_at
|
||||||
],
|
],
|
||||||
reactions={
|
reactions={
|
||||||
str(r["user"]["id"]): MessageReaction._extend_if_invalid(r["reaction"])
|
str(r["user"]["id"]): r["reaction"] for r in data["message_reactions"]
|
||||||
for r in data["message_reactions"]
|
|
||||||
},
|
},
|
||||||
sticker=_sticker.Sticker._from_graphql(data.get("sticker")),
|
sticker=_sticker.Sticker._from_graphql(data.get("sticker")),
|
||||||
attachments=attachments,
|
attachments=attachments,
|
||||||
|
@@ -1,10 +1,11 @@
|
|||||||
import attr
|
import attr
|
||||||
import datetime
|
import datetime
|
||||||
from ._core import attrs_default, Enum
|
import enum
|
||||||
|
from ._core import attrs_default
|
||||||
from . import _exception, _util, _session
|
from . import _exception, _util, _session
|
||||||
|
|
||||||
|
|
||||||
class GuestStatus(Enum):
|
class GuestStatus(enum.Enum):
|
||||||
INVITED = 1
|
INVITED = 1
|
||||||
GOING = 2
|
GOING = 2
|
||||||
DECLINED = 3
|
DECLINED = 3
|
||||||
|
@@ -2,12 +2,13 @@ import abc
|
|||||||
import attr
|
import attr
|
||||||
import collections
|
import collections
|
||||||
import datetime
|
import datetime
|
||||||
from ._core import attrs_default, Enum, Image
|
import enum
|
||||||
|
from ._core import attrs_default, Image
|
||||||
from . import _util, _exception, _session, _graphql, _attachment, _file, _plan
|
from . import _util, _exception, _session, _graphql, _attachment, _file, _plan
|
||||||
from typing import MutableMapping, Any, Iterable, Tuple
|
from typing import MutableMapping, Any, Iterable, Tuple, Optional
|
||||||
|
|
||||||
|
|
||||||
class ThreadLocation(Enum):
|
class ThreadLocation(enum.Enum):
|
||||||
"""Used to specify where a thread is located (inbox, pending, archived, other)."""
|
"""Used to specify where a thread is located (inbox, pending, archived, other)."""
|
||||||
|
|
||||||
INBOX = "INBOX"
|
INBOX = "INBOX"
|
||||||
@@ -16,39 +17,29 @@ class ThreadLocation(Enum):
|
|||||||
OTHER = "OTHER"
|
OTHER = "OTHER"
|
||||||
|
|
||||||
|
|
||||||
class ThreadColor(Enum):
|
DEFAULT_COLOR = "#0084ff"
|
||||||
"""Used to specify a thread colors."""
|
SETABLE_COLORS = (
|
||||||
|
DEFAULT_COLOR,
|
||||||
MESSENGER_BLUE = "#0084ff"
|
"#44bec7",
|
||||||
VIKING = "#44bec7"
|
"#ffc300",
|
||||||
GOLDEN_POPPY = "#ffc300"
|
"#fa3c4c",
|
||||||
RADICAL_RED = "#fa3c4c"
|
"#d696bb",
|
||||||
SHOCKING = "#d696bb"
|
"#6699cc",
|
||||||
PICTON_BLUE = "#6699cc"
|
"#13cf13",
|
||||||
FREE_SPEECH_GREEN = "#13cf13"
|
"#ff7e29",
|
||||||
PUMPKIN = "#ff7e29"
|
"#e68585",
|
||||||
LIGHT_CORAL = "#e68585"
|
"#7646ff",
|
||||||
MEDIUM_SLATE_BLUE = "#7646ff"
|
"#20cef5",
|
||||||
DEEP_SKY_BLUE = "#20cef5"
|
"#67b868",
|
||||||
FERN = "#67b868"
|
"#d4a88c",
|
||||||
CAMEO = "#d4a88c"
|
"#ff5ca1",
|
||||||
BRILLIANT_ROSE = "#ff5ca1"
|
"#a695c7",
|
||||||
BILOBA_FLOWER = "#a695c7"
|
"#ff7ca8",
|
||||||
TICKLE_ME_PINK = "#ff7ca8"
|
"#1adb5b",
|
||||||
MALACHITE = "#1adb5b"
|
"#f01d6a",
|
||||||
RUBY = "#f01d6a"
|
"#ff9c19",
|
||||||
DARK_TANGERINE = "#ff9c19"
|
"#0edcde",
|
||||||
BRIGHT_TURQUOISE = "#0edcde"
|
)
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def _from_graphql(cls, color):
|
|
||||||
if color is None:
|
|
||||||
return None
|
|
||||||
if not color:
|
|
||||||
return cls.MESSENGER_BLUE
|
|
||||||
color = color[2:] # Strip the alpha value
|
|
||||||
value = "#{}".format(color.lower())
|
|
||||||
return cls._extend_if_invalid(value)
|
|
||||||
|
|
||||||
|
|
||||||
class ThreadABC(metaclass=abc.ABCMeta):
|
class ThreadABC(metaclass=abc.ABCMeta):
|
||||||
@@ -375,22 +366,50 @@ class ThreadABC(metaclass=abc.ABCMeta):
|
|||||||
"/messaging/save_thread_nickname/?source=thread_settings&dpr=1", data
|
"/messaging/save_thread_nickname/?source=thread_settings&dpr=1", data
|
||||||
)
|
)
|
||||||
|
|
||||||
def set_color(self, color: ThreadColor):
|
def set_color(self, color: str):
|
||||||
"""Change thread color.
|
"""Change thread color.
|
||||||
|
|
||||||
|
The new color must be one of the following:
|
||||||
|
|
||||||
|
"#0084ff", "#44bec7", "#ffc300", "#fa3c4c", "#d696bb", "#6699cc", "#13cf13",
|
||||||
|
"#ff7e29", "#e68585", "#7646ff", "#20cef5", "#67b868", "#d4a88c", "#ff5ca1",
|
||||||
|
"#a695c7", "#ff7ca8", "#1adb5b", "#f01d6a", "#ff9c19" or "#0edcde".
|
||||||
|
|
||||||
|
The default is "#0084ff".
|
||||||
|
|
||||||
|
This list is subject to change in the future!
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
color: New thread color
|
color: New thread color
|
||||||
"""
|
"""
|
||||||
data = {
|
if color not in SETABLE_COLORS:
|
||||||
"color_choice": color.value if color != ThreadColor.MESSENGER_BLUE else "",
|
raise ValueError(
|
||||||
"thread_or_other_fbid": self.id,
|
"Invalid color! Please use one of: {}".format(SETABLE_COLORS)
|
||||||
}
|
)
|
||||||
|
|
||||||
|
# Set color to "" if DEFAULT_COLOR. Just how the endpoint works...
|
||||||
|
if color == DEFAULT_COLOR:
|
||||||
|
color = ""
|
||||||
|
|
||||||
|
data = {"color_choice": color, "thread_or_other_fbid": self.id}
|
||||||
j = self.session._payload_post(
|
j = self.session._payload_post(
|
||||||
"/messaging/save_thread_color/?source=thread_settings&dpr=1", data
|
"/messaging/save_thread_color/?source=thread_settings&dpr=1", data
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# def set_theme(self, theme_id: str):
|
||||||
|
# data = {
|
||||||
|
# "client_mutation_id": "0",
|
||||||
|
# "actor_id": self.session.user_id,
|
||||||
|
# "thread_id": self.id,
|
||||||
|
# "theme_id": theme_id,
|
||||||
|
# "source": "SETTINGS",
|
||||||
|
# }
|
||||||
|
# j = self.session._graphql_requests(
|
||||||
|
# _graphql.from_doc_id("1768656253222505", {"data": data})
|
||||||
|
# )
|
||||||
|
|
||||||
def set_emoji(self, emoji: str):
|
def set_emoji(self, emoji: str):
|
||||||
"""Change thread color.
|
"""Change thread emoji.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
emoji: New thread emoji
|
emoji: New thread emoji
|
||||||
@@ -541,15 +560,22 @@ class ThreadABC(metaclass=abc.ABCMeta):
|
|||||||
)
|
)
|
||||||
return j
|
return j
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _parse_color(inp: Optional[str]) -> str:
|
||||||
|
if not inp:
|
||||||
|
return DEFAULT_COLOR
|
||||||
|
# Strip the alpha value, and lower the string
|
||||||
|
return "#{}".format(inp[2:].lower())
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _parse_customization_info(data: Any) -> MutableMapping[str, Any]:
|
def _parse_customization_info(data: Any) -> MutableMapping[str, Any]:
|
||||||
if data is None or data.get("customization_info") is None:
|
if not data or not data.get("customization_info"):
|
||||||
return {}
|
return {"emoji": None, "color": DEFAULT_COLOR}
|
||||||
info = data["customization_info"]
|
info = data["customization_info"]
|
||||||
|
|
||||||
rtn = {
|
rtn = {
|
||||||
"emoji": info.get("emoji"),
|
"emoji": info.get("emoji"),
|
||||||
"color": ThreadColor._from_graphql(info.get("outgoing_bubble_color")),
|
"color": ThreadABC._parse_color(info.get("outgoing_bubble_color")),
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
data.get("thread_type") == "GROUP"
|
data.get("thread_type") == "GROUP"
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import attr
|
import attr
|
||||||
from ._core import log, attrs_default, Enum, Image
|
from ._core import log, attrs_default, Image
|
||||||
from . import _util, _session, _plan, _thread
|
from . import _util, _session, _plan, _thread
|
||||||
|
|
||||||
|
|
||||||
@@ -33,13 +33,6 @@ GENDERS = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class TypingStatus(Enum):
|
|
||||||
"""Used to specify whether the user is typing or has stopped typing."""
|
|
||||||
|
|
||||||
STOPPED = 0
|
|
||||||
TYPING = 1
|
|
||||||
|
|
||||||
|
|
||||||
@attrs_default
|
@attrs_default
|
||||||
class User(_thread.ThreadABC):
|
class User(_thread.ThreadABC):
|
||||||
"""Represents a Facebook user. Implements `ThreadABC`."""
|
"""Represents a Facebook user. Implements `ThreadABC`."""
|
||||||
@@ -110,7 +103,7 @@ class UserData(User):
|
|||||||
nickname = attr.ib(None)
|
nickname = attr.ib(None)
|
||||||
#: The clients nickname, as seen by the user
|
#: The clients nickname, as seen by the user
|
||||||
own_nickname = attr.ib(None)
|
own_nickname = attr.ib(None)
|
||||||
#: A `ThreadColor`. The message color
|
#: The message color
|
||||||
color = attr.ib(None)
|
color = attr.ib(None)
|
||||||
#: The default emoji
|
#: The default emoji
|
||||||
emoji = attr.ib(None)
|
emoji = attr.ib(None)
|
||||||
@@ -136,8 +129,8 @@ class UserData(User):
|
|||||||
gender=GENDERS.get(data["gender"]),
|
gender=GENDERS.get(data["gender"]),
|
||||||
affinity=data.get("viewer_affinity"),
|
affinity=data.get("viewer_affinity"),
|
||||||
nickname=c_info.get("nickname"),
|
nickname=c_info.get("nickname"),
|
||||||
color=c_info.get("color"),
|
color=c_info["color"],
|
||||||
emoji=c_info.get("emoji"),
|
emoji=c_info["emoji"],
|
||||||
own_nickname=c_info.get("own_nickname"),
|
own_nickname=c_info.get("own_nickname"),
|
||||||
photo=Image._from_uri(data["profile_picture"]),
|
photo=Image._from_uri(data["profile_picture"]),
|
||||||
name=data["name"],
|
name=data["name"],
|
||||||
@@ -186,8 +179,8 @@ class UserData(User):
|
|||||||
is_friend=user["is_viewer_friend"],
|
is_friend=user["is_viewer_friend"],
|
||||||
gender=GENDERS.get(user["gender"]),
|
gender=GENDERS.get(user["gender"]),
|
||||||
nickname=c_info.get("nickname"),
|
nickname=c_info.get("nickname"),
|
||||||
color=c_info.get("color"),
|
color=c_info["color"],
|
||||||
emoji=c_info.get("emoji"),
|
emoji=c_info["emoji"],
|
||||||
own_nickname=c_info.get("own_nickname"),
|
own_nickname=c_info.get("own_nickname"),
|
||||||
photo=Image._from_uri(user["big_image_src"]),
|
photo=Image._from_uri(user["big_image_src"]),
|
||||||
message_count=data["messages_count"],
|
message_count=data["messages_count"],
|
||||||
|
@@ -14,7 +14,6 @@ maintainer = "Mads Marquart"
|
|||||||
maintainer-email = "madsmtm@gmail.com"
|
maintainer-email = "madsmtm@gmail.com"
|
||||||
home-page = "https://github.com/carpedm20/fbchat/"
|
home-page = "https://github.com/carpedm20/fbchat/"
|
||||||
requires = [
|
requires = [
|
||||||
"aenum~=2.0",
|
|
||||||
"attrs>=19.1",
|
"attrs>=19.1",
|
||||||
"requests~=2.19",
|
"requests~=2.19",
|
||||||
"beautifulsoup4~=4.0",
|
"beautifulsoup4~=4.0",
|
||||||
|
@@ -1,14 +0,0 @@
|
|||||||
import pytest
|
|
||||||
from fbchat._core import Enum
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.filterwarnings("ignore::DeprecationWarning")
|
|
||||||
def test_enum_extend_if_invalid():
|
|
||||||
class TestEnum(Enum):
|
|
||||||
A = 1
|
|
||||||
B = 2
|
|
||||||
|
|
||||||
assert TestEnum._extend_if_invalid(1) == TestEnum.A
|
|
||||||
assert TestEnum._extend_if_invalid(3) == TestEnum.UNKNOWN_3
|
|
||||||
assert TestEnum._extend_if_invalid(3) == TestEnum.UNKNOWN_3
|
|
||||||
assert TestEnum(3) == TestEnum.UNKNOWN_3
|
|
@@ -35,7 +35,7 @@ def test_group_from_graphql(session):
|
|||||||
plan=None,
|
plan=None,
|
||||||
participants={"1234", "2345", "3456"},
|
participants={"1234", "2345", "3456"},
|
||||||
nicknames={},
|
nicknames={},
|
||||||
color=None,
|
color="#0084ff",
|
||||||
emoji="😀",
|
emoji="😀",
|
||||||
admins={"1234"},
|
admins={"1234"},
|
||||||
approval_mode=False,
|
approval_mode=False,
|
||||||
|
@@ -1,16 +1,11 @@
|
|||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from fbchat import Message, MessageReaction
|
from fbchat import Message
|
||||||
from utils import subset
|
from utils import subset
|
||||||
|
|
||||||
pytestmark = pytest.mark.online
|
pytestmark = pytest.mark.online
|
||||||
|
|
||||||
|
|
||||||
def test_set_reaction(client):
|
|
||||||
mid = client.send(Message(text="This message will be reacted to"))
|
|
||||||
client.react_to_message(mid, MessageReaction.LOVE)
|
|
||||||
|
|
||||||
|
|
||||||
def test_delete_messages(client):
|
def test_delete_messages(client):
|
||||||
text1 = "This message will stay"
|
text1 = "This message will stay"
|
||||||
text2 = "This message will be removed"
|
text2 = "This message will be removed"
|
||||||
|
@@ -1,20 +1,19 @@
|
|||||||
import pytest
|
import pytest
|
||||||
import fbchat
|
import fbchat
|
||||||
from fbchat import ThreadColor, ThreadABC, Thread
|
from fbchat import ThreadABC, Thread
|
||||||
|
|
||||||
|
|
||||||
def test_thread_color_from_graphql():
|
def test_parse_color():
|
||||||
assert None is ThreadColor._from_graphql(None)
|
assert "#0084ff" == ThreadABC._parse_color(None)
|
||||||
assert ThreadColor.MESSENGER_BLUE is ThreadColor._from_graphql("")
|
assert "#0084ff" == ThreadABC._parse_color("")
|
||||||
assert ThreadColor.VIKING is ThreadColor._from_graphql("FF44BEC7")
|
assert "#44bec7" == ThreadABC._parse_color("FF44BEC7")
|
||||||
assert ThreadColor._from_graphql("DEADBEEF") is getattr(
|
assert "#adbeef" == ThreadABC._parse_color("DEADBEEF")
|
||||||
ThreadColor, "UNKNOWN_#ADBEEF"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def test_thread_parse_customization_info_empty():
|
def test_thread_parse_customization_info_empty():
|
||||||
assert {} == ThreadABC._parse_customization_info(None)
|
default = {"color": "#0084ff", "emoji": None}
|
||||||
assert {} == ThreadABC._parse_customization_info({"customization_info": None})
|
assert default == ThreadABC._parse_customization_info(None)
|
||||||
|
assert default == ThreadABC._parse_customization_info({"customization_info": None})
|
||||||
|
|
||||||
|
|
||||||
def test_thread_parse_customization_info_group():
|
def test_thread_parse_customization_info_group():
|
||||||
@@ -34,7 +33,7 @@ def test_thread_parse_customization_info_group():
|
|||||||
}
|
}
|
||||||
expected = {
|
expected = {
|
||||||
"emoji": "🎉",
|
"emoji": "🎉",
|
||||||
"color": ThreadColor.BRILLIANT_ROSE,
|
"color": "#ff5ca1",
|
||||||
"nicknames": {"123456789": "A", "987654321": "B"},
|
"nicknames": {"123456789": "A", "987654321": "B"},
|
||||||
}
|
}
|
||||||
assert expected == ThreadABC._parse_customization_info(data)
|
assert expected == ThreadABC._parse_customization_info(data)
|
||||||
@@ -55,7 +54,7 @@ def test_thread_parse_customization_info_user():
|
|||||||
"thread_type": "ONE_TO_ONE",
|
"thread_type": "ONE_TO_ONE",
|
||||||
# ... Other irrelevant fields
|
# ... Other irrelevant fields
|
||||||
}
|
}
|
||||||
expected = {"emoji": None, "color": None, "own_nickname": "A", "nickname": "B"}
|
expected = {"emoji": None, "color": "#0084ff", "own_nickname": "A", "nickname": "B"}
|
||||||
assert expected == ThreadABC._parse_customization_info(data)
|
assert expected == ThreadABC._parse_customization_info(data)
|
||||||
|
|
||||||
|
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from fbchat import Message, FBchatFacebookError, TypingStatus, ThreadColor
|
from fbchat import Message, FBchatFacebookError
|
||||||
from utils import random_hex, subset
|
from utils import random_hex, subset
|
||||||
from os import path
|
from os import path
|
||||||
|
|
||||||
@@ -91,14 +91,10 @@ def test_change_image_remote(client1, group, catch_event):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
def test_change_color(client, catch_event, compare):
|
||||||
"color",
|
|
||||||
[x for x in ThreadColor if x in [ThreadColor.MESSENGER_BLUE, ThreadColor.PUMPKIN]],
|
|
||||||
)
|
|
||||||
def test_change_color(client, catch_event, compare, color):
|
|
||||||
with catch_event("on_color_change") as x:
|
with catch_event("on_color_change") as x:
|
||||||
client.change_thread_color(color)
|
client.change_thread_color("#44bec7")
|
||||||
assert compare(x, new_color=color)
|
assert compare(x, new_color="#44bec7")
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.xfail(raises=FBchatFacebookError, reason="Should fail, but doesn't")
|
@pytest.mark.xfail(raises=FBchatFacebookError, reason="Should fail, but doesn't")
|
||||||
@@ -109,7 +105,7 @@ def test_change_color_invalid(client):
|
|||||||
client.change_thread_color(InvalidColor())
|
client.change_thread_color(InvalidColor())
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("status", TypingStatus)
|
@pytest.mark.parametrize("status", [True, False])
|
||||||
def test_typing_status(client, catch_event, compare, status):
|
def test_typing_status(client, catch_event, compare, status):
|
||||||
with catch_event("on_typing") as x:
|
with catch_event("on_typing") as x:
|
||||||
client.set_typing_status(status)
|
client.set_typing_status(status)
|
||||||
|
@@ -27,6 +27,7 @@ def test_user_from_graphql(session):
|
|||||||
is_friend=True,
|
is_friend=True,
|
||||||
gender="female_singular",
|
gender="female_singular",
|
||||||
affinity=0.4560002,
|
affinity=0.4560002,
|
||||||
|
color="#0084ff",
|
||||||
) == UserData._from_graphql(session, data)
|
) == UserData._from_graphql(session, data)
|
||||||
|
|
||||||
|
|
||||||
@@ -152,7 +153,7 @@ def test_user_from_thread_fetch(session):
|
|||||||
gender="female_singular",
|
gender="female_singular",
|
||||||
nickname="A",
|
nickname="A",
|
||||||
own_nickname="B",
|
own_nickname="B",
|
||||||
color=None,
|
color="#0084ff",
|
||||||
emoji=None,
|
emoji=None,
|
||||||
) == UserData._from_thread_fetch(session, data)
|
) == UserData._from_thread_fetch(session, data)
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user