fix inconsistencies, remove some deprecated and unused things

This commit is contained in:
Dainius
2017-05-01 15:57:26 +03:00
parent 1475d8c4db
commit 3e327747bc

View File

@@ -12,11 +12,10 @@
"""
import requests
import json
import logging
from uuid import uuid1
import warnings
from random import random, choice
from random import choice
from datetime import datetime
from bs4 import BeautifulSoup as bs
from mimetypes import guess_type
@@ -52,15 +51,15 @@ facebookEncoding = 'UTF-8'
# Log settings
log = logging.getLogger("client")
class Client(object):
"""A client for the Facebook Chat (Messenger).
See http://github.com/carpedm20/fbchat for complete
documentation for the API.
"""
def __init__(self, email, password, debug=True, user_agent=None , max_retries=5, do_login=True):
def __init__(self, email, password, debug=True, user_agent=None, max_retries=5, do_login=True):
"""A client for the Facebook Chat (Messenger).
:param email: Facebook `email` or `id` or `phone number`
@@ -68,7 +67,6 @@ class Client(object):
import fbchat
chat = fbchat.Client(email, password)
"""
if do_login and not (email and password):
@@ -119,7 +117,7 @@ class Client(object):
handler.setLevel(logging_level)
log.addHandler(handler)
log.setLevel(logging.DEBUG)
if do_login:
self.login(email, password, max_retries)
@@ -131,13 +129,12 @@ class Client(object):
This method shouldn't be used anymore.
Use the log itself:
>>> import logging
>>> from fbchat.client import Client, log
>>> 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)
"""
warnings.warn(
"Client._console shouldn't be used. Use 'log.<level>'",
@@ -150,10 +147,9 @@ class Client(object):
self.ttstamp += '2'
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
'''
"""
payload = self.payloadDefault.copy()
if query:
payload.update(query)
@@ -230,7 +226,7 @@ class Client(object):
data['login'] = 'Log In'
r = self._cleanPost(LoginURL, data)
# Usually, 'Checkpoint' will refer to 2FA
if 'checkpoint' in r.url and 'Enter Security Code to Continue' in r.text:
r = self._2FA(r)
@@ -244,11 +240,11 @@ class Client(object):
return True
else:
return False
def _2FA(self,r):
soup = bs(r.text, "lxml")
data = dict()
s = raw_input('Please enter your 2FA code --> ')
s = input('Please enter your 2FA code --> ')
data['approvals_code'] = s
data['fb_dtsg'] = soup.find("input", {'name':'fb_dtsg'})['value']
data['nh'] = soup.find("input", {'name':'nh'})['value']
@@ -259,48 +255,48 @@ class Client(object):
if 'home' in r.url:
return r
del(data['approvals_code'])
del(data['submit[Submit Code]'])
del(data['codes_submitted'])
data['name_action_selected'] = 'save_device'
data['submit[Continue]'] = 'Continue'
log.info('Saving browser') #At this stage, we have dtsg, nh, name_action_selected, submit[Continue]
log.info('Saving browser') # At this stage, we have dtsg, nh, name_action_selected, submit[Continue]
r = self._cleanPost(CheckpointURL, data)
if 'home' in r.url:
return r
del(data['name_action_selected'])
log.info('Starting Facebook checkup flow') #At this stage, we have dtsg, nh, submit[Continue]
log.info('Starting Facebook checkup flow') # At this stage, we have dtsg, nh, submit[Continue]
r = self._cleanPost(CheckpointURL, data)
if 'home' in r.url:
return r
del(data['submit[Continue]'])
data['submit[This was me]'] = 'This Was Me'
log.info('Verifying login attempt') #At this stage, we have dtsg, nh, submit[This was me]
log.info('Verifying login attempt') # At this stage, we have dtsg, nh, submit[This was me]
r = self._cleanPost(CheckpointURL, data)
if 'home' in r.url:
return r
del(data['submit[This was me]'])
data['submit[Continue]'] = 'Continue'
data['name_action_selected'] = 'save_device'
log.info('Saving device again') #At this stage, we have dtsg, nh, submit[Continue], name_action_selected
log.info('Saving device again') # At this stage, we have dtsg, nh, submit[Continue], name_action_selected
r = self._cleanPost(CheckpointURL, data)
return r
def saveSession(self, sessionfile):
"""Dumps the session cookies to (sessionfile).
WILL OVERWRITE ANY EXISTING FILE
:param sessionfile: location of saved session file
"""
log.info('Saving session')
with open(sessionfile, 'w') as f:
# Grab cookies from current session, and save them as JSON
@@ -308,10 +304,10 @@ class Client(object):
def loadSession(self, sessionfile):
"""Loads session cookies from (sessionfile)
:param sessionfile: location of saved session file
"""
log.info('Loading session')
with open(sessionfile, 'r') as f:
try:
@@ -328,11 +324,11 @@ class Client(object):
def login(self, email, password, max_retries=5):
# Logging in
log.info("Logging in...")
self.email = email
self.password = password
for i in range(1,max_retries+1):
for i in range(1, max_retries+1):
if not self._login():
log.warning("Attempt #{} failed{}".format(i,{True:', retrying'}.get(i<5,'')))
time.sleep(1)
@@ -356,16 +352,12 @@ class Client(object):
self.seq = "0"
return r
def listen(self):
pass
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
:param user_in_chat: user info from chat
'dir': None,
'mThumbSrcSmall': None,
'is_friend': False,
@@ -382,9 +374,7 @@ class Client(object):
'uri': 'https://www.facebook.com/profile.php?id=100014812758264',
'id': '100014812758264',
'gender': 2
'''
"""
return {
'type': 'user',
@@ -457,7 +447,7 @@ class Client(object):
:param add_user_ids: a list of user ids to add to a chat
"""
messageAndOTID=generateOfflineThreadingID()
messageAndOTID = generateOfflineThreadingID()
timestamp = now()
date = datetime.now()
data = {
@@ -488,12 +478,12 @@ class Client(object):
'manual_retry_cnt' : '0',
'signatureID' : getSignatureID()
}
if message_type.lower() == 'group':
data["thread_fbid"] = recipient_id
data["thread_fbid"] = recipient_id
else:
data["other_user_fbid"] = recipient_id
if add_user_ids:
data['action_type'] = 'ma-type:log-message'
# It's possible to add multiple users
@@ -503,7 +493,7 @@ class Client(object):
else:
data['action_type'] = 'ma-type:user-generated-message'
data['body'] = message
data['has_attachment'] = image_id != None
data['has_attachment'] = image_id is not None
data['specific_to_list[0]'] = 'fbid:' + str(recipient_id)
data['specific_to_list[1]'] = 'fbid:' + str(self.uid)
@@ -519,10 +509,10 @@ class Client(object):
data["sticker_id"] = sticker
r = self._post(SendURL, data)
if not r.ok:
return False
if isinstance(r._content, str) is False:
r._content = r._content.decode(facebookEncoding)
j = get_json(r._content)
@@ -570,7 +560,7 @@ class Client(object):
r._content = r._content.decode(facebookEncoding)
# Strip the start and parse out the returned image_id
return json.loads(r._content[9:])['payload']['metadata'][0]['image_id']
def getThreadInfo(self, userID, last_n=20, start=None, thread_type='user'):
"""Get the info of one Thread
@@ -579,7 +569,7 @@ class Client(object):
:param start: (optional) the start index of a thread (Deprecated)
:param thread_type: (optional) change from 'user' for group threads
"""
assert last_n > 0, 'length must be positive integer, got %d' % last_n
assert start is None, '`start` is deprecated, always 0 offset querry is returned'
data = {}
@@ -613,11 +603,11 @@ class Client(object):
"""Get thread list of your facebook account.
:param start: the start index of a thread
:param end: (optional) the last index of a thread
:param length: (optional) the length of a thread
"""
assert length < 21, '`length` is deprecated, max. last 20 threads are returned'
timestamp = now()
date = datetime.now()
data = {
@@ -659,7 +649,7 @@ class Client(object):
'client': 'mercury_sync',
'folders[0]': 'inbox',
'last_action_timestamp': now() - 60*1000
#'last_action_timestamp': 0
# 'last_action_timestamp': 0
}
r = self._post(ThreadSyncURL, form)
@@ -722,10 +712,9 @@ class Client(object):
def _getSticky(self):
'''
Call pull api to get sticky and pool parameter,
"""Call pull api to get sticky and pool parameter,
newer api needs these parameter to work.
'''
"""
data = {
"msgs_recv": 0,
@@ -745,9 +734,7 @@ class Client(object):
def _pullMessage(self, sticky, pool):
'''
Call pull api with seq value to get message data.
'''
"""Call pull api with seq value to get message data."""
data = {
"msgs_recv": 0,
@@ -765,10 +752,9 @@ class Client(object):
def _parseMessage(self, content):
'''
Get message and author name from content.
"""Get message and author name from content.
May contains multiple messages in the content.
'''
"""
if 'ms' not in content: return
@@ -878,14 +864,14 @@ class Client(object):
def fbidStrip(_fbid):
# Stripping of `fbid:` from author_id
if type(_fbid) == int:
if type(_fbid) == int:
return _fbid
if type(_fbid) == str and 'fbid:' in _fbid:
return int(_fbid[5:])
user_ids = [fbidStrip(uid) for uid in user_ids]
data = {"ids[{}]".format(i):uid for i,uid in enumerate(user_ids)}
r = self._post(UserInfoURL, data)
@@ -898,39 +884,39 @@ class Client(object):
def remove_user_from_chat(self, threadID, userID):
"""Remove user (userID) from group chat (threadID)
:param threadID: group chat id
:param userID: user id to remove from chat
"""
data = {
"uid" : userID,
"tid" : threadID
}
r = self._post(RemoveUserURL, data)
self._console(r)
self._console(data)
log.info(r)
log.info(data)
return r.ok
def add_users_to_chat(self, threadID, userID):
"""Add user (userID) to group chat (threadID)
:param threadID: group chat id
:param userID: user id to add to chat
"""
return self.send(threadID, message_type='group', add_user_ids=[userID])
def changeThreadTitle(self, threadID, newTitle):
"""Change title of a group conversation
:param threadID: group chat id
:param newTitle: new group chat title
"""
messageAndOTID = generateOfflineThreadingID()
timestamp = now()
date = datetime.now()
@@ -964,76 +950,61 @@ class Client(object):
r = self._post(SendURL, data)
self._console(r)
self._console(data)
log.info(r)
log.info(data)
return r.ok
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.
'''
"""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)
def on_message(self, mid, author_id, author_name, message, metadata):
'''
subclass Client and override this method to add custom behavior on event
'''
"""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)
"""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
'''
"""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
'''
"""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
'''
"""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
'''
"""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
'''
"""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
'''
"""subclass Client and override this method to add custom behavior on event"""
log.warning("Exception:\n{}".format(exception))