diff --git a/src/Jackett.Common/Indexers/BaseIndexer.cs b/src/Jackett.Common/Indexers/BaseIndexer.cs index 77453dff6..1745b91ba 100644 --- a/src/Jackett.Common/Indexers/BaseIndexer.cs +++ b/src/Jackett.Common/Indexers/BaseIndexer.cs @@ -265,7 +265,7 @@ namespace Jackett.Common.Indexers return results; var filteredResults = results.Where( - result => result.Category.IsEmptyOrNull() || query.Categories.Intersect(result.Category).Any() || + result => result.Category?.Any() != true || query.Categories.Intersect(result.Category).Any() || TorznabCatType.QueryContainsParentCategory(query.Categories, result.Category)); return filteredResults; diff --git a/src/Jackett.Common/Indexers/Meta/BaseMetaIndexer.cs b/src/Jackett.Common/Indexers/Meta/BaseMetaIndexer.cs index c65789d90..fe933b684 100644 --- a/src/Jackett.Common/Indexers/Meta/BaseMetaIndexer.cs +++ b/src/Jackett.Common/Indexers/Meta/BaseMetaIndexer.cs @@ -85,7 +85,7 @@ namespace Jackett.Common.Indexers.Meta logger.Error(aggregateTask.Exception, "Error during request in metaindexer " + ID); } - var unorderedResult = aggregateTask.Result.Select(r => r.Releases).Flatten(); + var unorderedResult = aggregateTask.Result.SelectMany(r => r.Releases); var resultFilters = resultFilterProvider.FiltersForQuery(query); var filteredResults = resultFilters.Select(async f => await f.FilterResults(unorderedResult)).SelectMany(t => t.Result); var uniqueFilteredResults = filteredResults.Distinct(); diff --git a/src/Jackett.Common/Indexers/Meta/Fallbacks.cs b/src/Jackett.Common/Indexers/Meta/Fallbacks.cs index f977faa6b..e3f44ff0b 100644 --- a/src/Jackett.Common/Indexers/Meta/Fallbacks.cs +++ b/src/Jackett.Common/Indexers/Meta/Fallbacks.cs @@ -24,7 +24,7 @@ namespace Jackett.Common.Indexers.Meta public class NoFallbackStrategyProvider : IFallbackStrategyProvider { - public IEnumerable FallbackStrategiesForQuery(TorznabQuery query) => (new NoFallbackStrategy()).ToEnumerable(); + public IEnumerable FallbackStrategiesForQuery(TorznabQuery query) { yield return new NoFallbackStrategy(); } } public class ImdbFallbackStrategy : IFallbackStrategy @@ -32,18 +32,16 @@ namespace Jackett.Common.Indexers.Meta public ImdbFallbackStrategy(IImdbResolver resolver, TorznabQuery query) { this.resolver = resolver; - titles = null; this.query = query; } public async Task> FallbackQueries() { - titles ??= (await resolver.MovieForId(query.ImdbID.ToNonNull())).Title?.ToEnumerable() ?? Enumerable.Empty(); - return titles.Select(query.CreateFallback); + var title = (await resolver.MovieForId(query.ImdbID.ToNonNull())).Title; + return title != null ? new[] {query.CreateFallback(title)} : Enumerable.Empty(); } private readonly IImdbResolver resolver; - private IEnumerable titles; private readonly TorznabQuery query; } diff --git a/src/Jackett.Common/Indexers/Meta/ResultFilters.cs b/src/Jackett.Common/Indexers/Meta/ResultFilters.cs index 33284de8b..3a4ebe073 100644 --- a/src/Jackett.Common/Indexers/Meta/ResultFilters.cs +++ b/src/Jackett.Common/Indexers/Meta/ResultFilters.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; @@ -55,20 +56,16 @@ namespace Jackett.Common.Indexers.Meta var remainingResults = results.Except(wrongResults).Except(perfectResults); - var titles = (await resolver.MovieForId(query.ImdbID.ToNonNull())).Title?.ToEnumerable() ?? Enumerable.Empty(); - var strippedTitles = titles.Select(t => RemoveSpecialChars(t)); - var normalizedTitles = strippedTitles.SelectMany(t => GenerateTitleVariants(t)); + var title = (await resolver.MovieForId(query.ImdbID.ToNonNull())).Title; + if (title == null) + return perfectResults; - var titleFilteredResults = remainingResults.Where(r => - { - // TODO Make it possible to configure case insensitivity - var containsAnyTitle = normalizedTitles.Select(t => r.Title.ToLowerInvariant().Contains(t.ToLowerInvariant())); - var isProbablyValidResult = containsAnyTitle.Any(b => b); - return isProbablyValidResult; - }); + var normalizedTitles = GenerateTitleVariants(RemoveSpecialChars(title)); - var filteredResults = perfectResults.Concat(titleFilteredResults).Distinct(); - return filteredResults; + // TODO Make it possible to configure case insensitivity + var titleFilteredResults = remainingResults.Where( + r => normalizedTitles.Any(t => r.Title.IndexOf(t, StringComparison.InvariantCultureIgnoreCase) >= 0)); + return perfectResults.Union(titleFilteredResults); } // TODO improve character replacement with invalid chars @@ -97,7 +94,7 @@ namespace Jackett.Common.Indexers.Meta public class NoResultFilterProvider : IResultFilterProvider { - public IEnumerable FiltersForQuery(TorznabQuery query) => (new NoFilter()).ToEnumerable(); + public IEnumerable FiltersForQuery(TorznabQuery query) { yield return new NoFilter(); } } public class ImdbTitleResultFilterProvider : IResultFilterProvider @@ -106,12 +103,7 @@ namespace Jackett.Common.Indexers.Meta public IEnumerable FiltersForQuery(TorznabQuery query) { - IResultFilter filter = null; - if (!query.IsImdbQuery) - filter = new NoFilter(); - else - filter = new ImdbTitleResultFilter(resolver, query); - return filter.ToEnumerable(); + yield return !query.IsImdbQuery ? (IResultFilter)new NoFilter() : new ImdbTitleResultFilter(resolver, query); } private readonly IImdbResolver resolver; diff --git a/src/Jackett.Common/Indexers/TVstore.cs b/src/Jackett.Common/Indexers/TVstore.cs index ea4bac6bd..47dfc7e0a 100644 --- a/src/Jackett.Common/Indexers/TVstore.cs +++ b/src/Jackett.Common/Indexers/TVstore.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Globalization; +using System.Linq; using System.Net; using System.Text; using System.Text.RegularExpressions; @@ -255,12 +256,9 @@ namespace Jackett.Common.Indexers //TODO convert to initializer var releases = new List(); - /* If series from sites are indexed than we dont need to reindex them. */ - if (series == null || series.IsEmpty()) - { + // If series from sites are indexed then we don't need to reindex them. + if (series?.Any() != true) await GetSeriesInfo(); - } - var unixTimestamp = (int)(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds; WebClientStringResult results; diff --git a/src/Jackett.Common/Models/TorznabQuery.cs b/src/Jackett.Common/Models/TorznabQuery.cs index 606e9aea2..c890ead60 100644 --- a/src/Jackett.Common/Models/TorznabQuery.cs +++ b/src/Jackett.Common/Models/TorznabQuery.cs @@ -56,7 +56,7 @@ namespace Jackett.Common.Models var term = SearchTerm; if (SearchTerm == null) term = ""; - var safetitle = term.Where(c => (char.IsLetterOrDigit(c) + var safeTitle = term.Where(c => (char.IsLetterOrDigit(c) || char.IsWhiteSpace(c) || c == '-' || c == '.' @@ -70,8 +70,8 @@ namespace Jackett.Common.Models || c == ']' || c == '+' || c == '%' - )).AsString(); - return safetitle; + )); + return string.Concat(safeTitle); } } diff --git a/src/Jackett.Common/Utils/Extensions.cs b/src/Jackett.Common/Utils/Extensions.cs index 1194267d6..f97bd99cc 100644 --- a/src/Jackett.Common/Utils/Extensions.cs +++ b/src/Jackett.Common/Utils/Extensions.cs @@ -32,36 +32,18 @@ namespace Jackett.Common.Utils public static class GenericConversionExtensions { - public static IEnumerable ToEnumerable(this T obj) => new T[] { obj }; - public static NonNull ToNonNull(this T obj) where T : class => new NonNull(obj); } public static class EnumerableExtension { - public static string AsString(this IEnumerable chars) => string.Concat(chars); - - public static T FirstIfSingleOrDefault(this IEnumerable enumerable, T replace = default) + public static T FirstIfSingleOrDefault(this IEnumerable source, T replace = default) { - //Avoid enumerating the whole array. - //If enumerable.Count() < 2, takes whole array. - var test = enumerable.Take(2).ToList(); + if (source is ICollection collection) + return collection.Count == 1 ? collection.First() : replace; + var test = source.Take(2).ToList(); return test.Count == 1 ? test[0] : replace; } - - public static IEnumerable Flatten(this IEnumerable> list) => list.SelectMany(x => x); - } - - public static class CollectionExtension - { - // IEnumerable class above already does this. All ICollection are IEnumerable, so favor IEnumerable? - public static bool IsEmpty(this ICollection obj) => obj.Count == 0; - - // obj == null || obj.IsEmpty() causes VS to suggest merging sequential checks - // the result is obj?.IsEmpty() == true which returns false when null - // Other options are obj?.IsEmpty() == true || obj == null Or (obj?.IsEmpty()).GetValueOrDefault(true) - // All three options remove the suggestion and give the intended result of this function - public static bool IsEmptyOrNull(this ICollection obj) => obj?.IsEmpty() ?? true; } public static class XElementExtension @@ -71,11 +53,6 @@ namespace Jackett.Common.Utils public static string FirstValue(this XElement element, string name) => element.First(name).Value; } - public static class KeyValuePairsExtension - { - public static IDictionary ToDictionary(this IEnumerable> pairs) => pairs.ToDictionary(x => x.Key, x => x.Value); - } - public static class TaskExtensions { public static Task> Until(this IEnumerable> tasks, TimeSpan timeout)