Skip to content

Commit d6a74d6

Browse files
committed
Add start_dcf docs
1 parent 9230fa7 commit d6a74d6

File tree

1 file changed

+72
-0
lines changed

1 file changed

+72
-0
lines changed

twitchio/client.py

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,7 @@ async def login_dcf(
436436
scopes: Scopes | None = None,
437437
force_flow: bool = False,
438438
) -> DeviceCodeFlowResponse | None:
439+
# TODO: Docs...
439440
if self._login_called:
440441
return
441442

@@ -465,7 +466,70 @@ async def start_dcf(
465466
interval: int = 5,
466467
timeout: int | None = 90,
467468
scopes: Scopes | None = None,
469+
block: bool = True,
468470
) -> None:
471+
"""|coro|
472+
473+
.. warning::
474+
475+
DCF is intended to be used when your application cannot safely store a ``client-secret``. E.g. on a users
476+
device (phone, tv, etc...).
477+
478+
479+
.. note::
480+
481+
The :meth:`.login_dcf` method must be called before this method. :meth:`.login_dcf` provides a response payload
482+
and other useful data that can be used with :meth:`.start_dcf`.
483+
484+
485+
Method to start the :class:`~twitchio.Client` with DCF (Device Code Flow).
486+
487+
Unlike :meth:`.start` this method must be called after :meth:`.login_dcf` and does not directly call this method
488+
itself.
489+
490+
Unlike :meth:`.start` this method can be used to run the :class:`~twitchio.Client` with or without asynchronous
491+
blocking behaviours. However due to the design of ``DCF`` the :meth:`.login_dcf` method must still be called first.
492+
493+
When the ``device_code`` parameter is ``None`` (default), this method will not wait for an authorization response
494+
from Twitch. However, a token must be loaded prior to this method being called
495+
(usually automatically in :meth:`.login_dcf`), else a :exc:`RuntimeError` will be raised.
496+
497+
Parameters
498+
----------
499+
device_code: :class:`str` | ``None``
500+
The device code received as a response from :meth:`.login_dcf`. If :meth:`.login_dcf` loaded a saved token, you
501+
can safely disregard this parameter, unless you are forcing a user to reauthenticate.
502+
interval: :class:`int`
503+
An :class:`int` as seconds, passed to determine how long we should wait before checking the users authentication
504+
status in the DCF. This can be changed however the provided interval in the response from :meth:`.login_dcf` is
505+
usually preferred. Defaults to ``5``.
506+
timeout: :class:`int` | ``None``
507+
An :class:`int` as seconds before this method will timeout waiting for a user to complete the DCF. Could be
508+
``None`` to disable timeout. Defaults to ``90``. If a timeout occurs a :exc:`TimeoutError` will be raised.
509+
scopes: :class:`~twitchio.Scopes` | ``None``
510+
A :class:`~twitchio.Scopes` that will be granted by the user during the DCF. This should be the same scopes passed
511+
to :meth:`.login_dcf`. If scopes are assigned or passed to the :class:`~twitchio.Client` you do not need to pass
512+
scopes here or in :meth:`.login_dcf`. Defaults to ``None`` which means you would need to pass scopes to the client.
513+
block: :class:`bool`
514+
A bool indicating whether to run the :class:`~twitchio.Client` in a asynchronously blocking loop. This is the
515+
default and same behaviour as :meth:`.start`. When set to ``False``, your :class:`~twitchio.Client` will be logged
516+
in and can be used standalone. Defaults to ``True``.
517+
518+
Raises
519+
------
520+
RuntimeError
521+
:meth:`.login_dcf` must be called before this method.
522+
RuntimeError
523+
A token and refresh pair must be loaded prior to calling this method, or you must pass the ``device_code`` parameter.
524+
RuntimeError
525+
A valid :class:`~twitchio.User` could not be fetched with the token received.
526+
DeviceCodeFlowException
527+
...
528+
HTTPException
529+
...
530+
TimeoutError
531+
...
532+
"""
469533
if not self._login_called:
470534
raise RuntimeError('Client failed to start: "login_dcf" must be called before "start_dcf".')
471535

@@ -493,16 +557,24 @@ async def start_dcf(
493557
)
494558

495559
validated = await self.add_token(token=token, refresh=refresh)
560+
561+
# Technically a User Token, however this will allow similar default behaviours since DCF should be bound to a
562+
# ...single user.
496563
self._http._app_token = token
497564

498565
user = await self.fetch_user(id=validated.user_id)
499566
if not user:
500567
raise RuntimeError("Unable to fetch associated user with DCF token.")
501568

502569
self._bot_id = user.id
570+
571+
# Event Ready will act more similarly to setup_hook with DCF setups since we have to wait for the user to respond
503572
self.dispatch("ready")
504573
self._ready_event.set()
505574

575+
if not block:
576+
return
577+
506578
try:
507579
await self.__waiter.wait()
508580
finally:

0 commit comments

Comments
 (0)