Esempio n. 1
0
 async def async_step_process(self, step_id, user_input=None):
     """Handle the input processing of the config flow."""
     _LOGGER.debug(
         "Processing input for %s: %s",
         step_id,
         obfuscate(user_input),
     )
     self._save_user_input_to_config(user_input=user_input)
     if user_input and user_input.get(CONF_PROXY):
         return await self.async_step_user(user_input=None)
     if user_input:
         try:
             await self.login.login(data=user_input)
         except AlexapyConnectionError:
             self.automatic_steps = 0
             return self.async_show_form(
                 step_id=step_id,
                 errors={"base": "connection_error"},
                 description_placeholders={"message": ""},
             )
         except BaseException as ex:  # pylint: disable=broad-except
             _LOGGER.warning("Unknown error: %s", ex)
             if self.config[CONF_DEBUG]:
                 raise
             self.automatic_steps = 0
             return self.async_show_form(
                 step_id=step_id,
                 errors={"base": "unknown_error"},
                 description_placeholders={"message": ""},
             )
     return await self._test_login()
Esempio n. 2
0
 async def async_step_reauth(self, user_input=None):
     """Handle reauth processing for the config flow."""
     self._save_user_input_to_config(user_input)
     self.config["reauth"] = True
     reauth_schema = self._update_schema_defaults()
     _LOGGER.debug(
         "Creating reauth form with %s", obfuscate(self.config),
     )
     self.automatic_steps = 0
     if self.login is None:
         try:
             self.login = self.hass.data[DATA_ALEXAMEDIA]["accounts"][
                 self.config[CONF_EMAIL]
             ].get("login_obj")
         except KeyError:
             self.login = None
     seconds_since_login: int = (
         datetime.datetime.now() - self.login.stats["login_timestamp"]
     ).seconds if self.login else 60
     if seconds_since_login < 60:
         _LOGGER.debug(
             "Relogin requested within %s seconds; manual login required",
             seconds_since_login,
         )
         return self.async_show_form(
             step_id="user",
             data_schema=vol.Schema(reauth_schema),
             description_placeholders={"message": "REAUTH"},
         )
     _LOGGER.debug("Attempting automatic relogin")
     await sleep(15)
     return await self.async_step_user(self.config)
Esempio n. 3
0
async def test_login_status(hass, config_entry, login) -> bool:
    """Test the login status and spawn requests for info."""

    _LOGGER.debug("Testing login status: %s", login.status)
    if login.status and login.status.get("login_successful"):
        return True
    account = config_entry.data
    _LOGGER.debug("Logging in: %s %s", obfuscate(account), in_progess_instances(hass))
    _LOGGER.debug("Login stats: %s", login.stats)
    message: Text = (
        "Reauthenticate on the [Integrations](/config/integrations) page. "
    )
    if login.stats.get("login_timestamp") != datetime(1, 1, 1):
        elaspsed_time: str = str(datetime.now() - login.stats.get("login_timestamp"))
        api_calls: int = login.stats.get("api_calls")
        message += f"Relogin required after {elaspsed_time} and {api_calls} api calls."
    hass.components.persistent_notification.async_create(
        title="Alexa Media Reauthentication Required",
        message=message,
        notification_id="alexa_media_relogin_required",
    )
    flow = hass.data[DATA_ALEXAMEDIA]["config_flows"].get(
        f"{account[CONF_EMAIL]} - {account[CONF_URL]}"
    )
    if flow:
        if flow.get("flow_id") in in_progess_instances(hass):
            _LOGGER.debug("Existing config flow detected")
            return False
        _LOGGER.debug("Stopping orphaned config flow %s", flow.get("flow_id"))
        try:
            hass.config_entries.flow.async_abort(flow.get("flow_id"))
        except UnknownFlow:
            pass
        hass.data[DATA_ALEXAMEDIA]["config_flows"][
            f"{account[CONF_EMAIL]} - {account[CONF_URL]}"
        ] = None
    _LOGGER.debug("Creating new config flow to login")
    hass.data[DATA_ALEXAMEDIA]["config_flows"][
        f"{account[CONF_EMAIL]} - {account[CONF_URL]}"
    ] = await hass.config_entries.flow.async_init(
        DOMAIN,
        context={"source": "reauth"},
        data={
            CONF_EMAIL: account[CONF_EMAIL],
            CONF_PASSWORD: account[CONF_PASSWORD],
            CONF_URL: account[CONF_URL],
            CONF_DEBUG: account[CONF_DEBUG],
            CONF_INCLUDE_DEVICES: account[CONF_INCLUDE_DEVICES],
            CONF_EXCLUDE_DEVICES: account[CONF_EXCLUDE_DEVICES],
            CONF_SCAN_INTERVAL: account[CONF_SCAN_INTERVAL].total_seconds()
            if isinstance(account[CONF_SCAN_INTERVAL], timedelta)
            else account[CONF_SCAN_INTERVAL],
            CONF_COOKIES_TXT: account.get(CONF_COOKIES_TXT, ""),
            CONF_OTPSECRET: account.get(CONF_OTPSECRET, ""),
        },
    )
    return False
Esempio n. 4
0
 async def async_step_process(self, step_id, user_input=None):
     """Handle the input processing of the config flow."""
     _LOGGER.debug(
         "Processing input for %s: %s",
         step_id,
         obfuscate(user_input),
     )
     self._save_user_input_to_config(user_input=user_input)
     if user_input:
         return await self.async_step_user(user_input=None)
     return await self._test_login()
Esempio n. 5
0
 async def async_step_reauth(self, user_input=None):
     """Handle reauth processing for the config flow."""
     self._save_user_input_to_config(user_input)
     reauth_schema = self._update_schema_defaults()
     _LOGGER.debug(
         "Creating reauth form with %s",
         obfuscate(self.config),
     )
     self.automatic_steps = 0
     return self.async_show_form(
         step_id="user",
         data_schema=vol.Schema(reauth_schema),
         description_placeholders={"message": "REAUTH"},
     )
Esempio n. 6
0
 async def _test_login(self):
     login = self.login
     email = login.email
     _LOGGER.debug("Testing login status: %s", login.status)
     if login.status and login.status.get("login_successful"):
         existing_entry = await self.async_set_unique_id(
             f"{email} - {login.url}")
         self.config.pop(CONF_COOKIES_TXT)
         if existing_entry:
             self.hass.config_entries.async_update_entry(existing_entry,
                                                         data=self.config)
             _LOGGER.debug("Reauth successful for %s", hide_email(email))
             self.hass.bus.async_fire(
                 "alexa_media_relogin_success",
                 event_data={
                     "email": hide_email(email),
                     "url": login.url
                 },
             )
             self.hass.components.persistent_notification.async_dismiss(
                 "alexa_media_relogin_required")
             self.hass.data[DATA_ALEXAMEDIA]["accounts"][
                 self.config[CONF_EMAIL]]["login_obj"] = self.login
             self.hass.data[DATA_ALEXAMEDIA]["config_flows"][
                 f"{email} - {login.url}"] = None
             return self.async_abort(reason="reauth_successful")
         _LOGGER.debug("Setting up Alexa devices with %s",
                       dict(obfuscate(self.config)))
         self._abort_if_unique_id_configured(self.config)
         return self.async_create_entry(
             title=f"{login.email} - {login.url}", data=self.config)
     if login.status and login.status.get("captcha_required"):
         new_schema = self._update_ord_dict(
             self.captcha_schema,
             {
                 vol.Required(CONF_PASSWORD,
                              default=self.config[CONF_PASSWORD]):
                 str,
                 vol.Optional(
                     CONF_SECURITYCODE,
                     default=self.securitycode if self.securitycode else "",
                 ):
                 str,
             },
         )
         _LOGGER.debug("Creating config_flow to request captcha")
         self.automatic_steps = 0
         return self.async_show_form(
             step_id="captcha",
             data_schema=vol.Schema(new_schema),
             errors={},
             description_placeholders={
                 "email":
                 login.email,
                 "url":
                 login.url,
                 "captcha_image":
                 "[![captcha]({0})]({0})".format(
                     login.status["captcha_image_url"]),
                 "message":
                 f"  \n> {login.status.get('error_message','')}",
             },
         )
     if login.status and login.status.get("securitycode_required"):
         _LOGGER.debug(
             "Creating config_flow to request 2FA. Saved security code %s",
             self.securitycode,
         )
         if self.securitycode and self.automatic_steps < 1:
             _LOGGER.debug("Automatically submitting securitycode %s",
                           self.securitycode)
             self.automatic_steps += 1
             await sleep(1)
             return await self.async_step_twofactor(
                 user_input={CONF_SECURITYCODE: self.securitycode})
         self.twofactor_schema = OrderedDict([(
             vol.Required(CONF_SECURITYCODE, ),
             str,
         )])
         self.automatic_steps = 0
         return self.async_show_form(
             step_id="twofactor",
             data_schema=vol.Schema(self.twofactor_schema),
             errors={},
             description_placeholders={
                 "email": login.email,
                 "url": login.url,
                 "message": f"  \n> {login.status.get('error_message','')}",
             },
         )
     if login.status and login.status.get("claimspicker_required"):
         error_message = f"  \n> {login.status.get('error_message', '')}"
         _LOGGER.debug("Creating config_flow to select verification method")
         claimspicker_message = login.status["claimspicker_message"]
         self.automatic_steps = 0
         return self.async_show_form(
             step_id="claimspicker",
             data_schema=vol.Schema(self.claimspicker_schema),
             errors={},
             description_placeholders={
                 "email":
                 login.email,
                 "url":
                 login.url,
                 "message":
                 "  \n> {0}  \n> {1}".format(claimspicker_message,
                                             error_message),
             },
         )
     if login.status and login.status.get("authselect_required"):
         _LOGGER.debug("Creating config_flow to select OTA method")
         error_message = login.status.get("error_message", "")
         authselect_message = login.status["authselect_message"]
         self.automatic_steps = 0
         return self.async_show_form(
             step_id="authselect",
             data_schema=vol.Schema(self.authselect_schema),
             description_placeholders={
                 "email":
                 login.email,
                 "url":
                 login.url,
                 "message":
                 "  \n> {0}  \n> {1}".format(authselect_message,
                                             error_message),
             },
         )
     if login.status and login.status.get("verificationcode_required"):
         _LOGGER.debug("Creating config_flow to enter verification code")
         self.automatic_steps = 0
         return self.async_show_form(
             step_id="verificationcode",
             data_schema=vol.Schema(self.verificationcode_schema),
         )
     if login.status and login.status.get("force_get"):
         _LOGGER.debug("Creating config_flow to wait for user action")
         self.automatic_steps = 0
         return self.async_show_form(
             step_id="action_required",
             data_schema=vol.Schema(OrderedDict()),
             description_placeholders={
                 "email": login.email,
                 "url": login.url,
                 "message": f"  \n>{login.status.get('message','')}  \n",
             },
         )
     if login.status and login.status.get("login_failed"):
         _LOGGER.debug("Login failed: %s", login.status.get("login_failed"))
         await login.close()
         self.hass.components.persistent_notification.async_dismiss(
             "alexa_media_relogin_required")
         return self.async_abort(reason=login.status.get("login_failed"), )
     new_schema = self._update_schema_defaults()
     if login.status and login.status.get("error_message"):
         _LOGGER.debug("Login error detected: %s",
                       login.status.get("error_message"))
         if login.status.get("error_message") in {
                 "There was a problem\n            Enter a valid email or mobile number\n          "
         }:
             _LOGGER.debug(
                 "Trying automatic resubmission for error_message 'valid email'"
             )
             self.automatic_steps += 1
             await sleep(1)
             return await self.async_step_user(user_input=self.config)
         self.automatic_steps = 0
         return self.async_show_form(
             step_id="user",
             data_schema=vol.Schema(new_schema),
             description_placeholders={
                 "message": f"  \n> {login.status.get('error_message','')}"
             },
         )
     self.automatic_steps = 0
     return self.async_show_form(
         step_id="user",
         data_schema=vol.Schema(new_schema),
         description_placeholders={
             "message": f"  \n> {login.status.get('error_message','')}"
         },
     )
Esempio n. 7
0
 async def _test_login(self):
     # pylint: disable=too-many-statements, too-many-return-statements
     login = self.login
     email = login.email
     _LOGGER.debug("Testing login status: %s", login.status)
     if login.status and login.status.get("login_successful"):
         existing_entry = await self.async_set_unique_id(
             f"{email} - {login.url}")
         if self.config.get("reauth"):
             self.config.pop("reauth")
         if self.config.get(CONF_SECURITYCODE):
             self.config.pop(CONF_SECURITYCODE)
         if self.config.get("hass_url"):
             self.config.pop("hass_url")
         self.config[CONF_OAUTH] = {
             "access_token": login.access_token,
             "refresh_token": login.refresh_token,
             "expires_in": login.expires_in,
             "mac_dms": login.mac_dms
         }
         self.hass.data.setdefault(
             DATA_ALEXAMEDIA,
             {
                 "accounts": {},
                 "config_flows": {},
                 "notify_service": None
             },
         )
         self.hass.data[DATA_ALEXAMEDIA].setdefault("accounts", {})
         self.hass.data[DATA_ALEXAMEDIA].setdefault("config_flows", {})
         if existing_entry:
             self.hass.config_entries.async_update_entry(existing_entry,
                                                         data=self.config)
             _LOGGER.debug("Reauth successful for %s", hide_email(email))
             self.hass.bus.async_fire(
                 "alexa_media_relogin_success",
                 event_data={
                     "email": hide_email(email),
                     "url": login.url
                 },
             )
             self.hass.components.persistent_notification.async_dismiss(
                 f"alexa_media_{slugify(email)}{slugify(login.url[7:])}")
             if not self.hass.data[DATA_ALEXAMEDIA]["accounts"].get(
                     self.config[CONF_EMAIL]):
                 self.hass.data[DATA_ALEXAMEDIA]["accounts"][
                     self.config[CONF_EMAIL]] = {}
             self.hass.data[DATA_ALEXAMEDIA]["accounts"][
                 self.config[CONF_EMAIL]]["login_obj"] = self.login
             self.hass.data[DATA_ALEXAMEDIA]["config_flows"][
                 f"{email} - {login.url}"] = None
             return self.async_abort(reason="reauth_successful")
         _LOGGER.debug("Setting up Alexa devices with %s",
                       dict(obfuscate(self.config)))
         self._abort_if_unique_id_configured(self.config)
         return self.async_create_entry(
             title=f"{login.email} - {login.url}", data=self.config)
     if login.status and login.status.get("securitycode_required"):
         _LOGGER.debug(
             "Creating config_flow to request 2FA. Saved security code %s",
             self.securitycode,
         )
         generated_securitycode: str = login.get_totp_token()
         if (self.securitycode
                 or generated_securitycode) and self.automatic_steps < 2:
             if self.securitycode:
                 _LOGGER.debug("Automatically submitting securitycode %s",
                               self.securitycode)
             else:
                 _LOGGER.debug(
                     "Automatically submitting generated securitycode %s",
                     generated_securitycode,
                 )
             self.automatic_steps += 1
             await sleep(5)
             if generated_securitycode:
                 return await self.async_step_twofactor(
                     user_input={CONF_SECURITYCODE: generated_securitycode})
             return await self.async_step_twofactor(
                 user_input={CONF_SECURITYCODE: self.securitycode})
     if login.status and (login.status.get("login_failed")):
         _LOGGER.debug("Login failed: %s", login.status.get("login_failed"))
         await login.close()
         self.hass.components.persistent_notification.async_dismiss(
             f"alexa_media_{slugify(email)}{slugify(login.url[7:])}")
         return self.async_abort(reason="login_failed")
     new_schema = self._update_schema_defaults()
     if login.status and login.status.get("error_message"):
         _LOGGER.debug("Login error detected: %s",
                       login.status.get("error_message"))
         if (login.status.get("error_message") in {
                 "There was a problem\n            Enter a valid email or mobile number\n          "
         } and self.automatic_steps < 2):
             _LOGGER.debug(
                 "Trying automatic resubmission %s for error_message 'valid email'",
                 self.automatic_steps,
             )
             self.automatic_steps += 1
             await sleep(5)
             return await self.async_step_user_legacy(user_input=self.config
                                                      )
         _LOGGER.debug(
             "Done with automatic resubmission for error_message 'valid email'; returning error message",
         )
     self.automatic_steps = 0
     return self.async_show_form(
         step_id="user",
         data_schema=vol.Schema(new_schema),
         description_placeholders={
             "message": f"  \n> {login.status.get('error_message','')}"
         },
     )
Esempio n. 8
0
 async def _test_login(self):
     # pylint: disable=too-many-statements, too-many-return-statements
     login = self.login
     email = login.email
     _LOGGER.debug("Testing login status: %s", login.status)
     if login.status and login.status.get("login_successful"):
         existing_entry = await self.async_set_unique_id(f"{email} - {login.url}")
         if self.config.get("reauth"):
             self.config.pop("reauth")
         if self.config.get(CONF_SECURITYCODE):
             self.config.pop(CONF_SECURITYCODE)
         if self.config.get(CONF_PROXY):
             self.config.pop(CONF_PROXY)
         if self.config.get("hass_url"):
             self.config.pop("hass_url")
         self.config[CONF_OAUTH] = {
             "access_token": login.access_token,
             "refresh_token": login.refresh_token,
             "expires_in": login.expires_in,
         }
         self.hass.data.setdefault(
             DATA_ALEXAMEDIA,
             {"accounts": {}, "config_flows": {}},
         )
         if existing_entry:
             self.hass.config_entries.async_update_entry(
                 existing_entry, data=self.config
             )
             _LOGGER.debug("Reauth successful for %s", hide_email(email))
             self.hass.bus.async_fire(
                 "alexa_media_relogin_success",
                 event_data={"email": hide_email(email), "url": login.url},
             )
             self.hass.components.persistent_notification.async_dismiss(
                 f"alexa_media_{slugify(email)}{slugify(login.url[7:])}"
             )
             self.hass.data[DATA_ALEXAMEDIA]["accounts"][self.config[CONF_EMAIL]][
                 "login_obj"
             ] = self.login
             self.hass.data[DATA_ALEXAMEDIA]["config_flows"][
                 f"{email} - {login.url}"
             ] = None
             return self.async_abort(reason="reauth_successful")
         _LOGGER.debug(
             "Setting up Alexa devices with %s", dict(obfuscate(self.config))
         )
         self._abort_if_unique_id_configured(self.config)
         return self.async_create_entry(
             title=f"{login.email} - {login.url}", data=self.config
         )
     if login.status and login.status.get("captcha_required"):
         new_schema = self._update_ord_dict(
             self.captcha_schema,
             {
                 vol.Required(
                     CONF_PASSWORD, default=self.config[CONF_PASSWORD]
                 ): str,
                 vol.Optional(
                     CONF_SECURITYCODE,
                     default=self.securitycode if self.securitycode else "",
                 ): str,
             },
         )
         _LOGGER.debug("Creating config_flow to request captcha")
         self.automatic_steps = 0
         return self.async_show_form(
             step_id="captcha",
             data_schema=vol.Schema(new_schema),
             errors={},
             description_placeholders={
                 "email": login.email,
                 "url": login.url,
                 "captcha_image": "[![captcha]({0})]({0})".format(
                     login.status["captcha_image_url"]
                 ),
                 "message": f"  \n> {login.status.get('error_message','')}",
             },
         )
     if login.status and login.status.get("securitycode_required"):
         _LOGGER.debug(
             "Creating config_flow to request 2FA. Saved security code %s",
             self.securitycode,
         )
         generated_securitycode: Text = login.get_totp_token()
         if (
             self.securitycode or generated_securitycode
         ) and self.automatic_steps < 2:
             if self.securitycode:
                 _LOGGER.debug(
                     "Automatically submitting securitycode %s", self.securitycode
                 )
             else:
                 _LOGGER.debug(
                     "Automatically submitting generated securitycode %s",
                     generated_securitycode,
                 )
             self.automatic_steps += 1
             await sleep(5)
             if generated_securitycode:
                 return await self.async_step_twofactor(
                     user_input={CONF_SECURITYCODE: generated_securitycode}
                 )
             return await self.async_step_twofactor(
                 user_input={CONF_SECURITYCODE: self.securitycode}
             )
         self.twofactor_schema = OrderedDict(
             [
                 (vol.Optional(CONF_PROXY, default=False), bool),
                 (
                     vol.Required(
                         CONF_SECURITYCODE,
                         default=self.securitycode if self.securitycode else "",
                     ),
                     str,
                 ),
             ]
         )
         self.automatic_steps = 0
         return self.async_show_form(
             step_id="twofactor",
             data_schema=vol.Schema(self.twofactor_schema),
             errors={},
             description_placeholders={
                 "email": login.email,
                 "url": login.url,
                 "message": f"  \n> {login.status.get('error_message','')}",
             },
         )
     if login.status and login.status.get("claimspicker_required"):
         error_message = f"  \n> {login.status.get('error_message', '')}"
         _LOGGER.debug("Creating config_flow to select verification method")
         claimspicker_message = login.status["claimspicker_message"]
         self.automatic_steps = 0
         return self.async_show_form(
             step_id="claimspicker",
             data_schema=vol.Schema(self.claimspicker_schema),
             errors={},
             description_placeholders={
                 "email": login.email,
                 "url": login.url,
                 "message": "  \n> {}  \n> {}".format(
                     claimspicker_message, error_message
                 ),
             },
         )
     if login.status and login.status.get("authselect_required"):
         _LOGGER.debug("Creating config_flow to select OTA method")
         error_message = login.status.get("error_message", "")
         authselect_message = login.status["authselect_message"]
         self.automatic_steps = 0
         return self.async_show_form(
             step_id="authselect",
             data_schema=vol.Schema(self.authselect_schema),
             description_placeholders={
                 "email": login.email,
                 "url": login.url,
                 "message": "  \n> {}  \n> {}".format(
                     authselect_message, error_message
                 ),
             },
         )
     if login.status and login.status.get("verificationcode_required"):
         _LOGGER.debug("Creating config_flow to enter verification code")
         self.automatic_steps = 0
         return self.async_show_form(
             step_id="verificationcode",
             data_schema=vol.Schema(self.verificationcode_schema),
         )
     if (
         login.status
         and login.status.get("force_get")
         and not login.status.get("ap_error_href")
     ):
         _LOGGER.debug("Creating config_flow to wait for user action")
         self.automatic_steps = 0
         return self.async_show_form(
             step_id="action_required",
             data_schema=vol.Schema(
                 OrderedDict([(vol.Optional(CONF_PROXY, default=False), bool)])
             ),
             description_placeholders={
                 "email": login.email,
                 "url": login.url,
                 "message": f"  \n>{login.status.get('message','')}  \n",
             },
         )
     if login.status and (login.status.get("login_failed")):
         if login.oauth_login:
             _LOGGER.debug("Trying non-oauth login")
             await login.reset()
             login.oauth_login = False
             await login.login()
             return await self._test_login()
         _LOGGER.debug("Login failed: %s", login.status.get("login_failed"))
         await login.close()
         self.hass.components.persistent_notification.async_dismiss(
             f"alexa_media_{slugify(email)}{slugify(login.url[7:])}"
         )
         return self.async_abort(reason="login_failed")
     new_schema = self._update_schema_defaults()
     if login.status and login.status.get("error_message"):
         _LOGGER.debug("Login error detected: %s", login.status.get("error_message"))
         if (
             login.status.get("error_message")
             in {
                 "There was a problem\n            Enter a valid email or mobile number\n          "
             }
             and self.automatic_steps < 2
         ):
             _LOGGER.debug(
                 "Trying automatic resubmission %s for error_message 'valid email'",
                 self.automatic_steps,
             )
             self.automatic_steps += 1
             await sleep(5)
             return await self.async_step_user_legacy(user_input=self.config)
         _LOGGER.debug(
             "Done with automatic resubmission for error_message 'valid email'; returning error message",
         )
         self.automatic_steps = 0
         return self.async_show_form(
             step_id="user_legacy",
             data_schema=vol.Schema(new_schema),
             description_placeholders={
                 "message": f"  \n> {login.status.get('error_message','')}"
             },
         )
     self.automatic_steps = 0
     return self.async_show_form(
         step_id="user_legacy",
         data_schema=vol.Schema(new_schema),
         description_placeholders={
             "message": f"  \n> {login.status.get('error_message','')}"
         },
     )
 async def _test_login(self):
     login = self.login
     email = login.email
     _LOGGER.debug("Testing login status: %s", login.status)
     if login.status and login.status.get("login_successful"):
         existing_entry = await self.async_set_unique_id(
             f"{email} - {login.url}")
         if existing_entry:
             self.hass.config_entries.async_update_entry(existing_entry,
                                                         data=self.config)
             _LOGGER.debug("Reauth successful for %s", hide_email(email))
             self.hass.bus.async_fire(
                 "alexa_media_player_relogin_success",
                 event_data={
                     "email": hide_email(email),
                     "url": login.url
                 },
             )
             self.hass.components.persistent_notification.async_dismiss(
                 "alexa_media_player_relogin_required")
             self.hass.data[DATA_ALEXAMEDIA]["accounts"][
                 self.config[CONF_EMAIL]]["login_obj"] = self.login
             return self.async_abort(reason="reauth_successful")
         _LOGGER.debug("Setting up Alexa devices with %s",
                       dict(obfuscate(self.config)))
         self._abort_if_unique_id_configured(self.config)
         return self.async_create_entry(
             title=f"{login.email} - {login.url}", data=self.config)
     if login.status and login.status.get("captcha_required"):
         new_schema = self._update_ord_dict(
             self.captcha_schema,
             {
                 vol.Required(CONF_PASSWORD,
                              default=self.config[CONF_PASSWORD]):
                 str
             },
         )
         _LOGGER.debug("Creating config_flow to request captcha")
         return self.async_show_form(
             step_id="captcha",
             data_schema=vol.Schema(new_schema),
             errors={},
             description_placeholders={
                 "email":
                 login.email,
                 "url":
                 login.url,
                 "captcha_image":
                 "[![captcha]({0})]({0})".format(
                     login.status["captcha_image_url"]),
                 "message":
                 f"\n> {login.status.get('error_message','')}",
             },
         )
     if login.status and login.status.get("securitycode_required"):
         _LOGGER.debug("Creating config_flow to request 2FA")
         return self.async_show_form(
             step_id="twofactor",
             data_schema=vol.Schema(self.twofactor_schema),
             errors={},
             description_placeholders={
                 "email": login.email,
                 "url": login.url,
                 "message": f"\n> {login.status.get('error_message','')}",
             },
         )
     if login.status and login.status.get("claimspicker_required"):
         error_message = f"\n> {login.status.get('error_message', '')}"
         _LOGGER.debug("Creating config_flow to select verification method")
         claimspicker_message = login.status["claimspicker_message"]
         return self.async_show_form(
             step_id="claimspicker",
             data_schema=vol.Schema(self.claimspicker_schema),
             errors={},
             description_placeholders={
                 "email":
                 login.email,
                 "url":
                 login.url,
                 "message":
                 "\n> {0}\n> {1}".format(claimspicker_message,
                                         error_message),
             },
         )
     if login.status and login.status.get("authselect_required"):
         _LOGGER.debug("Creating config_flow to select OTA method")
         error_message = login.status.get("error_message", "")
         authselect_message = login.status["authselect_message"]
         return self.async_show_form(
             step_id="authselect",
             data_schema=vol.Schema(self.authselect_schema),
             description_placeholders={
                 "email":
                 login.email,
                 "url":
                 login.url,
                 "message":
                 "\n> {0}\n> {1}".format(authselect_message, error_message),
             },
         )
     if login.status and login.status.get("verificationcode_required"):
         _LOGGER.debug("Creating config_flow to enter verification code")
         return self.async_show_form(
             step_id="verificationcode",
             data_schema=vol.Schema(self.verificationcode_schema),
         )
     if login.status and login.status.get("force_get"):
         _LOGGER.debug("Creating config_flow to wait for user action")
         return self.async_show_form(
             step_id="action_required",
             data_schema=vol.Schema(OrderedDict()),
             description_placeholders={
                 "email": login.email,
                 "url": login.url,
                 "message":
                 f"```text\n{login.status.get('message','')}\n```",
             },
         )
     if login.status and login.status.get("login_failed"):
         _LOGGER.debug("Login failed: %s", login.status.get("login_failed"))
         await login.close()
         return self.async_abort(reason=login.status.get("login_failed"), )
     new_schema = self._update_ord_dict(
         self.data_schema,
         {
             vol.Required(CONF_EMAIL, default=self.config[CONF_EMAIL]):
             str,
             vol.Required(CONF_PASSWORD, default=self.config[CONF_PASSWORD]):
             str,
             vol.Optional("securitycode"):
             str,
             vol.Required(CONF_URL, default=self.config[CONF_URL]):
             str,
             vol.Optional(CONF_DEBUG, default=self.config[CONF_DEBUG]):
             bool,
             vol.Optional(
                 CONF_INCLUDE_DEVICES,
                 default=(self.config[CONF_INCLUDE_DEVICES] if isinstance(
                              self.config[CONF_INCLUDE_DEVICES], str) else ",".join(
                              map(str, self.config[CONF_INCLUDE_DEVICES]))),
             ):
             str,
             vol.Optional(
                 CONF_EXCLUDE_DEVICES,
                 default=(self.config[CONF_EXCLUDE_DEVICES] if isinstance(
                              self.config[CONF_EXCLUDE_DEVICES], str) else ",".join(
                              map(str, self.config[CONF_EXCLUDE_DEVICES]))),
             ):
             str,
             vol.Optional(CONF_SCAN_INTERVAL,
                          default=self.config[CONF_SCAN_INTERVAL]):
             int,
         },
     )
     if login.status and login.status.get("error_message"):
         _LOGGER.debug("Login error detected: %s",
                       login.status.get("error_message"))
         return self.async_show_form(
             step_id="user",
             data_schema=vol.Schema(new_schema),
             description_placeholders={
                 "message": f"\n> {login.status.get('error_message','')}"
             },
         )
     return self.async_show_form(
         step_id="user",
         data_schema=vol.Schema(new_schema),
         description_placeholders={
             "message": f"\n> {login.status.get('error_message','')}"
         },
     )