diff --git a/roborock/web_api.py b/roborock/web_api.py index 4f91b48a..e0231766 100644 --- a/roborock/web_api.py +++ b/roborock/web_api.py @@ -359,6 +359,10 @@ async def code_login_v4( raise RoborockInvalidUserAgreement( "User agreement must be accepted again - or you are attempting to use the Mi Home app account." ) + if response_code == 3039: + raise RoborockAccountDoesNotExist( + "This account does not exist - please ensure that you selected the right region and email." + ) raise RoborockException(f"{login_response.get('msg')} - response code: {response_code}") user_data = login_response.get("data") if not isinstance(user_data, dict): diff --git a/tests/test_web_api.py b/tests/test_web_api.py index bd528590..429783fc 100644 --- a/tests/test_web_api.py +++ b/tests/test_web_api.py @@ -6,6 +6,7 @@ from aioresponses.compat import normalize_url from roborock import HomeData, HomeDataScene, UserData +from roborock.exceptions import RoborockAccountDoesNotExist from roborock.web_api import IotLoginInfo, RoborockApiClient from tests.mock_data import HOME_DATA_RAW, USER_DATA @@ -88,6 +89,42 @@ async def test_code_login_v4_flow(mock_rest) -> None: assert ud == UserData.from_dict(USER_DATA) +async def test_code_login_v4_account_does_not_exist(mock_rest) -> None: + """Test that response code 3039 raises RoborockAccountDoesNotExist.""" + mock_rest.clear() + + mock_rest.post( + re.compile(r"https://.*iot\.roborock\.com/api/v1/getUrlByEmail.*"), + status=200, + payload={ + "code": 200, + "data": {"country": "US", "countrycode": "1", "url": "https://usiot.roborock.com"}, + "msg": "success", + }, + ) + mock_rest.post( + re.compile(r"https://.*iot\.roborock\.com/api/v4/email/code/send.*"), + status=200, + payload={"code": 200, "data": None, "msg": "success"}, + ) + mock_rest.post( + re.compile(r"https://.*iot\.roborock\.com/api/v3/key/sign.*"), + status=200, + payload={"code": 200, "data": {"k": "mock_k"}, "msg": "success"}, + ) + mock_rest.post( + re.compile(r"https://.*iot\.roborock\.com/api/v4/auth/email/login/code.*"), + status=200, + payload={"code": 3039, "data": None, "msg": "account does not exist"}, + ) + + api = RoborockApiClient(username="test_user@gmail.com") + await api.request_code_v4() + with pytest.raises(RoborockAccountDoesNotExist) as exc_info: + await api.code_login_v4(4123, "US", 1) + assert "This account does not exist" in str(exc_info.value) + + async def test_url_cycling(mock_rest) -> None: """Test that we cycle through the URLs correctly.""" # Clear mock rest so that we can override the patches.