120 lines
4.2 KiB
C#
120 lines
4.2 KiB
C#
using System;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using Microsoft.Extensions.Logging;
|
|
using MediaBrowser.Common.Configuration;
|
|
|
|
namespace Jellyfin.Plugin.Seasonals;
|
|
|
|
public class ScriptInjector
|
|
{
|
|
private readonly IApplicationPaths _appPaths;
|
|
private readonly ILogger<ScriptInjector> _logger;
|
|
private const string ScriptTag = "<script src=\"Seasonals/Resources/seasonals.js\"></script>";
|
|
private const string Marker = "</body>";
|
|
|
|
public ScriptInjector(IApplicationPaths appPaths, ILogger<ScriptInjector> logger)
|
|
{
|
|
_appPaths = appPaths;
|
|
_logger = logger;
|
|
}
|
|
|
|
public void Inject()
|
|
{
|
|
try
|
|
{
|
|
var webPath = GetWebPath();
|
|
if (string.IsNullOrEmpty(webPath))
|
|
{
|
|
_logger.LogWarning("Could not find Jellyfin web path. Script injection skipped.");
|
|
return;
|
|
}
|
|
|
|
var indexPath = Path.Combine(webPath, "index.html");
|
|
if (!File.Exists(indexPath))
|
|
{
|
|
_logger.LogWarning("index.html not found at {Path}. Script injection skipped.", indexPath);
|
|
return;
|
|
}
|
|
|
|
var content = File.ReadAllText(indexPath);
|
|
if (content.Contains(ScriptTag))
|
|
{
|
|
_logger.LogInformation("Seasonals script already injected.");
|
|
return;
|
|
}
|
|
|
|
var newContent = content.Replace(Marker, $"{ScriptTag}\n{Marker}");
|
|
if (newContent == content)
|
|
{
|
|
_logger.LogWarning("Could not find closing body tag in index.html. Script injection skipped.");
|
|
return;
|
|
}
|
|
|
|
File.WriteAllText(indexPath, newContent);
|
|
_logger.LogInformation("Successfully injected Seasonals script into index.html.");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Error injecting Seasonals script.");
|
|
}
|
|
}
|
|
|
|
public void Remove()
|
|
{
|
|
try
|
|
{
|
|
var webPath = GetWebPath();
|
|
if (string.IsNullOrEmpty(webPath)) return;
|
|
|
|
var indexPath = Path.Combine(webPath, "index.html");
|
|
if (!File.Exists(indexPath)) return;
|
|
|
|
var content = File.ReadAllText(indexPath);
|
|
if (!content.Contains(ScriptTag)) return;
|
|
|
|
var newContent = content.Replace(ScriptTag, "").Replace($"{ScriptTag}\n", "");
|
|
File.WriteAllText(indexPath, newContent);
|
|
_logger.LogInformation("Successfully removed Seasonals script from index.html.");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Error removing Seasonals script.");
|
|
}
|
|
}
|
|
|
|
private string? GetWebPath()
|
|
{
|
|
// Try to find the web path using IApplicationPaths
|
|
// Note: The property name might vary depending on the Jellyfin version,
|
|
// but usually it's accessible via the configuration or standard paths.
|
|
// For this plugin context, we'll try to rely on the standard path structure if IApplicationPaths doesn't expose it directly
|
|
// or if we need to infer it.
|
|
|
|
// In many Jellyfin versions, appPaths.WebPath is the property.
|
|
// However, since we are in a plugin, we might need to use reflection if the interface doesn't expose it in the reference assembly,
|
|
// or just assume it's there.
|
|
|
|
// Let's try to use the property if it exists.
|
|
// If the compilation fails, we will adjust.
|
|
// For now, we assume 'WebPath' is available on IApplicationPaths implementation
|
|
// but it might not be on the interface in the nuget package.
|
|
|
|
// Workaround: Check known locations if property is missing or use reflection.
|
|
|
|
// Attempt 1: Reflection to get WebPath property (safest if interface varies)
|
|
var prop = _appPaths.GetType().GetProperty("WebPath");
|
|
if (prop != null)
|
|
{
|
|
return prop.GetValue(_appPaths) as string;
|
|
}
|
|
|
|
// Attempt 2: Guess based on ProgramDataPath (common in Windows)
|
|
// Usually <ProgramData>/jellyfin/web or <InstallDir>/jellyfin-web
|
|
|
|
// Let's try to look relative to the application executable if possible, but that's hard from a plugin.
|
|
|
|
return null;
|
|
}
|
|
}
|