using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Controller;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
namespace Jellyfin.Plugin.ShareLinks.Web;
///
/// Best-effort extra: injects the ShareLinks client script into Jellyfin Web's
/// index.html on disk at startup, using explicit markers so the edit can be
/// applied and removed repeatedly without drift.
/// adds the same tag while Jellyfin serves the page, which is what makes the
/// guest flow work even when this cannot write to disk.
///
public sealed class WebInjectionHostedService : IHostedService
{
private const string Begin = "";
private const string End = "";
private readonly IServerApplicationPaths _paths;
private readonly ILogger _logger;
/// Initializes a new instance of the class.
public WebInjectionHostedService(IServerApplicationPaths paths, ILogger logger)
{
_paths = paths;
_logger = logger;
}
private string IndexPath => Path.Combine(_paths.WebPath, "index.html");
///
public Task StartAsync(CancellationToken cancellationToken)
{
try
{
Inject();
}
catch (Exception ex)
{
_logger.LogDebug(ex, "ShareLinks: could not write the script tag into index.html, it is added when the page is served instead.");
}
return Task.CompletedTask;
}
///
public Task StopAsync(CancellationToken cancellationToken)
{
// Leave the marker in place. Some Jellyfin containers expose the web
// client as root-owned files: startup injection may need a deployment
// helper, and removing the marker on shutdown would make it vanish on
// every restart.
return Task.CompletedTask;
}
private void Inject()
{
var path = IndexPath;
if (!File.Exists(path))
{
_logger.LogWarning("ShareLinks: web index.html not found at {Path}.", path);
return;
}
var html = File.ReadAllText(path);
if (html.Contains(Begin, StringComparison.Ordinal))
{
return;
}
TryBackup(path, path + ".sharelinks.bak");
var snippet = "\n" + Begin + "\n\n" + End + "\n";
var bodyIndex = html.LastIndexOf("