Skip to content

Commit 4503c2d

Browse files
committed
Add authorisation_by_user endpoint support
1 parent a35f6a0 commit 4503c2d

File tree

6 files changed

+100
-4
lines changed

6 files changed

+100
-4
lines changed

docs/getting-started/changelog.rst

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,12 @@ Changelog
1010
======
1111
- twitchio
1212
- Additions
13-
- Added - :func:`~twitchio.PartialUser.fetch_hype_train_status`
14-
- Added - :func:`~twitchio.PartialUser.fetch_stream`
13+
- Added - :class:`~twitchio.UserAuthorisation` model
14+
- Added - :func:`~twitchio.Client.fetch_auth_by_users` to :class:`~twitchio.Client`
15+
- Added - :func:`~twitchio.PartialUser.fetch_auth` to :class:`~twitchio.PartialUser`
16+
- Added - :func:`~twitchio.PartialUser.fetch_stream` to :class:`~twitchio.PartialUser` as a helper method.
17+
- Added - :func:`~twitchio.PartialUser.fetch_hype_train_status` to :class:`~twitchio.PartialUser`.
18+
This replaces :func:`~twitchio.PartialUser.fetch_hype_train_events` which has been deprecated
1519

1620

1721
3.1.0

docs/references/helix/helix_models.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,11 @@
367367
.. autoclass:: twitchio.VideoMarkers
368368
:members:
369369

370+
.. attributetable:: twitchio.UserAuthorisation
371+
372+
.. autoclass:: twitchio.UserAuthorisation
373+
:members:
374+
370375
.. attributetable:: twitchio.UserSubscription
371376

372377
.. autoclass:: twitchio.UserSubscription

twitchio/client.py

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
from .models.games import Game
4545
from .models.teams import Team
4646
from .payloads import EventErrorPayload, WebsocketSubscriptionData
47-
from .user import ActiveExtensions, Extension, PartialUser, User
47+
from .user import ActiveExtensions, Extension, PartialUser, User, UserAuthorisation
4848
from .utils import MISSING, EventWaiter, clamp, unwrap_function
4949
from .web import AiohttpAdapter, has_starlette
5050
from .web.utils import BaseAdapter
@@ -2205,6 +2205,32 @@ async def update_entitlements(
22052205
data = await self._http.patch_drop_entitlements(ids=ids, fulfillment_status=fulfillment_status, token_for=token_for)
22062206
return [EntitlementStatus(d) for d in data["data"]]
22072207

2208+
async def fetch_auth_by_users(self, user_ids: list[str]) -> list[UserAuthorisation]:
2209+
"""|coro|
2210+
Fetches authentication information for one or more users, up to 10.
2211+
This uses the app token associated with the Client ID and Secret provided.
2212+
2213+
Parameters
2214+
----------
2215+
user_ids: list[str]
2216+
A list of user IDs to fetch authentication information for.
2217+
You may only fetch a maximum of `10` user IDs at a time.
2218+
2219+
Returns
2220+
-------
2221+
list[UserAuthorisation]
2222+
2223+
Raises
2224+
------
2225+
ValueError
2226+
You may only fetch a maximum of ``10`` user IDs at a time.
2227+
"""
2228+
if len(user_ids) > 10:
2229+
raise ValueError("You may only fetch a maximum of 10 user IDs at a time.")
2230+
2231+
data = await self._http.get_auth_by_user(user_ids=user_ids)
2232+
return [UserAuthorisation(u, http=self._http) for u in data["data"]]
2233+
22082234
async def subscribe_websocket(
22092235
self,
22102236
payload: SubscriptionPayload,

twitchio/http.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@
8181
from .types_.responses import (
8282
AddBlockedTermResponse,
8383
AdScheduleResponse,
84+
AuthorizationByUserResponse,
8485
AutomodSettingsResponse,
8586
BannedUsersResponseData,
8687
BanUserResponse,
@@ -2510,6 +2511,11 @@ async def put_user(self, token_for: str, description: str | None) -> UpdateUserR
25102511
route: Route = Route("PUT", "users", params=params, token_for=token_for)
25112512
return await self.request_json(route)
25122513

2514+
async def get_auth_by_user(self, user_ids: list[str]) -> AuthorizationByUserResponse:
2515+
params = {"user_id": user_ids}
2516+
route: Route = Route("GET", "authorization/users", params=params)
2517+
return await self.request_json(route)
2518+
25132519
def get_user_block_list(
25142520
self, broadcaster_id: str | int, token_for: str, first: int = 20, max_results: int | None = None
25152521
) -> HTTPAsyncIterator[PartialUser]:

twitchio/types_/responses.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
__all__ = (
3131
"AdScheduleResponse",
3232
"AdScheduleResponseData",
33+
"AuthorizationByUserResponse",
34+
"AuthorizationByUserResponseData",
3335
"AuthorizationURLResponse",
3436
"BitsLeaderboardResponse",
3537
"ChannelChatBadgesResponseData",
@@ -1663,6 +1665,18 @@ class UpdateUserResponse(TypedDict):
16631665
data: list[UsersResponseData]
16641666

16651667

1668+
class AuthorizationByUserResponseData(TypedDict):
1669+
user_id: str
1670+
user_name: str
1671+
user_login: str
1672+
scopes: list[str]
1673+
has_authorized: bool
1674+
1675+
1676+
class AuthorizationByUserResponse(TypedDict):
1677+
data: list[AuthorizationByUserResponseData]
1678+
1679+
16661680
class UserBlockListResponseData(TypedDict):
16671681
user_id: str
16681682
user_login: str

twitchio/user.py

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import datetime
3838

3939
from twitchio.types_.responses import (
40+
AuthorizationByUserResponseData,
4041
UserActiveExtensionsResponseData,
4142
UserExtensionsResponseData,
4243
UserPanelComponentItem,
@@ -75,7 +76,7 @@
7576
from .models.subscriptions import BroadcasterSubscriptions, UserSubscription
7677
from .models.teams import ChannelTeam
7778

78-
__all__ = ("ActiveExtensions", "Extension", "PartialUser", "User")
79+
__all__ = ("ActiveExtensions", "Extension", "PartialUser", "User", "UserAuthorisation")
7980

8081

8182
class PartialUser:
@@ -3211,6 +3212,20 @@ async def update(self, description: str | None = None) -> User:
32113212
data = await self._http.put_user(token_for=self.id, description=description)
32123213
return User(data["data"][0], http=self._http)
32133214

3215+
async def fetch_auth(self) -> UserAuthorisation:
3216+
"""|coro|
3217+
3218+
Fetches the user's authentication information.
3219+
3220+
Returns
3221+
-------
3222+
UserAuthorisation
3223+
UserAuthorisation object.
3224+
"""
3225+
3226+
data = await self._http.get_auth_by_user(user_ids=[self.id])
3227+
return UserAuthorisation(data["data"][0], http=self._http)
3228+
32143229
def fetch_block_list(self, *, first: int = 20, max_results: int | None = None) -> HTTPAsyncIterator[PartialUser]:
32153230
"""|aiter|
32163231
@@ -4061,3 +4076,29 @@ async def follow_info(self) -> ChannelFollowerEvent | None:
40614076
user_id=self, broadcaster_id=self.channel, token_for=self.channel, max_results=1
40624077
)
40634078
return await anext(data.followers, None)
4079+
4080+
4081+
class UserAuthorisation:
4082+
"""A class that contains authorisation information for a user against a Client ID / Twitch application.
4083+
4084+
Attributes
4085+
-----------
4086+
user: PartialUser
4087+
The user having authorised checked.
4088+
scopes: Scopes
4089+
The scopes the user has granted to the Client ID / application.
4090+
authorised: bool
4091+
Whether the user has authorised the Client ID / application.
4092+
"""
4093+
4094+
__slots__ = ("authorised", "scopes", "user")
4095+
4096+
def __init__(self, data: AuthorizationByUserResponseData, *, http: HTTPClient) -> None:
4097+
from .authentication import Scopes
4098+
4099+
self.user: PartialUser = PartialUser(data["user_id"], data["user_login"], data["user_name"], http=http)
4100+
self.scopes: Scopes = Scopes(data["scopes"])
4101+
self.authorised: bool = bool(data["has_authorized"])
4102+
4103+
def __repr__(self) -> str:
4104+
return f"<UserAuthorisation user={self.user} authorised={self.authorised}>"

0 commit comments

Comments
 (0)