diff --git a/app/discord_client.py b/app/discord_client.py index b6730d9..be6c18a 100644 --- a/app/discord_client.py +++ b/app/discord_client.py @@ -9,7 +9,7 @@ from app.twitch_client import StreamInformation class DiscordClient: - _notification_msg_id: str = "" + notification_msg_id: str = "" def __init__(self): self._webhook_url = os.environ["DISCORD_WEBHOOK_URL"] @@ -60,7 +60,7 @@ class DiscordClient: response.raise_for_status() - self._notification_msg_id = response.json()["id"] + self.notification_msg_id = response.json()["id"] logger.info("Stream information sent with ping to Discord.") except (exceptions.ConnectionError, exceptions.HTTPError) as err: logger.opt(exception=err).warning( @@ -85,7 +85,7 @@ class DiscordClient: streamer_url = f"https://www.twitch.tv/{stream.user_login}" try: response = requests.patch( - url=f"{self._webhook_url}/messages/{self._notification_msg_id}", + url=f"{self._webhook_url}/messages/{self.notification_msg_id}", json={ "embeds": [ { @@ -127,7 +127,7 @@ class DiscordClient: self, streamer_name, vod_url: str | None, retry_count: int = 0 ) -> None: logger.info("Finalizing stream information on Discord...") - if not self._notification_msg_id: + if not self.notification_msg_id: logger.info("Message ID not set, nothing to finalize.") return @@ -136,7 +136,7 @@ class DiscordClient: try: response = requests.patch( - url=f"{self._webhook_url}/messages/{self._notification_msg_id}", + url=f"{self._webhook_url}/messages/{self.notification_msg_id}", json={ "username": "Oak Tree", "avatar_url": "https://i.imgur.com/DBOuwjx.png", diff --git a/app/main.py b/app/main.py index f51d8e5..8d231ae 100644 --- a/app/main.py +++ b/app/main.py @@ -1,6 +1,6 @@ +import json import os import time -from datetime import datetime from loguru import logger from requests import HTTPError @@ -11,14 +11,18 @@ from app.twitch_client import StreamInformation, TwitchClient class Main: is_live: bool = False - last_live_at = None - _previous_stream: StreamInformation = None + current_stream_id: str = "" + streams: dict[str, StreamInformation] def __init__(self): self.twitch_client = TwitchClient(streamer=os.environ["STREAMER_NAME"]) self.twitch_client.update_access_token() self.profile_image = self.twitch_client.get_streamer_profile_picture() self.discord_client = DiscordClient() + with open("streams.json", "r") as file: + saved_streams = json.load(file) + for stream_id, saved_stream in saved_streams: + self.streams[stream_id] = StreamInformation(**saved_stream) def update_status(self): try: @@ -28,41 +32,46 @@ class Main: if self.is_live: logger.info("Streamer went offline.") self.is_live = False - self.discord_client.finalize_information_on_discord( - streamer_name=self._previous_stream.user_name, - vod_url=self.twitch_client.get_vod( - user_id=self._previous_stream.user_id - ), - ) + stream = self.streams.get(self.current_stream_id) + if stream: + self.discord_client.finalize_information_on_discord( + streamer_name=stream.user_name, + vod_url=self.twitch_client.get_vod( + user_id=stream.user_id + ), + ) return if not self.is_live: logger.info("Streamer went live.") - if ( - self.last_live_at - and (datetime.now() - self.last_live_at).total_seconds() - < 300 - ): + existing_stream = self.streams.get(stream.id) + if existing_stream: logger.info( - "Streamer was already live once in the past 5 minutes. " - "This is probably due to a crash, not sending the Discord ping." + "Recovering from crash, updating discord if possible." ) - self.last_live_at = datetime.now() self.is_live = True + if existing_stream.discord_message_id: + self.discord_client.notification_msg_id = ( + existing_stream.discord_message_id + ) + self.discord_client.update_information_on_discord( + stream=stream, profile_image=self.profile_image + ) return + self.is_live = True + self.current_stream_id = stream.id + self.streams[stream.id] = stream self.discord_client.send_information_to_discord( stream=stream, profile_image=self.profile_image ) - self.last_live_at = datetime.now() - self.is_live = True + self.streams[ + stream.id + ].discord_message_id = self.discord_client.notification_msg_id else: - logger.info("Streamer still live.") self.discord_client.update_information_on_discord( stream=stream, profile_image=self.profile_image ) - - self._previous_stream = stream except HTTPError as e: logger.exception(e) @@ -71,12 +80,12 @@ class Main: return self.is_live = False - self.discord_client.finalize_information_on_discord( - streamer_name=self._previous_stream.user_login, - vod_url=self.twitch_client.get_vod( - user_id=self._previous_stream.user_id - ), - ) + stream = self.streams.get(self.current_stream_id) + if stream: + self.discord_client.finalize_information_on_discord( + streamer_name=stream.user_name, + vod_url=self.twitch_client.get_vod(user_id=stream.user_id), + ) DELAY_SECONDS = 30.0 @@ -91,6 +100,8 @@ def entry() -> None: try: while True: main.update_status() + with open("streams.json", "w") as file: + json.dump(main.streams, file) time.sleep( DELAY_SECONDS - ((time.time() - start_time) % DELAY_SECONDS) ) diff --git a/app/twitch_client.py b/app/twitch_client.py index cac248a..f7f99d5 100644 --- a/app/twitch_client.py +++ b/app/twitch_client.py @@ -25,6 +25,7 @@ class CachePrevent: @dataclass class StreamInformation: + id: str user_id: str user_name: str user_login: str @@ -33,6 +34,7 @@ class StreamInformation: viewer_count: int started_at: str _thumbnail_url: str + discord_message_id: str = "" @property def thumbnail_url(self): @@ -140,6 +142,7 @@ class TwitchClient: stream_data = streams[0] return StreamInformation( + id=stream_data.get("id"), user_id=stream_data.get("user_id"), user_name=stream_data.get("user_name"), user_login=stream_data.get("user_login"),