Added support for deprecating items, and maybe support for python 2.7

- Changed `test_data.js` to `test_data.json`
- Added `deprecated` decorator
- Added `deprecation` function
- Readded old functions, and marked them as deprecated
- Changed parameters back to being type-in-specific (support for python
2.x)
- Deprecated `info_log` and `debug` init paramters
This commit is contained in:
Mads Marquart
2017-05-10 14:54:07 +02:00
parent 58c7e08d12
commit 0d75c09036
8 changed files with 245 additions and 86 deletions

1
.gitignore vendored
View File

@@ -23,4 +23,5 @@ develop-eggs
docs/_build/ docs/_build/
# Data for tests # Data for tests
test_data.json
tests.data tests.data

View File

@@ -15,7 +15,7 @@ from .client import *
__copyright__ = 'Copyright 2015 by Taehoon Kim' __copyright__ = 'Copyright 2015 by Taehoon Kim'
__version__ = '0.10.1' __version__ = '0.10.2'
__license__ = 'BSD' __license__ = 'BSD'
__author__ = 'Taehoon Kim; Moreels Pieter-Jan' __author__ = 'Taehoon Kim; Moreels Pieter-Jan'
__email__ = 'carpedm20@gmail.com' __email__ = 'carpedm20@gmail.com'

View File

@@ -14,14 +14,12 @@
import requests import requests
import logging import logging
from uuid import uuid1 from uuid import uuid1
import warnings
from random import choice from random import choice
from datetime import datetime from datetime import datetime
from bs4 import BeautifulSoup as bs from bs4 import BeautifulSoup as bs
from mimetypes import guess_type from mimetypes import guess_type
from .utils import * from .utils import *
from .models import * from .models import *
from .stickers import *
import time import time
import sys import sys
@@ -58,6 +56,9 @@ facebookEncoding = 'UTF-8'
# Log settings # Log settings
log = logging.getLogger("client") log = logging.getLogger("client")
log.setLevel(logging.DEBUG) log.setLevel(logging.DEBUG)
# Creates the console handler
handler = logging.StreamHandler()
log.addHandler(handler)
class Client(object): class Client(object):
@@ -67,16 +68,17 @@ class Client(object):
documentation for the API. documentation for the API.
""" """
def __init__(self, email, password, debug=True, info_log=True, user_agent=None, max_retries=5, session_cookies=None): def __init__(self, email, password, debug=False, info_log=False, user_agent=None, max_retries=5, session_cookies=None, logging_level=logging.INFO):
"""A client for the Facebook Chat (Messenger). """A client for the Facebook Chat (Messenger).
:param email: Facebook `email` or `id` or `phone number` :param email: Facebook `email` or `id` or `phone number`
:param password: Facebook account password :param password: Facebook account password
:param debug: Configures the logger to `debug` logging_level :param debug: Configures the logger to `debug` logging_level (deprecated)
:param info_log: Configures the logger to `info` logging_level :param info_log: Configures the logger to `info` logging_level (deprecated)
:param user_agent: Custom user agent to use when sending requests. If `None`, user agent will be chosen from a premade list (see utils.py) :param user_agent: Custom user agent to use when sending requests. If `None`, user agent will be chosen from a premade list (see utils.py)
:param max_retries: Maximum number of times to retry login :param max_retries: Maximum number of times to retry login
:param session_cookies: Cookie dict from a previous session (Will default to login if these are invalid) :param session_cookies: Cookie dict from a previous session (Will default to login if these are invalid)
:param logging_level: Configures the logger to logging_level
""" """
self.sticky, self.pool = (None, None) self.sticky, self.pool = (None, None)
@@ -86,9 +88,8 @@ class Client(object):
self.payloadDefault = {} self.payloadDefault = {}
self.client = 'mercury' self.client = 'mercury'
self.listening = False self.listening = False
self.is_def_thread_set = False self.default_thread_id = None
self.def_thread_id = None self.default_thread_type = None
self.def_thread_type = None
self.threads = [] self.threads = []
if not user_agent: if not user_agent:
@@ -104,21 +105,39 @@ class Client(object):
# Configure the logger differently based on the 'debug' and 'info_log' parameters # Configure the logger differently based on the 'debug' and 'info_log' parameters
if debug: if debug:
deprecation('Client(debug)', deprecated_in='0.6.0', details='Use Client(logging_level) instead')
logging_level = logging.DEBUG logging_level = logging.DEBUG
elif info_log: elif info_log:
deprecation('Client(info_log)', deprecated_in='0.6.0', details='Use Client(logging_level) instead')
logging_level = logging.INFO logging_level = logging.INFO
else:
logging_level = logging.WARNING
# Creates the console handler
handler = logging.StreamHandler()
handler.setLevel(logging_level) handler.setLevel(logging_level)
log.addHandler(handler)
# If session cookies aren't set, not properly loaded or gives us an invalid session, then do the login # If session cookies aren't set, not properly loaded or gives us an invalid session, then do the login
if not session_cookies or not self.setSession(session_cookies) or not self.is_logged_in(): if not session_cookies or not self.setSession(session_cookies) or not self.is_logged_in():
self.login(email, password, max_retries) self.login(email, password, max_retries)
@deprecated(deprecated_in='0.6.0', details='Use log.<level> instead')
def _console(self, msg):
"""Assumes an INFO level and log it.
This method shouldn't be used anymore.
Use the log itself:
>>> import logging
>>> from fbchat.client import log
>>> log.setLevel(logging.DEBUG)
You can do the same thing by adding the 'debug' argument:
>>> from fbchat import Client
>>> client = Client("...", "...", debug=True)
"""
log.debug(msg)
def _setttstamp(self):
for i in self.fb_dtsg:
self.ttstamp += str(ord(i))
self.ttstamp += '2'
def _generatePayload(self, query): def _generatePayload(self, query):
"""Adds the following defaults to the payload: """Adds the following defaults to the payload:
__rev, __user, __a, ttstamp, fb_dtsg, __req __rev, __user, __a, ttstamp, fb_dtsg, __req
@@ -154,7 +173,7 @@ class Client(object):
self.payloadDefault = {} self.payloadDefault = {}
self.client_id = hex(int(random()*2147483648))[2:] self.client_id = hex(int(random()*2147483648))[2:]
self.start_time = now() self.start_time = now()
self.uid = str(self._session.cookies['c_user']) self.uid = int(self._session.cookies['c_user'])
self.user_channel = "p_" + str(self.uid) self.user_channel = "p_" + str(self.uid)
self.ttstamp = '' self.ttstamp = ''
@@ -294,7 +313,8 @@ class Client(object):
return True return True
def login(self, email, password, max_retries=5): def login(self, email, password, max_retries=5):
self.onLoggingIn(email=email) # Logging in
log.info("Logging in {}...".format(email))
if not (email and password): if not (email and password):
raise Exception("Email and password not set.") raise Exception("Email and password not set.")
@@ -308,7 +328,7 @@ class Client(object):
time.sleep(1) time.sleep(1)
continue continue
else: else:
self.onLoggedIn(email=email) log.info("Login of {} successful.".format(email))
break break
else: else:
raise Exception("Login failed. Check email/password.") raise Exception("Login failed. Check email/password.")
@@ -327,16 +347,19 @@ class Client(object):
self.req_counter = 1 self.req_counter = 1
self.seq = "0" self.seq = "0"
return r return r
@deprecated(deprecated_in='0.10.2', details='Use setDefaultThread instead')
def setDefaultRecipient(self, recipient_id, is_user=True):
self.setDefaultThread(recipient_id, thread_type=isUserToThreadType(is_user))
def setDefaultThreadId(self, thread_id=str, thread_type=ThreadType): def setDefaultThread(self, thread_id=None, thread_type=ThreadType.USER):
"""Sets default recipient to send messages and images to. """Sets default thread to send messages and images to.
:param thread_id: user/group ID to default to :param thread_id: user/group ID to default to
:param thread_type: type of thread_id :param thread_type: type of thread_id
""" """
self.def_thread_id = thread_id self.default_thread_id = thread_id
self.def_thread_type = thread_type self.default_thread_type = thread_type
self.is_def_thread_set = True
def _adapt_user_in_chat_to_user_model(self, user_in_chat): def _adapt_user_in_chat_to_user_model(self, user_in_chat):
""" Adapts user info from chat to User model acceptable initial dict """ Adapts user info from chat to User model acceptable initial dict
@@ -424,7 +447,7 @@ class Client(object):
SEND METHODS SEND METHODS
""" """
def _send(self, thread_id=None, message=None, thread_type=None, emoji_size=None, image_id=None, add_user_ids=None, new_title=None): def _send(self, thread_id=None, message=None, thread_type=ThreadType.USER, emoji_size=None, image_id=None, add_user_ids=None, new_title=None):
"""Send a message with given thread id """Send a message with given thread id
:param thread_id: the user id or thread id that you want to send a message to :param thread_id: the user id or thread id that you want to send a message to
@@ -436,11 +459,12 @@ class Client(object):
:return: a list of message ids of the sent message(s) :return: a list of message ids of the sent message(s)
""" """
if thread_id is None and self.is_def_thread_set: if thread_id is None:
thread_id = self.def_thread_id if self.default_thread_id is not None:
thread_type = self.def_thread_type thread_id = self.default_thread_id
elif thread_id is None and not self.is_def_thread_set: thread_type = self.default_thread_type
raise ValueError('Default Thread ID is not set.') else:
raise ValueError('Thread ID is not set.')
messageAndOTID = generateOfflineThreadingID() messageAndOTID = generateOfflineThreadingID()
timestamp = now() timestamp = now()
@@ -538,7 +562,11 @@ class Client(object):
log.debug("With data {}".format(data)) log.debug("With data {}".format(data))
return message_ids return message_ids
def sendMessage(self, message: str, thread_id: str = None, thread_type: ThreadType = None): @deprecated(deprecated_in='0.10.2', details='Use specific functions (eg. sendMessage()) instead')
def send(self, recipient_id=None, message=None, is_user=True, like=None, image_id=None, add_user_ids=None):
return self._send(thread_id=recipient_id, message=message, thread_type=isUserToThreadType(is_user), emoji_size=LIKES[like], image_id=image_id, add_user_ids=add_user_ids)
def sendMessage(self, message, thread_id=None, thread_type=ThreadType.USER):
""" """
Sends a message to given (or default, if not) thread with an additional image. Sends a message to given (or default, if not) thread with an additional image.
:param message: message to send :param message: message to send
@@ -546,19 +574,20 @@ class Client(object):
:param thread_type: specify whether thread_id is user or group chat :param thread_type: specify whether thread_id is user or group chat
:return: a list of message ids of the sent message(s) :return: a list of message ids of the sent message(s)
""" """
return self._send(thread_id, message, thread_type, None, None, None, None) return self._send(thread_id=thread_id, message=message, thread_type=thread_type)
def sendEmoji(self, emoji_size: EmojiSize, thread_id: str = None, thread_type: ThreadType = None): def sendEmoji(self, thread_id, size=Size.MEDIUM, emoji=None, thread_type=ThreadType.USER):
""" """
Sends an emoji to given (or default, if not) thread. Sends an emoji to given (or default, if not) thread.
:param emoji_size: size of emoji to send :param size: size of emoji to send
:param thread_id: user/group chat ID :param thread_id: user/group chat ID
:param emoji: WIP
:param thread_type: specify whether thread_id is user or group chat :param thread_type: specify whether thread_id is user or group chat
:return: a list of message ids of the sent message(s) :return: a list of message ids of the sent message(s)
""" """
return self._send(thread_id, None, thread_type, emoji_size, None, None, None) return self._send(thread_id=thread_id, thread_type=thread_type, emoji_size=size)
def sendRemoteImage(self, image_url: str, message: str = None, thread_id: str = None, thread_type: ThreadType = None): def sendRemoteImage(self, image_url, message=None, thread_id=None, thread_type=ThreadType.USER, recipient_id=None, is_user=None, image=None):
""" """
Sends an image from given URL to given (or default, if not) thread. Sends an image from given URL to given (or default, if not) thread.
:param image_url: URL of an image to upload and send :param image_url: URL of an image to upload and send
@@ -567,13 +596,22 @@ class Client(object):
:param thread_type: specify whether thread_id is user or group chat :param thread_type: specify whether thread_id is user or group chat
:return: a list of message ids of the sent message(s) :return: a list of message ids of the sent message(s)
""" """
if recipient_id is not None:
deprecation('sendRemoteImage(recipient_id)', deprecated_in='0.10.2', details='Use sendRemoteImage(thread_id) instead')
thread_id = recipient_id
if is_user is not None:
deprecation('sendRemoteImage(is_user)', deprecated_in='0.10.2', details='Use sendRemoteImage(thread_type) instead')
thread_type = isUserToThreadType(is_user)
if image is not None:
deprecation('sendRemoteImage(image)', deprecated_in='0.10.2', details='Use sendRemoteImage(image_url) instead')
image_url = image
mimetype = guess_type(image_url)[0] mimetype = guess_type(image_url)[0]
remote_image = requests.get(image_url).content remote_image = requests.get(image_url).content
image_id = self._uploadImage({'file': (image_url, remote_image, mimetype)}) image_id = self._uploadImage({'file': (image_url, remote_image, mimetype)})
return self._send(thread_id, message, thread_type, None, image_id, None, None) return self._send(thread_id=thread_id, message=message, thread_type=thread_type, image_id=image_id)
# Doesn't upload properly # Doesn't upload properly
def sendLocalImage(self, image_path: str, message: str = None, thread_id: str = None, thread_type: ThreadType = None): def sendLocalImage(self, image_path, message=None, thread_id=None, thread_type=ThreadType.USER, recipient_id=None, is_user=None, image=None):
""" """
Sends an image from given URL to given (or default, if not) thread. Sends an image from given URL to given (or default, if not) thread.
:param image_path: path of an image to upload and send :param image_path: path of an image to upload and send
@@ -582,20 +620,29 @@ class Client(object):
:param thread_type: specify whether thread_id is user or group chat :param thread_type: specify whether thread_id is user or group chat
:return: a list of message ids of the sent message(s) :return: a list of message ids of the sent message(s)
""" """
if recipient_id is not None:
deprecation('sendRemoteImage(recipient_id)', deprecated_in='0.10.2', details='Use sendLocalImage(thread_id) instead')
thread_id = recipient_id
if is_user is not None:
deprecation('sendRemoteImage(is_user)', deprecated_in='0.10.2', details='Use sendLocalImage(thread_type) instead')
thread_type = isUserToThreadType(is_user)
if image is not None:
deprecation('sendRemoteImage(image)', deprecated_in='0.10.2', details='Use sendLocalImage(image_path) instead')
image_path = image
mimetype = guess_type(image_path)[0] mimetype = guess_type(image_path)[0]
image_id = self._uploadImage({'file': (image_path, open(image_path, 'rb'), mimetype)}) image_id = self._uploadImage({'file': (image_path, open(image_path, 'rb'), mimetype)})
return self._send(thread_id, message, thread_type, None, image_id, None, None) return self._send(thread_id=thread_id, message=message, thread_type=thread_type, image_id=image_id)
def addUsersToChat(self, user_list: list, thread_id: str = None): def addUsersToChat(self, user_ids, thread_id=None):
""" """
Adds users to given (or default, if not) thread. Adds users to given (or default, if not) thread.
:param user_list: list of users to add :param user_ids: list of user ids to add
:param thread_id: group chat ID :param thread_id: group chat ID
:return: a list of message ids of the sent message(s) :return: a list of message ids of the sent message(s)
""" """
return self._send(thread_id, None, ThreadType.GROUP, None, None, user_list, None) return self._send(thread_id=thread_id, thread_type=ThreadType.GROUP, add_user_ids=users)
def removeUserFromChat(self, user_id: str, thread_id: str = None): def removeUserFromChat(self, user_id, thread_id=None):
""" """
Adds users to given (or default, if not) thread. Adds users to given (or default, if not) thread.
:param user_id: user ID to remove :param user_id: user ID to remove
@@ -617,18 +664,28 @@ class Client(object):
return r.ok return r.ok
def changeThreadTitle(self, new_title: str, thread_id: str = None): @deprecated(deprecated_in='0.10.2', details='Use removeUserFromChat() instead')
def add_users_to_chat(self, threadID, userID):
if not isinstance(userID, list):
userID = [userID]
return self.addUsersToChat(userID, thread_id=threadID)
@deprecated(deprecated_in='0.10.2', details='Use removeUserFromChat() instead')
def remove_user_from_chat(self, threadID, userID):
return self.removeUserFromChat(userID, thread_id=threadID)
@deprecated(deprecated_in='0.10.2', details='Use changeGroupTitle() instead')
def changeThreadTitle(self, threadID, newTitle):
return self.changeGroupTitle(newTitle, thread_id=threadID)
def changeGroupTitle(self, title, thread_id=None):
""" """
Change title of a group conversation. Change title of a group conversation.
:param new_title: new group chat title :param title: new group chat title
:param thread_id: group chat ID :param thread_id: group chat ID
:return: a list of message ids of the sent message(s) :return: a list of message ids of the sent message(s)
""" """
if thread_id is None and self.def_thread_type == ThreadType.GROUP: return self._send(thread_id=thread_id, thread_type=ThreadType.GROUP, new_title=title)
thread_id = self.def_thread_id
elif thread_id is None:
raise ValueError('Default Thread ID is not set.')
return self._send(thread_id, None, ThreadType.GROUP, None, None, None, new_title)
""" """
END SEND METHODS END SEND METHODS
@@ -647,7 +704,7 @@ class Client(object):
# Strip the start and parse out the returned image_id # Strip the start and parse out the returned image_id
return json.loads(response_content[9:])['payload']['metadata'][0]['image_id'] return json.loads(response_content[9:])['payload']['metadata'][0]['image_id']
def getThreadInfo(self, last_n=20, thread_id: str = None, thread_type: ThreadType = None): def getThreadInfo(self, last_n=20, thread_id=None, thread_type=ThreadType.USER):
"""Get the info of one Thread """Get the info of one Thread
:param last_n: number of retrieved messages from start (default 20) :param last_n: number of retrieved messages from start (default 20)
@@ -969,3 +1026,65 @@ class Client(object):
if len(full_data)==1: if len(full_data)==1:
full_data=full_data[0] full_data=full_data[0]
return full_data return full_data
def on_message_new(self, mid, author_id, message, metadata, recipient_id, thread_type):
"""subclass Client and override this method to add custom behavior on event
This version of on_message recieves recipient_id and thread_type.
For backwards compatability, this data is sent directly to the old on_message.
"""
self.on_message(mid, author_id, None, message, metadata)
@deprecated(deprecated_in='0.7.0', details='Use on_message_new() instead')
def on_message(self, mid, author_id, author_name, message, metadata):
"""subclass Client and override this method to add custom behavior on event"""
self.markAsDelivered(author_id, mid)
self.markAsRead(author_id)
log.info("%s said: %s" % (author_name, message))
def on_friend_request(self, from_id):
"""subclass Client and override this method to add custom behavior on event"""
log.info("Friend request from %s." % from_id)
def on_typing(self, author_id):
"""subclass Client and override this method to add custom behavior on event"""
pass
def on_read(self, author, reader, time):
"""subclass Client and override this method to add custom behavior on event"""
pass
def on_people_added(self, user_ids, actor_id, thread_id):
"""subclass Client and override this method to add custom behavior on event"""
log.info("User(s) {} was added to {} by {}".format(repr(user_ids), thread_id, actor_id))
def on_person_removed(self, user_id, actor_id, thread_id):
"""subclass Client and override this method to add custom behavior on event"""
log.info("User {} was removed from {} by {}".format(user_id, thread_id, actor_id))
def on_inbox(self, viewer, unseen, unread, other_unseen, other_unread, timestamp):
"""subclass Client and override this method to add custom behavior on event"""
pass
def on_message_error(self, exception, message):
"""subclass Client and override this method to add custom behavior on event"""
log.warning("Exception:\n{}".format(exception))
def on_qprimer(self, timestamp):
pass
def on_unknown_type(self, m):
"""subclass Client and override this method to add custom behavior on event"""
log.debug("Unknown type {}".format(m))

View File

@@ -1,5 +1,6 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import sys import sys
from enum import Enum
class Base(): class Base():
def __repr__(self): def __repr__(self):
@@ -37,7 +38,25 @@ class TypingStatus(Enum):
DELETED = 0 DELETED = 0
TYPING = 1 TYPING = 1
class EmojiSize(Enum):
# WIP
class StickerSize(Enum):
LARGE = '369239383222810' LARGE = '369239383222810'
MEDIUM = '369239343222814' MEDIUM = '369239343222814'
SMALL = '369239263222822' SMALL = '369239263222822'
#class Size(Enum):
# LARGE = 'large'
# MEDIUM = 'medium'
# SMALL = 'small'
Size = StickerSize
LIKES = {
'l': Size.LARGE,
'm': Size.MEDIUM,
's': Size.SMALL
}
LIKES['large'] = LIKES['l']
LIKES['medium'] =LIKES['m']
LIKES['small'] = LIKES['s']

View File

@@ -1,8 +0,0 @@
LIKES={
'l': '369239383222810',
'm': '369239343222814',
's': '369239263222822'
}
LIKES['large'] = LIKES['l']
LIKES['medium'] =LIKES['m']
LIKES['small'] = LIKES['s']

View File

@@ -2,6 +2,7 @@ import re
import json import json
from time import time from time import time
from random import random from random import random
import warnings
USER_AGENTS = [ USER_AGENTS = [
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.90 Safari/537.36", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.90 Safari/537.36",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/601.1.10 (KHTML, like Gecko) Version/8.0.5 Safari/601.1.10", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/601.1.10 (KHTML, like Gecko) Version/8.0.5 Safari/601.1.10",
@@ -62,3 +63,30 @@ def generateOfflineThreadingID() :
msgs = bin(ret) + string msgs = bin(ret) + string
return str(int(msgs,2)) return str(int(msgs,2))
def isUserToThreadType(is_user):
return ThreadType.USER if is_user else ThreadType.GROUP
def deprecation(name, deprecated_in=None, details='', stacklevel=3):
"""This is a function which should be used to mark parameters as deprecated.
It will result in a warning being emmitted when the parameter is used.
"""
warning = "{} is deprecated".format(name)
if deprecated_in:
warning += ' in v. {}'.format(deprecated_in)
if details:
warning += '. {}'.format(details)
warnings.simplefilter('always', DeprecationWarning)
warnings.warn(warning, category=DeprecationWarning, stacklevel=stacklevel)
warnings.simplefilter('default', DeprecationWarning)
def deprecated(deprecated_in=None, details=''):
"""This is a decorator which can be used to mark functions as deprecated.
It will result in a warning being emmitted when the decorated function is used.
"""
def wrap(func, *args, **kwargs):
def wrapped_func(*args, **kwargs):
deprecation(func.__qualname__, deprecated_in, details, stacklevel=2)
return func(*args, **kwargs)
return wrapped_func
return wrap

View File

@@ -1,6 +0,0 @@
{
"email": "",
"password": "",
"user_thread_id": "",
"group_thread_id": ""
}

View File

@@ -10,21 +10,27 @@ import unittest
import sys import sys
from os import path from os import path
# Disable logging #Setup logging
logging.basicConfig(level=100) logging.basicConfig(level=logging.INFO)
fbchat.log.setLevel(100)
""" """
Tests for fbchat Tests for fbchat
~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~
To use these tests, put: To use these tests, make a json file called test_data.json, put this example in it, and fill in the gaps:
- email {
- password "email": "example@email.com",
- a group_uid "password": "example_password",
- a user_uid (the user will be kicked from the group and then added again) `test_data.js`, "group_thread_id": 0,
or type them manually in the terminal prompts "user_thread_id": 0
}
or type this information manually in the terminal prompts.
- email: Your (or a test user's) email / phone number
- password: Your (or a test user's) password
- group_thread_id: A test group that will be used to test group functionality
- user_thread_id: A person that will be used to test kick/add functionality (This user should be in the group)
Please remember to test both python v. 2.7 and python v. 3.6! Please remember to test both python v. 2.7 and python v. 3.6!
@@ -101,8 +107,8 @@ class TestFbchat(unittest.TestCase):
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 # 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):
client.sendMessage('test_user_getThreadInfo', user_uid, ThreadType.USER) client.sendMessage('test_user_getThreadInfo', user_uid, ThreadType.USER)
@@ -117,12 +123,12 @@ class TestFbchat(unittest.TestCase):
self.assertEquals(info[0].author, 'fbid:' + client.uid) self.assertEquals(info[0].author, 'fbid:' + client.uid)
self.assertEquals(info[0].body, 'test_group_getThreadInfo') self.assertEquals(info[0].body, 'test_group_getThreadInfo')
# def test_markAs(self): def test_markAs(self):
# # To be implemented (requires some form of manual watching) # To be implemented (requires some form of manual watching)
# pass pass
# def test_listen(self): def test_listen(self):
# client.doOneListen() client.doOneListen()
def test_getUserInfo(self): def test_getUserInfo(self):
info = client.getUserInfo(4) info = client.getUserInfo(4)
@@ -165,15 +171,15 @@ if __name__ == 'tests':
try: try:
with open(path.join(path.dirname(__file__), 'test_data.js'), 'r') as f: with open(path.join(path.dirname(__file__), 'test_data.js'), 'r') as f:
json = json.load(f) json = json.load(f)
email = json["email"] email = json['email']
password = json["password"] password = json['password']
user_uid = json["user_thread_id"] user_uid = json['user_thread_id']
group_uid = json["group_thread_id"] group_uid = json['group_thread_id']
except (IOError, IndexError) as e: except (IOError, IndexError) as e:
email = input('Email: ') email = input('Email: ')
password = getpass.getpass() password = getpass.getpass()
group_uid = input('Please enter a group uid (To test group functionality): ') group_uid = input('Please enter a group thread id (To test group functionality): ')
user_uid = input('Please enter a user uid (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 = fbchat.Client(email, password) client = fbchat.Client(email, password)