From fe828534a79a471cc38c52bde25c576a23e0049e Mon Sep 17 00:00:00 2001 From: Bart Moorman Date: Mon, 3 Mar 2025 17:01:56 -0700 Subject: [PATCH 1/6] Refresh token if it will likely expire before the next validation --- twitchio/authentication/tokens.py | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/twitchio/authentication/tokens.py b/twitchio/authentication/tokens.py index 18cfa3f3..eb1f8b92 100644 --- a/twitchio/authentication/tokens.py +++ b/twitchio/authentication/tokens.py @@ -91,8 +91,6 @@ def __init__( self._validate_task: asyncio.Task[None] | None = None async def _attempt_refresh_on_add(self, token: str, refresh: str) -> ValidateTokenPayload: - logger.debug("Token was invalid when attempting to add it to the token manager. Attempting to refresh.") - try: resp: RefreshTokenPayload = await self.__isolated.refresh_token(refresh) except HTTPException as e: @@ -132,6 +130,7 @@ async def add_token(self, token: str, refresh: str) -> ValidateTokenPayload: msg: str = "Token was invalid. Please check the token or re-authenticate user with a new token." raise InvalidTokenException(msg, token=token, refresh=refresh, type_="token", original=e) + logger.debug("Token was invalid when attempting to add it to the token manager. Attempting to refresh.") return await self._attempt_refresh_on_add(token, refresh) if not resp.login or not resp.user_id: @@ -140,6 +139,10 @@ async def add_token(self, token: str, refresh: str) -> ValidateTokenPayload: return resp + if resp.expires_in <= 3600: + logger.debug("Token expires in %s seconds. Attempting to refresh.", resp.expires_in) + return await self._attempt_refresh_on_add(token, refresh) + self._tokens[resp.user_id] = { "user_id": resp.user_id, "token": token, @@ -268,13 +271,14 @@ async def _revalidate_all(self) -> None: logger.debug('Token for "%s" was invalid or expired. Attempting to refresh token.', user_id) await self._refresh_token(user_id, refresh) else: - self._tokens[user_id]["last_validated"] = datetime.datetime.now().isoformat() - - expires_in: int = valid_resp["expires_in"] - if expires_in <= 300: - logger.debug('Token for "%s" expires in %s seconds. Attempting to refresh token.', user_id, expires_in) + if valid_resp.expires_in <= 3600: + logger.debug( + 'Token for "%s" expires in %s seconds. Attempting to refresh token.', user_id, valid_resp.expires_in + ) await self._refresh_token(user_id, refresh) + else: + self._tokens[user_id]["last_validated"] = datetime.datetime.now().isoformat() async def __validate_loop(self) -> None: logger.debug("Started the token validation loop on %s.", self.__class__.__qualname__) From 8ee4dd1f6353d0836bf8bc2ee0d2959667bed315 Mon Sep 17 00:00:00 2001 From: Bart Moorman Date: Mon, 17 Mar 2025 19:56:40 -0600 Subject: [PATCH 2/6] Fix linting with newer version of ruff --- twitchio/eventsub/websockets.py | 32 +++++++++++++++---------------- twitchio/models/eventsub_.py | 4 ++-- twitchio/utils.py | 2 +- twitchio/web/aio_adapter.py | 4 ++-- twitchio/web/starlette_adapter.py | 4 ++-- 5 files changed, 23 insertions(+), 23 deletions(-) diff --git a/twitchio/eventsub/websockets.py b/twitchio/eventsub/websockets.py index 234c5a3c..d013b408 100644 --- a/twitchio/eventsub/websockets.py +++ b/twitchio/eventsub/websockets.py @@ -34,16 +34,6 @@ from ..backoff import Backoff from ..exceptions import HTTPException, WebsocketConnectionException from ..models.eventsub_ import SubscriptionRevoked, create_event_instance -from ..types_.conduits import ( - MessageTypes, - MetaData, - NotificationMessage, - ReconnectMessage, - RevocationMessage, - WebsocketMessages, - WelcomeMessage, - WelcomePayload, -) from ..utils import ( MISSING, _from_json, # type: ignore @@ -54,7 +44,17 @@ if TYPE_CHECKING: from ..authentication.tokens import ManagedHTTPClient from ..client import Client - from ..types_.conduits import Condition + from ..types_.conduits import ( + Condition, + MessageTypes, + MetaData, + NotificationMessage, + ReconnectMessage, + RevocationMessage, + WebsocketMessages, + WelcomeMessage, + WelcomePayload, + ) from ..types_.eventsub import SubscriptionResponse, _SubscriptionData @@ -327,7 +327,7 @@ async def _listen(self) -> None: self._last_keepalive = datetime.datetime.now() try: - data: WebsocketMessages = cast(WebsocketMessages, _from_json(message.data)) + data: WebsocketMessages = cast("WebsocketMessages", _from_json(message.data)) except Exception: logger.warning("Unable to parse JSON in eventsub websocket: <%s>", self) continue @@ -336,13 +336,13 @@ async def _listen(self) -> None: message_type: MessageTypes = metadata["message_type"] if message_type == "session_welcome": - welcome_data: WelcomeMessage = cast(WelcomeMessage, data) + welcome_data: WelcomeMessage = cast("WelcomeMessage", data) await self._process_welcome(welcome_data) elif message_type == "session_reconnect": logger.debug('Received "session_reconnect" message from eventsub websocket: <%s>', self) - reconnect_data: ReconnectMessage = cast(ReconnectMessage, data) + reconnect_data: ReconnectMessage = cast("ReconnectMessage", data) await self._process_reconnect(reconnect_data) @@ -352,12 +352,12 @@ async def _listen(self) -> None: elif message_type == "revocation": logger.debug('Received "revocation" message from eventsub websocket: <%s>', self) - revocation_data: RevocationMessage = cast(RevocationMessage, data) + revocation_data: RevocationMessage = cast("RevocationMessage", data) await self._process_revocation(revocation_data) elif message_type == "notification": logger.debug('Received "notification" message from eventsub websocket: <%s>. %s', self, data) - notification_data: NotificationMessage = cast(NotificationMessage, data) + notification_data: NotificationMessage = cast("NotificationMessage", data) try: await self._process_notification(notification_data) diff --git a/twitchio/models/eventsub_.py b/twitchio/models/eventsub_.py index 3ac5f11e..046daf46 100644 --- a/twitchio/models/eventsub_.py +++ b/twitchio/models/eventsub_.py @@ -3575,7 +3575,7 @@ async def fulfill(self, *, token_for: str | PartialUser) -> CustomRewardRedempti reward_id=self.reward.id, status="FULFILLED", ) - reward = cast(CustomReward, self.reward) + reward = cast("CustomReward", self.reward) return CustomRewardRedemption(data["data"][0], parent_reward=reward, http=self._http) async def refund(self, *, token_for: str | PartialUser) -> CustomRewardRedemption: @@ -3604,7 +3604,7 @@ async def refund(self, *, token_for: str | PartialUser) -> CustomRewardRedemptio reward_id=self.reward.id, status="CANCELED", ) - reward = cast(CustomReward, self.reward) + reward = cast("CustomReward", self.reward) return CustomRewardRedemption(data["data"][0], parent_reward=reward, http=self._http) diff --git a/twitchio/utils.py b/twitchio/utils.py index d4ca75ee..6b3cdc3d 100644 --- a/twitchio/utils.py +++ b/twitchio/utils.py @@ -929,7 +929,7 @@ def wrapper(*args: Any, **kwargs: Any) -> Any: return func(*new_args, **new_kwargs) - return cast(F, wrapper) + return cast("F", wrapper) return decorator diff --git a/twitchio/web/aio_adapter.py b/twitchio/web/aio_adapter.py index 1d54ece0..f60078e0 100644 --- a/twitchio/web/aio_adapter.py +++ b/twitchio/web/aio_adapter.py @@ -37,7 +37,6 @@ from ..eventsub.subscriptions import _SUB_MAPPING from ..exceptions import HTTPException from ..models.eventsub_ import SubscriptionRevoked, create_event_instance -from ..types_.eventsub import EventSubHeaders from ..utils import _from_json, parse_timestamp # type: ignore from .utils import MESSAGE_TYPES, BaseAdapter, FetchTokenPayload, verify_message @@ -47,6 +46,7 @@ from ..authentication import AuthorizationURLPayload, UserTokenPayload from ..client import Client + from ..types_.eventsub import EventSubHeaders __all__ = ("AiohttpAdapter",) @@ -221,7 +221,7 @@ async def run(self, host: str | None = None, port: int | None = None) -> None: self._runner_task = asyncio.create_task(site.start(), name=f"twitchio-web-adapter:{self.__class__.__qualname__}") async def eventsub_callback(self, request: web.Request) -> web.Response: - headers: EventSubHeaders = cast(EventSubHeaders, request.headers) + headers: EventSubHeaders = cast("EventSubHeaders", request.headers) msg_type: str | None = headers.get("Twitch-Eventsub-Message-Type") if not msg_type or msg_type not in MESSAGE_TYPES: diff --git a/twitchio/web/starlette_adapter.py b/twitchio/web/starlette_adapter.py index d85e188b..49f79cf8 100644 --- a/twitchio/web/starlette_adapter.py +++ b/twitchio/web/starlette_adapter.py @@ -40,7 +40,6 @@ from ..eventsub.subscriptions import _SUB_MAPPING from ..exceptions import HTTPException from ..models.eventsub_ import SubscriptionRevoked, create_event_instance -from ..types_.eventsub import EventSubHeaders from ..utils import _from_json, parse_timestamp # type: ignore from .utils import MESSAGE_TYPES, BaseAdapter, FetchTokenPayload, verify_message @@ -50,6 +49,7 @@ from ..authentication import AuthorizationURLPayload, UserTokenPayload from ..client import Client + from ..types_.eventsub import EventSubHeaders __all__ = ("StarletteAdapter",) @@ -226,7 +226,7 @@ async def run(self, host: str | None = None, port: int | None = None) -> None: self._runner_task = asyncio.create_task(server.serve(), name=f"twitchio-web-adapter:{self.__class__.__qualname__}") async def eventsub_callback(self, request: Request) -> Response: - headers: EventSubHeaders = cast(EventSubHeaders, request.headers) + headers: EventSubHeaders = cast("EventSubHeaders", request.headers) msg_type: str | None = headers.get("Twitch-Eventsub-Message-Type") if not msg_type or msg_type not in MESSAGE_TYPES: From 1a489795260a7bed985f40dbba42ec927c6e6148 Mon Sep 17 00:00:00 2001 From: Bart Moorman Date: Mon, 17 Mar 2025 19:59:23 -0600 Subject: [PATCH 3/6] Add channel.shared_chat.* to SubscriptionType enum --- twitchio/eventsub/enums.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/twitchio/eventsub/enums.py b/twitchio/eventsub/enums.py index d926ae88..6a5283ec 100644 --- a/twitchio/eventsub/enums.py +++ b/twitchio/eventsub/enums.py @@ -107,6 +107,9 @@ class SubscriptionType(enum.Enum): ChannelChatSettingsUpdate: Literal["channel.chat_settings.update"] ChannelChatUserMessageHold: Literal["channel.chat.user_message_hold"] ChannelChatUserMessageUpdate: Literal["channel.chat.user_message_update"] + ChannelSharedChatBegin: Literal["channel.shared_chat.begin"] + ChannelSharedChatUpdate: Literal["channel.shared_chat.update"] + ChannelSharedChatEnd: Literal["channel.shared_chat.end"] ChannelSubscribe: Literal["channel.subscribe"] ChannelSubscriptionEnd: Literal["channel.subscription.end"] ChannelSubscriptionGift: Literal["channel.subscription.gift"] @@ -183,6 +186,9 @@ class SubscriptionType(enum.Enum): ChannelChatSettingsUpdate = "channel.chat_settings.update" ChannelChatUserMessageHold = "channel.chat.user_message_hold" ChannelChatUserMessageUpdate = "channel.chat.user_message_update" + ChannelSharedChatBegin = "channel.shared_chat.begin" + ChannelSharedChatUpdate = "channel.shared_chat.update" + ChannelSharedChatEnd = "channel.shared_chat.end" ChannelSubscribe = "channel.subscribe" ChannelSubscriptionEnd = "channel.subscription.end" ChannelSubscriptionGift = "channel.subscription.gift" From ea53847ff6ddd2b769d9dff12059e5a529d07ba1 Mon Sep 17 00:00:00 2001 From: Bart Moorman Date: Mon, 17 Mar 2025 20:37:41 -0600 Subject: [PATCH 4/6] Add missing scopes and alphabetize --- twitchio/authentication/scopes.py | 117 ++++++++++++++++-------------- 1 file changed, 64 insertions(+), 53 deletions(-) diff --git a/twitchio/authentication/scopes.py b/twitchio/authentication/scopes.py index 2af22b94..40ffadd1 100644 --- a/twitchio/authentication/scopes.py +++ b/twitchio/authentication/scopes.py @@ -104,6 +104,8 @@ class Scopes(metaclass=_ScopeMeta): Equivalent to the ``analytics:read:games`` scope on Twitch. bits_read Equivalent to the ``bits:read`` scope on Twitch. + channel_bot + Equivalent to the ``channel:bot`` scope on Twitch. channel_manage_ads Equivalent to the ``channel:manage:ads`` scope on Twitch. channel_read_ads @@ -121,11 +123,11 @@ class Scopes(metaclass=_ScopeMeta): channel_read_goals Equivalent to the ``channel:read:goals`` scope on Twitch. channel_read_guest_star - Equivalent to the ``channel:read:guest:star`` scope on Twitch. + Equivalent to the ``channel:read:guest_star`` scope on Twitch. channel_manage_guest_star - Equivalent to the ``channel:manage:guest:star`` scope on Twitch. + Equivalent to the ``channel:manage:guest_star`` scope on Twitch. channel_read_hype_train - Equivalent to the ``channel:read:hype:train`` scope on Twitch. + Equivalent to the ``channel:read:hype_train`` scope on Twitch. channel_manage_moderators Equivalent to the ``channel:manage:moderators`` scope on Twitch. channel_read_polls @@ -145,7 +147,7 @@ class Scopes(metaclass=_ScopeMeta): channel_manage_schedule Equivalent to the ``channel:manage:schedule`` scope on Twitch. channel_read_stream_key - Equivalent to the ``channel:read:stream:key`` scope on Twitch. + Equivalent to the ``channel:read:stream_key`` scope on Twitch. channel_read_subscriptions Equivalent to the ``channel:read:subscriptions`` scope on Twitch. channel_manage_videos @@ -154,6 +156,8 @@ class Scopes(metaclass=_ScopeMeta): Equivalent to the ``channel:read:vips`` scope on Twitch. channel_manage_vips Equivalent to the ``channel:manage:vips`` scope on Twitch. + channel_moderate + Equivalent to the ``channel:moderate`` scope on Twitch. clips_edit Equivalent to the ``clips:edit`` scope on Twitch. moderation_read @@ -163,89 +167,93 @@ class Scopes(metaclass=_ScopeMeta): moderator_manage_automod Equivalent to the ``moderator:manage:automod`` scope on Twitch. moderator_read_automod_settings - Equivalent to the ``moderator:read:automod:settings`` scope on Twitch. + Equivalent to the ``moderator:read:automod_settings`` scope on Twitch. moderator_manage_automod_settings - Equivalent to the ``moderator:manage:automod:settings`` scope on Twitch. + Equivalent to the ``moderator:manage:automod_settings`` scope on Twitch. + moderator_read_banned_users + Equivalent to the ``moderator:read:banned_users`` scope on Twitch. moderator_manage_banned_users - Equivalent to the ``moderator:manage:banned:users`` scope on Twitch. + Equivalent to the ``moderator:manage:banned_users`` scope on Twitch. moderator_read_blocked_terms - Equivalent to the ``moderator:read:blocked:terms`` scope on Twitch. + Equivalent to the ``moderator:read:blocked_terms`` scope on Twitch. + moderator_read_chat_messages + Equivalent to the ``moderator:read:chat_messages`` scope on Twitch. moderator_manage_blocked_terms - Equivalent to the ``moderator:manage:blocked:terms`` scope on Twitch. + Equivalent to the ``moderator:manage:blocked_terms`` scope on Twitch. moderator_manage_chat_messages - Equivalent to the ``moderator:manage:chat:messages`` scope on Twitch. + Equivalent to the ``moderator:manage:chat_messages`` scope on Twitch. moderator_read_chat_settings - Equivalent to the ``moderator:read:chat:settings`` scope on Twitch. + Equivalent to the ``moderator:read:chat_settings`` scope on Twitch. moderator_manage_chat_settings - Equivalent to the ``moderator:manage:chat:settings`` scope on Twitch. + Equivalent to the ``moderator:manage:chat_settings`` scope on Twitch. moderator_read_chatters Equivalent to the ``moderator:read:chatters`` scope on Twitch. moderator_read_followers Equivalent to the ``moderator:read:followers`` scope on Twitch. moderator_read_guest_star - Equivalent to the ``moderator:read:guest:star`` scope on Twitch. + Equivalent to the ``moderator:read:guest_star`` scope on Twitch. moderator_manage_guest_star - Equivalent to the ``moderator:manage:guest:star`` scope on Twitch. + Equivalent to the ``moderator:manage:guest_star`` scope on Twitch. + moderator_read_moderators + Equivalent to the ``moderator:read:moderators`` scope on Twitch. moderator_read_shield_mode - Equivalent to the ``moderator:read:shield:mode`` scope on Twitch. + Equivalent to the ``moderator:read:shield_mode`` scope on Twitch. moderator_manage_shield_mode - Equivalent to the ``moderator:manage:shield:mode`` scope on Twitch. + Equivalent to the ``moderator:manage:shield_mode`` scope on Twitch. moderator_read_shoutouts Equivalent to the ``moderator:read:shoutouts`` scope on Twitch. moderator_manage_shoutouts Equivalent to the ``moderator:manage:shoutouts`` scope on Twitch. + moderator_read_suspicious_users + Equivalent to the ``moderator:read:suspicious_users`` scope on Twitch. moderator_read_unban_requests - Equivalent to the ``moderator:read:unban:requests`` scope on Twitch. + Equivalent to the ``moderator:read:unban_requests`` scope on Twitch. moderator_manage_unban_requests - Equivalent to the ``moderator:manage:unban:requests`` scope on Twitch. + Equivalent to the ``moderator:manage:unban_requests`` scope on Twitch. + moderator_read_vips + Equivalent to the ``moderator:read:vips`` scope on Twitch. moderator_read_warnings Equivalent to the ``moderator:read:warnings`` scope on Twitch. moderator_manage_warnings Equivalent to the ``moderator:manage:warnings`` scope on Twitch. - moderator_read_moderators - Equivalent to the ``moderator:read:moderators`` scope on Twitch. - moderator_read_vips - Equivalent to the ``moderator:read:vips`` scope on Twitch. + user_bot + Equivalent to the ``user:bot`` scope on Twitch. user_edit Equivalent to the ``user:edit`` scope on Twitch. - user_edit_follows - Equivalent to the ``user:edit:follows`` scope on Twitch. + user_edit_broadcast + Equivalent to the ``user:edit:broadcast`` scope on Twitch. user_read_blocked_users - Equivalent to the ``user:read:blocked:users`` scope on Twitch. + Equivalent to the ``user:read:blocked_users`` scope on Twitch. user_manage_blocked_users - Equivalent to the ``user:manage:blocked:users`` scope on Twitch. + Equivalent to the ``user:manage:blocked_users`` scope on Twitch. user_read_broadcast Equivalent to the ``user:read:broadcast`` scope on Twitch. + user_read_chat + Equivalent to the ``user:read:chat`` scope on Twitch. user_manage_chat_color - Equivalent to the ``user:manage:chat:color`` scope on Twitch. + Equivalent to the ``user:manage:chat_color`` scope on Twitch. user_read_email Equivalent to the ``user:read:email`` scope on Twitch. + user_read_emotes + Equivalent to the ``user:read:emotes`` scope on Twitch. user_read_follows Equivalent to the ``user:read:follows`` scope on Twitch. user_read_moderated_channels - Equivalent to the ``user:read:moderated:channels`` scope on Twitch. + Equivalent to the ``user:read:moderated_channels`` scope on Twitch. user_read_subscriptions Equivalent to the ``user:read:subscriptions`` scope on Twitch. - user_read_emotes - Equivalent to the ``user:read:emotes`` scope on Twitch. - user_manage_whispers - Equivalent to the ``user:manage:whispers`` scope on Twitch. user_read_whispers Equivalent to the ``user:read:whispers`` scope on Twitch. - channel_bot - Equivalent to the ``channel:bot`` scope on Twitch. - channel_moderate - Equivalent to the ``channel:moderate`` scope on Twitch. + user_manage_whispers + Equivalent to the ``user:manage:whispers`` scope on Twitch. + user_write_chat + Equivalent to the ``user:write:chat`` scope on Twitch. chat_edit Equivalent to the ``chat:edit`` scope on Twitch. chat_read Equivalent to the ``chat:read`` scope on Twitch. - user_bot - Equivalent to the ``user:bot`` scope on Twitch. - user_read_chat - Equivalent to the ``user:read:chat`` scope on Twitch. - user_write_chat - Equivalent to the ``user:write:chat`` scope on Twitch. + user_edit_follows + Equivalent to the ``user:edit:follows`` scope on Twitch. whispers_read Equivalent to the ``whispers:read`` scope on Twitch. whispers_edit @@ -257,6 +265,7 @@ class Scopes(metaclass=_ScopeMeta): analytics_read_extensions = _scope_property() analytics_read_games = _scope_property() bits_read = _scope_property() + channel_bot = _scope_property() channel_manage_ads = _scope_property() channel_read_ads = _scope_property() channel_manage_broadcast = _scope_property() @@ -282,14 +291,17 @@ class Scopes(metaclass=_ScopeMeta): channel_manage_videos = _scope_property() channel_read_vips = _scope_property() channel_manage_vips = _scope_property() + channel_moderate = _scope_property() clips_edit = _scope_property() moderation_read = _scope_property() moderator_manage_announcements = _scope_property() moderator_manage_automod = _scope_property() moderator_read_automod_settings = _scope_property() moderator_manage_automod_settings = _scope_property() + moderator_read_banned_users = _scope_property() moderator_manage_banned_users = _scope_property() moderator_read_blocked_terms = _scope_property() + moderator_read_chat_messages = _scope_property() moderator_manage_blocked_terms = _scope_property() moderator_manage_chat_messages = _scope_property() moderator_read_chat_settings = _scope_property() @@ -298,37 +310,36 @@ class Scopes(metaclass=_ScopeMeta): moderator_read_followers = _scope_property() moderator_read_guest_star = _scope_property() moderator_manage_guest_star = _scope_property() + moderator_read_moderators = _scope_property() moderator_read_shield_mode = _scope_property() moderator_manage_shield_mode = _scope_property() moderator_read_shoutouts = _scope_property() moderator_manage_shoutouts = _scope_property() + moderator_read_suspicious_users = _scope_property() moderator_read_unban_requests = _scope_property() moderator_manage_unban_requests = _scope_property() + moderator_read_vips = _scope_property() moderator_read_warnings = _scope_property() moderator_manage_warnings = _scope_property() - moderator_read_moderators = _scope_property() - moderator_read_vips = _scope_property() - user_edit_broadcast = _scope_property() + user_bot = _scope_property() user_edit = _scope_property() - user_edit_follows = _scope_property() + user_edit_broadcast = _scope_property() user_read_blocked_users = _scope_property() user_manage_blocked_users = _scope_property() user_read_broadcast = _scope_property() + user_read_chat = _scope_property() user_manage_chat_color = _scope_property() user_read_email = _scope_property() + user_read_emotes = _scope_property() user_read_follows = _scope_property() user_read_moderated_channels = _scope_property() user_read_subscriptions = _scope_property() - user_read_emotes = _scope_property() - user_manage_whispers = _scope_property() user_read_whispers = _scope_property() - channel_bot = _scope_property() - channel_moderate = _scope_property() + user_manage_whispers = _scope_property() + user_write_chat = _scope_property() chat_edit = _scope_property() chat_read = _scope_property() - user_bot = _scope_property() - user_read_chat = _scope_property() - user_write_chat = _scope_property() + user_edit_follows = _scope_property() whispers_read = _scope_property() whispers_edit = _scope_property() From 3e35d4c6a686740d198852a50ae6bfd834bad6e5 Mon Sep 17 00:00:00 2001 From: Bart Moorman Date: Sat, 22 Mar 2025 02:42:59 -0600 Subject: [PATCH 5/6] Ruff is angry - make it happy again --- twitchio/authentication/tokens.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/twitchio/authentication/tokens.py b/twitchio/authentication/tokens.py index 7d02e7ca..2d59b436 100644 --- a/twitchio/authentication/tokens.py +++ b/twitchio/authentication/tokens.py @@ -32,24 +32,22 @@ import aiohttp -from twitchio.http import Route -from twitchio.types_.responses import RawResponse - from ..backoff import Backoff from ..exceptions import HTTPException, InvalidTokenException from ..http import HTTPAsyncIterator, PaginatedConverter from ..payloads import TokenRefreshedPayload -from ..types_.tokens import TokenMappingData from ..utils import MISSING from .oauth import OAuth -from .payloads import ClientCredentialsPayload, ValidateTokenPayload from .scopes import Scopes if TYPE_CHECKING: + from twitchio.http import Route + from twitchio.types_.responses import RawResponse + from ..client import Client - from ..types_.tokens import TokenMapping, _TokenRefreshedPayload - from .payloads import RefreshTokenPayload + from ..types_.tokens import TokenMapping, TokenMappingData, _TokenRefreshedPayload + from .payloads import ClientCredentialsPayload, RefreshTokenPayload, ValidateTokenPayload logger: logging.Logger = logging.getLogger(__name__) From df5855986749eabf94765bd0fbe35dc4afd4be3f Mon Sep 17 00:00:00 2001 From: Bart Moorman Date: Sat, 22 Mar 2025 04:26:30 -0600 Subject: [PATCH 6/6] Continue instead of else --- twitchio/authentication/tokens.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/twitchio/authentication/tokens.py b/twitchio/authentication/tokens.py index 2d59b436..0958ca2f 100644 --- a/twitchio/authentication/tokens.py +++ b/twitchio/authentication/tokens.py @@ -299,8 +299,9 @@ async def _revalidate_all(self) -> None: ) await self._refresh_token(user_id, refresh) - else: - self._tokens[user_id]["last_validated"] = datetime.datetime.now().isoformat() + continue + + self._tokens[user_id]["last_validated"] = datetime.datetime.now().isoformat() async def __validate_loop(self) -> None: logger.debug("Started the token validation loop on %s.", self.__class__.__qualname__)