1 """Config flow for YouTube integration."""
3 from __future__
import annotations
5 from collections.abc
import Mapping
9 import voluptuous
as vol
10 from youtubeaio.helper
import first
11 from youtubeaio.types
import AuthScope, ForbiddenError
12 from youtubeaio.youtube
import YouTube
31 CHANNEL_CREATION_HELP_URL,
40 config_entry_oauth2_flow.AbstractOAuth2FlowHandler, domain=DOMAIN
42 """Config flow to handle Google OAuth2 authentication."""
44 _data: dict[str, Any] = {}
49 _youtube: YouTube |
None =
None
54 config_entry: ConfigEntry,
55 ) -> YouTubeOptionsFlowHandler:
56 """Get the options flow for this handler."""
62 return logging.getLogger(__name__)
66 """Extra data that needs to be appended to the authorize url."""
68 "scope":
" ".join(DEFAULT_ACCESS),
70 "access_type":
"offline",
75 self, entry_data: Mapping[str, Any]
76 ) -> ConfigFlowResult:
77 """Perform reauth upon an API authentication error."""
81 self, user_input: dict[str, Any] |
None =
None
82 ) -> ConfigFlowResult:
83 """Confirm reauth dialog."""
84 if user_input
is None:
85 return self.async_show_form(step_id=
"reauth_confirm")
86 return await self.async_step_user()
89 """Get Youtube resource async."""
92 await self.
_youtube_youtube.set_user_authentication(token, [AuthScope.READ_ONLY])
96 """Create an entry for the flow, or update existing entry."""
98 youtube = await self.
get_resourceget_resource(data[CONF_TOKEN][CONF_ACCESS_TOKEN])
99 own_channel = await first(youtube.get_user_channels())
100 if own_channel
is None or own_channel.snippet
is None:
101 return self.async_abort(
103 description_placeholders={
"support_url": CHANNEL_CREATION_HELP_URL},
105 except ForbiddenError
as ex:
107 return self.async_abort(
108 reason=
"access_not_configured",
109 description_placeholders={
"message": error},
111 except Exception
as ex:
112 LOGGER.error(
"Unknown error occurred: %s", ex.args)
113 return self.async_abort(reason=
"unknown")
114 self.
_title_title = own_channel.snippet.title
117 await self.async_set_unique_id(own_channel.channel_id)
118 if self.source != SOURCE_REAUTH:
119 self._abort_if_unique_id_configured()
123 self._abort_if_unique_id_mismatch(
124 reason=
"wrong_account",
125 description_placeholders={
"title": self.
_title_title},
128 return self.async_update_reload_and_abort(self._get_reauth_entry(), data=data)
131 self, user_input: dict[str, Any] |
None =
None
132 ) -> ConfigFlowResult:
133 """Select which channels to track."""
135 return self.async_create_entry(
137 data=self.
_data_data,
140 youtube = await self.
get_resourceget_resource(self.
_data_data[CONF_TOKEN][CONF_ACCESS_TOKEN])
141 selectable_channels = [
143 value=subscription.snippet.channel_id,
144 label=subscription.snippet.title,
146 async
for subscription
in youtube.get_user_subscriptions()
148 if not selectable_channels:
149 return self.async_abort(reason=
"no_subscriptions")
150 return self.async_show_form(
152 data_schema=vol.Schema(
163 """YouTube Options flow handler."""
166 self, user_input: dict[str, Any] |
None =
None
167 ) -> ConfigFlowResult:
168 """Initialize form."""
169 if user_input
is not None:
175 await youtube.set_user_authentication(
178 selectable_channels = [
180 value=subscription.snippet.channel_id,
181 label=subscription.snippet.title,
183 async
for subscription
in youtube.get_user_subscriptions()
192 options=selectable_channels, multiple=
True
ConfigFlowResult async_step_reauth(self, Mapping[str, Any] entry_data)
ConfigFlowResult async_step_reauth_confirm(self, dict[str, Any]|None user_input=None)
logging.Logger logger(self)
YouTube get_resource(self, str token)
dict[str, Any] extra_authorize_data(self)
ConfigFlowResult async_step_channels(self, dict[str, Any]|None user_input=None)
ConfigFlowResult async_oauth_create_entry(self, dict[str, Any] data)
YouTubeOptionsFlowHandler async_get_options_flow(ConfigEntry config_entry)
ConfigFlowResult async_step_init(self, dict[str, Any]|None user_input=None)
ConfigEntry config_entry(self)
None config_entry(self, ConfigEntry value)
vol.Schema add_suggested_values_to_schema(self, vol.Schema data_schema, Mapping[str, Any]|None suggested_values)
_FlowResultT async_show_form(self, *str|None step_id=None, vol.Schema|None data_schema=None, dict[str, str]|None errors=None, Mapping[str, str]|None description_placeholders=None, bool|None last_step=None, str|None preview=None)
_FlowResultT async_create_entry(self, *str|None title=None, Mapping[str, Any] data, str|None description=None, Mapping[str, str]|None description_placeholders=None)
aiohttp.ClientSession async_get_clientsession(HomeAssistant hass, bool verify_ssl=True, socket.AddressFamily family=socket.AF_UNSPEC, ssl_util.SSLCipherList ssl_cipher=ssl_util.SSLCipherList.PYTHON_DEFAULT)