Lidarr/NzbDrone.Core/Indexers/RssParserBase.cs

174 lines
5.4 KiB
C#
Raw Normal View History

2013-04-07 07:30:37 +00:00
using System;
using System.Collections.Generic;
2013-04-07 22:40:13 +00:00
using System.Globalization;
2013-04-07 07:30:37 +00:00
using System.IO;
2013-08-06 05:30:56 +00:00
using System.Linq;
2013-04-07 22:40:13 +00:00
using System.Text.RegularExpressions;
using System.Xml;
2013-08-06 02:45:57 +00:00
using System.Xml.Linq;
2013-04-07 07:30:37 +00:00
using NLog;
2013-08-31 01:42:30 +00:00
using NzbDrone.Common.Instrumentation;
2013-09-13 23:17:58 +00:00
using NzbDrone.Core.Indexers.Newznab;
using NzbDrone.Core.Parser.Model;
2013-04-07 07:30:37 +00:00
namespace NzbDrone.Core.Indexers
{
2013-09-13 23:17:58 +00:00
public abstract class RssParserBase : IParseFeed
2013-04-07 07:30:37 +00:00
{
private readonly Logger _logger;
2013-04-07 07:30:37 +00:00
2013-09-13 23:17:58 +00:00
protected virtual ReleaseInfo CreateNewReleaseInfo()
{
return new ReleaseInfo();
}
2013-04-07 07:30:37 +00:00
2013-09-13 23:17:58 +00:00
protected RssParserBase()
2013-04-07 07:30:37 +00:00
{
2013-08-31 01:42:30 +00:00
_logger = NzbDroneLogger.GetLogger(this);
2013-04-07 07:30:37 +00:00
}
2013-09-13 23:17:58 +00:00
public IEnumerable<ReleaseInfo> Process(string xml, string url)
2013-04-07 07:30:37 +00:00
{
PreProcess(xml, url);
2013-08-30 02:27:23 +00:00
using (var xmlTextReader = XmlReader.Create(new StringReader(xml), new XmlReaderSettings { ProhibitDtd = false, IgnoreComments = true }))
{
2013-09-13 23:17:58 +00:00
var document = XDocument.Load(xmlTextReader);
var items = document.Descendants("item");
2013-04-07 07:30:37 +00:00
2013-09-13 23:17:58 +00:00
var result = new List<ReleaseInfo>();
2013-04-07 07:30:37 +00:00
foreach (var item in items)
2013-04-07 07:30:37 +00:00
{
try
2013-04-07 07:30:37 +00:00
{
2013-09-13 23:17:58 +00:00
var reportInfo = ParseFeedItem(item.StripNameSpace(), url);
if (reportInfo != null)
{
2013-09-13 23:17:58 +00:00
reportInfo.DownloadUrl = GetNzbUrl(item);
reportInfo.InfoUrl = GetNzbInfoUrl(item);
result.Add(reportInfo);
}
}
catch (Exception itemEx)
{
itemEx.Data.Add("Item", item.Title());
_logger.ErrorException("An error occurred while processing feed item from " + url, itemEx);
2013-04-07 07:30:37 +00:00
}
}
return result;
}
2013-04-07 07:30:37 +00:00
}
2013-09-13 23:17:58 +00:00
private ReleaseInfo ParseFeedItem(XElement item, string url)
{
var title = GetTitle(item);
var reportInfo = CreateNewReleaseInfo();
reportInfo.Title = title;
reportInfo.PublishDate = item.PublishDate();
reportInfo.ReleaseGroup = ParseReleaseGroup(title);
reportInfo.DownloadUrl = GetNzbUrl(item);
reportInfo.InfoUrl = GetNzbInfoUrl(item);
try
{
reportInfo.Size = GetSize(item);
}
catch (Exception)
{
throw new SizeParsingException("Unable to parse size from: {0} [{1}]", reportInfo.Title, url);
}
_logger.Trace("Parsed: {0} from: {1}", reportInfo, item.Title());
return PostProcessor(item, reportInfo);
}
2013-04-07 07:30:37 +00:00
2013-08-06 02:45:57 +00:00
protected virtual string GetTitle(XElement item)
2013-04-07 07:30:37 +00:00
{
2013-08-06 02:45:57 +00:00
return item.Title();
2013-04-07 07:30:37 +00:00
}
2013-08-06 02:45:57 +00:00
protected virtual string GetNzbUrl(XElement item)
2013-04-07 07:30:37 +00:00
{
2013-08-06 05:30:56 +00:00
return item.Links().First();
2013-04-07 07:30:37 +00:00
}
2013-08-06 02:45:57 +00:00
protected virtual string GetNzbInfoUrl(XElement item)
2013-04-07 07:30:37 +00:00
{
2013-04-07 22:40:13 +00:00
return String.Empty;
2013-04-07 07:30:37 +00:00
}
2013-09-13 23:17:58 +00:00
protected abstract long GetSize(XElement item);
protected virtual void PreProcess(string source, string url)
{
}
2013-09-13 23:17:58 +00:00
protected virtual ReleaseInfo PostProcessor(XElement item, ReleaseInfo currentResult)
2013-04-07 07:30:37 +00:00
{
return currentResult;
}
2013-04-07 22:40:13 +00:00
public static string ParseReleaseGroup(string title)
{
title = title.Trim();
var index = title.LastIndexOf('-');
if (index < 0)
index = title.LastIndexOf(' ');
if (index < 0)
return String.Empty;
var group = title.Substring(index + 1);
2013-04-07 22:40:13 +00:00
if (@group.Length == title.Length)
return String.Empty;
2013-09-13 23:17:58 +00:00
return @group.Trim('-', ' ', '[', ']');
2013-04-07 22:40:13 +00:00
}
2013-07-17 07:33:54 +00:00
private static readonly Regex ReportSizeRegex = new Regex(@"(?<value>\d+\.\d{1,2}|\d+\,\d+\.\d{1,2}|\d+)\W?(?<unit>GB|MB|GiB|MiB)",
2013-04-07 22:40:13 +00:00
RegexOptions.IgnoreCase | RegexOptions.Compiled);
2013-09-13 23:17:58 +00:00
public static long ParseSize(string sizeString)
2013-04-07 22:40:13 +00:00
{
var match = ReportSizeRegex.Matches(sizeString);
if (match.Count != 0)
{
var cultureInfo = new CultureInfo("en-US");
var value = Decimal.Parse(Regex.Replace(match[0].Groups["value"].Value, "\\,", ""), cultureInfo);
var unit = match[0].Groups["unit"].Value;
if (unit.Equals("MB", StringComparison.InvariantCultureIgnoreCase) ||
unit.Equals("MiB", StringComparison.InvariantCultureIgnoreCase))
{
2013-07-17 07:33:54 +00:00
return ConvertToBytes(Convert.ToDouble(value), 2);
}
2013-04-07 22:40:13 +00:00
if (unit.Equals("GB", StringComparison.InvariantCultureIgnoreCase) ||
unit.Equals("GiB", StringComparison.InvariantCultureIgnoreCase))
{
2013-07-17 07:33:54 +00:00
return ConvertToBytes(Convert.ToDouble(value), 3);
}
2013-04-07 22:40:13 +00:00
}
return 0;
}
2013-07-17 07:33:54 +00:00
private static long ConvertToBytes(double value, int power)
{
var multiplier = Math.Pow(1024, power);
var result = value * multiplier;
2013-07-17 07:33:54 +00:00
return Convert.ToInt64(result);
}
2013-04-07 07:30:37 +00:00
}
2013-09-13 23:17:58 +00:00
}