Skip to content

Commit

Permalink
Add series refresh task and options
Browse files Browse the repository at this point in the history
Move tasks to separate category just for Refresh Sparse.
Fixes #6
  • Loading branch information
SenorSmartyPants committed Dec 24, 2022
1 parent 1abd6de commit bea7e45
Show file tree
Hide file tree
Showing 4 changed files with 286 additions and 1 deletion.
37 changes: 37 additions & 0 deletions Jellyfin.Plugin.RefreshSparse/Configuration/PluginConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,20 @@ public PluginConfiguration()
// all is being overwritten currently in 10.8 regardless of these settings.
ReplaceAllImages = false;
ReplaceAllMetadata = false;

// series defaults
SeriesStatusDays = 180;
SeriesMinimumProviderIds = 0;
SeriesOverview = true;
SeriesPrimary = true;
SeriesArt = false;
SeriesBanner = false;
SeriesLogo = false;
SeriesThumb = false;
SeriesBackdrop = true;
SeriesReplaceAllImages = false;
SeriesReplaceAllMetadata = false;

}

public int MaxDays { get; set; }
Expand Down Expand Up @@ -50,5 +64,28 @@ public PluginConfiguration()
public bool ReplaceAllMetadata { get; set; }

public string SeriesBlockList { get; set; }

// Series settings
public int SeriesStatusDays { get; set; }

public int SeriesMinimumProviderIds { get; set; }

public bool SeriesOverview { get; set; }

public bool SeriesPrimary { get; set; }

public bool SeriesArt { get; set; }

public bool SeriesBanner { get; set; }

public bool SeriesLogo { get; set; }

public bool SeriesThumb { get; set; }

public bool SeriesBackdrop { get; set; }

public bool SeriesReplaceAllImages { get; set; }

public bool SeriesReplaceAllMetadata { get; set; }
}
}
99 changes: 99 additions & 0 deletions Jellyfin.Plugin.RefreshSparse/Configuration/configPage.html
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,73 @@ <h3>Name</h3>
</div>
</fieldset>

<fieldset class="verticalSection">
<legend>
<h3>Series</h3>
</legend>

<div class="inputContainer">
<label class="inputLabel inputLabelUnfocused" for="SeriesStatusDays">Status</label>
<input id="SeriesStatusDays" name="SeriesStatusDays" type="number" is="emby-input" min="-1" />
<div class="fieldDescription">Check every X days if continuing series has ended. -1 to disable and never check.
</div>
</div>

<div class="inputContainer">
<label class="inputLabel inputLabelUnfocused" for="SeriesMinimumProviderIds">Minimum provider IDs</label>
<input id="SeriesMinimumProviderIds" name="SeriesMinimumProviderIds" type="number" is="emby-input" min="0" />
<div class="fieldDescription">Minimum number of external provider IDs</div>
</div>

<div class="checkboxContainer checkboxContainer-withDescription">
<label class="emby-checkbox-label">
<input id="SeriesOverview" name="SeriesOverview" type="checkbox" is="emby-checkbox" />
<span>Missing overview</span>
</label>
</div>

<div>
<h3 class="checkboxListLabel">Missing Images</h3>
<div class="paperList checkboxList checkboxList-paperList" id="SeriesImagesList">
<label class="emby-checkbox-label">
<input id="SeriesPrimary" name="SeriesPrimary" type="checkbox" is="emby-checkbox" />
<span>Primary</span>
</label>
<label class="emby-checkbox-label">
<input id="SeriesArt" name="SeriesArt" type="checkbox" is="emby-checkbox" />
<span>Clearart</span>
</label>
<label class="emby-checkbox-label">
<input id="SeriesBanner" name="SeriesBanner" type="checkbox" is="emby-checkbox" />
<span>Banner</span>
</label>
<label class="emby-checkbox-label">
<input id="SeriesLogo" name="SeriesLogo" type="checkbox" is="emby-checkbox" />
<span>Logo</span>
</label>
<label class="emby-checkbox-label">
<input id="SeriesThumb" name="SeriesThumb" type="checkbox" is="emby-checkbox" />
<span>Thumb</span>
</label>
<label class="emby-checkbox-label">
<input id="SeriesBackdrop" name="SeriesBackdrop" type="checkbox" is="emby-checkbox" />
<span>Backdrop</span>
</label>
</div>
</div>
<div class="checkboxContainer checkboxContainer-withDescription">
<label class="emby-checkbox-label">
<input id="SeriesReplaceAllMetadata" name="SeriesReplaceAllMetadata" type="checkbox" is="emby-checkbox" />
<span>Replace all metadata</span>
</label>
</div>
<div class="checkboxContainer checkboxContainer-withDescription">
<label class="emby-checkbox-label">
<input id="SeriesReplaceAllImages" name="SeriesReplaceAllImages" type="checkbox" is="emby-checkbox" />
<span>Replace all images</span>
</label>
</div>
</fieldset>


<div>
Expand Down Expand Up @@ -135,6 +202,22 @@ <h3>Name</h3>
document.querySelector('#RefreshCooldownMinutes').value = config.RefreshCooldownMinutes;
document.querySelector('#ReplaceAllImages').checked = config.ReplaceAllImages;
document.querySelector('#ReplaceAllMetadata').checked = config.ReplaceAllMetadata;

// series
document.querySelector('#SeriesStatusDays').value = config.SeriesStatusDays;
document.querySelector('#SeriesMinimumProviderIds').value = config.SeriesMinimumProviderIds;
document.querySelector('#SeriesOverview').checked = config.SeriesOverview;

document.querySelector('#SeriesPrimary').checked = config.SeriesPrimary;
document.querySelector('#SeriesArt').checked = config.SeriesArt;
document.querySelector('#SeriesBanner').checked = config.SeriesBanner;
document.querySelector('#SeriesLogo').checked = config.SeriesLogo;
document.querySelector('#SeriesThumb').checked = config.SeriesThumb;
document.querySelector('#SeriesBackdrop').checked = config.SeriesBackdrop;

document.querySelector('#SeriesReplaceAllImages').checked = config.SeriesReplaceAllImages;
document.querySelector('#SeriesReplaceAllMetadata').checked = config.SeriesReplaceAllMetadata;

Dashboard.hideLoadingMsg();
});
});
Expand All @@ -159,6 +242,22 @@ <h3>Name</h3>
config.RefreshCooldownMinutes = document.querySelector('#RefreshCooldownMinutes').value;
config.ReplaceAllImages = document.querySelector('#ReplaceAllImages').checked;
config.ReplaceAllMetadata = document.querySelector('#ReplaceAllMetadata').checked;

// series
config.SeriesStatusDays = document.querySelector('#SeriesStatusDays').value;
config.SeriesMinimumProviderIds = document.querySelector('#SeriesMinimumProviderIds').value;
config.SeriesOverview = document.querySelector('#SeriesOverview').checked;

config.SeriesPrimary = document.querySelector('#SeriesPrimary').checked;
config.SeriesArt = document.querySelector('#SeriesArt').checked;
config.SeriesBanner = document.querySelector('#SeriesBanner').checked;
config.SeriesLogo = document.querySelector('#SeriesLogo').checked;
config.SeriesThumb = document.querySelector('#SeriesThumb').checked;
config.SeriesBackdrop = document.querySelector('#SeriesBackdrop').checked;

config.SeriesReplaceAllImages = document.querySelector('#SeriesReplaceAllImages').checked;
config.SeriesReplaceAllMetadata = document.querySelector('#SeriesReplaceAllMetadata').checked;

ApiClient.updatePluginConfiguration(RefreshSparseConfig.pluginUniqueId, config).then(function (result) {
Dashboard.processPluginConfigurationUpdateResult(result);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ public abstract class BaseRefreshTask
get;
}

public string Category => _localization.GetLocalizedString("TasksLibraryCategory");
public string Category => _localization.GetLocalizedString("Sparse Items");

public string Key => "RefreshSparse";

Expand Down
149 changes: 149 additions & 0 deletions Jellyfin.Plugin.RefreshSparse/ScheduledTasks/RefreshSeriesTask.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
#pragma warning disable CS1591

using System;
using System.Collections.Generic;
using System.Linq;
using Jellyfin.Data.Enums;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Globalization;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Querying;
using MediaBrowser.Model.Tasks;
using Microsoft.Extensions.Logging;
using static Jellyfin.Plugin.RefreshSparse.Common.Utils;

namespace Jellyfin.Plugin.RefreshSparse
{
public class RefreshSeriesTask : BaseRefreshTask, IScheduledTask
{
public RefreshSeriesTask(
ILibraryManager libraryManager,
IServerConfigurationManager config,
ILogger<RefreshScheduledTask> logger,
ILocalizationManager localization,
IFileSystem fileSystem) : base(libraryManager, config, logger, localization, fileSystem)
{
}

protected override string ItemTypeName => "series";

public override string Name => Localization.GetLocalizedString("Refresh sparse series");

public override string Description => Localization.GetLocalizedString("Refresh series with missing metadata based on requirements configured.");

protected override IEnumerable<Series> GetItems()
{
// episodes that aired in the past MaxDays days
// or added to JF in MaxDays
DateTime? minDate = null;
var maxDays = PluginConfig.MaxDays;
if (maxDays > -1 )
{
minDate = DateTime.UtcNow.Date.AddDays(-(double)maxDays);
}

// todo mindatecreated? don't care, just time since last refresh?
// minutes since refresh?
return LibraryManager.GetItemList(
new InternalItemsQuery
{
IncludeItemTypes = new[] { BaseItemKind.Series },
IsVirtualItem = false,
Recursive = true,
MinDateCreated = minDate,
OrderBy = new[]
{
(ItemSortBy.SortName, SortOrder.Ascending)
}
}).Cast<Series>().Where(i => (maxDays == -1 || i.PremiereDate >= minDate || !i.PremiereDate.HasValue)
&& MinutesSinceRefresh(i) > PluginConfig.RefreshCooldownMinutes
&& !SeriesBlockList.Any(sbl => i.Name.Equals(sbl, StringComparison.OrdinalIgnoreCase))
&& NeedsRefresh(i));
}

protected override void LogWhatsMissingInfo(BaseItem item)
{
if (item.ProviderIds.Count < PluginConfig.SeriesMinimumProviderIds)
{
LogMissingProviders(item);
}

if (MissingOverview(item))
{
Logger.LogInformation(" missing overview");
}

if (MaybeEnded((Series)item))
{
Logger.LogInformation(" Continuing Series hasn't been refreshed in at least {0} days", PluginConfig.SeriesStatusDays);
}

if (MissingImage(item, ImageType.Primary, PluginConfig.SeriesPrimary))
{
Logger.LogInformation(" missing primary image");
}

if (MissingImage(item, ImageType.Art, PluginConfig.SeriesArt))
{
Logger.LogInformation(" missing clearart image");
}

if (MissingImage(item, ImageType.Banner, PluginConfig.SeriesBanner))
{
Logger.LogInformation(" missing banner image");
}

if (MissingImage(item, ImageType.Logo, PluginConfig.SeriesLogo))
{
Logger.LogInformation(" missing logo image");
}

if (MissingImage(item, ImageType.Thumb, PluginConfig.SeriesThumb))
{
Logger.LogInformation(" missing thumb image");
}

if (MissingImage(item, ImageType.Backdrop, PluginConfig.SeriesBackdrop))
{
Logger.LogInformation(" missing backdrop image");
}
}

protected override bool NeedsRefresh(BaseItem item)
{
return item.ProviderIds.Count < PluginConfig.SeriesMinimumProviderIds
|| MissingOverview(item)
|| MaybeEnded((Series)item)
|| MissingImage(item, ImageType.Primary, PluginConfig.SeriesPrimary)
|| MissingImage(item, ImageType.Art, PluginConfig.SeriesArt)
|| MissingImage(item, ImageType.Banner, PluginConfig.SeriesBanner)
|| MissingImage(item, ImageType.Logo, PluginConfig.SeriesLogo)
|| MissingImage(item, ImageType.Thumb, PluginConfig.SeriesThumb)
|| MissingImage(item, ImageType.Backdrop, PluginConfig.SeriesBackdrop);
}

protected override bool GetReplaceAllImages()
{
return Plugin.Instance.Configuration.SeriesReplaceAllImages;
}

protected override bool GetReplaceAllMetadata()
{
return Plugin.Instance.Configuration.SeriesReplaceAllMetadata;
}

private bool MaybeEnded(Series series)
{
return PluginConfig.SeriesStatusDays != -1 && (series.Status != SeriesStatus.Ended && DaysSinceRefresh(series) > PluginConfig.SeriesStatusDays);
}

private bool MissingOverview(BaseItem item)
{
return PluginConfig.SeriesOverview && string.IsNullOrWhiteSpace(item.Overview);
}
}
}

0 comments on commit bea7e45

Please sign in to comment.