diff --git a/README.md b/README.md
index c6bbaa6..d4f0640 100644
--- a/README.md
+++ b/README.md
@@ -45,6 +45,7 @@ The config file is stored in a directory named `data`.
* `buttons` (list) - [Information](#buttons)
* `label` (string) - The label to be displayed on the button.
* `url` (string) - A web address or a [dynamic URL placeholder](#dynamic-button-urls).
+ * `mediaTypes` (list, optional) - If set, the button is displayed only for the specified media types. Valid media types are `movie`, `episode` and `track`.
* `users` (list)
* `token` (string) - An access token associated with your Plex account. ([X-Plex-Token](https://support.plex.tv/articles/204059436-finding-an-authentication-token-x-plex-token/), [Authenticating with Plex](https://forums.plex.tv/t/authenticating-with-plex/609370))
* `servers` (list)
@@ -69,16 +70,15 @@ Due to a strange Discord bug, these buttons may be unresponsive or exhibit stran
#### Dynamic Button URLs
During runtime, the following dynamic URL placeholders will get replaced with real URLs based on the media being played:
+
* `dynamic:imdb`
* `dynamic:tmdb`
+* `dynamic:thetvdb`
+* `dynamic:trakt`
+* `dynamic:letterboxd`
+* `dynamic:musicbrainz`
-### Example
-
-
-
-YAML
-
-
+### Example (YAML)
```yaml
logging:
@@ -94,8 +94,10 @@ display:
buttons:
- label: IMDb
url: dynamic:imdb
- - label: My YouTube Channel
- url: https://www.youtube.com/channel/me
+ - label: Music Stats
+ url: https://github.com
+ mediaTypes:
+ - track
users:
- token: HPbrz2NhfLRjU888Rrdt
servers:
@@ -105,60 +107,6 @@ users:
- Movies
```
-
-
-
-
-JSON
-
-
-
-```json
-{
- "logging": {
- "debug": true,
- "writeToFile": false
- },
- "display": {
- "hideTotalTime": false,
- "useRemainingTime": false,
- "posters": {
- "enabled": true,
- "imgurClientID": "9e9sf637S8bRp4z",
- "maxSize": 256
- },
- "buttons": [
- {
- "label": "IMDb",
- "url": "dynamic:imdb"
- },
- {
- "label": "My YouTube Channel",
- "url": "https://www.youtube.com/channel/me"
- }
- ]
- },
- "users": [
- {
- "token": "HPbrz2NhfLRjU888Rrdt",
- "servers": [
- {
- "name": "Bob's Home Media Server"
- },
- {
- "name": "A Friend's Server",
- "whitelistedLibraries": [
- "Movies"
- ]
- }
- ]
- }
- ]
-}
-```
-
-
-
## Configuration - Discord
The "Display current activity as a status message" setting must be enabled in Discord Settings → Activity Settings → Activity Privacy.
@@ -168,7 +116,7 @@ The "Display current activity as a status message" setting must be enabled in Di
## Configuration - Environment Variables
* `DRPP_PLEX_SERVER_NAME_INPUT` - This is used only during the initial setup (when there are no users in the config) as the name of the Plex server to be added to the config file after user authentication. If this isn't set, in interactive environments, the user is prompted for an input, and in non-interactive environments, "ServerName" is used as a placeholder, which can later be changed by editing the config file and restarting the script.
-* `DRPP_NO_PIP_INSTALL` - Automatic invocation of pip to install missing dependencies is skipped if this is set to `true`.
+* `DRPP_NO_PIP_INSTALL` - Set this to `true` to skip automatic invocation of pip on script startup to install missing dependencies.
## Run with Docker
diff --git a/core/plex.py b/core/plex.py
index 987a792..42df1f2 100644
--- a/core/plex.py
+++ b/core/plex.py
@@ -34,6 +34,15 @@ def getAuthToken(id: str, code: str) -> Optional[str]:
}).json()
return response["authToken"]
+buttonTypeGuidTypeMap = {
+ "imdb": "imdb",
+ "tmdb": "tmdb",
+ "thetvdb": "tvdb",
+ "trakt": "tmdb",
+ "letterboxd": "tmdb",
+ "musicbrainz": "mbid",
+}
+
class PlexAlertListener(threading.Thread):
productName = "Plex Media Server"
@@ -242,32 +251,40 @@ class PlexAlertListener(threading.Thread):
},
}
if config["display"]["buttons"]:
- guidTags: list[Guid] = []
- if mediaType == "movie":
- guidTags = item.guids
- elif mediaType == "episode":
- guidTags = self.server.fetchItem(item.grandparentRatingKey).guids
- guids: list[str] = [guid.id for guid in guidTags]
+ guidsRaw: list[Guid] = item.guids if mediaType in ["movie", "track"] else self.server.fetchItem(item.grandparentRatingKey).guids
+ guids: dict[str, str] = { guidSplit[0]: guidSplit[1] for guidSplit in [guid.id.split("://") for guid in guidsRaw] if len(guidSplit) > 1 }
buttons: list[models.discord.ActivityButton] = []
for button in config["display"]["buttons"]:
- if button["url"].startswith("dynamic:"):
- if guids:
- newUrl = button["url"]
- if button["url"] == "dynamic:imdb":
- for guid in guids:
- if guid.startswith("imdb://"):
- newUrl = guid.replace("imdb://", "https://www.imdb.com/title/")
- break
- elif button["url"] == "dynamic:tmdb":
- for guid in guids:
- if guid.startswith("tmdb://"):
- tmdbPathSegment = "movie" if mediaType == "movie" else "tv"
- newUrl = guid.replace("tmdb://", f"https://www.themoviedb.org/{tmdbPathSegment}/")
- break
- if newUrl:
- buttons.append({ "label": button["label"], "url": newUrl })
- else:
- buttons.append(button)
+ if "mediaTypes" in button and mediaType not in button["mediaTypes"]:
+ continue
+ if not button["url"].startswith("dynamic:"):
+ buttons.append({ "label": button["label"], "url": button["url"] })
+ continue
+ buttonType = button["url"][8:]
+ guidType = buttonTypeGuidTypeMap.get(buttonType)
+ if not guidType:
+ continue
+ guid = guids.get(guidType)
+ if not guid:
+ continue
+ url = ""
+ if buttonType == "imdb":
+ url = f"https://www.imdb.com/title/{guid}"
+ elif buttonType == "tmdb":
+ tmdbPathSegment = "movie" if mediaType == "movie" else "tv"
+ url = f"https://www.themoviedb.org/{tmdbPathSegment}/{guid}"
+ elif buttonType == "thetvdb":
+ theTvdbPathSegment = "movie" if mediaType == "movie" else "series"
+ url = f"https://www.thetvdb.com/dereferrer/{theTvdbPathSegment}/{guid}"
+ elif buttonType == "trakt":
+ idType = "movie" if mediaType == "movie" else "show"
+ url = f"https://trakt.tv/search/tmdb/{guid}?id_type={idType}"
+ elif buttonType == "letterboxd" and mediaType == "movie":
+ url = f"https://letterboxd.com/tmdb/{guid}"
+ elif buttonType == "musicbrainz":
+ url = f"https://musicbrainz.org/track/{guid}"
+ if url:
+ buttons.append({ "label": button["label"], "url": url })
if buttons:
activity["buttons"] = buttons[:2]
if state == "playing":
diff --git a/models/config.py b/models/config.py
index 2a4ab30..91b79bb 100644
--- a/models/config.py
+++ b/models/config.py
@@ -12,6 +12,7 @@ class Posters(TypedDict):
class Button(TypedDict):
label: str
url: str
+ mediaTypes: list[str]
class Display(TypedDict):
hideTotalTime: bool