@@ -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