Compare commits

...

4 Commits

Author SHA1 Message Date
Kilian von Pflugk
bf258c1efb fix typos 2024-11-30 22:16:48 +01:00
Kilian von Pflugk
886908c636 Merge branch '10.10' into jellyfin_selections 2024-11-30 22:06:34 +01:00
Kilian von Pflugk
a8753a03a3 also remove AnalyzeMovies 2024-11-24 18:21:23 +01:00
Kilian von Pflugk
f20ccaed42 handle library selection by jellyfin 2024-11-24 17:53:07 +01:00
6 changed files with 108 additions and 104 deletions

View File

@ -1,7 +1,6 @@
// Copyright (C) 2024 Intro-Skipper contributors <intro-skipper.org> // Copyright (C) 2024 Intro-Skipper contributors <intro-skipper.org>
// SPDX-License-Identifier: GPL-3.0-only. // SPDX-License-Identifier: GPL-3.0-only.
using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using IntroSkipper.Data; using IntroSkipper.Data;
using MediaBrowser.Model.Plugins; using MediaBrowser.Model.Plugins;
@ -22,21 +21,6 @@ public class PluginConfiguration : BasePluginConfiguration
// ===== Analysis settings ===== // ===== Analysis settings =====
/// <summary>
/// Gets or sets the comma separated list of library names to analyze.
/// </summary>
public string SelectedLibraries { get; set; } = string.Empty;
/// <summary>
/// Gets or sets a value indicating whether all libraries should be analyzed.
/// </summary>
public bool SelectAllLibraries { get; set; } = true;
/// <summary>
/// Gets or sets a value indicating whether movies should be analyzed.
/// </summary>
public bool AnalyzeMovies { get; set; }
/// <summary> /// <summary>
/// Gets or sets the list of client to auto skip for. /// Gets or sets the list of client to auto skip for.
/// </summary> /// </summary>
@ -299,4 +283,21 @@ public class PluginConfiguration : BasePluginConfiguration
/// Gets or sets a value indicating whether the ManifestUrl is self-managed, e.g. for mainland China. /// Gets or sets a value indicating whether the ManifestUrl is self-managed, e.g. for mainland China.
/// </summary> /// </summary>
public bool OverrideManifestUrl { get; set; } public bool OverrideManifestUrl { get; set; }
// ===== Deprecated =====
/// <summary>
/// Gets or sets the comma separated list of library names to analyze.
/// </summary>
public string SelectedLibraries { get; set; } = string.Empty;
/// <summary>
/// Gets or sets a value indicating whether all libraries should be analyzed.
/// </summary>
public bool SelectAllLibraries { get; set; } = true;
/// <summary>
/// Gets or sets a value indicating whether movies should be analyzed.
/// </summary>
public bool AnalyzeMovies { get; set; }
} }

View File

@ -55,13 +55,6 @@
</div> </div>
</div> </div>
<div class="checkboxContainer">
<label class="emby-checkbox-label">
<input id="AnalyzeMovies" type="checkbox" is="emby-checkbox" />
<span>Analyze Movies</span>
</label>
</div>
<div class="checkboxContainer checkboxContainer-withDescription"> <div class="checkboxContainer checkboxContainer-withDescription">
<label class="emby-checkbox-label"> <label class="emby-checkbox-label">
<input id="AnalyzeSeasonZero" type="checkbox" is="emby-checkbox" /> <input id="AnalyzeSeasonZero" type="checkbox" is="emby-checkbox" />
@ -73,22 +66,6 @@
</div> </div>
</div> </div>
<div class="checkboxContainer checkboxContainer-withDescription">
<label class="emby-checkbox-label">
<input id="SelectAllLibraries" type="checkbox" is="emby-checkbox" />
<span>Enable analysis for all libraries containing television episodes</span>
</label>
<div class="folderAccessListContainer">
<div class="folderAccess">
<h3 class="checkboxListLabel">Limit analysis to the following libraries</h3>
<div class="checkboxList paperList" style="padding: 0.5em 1em" id="libraryCheckboxes"></div>
</div>
<label class="inputLabel" for="SelectedLibraries"></label>
<input id="SelectedLibraries" type="hidden" is="emby-input" />
</div>
</div>
<details id="intro_reqs"> <details id="intro_reqs">
<summary>Modify Segment Parameters</summary> <summary>Modify Segment Parameters</summary>
@ -762,7 +739,6 @@
var configurationFields = [ var configurationFields = [
// analysis // analysis
"MaxParallelism", "MaxParallelism",
"SelectedLibraries",
"ClientList", "ClientList",
"AnalysisPercent", "AnalysisPercent",
"AnalysisLengthLimit", "AnalysisLengthLimit",
@ -792,7 +768,22 @@
"AutoSkipNotificationText", "AutoSkipNotificationText",
]; ];
var booleanConfigurationFields = ["AutoDetectIntros", "AnalyzeMovies", "AnalyzeSeasonZero", "SelectAllLibraries", "UpdateMediaSegments", "RebuildMediaSegments", "ScanIntroduction", "ScanCredits", "ScanRecap", "ScanPreview", "CacheFingerprints", "PluginSkip", "AutoSkip", "SkipFirstEpisode", "PersistSkipButton", "SkipButtonEnabled"]; var booleanConfigurationFields = [
"AutoDetectIntros",
"AnalyzeSeasonZero",
"UpdateMediaSegments",
"RebuildMediaSegments",
"ScanIntroduction",
"ScanCredits",
"ScanRecap",
"ScanPreview",
"CacheFingerprints",
"PluginSkip",
"AutoSkip",
"SkipFirstEpisode",
"PersistSkipButton",
"SkipButtonEnabled"
];
// visualizer elements // visualizer elements
var analyzerActionsSection = document.querySelector("div#analyzerActionsSection"); var analyzerActionsSection = document.querySelector("div#analyzerActionsSection");
@ -823,15 +814,12 @@
var windowHashInterval = 0; var windowHashInterval = 0;
var analyzeMovies = document.getElementById("AnalyzeMovies");
var pluginSkip = document.getElementById("PluginSkip"); var pluginSkip = document.getElementById("PluginSkip");
var serverSkipSettings = document.getElementById("ServerSkipSettings"); var serverSkipSettings = document.getElementById("ServerSkipSettings");
var autoSkip = document.getElementById("AutoSkip"); var autoSkip = document.getElementById("AutoSkip");
var skipButtonVisible = document.getElementById("SkipButtonEnabled"); var skipButtonVisible = document.getElementById("SkipButtonEnabled");
var skipButtonVisibleLabel = document.getElementById("SkipButtonVisibleLabel"); var skipButtonVisibleLabel = document.getElementById("SkipButtonVisibleLabel");
var skipButtonSettings = document.getElementById("SkipButtonSettings"); var skipButtonSettings = document.getElementById("SkipButtonSettings");
var selectAllLibraries = document.querySelector("input#SelectAllLibraries");
var librariesContainer = document.querySelector("div.folderAccessListContainer");
var skipFirstEpisode = document.getElementById("divSkipFirstEpisode"); var skipFirstEpisode = document.getElementById("divSkipFirstEpisode");
var secondsOfIntroStartToPlay = document.getElementById("divSecondsOfIntroStartToPlay"); var secondsOfIntroStartToPlay = document.getElementById("divSecondsOfIntroStartToPlay");
var autoSkipClientList = document.querySelector("div.AutoSkipClientListContainer"); var autoSkipClientList = document.querySelector("div.AutoSkipClientListContainer");
@ -863,16 +851,6 @@
autoSkip.addEventListener("change", autoSkipChanged); autoSkip.addEventListener("change", autoSkipChanged);
function selectAllLibrariesChanged() {
if (selectAllLibraries.checked) {
librariesContainer.style.display = "none";
} else {
librariesContainer.style.display = "unset";
}
}
selectAllLibraries.addEventListener("change", selectAllLibrariesChanged);
function updateList(textField, container) { function updateList(textField, container) {
textField.value = Array.from(container.querySelectorAll('input[type="checkbox"]:checked')) textField.value = Array.from(container.querySelectorAll('input[type="checkbox"]:checked'))
.map((checkbox) => checkbox.nextElementSibling.textContent) .map((checkbox) => checkbox.nextElementSibling.textContent)
@ -911,13 +889,6 @@
generateCheckboxList(types, "autoSkipTypeCheckboxes", "TypeList"); generateCheckboxList(types, "autoSkipTypeCheckboxes", "TypeList");
} }
async function populateLibraries() {
const response = await getJson("Library/VirtualFolders");
const tvLibraries = response.filter((item) => item.CollectionType === undefined || item.CollectionType === "tvshows" || item.CollectionType === "movies");
const libraryNames = tvLibraries.map((lib) => lib.Name || "Unnamed Library");
generateCheckboxList(libraryNames, "libraryCheckboxes", "SelectedLibraries");
}
var persistSkip = document.getElementById("PersistSkipButton"); var persistSkip = document.getElementById("PersistSkipButton");
var showAdjustment = document.querySelector("div#divShowPromptAdjustment"); var showAdjustment = document.querySelector("div#divShowPromptAdjustment");
var hideAdjustment = document.querySelector("div#divHidePromptAdjustment"); var hideAdjustment = document.querySelector("div#divHidePromptAdjustment");
@ -949,16 +920,6 @@
pluginSkip.addEventListener("change", pluginSkipSettingChanged); pluginSkip.addEventListener("change", pluginSkipSettingChanged);
async function analyzeMoviesChanged() {
if (analyzeMovies.checked) {
movieCreditsDuration.style.display = "unset";
} else {
movieCreditsDuration.style.display = "none";
}
}
analyzeMovies.addEventListener("change", analyzeMoviesChanged);
// when the fingerprint visualizer opens, populate show names // when the fingerprint visualizer opens, populate show names
async function visualizerToggled() { async function visualizerToggled() {
if (!visualizer.open) { if (!visualizer.open) {
@ -1443,8 +1404,6 @@
document.getElementById("warningMessage").style.display = "none"; document.getElementById("warningMessage").style.display = "none";
} }
populateLibraries();
selectAllLibrariesChanged();
autoSkipChanged(); autoSkipChanged();
persistSkipChanged(); persistSkipChanged();
generateAutoSkipTypeList(); generateAutoSkipTypeList();

View File

@ -10,6 +10,8 @@ using IntroSkipper.Data;
using IntroSkipper.Db; using IntroSkipper.Db;
using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Configuration;
using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Updates; using MediaBrowser.Model.Updates;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
@ -21,7 +23,8 @@ internal static class LegacyMigrations
Plugin plugin, Plugin plugin,
IServerConfigurationManager serverConfiguration, IServerConfigurationManager serverConfiguration,
ILogger logger, ILogger logger,
IApplicationPaths applicationPaths) IApplicationPaths applicationPaths,
ILibraryManager libraryManager)
{ {
var pluginDirName = "introskipper"; var pluginDirName = "introskipper";
var introPath = Path.Join(applicationPaths.DataPath, pluginDirName, "intros.xml"); var introPath = Path.Join(applicationPaths.DataPath, pluginDirName, "intros.xml");
@ -32,6 +35,7 @@ internal static class LegacyMigrations
MigrateConfig(plugin, applicationPaths.PluginConfigurationsPath, logger); MigrateConfig(plugin, applicationPaths.PluginConfigurationsPath, logger);
MigrateRepoUrl(plugin, serverConfiguration, logger); MigrateRepoUrl(plugin, serverConfiguration, logger);
MigrateSettingsToJellyfin(plugin, logger, libraryManager);
InjectSkipButton(plugin, applicationPaths.WebPath, logger); InjectSkipButton(plugin, applicationPaths.WebPath, logger);
RestoreTimestamps(plugin.DbPath, introPath, creditsPath); RestoreTimestamps(plugin.DbPath, introPath, creditsPath);
} }
@ -123,7 +127,7 @@ internal static class LegacyMigrations
} }
catch (Exception) catch (Exception)
{ {
// If skip button is disabled and we can't access the file, just return silently // If skip button is disabled, and we can't access the file, just return silently
if (!plugin.Configuration.SkipButtonEnabled) if (!plugin.Configuration.SkipButtonEnabled)
{ {
logger.LogDebug("Skip button disabled and no permission to access index.html. Assuming its a fresh install."); logger.LogDebug("Skip button disabled and no permission to access index.html. Assuming its a fresh install.");
@ -215,4 +219,67 @@ internal static class LegacyMigrations
File.Delete(introPath); File.Delete(introPath);
File.Delete(creditsPath); File.Delete(creditsPath);
} }
private static void MigrateSettingsToJellyfin(Plugin plugin, ILogger logger, ILibraryManager libraryManager)
{
try
{
if (!plugin.Configuration.SelectAllLibraries)
{
logger.LogInformation("Migration of your old library settings to Jellyfin");
List<string> selectedLibraries = [.. plugin.Configuration.SelectedLibraries.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)];
foreach (var folder in libraryManager.GetVirtualFolders())
{
if (!selectedLibraries.Contains(folder.Name) && folder.CollectionType is CollectionTypeOptions.tvshows or CollectionTypeOptions.movies or CollectionTypeOptions.mixed)
{
// only add if not already disabled
if (!folder.LibraryOptions.DisabledMediaSegmentProviders.Contains(plugin.Name))
{
// append in case there other disabled media segment providers
folder.LibraryOptions.DisabledMediaSegmentProviders = [.. folder.LibraryOptions.DisabledMediaSegmentProviders, plugin.Name];
logger.LogInformation("Disable Media Segment Provider <{Name}> for Library <{Name}>", plugin.Name, folder.Name);
}
}
}
// reset to default
plugin.Configuration.SelectAllLibraries = true;
plugin.Configuration.SelectedLibraries = string.Empty;
plugin.SaveConfiguration();
}
if (!plugin.Configuration.AnalyzeMovies)
{
logger.LogInformation("Migration of your old Movie settings to Jellyfin");
foreach (var folder in libraryManager.GetVirtualFolders())
{
if (folder.CollectionType is CollectionTypeOptions.movies or CollectionTypeOptions.mixed)
{
// only add if not already disabled
if (!folder.LibraryOptions.DisabledMediaSegmentProviders.Contains(plugin.Name))
{
// append in case there other disabled media segment providers
folder.LibraryOptions.DisabledMediaSegmentProviders = [.. folder.LibraryOptions.DisabledMediaSegmentProviders, plugin.Name];
logger.LogInformation("Disable Media Segment Provider <{Name}> for Library <{Name}>", plugin.Name, folder.Name);
}
}
}
// reset to default
plugin.Configuration.AnalyzeMovies = true;
plugin.SaveConfiguration();
}
}
catch (Exception ex)
{
logger.LogWarning("The migration of your old library settings to Jellyfin has failed: {Exception}", ex);
}
finally
{
// reset to default
plugin.Configuration.SelectAllLibraries = true;
plugin.Configuration.SelectedLibraries = string.Empty;
plugin.SaveConfiguration();
}
}
} }

View File

@ -30,9 +30,6 @@ namespace IntroSkipper.Manager
private readonly ILogger<QueueManager> _logger = logger; private readonly ILogger<QueueManager> _logger = logger;
private readonly Dictionary<Guid, List<QueuedEpisode>> _queuedEpisodes = []; private readonly Dictionary<Guid, List<QueuedEpisode>> _queuedEpisodes = [];
private double _analysisPercent; private double _analysisPercent;
private List<string> _selectedLibraries = [];
private bool _selectAllLibraries;
private bool _analyzeMovies;
/// <summary> /// <summary>
/// Gets all media items on the server. /// Gets all media items on the server.
@ -48,9 +45,9 @@ namespace IntroSkipper.Manager
foreach (var folder in _libraryManager.GetVirtualFolders()) foreach (var folder in _libraryManager.GetVirtualFolders())
{ {
// If libraries have been selected for analysis, ensure this library was selected. // If libraries have been selected for analysis, ensure this library was selected.
if (!_selectAllLibraries && !_selectedLibraries.Contains(folder.Name)) if (folder.LibraryOptions.DisabledMediaSegmentProviders.Contains(Plugin.Instance.Name))
{ {
_logger.LogDebug("Not analyzing library \"{Name}\": not selected by user", folder.Name); _logger.LogDebug("Not analyzing library \"{Name}\": Intro Skipper is disabled in library settings. To enable, check library configuration > Media Segment Providers", folder.Name);
continue; continue;
} }
@ -93,23 +90,6 @@ namespace IntroSkipper.Manager
// Store the analysis percent // Store the analysis percent
_analysisPercent = Convert.ToDouble(config.AnalysisPercent) / 100; _analysisPercent = Convert.ToDouble(config.AnalysisPercent) / 100;
_selectAllLibraries = config.SelectAllLibraries;
_analyzeMovies = config.AnalyzeMovies;
if (!_selectAllLibraries)
{
// Get the list of library names which have been selected for analysis, ignoring whitespace and empty entries.
_selectedLibraries = [.. config.SelectedLibraries.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)];
// If any libraries have been selected for analysis, log their names.
_logger.LogInformation("Limiting analysis to the following libraries: {Selected}", _selectedLibraries);
}
else
{
_logger.LogDebug("Not limiting analysis by library name");
}
// If analysis settings have been changed from the default, log the modified settings. // If analysis settings have been changed from the default, log the modified settings.
if (config.AnalysisLengthLimit != 10 || config.AnalysisPercent != 25 || config.MinimumIntroDuration != 15) if (config.AnalysisLengthLimit != 10 || config.AnalysisPercent != 25 || config.MinimumIntroDuration != 15)
{ {
@ -154,10 +134,7 @@ namespace IntroSkipper.Manager
} }
else if (item is Movie movie) else if (item is Movie movie)
{ {
if (_analyzeMovies) QueueMovie(movie);
{
QueueMovie(movie);
}
} }
else else
{ {

View File

@ -90,7 +90,7 @@ public class Plugin : BasePlugin<PluginConfiguration>, IHasWebPages
try try
{ {
LegacyMigrations.MigrateAll(this, serverConfiguration, logger, applicationPaths); LegacyMigrations.MigrateAll(this, serverConfiguration, logger, applicationPaths, _libraryManager);
} }
catch (Exception ex) catch (Exception ex)
{ {

View File

@ -79,8 +79,8 @@ public class BaseItemAnalyzerTask(
int totalQueued = queue.Sum(kvp => kvp.Value.Count) * modes.Count; int totalQueued = queue.Sum(kvp => kvp.Value.Count) * modes.Count;
if (totalQueued == 0) if (totalQueued == 0)
{ {
throw new FingerprintException( _logger.LogInformation("No libraries selected for analysis. To enable, check library configuration > Media Segment Providers.");
"No libraries selected for analysis. Please visit the plugin settings to configure."); return;
} }
int totalProcessed = 0; int totalProcessed = 0;