chore: fix various warnings

pull/47/head
Robert Dailey 3 years ago
parent 74ca11e309
commit b1651c89c6

@ -0,0 +1,26 @@
using System;
using Newtonsoft.Json.Linq;
namespace Common
{
public static class JsonNetExtensions
{
public static JEnumerable<T> Children<T>(this JToken token, string key)
where T : JToken
{
return token[key]?.Children<T>() ?? JEnumerable<T>.Empty;
}
public static T ValueOrThrow<T>(this JToken token, string key)
where T : class
{
var value = token.Value<T>(key);
if (value is null)
{
throw new ArgumentNullException(token.Path);
}
return value;
}
}
}

@ -18,6 +18,7 @@ namespace Trash.Command.Helpers
{
public abstract class ServiceCommand : ICommand, IServiceCommand
{
private readonly AutofacContractResolver _contractResolver;
private readonly LoggingLevelSwitch _loggingLevelSwitch;
private readonly ILogJanitor _logJanitor;

@ -175,7 +175,7 @@ namespace TrashLib.Tests.Radarr.CustomFormat.Processors.PersistenceSteps
var radarrCfs = JsonConvert.DeserializeObject<List<JObject>>(radarrCfData);
var guideCfs = new List<ProcessedCustomFormatData>
{
new("created", "", guideCfData[0]),
new("created", "", guideCfData![0]),
new("updated_different_name", "", guideCfData[1])
{
CacheEntry = new TrashIdMapping("", "", 2)
@ -184,7 +184,7 @@ namespace TrashLib.Tests.Radarr.CustomFormat.Processors.PersistenceSteps
};
var processor = new JsonTransactionStep();
processor.Process(guideCfs, radarrCfs);
processor.Process(guideCfs, radarrCfs!);
var expectedJson = new[]
{
@ -297,8 +297,8 @@ namespace TrashLib.Tests.Radarr.CustomFormat.Processors.PersistenceSteps
var radarrCfs = JsonConvert.DeserializeObject<List<JObject>>(radarrCfData);
var processor = new JsonTransactionStep();
processor.Process(guideCfs, radarrCfs);
processor.RecordDeletions(deletedCfsInCache, radarrCfs);
processor.Process(guideCfs, radarrCfs!);
processor.RecordDeletions(deletedCfsInCache, radarrCfs!);
var expectedJson = @"{
'id': 1,
@ -356,7 +356,7 @@ namespace TrashLib.Tests.Radarr.CustomFormat.Processors.PersistenceSteps
var radarrCfs = JsonConvert.DeserializeObject<List<JObject>>(radarrCfData);
var processor = new JsonTransactionStep();
processor.RecordDeletions(deletedCfsInCache, radarrCfs);
processor.RecordDeletions(deletedCfsInCache, radarrCfs!);
var expectedTransactions = new CustomFormatTransactionData();
expectedTransactions.DeletedCustomFormatIds.Add(new TrashIdMapping("testtrashid", "testname", 2));
@ -410,12 +410,12 @@ namespace TrashLib.Tests.Radarr.CustomFormat.Processors.PersistenceSteps
var radarrCfs = JsonConvert.DeserializeObject<List<JObject>>(radarrCfData);
var guideCfs = new List<ProcessedCustomFormatData>
{
new("updated", "", guideCfData[0]),
new("updated", "", guideCfData![0]),
new("no_change", "", guideCfData[1])
};
var processor = new JsonTransactionStep();
processor.Process(guideCfs, radarrCfs);
processor.Process(guideCfs, radarrCfs!);
processor.Transactions.UpdatedCustomFormats.First().CacheEntry.Should()
.BeEquivalentTo(new TrashIdMapping("", "updated", 1));

@ -43,7 +43,7 @@ namespace TrashLib.Tests.Radarr.CustomFormat.Processors.PersistenceSteps
}]";
var api = Substitute.For<IQualityProfileService>();
api.GetQualityProfiles().Returns(JsonConvert.DeserializeObject<List<JObject>>(radarrQualityProfileData));
api.GetQualityProfiles()!.Returns(JsonConvert.DeserializeObject<List<JObject>>(radarrQualityProfileData));
var cfScores = new Dictionary<string, QualityProfileCustomFormatScoreMapping>
{
@ -68,7 +68,7 @@ namespace TrashLib.Tests.Radarr.CustomFormat.Processors.PersistenceSteps
const string radarrQualityProfileData = @"[{'name': 'profile1'}]";
var api = Substitute.For<IQualityProfileService>();
api.GetQualityProfiles().Returns(JsonConvert.DeserializeObject<List<JObject>>(radarrQualityProfileData));
api.GetQualityProfiles()!.Returns(JsonConvert.DeserializeObject<List<JObject>>(radarrQualityProfileData));
var cfScores = new Dictionary<string, QualityProfileCustomFormatScoreMapping>
{
@ -107,7 +107,7 @@ namespace TrashLib.Tests.Radarr.CustomFormat.Processors.PersistenceSteps
}]";
var api = Substitute.For<IQualityProfileService>();
api.GetQualityProfiles().Returns(JsonConvert.DeserializeObject<List<JObject>>(radarrQualityProfileData));
api.GetQualityProfiles()!.Returns(JsonConvert.DeserializeObject<List<JObject>>(radarrQualityProfileData));
var cfScores = new Dictionary<string, QualityProfileCustomFormatScoreMapping>
{
@ -134,7 +134,7 @@ namespace TrashLib.Tests.Radarr.CustomFormat.Processors.PersistenceSteps
});
api.Received().UpdateQualityProfile(
Verify.That<JObject>(j => j["formatItems"].Children().Should().HaveCount(3)),
Verify.That<JObject>(j => j["formatItems"]!.Children().Should().HaveCount(3)),
Arg.Any<int>());
}
@ -183,7 +183,7 @@ namespace TrashLib.Tests.Radarr.CustomFormat.Processors.PersistenceSteps
}]";
var api = Substitute.For<IQualityProfileService>();
api.GetQualityProfiles().Returns(JsonConvert.DeserializeObject<List<JObject>>(radarrQualityProfileData));
api.GetQualityProfiles()!.Returns(JsonConvert.DeserializeObject<List<JObject>>(radarrQualityProfileData));
var cfScores = new Dictionary<string, QualityProfileCustomFormatScoreMapping>
{

@ -33,7 +33,10 @@ namespace TrashLib.Radarr.CustomFormat.Api
.PostJsonAsync(cf.Json)
.ReceiveJson<JObject>();
cf.SetCache((int) response["id"]);
if (response != null)
{
cf.SetCache(response.Value<int>("id"));
}
}
public async Task UpdateCustomFormat(ProcessedCustomFormatData cf)

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Common;
using Common.Extensions;
using Newtonsoft.Json.Linq;
using TrashLib.Radarr.Config;
@ -96,19 +97,19 @@ namespace TrashLib.Radarr.CustomFormat.Processors.GuideSteps
private static ProcessedCustomFormatData ProcessCustomFormatData(string guideData, CustomFormatCache? cache)
{
JObject obj = JObject.Parse(guideData);
var name = (string) obj["name"];
var trashId = (string) obj["trash_id"];
var name = obj.ValueOrThrow<string>("name");
var trashId = obj.ValueOrThrow<string>("trash_id");
int? finalScore = null;
if (obj.TryGetValue("trash_score", out var score))
{
finalScore = (int) score;
obj.Property("trash_score").Remove();
obj.Property("trash_score")?.Remove();
}
// Remove trash_id, it's metadata that is not meant for Radarr itself
// Radarr supposedly drops this anyway, but I prefer it to be removed by TrashUpdater
obj.Property("trash_id").Remove();
obj.Property("trash_id")?.Remove();
return new ProcessedCustomFormatData(name, trashId, obj)
{

@ -44,7 +44,7 @@ namespace TrashLib.Radarr.CustomFormat.Processors.PersistenceSteps
// later).
if (guideCf.CacheEntry == null)
{
guideCf.SetCache((int) guideCf.Json["id"]);
guideCf.SetCache(guideCf.Json.Value<int>("id"));
}
if (!JToken.DeepEquals(radarrCf, guideCf.Json))
@ -82,13 +82,13 @@ namespace TrashLib.Radarr.CustomFormat.Processors.PersistenceSteps
// Try to find match in cache first
if (cfId != null)
{
match = radarrCfs.FirstOrDefault(rcf => cfId == rcf["id"].Value<int>());
match = radarrCfs.FirstOrDefault(rcf => cfId == rcf.Value<int>("id"));
}
// If we don't find by ID, search by name (if a name was given)
if (match == null && cfName != null)
{
match = radarrCfs.FirstOrDefault(rcf => cfName.EqualsIgnoreCase(rcf["name"].Value<string>()));
match = radarrCfs.FirstOrDefault(rcf => cfName.EqualsIgnoreCase(rcf.Value<string>("name")));
}
return match;
@ -98,8 +98,8 @@ namespace TrashLib.Radarr.CustomFormat.Processors.PersistenceSteps
{
MergeProperties(cfToModify, cfToMergeFrom, JTokenType.Array);
var radarrSpecs = cfToModify["specifications"].Children<JObject>();
var guideSpecs = cfToMergeFrom["specifications"].Children<JObject>();
var radarrSpecs = cfToModify["specifications"]?.Children<JObject>() ?? new JEnumerable<JObject>();
var guideSpecs = cfToMergeFrom["specifications"]?.Children<JObject>() ?? new JEnumerable<JObject>();
var matchedGuideSpecs = guideSpecs
.GroupBy(gs => radarrSpecs.FirstOrDefault(gss => KeyMatch(gss, gs, "name")))
@ -124,7 +124,7 @@ namespace TrashLib.Radarr.CustomFormat.Processors.PersistenceSteps
}
private static bool KeyMatch(JObject left, JObject right, string keyName)
=> left[keyName].Value<string>() == right[keyName].Value<string>();
=> left.Value<string>(keyName) == right.Value<string>(keyName);
private static void MergeProperties(JObject radarrCf, JObject guideCfJson,
JTokenType exceptType = JTokenType.None)
@ -156,14 +156,23 @@ namespace TrashLib.Radarr.CustomFormat.Processors.PersistenceSteps
everything else radarr can handle with backend logic
*/
foreach (var child in jsonPayload["specifications"])
var specs = jsonPayload["specifications"];
if (specs is not null)
{
// convert from `"fields": {}` to `"fields": [{}]` (object to array of object)
// Weirdly the exported version of a custom format is not in array form, but the API requires the array
// even if there's only one element.
var field = child["fields"];
field["name"] = "value";
child["fields"] = new JArray {field};
foreach (var child in specs)
{
// convert from `"fields": {}` to `"fields": [{}]` (object to array of object)
// Weirdly the exported version of a custom format is not in array form, but the API requires the array
// even if there's only one element.
var field = child["fields"];
if (field is null)
{
continue;
}
field["name"] = "value";
child["fields"] = new JArray {field};
}
}
return jsonPayload;

@ -2,6 +2,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Common;
using Common.Extensions;
using Newtonsoft.Json.Linq;
using TrashLib.Radarr.CustomFormat.Api;
@ -28,8 +29,8 @@ namespace TrashLib.Radarr.CustomFormat.Processors.PersistenceSteps
// do not match profiles in Radarr.
var profileScores = cfScores.GroupJoin(radarrProfiles,
s => s.Key,
p => (string) p["name"],
(s, p) => (s.Key, s.Value, p.SelectMany(pi => pi["formatItems"].Children<JObject>()).ToList()),
p => p.Value<string>("name"),
(s, p) => (s.Key, s.Value, p.SelectMany(pi => pi.Children<JObject>("formatItems")).ToList()),
StringComparer.InvariantCultureIgnoreCase);
foreach (var (profileName, scoreMap, formatItems) in profileScores)
@ -58,14 +59,14 @@ namespace TrashLib.Radarr.CustomFormat.Processors.PersistenceSteps
reason = FormatScoreUpdateReason.Reset;
}
if (scoreToUse == null || reason == null || (int) json["score"] == scoreToUse)
if (scoreToUse == null || reason == null || json.Value<int>("score") == scoreToUse)
{
continue;
}
json["score"] = scoreToUse.Value;
_updatedScores.GetOrCreate(profileName)
.Add(new UpdatedFormatScore((string) json["name"], scoreToUse.Value, reason.Value));
.Add(new UpdatedFormatScore(json.ValueOrThrow<string>("name"), scoreToUse.Value, reason.Value));
}
if (!_updatedScores.TryGetValue(profileName, out var updatedScores) || updatedScores.Count == 0)
@ -75,7 +76,7 @@ namespace TrashLib.Radarr.CustomFormat.Processors.PersistenceSteps
}
var jsonRoot = (JObject) formatItems.First().Root;
await api.UpdateQualityProfile(jsonRoot, (int) jsonRoot["id"]);
await api.UpdateQualityProfile(jsonRoot, jsonRoot.Value<int>("id"));
}
}
@ -84,7 +85,7 @@ namespace TrashLib.Radarr.CustomFormat.Processors.PersistenceSteps
{
return scoreMap.Mapping.FirstOrDefault(
m => m.CustomFormat.CacheEntry != null &&
(int) formatItem["format"] == m.CustomFormat.CacheEntry.CustomFormatId);
formatItem.Value<int>("format") == m.CustomFormat.CacheEntry.CustomFormatId);
}
}
}

@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Common.Extensions;

Loading…
Cancel
Save