Files
Gabrieal Jimmy f321976d70 init
2026-07-16 13:14:58 -05:00

107 lines
3.7 KiB
C#

using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
namespace Jellyfin.Plugin.RedditComments.Services;
/// <summary>
/// Injects the plugin's script tag into the Jellyfin web client's index.html at startup,
/// so the player gets the comments button. Re-applies automatically after web client updates.
/// </summary>
public class WebScriptInjector : IHostedService
{
private const string ScriptMarker = "RedditComments/Static/reddit-comments.js";
private readonly ILogger<WebScriptInjector> _logger;
private readonly IApplicationPaths _applicationPaths;
private readonly IServerConfigurationManager _configurationManager;
/// <summary>
/// Initializes a new instance of the <see cref="WebScriptInjector"/> class.
/// </summary>
/// <param name="logger">Logger.</param>
/// <param name="applicationPaths">Application paths.</param>
/// <param name="configurationManager">Server configuration manager.</param>
public WebScriptInjector(
ILogger<WebScriptInjector> logger,
IApplicationPaths applicationPaths,
IServerConfigurationManager configurationManager)
{
_logger = logger;
_applicationPaths = applicationPaths;
_configurationManager = configurationManager;
}
/// <inheritdoc />
public Task StartAsync(CancellationToken cancellationToken)
{
try
{
InjectScriptTag();
}
catch (Exception ex)
{
_logger.LogWarning(
ex,
"Could not inject the Reddit Comments script into the web client. The API will still work; "
+ "to enable the player button, add this tag to index.html of jellyfin-web manually: {Tag}",
BuildScriptTag());
}
return Task.CompletedTask;
}
/// <inheritdoc />
public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
private string BuildScriptTag()
{
var baseUrl = string.Empty;
try
{
if (_configurationManager.GetConfiguration("network") is NetworkConfiguration networkConfiguration)
{
baseUrl = (networkConfiguration.BaseUrl ?? string.Empty).TrimEnd('/');
}
}
catch (Exception ex)
{
_logger.LogDebug(ex, "Could not read the configured base URL, assuming none");
}
return string.Format(System.Globalization.CultureInfo.InvariantCulture, "<script src=\"{0}/{1}\" defer></script>", baseUrl, ScriptMarker);
}
private void InjectScriptTag()
{
var indexPath = Path.Combine(_applicationPaths.WebPath, "index.html");
if (!File.Exists(indexPath))
{
_logger.LogWarning("jellyfin-web index.html not found at {Path}, skipping script injection", indexPath);
return;
}
var contents = File.ReadAllText(indexPath);
if (contents.Contains(ScriptMarker, StringComparison.Ordinal))
{
_logger.LogDebug("Reddit Comments script tag already present in index.html");
return;
}
var tag = BuildScriptTag();
var bodyIndex = contents.LastIndexOf("</body>", StringComparison.OrdinalIgnoreCase);
contents = bodyIndex >= 0
? contents.Insert(bodyIndex, tag + Environment.NewLine)
: contents + Environment.NewLine + tag + Environment.NewLine;
File.WriteAllText(indexPath, contents);
_logger.LogInformation("Injected Reddit Comments script tag into {Path}", indexPath);
}
}