Skip to content

Commit 72fa2df

Browse files
authored
Refresh token if it will likely expire before the next validation (#487)
* Refresh token if it will likely expire before the next validation * Fix linting with newer version of ruff * Add channel.shared_chat.* to SubscriptionType enum * Add missing scopes and alphabetize * Ruff is angry - make it happy again * Continue instead of else
1 parent 52298ee commit 72fa2df

File tree

3 files changed

+87
-67
lines changed

3 files changed

+87
-67
lines changed

twitchio/authentication/scopes.py

Lines changed: 64 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,8 @@ class Scopes(metaclass=_ScopeMeta):
104104
Equivalent to the ``analytics:read:games`` scope on Twitch.
105105
bits_read
106106
Equivalent to the ``bits:read`` scope on Twitch.
107+
channel_bot
108+
Equivalent to the ``channel:bot`` scope on Twitch.
107109
channel_manage_ads
108110
Equivalent to the ``channel:manage:ads`` scope on Twitch.
109111
channel_read_ads
@@ -121,11 +123,11 @@ class Scopes(metaclass=_ScopeMeta):
121123
channel_read_goals
122124
Equivalent to the ``channel:read:goals`` scope on Twitch.
123125
channel_read_guest_star
124-
Equivalent to the ``channel:read:guest:star`` scope on Twitch.
126+
Equivalent to the ``channel:read:guest_star`` scope on Twitch.
125127
channel_manage_guest_star
126-
Equivalent to the ``channel:manage:guest:star`` scope on Twitch.
128+
Equivalent to the ``channel:manage:guest_star`` scope on Twitch.
127129
channel_read_hype_train
128-
Equivalent to the ``channel:read:hype:train`` scope on Twitch.
130+
Equivalent to the ``channel:read:hype_train`` scope on Twitch.
129131
channel_manage_moderators
130132
Equivalent to the ``channel:manage:moderators`` scope on Twitch.
131133
channel_read_polls
@@ -145,7 +147,7 @@ class Scopes(metaclass=_ScopeMeta):
145147
channel_manage_schedule
146148
Equivalent to the ``channel:manage:schedule`` scope on Twitch.
147149
channel_read_stream_key
148-
Equivalent to the ``channel:read:stream:key`` scope on Twitch.
150+
Equivalent to the ``channel:read:stream_key`` scope on Twitch.
149151
channel_read_subscriptions
150152
Equivalent to the ``channel:read:subscriptions`` scope on Twitch.
151153
channel_manage_videos
@@ -154,6 +156,8 @@ class Scopes(metaclass=_ScopeMeta):
154156
Equivalent to the ``channel:read:vips`` scope on Twitch.
155157
channel_manage_vips
156158
Equivalent to the ``channel:manage:vips`` scope on Twitch.
159+
channel_moderate
160+
Equivalent to the ``channel:moderate`` scope on Twitch.
157161
clips_edit
158162
Equivalent to the ``clips:edit`` scope on Twitch.
159163
moderation_read
@@ -163,89 +167,93 @@ class Scopes(metaclass=_ScopeMeta):
163167
moderator_manage_automod
164168
Equivalent to the ``moderator:manage:automod`` scope on Twitch.
165169
moderator_read_automod_settings
166-
Equivalent to the ``moderator:read:automod:settings`` scope on Twitch.
170+
Equivalent to the ``moderator:read:automod_settings`` scope on Twitch.
167171
moderator_manage_automod_settings
168-
Equivalent to the ``moderator:manage:automod:settings`` scope on Twitch.
172+
Equivalent to the ``moderator:manage:automod_settings`` scope on Twitch.
173+
moderator_read_banned_users
174+
Equivalent to the ``moderator:read:banned_users`` scope on Twitch.
169175
moderator_manage_banned_users
170-
Equivalent to the ``moderator:manage:banned:users`` scope on Twitch.
176+
Equivalent to the ``moderator:manage:banned_users`` scope on Twitch.
171177
moderator_read_blocked_terms
172-
Equivalent to the ``moderator:read:blocked:terms`` scope on Twitch.
178+
Equivalent to the ``moderator:read:blocked_terms`` scope on Twitch.
179+
moderator_read_chat_messages
180+
Equivalent to the ``moderator:read:chat_messages`` scope on Twitch.
173181
moderator_manage_blocked_terms
174-
Equivalent to the ``moderator:manage:blocked:terms`` scope on Twitch.
182+
Equivalent to the ``moderator:manage:blocked_terms`` scope on Twitch.
175183
moderator_manage_chat_messages
176-
Equivalent to the ``moderator:manage:chat:messages`` scope on Twitch.
184+
Equivalent to the ``moderator:manage:chat_messages`` scope on Twitch.
177185
moderator_read_chat_settings
178-
Equivalent to the ``moderator:read:chat:settings`` scope on Twitch.
186+
Equivalent to the ``moderator:read:chat_settings`` scope on Twitch.
179187
moderator_manage_chat_settings
180-
Equivalent to the ``moderator:manage:chat:settings`` scope on Twitch.
188+
Equivalent to the ``moderator:manage:chat_settings`` scope on Twitch.
181189
moderator_read_chatters
182190
Equivalent to the ``moderator:read:chatters`` scope on Twitch.
183191
moderator_read_followers
184192
Equivalent to the ``moderator:read:followers`` scope on Twitch.
185193
moderator_read_guest_star
186-
Equivalent to the ``moderator:read:guest:star`` scope on Twitch.
194+
Equivalent to the ``moderator:read:guest_star`` scope on Twitch.
187195
moderator_manage_guest_star
188-
Equivalent to the ``moderator:manage:guest:star`` scope on Twitch.
196+
Equivalent to the ``moderator:manage:guest_star`` scope on Twitch.
197+
moderator_read_moderators
198+
Equivalent to the ``moderator:read:moderators`` scope on Twitch.
189199
moderator_read_shield_mode
190-
Equivalent to the ``moderator:read:shield:mode`` scope on Twitch.
200+
Equivalent to the ``moderator:read:shield_mode`` scope on Twitch.
191201
moderator_manage_shield_mode
192-
Equivalent to the ``moderator:manage:shield:mode`` scope on Twitch.
202+
Equivalent to the ``moderator:manage:shield_mode`` scope on Twitch.
193203
moderator_read_shoutouts
194204
Equivalent to the ``moderator:read:shoutouts`` scope on Twitch.
195205
moderator_manage_shoutouts
196206
Equivalent to the ``moderator:manage:shoutouts`` scope on Twitch.
207+
moderator_read_suspicious_users
208+
Equivalent to the ``moderator:read:suspicious_users`` scope on Twitch.
197209
moderator_read_unban_requests
198-
Equivalent to the ``moderator:read:unban:requests`` scope on Twitch.
210+
Equivalent to the ``moderator:read:unban_requests`` scope on Twitch.
199211
moderator_manage_unban_requests
200-
Equivalent to the ``moderator:manage:unban:requests`` scope on Twitch.
212+
Equivalent to the ``moderator:manage:unban_requests`` scope on Twitch.
213+
moderator_read_vips
214+
Equivalent to the ``moderator:read:vips`` scope on Twitch.
201215
moderator_read_warnings
202216
Equivalent to the ``moderator:read:warnings`` scope on Twitch.
203217
moderator_manage_warnings
204218
Equivalent to the ``moderator:manage:warnings`` scope on Twitch.
205-
moderator_read_moderators
206-
Equivalent to the ``moderator:read:moderators`` scope on Twitch.
207-
moderator_read_vips
208-
Equivalent to the ``moderator:read:vips`` scope on Twitch.
219+
user_bot
220+
Equivalent to the ``user:bot`` scope on Twitch.
209221
user_edit
210222
Equivalent to the ``user:edit`` scope on Twitch.
211-
user_edit_follows
212-
Equivalent to the ``user:edit:follows`` scope on Twitch.
223+
user_edit_broadcast
224+
Equivalent to the ``user:edit:broadcast`` scope on Twitch.
213225
user_read_blocked_users
214-
Equivalent to the ``user:read:blocked:users`` scope on Twitch.
226+
Equivalent to the ``user:read:blocked_users`` scope on Twitch.
215227
user_manage_blocked_users
216-
Equivalent to the ``user:manage:blocked:users`` scope on Twitch.
228+
Equivalent to the ``user:manage:blocked_users`` scope on Twitch.
217229
user_read_broadcast
218230
Equivalent to the ``user:read:broadcast`` scope on Twitch.
231+
user_read_chat
232+
Equivalent to the ``user:read:chat`` scope on Twitch.
219233
user_manage_chat_color
220-
Equivalent to the ``user:manage:chat:color`` scope on Twitch.
234+
Equivalent to the ``user:manage:chat_color`` scope on Twitch.
221235
user_read_email
222236
Equivalent to the ``user:read:email`` scope on Twitch.
237+
user_read_emotes
238+
Equivalent to the ``user:read:emotes`` scope on Twitch.
223239
user_read_follows
224240
Equivalent to the ``user:read:follows`` scope on Twitch.
225241
user_read_moderated_channels
226-
Equivalent to the ``user:read:moderated:channels`` scope on Twitch.
242+
Equivalent to the ``user:read:moderated_channels`` scope on Twitch.
227243
user_read_subscriptions
228244
Equivalent to the ``user:read:subscriptions`` scope on Twitch.
229-
user_read_emotes
230-
Equivalent to the ``user:read:emotes`` scope on Twitch.
231-
user_manage_whispers
232-
Equivalent to the ``user:manage:whispers`` scope on Twitch.
233245
user_read_whispers
234246
Equivalent to the ``user:read:whispers`` scope on Twitch.
235-
channel_bot
236-
Equivalent to the ``channel:bot`` scope on Twitch.
237-
channel_moderate
238-
Equivalent to the ``channel:moderate`` scope on Twitch.
247+
user_manage_whispers
248+
Equivalent to the ``user:manage:whispers`` scope on Twitch.
249+
user_write_chat
250+
Equivalent to the ``user:write:chat`` scope on Twitch.
239251
chat_edit
240252
Equivalent to the ``chat:edit`` scope on Twitch.
241253
chat_read
242254
Equivalent to the ``chat:read`` scope on Twitch.
243-
user_bot
244-
Equivalent to the ``user:bot`` scope on Twitch.
245-
user_read_chat
246-
Equivalent to the ``user:read:chat`` scope on Twitch.
247-
user_write_chat
248-
Equivalent to the ``user:write:chat`` scope on Twitch.
255+
user_edit_follows
256+
Equivalent to the ``user:edit:follows`` scope on Twitch.
249257
whispers_read
250258
Equivalent to the ``whispers:read`` scope on Twitch.
251259
whispers_edit
@@ -257,6 +265,7 @@ class Scopes(metaclass=_ScopeMeta):
257265
analytics_read_extensions = _scope_property()
258266
analytics_read_games = _scope_property()
259267
bits_read = _scope_property()
268+
channel_bot = _scope_property()
260269
channel_manage_ads = _scope_property()
261270
channel_read_ads = _scope_property()
262271
channel_manage_broadcast = _scope_property()
@@ -282,14 +291,17 @@ class Scopes(metaclass=_ScopeMeta):
282291
channel_manage_videos = _scope_property()
283292
channel_read_vips = _scope_property()
284293
channel_manage_vips = _scope_property()
294+
channel_moderate = _scope_property()
285295
clips_edit = _scope_property()
286296
moderation_read = _scope_property()
287297
moderator_manage_announcements = _scope_property()
288298
moderator_manage_automod = _scope_property()
289299
moderator_read_automod_settings = _scope_property()
290300
moderator_manage_automod_settings = _scope_property()
301+
moderator_read_banned_users = _scope_property()
291302
moderator_manage_banned_users = _scope_property()
292303
moderator_read_blocked_terms = _scope_property()
304+
moderator_read_chat_messages = _scope_property()
293305
moderator_manage_blocked_terms = _scope_property()
294306
moderator_manage_chat_messages = _scope_property()
295307
moderator_read_chat_settings = _scope_property()
@@ -298,37 +310,36 @@ class Scopes(metaclass=_ScopeMeta):
298310
moderator_read_followers = _scope_property()
299311
moderator_read_guest_star = _scope_property()
300312
moderator_manage_guest_star = _scope_property()
313+
moderator_read_moderators = _scope_property()
301314
moderator_read_shield_mode = _scope_property()
302315
moderator_manage_shield_mode = _scope_property()
303316
moderator_read_shoutouts = _scope_property()
304317
moderator_manage_shoutouts = _scope_property()
318+
moderator_read_suspicious_users = _scope_property()
305319
moderator_read_unban_requests = _scope_property()
306320
moderator_manage_unban_requests = _scope_property()
321+
moderator_read_vips = _scope_property()
307322
moderator_read_warnings = _scope_property()
308323
moderator_manage_warnings = _scope_property()
309-
moderator_read_moderators = _scope_property()
310-
moderator_read_vips = _scope_property()
311-
user_edit_broadcast = _scope_property()
324+
user_bot = _scope_property()
312325
user_edit = _scope_property()
313-
user_edit_follows = _scope_property()
326+
user_edit_broadcast = _scope_property()
314327
user_read_blocked_users = _scope_property()
315328
user_manage_blocked_users = _scope_property()
316329
user_read_broadcast = _scope_property()
330+
user_read_chat = _scope_property()
317331
user_manage_chat_color = _scope_property()
318332
user_read_email = _scope_property()
333+
user_read_emotes = _scope_property()
319334
user_read_follows = _scope_property()
320335
user_read_moderated_channels = _scope_property()
321336
user_read_subscriptions = _scope_property()
322-
user_read_emotes = _scope_property()
323-
user_manage_whispers = _scope_property()
324337
user_read_whispers = _scope_property()
325-
channel_bot = _scope_property()
326-
channel_moderate = _scope_property()
338+
user_manage_whispers = _scope_property()
339+
user_write_chat = _scope_property()
327340
chat_edit = _scope_property()
328341
chat_read = _scope_property()
329-
user_bot = _scope_property()
330-
user_read_chat = _scope_property()
331-
user_write_chat = _scope_property()
342+
user_edit_follows = _scope_property()
332343
whispers_read = _scope_property()
333344
whispers_edit = _scope_property()
334345

twitchio/authentication/tokens.py

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -32,24 +32,22 @@
3232

3333
import aiohttp
3434

35-
from twitchio.http import Route
36-
from twitchio.types_.responses import RawResponse
37-
3835
from ..backoff import Backoff
3936
from ..exceptions import HTTPException, InvalidTokenException
4037
from ..http import HTTPAsyncIterator, PaginatedConverter
4138
from ..payloads import TokenRefreshedPayload
42-
from ..types_.tokens import TokenMappingData
4339
from ..utils import MISSING
4440
from .oauth import OAuth
45-
from .payloads import ClientCredentialsPayload, ValidateTokenPayload
4641
from .scopes import Scopes
4742

4843

4944
if TYPE_CHECKING:
45+
from twitchio.http import Route
46+
from twitchio.types_.responses import RawResponse
47+
5048
from ..client import Client
51-
from ..types_.tokens import TokenMapping, _TokenRefreshedPayload
52-
from .payloads import RefreshTokenPayload
49+
from ..types_.tokens import TokenMapping, TokenMappingData, _TokenRefreshedPayload
50+
from .payloads import ClientCredentialsPayload, RefreshTokenPayload, ValidateTokenPayload
5351

5452

5553
logger: logging.Logger = logging.getLogger(__name__)
@@ -111,8 +109,6 @@ def _dispatch_event(self, user_id: str, payload: RefreshTokenPayload) -> None:
111109
self._client.dispatch("token_refreshed", TokenRefreshedPayload(data=data))
112110

113111
async def _attempt_refresh_on_add(self, token: str, refresh: str) -> ValidateTokenPayload:
114-
logger.debug("Token was invalid when attempting to add it to the token manager. Attempting to refresh.")
115-
116112
try:
117113
resp: RefreshTokenPayload = await self.__isolated.refresh_token(refresh)
118114
except HTTPException as e:
@@ -153,6 +149,7 @@ async def add_token(self, token: str, refresh: str) -> ValidateTokenPayload:
153149
msg: str = "Token was invalid. Please check the token or re-authenticate user with a new token."
154150
raise InvalidTokenException(msg, token=token, refresh=refresh, type_="token", original=e)
155151

152+
logger.debug("Token was invalid when attempting to add it to the token manager. Attempting to refresh.")
156153
return await self._attempt_refresh_on_add(token, refresh)
157154

158155
if not resp.login or not resp.user_id:
@@ -161,6 +158,10 @@ async def add_token(self, token: str, refresh: str) -> ValidateTokenPayload:
161158

162159
return resp
163160

161+
if resp.expires_in <= 3600:
162+
logger.debug("Token expires in %s seconds. Attempting to refresh.", resp.expires_in)
163+
return await self._attempt_refresh_on_add(token, refresh)
164+
164165
self._tokens[resp.user_id] = {
165166
"user_id": resp.user_id,
166167
"token": token,
@@ -292,13 +293,15 @@ async def _revalidate_all(self) -> None:
292293
logger.debug('Token for "%s" was invalid or expired. Attempting to refresh token.', user_id)
293294
await self._refresh_token(user_id, refresh)
294295
else:
295-
self._tokens[user_id]["last_validated"] = datetime.datetime.now().isoformat()
296-
297-
expires_in: int = valid_resp["expires_in"]
298-
if expires_in <= 300:
299-
logger.debug('Token for "%s" expires in %s seconds. Attempting to refresh token.', user_id, expires_in)
296+
if valid_resp.expires_in <= 3600:
297+
logger.debug(
298+
'Token for "%s" expires in %s seconds. Attempting to refresh token.', user_id, valid_resp.expires_in
299+
)
300300

301301
await self._refresh_token(user_id, refresh)
302+
continue
303+
304+
self._tokens[user_id]["last_validated"] = datetime.datetime.now().isoformat()
302305

303306
async def __validate_loop(self) -> None:
304307
logger.debug("Started the token validation loop on %s.", self.__class__.__qualname__)

twitchio/eventsub/enums.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,9 @@ class SubscriptionType(enum.Enum):
108108
ChannelChatSettingsUpdate: Literal["channel.chat_settings.update"]
109109
ChannelChatUserMessageHold: Literal["channel.chat.user_message_hold"]
110110
ChannelChatUserMessageUpdate: Literal["channel.chat.user_message_update"]
111+
ChannelSharedChatBegin: Literal["channel.shared_chat.begin"]
112+
ChannelSharedChatUpdate: Literal["channel.shared_chat.update"]
113+
ChannelSharedChatEnd: Literal["channel.shared_chat.end"]
111114
ChannelSubscribe: Literal["channel.subscribe"]
112115
ChannelSubscriptionEnd: Literal["channel.subscription.end"]
113116
ChannelSubscriptionGift: Literal["channel.subscription.gift"]
@@ -185,6 +188,9 @@ class SubscriptionType(enum.Enum):
185188
ChannelChatSettingsUpdate = "channel.chat_settings.update"
186189
ChannelChatUserMessageHold = "channel.chat.user_message_hold"
187190
ChannelChatUserMessageUpdate = "channel.chat.user_message_update"
191+
ChannelSharedChatBegin = "channel.shared_chat.begin"
192+
ChannelSharedChatUpdate = "channel.shared_chat.update"
193+
ChannelSharedChatEnd = "channel.shared_chat.end"
188194
ChannelSubscribe = "channel.subscribe"
189195
ChannelSubscriptionEnd = "channel.subscription.end"
190196
ChannelSubscriptionGift = "channel.subscription.gift"

0 commit comments

Comments
 (0)