Skip to content
This repository was archived by the owner on Sep 8, 2025. It is now read-only.
Open
13 changes: 12 additions & 1 deletion kick/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from .chatroom import Chatroom, PartialChatroom
from .chatter import PartialChatter
from .http import HTTPClient
from .livestream import PartialLivestream
from .livestream import PartialLivestream, LivestreamEnd
from .message import Message
from .users import ClientUser, PartialUser, User
from .utils import MISSING, decorator, setup_logging
Expand Down Expand Up @@ -329,7 +329,18 @@ async def on_livestream_start(self, livestream: PartialLivestream) -> None:
livestream: `PartialLivestream`
The livestream
"""
async def on_livestream_end(self, livestream_End: LivestreamEnd) -> None:
"""
|coro|

on_livestream_end is an event that can be overriden with the `Client.event` decorator or with a subclass.
This is called when a user that is being watched ended streaming

Parameters
-----------
livestream: `LivestreamEnd`
The livestream
"""
async def on_follow(self, streamer: User) -> None:
"""
|coro|
Expand Down
30 changes: 28 additions & 2 deletions kick/livestream.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@
if TYPE_CHECKING:
from .http import HTTPClient
from .types.videos import LivestreamPayload
from .types.ws import PartialLivestreamPayload
from .types.ws import PartialLivestreamPayload, LivestreamEndPayload
from .users import User

__all__ = ("Livestream", "PartialLivestream")
__all__ = ("Livestream", "PartialLivestream", "LivestreamEnd")


class PartialLivestream:
Expand Down Expand Up @@ -229,3 +229,29 @@ def __eq__(self, other: object) -> bool:

def __repr__(self) -> str:
return f"<Livestream id={self.id} title={self.title} streamer={self.slug}>"

class LivestreamEnd(HTTPDataclass["LivestreamEndPayload"]):
"""
A dataclass which represents a livestream end on kick.

Attributes
-----------
id: int
The livestream's id
channel_id: int
The livestream's channel id
title: str
The livestream's title
streamer: `User` | None
The livestream's streaner
"""
@property
def id(self) -> int:
return self._data["id"]
@property
def channel_id(self):
return self._data["channel"]["id"]

@property
def streamer(self) -> User | None:
return self.http.client._watched_users.get(self.channel_id)
5 changes: 5 additions & 0 deletions kick/types/ws.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,8 @@ class FollowersUpdatePayload(TypedDict):
username: None | str
created_at: int
followed: bool


class LivestreamEndPayload(TypedDict):
id: int
channel_id: int
10 changes: 6 additions & 4 deletions kick/ws.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

from aiohttp import ClientWebSocketResponse as WebSocketResponse

from .livestream import PartialLivestream
from .livestream import PartialLivestream, LivestreamEnd
from .message import Message

if TYPE_CHECKING:
Expand All @@ -31,10 +31,10 @@ async def poll_event(self) -> None:

match raw_data["event"]:
case "App\\Events\\ChatMessageEvent":
msg = Message(data=data["livestream"], http=self.http)
msg = Message(data=data, http=self.http)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This reverts changes from your lasts PR

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that chatmsg not livestream hmm

self.http.client.dispatch("message", msg)
case "App\\Events\\StreamerIsLive":
livestream = PartialLivestream(data=data, http=self.http)
livestream = PartialLivestream(data=data["livestream"], http=self.http)
self.http.client.dispatch("livestream_start", livestream)
case "App\\Events\\FollowersUpdated":
user = self.http.client._watched_users[data["channel_id"]]
Expand All @@ -46,7 +46,9 @@ async def poll_event(self) -> None:
user._data["followers_count"] -= 1

self.http.client.dispatch(event, user)

case "App\\Events\\StopStreamBroadcast":
livestream = LivestreamEnd(data=data["livestream"], http=self.http)
self.http.client.dispatch("livestream_end", livestream)
async def start(self) -> None:
while not self.ws.closed:
await self.poll_event()
Expand Down