Browse Source

Handle Facebook account not being linked to an Instagram account

Tulir Asokan 3 years ago
parent
commit
0f524d2255

+ 1 - 0
mauigpapi/errors/__init__.py

@@ -5,6 +5,7 @@ from .response import (
     IGBad2FACodeError,
     IGChallengeWrongCodeError,
     IGCheckpointError,
+    IGFBNoContactPointFoundError,
     IGInactiveUserError,
     IGLoginBadPasswordError,
     IGLoginError,

+ 4 - 0
mauigpapi/errors/response.py

@@ -117,5 +117,9 @@ class IGLoginInvalidUserError(IGLoginError):
     pass
 
 
+class IGFBNoContactPointFoundError(IGLoginError):
+    pass
+
+
 class IGBad2FACodeError(IGResponseError):
     pass

+ 3 - 0
mauigpapi/http/base.py

@@ -31,6 +31,7 @@ from ..errors import (
     IGActionSpamError,
     IGBad2FACodeError,
     IGCheckpointError,
+    IGFBNoContactPointFoundError,
     IGInactiveUserError,
     IGLoginBadPasswordError,
     IGLoginInvalidUserError,
@@ -219,6 +220,8 @@ class BaseAndroidAPI:
             raise IGLoginInvalidUserError(resp, data)
         elif error_type == "sms_code_validation_code_invalid":
             raise IGBad2FACodeError(resp, data)
+        elif error_type == "fb_no_contact_point_found":
+            raise IGFBNoContactPointFoundError(resp, data)
 
         raise IGResponseError(resp, data)
 

+ 4 - 0
mauigpapi/types/error.py

@@ -104,3 +104,7 @@ class LoginErrorResponse(SerializableAttrs):
     two_factor_required: Optional[bool] = None
     two_factor_info: Optional[LoginTwoFactorInfo] = None
     phone_verification_settings: Optional[LoginPhoneVerificationSettings] = None
+
+    # FB login error fields
+    account_created: Optional[bool] = None
+    dryrun_passed: Optional[bool] = None

+ 26 - 2
mautrix_instagram/web/provisioning_api.py

@@ -31,6 +31,7 @@ from mauigpapi.errors import (
     IGBad2FACodeError,
     IGChallengeWrongCodeError,
     IGCheckpointError,
+    IGFBNoContactPointFoundError,
     IGLoginBadPasswordError,
     IGLoginInvalidUserError,
     IGLoginTwoFactorRequiredError,
@@ -370,13 +371,36 @@ class ProvisioningAPI:
 
         try:
             fb_access_token = data["access_token"]
-            logger_id = data["state"]["0_auth_logger_id"]
+            state = data.get("state", {})
+            if isinstance(state, str):
+                state = json.loads(state)
+            logger_id = state.get("0_auth_logger_id")
         except KeyError as e:
             raise self._missing_key_error(e)
+        except json.JSONDecodeError:
+            raise web.HTTPBadRequest(
+                text='{"error": "Non-JSON state field"}', headers=self._headers
+            )
 
         self.log.debug(
             "%s is attempting to log in with Facebook token (logger ID %s)", user.mxid, logger_id
         )
         api, state = await get_login_state(user, self.device_seed)
-        resp = await api.facebook_signup(fb_access_token)
+        try:
+            resp = await api.facebook_signup(fb_access_token)
+        except IGFBNoContactPointFoundError as e:
+            self.log.debug(
+                "%s sent a valid Facebook token, "
+                "but it didn't seem to have an Instagram account linked (%s)",
+                user.mxid,
+                e.body.serialize(),
+            )
+            return web.json_response(
+                data={
+                    "error": "You don't have an Instagram account linked to that Facebook account",
+                    "status": e.body.error_type,
+                },
+                status=403,
+                headers=self._acao_headers,
+            )
         return await self._finish_login(user, state, api, login_resp=resp, after="facebook auth")