Move user id handling to State

This commit is contained in:
Mads Marquart
2019-07-25 23:54:17 +02:00
parent a131e1ae73
commit ef8e7d4251
2 changed files with 22 additions and 20 deletions

View File

@@ -174,16 +174,11 @@ class Client(object):
""" """
try: try:
# Load cookies into current session # Load cookies into current session
state = State.from_cookies(session_cookies, user_agent=user_agent) self._state = State.from_cookies(session_cookies, user_agent=user_agent)
self._uid = self._state.user_id
except Exception as e: except Exception as e:
log.exception("Failed loading session") log.exception("Failed loading session")
return False return False
uid = state.get_user_id()
if uid is None:
log.warning("Could not find c_user cookie")
return False
self._state = state
self._uid = uid
return True return True
def login(self, email, password, max_tries=5, user_agent=None): def login(self, email, password, max_tries=5, user_agent=None):
@@ -209,23 +204,19 @@ class Client(object):
for i in range(1, max_tries + 1): for i in range(1, max_tries + 1):
try: try:
state = State.login( self._state = State.login(
email, email,
password, password,
on_2fa_callback=self.on2FACode, on_2fa_callback=self.on2FACode,
user_agent=user_agent, user_agent=user_agent,
) )
uid = state.get_user_id() self._uid = self._state.user_id
if uid is None:
raise FBchatException("Could not find user id")
except Exception: except Exception:
if i >= max_tries: if i >= max_tries:
raise raise
log.exception("Attempt #{} failed, retrying".format(i)) log.exception("Attempt #{} failed, retrying".format(i))
time.sleep(1) time.sleep(1)
else: else:
self._state = state
self._uid = uid
self.onLoggedIn(email=email) self.onLoggedIn(email=email)
break break

View File

@@ -12,6 +12,14 @@ from . import _graphql, _util, _exception
FB_DTSG_REGEX = re.compile(r'name="fb_dtsg" value="(.*?)"') FB_DTSG_REGEX = re.compile(r'name="fb_dtsg" value="(.*?)"')
def get_user_id(session):
# TODO: Optimize this `.get_dict()` call!
rtn = session.cookies.get_dict().get("c_user")
if rtn is None:
raise _exception.FBchatException("Could not find user id")
return str(rtn)
def find_input_fields(html): def find_input_fields(html):
return bs4.BeautifulSoup(html, "html.parser", parse_only=bs4.SoupStrainer("input")) return bs4.BeautifulSoup(html, "html.parser", parse_only=bs4.SoupStrainer("input"))
@@ -91,18 +99,13 @@ def _2fa_helper(session, code, r):
class State(object): class State(object):
"""Stores and manages state required for most Facebook requests.""" """Stores and manages state required for most Facebook requests."""
user_id = attr.ib()
fb_dtsg = attr.ib() fb_dtsg = attr.ib()
_revision = attr.ib() _revision = attr.ib()
_session = attr.ib(factory=session_factory) _session = attr.ib(factory=session_factory)
_counter = attr.ib(0) _counter = attr.ib(0)
_logout_h = attr.ib(None) _logout_h = attr.ib(None)
def get_user_id(self):
rtn = self.get_cookies().get("c_user")
if rtn is None:
return None
return str(rtn)
def get_params(self): def get_params(self):
self._counter += 1 # TODO: Make this operation atomic / thread-safe self._counter += 1 # TODO: Make this operation atomic / thread-safe
return { return {
@@ -163,6 +166,9 @@ class State(object):
@classmethod @classmethod
def from_session(cls, session): def from_session(cls, session):
# TODO: Automatically set user_id when the cookie changes in the session
user_id = get_user_id(session)
r = session.get(_util.prefix_url("/")) r = session.get(_util.prefix_url("/"))
soup = find_input_fields(r.text) soup = find_input_fields(r.text)
@@ -180,7 +186,11 @@ class State(object):
logout_h = logout_h_element["value"] if logout_h_element else None logout_h = logout_h_element["value"] if logout_h_element else None
return cls( return cls(
fb_dtsg=fb_dtsg, revision=revision, session=session, logout_h=logout_h user_id=user_id,
fb_dtsg=fb_dtsg,
revision=revision,
session=session,
logout_h=logout_h,
) )
def get_cookies(self): def get_cookies(self):
@@ -197,6 +207,7 @@ class State(object):
# It may be a bad idea to do this in an exception handler, if you have a better method, please suggest it! # It may be a bad idea to do this in an exception handler, if you have a better method, please suggest it!
_util.log.warning("Refreshing state and resending request") _util.log.warning("Refreshing state and resending request")
new = State.from_session(session=self._session) new = State.from_session(session=self._session)
self.user_id = new.user_id
self.fb_dtsg = new.fb_dtsg self.fb_dtsg = new.fb_dtsg
self._revision = new._revision self._revision = new._revision
self._counter = new._counter self._counter = new._counter