Added support for dynamic button labels

This commit is contained in:
Phin 2024-02-13 14:22:27 +05:30
parent 962ce6006b
commit f0a32011c5
3 changed files with 26 additions and 12 deletions

View file

@ -67,6 +67,10 @@ Discord can display up to 2 buttons in your Rich Presence.
Due to a strange Discord bug, these buttons may be unresponsive or exhibit strange behaviour towards your own clicks, but other users are able to click on them to open their corresponding URLs. Due to a strange Discord bug, these buttons may be unresponsive or exhibit strange behaviour towards your own clicks, but other users are able to click on them to open their corresponding URLs.
#### Dynamic Button Labels
Instances of `{title}` in button labels will be replaced with the top-level title of the media being played.
#### Dynamic Button URLs #### Dynamic Button URLs
During runtime, the following dynamic URL placeholders will get replaced with real URLs based on the media being played: During runtime, the following dynamic URL placeholders will get replaced with real URLs based on the media being played:
@ -92,7 +96,7 @@ display:
imgurClientID: 9e9sf637S8bRp4z imgurClientID: 9e9sf637S8bRp4z
maxSize: 256 maxSize: 256
buttons: buttons:
- label: IMDb - label: '{title} on IMDb'
url: dynamic:imdb url: dynamic:imdb
- label: Music Stats - label: Music Stats
url: https://github.com url: https://github.com

View file

@ -11,7 +11,7 @@ from plexapi.myplex import MyPlexAccount, PlexServer
from typing import Optional from typing import Optional
from utils.cache import getCacheKey, setCacheKey from utils.cache import getCacheKey, setCacheKey
from utils.logging import LoggerWithPrefix from utils.logging import LoggerWithPrefix
from utils.text import formatSeconds from utils.text import formatSeconds, truncate
import models.config import models.config
import models.discord import models.discord
import models.plex import models.plex
@ -131,8 +131,9 @@ class PlexAlertListener(threading.Thread):
def connectionCheck(self) -> None: def connectionCheck(self) -> None:
try: try:
self.logger.debug("Running periodic connection check")
assert self.server assert self.server
self.logger.debug("Request for list of clients to check connection: %s", self.server.clients()) self.server.clients()
except Exception as e: except Exception as e:
self.reconnect(e) self.reconnect(e)
else: else:
@ -220,7 +221,7 @@ class PlexAlertListener(threading.Thread):
if not config["display"]["hideTotalTime"] and item.duration and mediaType != "track": if not config["display"]["hideTotalTime"] and item.duration and mediaType != "track":
stateStrings.append(formatSeconds(item.duration / 1000)) stateStrings.append(formatSeconds(item.duration / 1000))
if mediaType == "movie": if mediaType == "movie":
title = item.title title = shortTitle = item.title
if item.year: if item.year:
title += f" ({item.year})" title += f" ({item.year})"
if item.genres: if item.genres:
@ -229,19 +230,22 @@ class PlexAlertListener(threading.Thread):
largeText = "Watching a movie" largeText = "Watching a movie"
thumb = item.thumb thumb = item.thumb
elif mediaType == "episode": elif mediaType == "episode":
title = item.grandparentTitle title = shortTitle = item.grandparentTitle
grandparent = self.server.fetchItem(item.grandparentRatingKey)
if grandparent.year:
title += f" ({grandparent.year})"
stateStrings.append(f"S{item.parentIndex:02}E{item.index:02}") stateStrings.append(f"S{item.parentIndex:02}E{item.index:02}")
stateStrings.append(item.title) stateStrings.append(item.title)
largeText = "Watching a TV show" largeText = "Watching a TV show"
thumb = item.grandparentThumb thumb = item.grandparentThumb
elif mediaType == "livetv": elif mediaType == "livetv":
title = item.grandparentTitle title = shortTitle = item.grandparentTitle
if item.title != item.grandparentTitle: if item.title != item.grandparentTitle:
stateStrings.append(item.title) stateStrings.append(item.title)
largeText = "Watching live TV" largeText = "Watching live TV"
thumb = item.grandparentThumb thumb = item.grandparentThumb
elif mediaType == "track": elif mediaType == "track":
title = item.title title = shortTitle = item.title
artistAlbum = f"{item.originalTitle or item.grandparentTitle} - {item.parentTitle}" artistAlbum = f"{item.originalTitle or item.grandparentTitle} - {item.parentTitle}"
parent = self.server.fetchItem(item.parentRatingKey) parent = self.server.fetchItem(item.parentRatingKey)
if parent.year: if parent.year:
@ -250,7 +254,7 @@ class PlexAlertListener(threading.Thread):
largeText = "Listening to music" largeText = "Listening to music"
thumb = item.thumb thumb = item.thumb
else: else:
title = item.title title = shortTitle = item.title
largeText = "Watching a video" largeText = "Watching a video"
thumb = item.thumb thumb = item.thumb
if state != "playing" and mediaType != "track": if state != "playing" and mediaType != "track":
@ -267,7 +271,7 @@ class PlexAlertListener(threading.Thread):
thumbUrl = uploadToImgur(self.server.url(thumb, True), config["display"]["posters"]["maxSize"]) thumbUrl = uploadToImgur(self.server.url(thumb, True), config["display"]["posters"]["maxSize"])
setCacheKey(thumb, thumbUrl) setCacheKey(thumb, thumbUrl)
activity: models.discord.Activity = { activity: models.discord.Activity = {
"details": title[:128], "details": truncate(title, 128),
"assets": { "assets": {
"large_text": largeText, "large_text": largeText,
"large_image": thumbUrl or "logo", "large_image": thumbUrl or "logo",
@ -276,7 +280,7 @@ class PlexAlertListener(threading.Thread):
}, },
} }
if stateText: if stateText:
activity["state"] = stateText[:128] activity["state"] = truncate(stateText, 128)
if config["display"]["buttons"]: if config["display"]["buttons"]:
guidsRaw: list[Guid] = [] guidsRaw: list[Guid] = []
if mediaType in ["movie", "track"]: if mediaType in ["movie", "track"]:
@ -288,8 +292,9 @@ class PlexAlertListener(threading.Thread):
for button in config["display"]["buttons"]: for button in config["display"]["buttons"]:
if "mediaTypes" in button and mediaType not in button["mediaTypes"]: if "mediaTypes" in button and mediaType not in button["mediaTypes"]:
continue continue
label = truncate(button["label"].format(title = shortTitle), 32)
if not button["url"].startswith("dynamic:"): if not button["url"].startswith("dynamic:"):
buttons.append({ "label": button["label"], "url": button["url"] }) buttons.append({ "label": label, "url": button["url"] })
continue continue
buttonType = button["url"][8:] buttonType = button["url"][8:]
guidType = buttonTypeGuidTypeMap.get(buttonType) guidType = buttonTypeGuidTypeMap.get(buttonType)
@ -315,7 +320,7 @@ class PlexAlertListener(threading.Thread):
elif buttonType == "musicbrainz": elif buttonType == "musicbrainz":
url = f"https://musicbrainz.org/track/{guid}" url = f"https://musicbrainz.org/track/{guid}"
if url: if url:
buttons.append({ "label": button["label"], "url": url }) buttons.append({ "label": label, "url": url })
if buttons: if buttons:
activity["buttons"] = buttons[:2] activity["buttons"] = buttons[:2]
if state == "playing": if state == "playing":

View file

@ -8,3 +8,8 @@ def formatSeconds(seconds: int | float, joiner: Optional[str] = None) -> str:
if timeValues["h"] == 0: if timeValues["h"] == 0:
del timeValues["h"] del timeValues["h"]
return joiner.join(str(v).rjust(2, "0") for v in timeValues.values()) return joiner.join(str(v).rjust(2, "0") for v in timeValues.values())
def truncate(text: str, maxLength: int) -> str:
if len(text) > maxLength:
text = text[:maxLength-3] + "..."
return text