Fixed examples, added changeNickname and changeThreadEmoji, changed changeGroupTitle back to changeThreadTitle

I also removed the parameter `set_default_events` from __init__, since
it's not really necessary
Also added testing of examples and simple testing of listen functions
This commit is contained in:
Mads Marquart
2017-05-26 18:48:37 +02:00
parent d2741ca419
commit 39eafa5a3e
6 changed files with 173 additions and 87 deletions

View File

@@ -4,11 +4,11 @@ from fbchat import log, Client
# Subclass fbchat.Client and override required methods # Subclass fbchat.Client and override required methods
class EchoBot(Client): class EchoBot(Client):
def onMessage(self, mid, author_id, message, thread_id, thread_type, ts, metadata, msg): def onMessage(self, author_id, message, thread_id, thread_type, **kwargs):
self.markAsDelivered(author_id, thread_id) self.markAsDelivered(author_id, thread_id)
self.markAsRead(author_id) self.markAsRead(author_id)
log.info("Message from {} in {} ({}): {}".format(author_id, thread_id, thread_type.name, message))) log.info("Message from {} in {} ({}): {}".format(author_id, thread_id, thread_type.name, message))
# If you're not the author, echo # If you're not the author, echo
if author_id != self.uid: if author_id != self.uid:

View File

@@ -18,39 +18,37 @@ old_nicknames = {
} }
class KeepBot(Client): class KeepBot(Client):
def onColorChange(self, mid, author_id, new_color, thread_id, thread_type, ts, metadata, msg): def onColorChange(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:
log.info("{} changed the thread color. It will be changed back".format(author_id)) log.info("{} changed the thread color. It will be changed back".format(author_id))
self.changeThreadColor(old_color, thread_id=thread_id) self.changeThreadColor(old_color, thread_id=thread_id)
def onEmojiChange(self, mid, author_id, new_emoji, thread_id, thread_type, ts, metadata, msg): def onEmojiChange(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:
log.info("{} changed the thread emoji. It will be changed back".format(author_id)) log.info("{} changed the thread emoji. It will be changed back".format(author_id))
# Not currently possible in `fbchat` self.changeThreadEmoji(old_emoji, thread_id=thread_id)
# self.changeThreadEmoji(old_emoji, thread_id=thread_id)
def onPeopleAdded(self, added_ids, author_id, thread_id, msg): def onPeopleAdded(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:
log.info("{} got added. They will be removed".format(added_ids)) log.info("{} 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.removeUserFromGroup(added_id, thread_id=thread_id)
def onPersonRemoved(self, removed_id, author_id, thread_id, msg): def onPersonRemoved(self, removed_id, author_id, thread_id, **kwargs):
# No point in trying to add ourself # No point in trying to add ourself
if old_thread_id == thread_id and removed_id != self.uid and author_id != self.uid: if old_thread_id == thread_id and removed_id != self.uid and author_id != self.uid:
log.info("{} got removed. They will be re-added".format(removed_id)) log.info("{} got removed. They will be re-added".format(removed_id))
self.addUsersToGroup(removed_id, thread_id=thread_id) self.addUsersToGroup(removed_id, thread_id=thread_id)
def onTitleChange(self, mid, author_id, new_title, thread_id, thread_type, ts, metadata, msg): def onTitleChange(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:
log.info("{} changed the thread title. It will be changed back".format(author_id)) log.info("{} changed the thread title. It will be changed back".format(author_id))
self.changeGroupTitle(old_title, thread_id=thread_id) self.changeThreadTitle(old_title, thread_id=thread_id, thread_type=thread_type)
def onNicknameChange(self, mid, author_id, changed_for, new_nickname, thread_id, thread_type, ts, metadata, msg): def onNicknameChange(self, author_id, changed_for, new_nickname, thread_id, thread_type, **kwargs):
if old_thread_id == thread_id and changed_for in old_nicknames: if old_thread_id == thread_id and changed_for in old_nicknames and old_nicknames[changed_for] != new_nickname:
log.info("{} changed {}'s' nickname. It will be changed back".format(author_id, changed_for)) log.info("{} changed {}'s' nickname. It will be changed back".format(author_id, changed_for))
# Not currently possible in `fbchat` self.changeNickname(old_nicknames[changed_for], changed_for, thread_id=thread_id, thread_type=thread_type)
# self.changeNickname(old_nicknames[changed_for], changed_for, thread_id=thread_id, thread_type=thread_type)
client = KeepBot("<email>", "<password>") client = KeepBot("<email>", "<password>")
client.listen() client.listen()

View File

@@ -4,13 +4,13 @@ from fbchat import log, Client
from fbchat.models import * from fbchat.models import *
class RemoveBot(Client): class RemoveBot(Client):
def onMessage(self, mid, author_id, message, thread_id, thread_type, ts, metadata, msg): def onMessage(self, author_id, message, 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 == 'Remove me!' and thread_type == ThreadType.GROUP: if message == 'Remove me!' and thread_type == ThreadType.GROUP:
log.info("{} will be removed from {}".format(author_id, thread_id))) log.info("{} will be removed from {}".format(author_id, thread_id))
self.removeUserFromGroup(user_id, thread_id=thread_id) self.removeUserFromGroup(author_id, thread_id=thread_id)
else: else:
log.info("Message from {} in {} ({}): {}".format(author_id, thread_id, thread_type.name, message))) log.info("Message from {} in {} ({}): {}".format(author_id, thread_id, thread_type.name, message))
client = RemoveBot("<email>", "<password>") client = RemoveBot("<email>", "<password>")
client.listen() client.listen()

View File

@@ -35,7 +35,7 @@ class Client(object):
""" """
def __init__(self, email, password, debug=False, info_log=False, user_agent=None, max_retries=5, def __init__(self, email, password, debug=False, info_log=False, user_agent=None, max_retries=5,
session_cookies=None, logging_level=logging.INFO, set_default_events=True): session_cookies=None, logging_level=logging.INFO):
"""Initializes and logs in the client """Initializes and logs in the client
:param email: Facebook `email`, `id` or `phone number` :param email: Facebook `email`, `id` or `phone number`
@@ -44,11 +44,9 @@ class Client(object):
:param max_retries: Maximum number of times to retry login :param max_retries: Maximum number of times to retry login
:param session_cookies: Cookies from a previous session (Will default to login if these are invalid) :param session_cookies: Cookies from a previous session (Will default to login if these are invalid)
:param logging_level: Configures the `logging level <https://docs.python.org/3/library/logging.html#logging-levels>`_. Defaults to `INFO` :param logging_level: Configures the `logging level <https://docs.python.org/3/library/logging.html#logging-levels>`_. Defaults to `INFO`
:param set_default_events: Specifies whether the default `logging.info` events should be initialized
:type max_retries: int :type max_retries: int
:type session_cookies: dict :type session_cookies: dict
:type logging_level: int :type logging_level: int
:type set_default_events: bool
:raises: Exception on failed login :raises: Exception on failed login
""" """
@@ -62,7 +60,6 @@ class Client(object):
self.default_thread_id = None self.default_thread_id = None
self.default_thread_type = None self.default_thread_type = None
self.threads = [] self.threads = []
self.set_default_events = set_default_events
self._setupEventHooks() self._setupEventHooks()
self._setupOldEventHooks() self._setupOldEventHooks()
@@ -94,10 +91,7 @@ class Client(object):
def _setEventHook(self, event_name, *functions): def _setEventHook(self, event_name, *functions):
if not hasattr(type(self), event_name): if not hasattr(type(self), event_name):
if self.set_default_events: eventhook = EventHook(*functions)
eventhook = EventHook(*functions)
else:
eventhook = EventHook()
setattr(self, event_name, eventhook) setattr(self, event_name, eventhook)
def _setupEventHooks(self): def _setupEventHooks(self):
@@ -138,16 +132,18 @@ class Client(object):
log.info("Marked messages as seen in threads {} at {}s".format([(x[0], x[1].name) for x in threads], seen_ts/1000))) log.info("Marked messages as seen in threads {} at {}s".format([(x[0], x[1].name) for x in threads], seen_ts/1000)))
self._setEventHook('onPeopleAdded', lambda added_ids, author_id, thread_id, msg:\ self._setEventHook('onPeopleAdded', lambda mid, added_ids, author_id, thread_id, ts, msg:\
log.info("{} added: {}".format(author_id, ', '.join(added_ids)))) log.info("{} added: {}".format(author_id, ', '.join(added_ids))))
self._setEventHook('onPersonRemoved', lambda removed_id, author_id, thread_id, msg:\ self._setEventHook('onPersonRemoved', lambda mid, removed_id, author_id, thread_id, ts, msg:\
log.info("{} removed: {}".format(author_id, removed_id))) log.info("{} removed: {}".format(author_id, removed_id)))
self._setEventHook('onFriendRequest', lambda from_id, msg: log.info("Friend request from {}".format(from_id))) self._setEventHook('onFriendRequest', lambda from_id, msg: log.info("Friend request from {}".format(from_id)))
self._setEventHook('onInbox', lambda unseen, unread, recent_unread, msg: log.info('Inbox event: {}, {}, {}'.format(unseen, unread, recent_unread))) self._setEventHook('onInbox', lambda unseen, unread, recent_unread, msg: log.info('Inbox event: {}, {}, {}'.format(unseen, unread, recent_unread)))
self._setEventHook('onQprimer', lambda made, msg: None)
self._setEventHook('onUnknownMesssageType', lambda msg: log.debug('Unknown message received: {}'.format(msg))) self._setEventHook('onUnknownMesssageType', lambda msg: log.debug('Unknown message received: {}'.format(msg)))
@@ -447,12 +443,9 @@ class Client(object):
""" """
Safely logs out the client Safely logs out the client
.. todo::
Possibly check return parameter with _checkRequest, and the write documentation about the return
:param timeout: See `requests timeout <http://docs.python-requests.org/en/master/user/advanced/#timeouts>`_ :param timeout: See `requests timeout <http://docs.python-requests.org/en/master/user/advanced/#timeouts>`_
:return: :return: True if the action was successful
:rtype: :rtype: bool
""" """
data = { data = {
'ref': "mb", 'ref': "mb",
@@ -466,7 +459,8 @@ class Client(object):
self._session = requests.session() self._session = requests.session()
self.req_counter = 1 self.req_counter = 1
self.seq = "0" self.seq = "0"
return r
return r.ok
@deprecated(deprecated_in='0.10.2', removed_in='0.15.0', details='Use setDefaultThread instead') @deprecated(deprecated_in='0.10.2', removed_in='0.15.0', details='Use setDefaultThread instead')
def setDefaultRecipient(self, recipient_id, is_user=True): def setDefaultRecipient(self, recipient_id, is_user=True):
@@ -928,13 +922,13 @@ class Client(object):
image_id = self._uploadImage(image_path, open(image_path, 'rb'), mimetype) image_id = self._uploadImage(image_path, open(image_path, 'rb'), mimetype)
return self.sendImage(image_id=image_id, message=message, thread_id=thread_id, thread_type=thread_type) return self.sendImage(image_id=image_id, message=message, thread_id=thread_id, thread_type=thread_type)
def addUsersToGroup(self, user_ids, thread_id=None): def addUsersToGroup(self, *user_ids, thread_id=None):
""" """
Adds users to a group. Adds users to a group.
:param user_ids: User ids to add :param user_ids: User ids to add
:param thread_id: Group ID to add people to. See :ref:`intro_thread_id` :param thread_id: Group ID to add people to. See :ref:`intro_thread_id`
:type user_ids: list :type user_ids: list of positional arguments
:return: :ref:`Message ID <intro_message_ids>` of the sent "message" :return: :ref:`Message ID <intro_message_ids>` of the sent "message"
""" """
thread_id, thread_type = self._getThread(thread_id, None) thread_id, thread_type = self._getThread(thread_id, None)
@@ -986,29 +980,61 @@ class Client(object):
def remove_user_from_chat(self, threadID, userID): def remove_user_from_chat(self, threadID, userID):
return self.removeUserFromGroup(userID, thread_id=threadID) return self.removeUserFromGroup(userID, thread_id=threadID)
@deprecated(deprecated_in='0.10.2', removed_in='0.15.0', details='Use changeGroupTitle() instead') def changeThreadTitle(self, title, thread_id=None, thread_type=ThreadType.USER):
def changeThreadTitle(self, threadID, newTitle):
return self.changeGroupTitle(newTitle, thread_id=threadID)
def changeGroupTitle(self, title, thread_id=None):
""" """
Changes title of a group conversation. Changes title of a thread
.. todo::
Check whether this can work on group threads, and if it does, change it (back) to changeThreadTitle
:param title: New group chat title :param title: New group chat title
:param thread_id: Group ID to change title of. See :ref:`intro_thread_id` :param thread_id: Group ID to change title of. See :ref:`intro_thread_id`
:return: :ref:`Message ID <intro_message_ids>` of the sent "message" :param thread_type: See :ref:`intro_thread_type`
:type thread_type: models.ThreadType
:return: True if the action was successful
:rtype: bool
""" """
thread_id, thread_type = self._getThread(thread_id, None) # For backwards compatability. Previously `thread_id` and `title` were swapped around
data = self._getSendData(thread_id, ThreadType.GROUP) try:
int(thread_id)
except ValueError:
deprecation('changeThreadTitle(threadID, newTitle)', deprecated_in='0.10.2', removed_in='0.15.0', details='Use changeThreadTitle(title, thread_id, thread_type) instead')
title, thread_id, thread_type = thread_id, title, ThreadType.GROUP
data['action_type'] = 'ma-type:log-message' thread_id, thread_type = self._getThread(thread_id, thread_type)
data['log_message_data[name]'] = title
data['log_message_type'] = 'log:thread-name'
return self._doSendRequest(data) if thread_type == ThreadType.USER:
# The thread is a user, so we change the user's nickname
return self.changeNickname(title, thread_id, thread_id=thread_id, thread_type=thread_type)
else:
data = self._getSendData(thread_id, thread_type)
data['action_type'] = 'ma-type:log-message'
data['log_message_data[name]'] = title
data['log_message_type'] = 'log:thread-name'
return False if self._doSendRequest(data) is None else True
def changeNickname(self, nickname, user_id, thread_id=None, thread_type=ThreadType.USER):
"""
Changes the nickname of a user in a thread
:param nickname: New nickname
:param user_id: User that will have their nickname changed
:param thread_id: User/Group ID to change color of. See :ref:`intro_thread_id`
:param thread_type: See :ref:`intro_thread_type`
:type thread_type: models.ThreadType
:return: True if the action was successful
:rtype: bool
"""
thread_id, thread_type = self._getThread(thread_id, thread_type)
data = {
'nickname': nickname,
'participant_id': user_id,
'thread_or_other_fbid': thread_id
}
j = self._checkRequest(self._post(ReqUrl.THREAD_NICKNAME, data))
return False if j is None else True
def changeThreadColor(self, color, thread_id=None): def changeThreadColor(self, color, thread_id=None):
""" """
@@ -1017,19 +1043,42 @@ class Client(object):
:param color: New thread color :param color: New thread color
:param thread_id: User/Group ID to change color of. See :ref:`intro_thread_id` :param thread_id: User/Group ID to change color of. See :ref:`intro_thread_id`
:type color: models.ThreadColor :type color: models.ThreadColor
:return: (*bool*) True if the action was successful :return: True if the action was successful
:rtype: bool
""" """
thread_id, thread_type = self._getThread(thread_id, None) thread_id, thread_type = self._getThread(thread_id, None)
data = { data = {
"color_choice": color.value, 'color_choice': color.value,
"thread_or_other_fbid": thread_id 'thread_or_other_fbid': thread_id
} }
j = self._checkRequest(self._post(ReqUrl.THREAD_COLOR, data)) j = self._checkRequest(self._post(ReqUrl.THREAD_COLOR, data))
return False if j is None else True return False if j is None else True
def changeThreadEmoji(self, emoji, thread_id=None):
"""
Changes thread color
Trivia: While changing the emoji, the Facebook web client actually sends multiple different requests, though only this one is required to make the change
:param color: New thread emoji
:param thread_id: User/Group ID to change emoji of. See :ref:`intro_thread_id`
:return: True if the action was successful
:rtype: bool
"""
thread_id, thread_type = self._getThread(thread_id, None)
data = {
'emoji_choice': emoji,
'thread_or_other_fbid': thread_id
}
j = self._checkRequest(self._post(ReqUrl.THREAD_EMOJI, data))
return False if j is None else True
def reactToMessage(self, message_id, reaction): def reactToMessage(self, message_id, reaction):
""" """
Reacts to a message. Reacts to a message.
@@ -1280,7 +1329,7 @@ class Client(object):
thread_id, thread_type = getThreadIdAndThreadType(metadata) thread_id, thread_type = getThreadIdAndThreadType(metadata)
self.onNicknameChange(mid=mid, author_id=author_id, changed_for=changed_for, self.onNicknameChange(mid=mid, author_id=author_id, changed_for=changed_for,
new_nickname=new_nickname, new_nickname=new_nickname,
thread_id=thread_id, thread_type=thread_type, ts=ts, metadata=metadata) thread_id=thread_id, thread_type=thread_type, ts=ts, metadata=metadata, msg=m)
continue continue
# Message delivered # Message delivered
@@ -1347,7 +1396,7 @@ class Client(object):
# Happens on every login # Happens on every login
elif mtype == "qprimer": elif mtype == "qprimer":
pass self.onQprimer(made=m.get("made"), msg=m)
# Is sent before any other message # Is sent before any other message
elif mtype == "deltaflow": elif mtype == "deltaflow":

View File

@@ -57,6 +57,8 @@ class ReqUrl(object):
SAVE_DEVICE = "https://m.facebook.com/login/save-device/cancel/" SAVE_DEVICE = "https://m.facebook.com/login/save-device/cancel/"
CHECKPOINT = "https://m.facebook.com/login/checkpoint/" CHECKPOINT = "https://m.facebook.com/login/checkpoint/"
THREAD_COLOR = "https://www.facebook.com/messaging/save_thread_color/?source=thread_settings&dpr=1" THREAD_COLOR = "https://www.facebook.com/messaging/save_thread_color/?source=thread_settings&dpr=1"
THREAD_NICKNAME = "https://www.facebook.com/messaging/save_thread_nickname/?source=thread_settings&dpr=1"
THREAD_EMOJI = "https://www.facebook.com/messaging/save_thread_emoji/?source=thread_settings&dpr=1"
MESSAGE_REACTION = "https://www.facebook.com/webgraphql/mutation" MESSAGE_REACTION = "https://www.facebook.com/webgraphql/mutation"
TYPING = "https://www.facebook.com/ajax/messaging/typ.php" TYPING = "https://www.facebook.com/ajax/messaging/typ.php"

View File

@@ -7,13 +7,33 @@ import logging
import unittest import unittest
from getpass import getpass from getpass import getpass
from sys import argv from sys import argv
from os import path from os import path, chdir
from glob import glob
from fbchat import Client from fbchat import Client
from fbchat.models import * from fbchat.models import *
import py_compile
logging_level = logging.ERROR logging_level = logging.ERROR
class CustomClient(Client):
def __init__(self, *args, **kwargs):
self.got_qprimer = False
super(type(self), self).__init__(*args, **kwargs)
def onQprimer(self, made, msg):
self.got_qprimer = True
class TestFbchat(unittest.TestCase): class TestFbchat(unittest.TestCase):
def test_examples(self):
# Checks for syntax errors in the examples
chdir('examples')
for f in glob('*.txt'):
print(f)
with self.assertRaises(py_compile.PyCompileError):
py_compile.compile(f)
chdir('..')
def test_loginFunctions(self): def test_loginFunctions(self):
self.assertTrue(client.isLoggedIn()) self.assertTrue(client.isLoggedIn())
@@ -31,13 +51,16 @@ class TestFbchat(unittest.TestCase):
def test_sessions(self): def test_sessions(self):
global client global client
session_cookies = client.getSession() session_cookies = client.getSession()
client = Client(email, password, session_cookies=session_cookies, logging_level=logging_level) client = CustomClient(email, password, session_cookies=session_cookies, logging_level=logging_level)
self.assertTrue(client.isLoggedIn()) self.assertTrue(client.isLoggedIn())
def test_defaultThread(self): def test_defaultThread(self):
# setDefaultThread # setDefaultThread
client.setDefaultThread(client.uid, ThreadType.USER) client.setDefaultThread(group_uid, ThreadType.GROUP)
self.assertTrue(client.sendMessage('test_default_recipient★'))
client.setDefaultThread(user_uid, ThreadType.USER)
self.assertTrue(client.sendMessage('test_default_recipient★')) self.assertTrue(client.sendMessage('test_default_recipient★'))
# resetDefaultThread # resetDefaultThread
@@ -50,7 +73,7 @@ class TestFbchat(unittest.TestCase):
self.assertGreater(len(users), 0) self.assertGreater(len(users), 0)
def test_getUsers(self): def test_getUsers(self):
users = client.getUsers("Mark Zuckerberg") users = client.getUsers('Mark Zuckerberg')
self.assertGreater(len(users), 0) self.assertGreater(len(users), 0)
u = users[0] u = users[0]
@@ -66,11 +89,11 @@ class TestFbchat(unittest.TestCase):
def test_sendEmoji(self): def test_sendEmoji(self):
self.assertTrue(client.sendEmoji(size=EmojiSize.SMALL, thread_id=user_uid, thread_type=ThreadType.USER)) self.assertTrue(client.sendEmoji(size=EmojiSize.SMALL, thread_id=user_uid, thread_type=ThreadType.USER))
self.assertTrue(client.sendEmoji(size=EmojiSize.MEDIUM, thread_id=user_uid, thread_type=ThreadType.USER)) self.assertTrue(client.sendEmoji(size=EmojiSize.MEDIUM, thread_id=user_uid, thread_type=ThreadType.USER))
self.assertTrue(client.sendEmoji("😆", EmojiSize.LARGE, user_uid, ThreadType.USER)) self.assertTrue(client.sendEmoji('😆', EmojiSize.LARGE, user_uid, ThreadType.USER))
self.assertTrue(client.sendEmoji(size=EmojiSize.SMALL, thread_id=group_uid, thread_type=ThreadType.GROUP)) self.assertTrue(client.sendEmoji(size=EmojiSize.SMALL, thread_id=group_uid, thread_type=ThreadType.GROUP))
self.assertTrue(client.sendEmoji(size=EmojiSize.MEDIUM, thread_id=group_uid, thread_type=ThreadType.GROUP)) self.assertTrue(client.sendEmoji(size=EmojiSize.MEDIUM, thread_id=group_uid, thread_type=ThreadType.GROUP))
self.assertTrue(client.sendEmoji("😆", EmojiSize.LARGE, group_uid, ThreadType.GROUP)) self.assertTrue(client.sendEmoji('😆', EmojiSize.LARGE, group_uid, ThreadType.GROUP))
def test_sendMessage(self): def test_sendMessage(self):
self.assertIsNotNone(client.sendMessage('test_send_user★', user_uid, ThreadType.USER)) self.assertIsNotNone(client.sendMessage('test_send_user★', user_uid, ThreadType.USER))
@@ -81,10 +104,9 @@ class TestFbchat(unittest.TestCase):
def test_sendImages(self): def test_sendImages(self):
image_url = 'https://cdn4.iconfinder.com/data/icons/ionicons/512/icon-image-128.png' image_url = 'https://cdn4.iconfinder.com/data/icons/ionicons/512/icon-image-128.png'
image_local_url = path.join(path.dirname(__file__), 'tests/image.png') image_local_url = path.join(path.dirname(__file__), 'tests/image.png')
#self.assertTrue(client.sendRemoteImage(image_url, 'test_send_user_images_remote', user_uid, ThreadType.USER)) self.assertTrue(client.sendRemoteImage(image_url, 'test_send_user_images_remote', user_uid, ThreadType.USER))
self.assertTrue(client.sendRemoteImage(image_url, 'test_send_group_images_remote★', group_uid, ThreadType.GROUP)) self.assertTrue(client.sendRemoteImage(image_url, 'test_send_group_images_remote★', group_uid, ThreadType.GROUP))
# Idk why but doesnt work, payload is null self.assertTrue(client.sendLocalImage(image_local_url, 'test_send_group_images_local★', user_uid, ThreadType.USER))
#self.assertTrue(client.sendLocalImage(image_local_url, 'test_send_group_images_local', user_uid, ThreadType.USER))
self.assertTrue(client.sendLocalImage(image_local_url, 'test_send_group_images_local★', group_uid, ThreadType.GROUP)) self.assertTrue(client.sendLocalImage(image_local_url, 'test_send_group_images_local★', group_uid, ThreadType.GROUP))
def test_getThreadInfo(self): def test_getThreadInfo(self):
@@ -100,23 +122,36 @@ class TestFbchat(unittest.TestCase):
self.assertEqual(info[0].author, 'fbid:' + client.uid) self.assertEqual(info[0].author, 'fbid:' + client.uid)
self.assertEqual(info[0].body, 'test_group_getThreadInfo★') self.assertEqual(info[0].body, 'test_group_getThreadInfo★')
def test_markAs(self):
# To be implemented (requires some form of manual watching)
pass
def test_listen(self): def test_listen(self):
client.startListening()
client.doOneListen() client.doOneListen()
client.stopListening()
self.assertTrue(client.got_qprimer)
def test_getUserInfo(self): def test_getUserInfo(self):
info = client.getUserInfo(4) info = client.getUserInfo(4)
self.assertEqual(info['name'], 'Mark Zuckerberg') self.assertEqual(info['name'], 'Mark Zuckerberg')
def test_removeAddFromGroup(self): def test_removeAddFromGroup(self):
self.assertTrue(client.removeUserFromGroup(user_uid, group_uid)) self.assertTrue(client.removeUserFromGroup(user_uid, thread_id=group_uid))
self.assertTrue(client.addUsersToGroup([user_uid], group_uid)) self.assertTrue(client.addUsersToGroup(user_uid, thread_id=group_uid))
def test_changeGroupTitle(self): def test_changeThreadTitle(self):
self.assertTrue(client.changeGroupTitle('test_changeGroupTitle★', group_uid)) self.assertTrue(client.changeThreadTitle('test_changeThreadTitle★', thread_id=group_uid, thread_type=ThreadType.GROUP))
self.assertTrue(client.changeThreadTitle('test_changeThreadTitle★', thread_id=user_uid, thread_type=ThreadType.USER))
def test_changeNickname(self):
self.assertTrue(client.changeNickname('test_changeNicknameSelf★', client.uid, thread_id=user_uid, thread_type=ThreadType.USER))
self.assertTrue(client.changeNickname('test_changeNicknameOther★', user_uid, thread_id=user_uid, thread_type=ThreadType.USER))
self.assertTrue(client.changeNickname('test_changeNicknameSelf★', client.uid, thread_id=group_uid, thread_type=ThreadType.GROUP))
self.assertTrue(client.changeNickname('test_changeNicknameOther★', user_uid, thread_id=group_uid, thread_type=ThreadType.GROUP))
def test_changeThreadEmoji(self):
self.assertTrue(client.changeThreadEmoji('😀', group_uid))
self.assertTrue(client.changeThreadEmoji('😀', user_uid))
self.assertTrue(client.changeThreadEmoji('😆', group_uid))
self.assertTrue(client.changeThreadEmoji('😆', user_uid))
def test_changeThreadColor(self): def test_changeThreadColor(self):
self.assertTrue(client.changeThreadColor(ThreadColor.BRILLIANT_ROSE, group_uid)) self.assertTrue(client.changeThreadColor(ThreadColor.BRILLIANT_ROSE, group_uid))
@@ -125,13 +160,16 @@ class TestFbchat(unittest.TestCase):
self.assertTrue(client.changeThreadColor(ThreadColor.MESSENGER_BLUE, user_uid)) self.assertTrue(client.changeThreadColor(ThreadColor.MESSENGER_BLUE, user_uid))
def test_reactToMessage(self): def test_reactToMessage(self):
mid = client.sendMessage('react_to_message', user_uid, ThreadType.USER) mid = client.sendMessage('test_reactToMessage', user_uid, ThreadType.USER)
self.assertTrue(client.reactToMessage(mid, MessageReaction.LOVE))
mid = client.sendMessage('test_reactToMessage★', group_uid, ThreadType.GROUP)
self.assertTrue(client.reactToMessage(mid, MessageReaction.LOVE)) self.assertTrue(client.reactToMessage(mid, MessageReaction.LOVE))
def test_setTypingStatus(self): def test_setTypingStatus(self):
self.assertTrue(client.sendMessage('Hi', thread_id=user_uid, thread_type=ThreadType.USER))
self.assertTrue(client.setTypingStatus(TypingStatus.TYPING, thread_id=user_uid, thread_type=ThreadType.USER)) self.assertTrue(client.setTypingStatus(TypingStatus.TYPING, thread_id=user_uid, thread_type=ThreadType.USER))
self.assertTrue(client.setTypingStatus(TypingStatus.STOPPED, thread_id=user_uid, thread_type=ThreadType.USER))
self.assertTrue(client.setTypingStatus(TypingStatus.TYPING, thread_id=group_uid, thread_type=ThreadType.GROUP)) self.assertTrue(client.setTypingStatus(TypingStatus.TYPING, thread_id=group_uid, thread_type=ThreadType.GROUP))
self.assertTrue(client.setTypingStatus(TypingStatus.STOPPED, thread_id=user_uid, thread_type=ThreadType.USER))
self.assertTrue(client.setTypingStatus(TypingStatus.STOPPED, thread_id=group_uid, thread_type=ThreadType.GROUP)) self.assertTrue(client.setTypingStatus(TypingStatus.STOPPED, thread_id=group_uid, thread_type=ThreadType.GROUP))
@@ -144,7 +182,7 @@ def start_test(param_client, param_group_uid, param_user_uid, tests=[]):
group_uid = param_group_uid group_uid = param_group_uid
user_uid = param_user_uid user_uid = param_user_uid
tests = ['test_' + test for test in tests] tests = ['test_' + test if 'test_' != test[:5] else test for test in tests]
if len(tests) == 0: if len(tests) == 0:
suite = unittest.TestLoader().loadTestsFromTestCase(TestFbchat) suite = unittest.TestLoader().loadTestsFromTestCase(TestFbchat)
@@ -177,8 +215,7 @@ if __name__ == '__main__':
user_uid = input('Please enter a user thread id (To test kicking/adding functionality): ') user_uid = input('Please enter a user thread id (To test kicking/adding functionality): ')
print('Logging in...') print('Logging in...')
client = Client(email, password, logging_level=logging_level) client = CustomClient(email, password, logging_level=logging_level)
# Warning! Taking user input directly like this could be dangerous! Use only for testing purposes! # Warning! Taking user input directly like this could be dangerous! Use only for testing purposes!
start_test(client, group_uid, user_uid, argv[1:]) start_test(client, group_uid, user_uid, argv[1:])