2013-04-07 10:30:37 +03:00
|
|
|
using System;
|
|
|
|
using System.Collections.Generic;
|
2013-04-08 01:40:13 +03:00
|
|
|
using System.Globalization;
|
2013-04-07 10:30:37 +03:00
|
|
|
using System.IO;
|
2013-08-06 08:30:56 +03:00
|
|
|
using System.Linq;
|
2013-04-08 01:40:13 +03:00
|
|
|
using System.Text.RegularExpressions;
|
2013-08-06 05:45:57 +03:00
|
|
|
using System.Xml.Linq;
|
2013-04-07 10:30:37 +03:00
|
|
|
using NLog;
|
2013-04-15 04:41:39 +03:00
|
|
|
using NzbDrone.Core.Parser.Model;
|
2013-04-07 10:30:37 +03:00
|
|
|
|
|
|
|
namespace NzbDrone.Core.Indexers
|
|
|
|
{
|
|
|
|
public interface IParseFeed
|
|
|
|
{
|
2013-04-15 04:41:39 +03:00
|
|
|
IEnumerable<ReportInfo> Process(Stream source);
|
2013-04-07 10:30:37 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
public class BasicRssParser : IParseFeed
|
|
|
|
{
|
|
|
|
private readonly Logger _logger;
|
|
|
|
|
|
|
|
public BasicRssParser()
|
|
|
|
{
|
|
|
|
_logger = LogManager.GetCurrentClassLogger();
|
|
|
|
}
|
|
|
|
|
2013-04-15 04:41:39 +03:00
|
|
|
public IEnumerable<ReportInfo> Process(Stream source)
|
2013-04-07 10:30:37 +03:00
|
|
|
{
|
2013-08-06 05:45:57 +03:00
|
|
|
var xdoc = XDocument.Load(source);
|
|
|
|
var items = xdoc.Descendants("item");
|
2013-04-07 10:30:37 +03:00
|
|
|
|
2013-04-15 04:41:39 +03:00
|
|
|
var result = new List<ReportInfo>();
|
2013-04-07 10:30:37 +03:00
|
|
|
|
2013-08-06 05:45:57 +03:00
|
|
|
foreach (var item in items)
|
2013-04-07 10:30:37 +03:00
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
2013-08-06 05:45:57 +03:00
|
|
|
var reportInfo = ParseFeedItem(item);
|
|
|
|
if (reportInfo != null)
|
2013-04-07 10:30:37 +03:00
|
|
|
{
|
2013-08-06 05:45:57 +03:00
|
|
|
reportInfo.NzbUrl = GetNzbUrl(item);
|
|
|
|
reportInfo.NzbInfoUrl = GetNzbInfoUrl(item);
|
|
|
|
|
|
|
|
result.Add(reportInfo);
|
2013-04-07 10:30:37 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (Exception itemEx)
|
|
|
|
{
|
2013-08-06 05:45:57 +03:00
|
|
|
itemEx.Data.Add("Item", item.Title());
|
2013-04-07 10:30:37 +03:00
|
|
|
_logger.ErrorException("An error occurred while processing feed item", itemEx);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-08-06 05:45:57 +03:00
|
|
|
protected virtual string GetTitle(XElement item)
|
2013-04-07 10:30:37 +03:00
|
|
|
{
|
2013-08-06 05:45:57 +03:00
|
|
|
return item.Title();
|
2013-04-07 10:30:37 +03:00
|
|
|
}
|
|
|
|
|
2013-08-06 05:45:57 +03:00
|
|
|
protected virtual string GetNzbUrl(XElement item)
|
2013-04-07 10:30:37 +03:00
|
|
|
{
|
2013-08-06 08:30:56 +03:00
|
|
|
return item.Links().First();
|
2013-04-07 10:30:37 +03:00
|
|
|
}
|
|
|
|
|
2013-08-06 05:45:57 +03:00
|
|
|
protected virtual string GetNzbInfoUrl(XElement item)
|
2013-04-07 10:30:37 +03:00
|
|
|
{
|
2013-04-08 01:40:13 +03:00
|
|
|
return String.Empty;
|
2013-04-07 10:30:37 +03:00
|
|
|
}
|
|
|
|
|
2013-08-06 05:45:57 +03:00
|
|
|
protected virtual ReportInfo PostProcessor(XElement item, ReportInfo currentResult)
|
2013-04-07 10:30:37 +03:00
|
|
|
{
|
|
|
|
return currentResult;
|
|
|
|
}
|
|
|
|
|
2013-08-06 05:45:57 +03:00
|
|
|
private ReportInfo ParseFeedItem(XElement item)
|
2013-04-07 10:30:37 +03:00
|
|
|
{
|
|
|
|
var title = GetTitle(item);
|
|
|
|
|
2013-04-23 09:14:55 +03:00
|
|
|
var reportInfo = new ReportInfo();
|
2013-04-15 04:41:39 +03:00
|
|
|
|
2013-04-23 09:14:55 +03:00
|
|
|
reportInfo.Title = title;
|
2013-08-06 05:45:57 +03:00
|
|
|
reportInfo.Age = DateTime.Now.Date.Subtract(item.PublishDate().Date).Days;
|
2013-04-23 09:14:55 +03:00
|
|
|
reportInfo.ReleaseGroup = ParseReleaseGroup(title);
|
2013-04-07 10:30:37 +03:00
|
|
|
|
2013-08-06 05:45:57 +03:00
|
|
|
_logger.Trace("Parsed: {0} from: {1}", reportInfo, item.Title());
|
2013-04-07 10:30:37 +03:00
|
|
|
|
2013-04-23 09:14:55 +03:00
|
|
|
return PostProcessor(item, reportInfo);
|
2013-04-07 10:30:37 +03:00
|
|
|
}
|
2013-04-07 22:01:24 +03:00
|
|
|
|
2013-04-08 01:40:13 +03:00
|
|
|
public static string ParseReleaseGroup(string title)
|
2013-04-07 22:01:24 +03:00
|
|
|
{
|
|
|
|
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-08 01:40:13 +03:00
|
|
|
if (@group.Length == title.Length)
|
2013-04-07 22:01:24 +03:00
|
|
|
return String.Empty;
|
|
|
|
|
2013-04-08 01:40:13 +03:00
|
|
|
return @group;
|
|
|
|
}
|
|
|
|
|
|
|
|
private static readonly Regex[] HeaderRegex = new[]
|
|
|
|
{
|
|
|
|
new Regex(@"(?:\[.+\]\-\[.+\]\-\[.+\]\-\[)(?<nzbTitle>.+)(?:\]\-.+)",
|
|
|
|
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
|
|
|
|
|
|
|
new Regex(@"(?:\[.+\]\W+\[.+\]\W+\[.+\]\W+\"")(?<nzbTitle>.+)(?:\"".+)",
|
|
|
|
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
|
|
|
|
|
|
|
new Regex(@"(?:\[)(?<nzbTitle>.+)(?:\]\-.+)",
|
|
|
|
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
|
|
|
};
|
|
|
|
|
|
|
|
public static string ParseHeader(string header)
|
|
|
|
{
|
|
|
|
foreach (var regex in HeaderRegex)
|
|
|
|
{
|
|
|
|
var match = regex.Matches(header);
|
|
|
|
|
|
|
|
if (match.Count != 0)
|
|
|
|
return match[0].Groups["nzbTitle"].Value.Trim();
|
|
|
|
}
|
|
|
|
|
|
|
|
return header;
|
|
|
|
}
|
|
|
|
|
2013-07-17 10:33:54 +03: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-08 01:40:13 +03:00
|
|
|
RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
|
|
|
|
|
|
|
|
|
|
|
public static long GetReportSize(string sizeString)
|
|
|
|
{
|
|
|
|
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;
|
|
|
|
|
2013-07-17 09:58:50 +03:00
|
|
|
if (unit.Equals("MB", StringComparison.InvariantCultureIgnoreCase) ||
|
|
|
|
unit.Equals("MiB", StringComparison.InvariantCultureIgnoreCase))
|
|
|
|
{
|
2013-07-17 10:33:54 +03:00
|
|
|
return ConvertToBytes(Convert.ToDouble(value), 2);
|
2013-07-17 09:58:50 +03:00
|
|
|
}
|
2013-04-08 01:40:13 +03:00
|
|
|
|
2013-07-17 09:58:50 +03:00
|
|
|
if (unit.Equals("GB", StringComparison.InvariantCultureIgnoreCase) ||
|
|
|
|
unit.Equals("GiB", StringComparison.InvariantCultureIgnoreCase))
|
|
|
|
{
|
2013-07-17 10:33:54 +03:00
|
|
|
return ConvertToBytes(Convert.ToDouble(value), 3);
|
2013-07-17 09:58:50 +03:00
|
|
|
}
|
2013-04-08 01:40:13 +03:00
|
|
|
}
|
|
|
|
return 0;
|
2013-04-07 22:01:24 +03:00
|
|
|
}
|
2013-07-17 10:33:54 +03:00
|
|
|
|
|
|
|
private static long ConvertToBytes(double value, int power)
|
|
|
|
{
|
|
|
|
var multiplier = Math.Pow(1024, power);
|
|
|
|
var result = value*multiplier;
|
|
|
|
|
|
|
|
return Convert.ToInt64(result);
|
|
|
|
}
|
2013-04-07 10:30:37 +03:00
|
|
|
}
|
|
|
|
}
|