Cleaned up login process, changed saveSession and loadSession and added is_logged_in

This commit is contained in:
Mads Marquart
2017-05-05 14:24:03 +02:00
parent 05ca457946
commit a280555536
2 changed files with 58 additions and 57 deletions

View File

@@ -66,42 +66,27 @@ 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, do_login=True): def __init__(self, email, password, debug=True, info_log=True, user_agent=None, max_retries=5, session_cookies=None):
"""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
import fbchat :param info_log: Configures the logger to `info` logging_level
chat = fbchat.Client(email, password) :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 session_cookies: Cookie dict from a previous session (Will default to login if these are invalid)
""" """
if do_login and not (email and password):
raise Exception("Email and password not found.")
self.is_def_recipient_set = False self.is_def_recipient_set = False
self.debug = debug
self.sticky, self.pool = (None, None) self.sticky, self.pool = (None, None)
self._session = requests.session() self._session = requests.session()
self.req_counter = 1 self.req_counter = 1
self.seq = "0" self.seq = "0"
self.payloadDefault={} self.payloadDefault = {}
self.client = 'mercury' self.client = 'mercury'
self.listening = False self.listening = False
self.GENDERS = { self.threads = []
0: 'unknown',
1: 'female_singular',
2: 'male_singular',
3: 'female_singular_guess',
4: 'male_singular_guess',
5: 'mixed',
6: 'neuter_singular',
7: 'unknown_singular',
8: 'female_plural',
9: 'male_plural',
10: 'neuter_plural',
11: 'unknown_plural',
}
if not user_agent: if not user_agent:
user_agent = choice(USER_AGENTS) user_agent = choice(USER_AGENTS)
@@ -114,7 +99,7 @@ class Client(object):
'Connection' : 'keep-alive', 'Connection' : 'keep-alive',
} }
# Configure the logger differently based on the 'debug' parameter # Configure the logger differently based on the 'debug' and 'info_log' parameters
if debug: if debug:
logging_level = logging.DEBUG logging_level = logging.DEBUG
elif info_log: elif info_log:
@@ -128,10 +113,12 @@ class Client(object):
log.addHandler(handler) log.addHandler(handler)
log.setLevel(logging.DEBUG) log.setLevel(logging.DEBUG)
if do_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():
self.login(email, password, max_retries) self.login(email, password, max_retries)
self.threads = [] def _init_logging(self):
def _console(self, msg): def _console(self, msg):
"""Assumes an INFO level and log it. """Assumes an INFO level and log it.
@@ -169,11 +156,11 @@ class Client(object):
return payload return payload
def _get(self, url, query=None, timeout=30): def _get(self, url, query=None, timeout=30):
payload=self._generatePayload(query) payload = self._generatePayload(query)
return self._session.get(url, headers=self._header, params=payload, timeout=timeout) return self._session.get(url, headers=self._header, params=payload, timeout=timeout)
def _post(self, url, query=None, timeout=30): def _post(self, url, query=None, timeout=30):
payload=self._generatePayload(query) payload = self._generatePayload(query)
return self._session.post(url, headers=self._header, data=payload, timeout=timeout) return self._session.post(url, headers=self._header, data=payload, timeout=timeout)
def _cleanGet(self, url, query=None, timeout=30): def _cleanGet(self, url, query=None, timeout=30):
@@ -302,40 +289,40 @@ class Client(object):
r = self._cleanPost(CheckpointURL, data) r = self._cleanPost(CheckpointURL, data)
return r return r
def saveSession(self, sessionfile): def is_logged_in(self):
"""Dumps the session cookies to (sessionfile). # Send a request to the login url, to see if we're directed to the home page.
WILL OVERWRITE ANY EXISTING FILE r = self._cleanGet(LoginURL)
if 'home' in r.url:
return True
else:
return False
:param sessionfile: location of saved session file def getSession(self):
"""Returns the session cookies"""
return self._session.cookies.get_dict()
def setSession(self, session_cookies):
"""Loads session cookies
:param session_cookies: dictionary containing session cookies
Return false if session_cookies does not contain proper cookies
""" """
log.info('Saving session') # Quick check to see if session_cookies is formatted properly
with open(sessionfile, 'w') as f: if not session_cookies or 'c_user' not in session_cookies:
# Grab cookies from current session, and save them as JSON return False
f.write(json.dumps(self._session.cookies.get_dict(), ensure_ascii=False))
# Load cookies into current session
def loadSession(self, sessionfile): self._session.cookies = requests.cookies.merge_cookies(self._session.cookies, session_cookies)
"""Loads session cookies from (sessionfile) self._post_login()
return True
:param sessionfile: location of saved session file
"""
log.info('Loading session')
with open(sessionfile, 'r') as f:
try:
j = json.load(f)
if not j or 'c_user' not in j:
return False
# Load cookies into current session
self._session.cookies = requests.cookies.merge_cookies(self._session.cookies, j)
self._post_login()
return True
except Exception as e:
raise Exception('Invalid json in {}, or bad merging of cookies'.format(sessionfile))
def login(self, email, password, max_retries=5): def login(self, email, password, max_retries=5):
# Logging in # Logging in
log.info("Logging in...") log.info("Logging in {}...".format(email))
if not (email and password):
raise Exception("Email and password not set.")
self.email = email self.email = email
self.password = password self.password = password
@@ -346,7 +333,7 @@ class Client(object):
time.sleep(1) time.sleep(1)
continue continue
else: else:
log.info("Login successful.") 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.")

View File

@@ -10,6 +10,20 @@ USER_AGENTS = [
"Mozilla/5.0 (X11; CrOS i686 2268.111.0) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.57 Safari/536.11", "Mozilla/5.0 (X11; CrOS i686 2268.111.0) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.57 Safari/536.11",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1092.0 Safari/536.6" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1092.0 Safari/536.6"
] ]
GENDERS = {
0: 'unknown',
1: 'female_singular',
2: 'male_singular',
3: 'female_singular_guess',
4: 'male_singular_guess',
5: 'mixed',
6: 'neuter_singular',
7: 'unknown_singular',
8: 'female_plural',
9: 'male_plural',
10: 'neuter_plural',
11: 'unknown_plural',
}
def now(): def now():
return int(time()*1000) return int(time()*1000)