V6 Cardigann Changes (#1045)

* V6 Cardigann Changes

* fixup!

* !fixup range

* !fixup more cardigann tests
This commit is contained in:
Qstick
2022-06-27 20:39:15 -05:00
committed by GitHub
parent 654d2dbad3
commit 5ee95e3cc2
13 changed files with 135 additions and 16 deletions

View File

@@ -24,6 +24,7 @@ const searchOptions = [
const seriesTokens = [ const seriesTokens = [
{ token: '{ImdbId:tt1234567}', example: 'tt12345' }, { token: '{ImdbId:tt1234567}', example: 'tt12345' },
{ token: '{TvdbId:12345}', example: '12345' }, { token: '{TvdbId:12345}', example: '12345' },
{ token: '{TmdbId:12345}', example: '12345' },
{ token: '{TvMazeId:12345}', example: '54321' }, { token: '{TvMazeId:12345}', example: '54321' },
{ token: '{Season:00}', example: '01' }, { token: '{Season:00}', example: '01' },
{ token: '{Episode:00}', example: '01' } { token: '{Episode:00}', example: '01' }

View File

@@ -0,0 +1,91 @@
using System;
using System.Collections.Generic;
using FizzWare.NBuilder;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.Indexers.Cardigann;
using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.IndexerTests.CardigannTests
{
public class ApplyGoTemplateTextFixture : CoreTest<CardigannBase>
{
private Dictionary<string, object> _variables;
private CardigannDefinition _definition;
[SetUp]
public void SetUp()
{
_variables = new Dictionary<string, object>
{
[".Config.sitelink"] = "https://somesite.com/",
[".True"] = "True",
[".False"] = null,
[".Today.Year"] = DateTime.Today.Year.ToString(),
[".Categories"] = new string[] { "tv", "movies" }
};
_definition = Builder<CardigannDefinition>.CreateNew()
.With(x => x.Encoding = "UTF-8")
.With(x => x.Links = new List<string>
{
"https://somesite.com/"
})
.With(x => x.Caps = new CapabilitiesBlock
{
Modes = new Dictionary<string, List<string>>
{
{ "search", new List<string> { "q" } }
}
})
.Build();
Mocker.SetConstant<CardigannDefinition>(_definition);
}
[TestCase("{{ range .Categories}}&categories[]={{.}}{{end}}", "&categories[]=tv&categories[]=movies")]
[TestCase("{{ range $i, $e := .Categories}}&categories[{{$i}}]={{.}}{{end}}", "&categories[0]=tv&categories[1]=movies")]
[TestCase("{{ range $index, $element := .Categories}}&categories[{{$index}}]={{.}}+postIndex[{{$index}}]{{end}}", "&categories[0]=tv+postIndex[0]&categories[1]=movies+postIndex[1]")]
public void should_handle_range_statements(string template, string expected)
{
var result = Subject.ApplyGoTemplateText(template, _variables);
result.Should().Be(expected);
}
[TestCase("{{ re_replace .Query.Keywords \"[^a-zA-Z0-9]+\" \"%\" }}", "abc%def")]
public void should_handle_re_replace_statements(string template, string expected)
{
_variables[".Query.Keywords"] = string.Join(" ", new List<string> { "abc", "def" });
var result = Subject.ApplyGoTemplateText(template, _variables);
result.Should().Be(expected);
}
[TestCase("{{ join .Categories \", \" }}", "tv, movies")]
public void should_handle_join_statements(string template, string expected)
{
var result = Subject.ApplyGoTemplateText(template, _variables);
result.Should().Be(expected);
}
[TestCase("{{ .Today.Year }}", "2022")]
public void should_handle_variables_statements(string template, string expected)
{
var result = Subject.ApplyGoTemplateText(template, _variables);
result.Should().Be(expected);
}
[TestCase("{{if .False }}0{{else}}1{{end}}", "1")]
[TestCase("{{if .True }}0{{else}}1{{end}}", "0")]
public void should_handle_if_statements(string template, string expected)
{
var result = Subject.ApplyGoTemplateText(template, _variables);
result.Should().Be(expected);
}
}
}

View File

@@ -136,6 +136,7 @@ namespace NzbDrone.Core.History
{ {
history.Data.Add("ImdbId", ((TvSearchCriteria)message.Query).FullImdbId ?? string.Empty); history.Data.Add("ImdbId", ((TvSearchCriteria)message.Query).FullImdbId ?? string.Empty);
history.Data.Add("TvdbId", ((TvSearchCriteria)message.Query).TvdbId?.ToString() ?? string.Empty); history.Data.Add("TvdbId", ((TvSearchCriteria)message.Query).TvdbId?.ToString() ?? string.Empty);
history.Data.Add("TmdbId", ((TvSearchCriteria)message.Query).TmdbId?.ToString() ?? string.Empty);
history.Data.Add("TraktId", ((TvSearchCriteria)message.Query).TraktId?.ToString() ?? string.Empty); history.Data.Add("TraktId", ((TvSearchCriteria)message.Query).TraktId?.ToString() ?? string.Empty);
history.Data.Add("RId", ((TvSearchCriteria)message.Query).RId?.ToString() ?? string.Empty); history.Data.Add("RId", ((TvSearchCriteria)message.Query).RId?.ToString() ?? string.Empty);
history.Data.Add("TvMazeId", ((TvSearchCriteria)message.Query).TvMazeId?.ToString() ?? string.Empty); history.Data.Add("TvMazeId", ((TvSearchCriteria)message.Query).TvMazeId?.ToString() ?? string.Empty);

View File

@@ -98,6 +98,7 @@ namespace NzbDrone.Core.IndexerSearch
GetNabElement("imdb", r.ImdbId.ToString("D7"), protocol), GetNabElement("imdb", r.ImdbId.ToString("D7"), protocol),
GetNabElement("tmdbid", r.TmdbId, protocol), GetNabElement("tmdbid", r.TmdbId, protocol),
GetNabElement("traktid", r.TraktId, protocol), GetNabElement("traktid", r.TraktId, protocol),
GetNabElement("doubanid", r.DoubanId, protocol),
GetNabElement("seeders", t.Seeders, protocol), GetNabElement("seeders", t.Seeders, protocol),
GetNabElement("files", r.Files, protocol), GetNabElement("files", r.Files, protocol),
GetNabElement("grabs", r.Grabs, protocol), GetNabElement("grabs", r.Grabs, protocol),

View File

@@ -28,7 +28,7 @@ namespace NzbDrone.Core.IndexerVersions
/* Update Service will fall back if version # does not exist for an indexer per Ta */ /* Update Service will fall back if version # does not exist for an indexer per Ta */
private const string DEFINITION_BRANCH = "master"; private const string DEFINITION_BRANCH = "master";
private const int DEFINITION_VERSION = 5; private const int DEFINITION_VERSION = 6;
//Used when moving yml to C# //Used when moving yml to C#
private readonly List<string> _defintionBlocklist = new List<string>() private readonly List<string> _defintionBlocklist = new List<string>()

View File

@@ -6,11 +6,9 @@ using System.Net.Http;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using AngleSharp.Html.Parser; using AngleSharp.Html.Parser;
using FluentValidation;
using NLog; using NLog;
using NzbDrone.Common.Extensions; using NzbDrone.Common.Extensions;
using NzbDrone.Common.Http; using NzbDrone.Common.Http;
using NzbDrone.Core.Annotations;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.Indexers.Exceptions; using NzbDrone.Core.Indexers.Exceptions;
using NzbDrone.Core.Indexers.Settings; using NzbDrone.Core.Indexers.Settings;
@@ -18,8 +16,6 @@ using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
using NzbDrone.Core.Parser.Model; using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.ThingiProvider;
using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.Definitions namespace NzbDrone.Core.Indexers.Definitions
{ {

View File

@@ -28,7 +28,7 @@ namespace NzbDrone.Core.Indexers.Cardigann
protected readonly IndexerCapabilitiesCategories _categories = new IndexerCapabilitiesCategories(); protected readonly IndexerCapabilitiesCategories _categories = new IndexerCapabilitiesCategories();
protected readonly List<string> _defaultCategories = new List<string>(); protected readonly List<string> _defaultCategories = new List<string>();
protected readonly string[] OptionalFields = new string[] { "imdb", "imdbid", "rageid", "tmdbid", "tvdbid", "poster", "banner", "description" }; protected readonly string[] OptionalFields = new string[] { "imdb", "imdbid", "rageid", "tmdbid", "tvdbid", "poster", "banner", "description", "doubanid" };
protected static readonly string[] _SupportedLogicFunctions = protected static readonly string[] _SupportedLogicFunctions =
{ {
@@ -338,9 +338,9 @@ namespace NzbDrone.Core.Indexers.Cardigann
return variables; return variables;
} }
protected delegate string TemplateTextModifier(string str); public delegate string TemplateTextModifier(string str);
protected string ApplyGoTemplateText(string template, Dictionary<string, object> variables = null, TemplateTextModifier modifier = null) public string ApplyGoTemplateText(string template, Dictionary<string, object> variables = null, TemplateTextModifier modifier = null)
{ {
if (variables == null) if (variables == null)
{ {
@@ -520,7 +520,7 @@ namespace NzbDrone.Core.Indexers.Cardigann
} }
// handle range expression // handle range expression
var rangeRegex = new Regex(@"{{\s*range\s*(.+?)\s*}}(.*?){{\.}}(.*?){{end}}"); var rangeRegex = new Regex(@"{{\s*range\s*(((?<index>\$.+?),)((\s*(?<element>.+?)\s*(:=)\s*)))?(?<variable>.+?)\s*}}(?<prefix>.*?){{\.}}(?<postfix>.*?){{end}}");
var rangeRegexMatches = rangeRegex.Match(template); var rangeRegexMatches = rangeRegex.Match(template);
while (rangeRegexMatches.Success) while (rangeRegexMatches.Success)
@@ -528,9 +528,13 @@ namespace NzbDrone.Core.Indexers.Cardigann
var expanded = string.Empty; var expanded = string.Empty;
var all = rangeRegexMatches.Groups[0].Value; var all = rangeRegexMatches.Groups[0].Value;
var variable = rangeRegexMatches.Groups[1].Value; var index = rangeRegexMatches.Groups["index"].Value;
var prefix = rangeRegexMatches.Groups[2].Value; var variable = rangeRegexMatches.Groups["variable"].Value;
var postfix = rangeRegexMatches.Groups[3].Value; var prefix = rangeRegexMatches.Groups["prefix"].Value;
var postfix = rangeRegexMatches.Groups["postfix"].Value;
var arrayIndex = 0;
var indexReplace = "{{" + index + "}}";
foreach (var value in (ICollection<string>)variables[variable]) foreach (var value in (ICollection<string>)variables[variable])
{ {
@@ -540,8 +544,17 @@ namespace NzbDrone.Core.Indexers.Cardigann
newvalue = modifier(newvalue); newvalue = modifier(newvalue);
} }
var indexValue = arrayIndex++;
if (index.IsNotNullOrWhiteSpace())
{
expanded += prefix.Replace(indexReplace, indexValue.ToString()) + newvalue + postfix.Replace(indexReplace, indexValue.ToString());
}
else
{
expanded += prefix + newvalue + postfix; expanded += prefix + newvalue + postfix;
} }
}
template = template.Replace(all, expanded); template = template.Replace(all, expanded);
rangeRegexMatches = rangeRegexMatches.NextMatch(); rangeRegexMatches = rangeRegexMatches.NextMatch();

View File

@@ -60,7 +60,9 @@ namespace NzbDrone.Core.Indexers.Cardigann
if (request.SearchPath.Response != null && request.SearchPath.Response.Type.Equals("json")) if (request.SearchPath.Response != null && request.SearchPath.Response.Type.Equals("json"))
{ {
if (request.SearchPath.Response != null && request.SearchPath.Response.NoResultsMessage != null && (request.SearchPath.Response.NoResultsMessage.Equals(results) || (request.SearchPath.Response.NoResultsMessage == string.Empty && results == string.Empty))) if (request.SearchPath.Response != null &&
request.SearchPath.Response.NoResultsMessage != null &&
((request.SearchPath.Response.NoResultsMessage != string.Empty && results.Contains(request.SearchPath.Response.NoResultsMessage)) || (request.SearchPath.Response.NoResultsMessage == string.Empty && results == string.Empty)))
{ {
return releases; return releases;
} }
@@ -575,6 +577,13 @@ namespace NzbDrone.Core.Indexers.Cardigann
release.TvdbId = (int)ParseUtil.CoerceLong(tvdbId); release.TvdbId = (int)ParseUtil.CoerceLong(tvdbId);
value = release.TvdbId.ToString(); value = release.TvdbId.ToString();
break; break;
case "doubanid":
var doubanIDRegEx = new Regex(@"(\d+)", RegexOptions.Compiled);
var doubanIDMatch = doubanIDRegEx.Match(value);
var doubanID = doubanIDMatch.Groups[1].Value;
release.DoubanId = (int)ParseUtil.CoerceLong(doubanID);
value = release.DoubanId.ToString();
break;
case "poster": case "poster":
if (!string.IsNullOrWhiteSpace(value)) if (!string.IsNullOrWhiteSpace(value))
{ {

View File

@@ -91,6 +91,7 @@ namespace NzbDrone.Core.Indexers.Cardigann
variables[".Query.IMDBID"] = searchCriteria.FullImdbId; variables[".Query.IMDBID"] = searchCriteria.FullImdbId;
variables[".Query.IMDBIDShort"] = searchCriteria.ImdbId; variables[".Query.IMDBIDShort"] = searchCriteria.ImdbId;
variables[".Query.TVDBID"] = searchCriteria.TvdbId?.ToString() ?? null; variables[".Query.TVDBID"] = searchCriteria.TvdbId?.ToString() ?? null;
variables[".Query.TMDBID"] = searchCriteria.TmdbId?.ToString() ?? null;
variables[".Query.TVRageID"] = searchCriteria.RId?.ToString() ?? null; variables[".Query.TVRageID"] = searchCriteria.RId?.ToString() ?? null;
variables[".Query.TVMazeID"] = searchCriteria.TvMazeId?.ToString() ?? null; variables[".Query.TVMazeID"] = searchCriteria.TvMazeId?.ToString() ?? null;
variables[".Query.TraktID"] = searchCriteria.TraktId?.ToString() ?? null; variables[".Query.TraktID"] = searchCriteria.TraktId?.ToString() ?? null;

View File

@@ -187,7 +187,7 @@ namespace NzbDrone.Core.Indexers.Newznab
} }
if (capabilities.TvSearchParams != null && if (capabilities.TvSearchParams != null &&
new[] { TvSearchParam.Q, TvSearchParam.TvdbId, TvSearchParam.RId }.Any(v => capabilities.TvSearchParams.Contains(v)) && new[] { TvSearchParam.Q, TvSearchParam.TvdbId, TvSearchParam.TmdbId, TvSearchParam.RId }.Any(v => capabilities.TvSearchParams.Contains(v)) &&
new[] { TvSearchParam.Season, TvSearchParam.Ep }.All(v => capabilities.TvSearchParams.Contains(v))) new[] { TvSearchParam.Season, TvSearchParam.Ep }.All(v => capabilities.TvSearchParams.Contains(v)))
{ {
return null; return null;

View File

@@ -125,6 +125,11 @@ namespace NzbDrone.Core.Indexers.Newznab
parameters.Add("tvdbid", searchCriteria.TvdbId.Value.ToString()); parameters.Add("tvdbid", searchCriteria.TvdbId.Value.ToString());
} }
if (searchCriteria.TmdbId.HasValue && capabilities.TvSearchTvdbAvailable)
{
parameters.Add("tmdbid", searchCriteria.TvdbId.Value.ToString());
}
if (searchCriteria.ImdbId.IsNotNullOrWhiteSpace() && capabilities.TvSearchImdbAvailable) if (searchCriteria.ImdbId.IsNotNullOrWhiteSpace() && capabilities.TvSearchImdbAvailable)
{ {
parameters.Add("imdbid", searchCriteria.ImdbId); parameters.Add("imdbid", searchCriteria.ImdbId);

View File

@@ -96,7 +96,7 @@ namespace NzbDrone.Core.Indexers.Newznab
releaseInfo = base.ProcessItem(item, releaseInfo); releaseInfo = base.ProcessItem(item, releaseInfo);
releaseInfo.ImdbId = GetIntAttribute(item, "imdb"); releaseInfo.ImdbId = GetIntAttribute(item, "imdb");
releaseInfo.TmdbId = GetIntAttribute(item, "tmdb"); releaseInfo.TmdbId = GetIntAttribute(item, "tmdbid");
releaseInfo.TvdbId = GetIntAttribute(item, "tvdbid"); releaseInfo.TvdbId = GetIntAttribute(item, "tvdbid");
releaseInfo.TvRageId = GetIntAttribute(item, "rageid"); releaseInfo.TvRageId = GetIntAttribute(item, "rageid");
releaseInfo.Grabs = GetIntAttribute(item, "grabs"); releaseInfo.Grabs = GetIntAttribute(item, "grabs");

View File

@@ -33,6 +33,7 @@ namespace NzbDrone.Core.Parser.Model
public int ImdbId { get; set; } public int ImdbId { get; set; }
public int TmdbId { get; set; } public int TmdbId { get; set; }
public int TraktId { get; set; } public int TraktId { get; set; }
public int DoubanId { get; set; }
public int Year { get; set; } public int Year { get; set; }
public string Author { get; set; } public string Author { get; set; }
public string BookTitle { get; set; } public string BookTitle { get; set; }