From d1b9da0b04eeb91d948226bd3b5d6ed1f35b2ab8 Mon Sep 17 00:00:00 2001 From: Zvonimir Rudinski Date: Tue, 9 Dec 2025 23:58:16 +0100 Subject: [PATCH] update rpc from jellyfin --- discord/models.py | 1 + discord/rpc.py | 5 +++++ jellyfin/api_client.py | 3 +++ jellyfin/models.py | 1 + jellyfin/utils.py | 38 ++++++++++++++++++++++++++++++++++++++ main.py | 16 +++++++++++++++- 6 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 jellyfin/utils.py diff --git a/discord/models.py b/discord/models.py index 66e944e..6eebeeb 100644 --- a/discord/models.py +++ b/discord/models.py @@ -2,6 +2,7 @@ from pydantic import BaseModel from pypresence.types import ActivityType class DiscordRPCUpdatePayload(BaseModel): + id: str title: str subtitle: str image_url: str diff --git a/discord/rpc.py b/discord/rpc.py index 1dedbdf..510aef7 100644 --- a/discord/rpc.py +++ b/discord/rpc.py @@ -8,11 +8,16 @@ class DiscordRPC: self.logger = logging.getLogger('DiscordRPC') self.logger.info("Connecting to Discord RPC...") + self.last_update_id = None self.rpc = Presence(settings.discord_app_id) self.rpc.connect() self.logger.info("Connected to Discord RPC.") def update(self, payload: DiscordRPCUpdatePayload): + if self.last_update_id == payload.id: + self.logger.debug("No update needed for Discord RPC presence.") + return + self.logger.info("Updating Discord RPC presence...") self.rpc.update( activity_type=payload.activity_type, diff --git a/jellyfin/api_client.py b/jellyfin/api_client.py index 342b6b1..c402d5b 100644 --- a/jellyfin/api_client.py +++ b/jellyfin/api_client.py @@ -62,6 +62,7 @@ class JellyfinApiClient: media_id = item.get('Id') return JellyfinMediaItem( + id=media_id, name=item.get('Name'), type=JellyfinMediaType.AUDIO, image_url=self.get_image_url(media_id), @@ -74,6 +75,7 @@ class JellyfinApiClient: media_id = item.get('Id') return JellyfinMediaItem( + id=media_id, name=item.get('Name'), type=JellyfinMediaType.MOVIE, image_url=self.get_image_url(media_id), @@ -84,6 +86,7 @@ class JellyfinApiClient: media_id = item.get('Id') return JellyfinMediaItem( + id=media_id, name=item.get('Name'), type=JellyfinMediaType.EPISODE, image_url=self.get_image_url(media_id), diff --git a/jellyfin/models.py b/jellyfin/models.py index 05754d1..071b54a 100644 --- a/jellyfin/models.py +++ b/jellyfin/models.py @@ -7,6 +7,7 @@ class JellyfinMediaType(str, Enum): EPISODE = 'Episode' class JellyfinMediaItem(BaseModel): + id: str name: str type: JellyfinMediaType image_url: str diff --git a/jellyfin/utils.py b/jellyfin/utils.py new file mode 100644 index 0000000..21c54be --- /dev/null +++ b/jellyfin/utils.py @@ -0,0 +1,38 @@ +from discord.models import DiscordRPCUpdatePayload +from jellyfin.models import JellyfinMediaItem, JellyfinMediaType +from pypresence.types import ActivityType + +def to_rpc_payload(media_item: JellyfinMediaItem) -> DiscordRPCUpdatePayload: + if media_item.type == JellyfinMediaType.AUDIO: + return DiscordRPCUpdatePayload( + id=media_item.id, + title=f"Listening to {media_item.name}", + subtitle=f"by {media_item.metadata.get('artist', 'Unknown Artist')}", + image_url=media_item.image_url, + details=media_item.name, + activity_type=ActivityType.LISTENING + ) + elif media_item.type == JellyfinMediaType.MOVIE: + return DiscordRPCUpdatePayload( + id=media_item.id, + title=f"Watching {media_item.name}", + subtitle="🍿", + image_url=media_item.image_url, + details=media_item.name, + activity_type=ActivityType.WATCHING + ) + elif media_item.type == JellyfinMediaType.EPISODE: + series_name = media_item.metadata.get('series', 'Unknown Series') + season = media_item.metadata.get('season', '?') + episode = media_item.metadata.get('episode', '?') + + subtitle = f"S{season:02}E{episode:02} of {series_name}" + + return DiscordRPCUpdatePayload( + id=media_item.id, + title=f"Watching {media_item.name}", + subtitle=subtitle, + image_url=media_item.image_url, + details=media_item.name, + activity_type=ActivityType.WATCHING + ) diff --git a/main.py b/main.py index 306df5f..61f908c 100644 --- a/main.py +++ b/main.py @@ -1,6 +1,8 @@ from discord.rpc import DiscordRPC from jellyfin.api_client import JellyfinApiClient +from jellyfin.utils import to_rpc_payload import logging +import time logging.basicConfig( level=logging.INFO, @@ -9,4 +11,16 @@ logging.basicConfig( discordRPC = DiscordRPC() jellyfinApiClient = JellyfinApiClient() -print(jellyfinApiClient.get_current_playback()) +def main(): + while True: + media_item = jellyfinApiClient.get_current_playback() + if not media_item: + discordRPC.clear() + time.sleep(15) + continue + + discordRPC.update(to_rpc_payload(media_item)) + time.sleep(15) + +if __name__ == "__main__": + main()