diff --git a/src/Jellyfin.Plugin.MediaBar/Controllers/MediaBarController.cs b/src/Jellyfin.Plugin.MediaBar/Controllers/MediaBarController.cs index 9193c35..38db0f9 100644 --- a/src/Jellyfin.Plugin.MediaBar/Controllers/MediaBarController.cs +++ b/src/Jellyfin.Plugin.MediaBar/Controllers/MediaBarController.cs @@ -1,32 +1,57 @@ using System.Reflection; +using System.Text.RegularExpressions; +using Jellyfin.Plugin.MediaBar.Model; using Microsoft.AspNetCore.Mvc; -namespace Jellyfin.Plugin.MediaBar.Controllers; - -[Route("[controller]")] -public class MediaBarController : ControllerBase +namespace Jellyfin.Plugin.MediaBar.Controllers { - [HttpGet("{file}")] - public ActionResult GetFile([FromRoute] string file) + [Route("[controller]")] + public class MediaBarController : ControllerBase { - Stream fileStream = Assembly.GetExecutingAssembly().GetManifestResourceStream("Jellyfin.Plugin.MediaBar.Inject." + file); - string fileContents = new StreamReader(fileStream).ReadToEnd(); + [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"; + 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"; - } + 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); + return Content(fileContents, contentType); + } + + [HttpPost("Patch/IndexHtml")] + public ActionResult PatchIndexHtml([FromBody] PatchRequestPayload payload) + { + Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream($"{typeof(MediaBarPlugin).Namespace}.Inject.index.html")!; + using TextReader reader = new StreamReader(stream); + + string regex = Regex.Replace(payload.Contents!, "()", $"{reader.ReadToEnd()}$1"); + + return Content(regex, "text/html"); + } + + [HttpPost("Patch/HomeHtmlChunk")] + public ActionResult PatchHomeHtmlChunk([FromBody] 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 Content(regex, "text/html"); + } } } \ 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 index 22b4945..3d31bab 100644 --- a/src/Jellyfin.Plugin.MediaBar/Jellyfin.Plugin.MediaBar.csproj +++ b/src/Jellyfin.Plugin.MediaBar/Jellyfin.Plugin.MediaBar.csproj @@ -5,11 +5,16 @@ enable enable false - 1.0.0 + 2.0.0 - + + + + + + @@ -25,4 +30,7 @@ + + + diff --git a/src/Jellyfin.Plugin.MediaBar/MediaBarPlugin.cs b/src/Jellyfin.Plugin.MediaBar/MediaBarPlugin.cs index 5536311..172ac70 100644 --- a/src/Jellyfin.Plugin.MediaBar/MediaBarPlugin.cs +++ b/src/Jellyfin.Plugin.MediaBar/MediaBarPlugin.cs @@ -1,56 +1,18 @@ -using System.Reflection; -using System.Text.RegularExpressions; -using Jellyfin.Plugin.FileTransformation.Controller; -using Jellyfin.Plugin.FileTransformation.Infrastructure; -using MediaBrowser.Common.Configuration; +using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Plugins; using MediaBrowser.Model.Plugins; using MediaBrowser.Model.Serialization; -using Microsoft.Extensions.DependencyInjection; -namespace Jellyfin.Plugin.MediaBar; - -public class MediaBarPlugin : BasePlugin +namespace Jellyfin.Plugin.MediaBar { - public override Guid Id => Guid.Parse("08f615ea-2107-4f04-89cc-091035f54448"); + public class MediaBarPlugin : BasePlugin + { + public override Guid Id => Guid.Parse("08f615ea-2107-4f04-89cc-091035f54448"); - public override string Name => "Media Bar"; + public override string Name => "Media Bar"; - public MediaBarPlugin(IApplicationPaths applicationPaths, IXmlSerializer xmlSerializer, IServiceProvider serviceProvider) : base(applicationPaths, xmlSerializer) - { - IWebFileTransformationWriteService webFileTransformationWriteService = serviceProvider.GetRequiredService(); - - webFileTransformationWriteService.AddTransformation("index.html", IndexHtml_Transformation); - webFileTransformationWriteService.AddTransformation("home-html\\.[a-zA-z0-9]+\\.chunk\\.js", HomeHtmlChunk_Transformation); - } - - private void IndexHtml_Transformation(string path, Stream contents) - { - Stream? stream = Assembly.GetExecutingAssembly().GetManifestResourceStream($"{GetType().Namespace}.Inject.index.html"); - using TextReader reader = new StreamReader(stream); - - using var textReader = new StreamReader(contents, null, true, -1, true); - var text = textReader.ReadToEnd(); - - var regex = Regex.Replace(text, "()", $"{reader.ReadToEnd()}$1"); - contents.Seek(0, SeekOrigin.Begin); - - using var textWriter = new StreamWriter(contents, null, -1, true); - textWriter.Write(regex); - } - - private void HomeHtmlChunk_Transformation(string path, Stream contents) - { - Stream? stream = Assembly.GetExecutingAssembly().GetManifestResourceStream($"{GetType().Namespace}.Inject.home-html.chunk.js"); - using TextReader reader = new StreamReader(stream); - - using var textReader = new StreamReader(contents, null, true, -1, true); - var text = textReader.ReadToEnd(); - - var regex = Regex.Replace(text, "(id=\"homeTab\" data-index=\"0\">)", $"$1{reader.ReadToEnd()}"); - contents.Seek(0, SeekOrigin.Begin); - - using var textWriter = new StreamWriter(contents, null, -1, true); - textWriter.Write(regex); + public MediaBarPlugin(IApplicationPaths applicationPaths, IXmlSerializer xmlSerializer, IServiceProvider serviceProvider) : base(applicationPaths, xmlSerializer) + { + } } } \ 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/Services/StartupService.cs b/src/Jellyfin.Plugin.MediaBar/Services/StartupService.cs new file mode 100644 index 0000000..4f45027 --- /dev/null +++ b/src/Jellyfin.Plugin.MediaBar/Services/StartupService.cs @@ -0,0 +1,82 @@ +using System.Net.Http.Headers; +using System.Reflection; +using MediaBrowser.Common.Configuration; +using MediaBrowser.Controller; +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; + + public StartupService(IServerApplicationHost serverApplicationHost, ILogger logger) + { + m_serverApplicationHost = serverApplicationHost; + m_logger = logger; + } + + public async Task ExecuteAsync(IProgress progress, CancellationToken cancellationToken) + { + List payloads = new List(); + + { + JObject payload = new JObject(); + payload.Add("id", "0dfac9d7-d898-4944-900b-1c1837707279"); + payload.Add("fileNamePattern", "index.html"); + payload.Add("tranformationEndpoint", "/MediaBar/Patch/IndexHtml"); + + payloads.Add(payload); + } + { + JObject payload = new JObject(); + payload.Add("id", "e6d32b76-d54b-4946-b73e-c5c9c50575c9"); + payload.Add("fileNamePattern", "home-html\\.[a-zA-z0-9]+\\.chunk\\.js"); + payload.Add("tranformationEndpoint", "/MediaBar/Patch/HomeHtmlChunk"); + + payloads.Add(payload); + } + + string? publishedServerUrl = m_serverApplicationHost.GetType() + .GetProperty("PublishedServerUrl", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(m_serverApplicationHost) as string; + + foreach (JObject payload in payloads) + { + HttpClient client = new HttpClient(); + client.BaseAddress = new Uri(publishedServerUrl ?? $"http://localhost:{m_serverApplicationHost.HttpPort}"); + + try + { + await client.PostAsync("/FileTransformation/RegisterTransformation", + new StringContent(payload.ToString(Formatting.None), + MediaTypeHeaderValue.Parse("application/json"))); + } + catch (Exception ex) + { + m_logger.LogError(ex, $"Caught exception when attempting to register file transformation. Ensure you have `File Transformation` plugin installed on your server."); + return; + } + } + } + + public IEnumerable GetDefaultTriggers() + { + yield return new TaskTriggerInfo() + { + Type = TaskTriggerInfo.TriggerStartup + }; + } + } +} \ No newline at end of file