diff --git a/.github/pull.yml b/.github/pull.yml new file mode 100644 index 0000000..5d5fefe --- /dev/null +++ b/.github/pull.yml @@ -0,0 +1,14 @@ +version: "1" +rules: + - base: main + upstream: MakD:Jellyfin-Media-Bar + mergeMethod: merge + mergeUnstable: false + assignees: + - IAmParadox27 + reviewers: + - IAmParadox27 + conflictReviewers: + - IAmParadox27 +label: ":arrow_heading_down: pull" +conflictLabel: "merge-conflict" \ No newline at end of file diff --git a/README.md b/README.md index b1f4c2b..8bb524e 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,80 @@ +

Media Bar

+

A Jellyfin Plugin

+

+ Logo +
+
+ + DBAD + + + Current Release + +

+ +## Reporting Issues + +If you face issues relating to the visuals or behaviour of buttons added by the Media Bar please report them on MakD's repo (the one this is forked from). This plugin pulls the content from their repo directly and is only in control of adding it without the need for modifying your JF install files. + +Any issues with plugin's settings (including using a playlist as your avatar's playlist) should be made here. +## Development Update - 20th August 2025 + +Hey all! Things are changing with my plugins are more and more people start to use them and report issues. In order to make it easier for me to manage I'm splitting bugs and features into different areas. For feature requests please head over to https://features.iamparadox.dev/ where you'll be able to signin with GitHub and make a feature request. For bugs please report them on the relevant GitHub repo and they will be added to the project board when I've seen them. I've found myself struggling to know when issues are made and such recently so I'm also planning to create a system that will monitor a particular view for new issues that come up and send me a notification which should hopefully allow me to keep more up to date and act faster on various issues. + +As with a lot of devs, I am very momentum based in my personal life coding and there are often times when these projects may appear dormant, I assure you now that I don't plan to let these projects go stale for a long time, there just might be times where there isn't an update or response for a couple weeks, but I'll try to keep that better than it has been. With all new releases to Jellyfin I will be updating as soon as possible, I have already made a start on 10.11.0 and will release an update to my plugins hopefully not long after that version is officially released! +## Installation + +### Prerequisites +- This plugin is based on Jellyfin Version `10.10.7` +- The following plugins are required to also be installed, please following their installation guides: + - File Transformation (https://github.com/IAmParadox27/jellyfin-plugin-file-transformation) at least v2.2.1.0 + +### Installation +1. Add `https://www.iamparadox.dev/jellyfin/plugins/manifest.json` to your plugin repositories. +2. Install `Media Bar` from the Catalogue. +3. Restart Jellyfin. +4. Force refresh your webpage (or app) and you should see your new Media Bar at the top of the home page. +## Upcoming Features/Known Issues +If you find an issue with any of the sections or usage of the plugin, please open an issue on GitHub. + +### FAQ + +#### I've updated Jellyfin to latest version but I can't see the plugin available in the catalogue + +The likelihood is the plugin hasn't been updated for that version of Jellyfin and the plugins are strictly 1 version compatible. Please wait until an update has been pushed. If you can see the version number in the release assets then please make an issue, but if its not in the assets, please wait. I know Jellyfin has updated, I'll update when I can. + +#### I've installed the plugins and the media bar doesn't appear. How do I fix? +This is common, particularly on a fresh install. The first thing you should try is the following +1. Launch your browsers developer tools + +![image](https://github.com/user-attachments/assets/e8781a69-464e-430e-a07c-5172a620ef84) + +3. Open the **Network** tab across the top bar +4. Check the **Disable cache** checkbox +5. Refresh the page **while the dev tools are still open** + +![image](https://github.com/user-attachments/assets/6f8c3fc7-89a3-4475-b8a6-cd4a58d51b84) + +## Credits +Credits for this plugin go to @MakD for his original work and to @BobHasNoSoul and @SethBacon for their influence to MakD. For full credits see below in the original README content + +## Original README + +
+ Original README.md from MakD + # Jellyfin-Media-Bar - Now with Play Now Function ![jsDelivr hits (GitHub)](https://img.shields.io/jsdelivr/gh/hm/makd/Jellyfin-Media-Bar?style=for-the-badge&logo=javascript&logoColor=white&labelColor=F0DB4F&color=323330&cacheSeconds=3600) -**IMP UPDATE — We have dropped support for the normal CSS version (for now). _(It still works, but there will be no further updates till the fullscreen mode is stabilized)_** +**IMP UPDATE — We have dropped support for the normal CSS version (for now). _(It still works, but there will be no further updates till the fullscreen mode is stabilized)_** The fullscreen version has a new look (in beta), and support for different screen sizes has been added. For any visual goof-ups, please open a bug report, including the device being used and whether it is encountered in portrait or landscape mode. -Thanks to the Man, the Legend [BobHasNoSoul](https://github.com/BobHasNoSoul) for his work on the [jellyfinfeatured](https://github.com/BobHasNoSoul/jellyfin-featured) and [SethBacon](https://forum.jellyfin.org/u-sethbacon) and [TedHinklater](https://github.com/tedhinklater) for their take on the [Jellyfin-Featured-Content-Bar](https://github.com/tedhinklater/Jellyfin-Featured-Content-Bar). +Thanks to the Man, the Legend [BobHasNoSoul](https://github.com/BobHasNoSoul) for his work on the [jellyfinfeatured](https://github.com/BobHasNoSoul/jellyfin-featured) and [SethBacon](https://forum.jellyfin.org/u-sethbacon) and [TedHinklater](https://github.com/tedhinklater) for their take on the [Jellyfin-Featured-Content-Bar](https://github.com/tedhinklater/Jellyfin-Featured-Content-Bar). Here I present my version with some code improvements, loading optimizations, and security enhancements. Works best with the [Zombie theme](https://github.com/MakD/zombie-release) (_Shameless Plug_ `@import url(https://cdn.jsdelivr.net/gh/MakD/zombie-release@latest/zombie_revived.css);`, visit the repo for more color schemes). @@ -18,15 +83,15 @@ Here I present my version with some code improvements, loading optimizations, an
Desktop Layout - + ![Jellyfin Desktop Layout](https://raw.githubusercontent.com/MakD/Jellyfin-Media-Bar/refs/heads/main/img/Jelly-Web%20-%20Fullscreen%20Mode.png) - +
Mobile Layout - + ![Jellyfin Mobile Layout](https://raw.githubusercontent.com/MakD/Jellyfin-Media-Bar/refs/heads/main/img/Jelly-Mobile-Fullscreen.png)
@@ -34,12 +99,12 @@ Here I present my version with some code improvements, loading optimizations, an # Prepping the files
- + index.html - 1. Navigate to your `jellyfin-web` folder and search for the file index.html. (you can use any code editor, just remember to open with administrator privileges. - 2. Search for `` - 3. Just before the ``, plug the below code +1. Navigate to your `jellyfin-web` folder and search for the file index.html. (you can use any code editor, just remember to open with administrator privileges. +2. Search for `` +3. Just before the ``, plug the below code ``` @@ -50,7 +115,7 @@ And that is it. Hard refresh your web page (CTRL+Shift+R) twice, and Profit! # Want a Custom List to be showcased instead of random items?? -No worries this got you covered. +No worries this got you covered. ## Steps @@ -71,7 +136,7 @@ The next time it loads, it will display these items. # Uninstall the Bar
- + Roll Back Restore the `index.html` file / remove the lines added and you are good to go!!! @@ -89,3 +154,5 @@ All modifications must be contributed back to this repository. Attribution to the original author (MakD) is required in any use or derivative work. Please take a look at the [LICENSE](LICENSE) file for full terms. + +
diff --git a/slideshowpure.js b/slideshowpure.js index b4daa2e..f5f6924 100644 --- a/slideshowpure.js +++ b/slideshowpure.js @@ -164,11 +164,12 @@ const initLocalization = async () => { */ const initLoadingScreen = () => { - const currentPath = window.location.href.toLowerCase(); + const currentPath = window.location.href.toLowerCase().replace(window.location.origin, ""); const isHomePage = currentPath.includes("/web/#/home.html") || currentPath.includes("/web/#/home") || currentPath.includes("/web/index.html#/home.html") || + currentPath === "/web/index.html#/home" || currentPath.endsWith("/web/"); if (!isHomePage) return; @@ -969,8 +970,8 @@ const VisibilityObserver = { if (!container) return; const isVisible = - (window.location.hash === "#/home.html" || - window.location.hash === "#/home") && + (window.location.hash === "#/home.html" || + window.location.hash === "#/home") && activeTab.getAttribute("data-index") === "0"; container.style.display = isVisible ? "block" : "none"; diff --git a/src/.gitignore b/src/.gitignore new file mode 100644 index 0000000..b3e292d --- /dev/null +++ b/src/.gitignore @@ -0,0 +1,9 @@ +bin/ +obj/ +.vs/ +.idea/ +artifacts +Release +*.zip +node_modules +dist/ \ No newline at end of file diff --git a/src/Jellyfin.Plugin.MediaBar/Attributes/JellyfinVersionAttribute.cs b/src/Jellyfin.Plugin.MediaBar/Attributes/JellyfinVersionAttribute.cs new file mode 100644 index 0000000..360b97b --- /dev/null +++ b/src/Jellyfin.Plugin.MediaBar/Attributes/JellyfinVersionAttribute.cs @@ -0,0 +1,20 @@ +using System.Reflection; + +namespace Jellyfin.Plugin.MediaBar.Attributes +{ + [AttributeUsage(AttributeTargets.Assembly)] + public class JellyfinVersionAttribute : Attribute + { + public string Version { get; set; } + + public JellyfinVersionAttribute(string version) + { + Version = version; + } + + public static string? GetVersion() + { + return Assembly.GetExecutingAssembly().GetCustomAttribute()?.Version; + } + } +} \ No newline at end of file diff --git a/src/Jellyfin.Plugin.MediaBar/Configuration/PluginConfiguration.cs b/src/Jellyfin.Plugin.MediaBar/Configuration/PluginConfiguration.cs new file mode 100644 index 0000000..d74bcdf --- /dev/null +++ b/src/Jellyfin.Plugin.MediaBar/Configuration/PluginConfiguration.cs @@ -0,0 +1,61 @@ +using MediaBrowser.Model.Plugins; + +namespace Jellyfin.Plugin.MediaBar.Configuration +{ + public enum MediaBarState + { + Disabled, + Enabled, + } + + public class PluginConfiguration : BasePluginConfiguration + { + public MediaBarState Enabled { get; set; } = MediaBarState.Enabled; + + public string VersionString { get; set; } = "main"; + + public bool UseAvatarsFile { get; set; } = true; + + public string AvatarsPlaylist { get; set; } = string.Empty; + + public WebConfig WebConfig { get; set; } = new WebConfig(); + } + + public class WebConfig + { + public ImageSvgs ImageSvgs { get; set; } = new ImageSvgs(); + + public int ShuffleInterval { get; set; } = -1; + + public int RetryInterval { get; set; } = -1; + + public int MinSwipeDistance { get; set; } = -1; + + public int LoadingCheckInterval { get; set; } = -1; + + public int MaxPlotLength { get; set; } = -1; + + public int MaxMovies { get; set; } = -1; + + public int MaxTvShows { get; set; } = -1; + + public int MaxItems { get; set; } = -1; + + public int PreloadCount { get; set; } = -1; + + public int FadeTransitionDuration { get; set; } = -1; + + public bool SlideAnimationEnabled { get; set; } = true; + } + + public class ImageSvgs + { + public string? ImdbLogo { get; set; } = null; + + public string? TomatoLogo { get; set; } = null; + + public string? FreshTomato { get; set; } = null; + + public string? RottenTomato { get; set; } = null; + } +} \ No newline at end of file diff --git a/src/Jellyfin.Plugin.MediaBar/Configuration/config.html b/src/Jellyfin.Plugin.MediaBar/Configuration/config.html new file mode 100644 index 0000000..a5c4e49 --- /dev/null +++ b/src/Jellyfin.Plugin.MediaBar/Configuration/config.html @@ -0,0 +1,262 @@ + + + + Media Bar + + +
+
+
+
+

Media Bar

+ + + Help + +
+
+
+
+ + +
+ +
+
+
+
+ Enabled: + + Whether the media bar should appear or not. +
+
+ + + +
Which version of the jsdelivr'd plugin should be used.
+
+
+ +
If checked, the plugin will look for a list.txt file in the avatars directory at the root of jellyfin-web.
+
+
+ + + +
If populated, and "Use physical avatars file" is disabled, this is the name of the playlist which is used to populate the media bar.
+ If empty, the media bar will randomly populate.
+
+
+
+ +
+ +
+
+ +
+ + \ No newline at end of file diff --git a/src/Jellyfin.Plugin.MediaBar/Controllers/MediaBarController.cs b/src/Jellyfin.Plugin.MediaBar/Controllers/MediaBarController.cs new file mode 100644 index 0000000..183a7ab --- /dev/null +++ b/src/Jellyfin.Plugin.MediaBar/Controllers/MediaBarController.cs @@ -0,0 +1,60 @@ +using System.Reflection; +using Jellyfin.Extensions; +using Jellyfin.Plugin.MediaBar.Configuration; +using Jellyfin.Plugin.MediaBar.Helpers; +using Jellyfin.Plugin.MediaBar.Model; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Playlists; +using Microsoft.AspNetCore.Mvc; +using MediaBrowser.Controller.Entities.TV; + +namespace Jellyfin.Plugin.MediaBar.Controllers +{ + [Route("[controller]")] + public class MediaBarController : ControllerBase + { + [HttpGet("{file}")] + public ActionResult GetFile([FromRoute] string file) + { + Stream fileStream = Assembly.GetExecutingAssembly().GetManifestResourceStream("Jellyfin.Plugin.MediaBar.Inject." + file)!; + string fileContents = new StreamReader(fileStream).ReadToEnd(); + + string contentType = "text/plain"; + + if (Path.GetExtension(file) == ".js") + { + contentType = "text/javascript"; + } + else if (Path.GetExtension(file) == ".css") + { + contentType = "text/css"; + } + else if (Path.GetExtension(file) == ".html") + { + contentType = "text/html"; + } + + return Content(fileContents, contentType); + } + + [HttpPost("Avatar/List")] + public ActionResult GetAvatarsList([FromBody] PatchRequestPayload payload) + { + string? content = TransformationPatches.AvatarsList(payload); + + if (content == null) + { + return NotFound(); + } + + return Content(content, "text/plain"); + } + + [HttpGet("WebConfig")] + public ActionResult GetWebConfig() + { + return Ok(MediaBarPlugin.Instance.Configuration.WebConfig); + } + } +} \ No newline at end of file diff --git a/src/Jellyfin.Plugin.MediaBar/Helpers/TransformationPatches.cs b/src/Jellyfin.Plugin.MediaBar/Helpers/TransformationPatches.cs new file mode 100644 index 0000000..dc0240a --- /dev/null +++ b/src/Jellyfin.Plugin.MediaBar/Helpers/TransformationPatches.cs @@ -0,0 +1,139 @@ +using System.Reflection; +using System.Text.RegularExpressions; +using Jellyfin.Extensions; +using Jellyfin.Plugin.MediaBar.Attributes; +using Jellyfin.Plugin.MediaBar.Configuration; +using Jellyfin.Plugin.MediaBar.Model; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.TV; +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Playlists; +using Microsoft.Extensions.DependencyInjection; + +namespace Jellyfin.Plugin.MediaBar.Helpers +{ + public static class TransformationPatches + { + public static string AvatarsList(PatchRequestPayload payload) + { + IPlaylistManager playlistManager = MediaBarPlugin.Instance.ServiceProvider.GetRequiredService(); + IUserManager userManager = MediaBarPlugin.Instance.ServiceProvider.GetRequiredService(); + + return AvatarsList(payload, playlistManager, userManager) ?? ""; + } + + private static string? AvatarsList(PatchRequestPayload payload, IPlaylistManager playlistManager, IUserManager userManager) + { + if (MediaBarPlugin.Instance.Configuration.UseAvatarsFile) + { + return payload.Contents; + } + + IEnumerable allUserIds = userManager.UsersIds; + + Playlist? playlist = null; + Guid? userIdToUse = null; + + foreach (Guid userId in allUserIds) + { + playlist = playlistManager.GetPlaylists(userId) + .FirstOrDefault(x => x.Name == MediaBarPlugin.Instance.Configuration.AvatarsPlaylist); + + if (playlist != null) + { + userIdToUse = userId; + break; + } + } + + if (playlist == null || userIdToUse == null) + { + return payload.Contents; + } + + IEnumerable> itemsRaw = playlist.GetManageableItems() + .Where(i => i.Item2.IsVisible(userManager.GetUserById(userIdToUse.Value))); + + StringWriter stringWriter = new StringWriter(); + + stringWriter.WriteLine(MediaBarPlugin.Instance.Configuration.AvatarsPlaylist); + + List idsWritten = new List(); + + foreach (Tuple item in itemsRaw) + { + BaseItem itemToUse = item.Item2; + if (item.Item2 is Episode episode) + { + itemToUse = episode.Series; + } + + if (!idsWritten.Contains(itemToUse.Id)) + { + idsWritten.Add(itemToUse.Id); + } + } + + idsWritten.Shuffle(); + + foreach (Guid id in idsWritten) + { + // For some reason the JF api doesn't treat GUIDs correctly + stringWriter.WriteLine(id.ToString().Replace("-", "")); + } + + return stringWriter.ToString(); + } + + public static string IndexHtml(PatchRequestPayload payload) + { + if (MediaBarPlugin.Instance.Configuration.Enabled == MediaBarState.Disabled) + { + return payload.Contents ?? string.Empty; + } + + Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream($"{typeof(MediaBarPlugin).Namespace}.Inject.index.html")!; + using TextReader reader = new StreamReader(stream); + + if (MediaBarPlugin.Instance.Configuration.VersionString == "latest") + { + MediaBarPlugin.Instance.Configuration.VersionString = "main"; + } + + if (MediaBarPlugin.Instance.Configuration.VersionString == "main" && + JellyfinVersionAttribute.GetVersion() == "10.11") + { + // Force 10.11 branch instead of main for now + MediaBarPlugin.Instance.Configuration.VersionString = "10.11"; + } + + string importedHtml = reader + .ReadToEnd() + .Replace("{{Config.VersionString}}", MediaBarPlugin.Instance.Configuration.VersionString); + + string regex = Regex.Replace(payload.Contents!, "()", $"{importedHtml}$1"); + + return regex; + } + + public static string HomeHtmlChunk(PatchRequestPayload payload) + { + Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream($"{typeof(MediaBarPlugin).Namespace}.Inject.home-html.chunk.js")!; + using TextReader reader = new StreamReader(stream); + + string regex = Regex.Replace(payload.Contents!, "(id=\"homeTab\" data-index=\"0\">)", $"$1{reader.ReadToEnd()}"); + + return regex; + } + + public static string MainBundle(PatchRequestPayload payload) + { + string replacementText = + "window.PlaybackManager=this.playbackManager;console.log(\"PlaybackManager is now globally available:\",window.PlaybackManager);"; + + string regex = Regex.Replace(payload.Contents!, @"(this\.playbackManager=e,)", $"$1{replacementText}"); + + return regex; + } + } +} \ No newline at end of file diff --git a/src/Jellyfin.Plugin.MediaBar/Inject/index.html b/src/Jellyfin.Plugin.MediaBar/Inject/index.html new file mode 100644 index 0000000..96b23a4 --- /dev/null +++ b/src/Jellyfin.Plugin.MediaBar/Inject/index.html @@ -0,0 +1,68 @@ + + + \ No newline at end of file diff --git a/src/Jellyfin.Plugin.MediaBar/Jellyfin.Plugin.MediaBar.csproj b/src/Jellyfin.Plugin.MediaBar/Jellyfin.Plugin.MediaBar.csproj new file mode 100644 index 0000000..be752d5 --- /dev/null +++ b/src/Jellyfin.Plugin.MediaBar/Jellyfin.Plugin.MediaBar.csproj @@ -0,0 +1,59 @@ + + + + 10.11.2 + $(JellyfinVersion) + $(JellyfinVersion) + 10.11.0 + 10.11.0 + net9.0 + net8.0 + enable + enable + false + 2.4.0.0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Jellyfin.Plugin.MediaBar/JellyfinVersionSpecific/10.10.7/StartupServiceHelper.cs b/src/Jellyfin.Plugin.MediaBar/JellyfinVersionSpecific/10.10.7/StartupServiceHelper.cs new file mode 100644 index 0000000..e7b5ed1 --- /dev/null +++ b/src/Jellyfin.Plugin.MediaBar/JellyfinVersionSpecific/10.10.7/StartupServiceHelper.cs @@ -0,0 +1,15 @@ +using MediaBrowser.Model.Tasks; + +namespace Jellyfin.Plugin.MediaBar.JellyfinVersionSpecific +{ + public static class StartupServiceHelper + { + public static IEnumerable GetDefaultTriggers() + { + yield return new TaskTriggerInfo() + { + Type = TaskTriggerInfo.TriggerStartup + }; + } + } +} \ No newline at end of file diff --git a/src/Jellyfin.Plugin.MediaBar/JellyfinVersionSpecific/10.11/StartupServiceHelper.cs b/src/Jellyfin.Plugin.MediaBar/JellyfinVersionSpecific/10.11/StartupServiceHelper.cs new file mode 100644 index 0000000..30cba08 --- /dev/null +++ b/src/Jellyfin.Plugin.MediaBar/JellyfinVersionSpecific/10.11/StartupServiceHelper.cs @@ -0,0 +1,15 @@ +using MediaBrowser.Model.Tasks; + +namespace Jellyfin.Plugin.MediaBar.JellyfinVersionSpecific +{ + public static class StartupServiceHelper + { + public static IEnumerable GetDefaultTriggers() + { + yield return new TaskTriggerInfo() + { + Type = TaskTriggerInfoType.StartupTrigger + }; + } + } +} \ No newline at end of file diff --git a/src/Jellyfin.Plugin.MediaBar/MediaBarPlugin.cs b/src/Jellyfin.Plugin.MediaBar/MediaBarPlugin.cs new file mode 100644 index 0000000..99882da --- /dev/null +++ b/src/Jellyfin.Plugin.MediaBar/MediaBarPlugin.cs @@ -0,0 +1,37 @@ +using Jellyfin.Plugin.MediaBar.Configuration; +using MediaBrowser.Common.Configuration; +using MediaBrowser.Common.Plugins; +using MediaBrowser.Model.Plugins; +using MediaBrowser.Model.Serialization; + +namespace Jellyfin.Plugin.MediaBar +{ + public class MediaBarPlugin : BasePlugin, IHasPluginConfiguration, IHasWebPages + { + public override Guid Id => Guid.Parse("08f615ea-2107-4f04-89cc-091035f54448"); + + public override string Name => "Media Bar"; + + public static MediaBarPlugin Instance { get; private set; } = null!; + + public IServiceProvider ServiceProvider { get; } + + public MediaBarPlugin(IApplicationPaths applicationPaths, IXmlSerializer xmlSerializer, IServiceProvider serviceProvider) : base(applicationPaths, xmlSerializer) + { + Instance = this; + + ServiceProvider = serviceProvider; + } + + public IEnumerable GetPages() + { + string? prefix = GetType().Namespace; + + yield return new PluginPageInfo + { + Name = Name, + EmbeddedResourcePath = $"{prefix}.Configuration.config.html" + }; + } + } +} \ No newline at end of file diff --git a/src/Jellyfin.Plugin.MediaBar/Model/PatchRequestPayload.cs b/src/Jellyfin.Plugin.MediaBar/Model/PatchRequestPayload.cs new file mode 100644 index 0000000..a43eac2 --- /dev/null +++ b/src/Jellyfin.Plugin.MediaBar/Model/PatchRequestPayload.cs @@ -0,0 +1,10 @@ +using System.Text.Json.Serialization; + +namespace Jellyfin.Plugin.MediaBar.Model +{ + public class PatchRequestPayload + { + [JsonPropertyName("contents")] + public string? Contents { get; set; } + } +} \ No newline at end of file diff --git a/src/Jellyfin.Plugin.MediaBar/PluginServiceRegistrator.cs b/src/Jellyfin.Plugin.MediaBar/PluginServiceRegistrator.cs new file mode 100644 index 0000000..35fa7dc --- /dev/null +++ b/src/Jellyfin.Plugin.MediaBar/PluginServiceRegistrator.cs @@ -0,0 +1,14 @@ +using Jellyfin.Plugin.MediaBar.Services; +using MediaBrowser.Controller; +using MediaBrowser.Controller.Plugins; +using Microsoft.Extensions.DependencyInjection; + +namespace Jellyfin.Plugin.MediaBar +{ + public class PluginServiceRegistrator : IPluginServiceRegistrator + { + public void RegisterServices(IServiceCollection serviceCollection, IServerApplicationHost applicationHost) + { + } + } +} \ No newline at end of file diff --git a/src/Jellyfin.Plugin.MediaBar/Properties/AssemblyInfo.cs b/src/Jellyfin.Plugin.MediaBar/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..d8d2df8 --- /dev/null +++ b/src/Jellyfin.Plugin.MediaBar/Properties/AssemblyInfo.cs @@ -0,0 +1,9 @@ +using System.Reflection; +using Jellyfin.Plugin.MediaBar.Attributes; + +[assembly: AssemblyCompany("IAmParadox27")] +[assembly: AssemblyProduct("Jellyfin.Plugins.MediaBar")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyTitle("Jellyfin.Plugins.MediaBar")] +[assembly: AssemblyVersion("2.4.0.0")] +[assembly: JellyfinVersion("10.11.2")] \ No newline at end of file diff --git a/src/Jellyfin.Plugin.MediaBar/Services/StartupService.cs b/src/Jellyfin.Plugin.MediaBar/Services/StartupService.cs new file mode 100644 index 0000000..91fa6e7 --- /dev/null +++ b/src/Jellyfin.Plugin.MediaBar/Services/StartupService.cs @@ -0,0 +1,94 @@ +using System.IO.Pipes; +using System.Net; +using System.Net.Http.Headers; +using System.Reflection; +using System.Runtime.Loader; +using System.Text; +using Jellyfin.Plugin.MediaBar.Helpers; +using Jellyfin.Plugin.MediaBar.JellyfinVersionSpecific; +using Jellyfin.Plugin.MediaBar.Model; +using MediaBrowser.Common.Configuration; +using MediaBrowser.Controller; +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Playlists; +using MediaBrowser.Model.Tasks; +using Microsoft.Extensions.Logging; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace Jellyfin.Plugin.MediaBar.Services +{ + public class StartupService : IScheduledTask + { + public string Name => "MediaBar Startup"; + + public string Key => "Jellyfin.Plugin.MediaBar.Startup"; + + public string Description => "Startup Service for MediaBar"; + + public string Category => "Startup Services"; + + private readonly IServerApplicationHost m_serverApplicationHost; + private readonly ILogger m_logger; + private readonly IUserManager m_userManager; + private readonly IPlaylistManager m_playlistManager; + + public StartupService(IServerApplicationHost serverApplicationHost, ILogger logger, + IUserManager userManager, IPlaylistManager playlistManager) + { + m_serverApplicationHost = serverApplicationHost; + m_logger = logger; + m_userManager = userManager; + m_playlistManager = playlistManager; + } + + public Task ExecuteAsync(IProgress progress, CancellationToken cancellationToken) + { + m_logger.LogInformation($"MediaBar Startup. Registering file transformations."); + + List payloads = new List(); + + { + JObject payload = new JObject(); + payload.Add("id", "0dfac9d7-d898-4944-900b-1c1837707279"); + payload.Add("fileNamePattern", "index.html"); + payload.Add("callbackAssembly", GetType().Assembly.FullName); + payload.Add("callbackClass", typeof(TransformationPatches).FullName); + payload.Add("callbackMethod", nameof(TransformationPatches.IndexHtml)); + + payloads.Add(payload); + } + { + JObject payload = new JObject(); + payload.Add("id", "8d374d6b-3c5b-464a-a2a2-96e92fa81345"); + payload.Add("fileNamePattern", "avatars/list.txt"); + payload.Add("callbackAssembly", GetType().Assembly.FullName); + payload.Add("callbackClass", typeof(TransformationPatches).FullName); + payload.Add("callbackMethod", nameof(TransformationPatches.AvatarsList)); + + payloads.Add(payload); + } + + Assembly? fileTransformationAssembly = + AssemblyLoadContext.All.SelectMany(x => x.Assemblies).FirstOrDefault(x => + x.FullName?.Contains(".FileTransformation") ?? false); + + if (fileTransformationAssembly != null) + { + Type? pluginInterfaceType = fileTransformationAssembly.GetType("Jellyfin.Plugin.FileTransformation.PluginInterface"); + + if (pluginInterfaceType != null) + { + foreach (JObject payload in payloads) + { + pluginInterfaceType.GetMethod("RegisterTransformation")?.Invoke(null, new object?[] { payload }); + } + } + } + + return Task.CompletedTask; + } + + public IEnumerable GetDefaultTriggers() => StartupServiceHelper.GetDefaultTriggers(); + } +} \ No newline at end of file diff --git a/src/logo.png b/src/logo.png new file mode 100644 index 0000000..d1421be Binary files /dev/null and b/src/logo.png differ