New: Detect audio vs text from newznab categories

pull/1063/head
ta264 4 years ago
parent 065f03a01a
commit 3abda061ba

@ -11,6 +11,7 @@ using NzbDrone.Core.DecisionEngine.Specifications;
using NzbDrone.Core.IndexerSearch.Definitions; using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
using NzbDrone.Core.Parser.Model; using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Qualities;
using NzbDrone.Core.Test.Framework; using NzbDrone.Core.Test.Framework;
using NzbDrone.Test.Common; using NzbDrone.Test.Common;
@ -60,7 +61,8 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
_remoteBook = new RemoteBook _remoteBook = new RemoteBook
{ {
Author = new Author(), Author = new Author(),
Books = new List<Book> { new Book() } Books = new List<Book> { new Book() },
ParsedBookInfo = Builder<ParsedBookInfo>.CreateNew().With(x => x.Quality = new QualityModel(Quality.FLAC)).Build()
}; };
Mocker.GetMock<IParsingService>() Mocker.GetMock<IParsingService>()

@ -21,7 +21,7 @@ namespace NzbDrone.Core.Test.Profiles
Subject.Handle(new ApplicationStartedEvent()); Subject.Handle(new ApplicationStartedEvent());
Mocker.GetMock<IProfileRepository>() Mocker.GetMock<IProfileRepository>()
.Verify(v => v.Insert(It.IsAny<QualityProfile>()), Times.Exactly(4)); .Verify(v => v.Insert(It.IsAny<QualityProfile>()), Times.Exactly(3));
} }
[Test] [Test]

@ -10,6 +10,7 @@ using NzbDrone.Core.Download.Aggregation;
using NzbDrone.Core.IndexerSearch.Definitions; using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
using NzbDrone.Core.Parser.Model; using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Qualities;
namespace NzbDrone.Core.DecisionEngine namespace NzbDrone.Core.DecisionEngine
{ {
@ -105,6 +106,12 @@ namespace NzbDrone.Core.DecisionEngine
remoteBook.Release = report; remoteBook.Release = report;
// parse quality again with title and category if unknown
if (remoteBook.ParsedBookInfo.Quality.Quality == Quality.Unknown)
{
remoteBook.ParsedBookInfo.Quality = QualityParser.ParseQuality(report.Title, null, report.Categories);
}
if (remoteBook.Author == null) if (remoteBook.Author == null)
{ {
decision = new DownloadDecision(remoteBook, new Rejection("Unknown Author")); decision = new DownloadDecision(remoteBook, new Rejection("Unknown Author"));
@ -138,7 +145,7 @@ namespace NzbDrone.Core.DecisionEngine
{ {
parsedBookInfo = new ParsedBookInfo parsedBookInfo = new ParsedBookInfo
{ {
Quality = QualityParser.ParseQuality(report.Title) Quality = QualityParser.ParseQuality(report.Title, null, report.Categories)
}; };
} }
@ -160,7 +167,7 @@ namespace NzbDrone.Core.DecisionEngine
{ {
parsedBookInfo = new ParsedBookInfo parsedBookInfo = new ParsedBookInfo
{ {
Quality = QualityParser.ParseQuality(report.Title, null) Quality = QualityParser.ParseQuality(report.Title, null, report.Categories)
}; };
} }

@ -121,6 +121,25 @@ namespace NzbDrone.Core.Indexers.Newznab
return base.GetPublishDate(item); return base.GetPublishDate(item);
} }
protected override List<int> GetCategories(XElement item)
{
var values = item.Elements(ns + "attr")
.Where(e => e.Attribute("name").Value.Equals("category", StringComparison.OrdinalIgnoreCase) &&
e.Attribute("value")?.Value != null)
.Select(e => e.Attribute("value").Value);
var cats = new List<int>();
foreach (var value in values)
{
if (int.TryParse(value, out var cat))
{
cats.Add(cat);
}
}
return cats;
}
protected virtual string GetAuthor(XElement item) protected virtual string GetAuthor(XElement item)
{ {
var authorString = TryGetNewznabAttribute(item, "author"); var authorString = TryGetNewznabAttribute(item, "author");

@ -159,6 +159,7 @@ namespace NzbDrone.Core.Indexers
releaseInfo.BasicAuthString = GetBasicAuth(); releaseInfo.BasicAuthString = GetBasicAuth();
releaseInfo.InfoUrl = GetInfoUrl(item); releaseInfo.InfoUrl = GetInfoUrl(item);
releaseInfo.CommentUrl = GetCommentUrl(item); releaseInfo.CommentUrl = GetCommentUrl(item);
releaseInfo.Categories = GetCategories(item);
try try
{ {
@ -230,6 +231,11 @@ namespace NzbDrone.Core.Indexers
return ParseUrl((string)item.Element("comments")); return ParseUrl((string)item.Element("comments"));
} }
protected virtual List<int> GetCategories(XElement item)
{
return new List<int>();
}
protected virtual long GetSize(XElement item) protected virtual long GetSize(XElement item)
{ {
if (UseEnclosureLength) if (UseEnclosureLength)

@ -91,9 +91,23 @@ namespace NzbDrone.Core.Indexers.Torznab
return size; return size;
} }
protected override DateTime GetPublishDate(XElement item) protected override List<int> GetCategories(XElement item)
{ {
return base.GetPublishDate(item); var values = item.Elements(ns + "attr")
.Where(e => e.Attribute("name").Value.Equals("category", StringComparison.OrdinalIgnoreCase) &&
e.Attribute("value")?.Value != null)
.Select(e => e.Attribute("value").Value);
var cats = new List<int>();
foreach (var value in values)
{
if (int.TryParse(value, out var cat))
{
cats.Add(cat);
}
}
return cats;
} }
protected override string GetDownloadUrl(XElement item) protected override string GetDownloadUrl(XElement item)

@ -1,4 +1,5 @@
using System; using System;
using System.Collections.Generic;
using System.Text; using System.Text;
using NzbDrone.Core.Indexers; using NzbDrone.Core.Indexers;
@ -25,7 +26,7 @@ namespace NzbDrone.Core.Parser.Model
public string Source { get; set; } public string Source { get; set; }
public string Container { get; set; } public string Container { get; set; }
public string Codec { get; set; } public string Codec { get; set; }
public string Resolution { get; set; } public List<int> Categories { get; set; }
public int Age public int Age
{ {

@ -1,5 +1,7 @@
using System; using System;
using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using NLog; using NLog;
using NzbDrone.Common.Disk; using NzbDrone.Common.Disk;
@ -29,7 +31,7 @@ namespace NzbDrone.Core.Parser
private static readonly Regex CodecRegex = new Regex(@"\b(?:(?<PDF>PDF)|(?<MOBI>MOBI)|(?<EPUB>EPUB)|(?<AZW3>AZW3?)|(?<MP1>MPEG Version \d(.5)? Audio, Layer 1|MP1)|(?<MP2>MPEG Version \d(.5)? Audio, Layer 2|MP2)|(?<MP3VBR>MP3.*VBR|MPEG Version \d(.5)? Audio, Layer 3 vbr)|(?<MP3CBR>MP3|MPEG Version \d(.5)? Audio, Layer 3)|(?<FLAC>flac)|(?<WAVPACK>wavpack|wv)|(?<ALAC>alac)|(?<WMA>WMA\d?)|(?<WAV>WAV|PCM)|(?<AAC>M4A|M4P|M4B|AAC|mp4a|MPEG-4 Audio(?!.*alac))|(?<OGG>OGG|OGA|Vorbis))\b|(?<APE>monkey's audio|[\[|\(].*\bape\b.*[\]|\)])|(?<OPUS>Opus Version \d(.5)? Audio|[\[|\(].*\bopus\b.*[\]|\)])", private static readonly Regex CodecRegex = new Regex(@"\b(?:(?<PDF>PDF)|(?<MOBI>MOBI)|(?<EPUB>EPUB)|(?<AZW3>AZW3?)|(?<MP1>MPEG Version \d(.5)? Audio, Layer 1|MP1)|(?<MP2>MPEG Version \d(.5)? Audio, Layer 2|MP2)|(?<MP3VBR>MP3.*VBR|MPEG Version \d(.5)? Audio, Layer 3 vbr)|(?<MP3CBR>MP3|MPEG Version \d(.5)? Audio, Layer 3)|(?<FLAC>flac)|(?<WAVPACK>wavpack|wv)|(?<ALAC>alac)|(?<WMA>WMA\d?)|(?<WAV>WAV|PCM)|(?<AAC>M4A|M4P|M4B|AAC|mp4a|MPEG-4 Audio(?!.*alac))|(?<OGG>OGG|OGA|Vorbis))\b|(?<APE>monkey's audio|[\[|\(].*\bape\b.*[\]|\)])|(?<OPUS>Opus Version \d(.5)? Audio|[\[|\(].*\bopus\b.*[\]|\)])",
RegexOptions.Compiled | RegexOptions.IgnoreCase); RegexOptions.Compiled | RegexOptions.IgnoreCase);
public static QualityModel ParseQuality(string name, string desc = null) public static QualityModel ParseQuality(string name, string desc = null, List<int> categories = null)
{ {
Logger.Debug("Trying to parse quality for {0}", name); Logger.Debug("Trying to parse quality for {0}", name);
@ -107,6 +109,16 @@ namespace NzbDrone.Core.Parser
} }
} }
//Based on category
if (result.Quality == Quality.Unknown && categories != null)
{
if (categories.Any(x => x >= 3000 && x < 4000))
{
result.Quality = Quality.UnknownAudio;
result.QualityDetectionSource = QualityDetectionSource.Category;
}
}
return result; return result;
} }

@ -1,9 +1,10 @@
namespace NzbDrone.Core.Qualities namespace NzbDrone.Core.Qualities
{ {
public enum QualityDetectionSource public enum QualityDetectionSource
{ {
Name, Name,
Extension, Extension,
TagLib TagLib,
Category
} }
} }

Loading…
Cancel
Save