diff --git a/src/twitchclient/api.py b/src/twitchclient/api.py index 54830df..1468f6c 100644 --- a/src/twitchclient/api.py +++ b/src/twitchclient/api.py @@ -1055,3 +1055,93 @@ class TwitchAPIClient(AioHTTPXClient): case _: raise s.Error(req.status_code, 'Internal Server Error') + + async def send_shoutout( + self, + access_token: str, + from_broadcaster_id: int | str, + to_broadcaster_id: int | str, + moderator_id: int | str, + ): + req = await self.post( + '/chat/shoutouts', + headers={'Authorization': f'Bearer {access_token}'}, + params={ + 'from_broadcaster_id': from_broadcaster_id, + 'to_broadcaster_id': to_broadcaster_id, + 'moderator_id': moderator_id, + }, + ) + + match req.status_code: + case st.NO_CONTENT: + return True + + case ( + st.BAD_REQUEST + | st.UNAUTHORIZED + | st.FORBIDDEN + | st.TOO_MANY_REQUESTS + ): + raise s.Error(req.status_code, req.json()['message']) + + case _: + raise s.Error(req.status_code, 'Internal Server Error') + + async def send_chat_message( + self, + access_token: str, + broadcaster_id: int | str, + sender_id: int | str, + message: str, + *, + reply_parent_message_id: str | None = None, + for_source_only: bool | None = None, + ): + req = await self.post( + '/chat/messages', + headers={'Authorization': f'Bearer {access_token}'}, + json=self.clean_dict( + { + 'broadcaster_id': broadcaster_id, + 'sender_id': sender_id, + 'reply_parent_message_id': reply_parent_message_id, + 'for_source_only': for_source_only, + 'message': message, + } + ), + ) + + match req.status_code: + case st.OK: + return s.Message.model_validate(req.json()).data + + case ( + st.BAD_REQUEST + | st.UNAUTHORIZED + | st.FORBIDDEN + | st.TOO_MANY_REQUESTS + ): + raise s.Error(req.status_code, req.json()['message']) + + case _: + raise s.Error(req.status_code, 'Internal Server Error') + + async def get_user_chat_color( + self, access_token: str, user_id: int | str | list[int] | list[str] + ): + req = await self.get( + '/chat/colors', + headers={'Authorization': f'Bearer {access_token}'}, + params={'user_id': user_id}, + ) + + match req.status_code: + case st.OK: + return s.UserChatColor.model_validate(req.json()) + + case st.BAD_REQUEST | st.UNAUTHORIZED: + raise s.Error(req.status_code, req.json()['message']) + + case _: + raise s.Error(req.status_code, 'Internal Server Error') diff --git a/src/twitchclient/schema.py b/src/twitchclient/schema.py index 3b533b6..99aedcb 100644 --- a/src/twitchclient/schema.py +++ b/src/twitchclient/schema.py @@ -604,3 +604,39 @@ class SharedChatSession(BaseModel): class UserEmotes(ChannelEmotes): pagination: Pagination | dict[Any, Any] | None = None + + +class MessageDropReason(BaseModel): + model_config = ConfigDict(extra='forbid') + + code: str + message: str + + +class MessageData(BaseModel): + model_config = ConfigDict(extra='forbid') + + message_id: str + is_sent: bool + drop_reason: MessageDropReason | None = None + + +class Message(BaseModel): + model_config = ConfigDict(extra='forbid') + + data: list[MessageData] + + +class UserChatColorData(BaseModel): + model_config = ConfigDict(extra='forbid') + + user_id: int + user_login: str + user_name: str + color: str + + +class UserChatColor(BaseModel): + model_config = ConfigDict(extra='forbid') + + data: list[UserChatColorData]