|
|
@ -0,0 +1,232 @@
|
|
|
|
|
|
|
|
using System;
|
|
|
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
|
|
using System.Linq;
|
|
|
|
|
|
|
|
using System.Net;
|
|
|
|
|
|
|
|
using System.ServiceModel.Syndication;
|
|
|
|
|
|
|
|
using System.Text;
|
|
|
|
|
|
|
|
using System.Text.RegularExpressions;
|
|
|
|
|
|
|
|
using Newtonsoft.Json;
|
|
|
|
|
|
|
|
using Ninject;
|
|
|
|
|
|
|
|
using NzbDrone.Common;
|
|
|
|
|
|
|
|
using NzbDrone.Core.Model;
|
|
|
|
|
|
|
|
using NzbDrone.Core.Model.Nzbx;
|
|
|
|
|
|
|
|
using NzbDrone.Core.Providers.Core;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace NzbDrone.Core.Providers.Indexer
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
class Nzbx : IndexerBase
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
[Inject]
|
|
|
|
|
|
|
|
public Nzbx(HttpProvider httpProvider, ConfigProvider configProvider)
|
|
|
|
|
|
|
|
: base(httpProvider, configProvider)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public override string Name
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
get { return "nzbx"; }
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
protected override string[] Urls
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
get
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
return new string[]
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
String.Format("https://nzbx.co/api/recent?category=tv")
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public override bool IsConfigured
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
get
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
//return !string.IsNullOrWhiteSpace(_configProvider.OmgwtfnzbsUsername) &&
|
|
|
|
|
|
|
|
// !string.IsNullOrWhiteSpace(_configProvider.OmgwtfnzbsApiKey);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
protected override IList<string> GetEpisodeSearchUrls(string seriesTitle, int seasonNumber, int episodeNumber)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
var searchUrls = new List<String>();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
searchUrls.Add(String.Format("https://nzbx.co/api/search?q={0}+S{1:00}E{2:00}", seriesTitle, seasonNumber, episodeNumber));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return searchUrls;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
protected override IList<string> GetDailyEpisodeSearchUrls(string seriesTitle, DateTime date)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
var searchUrls = new List<String>();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
searchUrls.Add(String.Format("https://nzbx.co/api/search?q={0}+{1:yyyy MM dd}", seriesTitle, date));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return searchUrls;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
protected override IList<string> GetSeasonSearchUrls(string seriesTitle, int seasonNumber)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
var searchUrls = new List<String>();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
searchUrls.Add(String.Format("https://nzbx.co/api/search?q={0}+S{1:00}", seriesTitle, seasonNumber));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return searchUrls;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
protected override IList<string> GetPartialSeasonSearchUrls(string seriesTitle, int seasonNumber, int episodeWildcard)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
var searchUrls = new List<String>();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
searchUrls.Add(String.Format("https://nzbx.co/api/search?q={0}+S{1:00}E{2}", seriesTitle, seasonNumber, episodeWildcard));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return searchUrls;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
protected override string NzbDownloadUrl(SyndicationItem item)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
throw new NotImplementedException();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
protected override string NzbInfoUrl(SyndicationItem item)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
throw new NotImplementedException();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
protected override EpisodeParseResult CustomParser(SyndicationItem item, EpisodeParseResult currentResult)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
throw new NotImplementedException();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public override IList<EpisodeParseResult> FetchRss()
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
_logger.Debug("Fetching feeds from " + Name);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var result = new List<EpisodeParseResult>();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!IsConfigured)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
_logger.Warn("Indexer '{0}' isn't configured correctly. please reconfigure the indexer in settings page.", Name);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
foreach (var url in Urls)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
var response = Download(url);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (response != null)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
var feed = JsonConvert.DeserializeObject<List<NzbxRecentItem>>(response);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
foreach (var item in feed)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
try
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
var episodeParseResult = Parser.ParseTitle(item.Name);
|
|
|
|
|
|
|
|
if (episodeParseResult != null)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
episodeParseResult.Age = DateTime.Now.Date.Subtract(item.PostDate).Days;
|
|
|
|
|
|
|
|
episodeParseResult.OriginalString = item.Name;
|
|
|
|
|
|
|
|
episodeParseResult.SceneSource = true;
|
|
|
|
|
|
|
|
episodeParseResult.NzbUrl = String.Format("http://nzbx.co/nzb?{0}", item.Guid);
|
|
|
|
|
|
|
|
episodeParseResult.Indexer = Name;
|
|
|
|
|
|
|
|
episodeParseResult.Size = item.Size;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
result.Add(episodeParseResult);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
catch (Exception itemEx)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
itemEx.Data.Add("FeedUrl", url);
|
|
|
|
|
|
|
|
itemEx.Data.Add("Item", item.Name);
|
|
|
|
|
|
|
|
_logger.ErrorException("An error occurred while processing feed item", itemEx);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
_logger.Debug("Finished processing feeds from " + Name);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
protected override List<EpisodeParseResult> Fetch(IEnumerable<string> urls)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
var result = new List<EpisodeParseResult>();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!IsConfigured)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
_logger.Warn("Indexer '{0}' isn't configured correctly. please reconfigure the indexer in settings page.", Name);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
foreach (var url in urls)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
var response = Download(url);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(response != null)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
var feed = JsonConvert.DeserializeObject<List<NzbxSearchItem>>(response);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
foreach (var item in feed)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
try
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
var episodeParseResult = Parser.ParseTitle(item.Name);
|
|
|
|
|
|
|
|
if (episodeParseResult != null)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
episodeParseResult.Age = DateTime.Now.Date.Subtract(item.PostDate).Days;
|
|
|
|
|
|
|
|
episodeParseResult.OriginalString = item.Name;
|
|
|
|
|
|
|
|
episodeParseResult.SceneSource = true;
|
|
|
|
|
|
|
|
episodeParseResult.NzbUrl = item.Nzb;
|
|
|
|
|
|
|
|
episodeParseResult.Indexer = Name;
|
|
|
|
|
|
|
|
episodeParseResult.Size = item.Size;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
result.Add(episodeParseResult);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
catch (Exception itemEx)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
itemEx.Data.Add("FeedUrl", url);
|
|
|
|
|
|
|
|
itemEx.Data.Add("Item", item.Name);
|
|
|
|
|
|
|
|
_logger.ErrorException("An error occurred while processing feed item", itemEx);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private string Download(string url)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
try
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
_logger.Trace("Downloading RSS " + url);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return _httpProvider.DownloadString(url, Credentials);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
catch (WebException webException)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (webException.Message.Contains("503"))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
_logger.Warn("{0} server is currently unavailable.{1} {2}", Name, url, webException.Message);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
webException.Data.Add("FeedUrl", url);
|
|
|
|
|
|
|
|
_logger.ErrorException("An error occurred while processing feed. " + url, webException);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
catch (Exception feedEx)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
feedEx.Data.Add("FeedUrl", url);
|
|
|
|
|
|
|
|
_logger.ErrorException("An error occurred while processing feed. " + url, feedEx);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|