Added additional display configuration fields

This commit is contained in:
Phin 2024-08-31 01:40:46 +05:30
parent 4d4c312ee1
commit 11efd871e0
5 changed files with 54 additions and 25 deletions

View file

@ -13,8 +13,12 @@ config: models.config.Config = {
"writeToFile": False, "writeToFile": False,
}, },
"display": { "display": {
"hideTotalTime": False, "duration": True,
"useRemainingTime": False, "genres": True,
"album": True,
"year": True,
"remainingTime": False,
"paused": False,
"posters": { "posters": {
"enabled": False, "enabled": False,
"imgurClientID": "", "imgurClientID": "",
@ -57,6 +61,12 @@ def loadConfig() -> None:
logger.exception("Failed to parse the config file. A new one will be created.") logger.exception("Failed to parse the config file. A new one will be created.")
else: else:
copyDict(loadedConfig, config) copyDict(loadedConfig, config)
if "hideTotalTime" in config["display"]:
config["display"]["duration"] = not config["display"]["hideTotalTime"]
del config["display"]["hideTotalTime"]
if "useRemainingTime" in config["display"]:
config["display"]["remainingTime"] = config["display"]["useRemainingTime"]
del config["display"]["useRemainingTime"]
saveConfig() saveConfig()
class YamlSafeDumper(yaml.SafeDumper): class YamlSafeDumper(yaml.SafeDumper):

View file

@ -10,7 +10,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, truncate from utils.text import formatSeconds, truncate, stripNonAscii
import models.config import models.config
import models.discord import models.discord
import models.plex import models.plex
@ -186,6 +186,7 @@ class PlexAlertListener(threading.Thread):
if "whitelistedLibraries" in self.serverConfig and libraryName not in self.serverConfig["whitelistedLibraries"]: if "whitelistedLibraries" in self.serverConfig and libraryName not in self.serverConfig["whitelistedLibraries"]:
self.logger.debug("Library '%s' is not whitelisted, ignoring", libraryName) self.logger.debug("Library '%s' is not whitelisted, ignoring", libraryName)
return return
isIgnorableState = state == "stopped" or (state == "paused" and not config["display"]["paused"])
if self.lastSessionKey == sessionKey and self.lastRatingKey == ratingKey: if self.lastSessionKey == sessionKey and self.lastRatingKey == ratingKey:
if self.updateTimeoutTimer: if self.updateTimeoutTimer:
self.updateTimeoutTimer.cancel() self.updateTimeoutTimer.cancel()
@ -198,11 +199,11 @@ class PlexAlertListener(threading.Thread):
return return
else: else:
self.ignoreCount = 0 self.ignoreCount = 0
if state == "stopped": if isIgnorableState:
self.disconnectRpc() self.disconnectRpc()
return return
elif state == "stopped": elif isIgnorableState:
self.logger.debug("Received 'stopped' state alert from unknown session, ignoring") self.logger.debug("Received '%s' state alert from unknown session, ignoring", state)
return return
if self.isServerOwner: if self.isServerOwner:
self.logger.debug("Searching sessions for session key %s", sessionKey) self.logger.debug("Searching sessions for session key %s", sessionKey)
@ -229,13 +230,13 @@ class PlexAlertListener(threading.Thread):
self.updateTimeoutTimer.start() self.updateTimeoutTimer.start()
self.lastState, self.lastSessionKey, self.lastRatingKey = state, sessionKey, ratingKey self.lastState, self.lastSessionKey, self.lastRatingKey = state, sessionKey, ratingKey
stateStrings: list[str] = [] stateStrings: list[str] = []
if not config["display"]["hideTotalTime"] and item.duration and mediaType != "track": if config["display"]["duration"] 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 = shortTitle = item.title title = shortTitle = item.title
if item.year: if config["display"]["year"] and item.year:
title += f" ({item.year})" title += f" ({item.year})"
if item.genres: if config["display"]["genres"] and item.genres:
genres: list[Genre] = item.genres[:3] genres: list[Genre] = item.genres[:3]
stateStrings.append(f"{', '.join(genre.tag for genre in genres)}") stateStrings.append(f"{', '.join(genre.tag for genre in genres)}")
largeText = "Watching a movie" largeText = "Watching a movie"
@ -244,9 +245,10 @@ class PlexAlertListener(threading.Thread):
smallThumb = "" smallThumb = ""
elif mediaType == "episode": elif mediaType == "episode":
title = shortTitle = item.grandparentTitle title = shortTitle = item.grandparentTitle
grandparent = self.server.fetchItem(item.grandparentRatingKey) if config["display"]["year"]:
if grandparent.year: grandparent = self.server.fetchItem(item.grandparentRatingKey)
title += f" ({grandparent.year})" 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"
@ -263,13 +265,17 @@ class PlexAlertListener(threading.Thread):
smallThumb = "" smallThumb = ""
elif mediaType == "track": elif mediaType == "track":
title = shortTitle = item.title title = shortTitle = item.title
largeText = item.parentTitle
parent = self.server.fetchItem(item.parentRatingKey)
if parent.year:
largeText += f" ({parent.year})"
thumb = item.thumb
smallText = item.originalTitle or item.grandparentTitle smallText = item.originalTitle or item.grandparentTitle
stateStrings.append(smallText) if config["display"]["album"]:
largeText = item.parentTitle
if config["display"]["year"]:
parent = self.server.fetchItem(item.parentRatingKey)
if parent.year:
largeText += f" ({parent.year})"
stateStrings.append(smallText)
else:
largeText = smallText
thumb = item.thumb
smallThumb = item.grandparentThumb smallThumb = item.grandparentThumb
else: else:
title = shortTitle = item.title title = shortTitle = item.title
@ -278,7 +284,7 @@ class PlexAlertListener(threading.Thread):
smallText = "" smallText = ""
smallThumb = "" smallThumb = ""
if state != "playing" and mediaType != "track": if state != "playing" and mediaType != "track":
if config["display"]["useRemainingTime"]: if config["display"]["remainingTime"]:
stateStrings.append(f"{formatSeconds((item.duration - viewOffset) / 1000, ':')} left") stateStrings.append(f"{formatSeconds((item.duration - viewOffset) / 1000, ':')} left")
else: else:
stateStrings.append(f"{formatSeconds(viewOffset / 1000, ':')} elapsed") stateStrings.append(f"{formatSeconds(viewOffset / 1000, ':')} elapsed")
@ -287,7 +293,7 @@ class PlexAlertListener(threading.Thread):
smallThumbUrl = self.uploadToImgur(smallThumb) if smallThumb and config["display"]["posters"]["enabled"] else "" smallThumbUrl = self.uploadToImgur(smallThumb) if smallThumb and config["display"]["posters"]["enabled"] else ""
activity: models.discord.Activity = { activity: models.discord.Activity = {
"type": mediaTypeActivityTypeMap[mediaType], "type": mediaTypeActivityTypeMap[mediaType],
"details": truncate(title, 128), "details": truncate(title, 120),
"assets": { "assets": {
"large_text": largeText, "large_text": largeText,
"large_image": thumbUrl or "logo", "large_image": thumbUrl or "logo",
@ -296,7 +302,7 @@ class PlexAlertListener(threading.Thread):
}, },
} }
if stateText: if stateText:
activity["state"] = truncate(stateText, 128) activity["state"] = truncate(stateText, 120)
if config["display"]["buttons"]: if config["display"]["buttons"]:
guidsRaw: list[Guid] = [] guidsRaw: list[Guid] = []
if mediaType in ["movie", "track"]: if mediaType in ["movie", "track"]:
@ -308,7 +314,7 @@ 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) label = truncate(button["label"].format(title = stripNonAscii(shortTitle)), 30)
if not button["url"].startswith("dynamic:"): if not button["url"].startswith("dynamic:"):
buttons.append({ "label": label, "url": button["url"] }) buttons.append({ "label": label, "url": button["url"] })
continue continue
@ -341,7 +347,7 @@ class PlexAlertListener(threading.Thread):
activity["buttons"] = buttons[:2] activity["buttons"] = buttons[:2]
if state == "playing": if state == "playing":
currentTimestamp = int(time.time() * 1000) currentTimestamp = int(time.time() * 1000)
if config["display"]["useRemainingTime"]: if config["display"]["remainingTime"]:
activity["timestamps"] = { "end": round(currentTimestamp + (item.duration - viewOffset)) } activity["timestamps"] = { "end": round(currentTimestamp + (item.duration - viewOffset)) }
else: else:
activity["timestamps"] = { "start": round(currentTimestamp - viewOffset) } activity["timestamps"] = { "start": round(currentTimestamp - viewOffset) }

View file

@ -86,6 +86,11 @@ def main() -> None:
userInput = input() userInput = input()
if userInput in ["exit", "quit"]: if userInput in ["exit", "quit"]:
raise KeyboardInterrupt raise KeyboardInterrupt
elif userInput == "reload-config":
loadConfig()
print("Config reloaded from file")
else:
print("Unrecognised command")
else: else:
while True: while True:
time.sleep(3600) time.sleep(3600)

View file

@ -15,8 +15,12 @@ class Button(TypedDict):
mediaTypes: list[str] mediaTypes: list[str]
class Display(TypedDict): class Display(TypedDict):
hideTotalTime: bool duration: bool
useRemainingTime: bool genres: bool
album: bool
year: bool
remainingTime: bool
paused: bool
posters: Posters posters: Posters
buttons: list[Button] buttons: list[Button]

View file

@ -1,4 +1,5 @@
from typing import Optional from typing import Optional
import re
def formatSeconds(seconds: int | float, joiner: Optional[str] = None) -> str: def formatSeconds(seconds: int | float, joiner: Optional[str] = None) -> str:
seconds = round(seconds) seconds = round(seconds)
@ -13,3 +14,6 @@ def truncate(text: str, maxLength: int) -> str:
if len(text) > maxLength: if len(text) > maxLength:
text = text[:maxLength-3] + "..." text = text[:maxLength-3] + "..."
return text return text
def stripNonAscii(text: str) -> str:
return re.sub(r"[^\x00-\x7f]", "", text)