using System; using System.IO; using MediaBrowser.Common.Configuration; using Microsoft.Extensions.Logging; namespace Jellyfin.Plugin.JellyLMS.Services; /// /// Injects (or removes) a script tag in the web client's index.html /// that adds a floating button linking to the JellyLMS remote control page. /// This follows the pattern used by other Jellyfin plugins (e.g. Intro Skipper) /// since there is no official plugin hook for adding buttons to the web client. /// public static class WebClientPatchService { private const string Marker = ""; private const string ScriptTag = ""; private const string Injected = ScriptTag + Marker + "\n"; /// /// Ensures the web client's index.html either has or does not have the /// JellyLMS remote button script injected, matching . /// /// The Jellyfin application paths. /// Whether the remote button script should be present. /// The logger. public static void Apply(IApplicationPaths applicationPaths, bool enableButton, ILogger logger) { var indexPath = Path.Combine(applicationPaths.WebPath, "index.html"); try { if (!File.Exists(indexPath)) { logger.LogDebug("JellyLMS: web client index.html not found at {Path}", indexPath); return; } var html = File.ReadAllText(indexPath); var hasMarker = html.Contains(Marker, StringComparison.Ordinal); if (enableButton && !hasMarker) { var patched = ReplaceLast(html, "", Injected); File.WriteAllText(indexPath, patched); logger.LogInformation("JellyLMS: injected remote control button into {Path}", indexPath); } else if (!enableButton && hasMarker) { var patched = html.Replace(ScriptTag + Marker + "\n", string.Empty, StringComparison.Ordinal) .Replace(ScriptTag + Marker, string.Empty, StringComparison.Ordinal); File.WriteAllText(indexPath, patched); logger.LogInformation("JellyLMS: removed remote control button from {Path}", indexPath); } } catch (Exception ex) when (ex is IOException or UnauthorizedAccessException) { logger.LogWarning(ex, "JellyLMS: failed to patch web client index.html at {Path}", indexPath); } } private static string ReplaceLast(string source, string find, string replace) { var index = source.LastIndexOf(find, StringComparison.Ordinal); if (index < 0) { return source; } return source[..index] + replace + source[(index + find.Length)..]; } }