You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
154 lines
5.9 KiB
154 lines
5.9 KiB
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text.RegularExpressions;
|
|
using System.Threading.Tasks;
|
|
using Serilog;
|
|
using TrashLib.Sonarr.Api;
|
|
using TrashLib.Sonarr.Api.Objects;
|
|
using TrashLib.Sonarr.Config;
|
|
|
|
namespace TrashLib.Sonarr.QualityDefinition
|
|
{
|
|
internal class SonarrQualityDefinitionUpdater : ISonarrQualityDefinitionUpdater
|
|
{
|
|
private readonly ISonarrApi _api;
|
|
private readonly ISonarrQualityDefinitionGuideParser _parser;
|
|
private readonly Regex _regexHybrid = new(@"720|1080", RegexOptions.Compiled);
|
|
|
|
public SonarrQualityDefinitionUpdater(ILogger logger, ISonarrQualityDefinitionGuideParser parser,
|
|
ISonarrApi api)
|
|
{
|
|
Log = logger;
|
|
_parser = parser;
|
|
_api = api;
|
|
}
|
|
|
|
private ILogger Log { get; }
|
|
|
|
public async Task Process(bool isPreview, SonarrConfiguration config)
|
|
{
|
|
Log.Information("Processing Quality Definition: {QualityDefinition}", config.QualityDefinition);
|
|
var qualityDefinitions = _parser.ParseMarkdown(await _parser.GetMarkdownData());
|
|
List<SonarrQualityData> selectedQuality;
|
|
|
|
if (config.QualityDefinition == SonarrQualityDefinitionType.Hybrid)
|
|
{
|
|
selectedQuality = BuildHybridQuality(qualityDefinitions[SonarrQualityDefinitionType.Anime],
|
|
qualityDefinitions[SonarrQualityDefinitionType.Series]);
|
|
}
|
|
else
|
|
{
|
|
selectedQuality = qualityDefinitions[config.QualityDefinition!.Value];
|
|
}
|
|
|
|
if (isPreview)
|
|
{
|
|
PrintQualityPreview(selectedQuality);
|
|
return;
|
|
}
|
|
|
|
await ProcessQualityDefinition(selectedQuality);
|
|
}
|
|
|
|
private List<SonarrQualityData> BuildHybridQuality(IReadOnlyCollection<SonarrQualityData> anime,
|
|
IEnumerable<SonarrQualityData> series)
|
|
{
|
|
// todo Verify anime & series are the same length? Probably not, because we might not care about some rows anyway.
|
|
Log.Information(
|
|
"Notice: Hybrid only functions on 720/1080 qualities and uses non-anime values for the rest (e.g. 2160)");
|
|
|
|
var hybrid = new List<SonarrQualityData>();
|
|
foreach (var left in series)
|
|
{
|
|
// Any qualities that anime doesn't care about get immediately added from Series quality
|
|
var match = _regexHybrid.Match(left.Name);
|
|
if (!match.Success)
|
|
{
|
|
Log.Debug("Using 'Series' Quality For: {QualityName}", left.Name);
|
|
hybrid.Add(left);
|
|
continue;
|
|
}
|
|
|
|
// If there's a quality in Series that Anime doesn't know about, we add the Series quality
|
|
var right = anime.FirstOrDefault(row => row.Name == left.Name);
|
|
if (right == null)
|
|
{
|
|
Log.Error("Could not find matching anime quality for series quality named {QualityName}",
|
|
left.Name);
|
|
hybrid.Add(left);
|
|
continue;
|
|
}
|
|
|
|
hybrid.Add(new SonarrQualityData
|
|
{
|
|
Name = left.Name,
|
|
Min = Math.Min(left.Min, right.Min),
|
|
Max = Math.Max(left.Max, right.Max)
|
|
});
|
|
}
|
|
|
|
return hybrid;
|
|
}
|
|
|
|
private static void PrintQualityPreview(IEnumerable<SonarrQualityData> quality)
|
|
{
|
|
Console.WriteLine("");
|
|
const string format = "{0,-20} {1,-10} {2,-15}";
|
|
Console.WriteLine(format, "Quality", "Min", "Max");
|
|
Console.WriteLine(format, "-------", "---", "---");
|
|
|
|
foreach (var q in quality)
|
|
{
|
|
Console.WriteLine(format, q.Name, q.AnnotatedMin, q.AnnotatedMax);
|
|
}
|
|
|
|
Console.WriteLine("");
|
|
}
|
|
|
|
private async Task ProcessQualityDefinition(IEnumerable<SonarrQualityData> guideQuality)
|
|
{
|
|
var serverQuality = await _api.GetQualityDefinition();
|
|
await UpdateQualityDefinition(serverQuality, guideQuality);
|
|
}
|
|
|
|
private async Task UpdateQualityDefinition(IReadOnlyCollection<SonarrQualityDefinitionItem> serverQuality,
|
|
IEnumerable<SonarrQualityData> guideQuality)
|
|
{
|
|
static bool QualityIsDifferent(SonarrQualityDefinitionItem a, SonarrQualityData b)
|
|
{
|
|
return b.IsMinDifferent(a.MinSize) ||
|
|
b.IsMaxDifferent(a.MaxSize);
|
|
}
|
|
|
|
var newQuality = new List<SonarrQualityDefinitionItem>();
|
|
foreach (var qualityData in guideQuality)
|
|
{
|
|
var entry = serverQuality.FirstOrDefault(q => q.Quality?.Name == qualityData.Name);
|
|
if (entry == null)
|
|
{
|
|
Log.Warning("Server lacks quality definition for {Quality}; it will be skipped", qualityData.Name);
|
|
continue;
|
|
}
|
|
|
|
if (!QualityIsDifferent(entry, qualityData))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// Not using the original list again, so it's OK to modify the definition reftype objects in-place.
|
|
entry.MinSize = qualityData.MinForApi;
|
|
entry.MaxSize = qualityData.MaxForApi;
|
|
newQuality.Add(entry);
|
|
|
|
Log.Debug("Setting Quality " +
|
|
"[Name: {Name}] [Source: {Source}] [Min: {Min}] [Max: {Max}]",
|
|
entry.Quality?.Name, entry.Quality?.Source, entry.MinSize, entry.MaxSize);
|
|
}
|
|
|
|
await _api.UpdateQualityDefinition(newQuality);
|
|
Log.Information("Number of updated qualities: {Count}", newQuality.Count);
|
|
}
|
|
}
|
|
}
|