Release 0.2.5: harden proxy and streamline metadata fetching

Remove obsolete rule formats, batch SQLite work, preserve artwork source URLs, and coordinate refresh workers with maintenance. Add regression coverage and document backup format changes.
This commit is contained in:
ajp_anton
2026-09-09 01:18:43 +00:00
parent 7eb62b156e
commit e36775f1a3
49 changed files with 2126 additions and 1813 deletions
@@ -0,0 +1,61 @@
using System.Text.Json;
using Jellyfin.Plugin.Multilang.Data;
using Jellyfin.Plugin.Multilang.Rules;
namespace Jellyfin.Plugin.Multilang.Tests;
public sealed class UserRulesNormalizerTests
{
[Fact]
public void LegacyFieldsAreNotConvertedOrWrittenBack()
{
var rules = JsonSerializer.Deserialize<UserRulesDocument>("""
{"Categories":[{"CriteriaText":"original_language is fi",
"FieldActions":{"title":"Language:fi"},
"Requirements":[{"Field":"original_language","Relation":"is","Values":["fi"]}]}]}
""")!;
UserRulesNormalizer.Normalize(rules, ["fi"]);
var category = Assert.Single(rules.Categories);
Assert.Empty(category.Requirements);
Assert.Equal(["Jellyfin"], category.FieldActionLists["title"]);
var saved = JsonSerializer.Serialize(rules);
Assert.DoesNotContain("CriteriaText", saved);
Assert.DoesNotContain("\"Field\":", saved);
Assert.DoesNotContain("\"FieldActions\":", saved);
}
[Fact]
public void CurrentRulesPreserveBooleanModesAndNormalizeOnlyCompleteConditions()
{
var rules = new UserRulesDocument
{
Categories = [new()
{
Label = "Finnish", MatchAllConditions = false, Scopes = ["M", "C"],
Requirements = [new() { Fields = ["audio_language", "original_language", "origin_countries"],
UseFieldOr = true, Relation = "contains", UseOr = true, Values = ["fi", "sv"] }, new()],
FieldActionLists = new() { ["title"] = ["Language:FI", "Language:de", "Original"], ["overview"] = [] }
}]
};
UserRulesNormalizer.Normalize(rules, ["fi"]);
var category = Assert.Single(rules.Categories);
Assert.False(category.MatchAllConditions);
Assert.Equal(["M", "C"], category.Scopes);
var condition = Assert.Single(category.Requirements);
Assert.Equal(["original_language", "audio_language"], condition.Fields);
Assert.True(condition.UseFieldOr);
Assert.True(condition.UseOr);
Assert.Equal(["Language:fi", "Original", "Jellyfin"], category.FieldActionLists["title"]);
Assert.Empty(category.FieldActionLists["overview"]);
Assert.Equal(JsonSerializer.Serialize(rules), JsonSerializer.Serialize(UserRulesNormalizer.Normalize(rules, ["fi"])));
}
[Fact]
public void NullExternalCollectionsNormalizeToDefaults()
{
var rules = JsonSerializer.Deserialize<UserRulesDocument>("""{"Categories":null,"FallbackFieldActions":null}""")!;
UserRulesNormalizer.Normalize(rules);
Assert.Empty(rules.Categories);
Assert.Equal(["Jellyfin"], rules.FallbackFieldActions["poster"]);
}
}