Skip to content

Commit 8e93d0e

Browse files
authored
Add new API routes (#441)
* Add new API routes * add docs
1 parent ce7ac6a commit 8e93d0e

File tree

4 files changed

+118
-1
lines changed

4 files changed

+118
-1
lines changed

docs/reference.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,13 @@ ActiveExtension
1111
:members:
1212
:inherited-members:
1313

14+
AdSchedule
15+
------------
16+
.. attributetable:: AdSchedule
17+
18+
.. autoclass:: AdSchedule
19+
:members:
20+
1421
AutomodCheckMessage
1522
---------------------
1623
.. attributetable:: AutomodCheckMessage

twitchio/http.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -645,7 +645,6 @@ async def get_hype_train(self, broadcaster_id: str, id: Optional[str] = None, to
645645
)
646646

647647
async def post_automod_check(self, token: str, broadcaster_id: str, *msgs: List[Dict[str, str]]):
648-
print(msgs)
649648
return await self.request(
650649
Route(
651650
"POST",
@@ -656,6 +655,14 @@ async def post_automod_check(self, token: str, broadcaster_id: str, *msgs: List[
656655
)
657656
)
658657

658+
async def post_snooze_ad(self, token: str, broadcaster_id: str):
659+
q = [("broadcaster_id", broadcaster_id)]
660+
return await self.request(Route("POST", "channels/ads/schedule/snooze", query=q, token=token))
661+
662+
async def get_ad_schedule(self, token: str, broadcaster_id: str):
663+
q = [("broadcaster_id", broadcaster_id)]
664+
return await self.request(Route("GET", "channels/ads", query=q, token=token))
665+
659666
async def get_channel_ban_unban_events(self, token: str, broadcaster_id: str, user_ids: List[str] = None):
660667
q = [("broadcaster_id", broadcaster_id)]
661668
if user_ids:
@@ -668,6 +675,10 @@ async def get_channel_bans(self, token: str, broadcaster_id: str, user_ids: List
668675
q.extend(("user_id", id) for id in user_ids)
669676
return await self.request(Route("GET", "moderation/banned", query=q, token=token))
670677

678+
async def get_moderated_channels(self, token: str, user_id: str):
679+
q = [("user_id", user_id)]
680+
return await self.request(Route("GET", "moderation/channels", query=q, token=token))
681+
671682
async def get_channel_moderators(self, token: str, broadcaster_id: str, user_ids: List[str] = None):
672683
q = [("broadcaster_id", broadcaster_id)]
673684
if user_ids:

twitchio/models.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
if TYPE_CHECKING:
3434
from .http import TwitchHTTP
3535
__all__ = (
36+
"AdSchedule",
3637
"BitsLeaderboard",
3738
"Clip",
3839
"CheerEmote",
@@ -87,6 +88,44 @@
8788
)
8889

8990

91+
class AdSchedule:
92+
"""
93+
Represents a channel's ad schedule.
94+
95+
Attributes
96+
-----------
97+
next_ad_at: Optional[:class:`datetime.datetime`]
98+
When the next ad will roll. Will be ``None`` if the streamer does not schedule ads, or is not live.
99+
last_ad_at: Optional[:class:`datetime.datetime`]
100+
When the last ad rolled. Will be ``None`` if the streamer has not rolled an ad.
101+
Will always be ``None`` when this comes from snoozing an ad.
102+
duration: :class:`int`
103+
How long the upcoming ad will be, in seconds.
104+
preroll_freeze_time: Optional[:class:`int`]
105+
The amount of pre-roll free time remaining for the channel in seconds. Will be 0 if the streamer is not pre-roll free.
106+
Will be ``None`` when this comes from snoozing an ad.
107+
snooze_count: :class:`int`
108+
How many snoozes the streamer has left.
109+
snooze_refresh_at: :class:`datetime.datetime`
110+
When the streamer will gain another snooze.
111+
"""
112+
113+
__slots__ = "next_ad_at", "last_ad_at", "duration", "preroll_freeze_time", "snooze_count", "snooze_refresh_at"
114+
115+
def __init__(self, data: dict) -> None:
116+
self.duration: int = data["duration"]
117+
self.preroll_freeze_time: int = data["preroll_freeze_time"]
118+
self.snooze_count: int = data["snooze_count"]
119+
120+
self.snooze_refresh_at: datetime.datetime = parse_timestamp(data["snooze_refresh_at"])
121+
self.next_ad_at: Optional[datetime.datetime] = (
122+
parse_timestamp(data["next_ad_at"]) if data["next_ad_at"] else None
123+
)
124+
self.last_ad_at: Optional[datetime.datetime] = (
125+
parse_timestamp(data["last_ad_at"]) if data["last_ad_at"] else None
126+
)
127+
128+
90129
class BitsLeaderboard:
91130
"""
92131
Represents a Bits leaderboard from the twitch API.

twitchio/user.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
from .http import TwitchHTTP
3838
from .channel import Channel
3939
from .models import (
40+
AdSchedule,
4041
BitsLeaderboard,
4142
Clip,
4243
ExtensionBuilder,
@@ -334,6 +335,48 @@ async def create_clip(self, token: str, has_delay=False) -> dict:
334335
data = await self._http.post_create_clip(token, self.id, has_delay)
335336
return data[0]
336337

338+
async def fetch_ad_schedule(self, token: str) -> AdSchedule:
339+
"""|coro|
340+
341+
Fetches the streamers's ad schedule.
342+
343+
Parameters
344+
-----------
345+
token: :class:`str`
346+
The user's oauth token with the ``channel:read:ads`` scope.
347+
348+
Returns
349+
--------
350+
:class:`twitchio.AdSchedule`
351+
"""
352+
from .models import AdSchedule
353+
354+
data = await self._http.get_ad_schedule(token, str(self.id))
355+
return AdSchedule(data[0])
356+
357+
async def snooze_ad(self, token: str) -> List[AdSchedule]:
358+
"""|coro|
359+
360+
Snoozes an ad on the streamer's channel.
361+
362+
.. note::
363+
The resulting :class:`~twitchio.AdSchedule` only has data for the :attr:`~twitchio.AdSchedule.snooze_count`,
364+
:attr:`~twitchio.AdSchedule.snooze_refresh_at`, and :attr:`~twitchio.AdSchedule.next_ad_at` attributes.
365+
366+
Parameters
367+
-----------
368+
token: :class:`str`
369+
The user's oauth token with the ``channel:manage:ads`` scope.
370+
371+
Returns
372+
--------
373+
:class:`twitchio.AdSchedule`
374+
"""
375+
from .models import AdSchedule
376+
377+
data = await self._http.post_snooze_ad(token, str(self.id))
378+
return AdSchedule(data[0])
379+
337380
async def fetch_clips(
338381
self,
339382
started_at: Optional[datetime.datetime] = None,
@@ -403,6 +446,23 @@ async def fetch_bans(self, token: str, userids: List[Union[str, int]] = None) ->
403446
data = await self._http.get_channel_bans(token, str(self.id), user_ids=userids)
404447
return [UserBan(self._http, d) for d in data]
405448

449+
async def fetch_moderated_channels(self, token: str) -> List[PartialUser]:
450+
"""|coro|
451+
452+
Fetches channels that this user moderates.
453+
454+
Parameters
455+
-----------
456+
token: :class:`str`
457+
An oauth token for this user with the ``user:read:moderated_channels`` scope.
458+
459+
Returns
460+
--------
461+
List[:class:`twitchio.PartialUser`]
462+
"""
463+
data = await self._http.get_moderated_channels(token, str(self.id))
464+
return [PartialUser(self._http, d["user_id"], d["user_name"]) for d in data]
465+
406466
async def fetch_moderators(self, token: str, userids: List[int] = None):
407467
"""|coro|
408468

0 commit comments

Comments
 (0)