From 49ad41c3f6d68351094e07a47ba76c35b78cb3b4 Mon Sep 17 00:00:00 2001
From: CodeDevMLH <145071728+CodeDevMLH@users.noreply.github.com>
Date: Wed, 4 Feb 2026 01:06:12 +0100
Subject: [PATCH] Enhance custom media ID functionality with manual trailer
override
---
.../Configuration/configPage.html | 19 +++++---
.../Web/mediaBarEnhanced.js | 48 ++++++++++++++++---
README.md | 3 ++
3 files changed, 57 insertions(+), 13 deletions(-)
diff --git a/Jellyfin.Plugin.MediaBarEnhanced/Configuration/configPage.html b/Jellyfin.Plugin.MediaBarEnhanced/Configuration/configPage.html
index 86fac3a..bcb95b6 100644
--- a/Jellyfin.Plugin.MediaBarEnhanced/Configuration/configPage.html
+++ b/Jellyfin.Plugin.MediaBarEnhanced/Configuration/configPage.html
@@ -16,7 +16,7 @@
- Help
+ ${Help}
@@ -109,20 +109,25 @@
Seasonal Mode Enabled: Define lines with date ranges (Format: DD.MM-DD.MM |
name | IDs).
Example:
- 20.10-31.10 | Halloween | ID1, ID2
+ 20.10-31.10 | Halloween | ID1, ID2 [https://youtu.be/...]
01.12-26.12 | Christmas | ID3, ID4
Only lines matching the current date will be used. If no line matches, it will try to
fetch the list.txt or use random items.
diff --git a/Jellyfin.Plugin.MediaBarEnhanced/Web/mediaBarEnhanced.js b/Jellyfin.Plugin.MediaBarEnhanced/Web/mediaBarEnhanced.js
index 99d5869..da34562 100644
--- a/Jellyfin.Plugin.MediaBarEnhanced/Web/mediaBarEnhanced.js
+++ b/Jellyfin.Plugin.MediaBarEnhanced/Web/mediaBarEnhanced.js
@@ -78,6 +78,7 @@ const STATE = {
videoPlayers: {},
sponsorBlockInterval: null,
isMuted: CONFIG.startMuted,
+ customTrailerUrls: {},
},
};
@@ -344,6 +345,7 @@ const resetSlideshowState = () => {
STATE.slideshow.itemIds = [];
STATE.slideshow.loadedItems = {};
STATE.slideshow.createdSlides = {};
+ STATE.slideshow.customTrailerUrls = {};
STATE.slideshow.totalItems = 0;
STATE.slideshow.isLoading = false;
};
@@ -1429,7 +1431,11 @@ const SlideCreator = {
let trailerUrl = null;
// 1. Check for Remote Trailers (YouTube)
- if (item.RemoteTrailers && item.RemoteTrailers.length > 0) {
+ // Priority: Custom Config URL > Metadata RemoteTrailer
+ if (STATE.slideshow.customTrailerUrls && STATE.slideshow.customTrailerUrls[itemId]) {
+ trailerUrl = STATE.slideshow.customTrailerUrls[itemId];
+ console.log(`Using custom trailer URL for ${itemId}: ${trailerUrl}`);
+ } else if (item.RemoteTrailers && item.RemoteTrailers.length > 0) {
trailerUrl = item.RemoteTrailers[0].Url;
}
@@ -2575,10 +2581,25 @@ const SlideshowManager = {
*/
parseCustomIds() {
if (!CONFIG.enableSeasonalContent) {
- return CONFIG.customMediaIds
- .split(/[\n,]/) // Split by comma or newline
- .map((id) => id.trim()) // Remove whitespace
- .filter((id) => id); // Remove empty strings
+ return CONFIG.customMediaIds
+ .split(/[\n,]/).map((line) => {
+ const urlMatch = line.match(/\[(.*?)\]/);
+ let id = line;
+ if (urlMatch) {
+ const url = urlMatch[1];
+ id = line.replace(/\[.*?\]/, '').trim();
+ const guidMatch = id.match(/([0-9a-f]{32})/i);
+ if (guidMatch) {
+ id = guidMatch[1];
+ } else {
+ id = id.split('|')[0].trim();
+ }
+ STATE.slideshow.customTrailerUrls[id] = url;
+ }
+ return id.trim();
+ })
+ .map((id) => id.trim())
+ .filter((id) => id);
} else {
return this.parseSeasonalIds();
}
@@ -2635,7 +2656,22 @@ const SlideshowManager = {
if (isInRange) {
console.log(`Seasonal match found: ${line}`);
- const ids = idsPart.split(/[,]/).map(id => id.trim()).filter(id => id);
+ const ids = idsPart.split(/[,]/).map(line => {
+ const urlMatch = line.match(/\[(.*?)\]/);
+ let id = line;
+ if (urlMatch) {
+ const url = urlMatch[1];
+ id = line.replace(/\[.*?\]/, '').trim();
+ const guidMatch = id.match(/([0-9a-f]{32})/i);
+ if (guidMatch) {
+ id = guidMatch[1];
+ } else {
+ id = id.split('|')[0].trim();
+ }
+ STATE.slideshow.customTrailerUrls[id] = url;
+ }
+ return id.trim();
+ }).filter(id => id);
rawIds.push(...ids);
}
}
diff --git a/README.md b/README.md
index ee356b7..d0550b8 100644
--- a/README.md
+++ b/README.md
@@ -144,6 +144,9 @@ Configure the plugin via **Dashboard** > **Plugins** > **Media Bar Enhanced**.
Define exactly what shows up in your bar.
* **Enable Custom Media IDs**: Restrict the slideshow to a specific list of IDs.
+ * **Manual Trailer Override**: Add `[YouTube_URL]` after an ID to force a specific trailer.
+ * Example ID: `a1b2c3d4e5... [https://www.youtube.com/watch?v=VIDEO_ID]`
+ * Example Collection Name: `Halloween Collection [https://...] | My Description` (Note: Use `|` to separate description from name if using a name instead of an ID)
* **Enable Seasonal Content Mode**: Advanced date-based scheduling.
* Format: `DD.MM-DD.MM | Name | ID1, ID2, ID3`
* Example: `20.10-31.10 | Halloween | `