async def on_logged_in(self, state: AndroidState) -> None: self.fbid = state.session.uid self.state = state self.client = AndroidAPI(state, log=self.log.getChild("api")) await self.save() self.stop_listen() asyncio.ensure_future(self.post_login(), loop=self.loop)
async def load_session(self, _override: bool = False, _raise_errors: bool = False) -> bool: if self._is_logged_in and not _override: return True elif not self.state: return False attempt = 0 client = AndroidAPI(self.state, log=self.log.getChild("api")) while True: try: user_info = await client.get_self() break except (ProxyError, ProxyTimeoutError, ProxyConnectionError, ConnectionError) as e: attempt += 1 wait = min(attempt * 10, 60) self.log.warning(f"{e.__class__.__name__} while trying to restore session, " f"retrying in {wait} seconds: {e}") await asyncio.sleep(wait) except Exception: self.log.exception("Failed to restore session") if _raise_errors: raise return False if user_info: self.log.info("Loaded session successfully") self.client = client self._track_metric(METRIC_LOGGED_IN, True) self._is_logged_in = True self.is_connected = None self.stop_listen() asyncio.ensure_future(self.post_login(), loop=self.loop) return True return False
async def login_prepare(self, request: web.Request) -> web.Response: user = await self.check_token(request) state = AndroidState() state.generate(user.mxid) api = AndroidAPI(state, log=user.log.getChild("login-api")) user.command_status = { "action": "Login", "state": state, "api": api, } try: await api.mobile_config_sessionless() except Exception as e: self.log.exception( "Failed to get mobile_config_sessionless to prepare login " f"for {user.mxid}") return web.json_response({"error": str(e)}, headers=self._acao_headers) return web.json_response( { "status": "login", "password_encryption_key_id": state.session.password_encryption_key_id, "password_encryption_pubkey": state.session.password_encryption_pubkey }, headers=self._acao_headers)
async def login(self, request: web.Request) -> web.Response: user = await self.check_token(request) try: data = await request.json() except json.JSONDecodeError: raise web.HTTPBadRequest(text='{"error": "Malformed JSON"}', headers=self._headers) try: email = data["email"] except KeyError: raise web.HTTPBadRequest(text='{"error": "Missing email"}', headers=self._headers) try: password = data["password"] encrypted_password = None except KeyError: try: encrypted_password = data["encrypted_password"] password = None except KeyError: raise web.HTTPBadRequest(text='{"error": "Missing password"}', headers=self._headers) if encrypted_password: if not user.command_status or user.command_status["action"] != "Login": raise web.HTTPBadRequest(text='{"error": "No login in progress"}', headers=self._headers) state: AndroidState = user.command_status["state"] api: AndroidAPI = user.command_status["api"] else: state = AndroidState() state.generate(user.mxid) api = AndroidAPI(state, log=user.log.getChild("login-api")) await api.mobile_config_sessionless() try: await api.login(email, password=password, encrypted_password=encrypted_password) await user.on_logged_in(state) return web.json_response({"status": "logged-in"}, headers=self._acao_headers) except TwoFactorRequired as e: user.command_status = { "action": "Login", "state": state, "api": api, } return web.json_response({ "status": "two-factor", "error": e.data, }, headers=self._acao_headers) except OAuthException as e: return web.json_response({"error": str(e)}, headers=self._acao_headers)
async def login(evt: CommandEvent) -> None: if len(evt.args) < 2: await evt.reply("Usage: `$cmdprefix+sp login <email> <password>`") return email, password = evt.args[0], " ".join(evt.args[1:]) try: await evt.az.intent.redact(evt.room_id, evt.event_id) except MForbidden: pass if evt.sender.client: await evt.reply("You're already logged in") return state = AndroidState() state.generate(evt.sender.mxid) api = AndroidAPI(state, log=evt.sender.log.getChild("login-api")) try: await api.mobile_config_sessionless() await api.login(email, password) await evt.sender.on_logged_in(state) await evt.reply("Successfully logged in") except TwoFactorRequired: await evt.reply( "You have two-factor authentication turned on. Please either send the code" " from SMS or your authenticator app here, or approve the login from" " another device logged into Messenger.") checker_task = asyncio.create_task( check_approved_login(state, api, evt)) evt.sender.command_status = { "action": "Login", "room_id": evt.room_id, "next": enter_2fa_code, "state": state, "api": api, "email": email, "checker_task": checker_task, } except OAuthException as e: await evt.reply(f"Error from Messenger:\n\n> {e}") except Exception as e: evt.log.exception("Failed to log in") evt.sender.command_status = None await evt.reply(f"Failed to log in: {e}")