Clean Cache Task to Remove Unused Files (#195)
This commit is contained in:
parent
a9cdaf66b0
commit
ddecb15a51
@ -615,11 +615,6 @@
|
||||
|
||||
<input type="checkbox" id="eraseModeCacheCheckbox" style="margin-left: 10px;">
|
||||
<label for="eraseModeCacheCheckbox" style="margin-left: 5px;">Erase cached fingerprint files</label>
|
||||
<br />
|
||||
|
||||
<button id="btnCleanCache">
|
||||
Clean cache from unused fingerprints
|
||||
</button>
|
||||
</details>
|
||||
</fieldset>
|
||||
</div>
|
||||
@ -644,7 +639,6 @@
|
||||
var support = document.querySelector("details#support");
|
||||
var btnEraseIntroTimestamps = document.querySelector("button#btnEraseIntroTimestamps");
|
||||
var btnEraseCreditTimestamps = document.querySelector("button#btnEraseCreditTimestamps");
|
||||
var btnCleanCache = document.querySelector("button#btnCleanCache");
|
||||
|
||||
// all plugin configuration fields that can be get or set with .value (i.e. strings or numbers).
|
||||
var configurationFields = [
|
||||
@ -1060,25 +1054,6 @@
|
||||
});
|
||||
}
|
||||
|
||||
// erase all intro/credits cache
|
||||
function cleanCache() {
|
||||
const title = "Confirm Cache erasure";
|
||||
const body = "Are you sure you want to erase all unused fingerprints?";
|
||||
|
||||
Dashboard.confirm(
|
||||
body,
|
||||
title,
|
||||
(result) => {
|
||||
if (!result) {
|
||||
return;
|
||||
}
|
||||
|
||||
fetchWithAuth("Intros/CleanCache", "POST", null);
|
||||
|
||||
Dashboard.alert("Cache cleaned");
|
||||
});
|
||||
}
|
||||
|
||||
document.querySelector('#TemplateConfigPage')
|
||||
.addEventListener('pageshow', function () {
|
||||
Dashboard.showLoadingMsg();
|
||||
@ -1136,10 +1111,6 @@
|
||||
eraseTimestamps("Credits");
|
||||
e.preventDefault();
|
||||
});
|
||||
btnCleanCache.addEventListener("click", (e) => {
|
||||
cleanCache();
|
||||
e.preventDefault();
|
||||
});
|
||||
btnSeasonEraseTimestamps.addEventListener("click", () => {
|
||||
Dashboard.confirm(
|
||||
"Are you sure you want to erase all timestamps for this season?",
|
||||
|
@ -139,19 +139,6 @@ public class SkipIntroController : ControllerBase
|
||||
return NoContent();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Erases all previously cached introduction fingerprints.
|
||||
/// </summary>
|
||||
/// <response code="204">Operation successful.</response>
|
||||
/// <returns>No content.</returns>
|
||||
[Authorize(Policy = "RequiresElevation")]
|
||||
[HttpPost("Intros/CleanCache")]
|
||||
public ActionResult CleanIntroCache()
|
||||
{
|
||||
FFmpegWrapper.CleanCacheFiles();
|
||||
return NoContent();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get all introductions or credits. Only used by the end to end testing script.
|
||||
/// </summary>
|
||||
|
@ -4,7 +4,6 @@ using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using Microsoft.Extensions.Logging;
|
||||
@ -641,35 +640,6 @@ public static class FFmpegWrapper
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove a cached episode fingerprint from disk.
|
||||
/// </summary>
|
||||
public static void CleanCacheFiles()
|
||||
{
|
||||
// Get valid episode IDs from the dictionaries
|
||||
HashSet<Guid> validEpisodeIds = new HashSet<Guid>(Plugin.Instance!.Intros.Keys.Concat(Plugin.Instance!.Credits.Keys)); // Or use GetMediaItems instead?
|
||||
|
||||
// Delete invalid cache files
|
||||
foreach (string filePath in Directory.EnumerateFiles(Plugin.Instance!.FingerprintCachePath))
|
||||
{
|
||||
string fileName = Path.GetFileNameWithoutExtension(filePath);
|
||||
|
||||
int dashIndex = fileName.IndexOf('-', StringComparison.Ordinal); // Find the index of the first '-' character
|
||||
if (dashIndex > 0)
|
||||
{
|
||||
fileName = fileName.Substring(0, dashIndex);
|
||||
}
|
||||
|
||||
if (Guid.TryParse(fileName, out Guid episodeId))
|
||||
{
|
||||
if (!validEpisodeIds.Contains(episodeId))
|
||||
{
|
||||
DeleteEpisodeCache(episodeId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines the path an episode should be cached at.
|
||||
/// This function was created before the unified caching mechanism was introduced (in v0.1.7).
|
||||
|
@ -374,6 +374,24 @@ public class Plugin : BasePlugin<PluginConfiguration>, IHasWebPages
|
||||
SaveTimestamps(mode);
|
||||
}
|
||||
|
||||
internal void CleanTimestamps(HashSet<Guid> validEpisodeIds)
|
||||
{
|
||||
var allKeys = new HashSet<Guid>(Instance!.Intros.Keys);
|
||||
allKeys.UnionWith(Instance!.Credits.Keys);
|
||||
|
||||
foreach (var key in allKeys)
|
||||
{
|
||||
if (!validEpisodeIds.Contains(key))
|
||||
{
|
||||
Instance!.Intros.TryRemove(key, out _);
|
||||
Instance!.Credits.TryRemove(key, out _);
|
||||
}
|
||||
}
|
||||
|
||||
SaveTimestamps(AnalysisMode.Introduction);
|
||||
SaveTimestamps(AnalysisMode.Credits);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inject the skip button script into the web interface.
|
||||
/// </summary>
|
||||
|
@ -0,0 +1,117 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Model.Tasks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace ConfusedPolarBear.Plugin.IntroSkipper;
|
||||
|
||||
/// <summary>
|
||||
/// Analyze all television episodes for introduction sequences.
|
||||
/// </summary>
|
||||
public class CleanCacheTask : IScheduledTask
|
||||
{
|
||||
private readonly ILogger<CleanCacheTask> _logger;
|
||||
|
||||
private readonly ILoggerFactory _loggerFactory;
|
||||
|
||||
private readonly ILibraryManager _libraryManager;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CleanCacheTask"/> class.
|
||||
/// </summary>
|
||||
/// <param name="loggerFactory">Logger factory.</param>
|
||||
/// <param name="libraryManager">Library manager.</param>
|
||||
/// <param name="logger">Logger.</param>
|
||||
public CleanCacheTask(
|
||||
ILogger<CleanCacheTask> logger,
|
||||
ILoggerFactory loggerFactory,
|
||||
ILibraryManager libraryManager)
|
||||
{
|
||||
_logger = logger;
|
||||
_loggerFactory = loggerFactory;
|
||||
_libraryManager = libraryManager;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the task name.
|
||||
/// </summary>
|
||||
public string Name => "Clean Intro Skipper Cache";
|
||||
|
||||
/// <summary>
|
||||
/// Gets the task category.
|
||||
/// </summary>
|
||||
public string Category => "Intro Skipper";
|
||||
|
||||
/// <summary>
|
||||
/// Gets the task description.
|
||||
/// </summary>
|
||||
public string Description => "Clear Intro Skipper cache of unused files.";
|
||||
|
||||
/// <summary>
|
||||
/// Gets the task key.
|
||||
/// </summary>
|
||||
public string Key => "CPBIntroSkipperCleanCache";
|
||||
|
||||
/// <summary>
|
||||
/// Cleans the Intro Skipper cache by removing files that are no longer associated with episodes in the library.
|
||||
/// </summary>
|
||||
/// <param name="progress">Task progress.</param>
|
||||
/// <param name="cancellationToken">Cancellation token.</param>
|
||||
/// <returns>Task.</returns>
|
||||
public Task ExecuteAsync(IProgress<double> progress, CancellationToken cancellationToken)
|
||||
{
|
||||
if (_libraryManager is null)
|
||||
{
|
||||
throw new InvalidOperationException("Library manager was null");
|
||||
}
|
||||
|
||||
var queueManager = new QueueManager(
|
||||
_loggerFactory.CreateLogger<QueueManager>(),
|
||||
_libraryManager);
|
||||
|
||||
// Retrieve media items and get valid episode IDs
|
||||
var queue = queueManager.GetMediaItems();
|
||||
var validEpisodeIds = new HashSet<Guid>(queue.Values.SelectMany(episodes => episodes.Select(e => e.EpisodeId)));
|
||||
|
||||
Plugin.Instance!.CleanTimestamps(validEpisodeIds);
|
||||
|
||||
// Identify invalid episode IDs
|
||||
var invalidEpisodeIds = Directory.EnumerateFiles(Plugin.Instance!.FingerprintCachePath)
|
||||
.Select(filePath =>
|
||||
{
|
||||
var fileName = Path.GetFileNameWithoutExtension(filePath);
|
||||
var episodeIdStr = fileName.Split('-')[0];
|
||||
if (Guid.TryParse(episodeIdStr, out Guid episodeId))
|
||||
{
|
||||
return validEpisodeIds.Contains(episodeId) ? (Guid?)null : episodeId;
|
||||
}
|
||||
|
||||
return null;
|
||||
})
|
||||
.OfType<Guid>()
|
||||
.ToHashSet();
|
||||
|
||||
// Delete cache files for invalid episode IDs
|
||||
foreach (var episodeId in invalidEpisodeIds)
|
||||
{
|
||||
_logger.LogDebug("Deleting cache files for episode ID: {EpisodeId}", episodeId);
|
||||
FFmpegWrapper.DeleteEpisodeCache(episodeId);
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get task triggers.
|
||||
/// </summary>
|
||||
/// <returns>Task triggers.</returns>
|
||||
public IEnumerable<TaskTriggerInfo> GetDefaultTriggers()
|
||||
{
|
||||
return Array.Empty<TaskTriggerInfo>();
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user