Use snake_case method names

Renamed:
- Message.formatMentions
- _util.digitToChar
- _util.generateMessageID
- _util.getSignatureID
- _util.generateOfflineThreadingID
- Client._markAlive

Renamed following Client methods:
- isLoggedIn
- getSession
- setSession
- _forcedFetch
- fetchThreads
- fetchAllUsersFromThreads
- fetchAllUsers
- searchForUsers
- searchForPages
- searchForGroups
- searchForThreads
- searchForMessageIDs
- searchForMessages
- _fetchInfo
- fetchUserInfo
- fetchPageInfo
- fetchGroupInfo
- fetchThreadInfo
- fetchThreadMessages
- fetchThreadList
- fetchUnread
- fetchUnseen
- fetchImageUrl
- fetchMessageInfo
- fetchPollOptions
- fetchPlanInfo
- _getPrivateData
- getPhoneNumbers
- getEmails
- getUserActiveStatus
- fetchThreadImages
- _oldMessage
- _doSendRequest
- quickReply
- _sendLocation
- sendLocation
- sendPinnedLocation
- _sendFiles
- sendRemoteFiles
- sendLocalFiles
- sendRemoteVoiceClips
- sendLocalVoiceClips
- forwardAttachment
- createGroup
- addUsersToGroup
- removeUserFromGroup
- _adminStatus
- addGroupAdmins
- removeGroupAdmins
- changeGroupApprovalMode
- _usersApproval
- acceptUsersToGroup
- denyUsersFromGroup
- _changeGroupImage
- changeGroupImageRemote
- changeGroupImageLocal
- changeThreadTitle
- changeNickname
- changeThreadColor
- changeThreadEmoji
- reactToMessage
- createPlan
- editPlan
- deletePlan
- changePlanParticipation
- createPoll
- updatePollVote
- setTypingStatus
- markAsDelivered
- _readStatus
- markAsRead
- markAsUnread
- markAsSeen
- friendConnect
- removeFriend
- blockUser
- unblockUser
- moveThreads
- deleteThreads
- markAsSpam
- deleteMessages
- muteThread
- unmuteThread
- muteThreadReactions
- unmuteThreadReactions
- muteThreadMentions
- unmuteThreadMentions
- _pullMessage
- _parseMessage
- _doOneListen
- setActiveStatus
- onLoggingIn
- on2FACode
- onLoggedIn
- onListening
- onListenError
- onMessage
- onColorChange
- onEmojiChange
- onTitleChange
- onImageChange
- onNicknameChange
- onAdminAdded
- onAdminRemoved
- onApprovalModeChange
- onMessageSeen
- onMessageDelivered
- onMarkedSeen
- onMessageUnsent
- onPeopleAdded
- onPersonRemoved
- onFriendRequest
- onInbox
- onTyping
- onGamePlayed
- onReactionAdded
- onReactionRemoved
- onBlock
- onUnblock
- onLiveLocation
- onCallStarted
- onCallEnded
- onUserJoinedCall
- onPollCreated
- onPollVoted
- onPlanCreated
- onPlanEnded
- onPlanEdited
- onPlanDeleted
- onPlanParticipation
- onQprimer
- onChatTimestamp
- onBuddylistOverlay
- onUnknownMesssageType
- onMessageError
This commit is contained in:
Mads Marquart
2019-09-08 19:53:55 +02:00
parent 8d8ef6bbc9
commit 614e5ad4bb
24 changed files with 453 additions and 449 deletions

View File

@@ -14,7 +14,7 @@ Logging In
---------- ----------
Simply create an instance of :class:`Client`. If you have two factor authentication enabled, type the code in the terminal prompt Simply create an instance of :class:`Client`. If you have two factor authentication enabled, type the code in the terminal prompt
(If you want to supply the code in another fashion, overwrite :func:`Client.on2FACode`):: (If you want to supply the code in another fashion, overwrite :func:`Client.on_2fa_code`)::
from fbchat import Client from fbchat import Client
from fbchat.models import * from fbchat.models import *
@@ -28,10 +28,10 @@ Replace ``<email>`` and ``<password>`` with your email and password respectively
If you want to change how verbose ``fbchat`` is, change the logging level (in :class:`Client`) If you want to change how verbose ``fbchat`` is, change the logging level (in :class:`Client`)
Throughout your code, if you want to check whether you are still logged in, use :func:`Client.isLoggedIn`. Throughout your code, if you want to check whether you are still logged in, use :func:`Client.is_logged_in`.
An example would be to login again if you've been logged out, using :func:`Client.login`:: An example would be to login again if you've been logged out, using :func:`Client.login`::
if not client.isLoggedIn(): if not client.is_logged_in():
client.login('<email>', '<password>') client.login('<email>', '<password>')
When you're done using the client, and want to securely logout, use :func:`Client.logout`:: When you're done using the client, and want to securely logout, use :func:`Client.logout`::
@@ -50,8 +50,8 @@ A thread can refer to two things: A Messenger group chat or a single Facebook us
These will specify whether the thread is a single user chat or a group chat. These will specify whether the thread is a single user chat or a group chat.
This is required for many of ``fbchat``'s functions, since Facebook differentiates between these two internally This is required for many of ``fbchat``'s functions, since Facebook differentiates between these two internally
Searching for group chats and finding their ID can be done via. :func:`Client.searchForGroups`, Searching for group chats and finding their ID can be done via. :func:`Client.search_for_groups`,
and searching for users is possible via. :func:`Client.searchForUsers`. See :ref:`intro_fetching` and searching for users is possible via. :func:`Client.search_for_users`. See :ref:`intro_fetching`
You can get your own user ID by using :any:`Client.uid` You can get your own user ID by using :any:`Client.uid`
@@ -71,10 +71,10 @@ corresponds to the ID of a single user, and the ID of a group respectively::
client.send(Message(text='<message>'), thread_id='<user id>', thread_type=ThreadType.USER) client.send(Message(text='<message>'), thread_id='<user id>', thread_type=ThreadType.USER)
client.send(Message(text='<message>'), thread_id='<group id>', thread_type=ThreadType.GROUP) client.send(Message(text='<message>'), thread_id='<group id>', thread_type=ThreadType.GROUP)
Some functions (e.g. :func:`Client.changeThreadColor`) don't require a thread type, so in these cases you just provide the thread ID:: Some functions (e.g. :func:`Client.change_thread_color`) don't require a thread type, so in these cases you just provide the thread ID::
client.changeThreadColor(ThreadColor.BILOBA_FLOWER, thread_id='<user id>') client.change_thread_color(ThreadColor.BILOBA_FLOWER, thread_id='<user id>')
client.changeThreadColor(ThreadColor.MESSENGER_BLUE, thread_id='<group id>') client.change_thread_color(ThreadColor.MESSENGER_BLUE, thread_id='<group id>')
.. _intro_message_ids: .. _intro_message_ids:
@@ -85,12 +85,12 @@ 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 :func:`Client.reactToMessage`, Some of ``fbchat``'s functions require these ID's, like :func:`Client.react_to_message`,
and some of then provide this ID, like :func:`Client.sendMessage`. and some of then provide this ID, like :func:`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 = client.send(Message(text='message'), thread_id=thread_id, thread_type=thread_type) message_id = client.send(Message(text='message'), thread_id=thread_id, thread_type=thread_type)
client.reactToMessage(message_id, MessageReaction.LOVE) client.react_to_message(message_id, MessageReaction.LOVE)
.. _intro_interacting: .. _intro_interacting:
@@ -118,10 +118,10 @@ Fetching Information
You can use ``fbchat`` to fetch basic information like user names, profile pictures, thread names and user IDs You can use ``fbchat`` to fetch basic information like user names, profile pictures, thread names and user IDs
You can retrieve a user's ID with :func:`Client.searchForUsers`. You can retrieve a user's ID with :func:`Client.search_for_users`.
The following snippet will search for users by their name, take the first (and most likely) user, and then get their user ID from the result:: The following snippet will search for users by their name, take the first (and most likely) user, and then get their user ID from the result::
users = client.searchForUsers('<name of user>') users = client.search_for_users('<name of user>')
user = users[0] user = users[0]
print("User's ID: {}".format(user.uid)) print("User's ID: {}".format(user.uid))
print("User's name: {}".format(user.name)) print("User's name: {}".format(user.name))
@@ -140,13 +140,13 @@ Sessions
``fbchat`` provides functions to retrieve and set the session cookies. ``fbchat`` provides functions to retrieve and set the session cookies.
This will enable you to store the session cookies in a separate file, so that you don't have to login each time you start your script. This will enable you to store the session cookies in a separate file, so that you don't have to login each time you start your script.
Use :func:`Client.getSession` to retrieve the cookies:: Use :func:`Client.get_gession` to retrieve the cookies::
session_cookies = client.getSession() session_cookies = client.get_gession()
Then you can use :func:`Client.setSession`:: Then you can use :func:`Client.set_gession`::
client.setSession(session_cookies) client.set_gession(session_cookies)
Or you can set the ``session_cookies`` on your initial login. Or you can set the ``session_cookies`` on your initial login.
(If the session cookies are invalid, your email and password will be used to login instead):: (If the session cookies are invalid, your email and password will be used to login instead)::
@@ -168,12 +168,12 @@ By default, (most) events will just be a `logging.info` statement,
meaning it will simply print information to the console when an event happens meaning it will simply print information to the console when an event happens
.. note:: .. note::
You can identify the event methods by their ``on`` prefix, e.g. `onMessage` You can identify the event methods by their ``on`` prefix, e.g. ``on_message``
The event actions can be changed by subclassing the :class:`Client`, and then overwriting the event methods:: The event actions can be changed by subclassing the :class:`Client`, and then overwriting the event methods::
class CustomClient(Client): class CustomClient(Client):
def onMessage(self, mid, author_id, message_object, thread_id, thread_type, ts, metadata, msg, **kwargs): def on_message(self, mid, author_id, message_object, thread_id, thread_type, ts, metadata, msg, **kwargs):
# Do something with message_object here # Do something with message_object here
pass pass
@@ -182,13 +182,13 @@ The event actions can be changed by subclassing the :class:`Client`, and then ov
**Notice:** The following snippet is as equally valid as the previous one:: **Notice:** The following snippet is as equally valid as the previous one::
class CustomClient(Client): class CustomClient(Client):
def onMessage(self, message_object, author_id, thread_id, thread_type, **kwargs): def on_message(self, message_object, author_id, thread_id, thread_type, **kwargs):
# Do something with message_object here # Do something with message_object here
pass pass
client = CustomClient('<email>', '<password>') client = CustomClient('<email>', '<password>')
The change was in the parameters that our `onMessage` method took: ``message_object`` and ``author_id`` got swapped, The change was in the parameters that our ``on_message`` method took: ``message_object`` and ``author_id`` got swapped,
and ``mid``, ``ts``, ``metadata`` and ``msg`` got removed, but the function still works, since we included ``**kwargs`` and ``mid``, ``ts``, ``metadata`` and ``msg`` got removed, but the function still works, since we included ``**kwargs``
.. note:: .. note::

View File

@@ -9,7 +9,7 @@ This page will be periodically updated to show missing features and documentatio
Missing Functionality Missing Functionality
--------------------- ---------------------
- Implement ``Client.searchForMessage`` - Implement ``Client.search_for_message``
- This will use the GraphQL request API - This will use the GraphQL request API
- Implement chatting with pages properly - Implement chatting with pages properly
- Write better FAQ - Write better FAQ

View File

@@ -2,9 +2,9 @@ from fbchat import Client
# Subclass fbchat.Client and override required methods # Subclass fbchat.Client and override required methods
class EchoBot(Client): class EchoBot(Client):
def onMessage(self, author_id, message_object, thread_id, thread_type, **kwargs): def on_message(self, author_id, message_object, thread_id, thread_type, **kwargs):
self.markAsDelivered(thread_id, message_object.uid) self.mark_as_delivered(thread_id, message_object.uid)
self.markAsRead(thread_id) self.mark_as_read(thread_id)
print("{} from {} in {}".format(message_object, thread_id, thread_type.name)) print("{} from {} in {}".format(message_object, thread_id, thread_type.name))

View File

@@ -5,24 +5,24 @@ from fbchat.models import *
client = Client("<email>", "<password>") client = Client("<email>", "<password>")
# Fetches a list of all users you're currently chatting with, as `User` objects # Fetches a list of all users you're currently chatting with, as `User` objects
users = client.fetchAllUsers() users = client.fetch_all_users()
print("users' IDs: {}".format([user.uid for user in users])) print("users' IDs: {}".format([user.uid for user in users]))
print("users' names: {}".format([user.name for user in users])) print("users' names: {}".format([user.name for user in users]))
# If we have a user id, we can use `fetchUserInfo` to fetch a `User` object # If we have a user id, we can use `fetch_user_info` to fetch a `User` object
user = client.fetchUserInfo("<user id>")["<user id>"] user = client.fetch_user_info("<user id>")["<user id>"]
# We can also query both mutiple users together, which returns list of `User` objects # We can also query both mutiple users together, which returns list of `User` objects
users = client.fetchUserInfo("<1st user id>", "<2nd user id>", "<3rd user id>") users = client.fetch_user_info("<1st user id>", "<2nd user id>", "<3rd user id>")
print("user's name: {}".format(user.name)) print("user's name: {}".format(user.name))
print("users' names: {}".format([users[k].name for k in users])) print("users' names: {}".format([users[k].name for k in users]))
# `searchForUsers` searches for the user and gives us a list of the results, # `search_for_users` searches for the user and gives us a list of the results,
# and then we just take the first one, aka. the most likely one: # and then we just take the first one, aka. the most likely one:
user = client.searchForUsers("<name of user>")[0] user = client.search_for_users("<name of user>")[0]
print("user ID: {}".format(user.uid)) print("user ID: {}".format(user.uid))
print("user's name: {}".format(user.name)) print("user's name: {}".format(user.name))
@@ -31,15 +31,15 @@ print("Is user client's friend: {}".format(user.is_friend))
# Fetches a list of the 20 top threads you're currently chatting with # Fetches a list of the 20 top threads you're currently chatting with
threads = client.fetchThreadList() threads = client.fetch_thread_list()
# Fetches the next 10 threads # Fetches the next 10 threads
threads += client.fetchThreadList(offset=20, limit=10) threads += client.fetch_thread_list(offset=20, limit=10)
print("Threads: {}".format(threads)) print("Threads: {}".format(threads))
# Gets the last 10 messages sent to the thread # Gets the last 10 messages sent to the thread
messages = client.fetchThreadMessages(thread_id="<thread id>", limit=10) messages = client.fetch_thread_messages(thread_id="<thread id>", limit=10)
# Since the message come in reversed order, reverse them # Since the message come in reversed order, reverse them
messages.reverse() messages.reverse()
@@ -48,14 +48,14 @@ for message in messages:
print(message.text) print(message.text)
# If we have a thread id, we can use `fetchThreadInfo` to fetch a `Thread` object # If we have a thread id, we can use `fetch_thread_info` to fetch a `Thread` object
thread = client.fetchThreadInfo("<thread id>")["<thread id>"] thread = client.fetch_thread_info("<thread id>")["<thread id>"]
print("thread's name: {}".format(thread.name)) print("thread's name: {}".format(thread.name))
print("thread's type: {}".format(thread.type)) print("thread's type: {}".format(thread.type))
# `searchForThreads` searches works like `searchForUsers`, but gives us a list of threads instead # `search_for_threads` searches works like `search_for_users`, but gives us a list of threads instead
thread = client.searchForThreads("<name of thread>")[0] thread = client.search_for_threads("<name of thread>")[0]
print("thread's name: {}".format(thread.name)) print("thread's name: {}".format(thread.name))
print("thread's type: {}".format(thread.type)) print("thread's type: {}".format(thread.type))
@@ -64,6 +64,6 @@ print("thread's type: {}".format(thread.type))
# Print image url for 20 last images from thread. # Print image url for 20 last images from thread.
images = client.fetchThreadImages("<thread id>") images = client.fetch_thread_images("<thread id>")
for image in islice(image, 20): for image in islice(image, 20):
print(image.large_preview_url) print(image.large_preview_url)

View File

@@ -38,7 +38,7 @@ client.send(
) )
# Will send the image located at `<image path>` # Will send the image located at `<image path>`
client.sendLocalImage( client.send_local_image(
"<image path>", "<image path>",
message=Message(text="This is a local image"), message=Message(text="This is a local image"),
thread_id=thread_id, thread_id=thread_id,
@@ -46,7 +46,7 @@ client.sendLocalImage(
) )
# Will download the image at the URL `<image url>`, and then send it # Will download the image at the URL `<image url>`, and then send it
client.sendRemoteImage( client.send_remote_image(
"<image url>", "<image url>",
message=Message(text="This is a remote image"), message=Message(text="This is a remote image"),
thread_id=thread_id, thread_id=thread_id,
@@ -57,35 +57,35 @@ client.sendRemoteImage(
# Only do these actions if the thread is a group # Only do these actions if the thread is a group
if thread_type == ThreadType.GROUP: if thread_type == ThreadType.GROUP:
# Will remove the user with ID `<user id>` from the thread # Will remove the user with ID `<user id>` from the thread
client.removeUserFromGroup("<user id>", thread_id=thread_id) client.remove_user_from_group("<user id>", thread_id=thread_id)
# Will add the user with ID `<user id>` to the thread # Will add the user with ID `<user id>` to the thread
client.addUsersToGroup("<user id>", thread_id=thread_id) client.add_users_to_group("<user id>", thread_id=thread_id)
# Will add the users with IDs `<1st user id>`, `<2nd user id>` and `<3th user id>` to the thread # Will add the users with IDs `<1st user id>`, `<2nd user id>` and `<3th user id>` to the thread
client.addUsersToGroup( client.add_users_to_group(
["<1st user id>", "<2nd user id>", "<3rd user id>"], thread_id=thread_id ["<1st user id>", "<2nd user id>", "<3rd user id>"], thread_id=thread_id
) )
# Will change the nickname of the user `<user_id>` to `<new nickname>` # Will change the nickname of the user `<user_id>` to `<new nickname>`
client.changeNickname( client.change_nickname(
"<new nickname>", "<user id>", thread_id=thread_id, thread_type=thread_type "<new nickname>", "<user id>", thread_id=thread_id, thread_type=thread_type
) )
# Will change the title of the thread to `<title>` # Will change the title of the thread to `<title>`
client.changeThreadTitle("<title>", thread_id=thread_id, thread_type=thread_type) client.change_thread_title("<title>", thread_id=thread_id, thread_type=thread_type)
# Will set the typing status of the thread to `TYPING` # Will set the typing status of the thread to `TYPING`
client.setTypingStatus( client.set_typing_status(
TypingStatus.TYPING, thread_id=thread_id, thread_type=thread_type TypingStatus.TYPING, thread_id=thread_id, thread_type=thread_type
) )
# Will change the thread color to `MESSENGER_BLUE` # Will change the thread color to `MESSENGER_BLUE`
client.changeThreadColor(ThreadColor.MESSENGER_BLUE, thread_id=thread_id) client.change_thread_color(ThreadColor.MESSENGER_BLUE, thread_id=thread_id)
# Will change the thread emoji to `👍` # Will change the thread emoji to `👍`
client.changeThreadEmoji("👍", thread_id=thread_id) client.change_thread_emoji("👍", thread_id=thread_id)
# Will react to a message with a 😍 emoji # Will react to a message with a 😍 emoji
client.reactToMessage("<message id>", MessageReaction.LOVE) client.react_to_message("<message id>", MessageReaction.LOVE)

View File

@@ -17,27 +17,27 @@ old_nicknames = {
class KeepBot(Client): class KeepBot(Client):
def onColorChange(self, author_id, new_color, thread_id, thread_type, **kwargs): def on_color_change(self, author_id, new_color, thread_id, thread_type, **kwargs):
if old_thread_id == thread_id and old_color != new_color: if old_thread_id == thread_id and old_color != new_color:
print( print(
"{} changed the thread color. It will be changed back".format(author_id) "{} changed the thread color. It will be changed back".format(author_id)
) )
self.changeThreadColor(old_color, thread_id=thread_id) self.change_thread_color(old_color, thread_id=thread_id)
def onEmojiChange(self, author_id, new_emoji, thread_id, thread_type, **kwargs): def on_emoji_change(self, author_id, new_emoji, thread_id, thread_type, **kwargs):
if old_thread_id == thread_id and new_emoji != old_emoji: if old_thread_id == thread_id and new_emoji != old_emoji:
print( print(
"{} changed the thread emoji. It will be changed back".format(author_id) "{} changed the thread emoji. It will be changed back".format(author_id)
) )
self.changeThreadEmoji(old_emoji, thread_id=thread_id) self.change_thread_emoji(old_emoji, thread_id=thread_id)
def onPeopleAdded(self, added_ids, author_id, thread_id, **kwargs): def on_people_added(self, added_ids, author_id, thread_id, **kwargs):
if old_thread_id == thread_id and author_id != self.uid: if old_thread_id == thread_id and author_id != self.uid:
print("{} got added. They will be removed".format(added_ids)) print("{} got added. They will be removed".format(added_ids))
for added_id in added_ids: for added_id in added_ids:
self.removeUserFromGroup(added_id, thread_id=thread_id) self.remove_user_from_group(added_id, thread_id=thread_id)
def onPersonRemoved(self, removed_id, author_id, thread_id, **kwargs): def on_person_removed(self, removed_id, author_id, thread_id, **kwargs):
# No point in trying to add ourself # No point in trying to add ourself
if ( if (
old_thread_id == thread_id old_thread_id == thread_id
@@ -45,18 +45,18 @@ class KeepBot(Client):
and author_id != self.uid and author_id != self.uid
): ):
print("{} got removed. They will be re-added".format(removed_id)) print("{} got removed. They will be re-added".format(removed_id))
self.addUsersToGroup(removed_id, thread_id=thread_id) self.add_users_to_group(removed_id, thread_id=thread_id)
def onTitleChange(self, author_id, new_title, thread_id, thread_type, **kwargs): def on_title_change(self, author_id, new_title, thread_id, thread_type, **kwargs):
if old_thread_id == thread_id and old_title != new_title: if old_thread_id == thread_id and old_title != new_title:
print( print(
"{} changed the thread title. It will be changed back".format(author_id) "{} changed the thread title. It will be changed back".format(author_id)
) )
self.changeThreadTitle( self.change_thread_title(
old_title, thread_id=thread_id, thread_type=thread_type old_title, thread_id=thread_id, thread_type=thread_type
) )
def onNicknameChange( def on_nickname_change(
self, author_id, changed_for, new_nickname, thread_id, thread_type, **kwargs self, author_id, changed_for, new_nickname, thread_id, thread_type, **kwargs
): ):
if ( if (
@@ -69,7 +69,7 @@ class KeepBot(Client):
author_id, changed_for author_id, changed_for
) )
) )
self.changeNickname( self.change_nickname(
old_nicknames[changed_for], old_nicknames[changed_for],
changed_for, changed_for,
thread_id=thread_id, thread_id=thread_id,

View File

@@ -3,14 +3,14 @@ from fbchat.models import *
class RemoveBot(Client): class RemoveBot(Client):
def onMessage(self, author_id, message_object, thread_id, thread_type, **kwargs): def on_message(self, author_id, message_object, thread_id, thread_type, **kwargs):
# We can only kick people from group chats, so no need to try if it's a user chat # We can only kick people from group chats, so no need to try if it's a user chat
if message_object.text == "Remove me!" and thread_type == ThreadType.GROUP: if message_object.text == "Remove me!" and thread_type == ThreadType.GROUP:
print("{} will be removed from {}".format(author_id, thread_id)) print("{} will be removed from {}".format(author_id, thread_id))
self.removeUserFromGroup(author_id, thread_id=thread_id) self.remove_user_from_group(author_id, thread_id=thread_id)
else: else:
# Sends the data to the inherited onMessage, so that we can still see when a message is recieved # Sends the data to the inherited on_message, so that we can still see when a message is recieved
super(RemoveBot, self).onMessage( super(RemoveBot, self).on_message(
author_id=author_id, author_id=author_id,
message_object=message_object, message_object=message_object,
thread_id=thread_id, thread_id=thread_id,

File diff suppressed because it is too large Load Diff

View File

@@ -59,7 +59,7 @@ class AudioAttachment(Attachment):
class ImageAttachment(Attachment): class ImageAttachment(Attachment):
"""Represents an image that has been sent as a Facebook attachment. """Represents an image that has been sent as a Facebook attachment.
To retrieve the full image URL, use: `Client.fetchImageUrl`, and pass it the id of To retrieve the full image URL, use: `Client.fetch_image_url`, and pass it the id of
the image attachment. the image attachment.
""" """

View File

@@ -72,7 +72,7 @@ class Message:
created_at = attr.ib(None, init=False) created_at = attr.ib(None, init=False)
#: Whether the message is read #: Whether the message is read
is_read = attr.ib(None, init=False) is_read = attr.ib(None, init=False)
#: A list of people IDs who read the message, works only with :func:`fbchat.Client.fetchThreadMessages` #: A list of people IDs who read the message, works only with :func:`fbchat.Client.fetch_thread_messages`
read_by = attr.ib(factory=list, init=False) read_by = attr.ib(factory=list, init=False)
#: A dictionary with user's IDs as keys, and their :class:`MessageReaction` as values #: A dictionary with user's IDs as keys, and their :class:`MessageReaction` as values
reactions = attr.ib(factory=dict, init=False) reactions = attr.ib(factory=dict, init=False)
@@ -92,15 +92,15 @@ class Message:
forwarded = attr.ib(False, init=False) forwarded = attr.ib(False, init=False)
@classmethod @classmethod
def formatMentions(cls, text, *args, **kwargs): def format_mentions(cls, text, *args, **kwargs):
"""Like `str.format`, but takes tuples with a thread id and text instead. """Like `str.format`, but takes tuples with a thread id and text instead.
Return a `Message` object, with the formatted string and relevant mentions. Return a `Message` object, with the formatted string and relevant mentions.
>>> Message.formatMentions("Hey {!r}! My name is {}", ("1234", "Peter"), ("4321", "Michael")) >>> Message.format_mentions("Hey {!r}! My name is {}", ("1234", "Peter"), ("4321", "Michael"))
<Message (None): "Hey 'Peter'! My name is Michael", mentions=[<Mention 1234: offset=4 length=7>, <Mention 4321: offset=24 length=7>] emoji_size=None attachments=[]> <Message (None): "Hey 'Peter'! My name is Michael", mentions=[<Mention 1234: offset=4 length=7>, <Mention 4321: offset=24 length=7>] emoji_size=None attachments=[]>
>>> Message.formatMentions("Hey {p}! My name is {}", ("1234", "Michael"), p=("4321", "Peter")) >>> Message.format_mentions("Hey {p}! My name is {}", ("1234", "Michael"), p=("4321", "Peter"))
<Message (None): 'Hey Peter! My name is Michael', mentions=[<Mention 4321: offset=4 length=5>, <Mention 1234: offset=22 length=7>] emoji_size=None attachments=[]> <Message (None): 'Hey Peter! My name is Michael', mentions=[<Mention 4321: offset=4 length=5>, <Mention 1234: offset=22 length=7>] emoji_size=None attachments=[]>
""" """
result = "" result = ""

View File

@@ -7,7 +7,7 @@ class Poll:
#: Title of the poll #: Title of the poll
title = attr.ib() title = attr.ib()
#: List of :class:`PollOption`, can be fetched with :func:`fbchat.Client.fetchPollOptions` #: List of :class:`PollOption`, can be fetched with :func:`fbchat.Client.fetch_poll_options`
options = attr.ib() options = attr.ib()
#: Options count #: Options count
options_count = attr.ib(None) options_count = attr.ib(None)

View File

@@ -264,14 +264,14 @@ class State:
] ]
def _do_send_request(self, data): def _do_send_request(self, data):
offline_threading_id = _util.generateOfflineThreadingID() offline_threading_id = _util.generate_offline_threading_id()
data["client"] = "mercury" data["client"] = "mercury"
data["author"] = "fbid:{}".format(self.user_id) data["author"] = "fbid:{}".format(self.user_id)
data["timestamp"] = _util.now() data["timestamp"] = _util.now()
data["source"] = "source:chat:web" data["source"] = "source:chat:web"
data["offline_threading_id"] = offline_threading_id data["offline_threading_id"] = offline_threading_id
data["message_id"] = offline_threading_id data["message_id"] = offline_threading_id
data["threading_id"] = _util.generateMessageID(self._client_id) data["threading_id"] = _util.generate_message_id(self._client_id)
data["ephemeral_ttl_mode:"] = "0" data["ephemeral_ttl_mode:"] = "0"
j = self._post("/messaging/send/", data) j = self._post("/messaging/send/", data)

View File

@@ -55,7 +55,7 @@ def parse_json(content):
raise FBchatFacebookError("Error while parsing JSON: {!r}".format(content)) raise FBchatFacebookError("Error while parsing JSON: {!r}".format(content))
def digitToChar(digit): def digit_to_char(digit):
if digit < 10: if digit < 10:
return str(digit) return str(digit)
return chr(ord("a") + digit - 10) return chr(ord("a") + digit - 10)
@@ -66,21 +66,21 @@ def str_base(number, base):
return "-" + str_base(-number, base) return "-" + str_base(-number, base)
(d, m) = divmod(number, base) (d, m) = divmod(number, base)
if d > 0: if d > 0:
return str_base(d, base) + digitToChar(m) return str_base(d, base) + digit_to_char(m)
return digitToChar(m) return digit_to_char(m)
def generateMessageID(client_id=None): def generate_message_id(client_id=None):
k = now() k = now()
l = int(random.random() * 4294967295) l = int(random.random() * 4294967295)
return "<{}:{}-{}@mail.projektitan.com>".format(k, l, client_id) return "<{}:{}-{}@mail.projektitan.com>".format(k, l, client_id)
def getSignatureID(): def get_signature_id():
return hex(int(random.random() * 2147483648)) return hex(int(random.random() * 2147483648))
def generateOfflineThreadingID(): def generate_offline_threading_id():
ret = now() ret = now()
value = int(random.random() * 4294967295) value = int(random.random() * 4294967295)
string = ("0000000000000000000000" + format(value, "b"))[-22:] string = ("0000000000000000000000" + format(value, "b"))[-22:]

View File

@@ -88,7 +88,7 @@ def catch_event(client2):
try: try:
# Make the client send a messages to itself, so the blocking pull request will return # Make the client send a messages to itself, so the blocking pull request will return
# This is probably not safe, since the client is making two requests simultaneously # This is probably not safe, since the client is making two requests simultaneously
client2.sendMessage(random_hex(), client2.uid) client2.send(Message(text=random_hex()), client2.uid)
finally: finally:
t.join() t.join()

View File

@@ -16,25 +16,25 @@ def test_examples():
@pytest.mark.trylast @pytest.mark.trylast
@pytest.mark.expensive @pytest.mark.expensive
def test_login(client1): def test_login(client1):
assert client1.isLoggedIn() assert client1.is_logged_in()
email = client1.email email = client1.email
password = client1.password password = client1.password
client1.logout() client1.logout()
assert not client1.isLoggedIn() assert not client1.is_logged_in()
with pytest.raises(FBchatException): with pytest.raises(FBchatException):
client1.login("<invalid email>", "<invalid password>", max_tries=1) client1.login("<invalid email>", "<invalid password>", max_tries=1)
client1.login(email, password) client1.login(email, password)
assert client1.isLoggedIn() assert client1.is_logged_in()
@pytest.mark.trylast @pytest.mark.trylast
def test_sessions(client1): def test_sessions(client1):
session = client1.getSession() session = client1.get_session()
Client("no email needed", "no password needed", session_cookies=session) Client("no email needed", "no password needed", session_cookies=session)
client1.setSession(session) client1.set_session(session)
assert client1.isLoggedIn() assert client1.is_logged_in()

View File

@@ -6,24 +6,24 @@ from utils import subset, STICKER_LIST, EMOJI_LIST
def test_fetch_all_users(client1): def test_fetch_all_users(client1):
users = client1.fetchAllUsers() users = client1.fetch_all_users()
assert len(users) > 0 assert len(users) > 0
def test_fetch_thread_list(client1): def test_fetch_thread_list(client1):
threads = client1.fetchThreadList(limit=2) threads = client1.fetch_thread_list(limit=2)
assert len(threads) == 2 assert len(threads) == 2
def test_fetch_threads(client1): def test_fetch_threads(client1):
threads = client1.fetchThreads(limit=2) threads = client1.fetch_threads(limit=2)
assert len(threads) == 2 assert len(threads) == 2
@pytest.mark.parametrize("emoji, emoji_size", EMOJI_LIST) @pytest.mark.parametrize("emoji, emoji_size", EMOJI_LIST)
def test_fetch_message_emoji(client, emoji, emoji_size): def test_fetch_message_emoji(client, emoji, emoji_size):
mid = client.sendEmoji(emoji, emoji_size) mid = client.send_emoji(emoji, emoji_size)
message, = client.fetchThreadMessages(limit=1) message, = client.fetch_thread_messages(limit=1)
assert subset( assert subset(
vars(message), uid=mid, author=client.uid, text=emoji, emoji_size=emoji_size vars(message), uid=mid, author=client.uid, text=emoji, emoji_size=emoji_size
@@ -32,8 +32,8 @@ def test_fetch_message_emoji(client, emoji, emoji_size):
@pytest.mark.parametrize("emoji, emoji_size", EMOJI_LIST) @pytest.mark.parametrize("emoji, emoji_size", EMOJI_LIST)
def test_fetch_message_info_emoji(client, thread, emoji, emoji_size): def test_fetch_message_info_emoji(client, thread, emoji, emoji_size):
mid = client.sendEmoji(emoji, emoji_size) mid = client.send_emoji(emoji, emoji_size)
message = client.fetchMessageInfo(mid, thread_id=thread["id"]) message = client.fetch_message_info(mid, thread_id=thread["id"])
assert subset( assert subset(
vars(message), uid=mid, author=client.uid, text=emoji, emoji_size=emoji_size vars(message), uid=mid, author=client.uid, text=emoji, emoji_size=emoji_size
@@ -42,7 +42,7 @@ def test_fetch_message_info_emoji(client, thread, emoji, emoji_size):
def test_fetch_message_mentions(client, thread, message_with_mentions): def test_fetch_message_mentions(client, thread, message_with_mentions):
mid = client.send(message_with_mentions) mid = client.send(message_with_mentions)
message, = client.fetchThreadMessages(limit=1) message, = client.fetch_thread_messages(limit=1)
assert subset( assert subset(
vars(message), uid=mid, author=client.uid, text=message_with_mentions.text vars(message), uid=mid, author=client.uid, text=message_with_mentions.text
@@ -54,7 +54,7 @@ def test_fetch_message_mentions(client, thread, message_with_mentions):
def test_fetch_message_info_mentions(client, thread, message_with_mentions): def test_fetch_message_info_mentions(client, thread, message_with_mentions):
mid = client.send(message_with_mentions) mid = client.send(message_with_mentions)
message = client.fetchMessageInfo(mid, thread_id=thread["id"]) message = client.fetch_message_info(mid, thread_id=thread["id"])
assert subset( assert subset(
vars(message), uid=mid, author=client.uid, text=message_with_mentions.text vars(message), uid=mid, author=client.uid, text=message_with_mentions.text
@@ -67,7 +67,7 @@ def test_fetch_message_info_mentions(client, thread, message_with_mentions):
@pytest.mark.parametrize("sticker", STICKER_LIST) @pytest.mark.parametrize("sticker", STICKER_LIST)
def test_fetch_message_sticker(client, sticker): def test_fetch_message_sticker(client, sticker):
mid = client.send(Message(sticker=sticker)) mid = client.send(Message(sticker=sticker))
message, = client.fetchThreadMessages(limit=1) message, = client.fetch_thread_messages(limit=1)
assert subset(vars(message), uid=mid, author=client.uid) assert subset(vars(message), uid=mid, author=client.uid)
assert subset(vars(message.sticker), uid=sticker.uid) assert subset(vars(message.sticker), uid=sticker.uid)
@@ -76,22 +76,24 @@ def test_fetch_message_sticker(client, sticker):
@pytest.mark.parametrize("sticker", STICKER_LIST) @pytest.mark.parametrize("sticker", STICKER_LIST)
def test_fetch_message_info_sticker(client, thread, sticker): def test_fetch_message_info_sticker(client, thread, sticker):
mid = client.send(Message(sticker=sticker)) mid = client.send(Message(sticker=sticker))
message = client.fetchMessageInfo(mid, thread_id=thread["id"]) message = client.fetch_message_info(mid, thread_id=thread["id"])
assert subset(vars(message), uid=mid, author=client.uid) assert subset(vars(message), uid=mid, author=client.uid)
assert subset(vars(message.sticker), uid=sticker.uid) assert subset(vars(message.sticker), uid=sticker.uid)
def test_fetch_info(client1, group): def test_fetch_info(client1, group):
info = client1.fetchUserInfo("4")["4"] info = client1.fetch_user_info("4")["4"]
assert info.name == "Mark Zuckerberg" assert info.name == "Mark Zuckerberg"
info = client1.fetchGroupInfo(group["id"])[group["id"]] info = client1.fetch_group_info(group["id"])[group["id"]]
assert info.type == ThreadType.GROUP assert info.type == ThreadType.GROUP
def test_fetch_image_url(client): def test_fetch_image_url(client):
client.sendLocalFiles([path.join(path.dirname(__file__), "resources", "image.png")]) client.send_local_files(
message, = client.fetchThreadMessages(limit=1) [path.join(path.dirname(__file__), "resources", "image.png")]
)
message, = client.fetch_thread_messages(limit=1)
assert client.fetchImageUrl(message.attachments[0].uid) assert client.fetch_image_url(message.attachments[0].uid)

View File

@@ -6,14 +6,14 @@ from utils import subset
def test_set_reaction(client): def test_set_reaction(client):
mid = client.send(Message(text="This message will be reacted to")) mid = client.send(Message(text="This message will be reacted to"))
client.reactToMessage(mid, MessageReaction.LOVE) 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"
mid1 = client.sendMessage(text1) mid1 = client.send(Message(text=text1))
mid2 = client.sendMessage(text2) mid2 = client.send(Message(text=text2))
client.deleteMessages(mid2) client.delete_messages(mid2)
message, = client.fetchThreadMessages(limit=1) message, = client.fetch_thread_messages(limit=1)
assert subset(vars(message), uid=mid1, author=client.uid, text=text1) assert subset(vars(message), uid=mid1, author=client.uid, text=text1)

View File

@@ -17,8 +17,8 @@ from time import time
], ],
) )
def plan_data(request, client, user, thread, catch_event, compare): def plan_data(request, client, user, thread, catch_event, compare):
with catch_event("onPlanCreated") as x: with catch_event("on_plan_created") as x:
client.createPlan(request.param, thread["id"]) client.create_plan(request.param, thread["id"])
assert compare(x) assert compare(x)
assert subset( assert subset(
vars(x.res["plan"]), vars(x.res["plan"]),
@@ -32,8 +32,8 @@ def plan_data(request, client, user, thread, catch_event, compare):
assert user["id"] in x.res["plan"].invited assert user["id"] in x.res["plan"].invited
request.param.uid = x.res["plan"].uid request.param.uid = x.res["plan"].uid
yield x.res, request.param yield x.res, request.param
with catch_event("onPlanDeleted") as x: with catch_event("on_plan_deleted") as x:
client.deletePlan(plan_id) client.delete_plan(plan_id)
assert compare(x) assert compare(x)
@@ -44,7 +44,7 @@ def test_create_delete_plan(plan_data):
def test_fetch_plan_info(client, catch_event, plan_data): def test_fetch_plan_info(client, catch_event, plan_data):
event, plan = plan_data event, plan = plan_data
fetched_plan = client.fetchPlanInfo(plan.uid) fetched_plan = client.fetch_plan_info(plan.uid)
assert subset( assert subset(
vars(fetched_plan), time=plan.time, title=plan.title, author_id=int(client.uid) vars(fetched_plan), time=plan.time, title=plan.title, author_id=int(client.uid)
) )
@@ -55,8 +55,8 @@ def test_change_plan_participation(
client, thread, catch_event, compare, plan_data, take_part client, thread, catch_event, compare, plan_data, take_part
): ):
event, plan = plan_data event, plan = plan_data
with catch_event("onPlanParticipation") as x: with catch_event("on_plan_participation") as x:
client.changePlanParticipation(plan, take_part=take_part) client.change_plan_participation(plan, take_part=take_part)
assert compare(x, take_part=take_part) assert compare(x, take_part=take_part)
assert subset( assert subset(
vars(x.res["plan"]), vars(x.res["plan"]),
@@ -72,8 +72,8 @@ def test_change_plan_participation(
def test_edit_plan(client, thread, catch_event, compare, plan_data): def test_edit_plan(client, thread, catch_event, compare, plan_data):
event, plan = plan_data event, plan = plan_data
new_plan = Plan(plan.time + 100, random_hex()) new_plan = Plan(plan.time + 100, random_hex())
with catch_event("onPlanEdited") as x: with catch_event("on_plan_edited") as x:
client.editPlan(plan, new_plan) client.edit_plan(plan, new_plan)
assert compare(x) assert compare(x)
assert subset( assert subset(
vars(x.res["plan"]), vars(x.res["plan"]),
@@ -86,8 +86,8 @@ def test_edit_plan(client, thread, catch_event, compare, plan_data):
@pytest.mark.trylast @pytest.mark.trylast
@pytest.mark.expensive @pytest.mark.expensive
def test_on_plan_ended(client, thread, catch_event, compare): def test_on_plan_ended(client, thread, catch_event, compare):
with catch_event("onPlanEnded") as x: with catch_event("on_plan_ended") as x:
client.createPlan(Plan(int(time()) + 120, "Wait for ending")) client.create_plan(Plan(int(time()) + 120, "Wait for ending"))
x.wait(180) x.wait(180)
assert subset( assert subset(
x.res, x.res,
@@ -96,15 +96,15 @@ def test_on_plan_ended(client, thread, catch_event, compare):
) )
# createPlan(self, plan, thread_id=None) # create_plan(self, plan, thread_id=None)
# editPlan(self, plan, new_plan) # edit_plan(self, plan, new_plan)
# deletePlan(self, plan) # delete_plan(self, plan)
# changePlanParticipation(self, plan, take_part=True) # change_plan_participation(self, plan, take_part=True)
# onPlanCreated(self, mid=None, plan=None, author_id=None, thread_id=None, thread_type=None, ts=None, metadata=None, msg=None) # on_plan_created(self, mid=None, plan=None, author_id=None, thread_id=None, thread_type=None, ts=None, metadata=None, msg=None)
# onPlanEnded(self, mid=None, plan=None, thread_id=None, thread_type=None, ts=None, metadata=None, msg=None) # on_plan_ended(self, mid=None, plan=None, thread_id=None, thread_type=None, ts=None, metadata=None, msg=None)
# onPlanEdited(self, mid=None, plan=None, author_id=None, thread_id=None, thread_type=None, ts=None, metadata=None, msg=None) # on_plan_edited(self, mid=None, plan=None, author_id=None, thread_id=None, thread_type=None, ts=None, metadata=None, msg=None)
# onPlanDeleted(self, mid=None, plan=None, author_id=None, thread_id=None, thread_type=None, ts=None, metadata=None, msg=None) # on_plan_deleted(self, mid=None, plan=None, author_id=None, thread_id=None, thread_type=None, ts=None, metadata=None, msg=None)
# onPlanParticipation(self, mid=None, plan=None, take_part=None, author_id=None, thread_id=None, thread_type=None, ts=None, metadata=None, msg=None) # on_plan_participation(self, mid=None, plan=None, take_part=None, author_id=None, thread_id=None, thread_type=None, ts=None, metadata=None, msg=None)
# fetchPlanInfo(self, plan_id) # fetch_plan_info(self, plan_id)

View File

@@ -39,9 +39,9 @@ from utils import random_hex, subset
], ],
) )
def poll_data(request, client1, group, catch_event): def poll_data(request, client1, group, catch_event):
with catch_event("onPollCreated") as x: with catch_event("on_poll_created") as x:
client1.createPoll(request.param, thread_id=group["id"]) client1.create_poll(request.param, thread_id=group["id"])
options = client1.fetchPollOptions(x.res["poll"].uid) options = client1.fetch_poll_options(x.res["poll"].uid)
return x.res, request.param, options return x.res, request.param, options
@@ -79,8 +79,8 @@ def test_update_poll_vote(client1, group, catch_event, poll_data):
new_vote_ids = [o.uid for o in options[0 : len(options) : 2] if not o.vote] new_vote_ids = [o.uid for o in options[0 : len(options) : 2] if not o.vote]
re_vote_ids = [o.uid for o in options[0 : len(options) : 2] if o.vote] re_vote_ids = [o.uid for o in options[0 : len(options) : 2] if o.vote]
new_options = [random_hex(), random_hex()] new_options = [random_hex(), random_hex()]
with catch_event("onPollVoted") as x: with catch_event("on_poll_voted") as x:
client1.updatePollVote( client1.update_poll_vote(
event["poll"].uid, event["poll"].uid,
option_ids=new_vote_ids + re_vote_ids, option_ids=new_vote_ids + re_vote_ids,
new_options=new_options, new_options=new_options,

View File

@@ -2,7 +2,7 @@ from fbchat import ThreadType
def test_search_for(client1): def test_search_for(client1):
users = client1.searchForUsers("Mark Zuckerberg") users = client1.search_for_users("Mark Zuckerberg")
assert len(users) > 0 assert len(users) > 0
u = users[0] u = users[0]

View File

@@ -7,8 +7,8 @@ from utils import subset, STICKER_LIST, EMOJI_LIST, TEXT_LIST
@pytest.mark.parametrize("text", TEXT_LIST) @pytest.mark.parametrize("text", TEXT_LIST)
def test_send_text(client, catch_event, compare, text): def test_send_text(client, catch_event, compare, text):
with catch_event("onMessage") as x: with catch_event("on_message") as x:
mid = client.sendMessage(text) mid = client.send(Message(text=text))
assert compare(x, mid=mid, message=text) assert compare(x, mid=mid, message=text)
assert subset(vars(x.res["message_object"]), uid=mid, author=client.uid, text=text) assert subset(vars(x.res["message_object"]), uid=mid, author=client.uid, text=text)
@@ -16,8 +16,8 @@ def test_send_text(client, catch_event, compare, text):
@pytest.mark.parametrize("emoji, emoji_size", EMOJI_LIST) @pytest.mark.parametrize("emoji, emoji_size", EMOJI_LIST)
def test_send_emoji(client, catch_event, compare, emoji, emoji_size): def test_send_emoji(client, catch_event, compare, emoji, emoji_size):
with catch_event("onMessage") as x: with catch_event("on_message") as x:
mid = client.sendEmoji(emoji, emoji_size) mid = client.send_emoji(emoji, emoji_size)
assert compare(x, mid=mid, message=emoji) assert compare(x, mid=mid, message=emoji)
assert subset( assert subset(
@@ -30,7 +30,7 @@ def test_send_emoji(client, catch_event, compare, emoji, emoji_size):
def test_send_mentions(client, catch_event, compare, message_with_mentions): def test_send_mentions(client, catch_event, compare, message_with_mentions):
with catch_event("onMessage") as x: with catch_event("on_message") as x:
mid = client.send(message_with_mentions) mid = client.send(message_with_mentions)
assert compare(x, mid=mid, message=message_with_mentions.text) assert compare(x, mid=mid, message=message_with_mentions.text)
@@ -47,7 +47,7 @@ def test_send_mentions(client, catch_event, compare, message_with_mentions):
@pytest.mark.parametrize("sticker", STICKER_LIST) @pytest.mark.parametrize("sticker", STICKER_LIST)
def test_send_sticker(client, catch_event, compare, sticker): def test_send_sticker(client, catch_event, compare, sticker):
with catch_event("onMessage") as x: with catch_event("on_message") as x:
mid = client.send(Message(sticker=sticker)) mid = client.send(Message(sticker=sticker))
assert compare(x, mid=mid) assert compare(x, mid=mid)
@@ -68,7 +68,7 @@ def test_send_sticker(client, catch_event, compare, sticker):
) )
def test_send_images(client, catch_event, compare, method_name, url): def test_send_images(client, catch_event, compare, method_name, url):
text = "An image sent with {}".format(method_name) text = "An image sent with {}".format(method_name)
with catch_event("onMessage") as x: with catch_event("on_message") as x:
mid = getattr(client, method_name)(url, Message(text)) mid = getattr(client, method_name)(url, Message(text))
assert compare(x, mid=mid, message=text) assert compare(x, mid=mid, message=text)
@@ -87,8 +87,8 @@ def test_send_local_files(client, catch_event, compare):
"video.mp4", "video.mp4",
] ]
text = "Files sent locally" text = "Files sent locally"
with catch_event("onMessage") as x: with catch_event("on_message") as x:
mid = client.sendLocalFiles( mid = client.send_local_files(
[path.join(path.dirname(__file__), "resources", f) for f in files], [path.join(path.dirname(__file__), "resources", f) for f in files],
message=Message(text), message=Message(text),
) )
@@ -102,8 +102,8 @@ def test_send_local_files(client, catch_event, compare):
def test_send_remote_files(client, catch_event, compare): def test_send_remote_files(client, catch_event, compare):
files = ["image.png", "data.json"] files = ["image.png", "data.json"]
text = "Files sent from remote" text = "Files sent from remote"
with catch_event("onMessage") as x: with catch_event("on_message") as x:
mid = client.sendRemoteFiles( mid = client.send_remote_files(
[ [
"https://github.com/carpedm20/fbchat/raw/master/tests/{}".format(f) "https://github.com/carpedm20/fbchat/raw/master/tests/{}".format(f)
for f in files for f in files

View File

@@ -3,6 +3,6 @@ import pytest
def test_catch_event(client2, catch_event): def test_catch_event(client2, catch_event):
mid = "test" mid = "test"
with catch_event("onMessage") as x: with catch_event("on_message") as x:
client2.onMessage(mid=mid) client2.on_message(mid=mid)
assert x.res["mid"] == mid assert x.res["mid"] == mid

View File

@@ -8,14 +8,14 @@ from os import path
def test_remove_from_and_add_to_group(client1, client2, group, catch_event): def test_remove_from_and_add_to_group(client1, client2, group, catch_event):
# Test both methods, while ensuring that the user gets added to the group # Test both methods, while ensuring that the user gets added to the group
try: try:
with catch_event("onPersonRemoved") as x: with catch_event("on_person_removed") as x:
client1.removeUserFromGroup(client2.uid, group["id"]) client1.remove_user_from_group(client2.uid, group["id"])
assert subset( assert subset(
x.res, removed_id=client2.uid, author_id=client1.uid, thread_id=group["id"] x.res, removed_id=client2.uid, author_id=client1.uid, thread_id=group["id"]
) )
finally: finally:
with catch_event("onPeopleAdded") as x: with catch_event("on_people_added") as x:
client1.addUsersToGroup(client2.uid, group["id"]) client1.add_users_to_group(client2.uid, group["id"])
assert subset( assert subset(
x.res, added_ids=[client2.uid], author_id=client1.uid, thread_id=group["id"] x.res, added_ids=[client2.uid], author_id=client1.uid, thread_id=group["id"]
) )
@@ -24,14 +24,14 @@ def test_remove_from_and_add_to_group(client1, client2, group, catch_event):
def test_remove_from_and_add_admins_to_group(client1, client2, group, catch_event): def test_remove_from_and_add_admins_to_group(client1, client2, group, catch_event):
# Test both methods, while ensuring that the user gets added as group admin # Test both methods, while ensuring that the user gets added as group admin
try: try:
with catch_event("onAdminRemoved") as x: with catch_event("on_admin_removed") as x:
client1.removeGroupAdmins(client2.uid, group["id"]) client1.remove_group_admins(client2.uid, group["id"])
assert subset( assert subset(
x.res, removed_id=client2.uid, author_id=client1.uid, thread_id=group["id"] x.res, removed_id=client2.uid, author_id=client1.uid, thread_id=group["id"]
) )
finally: finally:
with catch_event("onAdminAdded") as x: with catch_event("on_admin_added") as x:
client1.addGroupAdmins(client2.uid, group["id"]) client1.add_group_admins(client2.uid, group["id"])
assert subset( assert subset(
x.res, added_id=client2.uid, author_id=client1.uid, thread_id=group["id"] x.res, added_id=client2.uid, author_id=client1.uid, thread_id=group["id"]
) )
@@ -39,8 +39,8 @@ def test_remove_from_and_add_admins_to_group(client1, client2, group, catch_even
def test_change_title(client1, group, catch_event): def test_change_title(client1, group, catch_event):
title = random_hex() title = random_hex()
with catch_event("onTitleChange") as x: with catch_event("on_title_change") as x:
client1.changeThreadTitle(title, group["id"], thread_type=ThreadType.GROUP) client1.change_thread_title(title, group["id"], thread_type=ThreadType.GROUP)
assert subset( assert subset(
x.res, x.res,
author_id=client1.uid, author_id=client1.uid,
@@ -52,8 +52,8 @@ def test_change_title(client1, group, catch_event):
def test_change_nickname(client, client_all, catch_event, compare): def test_change_nickname(client, client_all, catch_event, compare):
nickname = random_hex() nickname = random_hex()
with catch_event("onNicknameChange") as x: with catch_event("on_nickname_change") as x:
client.changeNickname(nickname, client_all.uid) client.change_nickname(nickname, client_all.uid)
assert compare(x, changed_for=client_all.uid, new_nickname=nickname) assert compare(x, changed_for=client_all.uid, new_nickname=nickname)
@@ -71,15 +71,15 @@ def test_change_nickname(client, client_all, catch_event, compare):
], ],
) )
def test_change_emoji(client, catch_event, compare, emoji): def test_change_emoji(client, catch_event, compare, emoji):
with catch_event("onEmojiChange") as x: with catch_event("on_emoji_change") as x:
client.changeThreadEmoji(emoji) client.change_thread_emoji(emoji)
assert compare(x, new_emoji=emoji) assert compare(x, new_emoji=emoji)
def test_change_image_local(client1, group, catch_event): def test_change_image_local(client1, group, catch_event):
url = path.join(path.dirname(__file__), "resources", "image.png") url = path.join(path.dirname(__file__), "resources", "image.png")
with catch_event("onImageChange") as x: with catch_event("on_image_change") as x:
image_id = client1.changeGroupImageLocal(url, group["id"]) image_id = client1.change_group_image_local(url, group["id"])
assert subset( assert subset(
x.res, new_image=image_id, author_id=client1.uid, thread_id=group["id"] x.res, new_image=image_id, author_id=client1.uid, thread_id=group["id"]
) )
@@ -88,8 +88,8 @@ def test_change_image_local(client1, group, catch_event):
# To be changed when merged into master # To be changed when merged into master
def test_change_image_remote(client1, group, catch_event): def test_change_image_remote(client1, group, catch_event):
url = "https://github.com/carpedm20/fbchat/raw/master/tests/image.png" url = "https://github.com/carpedm20/fbchat/raw/master/tests/image.png"
with catch_event("onImageChange") as x: with catch_event("on_image_change") as x:
image_id = client1.changeGroupImageRemote(url, group["id"]) image_id = client1.change_group_image_remote(url, group["id"])
assert subset( assert subset(
x.res, new_image=image_id, author_id=client1.uid, thread_id=group["id"] x.res, new_image=image_id, author_id=client1.uid, thread_id=group["id"]
) )
@@ -105,8 +105,8 @@ def test_change_image_remote(client1, group, catch_event):
], ],
) )
def test_change_color(client, catch_event, compare, color): def test_change_color(client, catch_event, compare, color):
with catch_event("onColorChange") as x: with catch_event("on_color_change") as x:
client.changeThreadColor(color) client.change_thread_color(color)
assert compare(x, new_color=color) assert compare(x, new_color=color)
@@ -115,20 +115,20 @@ def test_change_color_invalid(client):
class InvalidColor: class InvalidColor:
value = "#0077ff" value = "#0077ff"
client.changeThreadColor(InvalidColor()) client.change_thread_color(InvalidColor())
@pytest.mark.parametrize("status", TypingStatus) @pytest.mark.parametrize("status", TypingStatus)
def test_typing_status(client, catch_event, compare, status): def test_typing_status(client, catch_event, compare, status):
with catch_event("onTyping") as x: with catch_event("on_typing") as x:
client.setTypingStatus(status) client.set_typing_status(status)
assert compare(x, status=status) assert compare(x, status=status)
@pytest.mark.parametrize("require_admin_approval", [True, False]) @pytest.mark.parametrize("require_admin_approval", [True, False])
def test_change_approval_mode(client1, group, catch_event, require_admin_approval): def test_change_approval_mode(client1, group, catch_event, require_admin_approval):
with catch_event("onApprovalModeChange") as x: with catch_event("on_approval_mode_change") as x:
client1.changeGroupApprovalMode(require_admin_approval, group["id"]) client1.change_group_approval_mode(require_admin_approval, group["id"])
assert subset( assert subset(
x.res, x.res,
@@ -140,15 +140,15 @@ def test_change_approval_mode(client1, group, catch_event, require_admin_approva
@pytest.mark.parametrize("mute_time", [0, 10, 100, 1000, -1]) @pytest.mark.parametrize("mute_time", [0, 10, 100, 1000, -1])
def test_mute_thread(client, mute_time): def test_mute_thread(client, mute_time):
assert client.muteThread(mute_time) assert client.mute_thread(mute_time)
assert client.unmuteThread() assert client.unmute_thread()
def test_mute_thread_reactions(client): def test_mute_thread_reactions(client):
assert client.muteThreadReactions() assert client.mute_thread_reactions()
assert client.unmuteThreadReactions() assert client.unmute_thread_reactions()
def test_mute_thread_mentions(client): def test_mute_thread_mentions(client):
assert client.muteThreadMentions() assert client.mute_thread_mentions()
assert client.unmuteThreadMentions() assert client.unmute_thread_mentions()

View File

@@ -46,11 +46,11 @@ class ClientThread(threading.Thread):
super(ClientThread, self).__init__(*args, **kwargs) super(ClientThread, self).__init__(*args, **kwargs)
def start(self): def start(self):
self.client._doOneListen() # QPrimer, Facebook now knows we're about to start pulling self.client._do_one_listen() # QPrimer, Facebook now knows we're about to start pulling
super(ClientThread, self).start() super(ClientThread, self).start()
def run(self): def run(self):
while not self.should_stop.is_set() and self.client._doOneListen(): while not self.should_stop.is_set() and self.client._do_one_listen():
pass pass
@@ -95,4 +95,4 @@ def load_client(n, cache):
max_tries=1, max_tries=1,
) )
yield client yield client
cache.set("client{}_session".format(n), client.getSession()) cache.set("client{}_session".format(n), client.get_session())