mirror of
https://github.com/Prowlarr/Prowlarr.git
synced 2025-09-17 17:14:18 +02:00
V6 Cardigann Changes (#1045)
* V6 Cardigann Changes * fixup! * !fixup range * !fixup more cardigann tests
This commit is contained in:
@@ -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' }
|
||||||
|
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -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);
|
||||||
|
@@ -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),
|
||||||
|
@@ -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>()
|
||||||
|
@@ -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
|
||||||
{
|
{
|
||||||
|
@@ -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();
|
||||||
|
@@ -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))
|
||||||
{
|
{
|
||||||
|
@@ -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;
|
||||||
|
@@ -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;
|
||||||
|
@@ -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);
|
||||||
|
@@ -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");
|
||||||
|
@@ -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; }
|
||||||
|
Reference in New Issue
Block a user