Indexer Cleanup

pull/993/head
Qstick 2 years ago
parent f87aa820c7
commit 1a71375c3f

@ -0,0 +1,56 @@
using FluentMigrator;
using NzbDrone.Core.Datastore.Migration.Framework;
namespace NzbDrone.Core.Datastore.Migration
{
[Migration(017)]
public class indexer_cleanup : NzbDroneMigrationBase
{
protected override void MainDbUpgrade()
{
//Remove v3 yml transfers
Delete.FromTable("Indexers").Row(new { Implementation = "Aither" });
Delete.FromTable("Indexers").Row(new { Implementation = "Anilibria" });
Delete.FromTable("Indexers").Row(new { Implementation = "AnimeWorld" });
Delete.FromTable("Indexers").Row(new { Implementation = "LatTeam" });
Delete.FromTable("Indexers").Row(new { Implementation = "Blutopia" });
Delete.FromTable("Indexers").Row(new { Implementation = "DanishBytes" });
Delete.FromTable("Indexers").Row(new { Implementation = "DesiTorrents" });
Delete.FromTable("Indexers").Row(new { Implementation = "DigitalCore" });
Delete.FromTable("Indexers").Row(new { Implementation = "InternetArchive" });
Delete.FromTable("Indexers").Row(new { Implementation = "Milkie" });
Delete.FromTable("Indexers").Row(new { Implementation = "ShareIsland" });
Delete.FromTable("Indexers").Row(new { Implementation = "SuperBits" });
Delete.FromTable("Indexers").Row(new { Implementation = "ThePirateBay" });
Delete.FromTable("Indexers").Row(new { Implementation = "TorrentLeech" });
Delete.FromTable("Indexers").Row(new { Implementation = "TorrentSeeds" });
Delete.FromTable("Indexers").Row(new { Implementation = "TorrentParadiseMI" });
Delete.FromTable("Indexers").Row(new { Implementation = "YTS" });
//Change settings to shared classes
Update.Table("Indexers").Set(new { ConfigContract = "NoAuthTorrentBaseSettings" }).Where(new { Implementation = "Animedia" });
Update.Table("Indexers").Set(new { ConfigContract = "NoAuthTorrentBaseSettings" }).Where(new { Implementation = "Shizaproject" });
Update.Table("Indexers").Set(new { ConfigContract = "NoAuthTorrentBaseSettings" }).Where(new { Implementation = "ShowRSS" });
Update.Table("Indexers").Set(new { ConfigContract = "NoAuthTorrentBaseSettings" }).Where(new { Implementation = "SubsPlease" });
Update.Table("Indexers").Set(new { ConfigContract = "NoAuthTorrentBaseSettings" }).Where(new { Implementation = "TorrentsCSV" });
//Change settings to shared classes
Update.Table("Indexers").Set(new { ConfigContract = "UserPassTorrentBaseSettings" }).Where(new { Implementation = "Anidub" });
Update.Table("Indexers").Set(new { ConfigContract = "UserPassTorrentBaseSettings" }).Where(new { Implementation = "AnimeTorrents" });
Update.Table("Indexers").Set(new { ConfigContract = "UserPassTorrentBaseSettings" }).Where(new { Implementation = "Anthelion" });
Update.Table("Indexers").Set(new { ConfigContract = "UserPassTorrentBaseSettings" }).Where(new { Implementation = "BB" });
Update.Table("Indexers").Set(new { ConfigContract = "UserPassTorrentBaseSettings" }).Where(new { Implementation = "HDSpace" });
Update.Table("Indexers").Set(new { ConfigContract = "UserPassTorrentBaseSettings" }).Where(new { Implementation = "HDTorrents" });
Update.Table("Indexers").Set(new { ConfigContract = "UserPassTorrentBaseSettings" }).Where(new { Implementation = "ImmortalSeed" });
Update.Table("Indexers").Set(new { ConfigContract = "UserPassTorrentBaseSettings" }).Where(new { Implementation = "RevolutionTT" });
Update.Table("Indexers").Set(new { ConfigContract = "UserPassTorrentBaseSettings" }).Where(new { Implementation = "SpeedCD" });
Update.Table("Indexers").Set(new { ConfigContract = "UserPassTorrentBaseSettings" }).Where(new { Implementation = "TVVault" });
Update.Table("Indexers").Set(new { ConfigContract = "UserPassTorrentBaseSettings" }).Where(new { Implementation = "ZonaQ" });
//Change settings to shared classes
Update.Table("Indexers").Set(new { ConfigContract = "CookieTorrentBaseSettings" }).Where(new { Implementation = "TorrentDay" });
Update.Table("Indexers").Set(new { ConfigContract = "CookieTorrentBaseSettings" }).Where(new { Implementation = "MoreThanTV" });
Update.Table("Indexers").Set(new { ConfigContract = "CookieTorrentBaseSettings" }).Where(new { Implementation = "BitHDTV" });
}
}
}

@ -1,61 +0,0 @@
using System;
using System.Collections.Generic;
using NLog;
using NzbDrone.Common.Http;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.Indexers.Definitions.UNIT3D;
using NzbDrone.Core.Messaging.Events;
namespace NzbDrone.Core.Indexers.Definitions
{
[Obsolete("Moved to YML for Cardigann v3")]
public class Aither : Unit3dBase
{
public override string Name => "Aither";
public override string[] IndexerUrls => new string[] { "https://aither.cc/" };
public override string Description => "Aither is a Private Torrent Tracker for HD MOVIES / TV";
public override string Language => "en-US";
public override IndexerPrivacy Privacy => IndexerPrivacy.Private;
public Aither(IIndexerHttpClient httpClient, IEventAggregator eventAggregator, IIndexerStatusService indexerStatusService, IConfigService configService, Logger logger)
: base(httpClient, eventAggregator, indexerStatusService, configService, logger)
{
}
protected override IndexerCapabilities SetCapabilities()
{
var caps = new IndexerCapabilities
{
TvSearchParams = new List<TvSearchParam>
{
TvSearchParam.Q, TvSearchParam.Season, TvSearchParam.Ep, TvSearchParam.ImdbId, TvSearchParam.TvdbId
},
MovieSearchParams = new List<MovieSearchParam>
{
MovieSearchParam.Q, MovieSearchParam.ImdbId, MovieSearchParam.TmdbId
},
MusicSearchParams = new List<MusicSearchParam>
{
MusicSearchParam.Q
},
BookSearchParams = new List<BookSearchParam>
{
BookSearchParam.Q
}
};
caps.Categories.AddCategoryMapping(1, NewznabStandardCategory.Movies, "Movie");
caps.Categories.AddCategoryMapping(2, NewznabStandardCategory.TV, "TV");
caps.Categories.AddCategoryMapping(3, NewznabStandardCategory.Audio, "Music");
caps.Categories.AddCategoryMapping(4, NewznabStandardCategory.PCGames, "Games");
caps.Categories.AddCategoryMapping(6, NewznabStandardCategory.XXX, "XXX");
caps.Categories.AddCategoryMapping(9, NewznabStandardCategory.TVSport, "Sport");
caps.Categories.AddCategoryMapping(10, NewznabStandardCategory.PC, "Software/Apps");
caps.Categories.AddCategoryMapping(11, NewznabStandardCategory.BooksEBook, "Ebooks/Magazines");
caps.Categories.AddCategoryMapping(14, NewznabStandardCategory.AudioAudiobook, "AudioBooks");
caps.Categories.AddCategoryMapping(15, NewznabStandardCategory.Other, "Education");
return caps;
}
}
}

@ -14,6 +14,7 @@ using NzbDrone.Common.Http;
using NzbDrone.Core.Annotations; using NzbDrone.Core.Annotations;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.Indexers.Exceptions; using NzbDrone.Core.Indexers.Exceptions;
using NzbDrone.Core.Indexers.Settings;
using NzbDrone.Core.IndexerSearch.Definitions; using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
@ -22,7 +23,7 @@ using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.Definitions namespace NzbDrone.Core.Indexers.Definitions
{ {
public class Anidub : TorrentIndexerBase<AnidubSettings> public class Anidub : TorrentIndexerBase<UserPassTorrentBaseSettings>
{ {
public override string Name => "Anidub"; public override string Name => "Anidub";
public override string[] IndexerUrls => new string[] { "https://tr.anidub.com/" }; public override string[] IndexerUrls => new string[] { "https://tr.anidub.com/" };
@ -142,7 +143,7 @@ namespace NzbDrone.Core.Indexers.Definitions
public class AnidubRequestGenerator : IIndexerRequestGenerator public class AnidubRequestGenerator : IIndexerRequestGenerator
{ {
public AnidubSettings Settings { get; set; } public UserPassTorrentBaseSettings Settings { get; set; }
public IndexerCapabilities Capabilities { get; set; } public IndexerCapabilities Capabilities { get; set; }
public AnidubRequestGenerator() public AnidubRequestGenerator()
@ -252,7 +253,7 @@ namespace NzbDrone.Core.Indexers.Definitions
public class AnidubParser : IParseIndexerResponse public class AnidubParser : IParseIndexerResponse
{ {
private readonly AnidubSettings _settings; private readonly UserPassTorrentBaseSettings _settings;
private readonly IndexerCapabilitiesCategories _categories; private readonly IndexerCapabilitiesCategories _categories;
public IIndexerHttpClient HttpClient { get; set; } public IIndexerHttpClient HttpClient { get; set; }
public Logger Logger { get; set; } public Logger Logger { get; set; }
@ -277,7 +278,7 @@ namespace NzbDrone.Core.Indexers.Definitions
{ "/anons_ongoing", "12" } { "/anons_ongoing", "12" }
}; };
public AnidubParser(AnidubSettings settings, IndexerCapabilitiesCategories categories) public AnidubParser(UserPassTorrentBaseSettings settings, IndexerCapabilitiesCategories categories)
{ {
_settings = settings; _settings = settings;
_categories = categories; _categories = categories;
@ -510,41 +511,4 @@ namespace NzbDrone.Core.Indexers.Definitions
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; } public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
} }
public class AnidubSettingsValidator : AbstractValidator<AnidubSettings>
{
public AnidubSettingsValidator()
{
RuleFor(c => c.Username).NotEmpty();
RuleFor(c => c.Password).NotEmpty();
}
}
public class AnidubSettings : IIndexerSettings
{
private static readonly AnidubSettingsValidator Validator = new AnidubSettingsValidator();
public AnidubSettings()
{
Username = "";
Password = "";
}
[FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2, Label = "Username", HelpText = "Site Username", Privacy = PrivacyLevel.UserName)]
public string Username { get; set; }
[FieldDefinition(3, Label = "Password", HelpText = "Site Password", Privacy = PrivacyLevel.Password, Type = FieldType.Password)]
public string Password { get; set; }
[FieldDefinition(4)]
public IndexerBaseSettings BaseSettings { get; set; } = new IndexerBaseSettings();
public NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));
}
}
} }

@ -1,296 +0,0 @@
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Text;
using System.Text.RegularExpressions;
using FluentValidation;
using Newtonsoft.Json;
using NLog;
using NzbDrone.Common.Http;
using NzbDrone.Core.Annotations;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Parser;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.Definitions
{
[Obsolete("Moved to YML for Cardigann v3")]
public class Anilibria : TorrentIndexerBase<AnilibriaSettings>
{
public override string Name => "Anilibria";
public override string[] IndexerUrls => new string[] { "https://anilibria.tv/" };
public override string Description => "Anilibria is russian anime voiceover group and eponymous anime tracker.";
public override string Language => "ru-RU";
public override Encoding Encoding => Encoding.UTF8;
public override DownloadProtocol Protocol => DownloadProtocol.Torrent;
public override IndexerPrivacy Privacy => IndexerPrivacy.Public;
public override IndexerCapabilities Capabilities => SetCapabilities();
public Anilibria(IIndexerHttpClient httpClient, IEventAggregator eventAggregator, IIndexerStatusService indexerStatusService, IConfigService configService, Logger logger)
: base(httpClient, eventAggregator, indexerStatusService, configService, logger)
{
}
public override IIndexerRequestGenerator GetRequestGenerator()
{
return new AnilibriaRequestGenerator() { Settings = Settings, Capabilities = Capabilities };
}
public override IParseIndexerResponse GetParser()
{
return new AnilibriaParser(Settings, Capabilities.Categories);
}
private IndexerCapabilities SetCapabilities()
{
var caps = new IndexerCapabilities
{
TvSearchParams = new List<TvSearchParam>
{
TvSearchParam.Q, TvSearchParam.Season, TvSearchParam.Ep
},
MovieSearchParams = new List<MovieSearchParam>
{
MovieSearchParam.Q
}
};
caps.Categories.AddCategoryMapping(1, NewznabStandardCategory.TVAnime, "ТВ");
caps.Categories.AddCategoryMapping(3, NewznabStandardCategory.TVAnime, "ONA");
caps.Categories.AddCategoryMapping(4, NewznabStandardCategory.TVAnime, "OVA");
caps.Categories.AddCategoryMapping(5, NewznabStandardCategory.Movies, "Фильм");
return caps;
}
}
public class AnilibriaRequestGenerator : IIndexerRequestGenerator
{
public AnilibriaSettings Settings { get; set; }
public IndexerCapabilities Capabilities { get; set; }
public AnilibriaRequestGenerator()
{
}
private IEnumerable<IndexerRequest> GetPagedRequests(string term, int[] categories)
{
var apiUrl = Regex.Replace(Settings.BaseUrl, @"(https?:\/\/)(.*)", "$1api.$2v2");
var queryCollection = new NameValueCollection
{
{ "limit", "100" },
{ "filter", "names,code,torrents.list,season.year,type.string" }
};
if (string.IsNullOrWhiteSpace(term))
{
apiUrl += "/getUpdates?" + queryCollection.GetQueryString();
}
else
{
apiUrl += "/searchTitles?" + queryCollection.GetQueryString() + "&search=" + Uri.EscapeDataString(term);
}
var request = new IndexerRequest(apiUrl, HttpAccept.Json);
yield return request;
}
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories));
return pageableRequests;
}
public IndexerPageableRequestChain GetSearchRequests(TvSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedTvSearchString), searchCriteria.Categories));
return pageableRequests;
}
public IndexerPageableRequestChain GetSearchRequests(BasicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories));
return pageableRequests;
}
// Anilibria doesn't support music, but this function required by interface
public IndexerPageableRequestChain GetSearchRequests(MusicSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
}
// Anilibria doesn't support books, but this function required by interface
public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
}
public Func<IDictionary<string, string>> GetCookies { get; set; }
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
}
public class AnilibriaParser : IParseIndexerResponse
{
private readonly AnilibriaSettings _settings;
private readonly IndexerCapabilitiesCategories _categories;
public AnilibriaParser(AnilibriaSettings settings, IndexerCapabilitiesCategories categories)
{
_settings = settings;
_categories = categories;
}
private string composeTitle(AnilibriaTitle tl, AnilibriaTorrent tr)
{
var title = tl.Names.Ru;
title += " / " + tl.Names.En;
if (tl.Names.Alternative is string)
{
title += " / " + tl.Names.Alternative;
}
title += " " + tl.Season.Year;
title += " [" + tr.Quality.String + "]";
if (!string.IsNullOrWhiteSpace(tr.Series.String))
{
title += " - E" + tr.Series.String;
}
return title;
}
public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse)
{
var torrentInfos = new List<ReleaseInfo>();
var queryResponseItems = JsonConvert.DeserializeObject<List<AnilibriaTitle>>(indexerResponse.Content);
var wwwUrl = Regex.Replace(_settings.BaseUrl, @"(https?:\/\/)(.*)", "$1www.$2/");
foreach (var tl in queryResponseItems)
{
foreach (var tr in tl.Torrents.List)
{
var torrentInfo = new TorrentInfo
{
Title = composeTitle(tl, tr),
InfoUrl = string.Format("{0}/release/{1}.html", _settings.BaseUrl.TrimEnd('/'), tl.Code),
DownloadVolumeFactor = 0,
UploadVolumeFactor = 1,
Seeders = tr.Seeders,
Peers = tr.Leechers + tr.Seeders,
Grabs = tr.Downloads,
Categories = _categories.MapTrackerCatDescToNewznab(tl.Type.String),
// API provides timestamp in UTC+3 timezone, so we need to substract 3 hours
PublishDate = DateTimeUtil.UnixTimestampToDateTime(tr.UploadedTimestamp).AddHours(-3),
Guid = wwwUrl + tr.Url,
DownloadUrl = wwwUrl + tr.Url,
Size = tr.TotalSize,
Resolution = tr.Quality.Resolution,
Codec = tr.Quality.Encoder
};
torrentInfos.Add(torrentInfo);
}
}
return torrentInfos.ToArray();
}
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
}
public class AnilibriaSettingsValidator : AbstractValidator<AnilibriaSettings>
{
public AnilibriaSettingsValidator()
{
}
}
public class AnilibriaSettings : IIndexerSettings
{
private static readonly AnilibriaSettingsValidator Validator = new AnilibriaSettingsValidator();
[FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2)]
public IndexerBaseSettings BaseSettings { get; set; } = new IndexerBaseSettings();
public NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));
}
}
public class AnilibriaTitle
{
public AnilibriaNames Names { get; set; }
public string Code { get; set; }
public AnilibriaTorrents Torrents { get; set; }
public AnilibriaSeason Season { get; set; }
public AnilibriaTitleType Type { get; set; }
}
public class AnilibriaTitleType
{
public string String { get; set; }
}
public class AnilibriaNames
{
public string Ru { get; set; }
public string En { get; set; }
public object Alternative { get; set; }
}
public class AnilibriaSeason
{
public long Year { get; set; }
}
public class AnilibriaTorrents
{
public AnilibriaTorrent[] List { get; set; }
}
public class AnilibriaTorrent
{
public AnilibriaSeries Series { get; set; }
public AnilibriaQuality Quality { get; set; }
public int Leechers { get; set; }
public int Seeders { get; set; }
public int Downloads { get; set; }
[JsonProperty("total_size")]
public long TotalSize { get; set; }
public string Url { get; set; }
[JsonProperty("uploaded_timestamp")]
public long UploadedTimestamp { get; set; }
}
public class AnilibriaQuality
{
public string String { get; set; }
public string Type { get; set; }
public string Resolution { get; set; }
public string Encoder { get; set; }
}
public class AnilibriaSeries
{
public long First { get; set; }
public long Last { get; set; }
public string String { get; set; }
}
}

@ -15,6 +15,7 @@ using NzbDrone.Common.Http;
using NzbDrone.Core.Annotations; using NzbDrone.Core.Annotations;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.Indexers.Exceptions; using NzbDrone.Core.Indexers.Exceptions;
using NzbDrone.Core.Indexers.Settings;
using NzbDrone.Core.IndexerSearch.Definitions; using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
@ -474,7 +475,7 @@ namespace NzbDrone.Core.Indexers.Definitions
} }
} }
public class AnimeBytesSettings : IIndexerSettings public class AnimeBytesSettings : NoAuthTorrentBaseSettings
{ {
private static readonly AnimeBytesSettingsValidator Validator = new AnimeBytesSettingsValidator(); private static readonly AnimeBytesSettingsValidator Validator = new AnimeBytesSettingsValidator();
@ -485,9 +486,6 @@ namespace NzbDrone.Core.Indexers.Definitions
EnableSonarrCompatibility = true; EnableSonarrCompatibility = true;
} }
[FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2, Label = "Passkey", HelpText = "Site Passkey", Privacy = PrivacyLevel.Password, Type = FieldType.Password)] [FieldDefinition(2, Label = "Passkey", HelpText = "Site Passkey", Privacy = PrivacyLevel.Password, Type = FieldType.Password)]
public string Passkey { get; set; } public string Passkey { get; set; }
@ -497,10 +495,7 @@ namespace NzbDrone.Core.Indexers.Definitions
[FieldDefinition(4, Label = "Enable Sonarr Compatibility", Type = FieldType.Checkbox, HelpText = "Makes Prowlarr try to add Season information into Release names, without this Sonarr can't match any Seasons, but it has a lot of false positives as well")] [FieldDefinition(4, Label = "Enable Sonarr Compatibility", Type = FieldType.Checkbox, HelpText = "Makes Prowlarr try to add Season information into Release names, without this Sonarr can't match any Seasons, but it has a lot of false positives as well")]
public bool EnableSonarrCompatibility { get; set; } public bool EnableSonarrCompatibility { get; set; }
[FieldDefinition(5)] public override NzbDroneValidationResult Validate()
public IndexerBaseSettings BaseSettings { get; set; } = new IndexerBaseSettings();
public NzbDroneValidationResult Validate()
{ {
return new NzbDroneValidationResult(Validator.Validate(this)); return new NzbDroneValidationResult(Validator.Validate(this));
} }

@ -13,6 +13,7 @@ using NzbDrone.Common.Http;
using NzbDrone.Core.Annotations; using NzbDrone.Core.Annotations;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.Indexers.Exceptions; using NzbDrone.Core.Indexers.Exceptions;
using NzbDrone.Core.Indexers.Settings;
using NzbDrone.Core.IndexerSearch.Definitions; using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
@ -21,7 +22,7 @@ using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.Definitions namespace NzbDrone.Core.Indexers.Definitions
{ {
public class AnimeTorrents : TorrentIndexerBase<AnimeTorrentsSettings> public class AnimeTorrents : TorrentIndexerBase<UserPassTorrentBaseSettings>
{ {
public override string Name => "AnimeTorrents"; public override string Name => "AnimeTorrents";
@ -134,7 +135,7 @@ namespace NzbDrone.Core.Indexers.Definitions
public class AnimeTorrentsRequestGenerator : IIndexerRequestGenerator public class AnimeTorrentsRequestGenerator : IIndexerRequestGenerator
{ {
public AnimeTorrentsSettings Settings { get; set; } public UserPassTorrentBaseSettings Settings { get; set; }
public IndexerCapabilities Capabilities { get; set; } public IndexerCapabilities Capabilities { get; set; }
public AnimeTorrentsRequestGenerator() public AnimeTorrentsRequestGenerator()
@ -227,10 +228,10 @@ namespace NzbDrone.Core.Indexers.Definitions
public class AnimeTorrentsParser : IParseIndexerResponse public class AnimeTorrentsParser : IParseIndexerResponse
{ {
private readonly AnimeTorrentsSettings _settings; private readonly UserPassTorrentBaseSettings _settings;
private readonly IndexerCapabilitiesCategories _categories; private readonly IndexerCapabilitiesCategories _categories;
public AnimeTorrentsParser(AnimeTorrentsSettings settings, IndexerCapabilitiesCategories categories) public AnimeTorrentsParser(UserPassTorrentBaseSettings settings, IndexerCapabilitiesCategories categories)
{ {
_settings = settings; _settings = settings;
_categories = categories; _categories = categories;
@ -328,41 +329,4 @@ namespace NzbDrone.Core.Indexers.Definitions
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; } public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
} }
public class AnimeTorrentsSettingsValidator : AbstractValidator<AnimeTorrentsSettings>
{
public AnimeTorrentsSettingsValidator()
{
RuleFor(c => c.Username).NotEmpty();
RuleFor(c => c.Password).NotEmpty();
}
}
public class AnimeTorrentsSettings : IIndexerSettings
{
private static readonly AnimeTorrentsSettingsValidator Validator = new AnimeTorrentsSettingsValidator();
public AnimeTorrentsSettings()
{
Username = "";
Password = "";
}
[FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2, Label = "Username", HelpText = "Site Username", Privacy = PrivacyLevel.UserName)]
public string Username { get; set; }
[FieldDefinition(3, Label = "Password", HelpText = "Site Password", Privacy = PrivacyLevel.Password, Type = FieldType.Password)]
public string Password { get; set; }
[FieldDefinition(4)]
public IndexerBaseSettings BaseSettings { get; set; } = new IndexerBaseSettings();
public NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));
}
}
} }

@ -1,66 +0,0 @@
using System;
using System.Collections.Generic;
using NLog;
using NzbDrone.Common.Http;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.Indexers.Definitions.UNIT3D;
using NzbDrone.Core.Messaging.Events;
namespace NzbDrone.Core.Indexers.Definitions
{
[Obsolete("Moved to YML for Cardigann v3")]
public class AnimeWorld : Unit3dBase
{
public override string Name => "AnimeWorld";
public override string[] IndexerUrls => new string[] { "https://animeworld.cx/" };
public override string Description => "AnimeWorld (AW) is a GERMAN Private site for ANIME / MANGA / HENTAI";
public override string Language => "de-DE";
public override IndexerPrivacy Privacy => IndexerPrivacy.Private;
public AnimeWorld(IIndexerHttpClient httpClient, IEventAggregator eventAggregator, IIndexerStatusService indexerStatusService, IConfigService configService, Logger logger)
: base(httpClient, eventAggregator, indexerStatusService, configService, logger)
{
}
protected override IndexerCapabilities SetCapabilities()
{
var caps = new IndexerCapabilities
{
TvSearchParams = new List<TvSearchParam>
{
TvSearchParam.Q, TvSearchParam.Season, TvSearchParam.Ep, TvSearchParam.ImdbId, TvSearchParam.TvdbId
},
MovieSearchParams = new List<MovieSearchParam>
{
MovieSearchParam.Q, MovieSearchParam.ImdbId, MovieSearchParam.TmdbId
},
MusicSearchParams = new List<MusicSearchParam>
{
MusicSearchParam.Q
},
BookSearchParams = new List<BookSearchParam>
{
BookSearchParam.Q
}
};
caps.Categories.AddCategoryMapping(1, NewznabStandardCategory.Movies, "Anime Movie");
caps.Categories.AddCategoryMapping(2, NewznabStandardCategory.TVAnime, "Anime Series");
caps.Categories.AddCategoryMapping(3, NewznabStandardCategory.Audio, "Anime Musik/OST");
caps.Categories.AddCategoryMapping(4, NewznabStandardCategory.PCGames, "Anime Spiele");
caps.Categories.AddCategoryMapping(5, NewznabStandardCategory.XXX, "Anime Hentai");
caps.Categories.AddCategoryMapping(6, NewznabStandardCategory.PCGames, "Software");
caps.Categories.AddCategoryMapping(7, NewznabStandardCategory.Other, "Sonstiges");
caps.Categories.AddCategoryMapping(8, NewznabStandardCategory.Movies, "Filme");
caps.Categories.AddCategoryMapping(9, NewznabStandardCategory.TV, "Serien");
caps.Categories.AddCategoryMapping(10, NewznabStandardCategory.PCGames, "Spiele");
caps.Categories.AddCategoryMapping(11, NewznabStandardCategory.Audio, "Musik");
caps.Categories.AddCategoryMapping(12, NewznabStandardCategory.BooksComics, "Mangas");
caps.Categories.AddCategoryMapping(13, NewznabStandardCategory.Movies, "Cartoon Filme");
caps.Categories.AddCategoryMapping(14, NewznabStandardCategory.TV, "Cartoon Serie");
caps.Categories.AddCategoryMapping(15, NewznabStandardCategory.XXX, "H-Manga / Doujinshi");
return caps;
}
}
}

@ -10,6 +10,7 @@ using NzbDrone.Common.Http;
using NzbDrone.Core.Annotations; using NzbDrone.Core.Annotations;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.Indexers.Exceptions; using NzbDrone.Core.Indexers.Exceptions;
using NzbDrone.Core.Indexers.Settings;
using NzbDrone.Core.IndexerSearch.Definitions; using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
@ -18,7 +19,7 @@ using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.Definitions namespace NzbDrone.Core.Indexers.Definitions
{ {
public class Animedia : TorrentIndexerBase<AnimediaSettings> public class Animedia : TorrentIndexerBase<NoAuthTorrentBaseSettings>
{ {
public override string Name => "Animedia"; public override string Name => "Animedia";
public override string[] IndexerUrls => new string[] { "https://tt.animedia.tv/" }; public override string[] IndexerUrls => new string[] { "https://tt.animedia.tv/" };
@ -67,7 +68,7 @@ namespace NzbDrone.Core.Indexers.Definitions
public class AnimediaRequestGenerator : IIndexerRequestGenerator public class AnimediaRequestGenerator : IIndexerRequestGenerator
{ {
public AnimediaSettings Settings { get; set; } public NoAuthTorrentBaseSettings Settings { get; set; }
public IndexerCapabilities Capabilities { get; set; } public IndexerCapabilities Capabilities { get; set; }
public AnimediaRequestGenerator() public AnimediaRequestGenerator()
@ -144,7 +145,7 @@ namespace NzbDrone.Core.Indexers.Definitions
public class AnimediaParser : IParseIndexerResponse public class AnimediaParser : IParseIndexerResponse
{ {
private readonly AnimediaSettings _settings; private readonly NoAuthTorrentBaseSettings _settings;
private readonly IndexerCapabilitiesCategories _categories; private readonly IndexerCapabilitiesCategories _categories;
private static readonly Regex EpisodesInfoQueryRegex = new Regex(@"сери[ия] (\d+)(?:-(\d+))? из.*", RegexOptions.Compiled | RegexOptions.IgnoreCase); private static readonly Regex EpisodesInfoQueryRegex = new Regex(@"сери[ия] (\d+)(?:-(\d+))? из.*", RegexOptions.Compiled | RegexOptions.IgnoreCase);
private static readonly Regex ResolutionInfoQueryRegex = new Regex(@"качество (\d+)", RegexOptions.Compiled | RegexOptions.IgnoreCase); private static readonly Regex ResolutionInfoQueryRegex = new Regex(@"качество (\d+)", RegexOptions.Compiled | RegexOptions.IgnoreCase);
@ -156,7 +157,7 @@ namespace NzbDrone.Core.Indexers.Definitions
public IIndexerHttpClient HttpClient { get; set; } public IIndexerHttpClient HttpClient { get; set; }
public Logger Logger { get; set; } public Logger Logger { get; set; }
public AnimediaParser(AnimediaSettings settings, IndexerCapabilitiesCategories categories) public AnimediaParser(NoAuthTorrentBaseSettings settings, IndexerCapabilitiesCategories categories)
{ {
_settings = settings; _settings = settings;
_categories = categories; _categories = categories;
@ -324,27 +325,4 @@ namespace NzbDrone.Core.Indexers.Definitions
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; } public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
} }
public class AnimediaSettingsValidator : AbstractValidator<AnimediaSettings>
{
public AnimediaSettingsValidator()
{
}
}
public class AnimediaSettings : IIndexerSettings
{
private static readonly AnimediaSettingsValidator Validator = new AnimediaSettingsValidator();
[FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2)]
public IndexerBaseSettings BaseSettings { get; set; } = new IndexerBaseSettings();
public NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));
}
}
} }

@ -13,6 +13,7 @@ using NzbDrone.Common.Http;
using NzbDrone.Core.Annotations; using NzbDrone.Core.Annotations;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.Indexers.Exceptions; using NzbDrone.Core.Indexers.Exceptions;
using NzbDrone.Core.Indexers.Settings;
using NzbDrone.Core.IndexerSearch.Definitions; using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
@ -22,7 +23,7 @@ using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.Definitions namespace NzbDrone.Core.Indexers.Definitions
{ {
public class Anthelion : TorrentIndexerBase<AnthelionSettings> public class Anthelion : TorrentIndexerBase<UserPassTorrentBaseSettings>
{ {
public override string Name => "Anthelion"; public override string Name => "Anthelion";
public override string[] IndexerUrls => new string[] { "https://anthelion.me/" }; public override string[] IndexerUrls => new string[] { "https://anthelion.me/" };
@ -130,7 +131,7 @@ namespace NzbDrone.Core.Indexers.Definitions
public class AnthelionRequestGenerator : IIndexerRequestGenerator public class AnthelionRequestGenerator : IIndexerRequestGenerator
{ {
public AnthelionSettings Settings { get; set; } public UserPassTorrentBaseSettings Settings { get; set; }
public IndexerCapabilities Capabilities { get; set; } public IndexerCapabilities Capabilities { get; set; }
public AnthelionRequestGenerator() public AnthelionRequestGenerator()
@ -212,10 +213,10 @@ namespace NzbDrone.Core.Indexers.Definitions
public class AnthelionParser : IParseIndexerResponse public class AnthelionParser : IParseIndexerResponse
{ {
private readonly AnthelionSettings _settings; private readonly UserPassTorrentBaseSettings _settings;
private readonly IndexerCapabilitiesCategories _categories; private readonly IndexerCapabilitiesCategories _categories;
public AnthelionParser(AnthelionSettings settings, IndexerCapabilitiesCategories categories) public AnthelionParser(UserPassTorrentBaseSettings settings, IndexerCapabilitiesCategories categories)
{ {
_settings = settings; _settings = settings;
_categories = categories; _categories = categories;
@ -297,41 +298,4 @@ namespace NzbDrone.Core.Indexers.Definitions
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; } public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
} }
public class AnthelionSettingsValidator : AbstractValidator<AnthelionSettings>
{
public AnthelionSettingsValidator()
{
RuleFor(c => c.Username).NotEmpty();
RuleFor(c => c.Password).NotEmpty();
}
}
public class AnthelionSettings : IIndexerSettings
{
private static readonly AnthelionSettingsValidator Validator = new AnthelionSettingsValidator();
public AnthelionSettings()
{
Username = "";
Password = "";
}
[FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2, Label = "Username", HelpText = "Site Username", Privacy = PrivacyLevel.UserName)]
public string Username { get; set; }
[FieldDefinition(3, Label = "Password", HelpText = "Site Password", Privacy = PrivacyLevel.Password, Type = FieldType.Password)]
public string Password { get; set; }
[FieldDefinition(4)]
public IndexerBaseSettings BaseSettings { get; set; } = new IndexerBaseSettings();
public NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));
}
}
} }

@ -1,5 +1,6 @@
using FluentValidation; using FluentValidation;
using NzbDrone.Core.Annotations; using NzbDrone.Core.Annotations;
using NzbDrone.Core.Indexers.Settings;
using NzbDrone.Core.Validation; using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.Definitions.Avistaz namespace NzbDrone.Core.Indexers.Definitions.Avistaz
@ -14,7 +15,7 @@ namespace NzbDrone.Core.Indexers.Definitions.Avistaz
} }
} }
public class AvistazSettings : IIndexerSettings public class AvistazSettings : NoAuthTorrentBaseSettings
{ {
private static readonly AvistazSettingsValidator Validator = new AvistazSettingsValidator(); private static readonly AvistazSettingsValidator Validator = new AvistazSettingsValidator();
@ -25,9 +26,6 @@ namespace NzbDrone.Core.Indexers.Definitions.Avistaz
public string Token { get; set; } public string Token { get; set; }
[FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2, Label = "Username", HelpText = "Site Username", Privacy = PrivacyLevel.UserName)] [FieldDefinition(2, Label = "Username", HelpText = "Site Username", Privacy = PrivacyLevel.UserName)]
public string Username { get; set; } public string Username { get; set; }
@ -37,10 +35,7 @@ namespace NzbDrone.Core.Indexers.Definitions.Avistaz
[FieldDefinition(4, Label = "PID", HelpText = "PID from My Account or My Profile page")] [FieldDefinition(4, Label = "PID", HelpText = "PID from My Account or My Profile page")]
public string Pid { get; set; } public string Pid { get; set; }
[FieldDefinition(5)] public override NzbDroneValidationResult Validate()
public IndexerBaseSettings BaseSettings { get; set; } = new IndexerBaseSettings();
public NzbDroneValidationResult Validate()
{ {
return new NzbDroneValidationResult(Validator.Validate(this)); return new NzbDroneValidationResult(Validator.Validate(this));
} }

@ -13,6 +13,7 @@ using NzbDrone.Common.Http;
using NzbDrone.Core.Annotations; using NzbDrone.Core.Annotations;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.Indexers.Exceptions; using NzbDrone.Core.Indexers.Exceptions;
using NzbDrone.Core.Indexers.Settings;
using NzbDrone.Core.IndexerSearch.Definitions; using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
@ -21,7 +22,7 @@ using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.Definitions namespace NzbDrone.Core.Indexers.Definitions
{ {
public class BB : TorrentIndexerBase<BBSettings> public class BB : TorrentIndexerBase<UserPassTorrentBaseSettings>
{ {
public override string Name => "BB"; public override string Name => "BB";
public override string[] IndexerUrls => new string[] { StringUtil.FromBase64("aHR0cHM6Ly9iYWNvbmJpdHMub3JnLw==") }; public override string[] IndexerUrls => new string[] { StringUtil.FromBase64("aHR0cHM6Ly9iYWNvbmJpdHMub3JnLw==") };
@ -159,7 +160,7 @@ namespace NzbDrone.Core.Indexers.Definitions
public class BBRequestGenerator : IIndexerRequestGenerator public class BBRequestGenerator : IIndexerRequestGenerator
{ {
public BBSettings Settings { get; set; } public UserPassTorrentBaseSettings Settings { get; set; }
public IndexerCapabilities Capabilities { get; set; } public IndexerCapabilities Capabilities { get; set; }
public BBRequestGenerator() public BBRequestGenerator()
@ -247,10 +248,10 @@ namespace NzbDrone.Core.Indexers.Definitions
public class BBParser : IParseIndexerResponse public class BBParser : IParseIndexerResponse
{ {
private readonly BBSettings _settings; private readonly UserPassTorrentBaseSettings _settings;
private readonly IndexerCapabilitiesCategories _categories; private readonly IndexerCapabilitiesCategories _categories;
public BBParser(BBSettings settings, IndexerCapabilitiesCategories categories) public BBParser(UserPassTorrentBaseSettings settings, IndexerCapabilitiesCategories categories)
{ {
_settings = settings; _settings = settings;
_categories = categories; _categories = categories;
@ -330,41 +331,4 @@ namespace NzbDrone.Core.Indexers.Definitions
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; } public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
} }
public class BBSettingsValidator : AbstractValidator<BBSettings>
{
public BBSettingsValidator()
{
RuleFor(c => c.Username).NotEmpty();
RuleFor(c => c.Password).NotEmpty();
}
}
public class BBSettings : IIndexerSettings
{
private static readonly BBSettingsValidator Validator = new BBSettingsValidator();
public BBSettings()
{
Username = "";
Password = "";
}
[FieldDefinition(1, Label = "Base Url", HelpText = "Select which baseurl Prowlarr will use for requests to the site", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls")]
public string BaseUrl { get; set; }
[FieldDefinition(2, Label = "Username", HelpText = "Site Username", Privacy = PrivacyLevel.UserName)]
public string Username { get; set; }
[FieldDefinition(3, Label = "Password", HelpText = "Site Password", Privacy = PrivacyLevel.Password, Type = FieldType.Password)]
public string Password { get; set; }
[FieldDefinition(4)]
public IndexerBaseSettings BaseSettings { get; set; } = new IndexerBaseSettings();
public NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));
}
}
} }

@ -14,6 +14,7 @@ using NzbDrone.Common.Http;
using NzbDrone.Core.Annotations; using NzbDrone.Core.Annotations;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.Indexers.Exceptions; using NzbDrone.Core.Indexers.Exceptions;
using NzbDrone.Core.Indexers.Settings;
using NzbDrone.Core.IndexerSearch.Definitions; using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
@ -412,34 +413,12 @@ namespace NzbDrone.Core.Indexers.Definitions
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; } public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
} }
public class BakaBTSettingsValidator : AbstractValidator<BakaBTSettings> public class BakaBTSettings : UserPassTorrentBaseSettings
{ {
public BakaBTSettingsValidator()
{
RuleFor(c => c.Username).NotEmpty();
RuleFor(c => c.Password).NotEmpty();
}
}
public class BakaBTSettings : IIndexerSettings
{
private static readonly BakaBTSettingsValidator Validator = new BakaBTSettingsValidator();
public BakaBTSettings() public BakaBTSettings()
{ {
Username = "";
Password = "";
} }
[FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2, Label = "Username", HelpText = "Site Username", Privacy = PrivacyLevel.UserName)]
public string Username { get; set; }
[FieldDefinition(3, Label = "Password", HelpText = "Site Password", Privacy = PrivacyLevel.Password, Type = FieldType.Password)]
public string Password { get; set; }
[FieldDefinition(4, Label = "Add Romaji Title", Type = FieldType.Checkbox, HelpText = "Add releases for Romaji Title")] [FieldDefinition(4, Label = "Add Romaji Title", Type = FieldType.Checkbox, HelpText = "Add releases for Romaji Title")]
public bool AddRomajiTitle { get; set; } public bool AddRomajiTitle { get; set; }
@ -448,13 +427,5 @@ namespace NzbDrone.Core.Indexers.Definitions
[FieldDefinition(6, Label = "Adult Content", Type = FieldType.Checkbox, HelpText = "Allow Adult Content (Must be enabled in BakaBT settings)")] [FieldDefinition(6, Label = "Adult Content", Type = FieldType.Checkbox, HelpText = "Allow Adult Content (Must be enabled in BakaBT settings)")]
public bool AdultContent { get; set; } public bool AdultContent { get; set; }
[FieldDefinition(7)]
public IndexerBaseSettings BaseSettings { get; set; } = new IndexerBaseSettings();
public NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));
}
} }
} }

@ -13,6 +13,7 @@ using NzbDrone.Common.Serializer;
using NzbDrone.Core.Annotations; using NzbDrone.Core.Annotations;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.Indexers.Exceptions; using NzbDrone.Core.Indexers.Exceptions;
using NzbDrone.Core.Indexers.Settings;
using NzbDrone.Core.IndexerSearch.Definitions; using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
@ -249,7 +250,7 @@ namespace NzbDrone.Core.Indexers.Definitions
} }
} }
public class BeyondHDSettings : IIndexerSettings public class BeyondHDSettings : NoAuthTorrentBaseSettings
{ {
private static readonly BeyondHDSettingsValidator Validator = new BeyondHDSettingsValidator(); private static readonly BeyondHDSettingsValidator Validator = new BeyondHDSettingsValidator();
@ -257,19 +258,13 @@ namespace NzbDrone.Core.Indexers.Definitions
{ {
} }
[FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2, Label = "API Key", HelpText = "API Key from the Site (Found in My Security => API Key)", Privacy = PrivacyLevel.ApiKey)] [FieldDefinition(2, Label = "API Key", HelpText = "API Key from the Site (Found in My Security => API Key)", Privacy = PrivacyLevel.ApiKey)]
public string ApiKey { get; set; } public string ApiKey { get; set; }
[FieldDefinition(3, Label = "RSS Key", HelpText = "RSS Key from the Site (Found in My Security => RSS Key)", Privacy = PrivacyLevel.ApiKey)] [FieldDefinition(3, Label = "RSS Key", HelpText = "RSS Key from the Site (Found in My Security => RSS Key)", Privacy = PrivacyLevel.ApiKey)]
public string RssKey { get; set; } public string RssKey { get; set; }
[FieldDefinition(4)] public override NzbDroneValidationResult Validate()
public IndexerBaseSettings BaseSettings { get; set; } = new IndexerBaseSettings();
public NzbDroneValidationResult Validate()
{ {
return new NzbDroneValidationResult(Validator.Validate(this)); return new NzbDroneValidationResult(Validator.Validate(this));
} }

@ -12,6 +12,7 @@ using NzbDrone.Common.Extensions;
using NzbDrone.Common.Http; using NzbDrone.Common.Http;
using NzbDrone.Core.Annotations; using NzbDrone.Core.Annotations;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.Indexers.Settings;
using NzbDrone.Core.IndexerSearch.Definitions; using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
@ -21,7 +22,7 @@ using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.Definitions namespace NzbDrone.Core.Indexers.Definitions
{ {
public class BitHDTV : TorrentIndexerBase<BitHDTVSettings> public class BitHDTV : TorrentIndexerBase<CookieTorrentBaseSettings>
{ {
public override string Name => "BitHDTV"; public override string Name => "BitHDTV";
public override string[] IndexerUrls => new string[] { "https://www.bit-hdtv.com/" }; public override string[] IndexerUrls => new string[] { "https://www.bit-hdtv.com/" };
@ -89,7 +90,7 @@ namespace NzbDrone.Core.Indexers.Definitions
public class BitHDTVRequestGenerator : IIndexerRequestGenerator public class BitHDTVRequestGenerator : IIndexerRequestGenerator
{ {
public BitHDTVSettings Settings { get; set; } public CookieTorrentBaseSettings Settings { get; set; }
public IndexerCapabilities Capabilities { get; set; } public IndexerCapabilities Capabilities { get; set; }
public BitHDTVRequestGenerator() public BitHDTVRequestGenerator()
@ -179,10 +180,10 @@ namespace NzbDrone.Core.Indexers.Definitions
public class BitHDTVParser : IParseIndexerResponse public class BitHDTVParser : IParseIndexerResponse
{ {
private readonly BitHDTVSettings _settings; private readonly CookieTorrentBaseSettings _settings;
private readonly IndexerCapabilitiesCategories _categories; private readonly IndexerCapabilitiesCategories _categories;
public BitHDTVParser(BitHDTVSettings settings, IndexerCapabilitiesCategories categories) public BitHDTVParser(CookieTorrentBaseSettings settings, IndexerCapabilitiesCategories categories)
{ {
_settings = settings; _settings = settings;
_categories = categories; _categories = categories;
@ -267,36 +268,4 @@ namespace NzbDrone.Core.Indexers.Definitions
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; } public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
} }
public class BitHDTVSettingsValidator : AbstractValidator<BitHDTVSettings>
{
public BitHDTVSettingsValidator()
{
RuleFor(c => c.Cookie).NotEmpty();
}
}
public class BitHDTVSettings : IIndexerSettings
{
private static readonly BitHDTVSettingsValidator Validator = new BitHDTVSettingsValidator();
public BitHDTVSettings()
{
Cookie = "";
}
[FieldDefinition(1, Label = "Base Url", HelpText = "Select which baseurl Prowlarr will use for requests to the site", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls")]
public string BaseUrl { get; set; }
[FieldDefinition(2, Label = "Cookie", HelpText = "Login cookie from website")]
public string Cookie { get; set; }
[FieldDefinition(3)]
public IndexerBaseSettings BaseSettings { get; set; } = new IndexerBaseSettings();
public NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));
}
}
} }

@ -1,54 +0,0 @@
using System;
using System.Collections.Generic;
using NLog;
using NzbDrone.Common.Http;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.Indexers.Definitions.UNIT3D;
using NzbDrone.Core.Messaging.Events;
namespace NzbDrone.Core.Indexers.Definitions
{
[Obsolete("Moved to YML for Cardigann v3")]
public class Blutopia : Unit3dBase
{
public override string Name => "Blutopia";
public override string[] IndexerUrls => new string[] { "https://blutopia.xyz/" };
public override string Description => "Blutopia (BLU) is a Private Torrent Tracker for HD MOVIES / TV";
public override IndexerPrivacy Privacy => IndexerPrivacy.Private;
public Blutopia(IIndexerHttpClient httpClient, IEventAggregator eventAggregator, IIndexerStatusService indexerStatusService, IConfigService configService, Logger logger)
: base(httpClient, eventAggregator, indexerStatusService, configService, logger)
{
}
protected override IndexerCapabilities SetCapabilities()
{
var caps = new IndexerCapabilities
{
TvSearchParams = new List<TvSearchParam>
{
TvSearchParam.Q, TvSearchParam.Season, TvSearchParam.Ep, TvSearchParam.ImdbId, TvSearchParam.TvdbId
},
MovieSearchParams = new List<MovieSearchParam>
{
MovieSearchParam.Q, MovieSearchParam.ImdbId, MovieSearchParam.TmdbId
},
MusicSearchParams = new List<MusicSearchParam>
{
MusicSearchParam.Q
},
BookSearchParams = new List<BookSearchParam>
{
BookSearchParam.Q
}
};
caps.Categories.AddCategoryMapping(1, NewznabStandardCategory.Movies, "Movie");
caps.Categories.AddCategoryMapping(2, NewznabStandardCategory.TV, "TV Show");
caps.Categories.AddCategoryMapping(3, NewznabStandardCategory.MoviesOther, "FANRES");
caps.Categories.AddCategoryMapping(5, NewznabStandardCategory.MoviesOther, "Trailer");
return caps;
}
}
}

@ -1,5 +1,6 @@
using FluentValidation; using FluentValidation;
using NzbDrone.Core.Annotations; using NzbDrone.Core.Annotations;
using NzbDrone.Core.Indexers.Settings;
using NzbDrone.Core.Validation; using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.BroadcastheNet namespace NzbDrone.Core.Indexers.BroadcastheNet
@ -12,7 +13,7 @@ namespace NzbDrone.Core.Indexers.BroadcastheNet
} }
} }
public class BroadcastheNetSettings : IIndexerSettings public class BroadcastheNetSettings : NoAuthTorrentBaseSettings
{ {
private static readonly BroadcastheNetSettingsValidator Validator = new BroadcastheNetSettingsValidator(); private static readonly BroadcastheNetSettingsValidator Validator = new BroadcastheNetSettingsValidator();
@ -20,16 +21,10 @@ namespace NzbDrone.Core.Indexers.BroadcastheNet
{ {
} }
[FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2, Label = "API Key", Privacy = PrivacyLevel.ApiKey)] [FieldDefinition(2, Label = "API Key", Privacy = PrivacyLevel.ApiKey)]
public string ApiKey { get; set; } public string ApiKey { get; set; }
[FieldDefinition(3)] public override NzbDroneValidationResult Validate()
public IndexerBaseSettings BaseSettings { get; set; } = new IndexerBaseSettings();
public NzbDroneValidationResult Validate()
{ {
return new NzbDroneValidationResult(Validator.Validate(this)); return new NzbDroneValidationResult(Validator.Validate(this));
} }

@ -1,6 +1,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using FluentValidation; using FluentValidation;
using NzbDrone.Core.Annotations; using NzbDrone.Core.Annotations;
using NzbDrone.Core.Indexers.Settings;
using NzbDrone.Core.Validation; using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.Cardigann namespace NzbDrone.Core.Indexers.Cardigann
@ -12,7 +13,7 @@ namespace NzbDrone.Core.Indexers.Cardigann
} }
} }
public class CardigannSettings : IIndexerSettings public class CardigannSettings : NoAuthTorrentBaseSettings
{ {
private static readonly CardigannSettingsValidator Validator = new CardigannSettingsValidator(); private static readonly CardigannSettingsValidator Validator = new CardigannSettingsValidator();
@ -24,17 +25,9 @@ namespace NzbDrone.Core.Indexers.Cardigann
[FieldDefinition(0, Hidden = HiddenType.Hidden)] [FieldDefinition(0, Hidden = HiddenType.Hidden)]
public string DefinitionFile { get; set; } public string DefinitionFile { get; set; }
[FieldDefinition(2, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(1)]
public IndexerBaseSettings BaseSettings { get; set; } = new IndexerBaseSettings();
public Dictionary<string, object> ExtraFieldData { get; set; } public Dictionary<string, object> ExtraFieldData { get; set; }
// Field 8 is used by TorznabSettings MinimumSeeders public override NzbDroneValidationResult Validate()
// If you need to add another field here, update TorznabSettings as well and this comment
public virtual NzbDroneValidationResult Validate()
{ {
return new NzbDroneValidationResult(Validator.Validate(this)); return new NzbDroneValidationResult(Validator.Validate(this));
} }

@ -1,342 +0,0 @@
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Net;
using FluentValidation;
using Newtonsoft.Json;
using NLog;
using NzbDrone.Common.Extensions;
using NzbDrone.Common.Http;
using NzbDrone.Core.Annotations;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.Indexers.Exceptions;
using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Parser;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.Definitions
{
[Obsolete("Moved to YML")]
public class DanishBytes : TorrentIndexerBase<DanishBytesSettings>
{
public override string Name => "DanishBytes";
public override string[] IndexerUrls => new string[] { "https://danishbytes.club/", "https://danishbytes2.org/" };
public override string Description => "DanishBytes is a Private Danish Tracker";
public override DownloadProtocol Protocol => DownloadProtocol.Torrent;
public override IndexerPrivacy Privacy => IndexerPrivacy.Private;
public override IndexerCapabilities Capabilities => SetCapabilities();
public DanishBytes(IIndexerHttpClient httpClient, IEventAggregator eventAggregator, IIndexerStatusService indexerStatusService, IConfigService configService, Logger logger)
: base(httpClient, eventAggregator, indexerStatusService, configService, logger)
{
}
public override IIndexerRequestGenerator GetRequestGenerator()
{
return new DanishBytesRequestGenerator() { Settings = Settings, Capabilities = Capabilities };
}
public override IParseIndexerResponse GetParser()
{
return new DanishBytesParser(Settings, Capabilities.Categories);
}
private IndexerCapabilities SetCapabilities()
{
var caps = new IndexerCapabilities
{
TvSearchParams = new List<TvSearchParam>
{
TvSearchParam.Q, TvSearchParam.Season, TvSearchParam.Ep, TvSearchParam.ImdbId, TvSearchParam.TvdbId
},
MovieSearchParams = new List<MovieSearchParam>
{
MovieSearchParam.Q, MovieSearchParam.ImdbId, MovieSearchParam.TmdbId
},
MusicSearchParams = new List<MusicSearchParam>
{
MusicSearchParam.Q
},
BookSearchParams = new List<BookSearchParam>
{
BookSearchParam.Q
}
};
caps.Categories.AddCategoryMapping("1", NewznabStandardCategory.Movies, "Movies");
caps.Categories.AddCategoryMapping("2", NewznabStandardCategory.TV, "TV");
caps.Categories.AddCategoryMapping("3", NewznabStandardCategory.Audio, "Music");
caps.Categories.AddCategoryMapping("4", NewznabStandardCategory.PCGames, "Games");
caps.Categories.AddCategoryMapping("5", NewznabStandardCategory.PC0day, "Appz");
caps.Categories.AddCategoryMapping("8", NewznabStandardCategory.Books, "Bookz");
return caps;
}
}
public class DanishBytesRequestGenerator : IIndexerRequestGenerator
{
public DanishBytesSettings Settings { get; set; }
public IndexerCapabilities Capabilities { get; set; }
public DanishBytesRequestGenerator()
{
}
private IEnumerable<IndexerRequest> GetPagedRequests(string term, int[] categories, string imdbId = null, int tmdbId = 0, int tvdbId = 0)
{
var qc = new NameValueCollection
{
{ "search", term },
{ "api_token", Settings.ApiKey },
};
if (imdbId.IsNotNullOrWhiteSpace())
{
qc.Add("imdb", imdbId);
}
if (tmdbId > 0)
{
qc.Add("tmdb", tmdbId.ToString());
}
if (tvdbId > 0)
{
qc.Add("tvdb", tvdbId.ToString());
}
var searchUrl = string.Format("{0}/api/torrents/v2/filter?{1}", Settings.BaseUrl.TrimEnd('/'), qc.GetQueryString());
foreach (var cat in Capabilities.Categories.MapTorznabCapsToTrackers(categories))
{
searchUrl += $"&categories[]={cat}";
}
var request = new HttpRequest(searchUrl, HttpAccept.Json);
var indexerRequest = new IndexerRequest(request);
yield return indexerRequest;
}
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories, searchCriteria.FullImdbId, searchCriteria.TmdbId.GetValueOrDefault(0)));
return pageableRequests;
}
public IndexerPageableRequestChain GetSearchRequests(MusicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories));
return pageableRequests;
}
public IndexerPageableRequestChain GetSearchRequests(TvSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedTvSearchString), searchCriteria.Categories, searchCriteria.FullImdbId, 0, searchCriteria.TvdbId.GetValueOrDefault(0)));
return pageableRequests;
}
public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories));
return pageableRequests;
}
public IndexerPageableRequestChain GetSearchRequests(BasicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories));
return pageableRequests;
}
public Func<IDictionary<string, string>> GetCookies { get; set; }
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
}
public class DanishBytesParser : IParseIndexerResponse
{
private readonly DanishBytesSettings _settings;
private readonly IndexerCapabilitiesCategories _categories;
public DanishBytesParser(DanishBytesSettings settings, IndexerCapabilitiesCategories categories)
{
_settings = settings;
_categories = categories;
}
public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse)
{
var torrentInfos = new List<TorrentInfo>();
if (indexerResponse.HttpResponse.StatusCode != HttpStatusCode.OK)
{
throw new IndexerException(indexerResponse, $"Unexpected response status {indexerResponse.HttpResponse.StatusCode} code from API request");
}
if (!indexerResponse.HttpResponse.Headers.ContentType.Contains(HttpAccept.Json.Value))
{
throw new IndexerException(indexerResponse, $"Unexpected response header {indexerResponse.HttpResponse.Headers.ContentType} from API request, expected {HttpAccept.Json.Value}");
}
var jsonResponse = new HttpResponse<DanishBytesResponse>(indexerResponse.HttpResponse);
foreach (var row in jsonResponse.Resource.Torrents)
{
var infoUrl = $"{_settings.BaseUrl}torrents/{row.Id}";
var release = new TorrentInfo
{
Title = row.Name,
InfoUrl = infoUrl,
DownloadUrl = $"{_settings.BaseUrl}torrent/download/{row.Id}.{jsonResponse.Resource.Rsskey}",
Guid = infoUrl,
PosterUrl = row.PosterImage,
PublishDate = row.CreatedAt,
Categories = _categories.MapTrackerCatToNewznab(row.CategoryId),
Size = row.Size,
Seeders = row.Seeders,
Peers = row.Leechers + row.Seeders,
Grabs = row.TimesCompleted,
DownloadVolumeFactor = row.Free ? 0 : 1,
UploadVolumeFactor = row.Doubleup ? 2 : 1
};
torrentInfos.Add(release);
}
// order by date
return torrentInfos.OrderByDescending(o => o.PublishDate).ToArray();
}
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
}
public class DanishBytesSettingsValidator : AbstractValidator<DanishBytesSettings>
{
public DanishBytesSettingsValidator()
{
RuleFor(c => c.ApiKey).NotEmpty();
}
}
public class DanishBytesSettings : IIndexerSettings
{
private static readonly DanishBytesSettingsValidator Validator = new DanishBytesSettingsValidator();
public DanishBytesSettings()
{
}
[FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2, Label = "API Key", HelpText = "API Key from Site", Privacy = PrivacyLevel.ApiKey)]
public string ApiKey { get; set; }
[FieldDefinition(3)]
public IndexerBaseSettings BaseSettings { get; set; } = new IndexerBaseSettings();
public NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));
}
}
public class DanishBytesTorrent
{
public int Id { get; set; }
public string Name { get; set; }
[JsonProperty(PropertyName = "info_hash")]
public string InfoHash { get; set; }
public long Size { get; set; }
public int Leechers { get; set; }
public int Seeders { get; set; }
[JsonProperty(PropertyName = "times_completed")]
public int TimesCompleted { get; set; }
[JsonProperty(PropertyName = "category_id")]
public string CategoryId { get; set; }
public string Tmdb { get; set; }
public string Igdb { get; set; }
public string Mal { get; set; }
public string Tvdb { get; set; }
public string Imdb { get; set; }
public int Stream { get; set; }
public bool Free { get; set; }
[JsonProperty(PropertyName = "on_fire")]
public bool OnFire { get; set; }
public bool Doubleup { get; set; }
public bool Highspeed { get; set; }
public bool Featured { get; set; }
public bool Webstream { get; set; }
public bool Anon { get; set; }
public bool Sticky { get; set; }
public bool Sd { get; set; }
[JsonProperty(PropertyName = "created_at")]
public DateTime CreatedAt { get; set; }
[JsonProperty(PropertyName = "resolution_id")]
public int ResolutionId { get; set; }
[JsonProperty(PropertyName = "poster_image")]
public string PosterImage { get; set; }
public string Video { get; set; }
[JsonProperty(PropertyName = "thanks_count")]
public int ThanksCount { get; set; }
[JsonProperty(PropertyName = "comments_count")]
public int CommentsCount { get; set; }
public string GetSize { get; set; }
[JsonProperty(PropertyName = "created_at_human")]
public string CreatedAtHuman { get; set; }
public bool Bookmarked { get; set; }
public bool Liked { get; set; }
[JsonProperty(PropertyName = "show_last_torrents")]
public bool ShowLastTorrents { get; set; }
}
public class DanishBytesPageLinks
{
public int To { get; set; }
public string Qty { get; set; }
[JsonProperty(PropertyName = "current_page")]
public int CurrentPage { get; set; }
}
public class DanishBytesResponse
{
public DanishBytesTorrent[] Torrents { get; set; }
public int ResultsCount { get; set; }
public DanishBytesPageLinks Links { get; set; }
public string CurrentCount { get; set; }
public int TorrentCountTotal { get; set; }
public string Rsskey { get; set; }
}
}

@ -1,84 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using NLog;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.Indexers.Definitions.UNIT3D;
using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Parser.Model;
namespace NzbDrone.Core.Indexers.Definitions
{
[Obsolete("Moved to YML for Cardigann v3")]
public class DesiTorrents : Unit3dBase
{
public override string Name => "DesiTorrents";
public override string Language => "en-US";
public override string[] IndexerUrls => new[] { "https://desitorrents.tv/", "https://desitorrents.rocks/" };
public override string Description => "Desitorrents is a Private Torrent Tracker for BOLLYWOOD / TOLLYWOOD / GENERAL";
public override IndexerPrivacy Privacy => IndexerPrivacy.Private;
public DesiTorrents(IIndexerHttpClient httpClient, IEventAggregator eventAggregator, IIndexerStatusService indexerStatusService, IConfigService configService, Logger logger)
: base(httpClient, eventAggregator, indexerStatusService, configService, logger)
{
}
public override IParseIndexerResponse GetParser()
{
return new DesiTorrentsParser(Settings, Capabilities.Categories);
}
protected override IndexerCapabilities SetCapabilities()
{
var caps = new IndexerCapabilities
{
TvSearchParams = new List<TvSearchParam>
{
TvSearchParam.Q, TvSearchParam.Season, TvSearchParam.Ep
},
MovieSearchParams = new List<MovieSearchParam>
{
MovieSearchParam.Q
},
MusicSearchParams = new List<MusicSearchParam>
{
MusicSearchParam.Q
},
BookSearchParams = new List<BookSearchParam>
{
BookSearchParam.Q
}
};
caps.Categories.AddCategoryMapping(1, NewznabStandardCategory.Movies, "Movies");
caps.Categories.AddCategoryMapping(2, NewznabStandardCategory.TV, "TV");
caps.Categories.AddCategoryMapping(3, NewznabStandardCategory.Audio, "Music");
caps.Categories.AddCategoryMapping(4, NewznabStandardCategory.BooksEBook, "ebooks");
caps.Categories.AddCategoryMapping(5, NewznabStandardCategory.TVSport, "Sports");
caps.Categories.AddCategoryMapping(6, NewznabStandardCategory.PCGames, "Games");
return caps;
}
}
public class DesiTorrentsParser : Unit3dParser
{
public DesiTorrentsParser(Unit3dSettings settings, IndexerCapabilitiesCategories categories)
: base(settings, categories)
{
}
public override IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse)
{
var releases = base.ParseResponse(indexerResponse);
foreach (TorrentInfo release in releases)
{
release.MinimumRatio = 0.6;
release.MinimumSeedTime = 259200;
}
return releases;
}
}
}

@ -1,348 +0,0 @@
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Globalization;
using System.Linq;
using System.Net;
using FluentValidation;
using Newtonsoft.Json;
using NLog;
using NzbDrone.Common.Extensions;
using NzbDrone.Common.Http;
using NzbDrone.Core.Annotations;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.Indexers.Exceptions;
using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Parser;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.Definitions
{
[Obsolete("Moved to YML for Cardigann v3")]
public class DigitalCore : TorrentIndexerBase<DigitalCoreSettings>
{
public override string Name => "DigitalCore";
public override string[] IndexerUrls => new string[] { "https://digitalcore.club/" };
public override string Description => "DigitalCore is a Private Torrent Tracker for MOVIES / TV / GENERAL";
public override DownloadProtocol Protocol => DownloadProtocol.Torrent;
public override IndexerPrivacy Privacy => IndexerPrivacy.Private;
public override IndexerCapabilities Capabilities => SetCapabilities();
public DigitalCore(IIndexerHttpClient httpClient, IEventAggregator eventAggregator, IIndexerStatusService indexerStatusService, IConfigService configService, Logger logger)
: base(httpClient, eventAggregator, indexerStatusService, configService, logger)
{
}
public override IIndexerRequestGenerator GetRequestGenerator()
{
return new DigitalCoreRequestGenerator() { Settings = Settings, PageSize = PageSize, Capabilities = Capabilities };
}
public override IParseIndexerResponse GetParser()
{
return new DigitalCoreParser(Settings, Capabilities.Categories);
}
protected override IDictionary<string, string> GetCookies()
{
var cookies = new Dictionary<string, string>();
cookies.Add("uid", Settings.UId);
cookies.Add("pass", Settings.Passphrase);
return cookies;
}
private IndexerCapabilities SetCapabilities()
{
var caps = new IndexerCapabilities
{
TvSearchParams = new List<TvSearchParam>
{
TvSearchParam.Q, TvSearchParam.Season, TvSearchParam.Ep
},
MovieSearchParams = new List<MovieSearchParam>
{
MovieSearchParam.Q, MovieSearchParam.ImdbId
},
MusicSearchParams = new List<MusicSearchParam>
{
MusicSearchParam.Q
},
BookSearchParams = new List<BookSearchParam>
{
BookSearchParam.Q
}
};
caps.Categories.AddCategoryMapping(1, NewznabStandardCategory.MoviesDVD, "Movies/DVDR");
caps.Categories.AddCategoryMapping(2, NewznabStandardCategory.MoviesSD, "Movies/SD");
caps.Categories.AddCategoryMapping(3, NewznabStandardCategory.MoviesBluRay, "Movies/BluRay");
caps.Categories.AddCategoryMapping(4, NewznabStandardCategory.MoviesUHD, "Movies/4K");
caps.Categories.AddCategoryMapping(5, NewznabStandardCategory.MoviesHD, "Movies/720p");
caps.Categories.AddCategoryMapping(6, NewznabStandardCategory.MoviesHD, "Movies/1080p");
caps.Categories.AddCategoryMapping(7, NewznabStandardCategory.MoviesHD, "Movies/PACKS");
caps.Categories.AddCategoryMapping(8, NewznabStandardCategory.TVHD, "TV/720p");
caps.Categories.AddCategoryMapping(9, NewznabStandardCategory.TVHD, "TV/1080p");
caps.Categories.AddCategoryMapping(10, NewznabStandardCategory.TVSD, "TV/SD");
caps.Categories.AddCategoryMapping(11, NewznabStandardCategory.TVSD, "TV/DVDR");
caps.Categories.AddCategoryMapping(12, NewznabStandardCategory.TVHD, "TV/PACKS");
caps.Categories.AddCategoryMapping(13, NewznabStandardCategory.TVUHD, "TV/4K");
caps.Categories.AddCategoryMapping(14, NewznabStandardCategory.TVHD, "TV/BluRay");
caps.Categories.AddCategoryMapping(17, NewznabStandardCategory.Other, "Unknown");
caps.Categories.AddCategoryMapping(18, NewznabStandardCategory.PC0day, "Apps/0day");
caps.Categories.AddCategoryMapping(20, NewznabStandardCategory.PCISO, "Apps/PC");
caps.Categories.AddCategoryMapping(21, NewznabStandardCategory.PCMac, "Apps/Mac");
caps.Categories.AddCategoryMapping(33, NewznabStandardCategory.PC, "Apps/Tutorials");
caps.Categories.AddCategoryMapping(22, NewznabStandardCategory.AudioMP3, "Music/MP3");
caps.Categories.AddCategoryMapping(23, NewznabStandardCategory.AudioLossless, "Music/FLAC");
caps.Categories.AddCategoryMapping(24, NewznabStandardCategory.Audio, "Music/MTV");
caps.Categories.AddCategoryMapping(29, NewznabStandardCategory.Audio, "Music/PACKS");
caps.Categories.AddCategoryMapping(25, NewznabStandardCategory.PCGames, "Games/PC");
caps.Categories.AddCategoryMapping(26, NewznabStandardCategory.Console, "Games/NSW");
caps.Categories.AddCategoryMapping(27, NewznabStandardCategory.PCMac, "Games/Mac");
caps.Categories.AddCategoryMapping(28, NewznabStandardCategory.Books, "Ebooks");
caps.Categories.AddCategoryMapping(30, NewznabStandardCategory.XXXSD, "XXX/SD");
caps.Categories.AddCategoryMapping(31, NewznabStandardCategory.XXX, "XXX/HD");
caps.Categories.AddCategoryMapping(32, NewznabStandardCategory.XXXUHD, "XXX/4K");
caps.Categories.AddCategoryMapping(35, NewznabStandardCategory.XXXSD, "XXX/Movies/SD");
caps.Categories.AddCategoryMapping(36, NewznabStandardCategory.XXX, "XXX/Movies/HD");
caps.Categories.AddCategoryMapping(37, NewznabStandardCategory.XXXUHD, "XXX/Movies/4K");
caps.Categories.AddCategoryMapping(34, NewznabStandardCategory.XXXImageSet, "XXX/Imagesets");
return caps;
}
}
public class DigitalCoreRequestGenerator : IIndexerRequestGenerator
{
public DigitalCoreSettings Settings { get; set; }
public IndexerCapabilities Capabilities { get; set; }
public int MaxPages { get; set; }
public int PageSize { get; set; }
public DigitalCoreRequestGenerator()
{
MaxPages = 30;
PageSize = 100;
}
private IEnumerable<IndexerRequest> GetPagedRequests(string term, int[] categories, string imdbId = null)
{
var searchUrl = string.Format("{0}/api/v1/torrents", Settings.BaseUrl.TrimEnd('/'));
var parameters = new NameValueCollection();
parameters.Add("extendedSearch", "false");
parameters.Add("freeleech", "false");
parameters.Add("index", "0");
parameters.Add("limit", "100");
parameters.Add("order", "desc");
parameters.Add("page", "search");
if (imdbId.IsNotNullOrWhiteSpace())
{
parameters.Add("searchText", imdbId);
}
else
{
parameters.Add("searchText", term);
}
parameters.Add("sort", "d");
parameters.Add("section", "all");
parameters.Add("stereoscopic", "false");
parameters.Add("watchview", "false");
searchUrl += "?" + parameters.GetQueryString();
foreach (var cat in Capabilities.Categories.MapTorznabCapsToTrackers(categories))
{
searchUrl += "&categories[]=" + cat;
}
var request = new IndexerRequest(searchUrl, HttpAccept.Json);
yield return request;
}
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories, searchCriteria.FullImdbId));
return pageableRequests;
}
public IndexerPageableRequestChain GetSearchRequests(MusicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories));
return pageableRequests;
}
public IndexerPageableRequestChain GetSearchRequests(TvSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedTvSearchString), searchCriteria.Categories, searchCriteria.FullImdbId));
return pageableRequests;
}
public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories));
return pageableRequests;
}
public IndexerPageableRequestChain GetSearchRequests(BasicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SearchTerm), searchCriteria.Categories));
return pageableRequests;
}
public Func<IDictionary<string, string>> GetCookies { get; set; }
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
}
public class DigitalCoreParser : IParseIndexerResponse
{
private readonly DigitalCoreSettings _settings;
private readonly IndexerCapabilitiesCategories _categories;
public DigitalCoreParser(DigitalCoreSettings settings, IndexerCapabilitiesCategories categories)
{
_settings = settings;
_categories = categories;
}
public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse)
{
var torrentInfos = new List<ReleaseInfo>();
if (indexerResponse.HttpResponse.StatusCode != HttpStatusCode.OK)
{
throw new IndexerException(indexerResponse,
"Unexpected response status {0} code from API request",
indexerResponse.HttpResponse.StatusCode);
}
try
{
//var json = JArray.Parse(results.Content);
var json = JsonConvert.DeserializeObject<dynamic>(indexerResponse.Content);
foreach (var row in json ?? Enumerable.Empty<dynamic>())
{
var release = new TorrentInfo();
var descriptions = new List<string>();
var tags = new List<string>();
release.MinimumRatio = 1.1;
release.MinimumSeedTime = 432000; // 120 hours
release.Title = row.name;
release.Categories = _categories.MapTrackerCatToNewznab(row.category.ToString());
release.Size = row.size;
release.Seeders = row.seeders;
release.Peers = row.leechers + release.Seeders;
release.PublishDate = DateTime.ParseExact(row.added.ToString() + " +01:00", "yyyy-MM-dd HH:mm:ss zzz", CultureInfo.InvariantCulture);
release.Files = row.numfiles;
release.Grabs = row.times_completed;
var infoUrl = _settings.BaseUrl + "torrent/" + row.id.ToString() + "/";
release.Guid = infoUrl;
release.DownloadUrl = _settings.BaseUrl + "api/v1/torrents/download/" + row.id.ToString();
release.InfoUrl = infoUrl;
if (row.frileech == 1)
{
release.DownloadVolumeFactor = 0;
}
else
{
release.DownloadVolumeFactor = 1;
}
release.UploadVolumeFactor = 1;
if (row.imdbid2 != null && row.imdbid2.ToString().StartsWith("tt"))
{
if (int.TryParse((string)row.imdbid2, out int imdbNumber))
{
release.ImdbId = imdbNumber;
}
}
torrentInfos.Add(release);
}
}
catch (Exception ex)
{
throw new IndexerException(indexerResponse,
"Unable to parse response from DigitalCore: {0}",
ex.Message);
}
return torrentInfos.ToArray();
}
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
}
public class DigitalCoreSettingsValidator : AbstractValidator<DigitalCoreSettings>
{
public DigitalCoreSettingsValidator()
{
RuleFor(c => c.UId).NotEmpty();
RuleFor(c => c.Passphrase).NotEmpty();
}
}
public class DigitalCoreSettings : IIndexerSettings
{
private static readonly DigitalCoreSettingsValidator Validator = new DigitalCoreSettingsValidator();
public DigitalCoreSettings()
{
UId = "";
Passphrase = "";
}
[FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2, Label = "UID", HelpText = "UID from login cookie", Privacy = PrivacyLevel.UserName)]
public string UId { get; set; }
[FieldDefinition(3, Label = "Passphrase", HelpText = "Passphrase from login cookie", Privacy = PrivacyLevel.Password, Type = FieldType.Password)]
public string Passphrase { get; set; }
[FieldDefinition(4)]
public IndexerBaseSettings BaseSettings { get; set; } = new IndexerBaseSettings();
public NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));
}
}
}

@ -1,5 +1,6 @@
using FluentValidation; using FluentValidation;
using NzbDrone.Core.Annotations; using NzbDrone.Core.Annotations;
using NzbDrone.Core.Indexers.Settings;
using NzbDrone.Core.Validation; using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.FileList namespace NzbDrone.Core.Indexers.FileList
@ -13,7 +14,7 @@ namespace NzbDrone.Core.Indexers.FileList
} }
} }
public class FileListSettings : IIndexerSettings public class FileListSettings : NoAuthTorrentBaseSettings
{ {
private static readonly FileListSettingsValidator Validator = new FileListSettingsValidator(); private static readonly FileListSettingsValidator Validator = new FileListSettingsValidator();
@ -22,19 +23,13 @@ namespace NzbDrone.Core.Indexers.FileList
BaseUrl = "https://filelist.io"; BaseUrl = "https://filelist.io";
} }
[FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2, Label = "Username", HelpText = "Site Username", Privacy = PrivacyLevel.UserName)] [FieldDefinition(2, Label = "Username", HelpText = "Site Username", Privacy = PrivacyLevel.UserName)]
public string Username { get; set; } public string Username { get; set; }
[FieldDefinition(3, Label = "Passkey", HelpText = "Site Passkey", Privacy = PrivacyLevel.Password, Type = FieldType.Password)] [FieldDefinition(3, Label = "Passkey", HelpText = "Site Passkey", Privacy = PrivacyLevel.Password, Type = FieldType.Password)]
public string Passkey { get; set; } public string Passkey { get; set; }
[FieldDefinition(4)] public override NzbDroneValidationResult Validate()
public IndexerBaseSettings BaseSettings { get; set; } = new IndexerBaseSettings();
public NzbDroneValidationResult Validate()
{ {
return new NzbDroneValidationResult(Validator.Validate(this)); return new NzbDroneValidationResult(Validator.Validate(this));
} }

@ -1,22 +1,12 @@
using FluentValidation; using FluentValidation;
using NzbDrone.Core.Annotations; using NzbDrone.Core.Annotations;
using NzbDrone.Core.Indexers.Settings;
using NzbDrone.Core.Validation; using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.Gazelle namespace NzbDrone.Core.Indexers.Gazelle
{ {
public class GazelleSettingsValidator : AbstractValidator<GazelleSettings> public class GazelleSettings : UserPassTorrentBaseSettings
{ {
public GazelleSettingsValidator()
{
RuleFor(c => c.Username).NotEmpty();
RuleFor(c => c.Password).NotEmpty();
}
}
public class GazelleSettings : IIndexerSettings
{
private static readonly GazelleSettingsValidator Validator = new GazelleSettingsValidator();
public GazelleSettings() public GazelleSettings()
{ {
} }
@ -24,24 +14,7 @@ namespace NzbDrone.Core.Indexers.Gazelle
public string AuthKey; public string AuthKey;
public string PassKey; public string PassKey;
[FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2, Label = "Username", HelpText = "Site Username", Privacy = PrivacyLevel.UserName)]
public string Username { get; set; }
[FieldDefinition(3, Label = "Password", HelpText = "Site Password", Privacy = PrivacyLevel.Password, Type = FieldType.Password)]
public string Password { get; set; }
[FieldDefinition(4, Type = FieldType.Checkbox, Label = "Use Freeleech Token", HelpText = "Use Freeleech Token")] [FieldDefinition(4, Type = FieldType.Checkbox, Label = "Use Freeleech Token", HelpText = "Use Freeleech Token")]
public bool UseFreeleechToken { get; set; } public bool UseFreeleechToken { get; set; }
[FieldDefinition(5)]
public IndexerBaseSettings BaseSettings { get; set; } = new IndexerBaseSettings();
public NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));
}
} }
} }

@ -10,6 +10,7 @@ using NLog;
using NzbDrone.Common.Http; using NzbDrone.Common.Http;
using NzbDrone.Core.Annotations; using NzbDrone.Core.Annotations;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.Indexers.Settings;
using NzbDrone.Core.IndexerSearch.Definitions; using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
@ -392,39 +393,14 @@ namespace NzbDrone.Core.Indexers.Definitions
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; } public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
} }
public class GazelleGamesSettingsValidator : AbstractValidator<GazelleGamesSettings> public class GazelleGamesSettings : CookieTorrentBaseSettings
{ {
public GazelleGamesSettingsValidator()
{
RuleFor(c => c.Cookie).NotEmpty();
}
}
public class GazelleGamesSettings : IIndexerSettings
{
private static readonly GazelleGamesSettingsValidator Validator = new GazelleGamesSettingsValidator();
public GazelleGamesSettings() public GazelleGamesSettings()
{ {
Cookie = "";
SearchGroupNames = false; SearchGroupNames = false;
} }
[FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2, Label = "Cookie", HelpText = "Login cookie from website")]
public string Cookie { get; set; }
[FieldDefinition(3, Label = "Search Group Names", Type = FieldType.Checkbox, HelpText = "Search Group Names Only")] [FieldDefinition(3, Label = "Search Group Names", Type = FieldType.Checkbox, HelpText = "Search Group Names Only")]
public bool SearchGroupNames { get; set; } public bool SearchGroupNames { get; set; }
[FieldDefinition(4)]
public IndexerBaseSettings BaseSettings { get; set; } = new IndexerBaseSettings();
public NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));
}
} }
} }

@ -1,6 +1,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using FluentValidation; using FluentValidation;
using NzbDrone.Core.Annotations; using NzbDrone.Core.Annotations;
using NzbDrone.Core.Indexers.Settings;
using NzbDrone.Core.Validation; using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.HDBits namespace NzbDrone.Core.Indexers.HDBits
@ -13,7 +14,7 @@ namespace NzbDrone.Core.Indexers.HDBits
} }
} }
public class HDBitsSettings : IIndexerSettings public class HDBitsSettings : NoAuthTorrentBaseSettings
{ {
private static readonly HDBitsSettingsValidator Validator = new HDBitsSettingsValidator(); private static readonly HDBitsSettingsValidator Validator = new HDBitsSettingsValidator();
@ -23,9 +24,6 @@ namespace NzbDrone.Core.Indexers.HDBits
Mediums = System.Array.Empty<int>(); Mediums = System.Array.Empty<int>();
} }
[FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2, Label = "Username", HelpText = "Site Username", Privacy = PrivacyLevel.UserName)] [FieldDefinition(2, Label = "Username", HelpText = "Site Username", Privacy = PrivacyLevel.UserName)]
public string Username { get; set; } public string Username { get; set; }
@ -38,10 +36,7 @@ namespace NzbDrone.Core.Indexers.HDBits
[FieldDefinition(5, Label = "Mediums", Type = FieldType.TagSelect, SelectOptions = typeof(HdBitsMedium), Advanced = true, HelpText = "Options: BluRay, Encode, Capture, Remux, WebDL. If unspecified, all options are used.")] [FieldDefinition(5, Label = "Mediums", Type = FieldType.TagSelect, SelectOptions = typeof(HdBitsMedium), Advanced = true, HelpText = "Options: BluRay, Encode, Capture, Remux, WebDL. If unspecified, all options are used.")]
public IEnumerable<int> Mediums { get; set; } public IEnumerable<int> Mediums { get; set; }
[FieldDefinition(6)] public override NzbDroneValidationResult Validate()
public IndexerBaseSettings BaseSettings { get; set; } = new IndexerBaseSettings();
public NzbDroneValidationResult Validate()
{ {
return new NzbDroneValidationResult(Validator.Validate(this)); return new NzbDroneValidationResult(Validator.Validate(this));
} }

@ -13,6 +13,7 @@ using NzbDrone.Common.Http;
using NzbDrone.Core.Annotations; using NzbDrone.Core.Annotations;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.Indexers.Exceptions; using NzbDrone.Core.Indexers.Exceptions;
using NzbDrone.Core.Indexers.Settings;
using NzbDrone.Core.IndexerSearch.Definitions; using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
@ -21,7 +22,7 @@ using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.Definitions namespace NzbDrone.Core.Indexers.Definitions
{ {
public class HDSpace : TorrentIndexerBase<HDSpaceSettings> public class HDSpace : TorrentIndexerBase<UserPassTorrentBaseSettings>
{ {
public override string Name => "HD-Space"; public override string Name => "HD-Space";
public override string[] IndexerUrls => new string[] { "https://hd-space.org/" }; public override string[] IndexerUrls => new string[] { "https://hd-space.org/" };
@ -146,7 +147,7 @@ namespace NzbDrone.Core.Indexers.Definitions
public class HDSpaceRequestGenerator : IIndexerRequestGenerator public class HDSpaceRequestGenerator : IIndexerRequestGenerator
{ {
public HDSpaceSettings Settings { get; set; } public UserPassTorrentBaseSettings Settings { get; set; }
public IndexerCapabilities Capabilities { get; set; } public IndexerCapabilities Capabilities { get; set; }
public HDSpaceRequestGenerator() public HDSpaceRequestGenerator()
@ -228,10 +229,10 @@ namespace NzbDrone.Core.Indexers.Definitions
public class HDSpaceParser : IParseIndexerResponse public class HDSpaceParser : IParseIndexerResponse
{ {
private readonly HDSpaceSettings _settings; private readonly UserPassTorrentBaseSettings _settings;
private readonly IndexerCapabilitiesCategories _categories; private readonly IndexerCapabilitiesCategories _categories;
public HDSpaceParser(HDSpaceSettings settings, IndexerCapabilitiesCategories categories) public HDSpaceParser(UserPassTorrentBaseSettings settings, IndexerCapabilitiesCategories categories)
{ {
_settings = settings; _settings = settings;
_categories = categories; _categories = categories;
@ -313,41 +314,4 @@ namespace NzbDrone.Core.Indexers.Definitions
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; } public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
} }
public class HDSpaceSettingsValidator : AbstractValidator<HDSpaceSettings>
{
public HDSpaceSettingsValidator()
{
RuleFor(c => c.Username).NotEmpty();
RuleFor(c => c.Password).NotEmpty();
}
}
public class HDSpaceSettings : IIndexerSettings
{
private static readonly HDSpaceSettingsValidator Validator = new HDSpaceSettingsValidator();
public HDSpaceSettings()
{
Username = "";
Password = "";
}
[FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2, Label = "Username", HelpText = "Site Username", Privacy = PrivacyLevel.UserName)]
public string Username { get; set; }
[FieldDefinition(3, Label = "Password", HelpText = "Site Password", Privacy = PrivacyLevel.Password, Type = FieldType.Password)]
public string Password { get; set; }
[FieldDefinition(4)]
public IndexerBaseSettings BaseSettings { get; set; } = new IndexerBaseSettings();
public NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));
}
}
} }

@ -12,6 +12,7 @@ using NLog;
using NzbDrone.Common.Http; using NzbDrone.Common.Http;
using NzbDrone.Core.Annotations; using NzbDrone.Core.Annotations;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.Indexers.Settings;
using NzbDrone.Core.IndexerSearch.Definitions; using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
@ -20,7 +21,7 @@ using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.Definitions namespace NzbDrone.Core.Indexers.Definitions
{ {
public class HDTorrents : TorrentIndexerBase<HDTorrentsSettings> public class HDTorrents : TorrentIndexerBase<UserPassTorrentBaseSettings>
{ {
public override string Name => "HD-Torrents"; public override string Name => "HD-Torrents";
@ -140,7 +141,7 @@ namespace NzbDrone.Core.Indexers.Definitions
public class HDTorrentsRequestGenerator : IIndexerRequestGenerator public class HDTorrentsRequestGenerator : IIndexerRequestGenerator
{ {
public HDTorrentsSettings Settings { get; set; } public UserPassTorrentBaseSettings Settings { get; set; }
public IndexerCapabilities Capabilities { get; set; } public IndexerCapabilities Capabilities { get; set; }
public HDTorrentsRequestGenerator() public HDTorrentsRequestGenerator()
@ -219,7 +220,7 @@ namespace NzbDrone.Core.Indexers.Definitions
public class HDTorrentsParser : IParseIndexerResponse public class HDTorrentsParser : IParseIndexerResponse
{ {
private readonly HDTorrentsSettings _settings; private readonly UserPassTorrentBaseSettings _settings;
private readonly IndexerCapabilitiesCategories _categories; private readonly IndexerCapabilitiesCategories _categories;
private readonly Regex _posterRegex = new Regex(@"src=\\'./([^']+)\\'", RegexOptions.IgnoreCase); private readonly Regex _posterRegex = new Regex(@"src=\\'./([^']+)\\'", RegexOptions.IgnoreCase);
@ -233,7 +234,7 @@ namespace NzbDrone.Core.Indexers.Definitions
"Owner" "Owner"
}; };
public HDTorrentsParser(HDTorrentsSettings settings, IndexerCapabilitiesCategories categories) public HDTorrentsParser(UserPassTorrentBaseSettings settings, IndexerCapabilitiesCategories categories)
{ {
_settings = settings; _settings = settings;
_categories = categories; _categories = categories;
@ -356,41 +357,4 @@ namespace NzbDrone.Core.Indexers.Definitions
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; } public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
} }
public class HDTorrentsSettingsValidator : AbstractValidator<HDTorrentsSettings>
{
public HDTorrentsSettingsValidator()
{
RuleFor(c => c.Username).NotEmpty();
RuleFor(c => c.Password).NotEmpty();
}
}
public class HDTorrentsSettings : IIndexerSettings
{
private static readonly HDTorrentsSettingsValidator Validator = new HDTorrentsSettingsValidator();
public HDTorrentsSettings()
{
Username = "";
Password = "";
}
[FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2, Label = "Username", HelpText = "Site Username", Privacy = PrivacyLevel.UserName)]
public string Username { get; set; }
[FieldDefinition(3, Label = "Password", HelpText = "Site Password", Privacy = PrivacyLevel.Password, Type = FieldType.Password)]
public string Password { get; set; }
[FieldDefinition(4)]
public IndexerBaseSettings BaseSettings { get; set; } = new IndexerBaseSettings();
public NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));
}
}
} }

@ -9,6 +9,7 @@ using NzbDrone.Common.Extensions;
using NzbDrone.Common.Http; using NzbDrone.Common.Http;
using NzbDrone.Core.Annotations; using NzbDrone.Core.Annotations;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.Indexers.Settings;
using NzbDrone.Core.IndexerSearch.Definitions; using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
@ -348,38 +349,13 @@ namespace NzbDrone.Core.Indexers.Definitions
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; } public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
} }
public class IPTorrentsSettingsValidator : AbstractValidator<IPTorrentsSettings> public class IPTorrentsSettings : CookieTorrentBaseSettings
{ {
public IPTorrentsSettingsValidator()
{
RuleFor(c => c.Cookie).NotEmpty();
}
}
public class IPTorrentsSettings : IIndexerSettings
{
private static readonly IPTorrentsSettingsValidator Validator = new IPTorrentsSettingsValidator();
public IPTorrentsSettings() public IPTorrentsSettings()
{ {
Cookie = "";
} }
[FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2, Label = "Cookie", HelpText = "Enter the cookie for the site. Example: `cf_clearance=0f7e7f10c62fd069323da10dcad545b828a44b6-1622730685-9-100; uid=123456789; pass=passhashwillbehere`", HelpLink = "https://wiki.servarr.com/prowlarr/faq#finding-cookies")]
public string Cookie { get; set; }
[FieldDefinition(3, Label = "FreeLeech Only", Type = FieldType.Checkbox, Advanced = true, HelpText = "Search Freeleech torrents only")] [FieldDefinition(3, Label = "FreeLeech Only", Type = FieldType.Checkbox, Advanced = true, HelpText = "Search Freeleech torrents only")]
public bool FreeLeechOnly { get; set; } public bool FreeLeechOnly { get; set; }
[FieldDefinition(4)]
public IndexerBaseSettings BaseSettings { get; set; } = new IndexerBaseSettings();
public NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));
}
} }
} }

@ -13,6 +13,7 @@ using NzbDrone.Common.Http;
using NzbDrone.Core.Annotations; using NzbDrone.Core.Annotations;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.Indexers.Exceptions; using NzbDrone.Core.Indexers.Exceptions;
using NzbDrone.Core.Indexers.Settings;
using NzbDrone.Core.IndexerSearch.Definitions; using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
@ -22,7 +23,7 @@ using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.Definitions namespace NzbDrone.Core.Indexers.Definitions
{ {
public class ImmortalSeed : TorrentIndexerBase<ImmortalSeedSettings> public class ImmortalSeed : TorrentIndexerBase<UserPassTorrentBaseSettings>
{ {
public override string Name => "ImmortalSeed"; public override string Name => "ImmortalSeed";
@ -161,7 +162,7 @@ namespace NzbDrone.Core.Indexers.Definitions
public class ImmortalSeedRequestGenerator : IIndexerRequestGenerator public class ImmortalSeedRequestGenerator : IIndexerRequestGenerator
{ {
public ImmortalSeedSettings Settings { get; set; } public UserPassTorrentBaseSettings Settings { get; set; }
public IndexerCapabilities Capabilities { get; set; } public IndexerCapabilities Capabilities { get; set; }
public ImmortalSeedRequestGenerator() public ImmortalSeedRequestGenerator()
@ -243,10 +244,10 @@ namespace NzbDrone.Core.Indexers.Definitions
public class ImmortalSeedParser : IParseIndexerResponse public class ImmortalSeedParser : IParseIndexerResponse
{ {
private readonly ImmortalSeedSettings _settings; private readonly UserPassTorrentBaseSettings _settings;
private readonly IndexerCapabilitiesCategories _categories; private readonly IndexerCapabilitiesCategories _categories;
public ImmortalSeedParser(ImmortalSeedSettings settings, IndexerCapabilitiesCategories categories) public ImmortalSeedParser(UserPassTorrentBaseSettings settings, IndexerCapabilitiesCategories categories)
{ {
_settings = settings; _settings = settings;
_categories = categories; _categories = categories;
@ -333,41 +334,4 @@ namespace NzbDrone.Core.Indexers.Definitions
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; } public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
} }
public class ImmortalSeedSettingsValidator : AbstractValidator<ImmortalSeedSettings>
{
public ImmortalSeedSettingsValidator()
{
RuleFor(c => c.Username).NotEmpty();
RuleFor(c => c.Password).NotEmpty();
}
}
public class ImmortalSeedSettings : IIndexerSettings
{
private static readonly ImmortalSeedSettingsValidator Validator = new ImmortalSeedSettingsValidator();
public ImmortalSeedSettings()
{
Username = "";
Password = "";
}
[FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2, Label = "Username", HelpText = "Site Username", Privacy = PrivacyLevel.UserName)]
public string Username { get; set; }
[FieldDefinition(3, Label = "Password", HelpText = "Site Password", Privacy = PrivacyLevel.Password, Type = FieldType.Password)]
public string Password { get; set; }
[FieldDefinition(4)]
public IndexerBaseSettings BaseSettings { get; set; } = new IndexerBaseSettings();
public NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));
}
}
} }

@ -1,330 +0,0 @@
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Net;
using Newtonsoft.Json;
using NLog;
using NzbDrone.Common.Extensions;
using NzbDrone.Common.Http;
using NzbDrone.Core.Annotations;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.Indexers.Exceptions;
using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Parser;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.Definitions
{
[Obsolete("Moved to YML for Cardigann v3")]
public class InternetArchive : TorrentIndexerBase<InternetArchiveSettings>
{
public override string Name => "Internet Archive";
public override string[] IndexerUrls => new string[] { "https://archive.org/" };
public override string Description => "Internet Archive is a non-profit library of millions of free books, movies, software, music, websites, and more.";
public override DownloadProtocol Protocol => DownloadProtocol.Torrent;
public override IndexerPrivacy Privacy => IndexerPrivacy.Public;
public override IndexerCapabilities Capabilities => SetCapabilities();
public override bool FollowRedirect => true;
public InternetArchive(IIndexerHttpClient httpClient, IEventAggregator eventAggregator, IIndexerStatusService indexerStatusService, IConfigService configService, Logger logger)
: base(httpClient, eventAggregator, indexerStatusService, configService, logger)
{
}
public override IParseIndexerResponse GetParser()
{
return new InternetArchiveParser(Settings, Capabilities.Categories);
}
public override IIndexerRequestGenerator GetRequestGenerator()
{
return new InternetArchiveRequestGenerator() { Settings = Settings, Capabilities = Capabilities };
}
private IndexerCapabilities SetCapabilities()
{
var caps = new IndexerCapabilities
{
TvSearchParams = new List<TvSearchParam>
{
TvSearchParam.Q
},
MovieSearchParams = new List<MovieSearchParam>
{
MovieSearchParam.Q
},
BookSearchParams = new List<BookSearchParam>
{
BookSearchParam.Q
},
MusicSearchParams = new List<MusicSearchParam>
{
MusicSearchParam.Q
}
};
// c.f. https://archive.org/services/docs/api/metadata-schema/index.html?highlight=mediatype#mediatype
// "Movies" is a catch all category for videos
caps.Categories.AddCategoryMapping("texts", NewznabStandardCategory.Books);
caps.Categories.AddCategoryMapping("etree", NewznabStandardCategory.Audio);
caps.Categories.AddCategoryMapping("audio", NewznabStandardCategory.Audio);
caps.Categories.AddCategoryMapping("movies", NewznabStandardCategory.Movies);
caps.Categories.AddCategoryMapping("movies", NewznabStandardCategory.TV);
caps.Categories.AddCategoryMapping("software", NewznabStandardCategory.PC);
caps.Categories.AddCategoryMapping("image", NewznabStandardCategory.OtherMisc);
caps.Categories.AddCategoryMapping("data", NewznabStandardCategory.Other);
caps.Categories.AddCategoryMapping("web", NewznabStandardCategory.Other);
caps.Categories.AddCategoryMapping("collection", NewznabStandardCategory.Other);
caps.Categories.AddCategoryMapping("account", NewznabStandardCategory.Other);
caps.Categories.AddCategoryMapping("other", NewznabStandardCategory.Other);
return caps;
}
}
public class InternetArchiveRequestGenerator : IIndexerRequestGenerator
{
public InternetArchiveSettings Settings { get; set; }
public IndexerCapabilities Capabilities { get; set; }
public InternetArchiveRequestGenerator()
{
}
private IEnumerable<IndexerRequest> GetPagedRequests(string searchTerm, SearchCriteriaBase searchCriteria)
{
var query = "format:(\"Archive BitTorrent\")";
if (searchTerm.IsNotNullOrWhiteSpace())
{
if (Settings.TitleOnly)
{
query = string.Format("title:({0}) AND {1}", searchTerm, query);
}
else
{
query = string.Format("{0} AND {1}", searchTerm, query);
}
}
var categories = Capabilities.Categories.MapTorznabCapsToTrackers(searchCriteria.Categories);
if (categories.Count > 0)
{
query = string.Format("{0} AND mediatype:({1})", query, string.Join(" OR ", categories));
}
string sortBy = (InternetArchiveSort)Settings.SortBy switch
{
InternetArchiveSort.PublicDate => "publicdate",
InternetArchiveSort.Downloads => "downloads",
InternetArchiveSort.Size => "item_size",
_ => "publicdate",
};
string sortOrder = (InternetArchiveSortOrder)Settings.SortOrder switch
{
InternetArchiveSortOrder.Descending => "desc",
InternetArchiveSortOrder.Ascending => "asc",
_ => "desc",
};
var parameters = new NameValueCollection
{
{ "q", query },
{ "fields", "btih,downloads,identifier,item_size,mediatype,publicdate,title" },
{ "count", searchCriteria.Limit.GetValueOrDefault(100).ToString() }, // API default is 5000, don't think thats viable at all.
{ "sorts", string.Format("{0} {1}", sortBy, sortOrder) }
};
var searchUrl = string.Format("{0}/services/search/v1/scrape?{1}", Settings.BaseUrl.TrimEnd('/'), parameters.GetQueryString());
var request = new IndexerRequest(searchUrl, HttpAccept.Json);
yield return request;
}
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria));
return pageableRequests;
}
public IndexerPageableRequestChain GetSearchRequests(MusicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria));
return pageableRequests;
}
public IndexerPageableRequestChain GetSearchRequests(TvSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedTvSearchString), searchCriteria));
return pageableRequests;
}
public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria));
return pageableRequests;
}
public IndexerPageableRequestChain GetSearchRequests(BasicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria));
return pageableRequests;
}
public Func<IDictionary<string, string>> GetCookies { get; set; }
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
}
public class InternetArchiveParser : IParseIndexerResponse
{
private readonly InternetArchiveSettings _settings;
private readonly IndexerCapabilitiesCategories _categories;
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
public InternetArchiveParser(InternetArchiveSettings settings, IndexerCapabilitiesCategories categories)
{
_settings = settings;
_categories = categories;
}
public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse)
{
var torrentInfos = new List<TorrentInfo>();
if (indexerResponse.HttpResponse.StatusCode != HttpStatusCode.OK)
{
throw new IndexerException(indexerResponse, $"Unexpected response status {indexerResponse.HttpResponse.StatusCode} code from API request");
}
if (!indexerResponse.HttpResponse.Headers.ContentType.Contains(HttpAccept.Json.Value))
{
throw new IndexerException(indexerResponse, $"Unexpected response header {indexerResponse.HttpResponse.Headers.ContentType} from API request, expected {HttpAccept.Json.Value}");
}
var jsonResponse = new HttpResponse<InternetArchiveResponse>(indexerResponse.HttpResponse);
foreach (var searchResult in jsonResponse.Resource.SearchResults)
{
var title = searchResult.Title ?? searchResult.Identifier;
var downloadUrl = string.Format("{0}/download/{1}/{1}_archive.torrent", _settings.BaseUrl.TrimEnd('/'), searchResult.Identifier);
var detailsUrl = string.Format("{0}/details/{1}", _settings.BaseUrl.TrimEnd('/'), searchResult.Identifier);
var category = _categories.MapTrackerCatToNewznab(searchResult.MediaType ?? "other");
var release = new TorrentInfo
{
Categories = category,
CommentUrl = detailsUrl,
DownloadUrl = downloadUrl,
DownloadVolumeFactor = 0,
Guid = detailsUrl,
Grabs = searchResult.Downloads,
InfoHash = searchResult.InfoHash,
InfoUrl = detailsUrl,
Peers = 2,
PublishDate = searchResult.PublicDate,
Seeders = 1,
Size = searchResult.Size,
Title = title,
UploadVolumeFactor = 1
};
if (!_settings.TorrentFileOnly && searchResult.InfoHash != null)
{
release.MagnetUrl = MagnetLinkBuilder.BuildPublicMagnetLink(searchResult.InfoHash, title);
}
torrentInfos.Add(release);
}
return torrentInfos.ToArray();
}
}
public class InternetArchiveResponse
{
[JsonProperty(PropertyName = "items")]
public List<InternetArchiveTorrent> SearchResults { get; set; }
public string Cursor { get; set; }
public int Count { get; set; }
public int Total { get; set; }
}
public class InternetArchiveTorrent
{
public int Downloads { get; set; }
public string Identifier { get; set; }
[JsonProperty(PropertyName = "btih")]
public string InfoHash { get; set; }
public string MediaType { get; set; }
public DateTime PublicDate { get; set; }
[JsonProperty(PropertyName = "item_size")]
public long Size { get; set; }
public string Title { get; set; }
}
public class InternetArchiveSettings : IIndexerSettings
{
[FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2, Label = "Sort By", Type = FieldType.Select, Advanced = true, SelectOptions = typeof(InternetArchiveSort), HelpText = "Field used to sort the search results.")]
public int SortBy { get; set; }
[FieldDefinition(3, Label = "Sort Order", Type = FieldType.Select, Advanced = true, SelectOptions = typeof(InternetArchiveSortOrder), HelpText = "Order to use when sorting results.")]
public int SortOrder { get; set; }
[FieldDefinition(4, Label = "Title Only", Type = FieldType.Checkbox, Advanced = true, HelpText = "Whether to search in title only.")]
public bool TitleOnly { get; set; }
[FieldDefinition(5, Label = "Torrent File Only", Type = FieldType.Checkbox, Advanced = true, HelpText = "Only use torrent files, not magnet links.")]
public bool TorrentFileOnly { get; set; }
[FieldDefinition(6)]
public IndexerBaseSettings BaseSettings { get; set; } = new IndexerBaseSettings();
public InternetArchiveSettings()
{
SortBy = (int)InternetArchiveSort.PublicDate;
SortOrder = (int)InternetArchiveSortOrder.Descending;
TitleOnly = false;
TorrentFileOnly = false;
}
public NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult();
}
}
public enum InternetArchiveSort
{
PublicDate,
Downloads,
Size
}
public enum InternetArchiveSortOrder
{
Descending,
Ascending
}
}

@ -1,51 +0,0 @@
using System.Collections.Generic;
using NLog;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.Indexers.Definitions.UNIT3D;
using NzbDrone.Core.Messaging.Events;
namespace NzbDrone.Core.Indexers.Definitions
{
public class LatTeam : Unit3dBase
{
public override string Name => "Lat-Team";
public override string Language => "es";
public override string[] IndexerUrls => new[] { "https://lat-team.com/" };
public override string Description => "Lat-Team is a Private Torrent Tracker for HD MOVIES / TV";
public override IndexerPrivacy Privacy => IndexerPrivacy.Private;
public LatTeam(IIndexerHttpClient httpClient, IEventAggregator eventAggregator, IIndexerStatusService indexerStatusService, IConfigService configService, Logger logger)
: base(httpClient, eventAggregator, indexerStatusService, configService, logger)
{
}
protected override IndexerCapabilities SetCapabilities()
{
var caps = new IndexerCapabilities
{
TvSearchParams = new List<TvSearchParam>
{
TvSearchParam.Q, TvSearchParam.Season, TvSearchParam.Ep, TvSearchParam.ImdbId, TvSearchParam.TvdbId
},
MovieSearchParams = new List<MovieSearchParam>
{
MovieSearchParam.Q, MovieSearchParam.ImdbId, MovieSearchParam.TmdbId
},
MusicSearchParams = new List<MusicSearchParam>
{
MusicSearchParam.Q
},
};
caps.Categories.AddCategoryMapping(1, NewznabStandardCategory.Movies, "Peliculas");
caps.Categories.AddCategoryMapping(6, NewznabStandardCategory.MoviesOther, "Retro Pelicula");
caps.Categories.AddCategoryMapping(5, NewznabStandardCategory.TVAnime, "Anime");
caps.Categories.AddCategoryMapping(2, NewznabStandardCategory.TV, "TV Series");
caps.Categories.AddCategoryMapping(7, NewznabStandardCategory.TVOther, "Retro Serie TV");
caps.Categories.AddCategoryMapping(8, NewznabStandardCategory.TVForeign, "Telenovelas y Teleseries");
caps.Categories.AddCategoryMapping(3, NewznabStandardCategory.Audio, "Musica");
return caps;
}
}
}

@ -1,270 +0,0 @@
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using FluentValidation;
using Newtonsoft.Json;
using NLog;
using NzbDrone.Common.Http;
using NzbDrone.Core.Annotations;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Parser;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.Definitions
{
[Obsolete("Moved to YML for Cardigann v3")]
public class Milkie : TorrentIndexerBase<MilkieSettings>
{
public override string Name => "Milkie";
public override string[] IndexerUrls => new string[] { "https://milkie.cc/" };
public override string Description => "Milkie is a general tracker providing unpacked and 0day/0sec scene content.";
public override DownloadProtocol Protocol => DownloadProtocol.Torrent;
public override IndexerPrivacy Privacy => IndexerPrivacy.Private;
public override IndexerCapabilities Capabilities => SetCapabilities();
public Milkie(IIndexerHttpClient httpClient, IEventAggregator eventAggregator, IIndexerStatusService indexerStatusService, IConfigService configService, Logger logger)
: base(httpClient, eventAggregator, indexerStatusService, configService, logger)
{
}
public override IIndexerRequestGenerator GetRequestGenerator()
{
return new MilkieRequestGenerator() { Settings = Settings, Capabilities = Capabilities };
}
public override IParseIndexerResponse GetParser()
{
return new MilkieParser(Settings, Capabilities.Categories);
}
private IndexerCapabilities SetCapabilities()
{
var caps = new IndexerCapabilities
{
TvSearchParams = new List<TvSearchParam>
{
TvSearchParam.Q, TvSearchParam.Season, TvSearchParam.Ep
},
MovieSearchParams = new List<MovieSearchParam>
{
MovieSearchParam.Q
},
MusicSearchParams = new List<MusicSearchParam>
{
MusicSearchParam.Q
},
BookSearchParams = new List<BookSearchParam>
{
BookSearchParam.Q
}
};
caps.Categories.AddCategoryMapping("1", NewznabStandardCategory.Movies, "Movies");
caps.Categories.AddCategoryMapping("2", NewznabStandardCategory.TV, "TV");
caps.Categories.AddCategoryMapping("3", NewznabStandardCategory.Audio, "Music");
caps.Categories.AddCategoryMapping("4", NewznabStandardCategory.PCGames, "Games");
caps.Categories.AddCategoryMapping("5", NewznabStandardCategory.Books, "Ebook");
caps.Categories.AddCategoryMapping("6", NewznabStandardCategory.PC, "Apps");
caps.Categories.AddCategoryMapping("7", NewznabStandardCategory.XXX, "Adult");
return caps;
}
}
public class MilkieRequestGenerator : IIndexerRequestGenerator
{
public MilkieSettings Settings { get; set; }
public IndexerCapabilities Capabilities { get; set; }
public MilkieRequestGenerator()
{
}
private IEnumerable<IndexerRequest> GetPagedRequests(string term, int[] categories, string imdbId = null)
{
var searchUrl = Settings.BaseUrl + "api/v1/torrents";
var qc = new NameValueCollection
{
{ "ps", "100" }
};
if (!string.IsNullOrWhiteSpace(term))
{
qc.Add("query", term);
}
if (categories != null && categories.Length > 0)
{
qc.Add("categories", string.Join(",", Capabilities.Categories.MapTorznabCapsToTrackers(categories)));
}
searchUrl = searchUrl + "?" + qc.GetQueryString();
var request = new IndexerRequest(searchUrl, HttpAccept.Json);
request.HttpRequest.Headers.Add("x-milkie-auth", Settings.ApiKey);
yield return request;
}
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SearchTerm), searchCriteria.Categories, searchCriteria.FullImdbId));
return pageableRequests;
}
public IndexerPageableRequestChain GetSearchRequests(MusicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SearchTerm), searchCriteria.Categories));
return pageableRequests;
}
public IndexerPageableRequestChain GetSearchRequests(TvSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SearchTerm), searchCriteria.Categories, searchCriteria.FullImdbId));
return pageableRequests;
}
public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SearchTerm), searchCriteria.Categories));
return pageableRequests;
}
public IndexerPageableRequestChain GetSearchRequests(BasicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SearchTerm), searchCriteria.Categories));
return pageableRequests;
}
public Func<IDictionary<string, string>> GetCookies { get; set; }
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
}
public class MilkieParser : IParseIndexerResponse
{
private readonly MilkieSettings _settings;
private readonly IndexerCapabilitiesCategories _categories;
public MilkieParser(MilkieSettings settings, IndexerCapabilitiesCategories categories)
{
_settings = settings;
_categories = categories;
}
public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse)
{
var torrentInfos = new List<TorrentInfo>();
var response = JsonConvert.DeserializeObject<MilkieResponse>(indexerResponse.Content);
var dlQueryParams = new NameValueCollection
{
{ "key", _settings.ApiKey }
};
foreach (var torrent in response.Torrents)
{
var torrentUrl = _settings.BaseUrl + "api/v1/torrents";
var link = $"{torrentUrl}/{torrent.Id}/torrent?{dlQueryParams.GetQueryString()}";
var details = $"{_settings.BaseUrl}browse/{torrent.Id}";
var publishDate = DateTimeUtil.FromUnknown(torrent.CreatedAt);
var release = new TorrentInfo
{
Title = torrent.ReleaseName,
DownloadUrl = link,
InfoUrl = details,
Guid = details,
PublishDate = publishDate,
Categories = _categories.MapTrackerCatToNewznab(torrent.Category.ToString()),
Size = torrent.Size,
Seeders = torrent.Seeders,
Peers = torrent.Seeders + torrent.PartialSeeders + torrent.Leechers,
Grabs = torrent.Downloaded,
UploadVolumeFactor = 1,
DownloadVolumeFactor = 0,
MinimumRatio = 1,
MinimumSeedTime = 172800 // 48 hours
};
torrentInfos.Add(release);
}
return torrentInfos.ToArray();
}
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
}
public class MilkieSettingsValidator : AbstractValidator<MilkieSettings>
{
public MilkieSettingsValidator()
{
RuleFor(c => c.ApiKey).NotEmpty();
}
}
public class MilkieSettings : IIndexerSettings
{
private static readonly MilkieSettingsValidator Validator = new MilkieSettingsValidator();
public MilkieSettings()
{
ApiKey = "";
}
[FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2, Label = "API Key", HelpText = "Site API Key", Privacy = PrivacyLevel.ApiKey)]
public string ApiKey { get; set; }
[FieldDefinition(3)]
public IndexerBaseSettings BaseSettings { get; set; } = new IndexerBaseSettings();
public NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));
}
}
public class MilkieResponse
{
public int Hits { get; set; }
public int Took { get; set; }
public MilkieTorrent[] Torrents { get; set; }
}
public class MilkieTorrent
{
public string Id { get; set; }
public string ReleaseName { get; set; }
public int Category { get; set; }
public int Downloaded { get; set; }
public int Seeders { get; set; }
public int PartialSeeders { get; set; }
public int Leechers { get; set; }
public long Size { get; set; }
public string CreatedAt { get; set; }
}
}

@ -14,6 +14,7 @@ using NLog;
using NzbDrone.Common.Http; using NzbDrone.Common.Http;
using NzbDrone.Core.Annotations; using NzbDrone.Core.Annotations;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.Indexers.Settings;
using NzbDrone.Core.IndexerSearch.Definitions; using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
@ -22,7 +23,7 @@ using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.Definitions; namespace NzbDrone.Core.Indexers.Definitions;
public class MoreThanTV : TorrentIndexerBase<MoreThanTVSettings> public class MoreThanTV : TorrentIndexerBase<CookieTorrentBaseSettings>
{ {
public override string Name => "MoreThanTV"; public override string Name => "MoreThanTV";
public override string[] IndexerUrls => new[] { "https://www.morethantv.me/" }; public override string[] IndexerUrls => new[] { "https://www.morethantv.me/" };
@ -74,12 +75,12 @@ public class MoreThanTV : TorrentIndexerBase<MoreThanTVSettings>
public class MoreThanTVRequestGenerator : IIndexerRequestGenerator public class MoreThanTVRequestGenerator : IIndexerRequestGenerator
{ {
private MoreThanTVSettings Settings { get; } private CookieTorrentBaseSettings Settings { get; }
private IndexerCapabilities Capabilities { get; } private IndexerCapabilities Capabilities { get; }
private NameValueCollection BrowserHeaders { get; } private NameValueCollection BrowserHeaders { get; }
public MoreThanTVRequestGenerator(MoreThanTVSettings settings, IndexerCapabilities capabilities) public MoreThanTVRequestGenerator(CookieTorrentBaseSettings settings, IndexerCapabilities capabilities)
{ {
Settings = settings; Settings = settings;
Capabilities = capabilities; Capabilities = capabilities;
@ -170,7 +171,7 @@ public class MoreThanTVRequestGenerator : IIndexerRequestGenerator
public class MoreThanTVParser : IParseIndexerResponse public class MoreThanTVParser : IParseIndexerResponse
{ {
public MoreThanTVSettings Settings { get; init; } public CookieTorrentBaseSettings Settings { get; init; }
public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse) public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse)
{ {
@ -304,35 +305,3 @@ public class MoreThanTVParser : IParseIndexerResponse
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; } public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
} }
public class MoreThanTVSettingsValidator : AbstractValidator<MoreThanTVSettings>
{
public MoreThanTVSettingsValidator()
{
RuleFor(c => c.Cookie).NotEmpty();
}
}
public class MoreThanTVSettings : IIndexerSettings
{
private static readonly MoreThanTVSettingsValidator Validator = new ();
public MoreThanTVSettings()
{
Cookie = "";
}
[FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2, Label = "Cookie", HelpText = "Enter the cookies for the site, just copy everything after 'cookie:' from the request headers to the site", HelpLink = "https://wiki.servarr.com/prowlarr/faq#finding-cookies")]
public string Cookie { get; set; }
[FieldDefinition(3)]
public IndexerBaseSettings BaseSettings { get; set; } = new IndexerBaseSettings();
public NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));
}
}

@ -14,6 +14,7 @@ using NzbDrone.Common.Serializer;
using NzbDrone.Core.Annotations; using NzbDrone.Core.Annotations;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.Indexers.Exceptions; using NzbDrone.Core.Indexers.Exceptions;
using NzbDrone.Core.Indexers.Settings;
using NzbDrone.Core.IndexerSearch.Definitions; using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
@ -434,7 +435,7 @@ namespace NzbDrone.Core.Indexers.Definitions
} }
} }
public class MyAnonamouseSettings : IIndexerSettings public class MyAnonamouseSettings : NoAuthTorrentBaseSettings
{ {
private static readonly MyAnonamouseSettingsValidator Validator = new MyAnonamouseSettingsValidator(); private static readonly MyAnonamouseSettingsValidator Validator = new MyAnonamouseSettingsValidator();
@ -443,9 +444,6 @@ namespace NzbDrone.Core.Indexers.Definitions
MamId = ""; MamId = "";
} }
[FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2, Label = "Mam Id", HelpText = "Mam Session Id (Created Under Preferences -> Security)")] [FieldDefinition(2, Label = "Mam Id", HelpText = "Mam Session Id (Created Under Preferences -> Security)")]
public string MamId { get; set; } public string MamId { get; set; }
@ -455,10 +453,7 @@ namespace NzbDrone.Core.Indexers.Definitions
[FieldDefinition(4, Type = FieldType.Checkbox, Label = "Freeleech", HelpText = "Use freeleech token for download")] [FieldDefinition(4, Type = FieldType.Checkbox, Label = "Freeleech", HelpText = "Use freeleech token for download")]
public bool Freeleech { get; set; } public bool Freeleech { get; set; }
[FieldDefinition(5)] public override NzbDroneValidationResult Validate()
public IndexerBaseSettings BaseSettings { get; set; } = new IndexerBaseSettings();
public NzbDroneValidationResult Validate()
{ {
return new NzbDroneValidationResult(Validator.Validate(this)); return new NzbDroneValidationResult(Validator.Validate(this));
} }

@ -12,6 +12,7 @@ using NLog;
using NzbDrone.Common.Http; using NzbDrone.Common.Http;
using NzbDrone.Core.Annotations; using NzbDrone.Core.Annotations;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.Indexers.Settings;
using NzbDrone.Core.IndexerSearch.Definitions; using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
@ -267,44 +268,14 @@ namespace NzbDrone.Core.Indexers.Definitions
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; } public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
} }
public class NebulanceSettingsValidator : AbstractValidator<NebulanceSettings> public class NebulanceSettings : UserPassTorrentBaseSettings
{ {
public NebulanceSettingsValidator()
{
RuleFor(c => c.Username).NotEmpty();
RuleFor(c => c.Password).NotEmpty();
}
}
public class NebulanceSettings : IIndexerSettings
{
private static readonly NebulanceSettingsValidator Validator = new NebulanceSettingsValidator();
public NebulanceSettings() public NebulanceSettings()
{ {
Username = "";
Password = "";
TwoFactorAuth = ""; TwoFactorAuth = "";
} }
[FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2, Label = "Username", HelpText = "Site Username", Privacy = PrivacyLevel.UserName)]
public string Username { get; set; }
[FieldDefinition(3, Label = "Password", HelpText = "Site Password", Privacy = PrivacyLevel.Password, Type = FieldType.Password)]
public string Password { get; set; }
[FieldDefinition(4, Label = "Two Factor Auth", HelpText = "Two-Factor Auth")] [FieldDefinition(4, Label = "Two Factor Auth", HelpText = "Two-Factor Auth")]
public string TwoFactorAuth { get; set; } public string TwoFactorAuth { get; set; }
[FieldDefinition(5)]
public IndexerBaseSettings BaseSettings { get; set; } = new IndexerBaseSettings();
public NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));
}
} }
} }

@ -16,6 +16,7 @@ using NzbDrone.Common.Http;
using NzbDrone.Core.Annotations; using NzbDrone.Core.Annotations;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.Indexers.Exceptions; using NzbDrone.Core.Indexers.Exceptions;
using NzbDrone.Core.Indexers.Settings;
using NzbDrone.Core.IndexerSearch.Definitions; using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
@ -393,43 +394,13 @@ namespace NzbDrone.Core.Indexers.Definitions
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; } public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
} }
public class NorBitsSettingsValidator : AbstractValidator<NorBitsSettings> public class NorBitsSettings : UserPassTorrentBaseSettings
{ {
public NorBitsSettingsValidator()
{
RuleFor(c => c.Username).NotEmpty();
RuleFor(c => c.Password).NotEmpty();
}
}
public class NorBitsSettings : IIndexerSettings
{
private static readonly NorBitsSettingsValidator Validator = new NorBitsSettingsValidator();
public NorBitsSettings() public NorBitsSettings()
{ {
Username = "";
Password = "";
} }
[FieldDefinition(1, Label = "Base Url", HelpText = "Select which baseurl Prowlarr will use for requests to the site", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls")]
public string BaseUrl { get; set; }
[FieldDefinition(2, Label = "Username", HelpText = "Site Username", Privacy = PrivacyLevel.UserName)]
public string Username { get; set; }
[FieldDefinition(3, Label = "Password", HelpText = "Site Password", Privacy = PrivacyLevel.Password, Type = FieldType.Password)]
public string Password { get; set; }
[FieldDefinition(4, Label = "Use Full Search", HelpText = "Use Full Search from Site", Type = FieldType.Checkbox)] [FieldDefinition(4, Label = "Use Full Search", HelpText = "Use Full Search from Site", Type = FieldType.Checkbox)]
public bool UseFullSearch { get; set; } public bool UseFullSearch { get; set; }
[FieldDefinition(5)]
public IndexerBaseSettings BaseSettings { get; set; } = new IndexerBaseSettings();
public NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));
}
} }
} }

@ -1,5 +1,6 @@
using FluentValidation; using FluentValidation;
using NzbDrone.Core.Annotations; using NzbDrone.Core.Annotations;
using NzbDrone.Core.Indexers.Settings;
using NzbDrone.Core.Validation; using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.PassThePopcorn namespace NzbDrone.Core.Indexers.PassThePopcorn
@ -13,7 +14,7 @@ namespace NzbDrone.Core.Indexers.PassThePopcorn
} }
} }
public class PassThePopcornSettings : IIndexerSettings public class PassThePopcornSettings : NoAuthTorrentBaseSettings
{ {
private static readonly PassThePopcornSettingsValidator Validator = new PassThePopcornSettingsValidator(); private static readonly PassThePopcornSettingsValidator Validator = new PassThePopcornSettingsValidator();
@ -21,19 +22,13 @@ namespace NzbDrone.Core.Indexers.PassThePopcorn
{ {
} }
[FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2, Label = "APIUser", HelpText = "These settings are found in your PassThePopcorn security settings (Edit Profile > Security).", Privacy = PrivacyLevel.UserName)] [FieldDefinition(2, Label = "APIUser", HelpText = "These settings are found in your PassThePopcorn security settings (Edit Profile > Security).", Privacy = PrivacyLevel.UserName)]
public string APIUser { get; set; } public string APIUser { get; set; }
[FieldDefinition(3, Label = "API Key", HelpText = "Site API Key", Privacy = PrivacyLevel.ApiKey)] [FieldDefinition(3, Label = "API Key", HelpText = "Site API Key", Privacy = PrivacyLevel.ApiKey)]
public string APIKey { get; set; } public string APIKey { get; set; }
[FieldDefinition(4)] public override NzbDroneValidationResult Validate()
public IndexerBaseSettings BaseSettings { get; set; } = new IndexerBaseSettings();
public NzbDroneValidationResult Validate()
{ {
return new NzbDroneValidationResult(Validator.Validate(this)); return new NzbDroneValidationResult(Validator.Validate(this));
} }

@ -12,6 +12,7 @@ using NzbDrone.Common.Http;
using NzbDrone.Core.Annotations; using NzbDrone.Core.Annotations;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.Indexers.Exceptions; using NzbDrone.Core.Indexers.Exceptions;
using NzbDrone.Core.Indexers.Settings;
using NzbDrone.Core.IndexerSearch.Definitions; using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
@ -420,43 +421,13 @@ namespace NzbDrone.Core.Indexers.Definitions
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; } public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
} }
public class PornoLabSettingsValidator : AbstractValidator<PornoLabSettings> public class PornoLabSettings : UserPassTorrentBaseSettings
{ {
public PornoLabSettingsValidator()
{
RuleFor(c => c.Username).NotEmpty();
RuleFor(c => c.Password).NotEmpty();
}
}
public class PornoLabSettings : IIndexerSettings
{
private static readonly PornoLabSettingsValidator Validator = new PornoLabSettingsValidator();
public PornoLabSettings() public PornoLabSettings()
{ {
Username = "";
Password = "";
} }
[FieldDefinition(1, Label = "Base Url", HelpText = "Select which baseurl Prowlarr will use for requests to the site", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls")]
public string BaseUrl { get; set; }
[FieldDefinition(2, Label = "Username", HelpText = "Site Username", Privacy = PrivacyLevel.UserName)]
public string Username { get; set; }
[FieldDefinition(3, Label = "Password", HelpText = "Site Password", Privacy = PrivacyLevel.Password, Type = FieldType.Password)]
public string Password { get; set; }
[FieldDefinition(4, Label = "Strip Russian Letters", HelpLink = "Strip Cyrillic letters from release names", Type = FieldType.Checkbox)] [FieldDefinition(4, Label = "Strip Russian Letters", HelpLink = "Strip Cyrillic letters from release names", Type = FieldType.Checkbox)]
public bool StripRussianLetters { get; set; } public bool StripRussianLetters { get; set; }
[FieldDefinition(5)]
public IndexerBaseSettings BaseSettings { get; set; } = new IndexerBaseSettings();
public NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));
}
} }
} }

@ -13,6 +13,7 @@ using NzbDrone.Common.Http;
using NzbDrone.Core.Annotations; using NzbDrone.Core.Annotations;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.Indexers.Exceptions; using NzbDrone.Core.Indexers.Exceptions;
using NzbDrone.Core.Indexers.Settings;
using NzbDrone.Core.IndexerSearch.Definitions; using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
@ -387,7 +388,7 @@ namespace NzbDrone.Core.Indexers.Definitions
} }
} }
public class PreToMeSettings : IIndexerSettings public class PreToMeSettings : NoAuthTorrentBaseSettings
{ {
private static readonly PreToMeSettingsValidator Validator = new PreToMeSettingsValidator(); private static readonly PreToMeSettingsValidator Validator = new PreToMeSettingsValidator();
@ -398,9 +399,6 @@ namespace NzbDrone.Core.Indexers.Definitions
Password = ""; Password = "";
} }
[FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2, Label = "Pin", HelpText = "Site Pin", Privacy = PrivacyLevel.Password)] [FieldDefinition(2, Label = "Pin", HelpText = "Site Pin", Privacy = PrivacyLevel.Password)]
public string Pin { get; set; } public string Pin { get; set; }
@ -410,10 +408,7 @@ namespace NzbDrone.Core.Indexers.Definitions
[FieldDefinition(4, Label = "Password", HelpText = "Site Password", Privacy = PrivacyLevel.Password, Type = FieldType.Password)] [FieldDefinition(4, Label = "Password", HelpText = "Site Password", Privacy = PrivacyLevel.Password, Type = FieldType.Password)]
public string Password { get; set; } public string Password { get; set; }
[FieldDefinition(5)] public override NzbDroneValidationResult Validate()
public IndexerBaseSettings BaseSettings { get; set; } = new IndexerBaseSettings();
public NzbDroneValidationResult Validate()
{ {
return new NzbDroneValidationResult(Validator.Validate(this)); return new NzbDroneValidationResult(Validator.Validate(this));
} }

@ -1,40 +1,21 @@
using FluentValidation; using FluentValidation;
using NzbDrone.Core.Annotations; using NzbDrone.Core.Annotations;
using NzbDrone.Core.Indexers.Settings;
using NzbDrone.Core.Validation; using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.Rarbg namespace NzbDrone.Core.Indexers.Rarbg
{ {
public class RarbgSettingsValidator : AbstractValidator<RarbgSettings> public class RarbgSettings : NoAuthTorrentBaseSettings
{ {
public RarbgSettingsValidator()
{
}
}
public class RarbgSettings : IIndexerSettings
{
private static readonly RarbgSettingsValidator Validator = new RarbgSettingsValidator();
public RarbgSettings() public RarbgSettings()
{ {
RankedOnly = false; RankedOnly = false;
} }
[FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2, Type = FieldType.Checkbox, Label = "Ranked Only", HelpText = "Only include ranked results.")] [FieldDefinition(2, Type = FieldType.Checkbox, Label = "Ranked Only", HelpText = "Only include ranked results.")]
public bool RankedOnly { get; set; } public bool RankedOnly { get; set; }
[FieldDefinition(3, Type = FieldType.Captcha, Label = "CAPTCHA Token", HelpText = "CAPTCHA Clearance token used to handle CloudFlare Anti-DDOS measures on shared-ip VPNs.")] [FieldDefinition(3, Type = FieldType.Captcha, Label = "CAPTCHA Token", HelpText = "CAPTCHA Clearance token used to handle CloudFlare Anti-DDOS measures on shared-ip VPNs.")]
public string CaptchaToken { get; set; } public string CaptchaToken { get; set; }
[FieldDefinition(4)]
public IndexerBaseSettings BaseSettings { get; set; } = new IndexerBaseSettings();
public NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));
}
} }
} }

@ -13,6 +13,7 @@ using NzbDrone.Core.Annotations;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.Indexers.Exceptions; using NzbDrone.Core.Indexers.Exceptions;
using NzbDrone.Core.Indexers.Gazelle; using NzbDrone.Core.Indexers.Gazelle;
using NzbDrone.Core.Indexers.Settings;
using NzbDrone.Core.IndexerSearch.Definitions; using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Parser.Model; using NzbDrone.Core.Parser.Model;
@ -338,7 +339,7 @@ namespace NzbDrone.Core.Indexers.Definitions
} }
} }
public class RedactedSettings : IIndexerSettings public class RedactedSettings : NoAuthTorrentBaseSettings
{ {
private static readonly RedactedSettingsValidator Validator = new RedactedSettingsValidator(); private static readonly RedactedSettingsValidator Validator = new RedactedSettingsValidator();
@ -349,21 +350,15 @@ namespace NzbDrone.Core.Indexers.Definitions
UseFreeleechToken = false; UseFreeleechToken = false;
} }
[FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2, Label = "API Key", HelpText = "API Key from the Site (Found in Settings => Access Settings)", Privacy = PrivacyLevel.ApiKey)] [FieldDefinition(2, Label = "API Key", HelpText = "API Key from the Site (Found in Settings => Access Settings)", Privacy = PrivacyLevel.ApiKey)]
public string Apikey { get; set; } public string Apikey { get; set; }
[FieldDefinition(3, Label = "Use Freeleech Tokens", HelpText = "Use freeleech tokens when available", Type = FieldType.Checkbox)] [FieldDefinition(3, Label = "Use Freeleech Tokens", HelpText = "Use freeleech tokens when available", Type = FieldType.Checkbox)]
public bool UseFreeleechToken { get; set; } public bool UseFreeleechToken { get; set; }
[FieldDefinition(4)]
public IndexerBaseSettings BaseSettings { get; set; } = new IndexerBaseSettings();
public string Passkey { get; set; } public string Passkey { get; set; }
public NzbDroneValidationResult Validate() public override NzbDroneValidationResult Validate()
{ {
return new NzbDroneValidationResult(Validator.Validate(this)); return new NzbDroneValidationResult(Validator.Validate(this));
} }

@ -13,6 +13,7 @@ using NzbDrone.Common.Http;
using NzbDrone.Core.Annotations; using NzbDrone.Core.Annotations;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.Indexers.Exceptions; using NzbDrone.Core.Indexers.Exceptions;
using NzbDrone.Core.Indexers.Settings;
using NzbDrone.Core.IndexerSearch.Definitions; using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
@ -21,7 +22,7 @@ using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.Definitions namespace NzbDrone.Core.Indexers.Definitions
{ {
public class RevolutionTT : TorrentIndexerBase<RevolutionTTSettings> public class RevolutionTT : TorrentIndexerBase<UserPassTorrentBaseSettings>
{ {
public override string Name => "RevolutionTT"; public override string Name => "RevolutionTT";
@ -154,7 +155,7 @@ namespace NzbDrone.Core.Indexers.Definitions
public class RevolutionTTRequestGenerator : IIndexerRequestGenerator public class RevolutionTTRequestGenerator : IIndexerRequestGenerator
{ {
public RevolutionTTSettings Settings { get; set; } public UserPassTorrentBaseSettings Settings { get; set; }
public IndexerCapabilities Capabilities { get; set; } public IndexerCapabilities Capabilities { get; set; }
public RevolutionTTRequestGenerator() public RevolutionTTRequestGenerator()
@ -247,10 +248,10 @@ namespace NzbDrone.Core.Indexers.Definitions
public class RevolutionTTParser : IParseIndexerResponse public class RevolutionTTParser : IParseIndexerResponse
{ {
private readonly RevolutionTTSettings _settings; private readonly UserPassTorrentBaseSettings _settings;
private readonly IndexerCapabilitiesCategories _categories; private readonly IndexerCapabilitiesCategories _categories;
public RevolutionTTParser(RevolutionTTSettings settings, IndexerCapabilitiesCategories categories) public RevolutionTTParser(UserPassTorrentBaseSettings settings, IndexerCapabilitiesCategories categories)
{ {
_settings = settings; _settings = settings;
_categories = categories; _categories = categories;
@ -327,41 +328,4 @@ namespace NzbDrone.Core.Indexers.Definitions
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; } public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
} }
public class RevolutionTTSettingsValidator : AbstractValidator<RevolutionTTSettings>
{
public RevolutionTTSettingsValidator()
{
RuleFor(c => c.Username).NotEmpty();
RuleFor(c => c.Password).NotEmpty();
}
}
public class RevolutionTTSettings : IIndexerSettings
{
private static readonly RevolutionTTSettingsValidator Validator = new RevolutionTTSettingsValidator();
public RevolutionTTSettings()
{
Username = "";
Password = "";
}
[FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2, Label = "Username", HelpText = "Site Username", Privacy = PrivacyLevel.UserName)]
public string Username { get; set; }
[FieldDefinition(3, Label = "Password", HelpText = "Site Password", Privacy = PrivacyLevel.Password, Type = FieldType.Password)]
public string Password { get; set; }
[FieldDefinition(4)]
public IndexerBaseSettings BaseSettings { get; set; } = new IndexerBaseSettings();
public NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));
}
}
} }

@ -14,6 +14,7 @@ using NzbDrone.Common.Http;
using NzbDrone.Core.Annotations; using NzbDrone.Core.Annotations;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.Indexers.Exceptions; using NzbDrone.Core.Indexers.Exceptions;
using NzbDrone.Core.Indexers.Settings;
using NzbDrone.Core.IndexerSearch.Definitions; using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
@ -1728,44 +1729,14 @@ namespace NzbDrone.Core.Indexers.Definitions
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; } public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
} }
public class RuTrackerSettingsValidator : AbstractValidator<RuTrackerSettings> public class RuTrackerSettings : UserPassTorrentBaseSettings
{ {
public RuTrackerSettingsValidator()
{
RuleFor(c => c.Username).NotEmpty();
RuleFor(c => c.Password).NotEmpty();
}
}
public class RuTrackerSettings : IIndexerSettings
{
private static readonly RuTrackerSettingsValidator Validator = new RuTrackerSettingsValidator();
public RuTrackerSettings() public RuTrackerSettings()
{ {
Username = "";
Password = "";
RussianLetters = false; RussianLetters = false;
} }
[FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2, Label = "Username", Advanced = false, HelpText = "Site Username")]
public string Username { get; set; }
[FieldDefinition(3, Label = "Password", Type = FieldType.Password, Privacy = PrivacyLevel.Password, HelpText = "Site Password")]
public string Password { get; set; }
[FieldDefinition(4, Label = "Strip Russian letters", Type = FieldType.Checkbox, SelectOptionsProviderAction = "stripRussian", HelpText = "Removes russian letters")] [FieldDefinition(4, Label = "Strip Russian letters", Type = FieldType.Checkbox, SelectOptionsProviderAction = "stripRussian", HelpText = "Removes russian letters")]
public bool RussianLetters { get; set; } public bool RussianLetters { get; set; }
[FieldDefinition(5)]
public IndexerBaseSettings BaseSettings { get; set; } = new IndexerBaseSettings();
public NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));
}
} }
} }

@ -12,6 +12,7 @@ using NzbDrone.Common.Http;
using NzbDrone.Core.Annotations; using NzbDrone.Core.Annotations;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.Indexers.Exceptions; using NzbDrone.Core.Indexers.Exceptions;
using NzbDrone.Core.Indexers.Settings;
using NzbDrone.Core.IndexerSearch.Definitions; using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
@ -240,7 +241,7 @@ namespace NzbDrone.Core.Indexers.Definitions
} }
} }
public class SceneHDSettings : IIndexerSettings public class SceneHDSettings : NoAuthTorrentBaseSettings
{ {
private static readonly SceneHDSettingsValidator Validator = new SceneHDSettingsValidator(); private static readonly SceneHDSettingsValidator Validator = new SceneHDSettingsValidator();
@ -249,16 +250,10 @@ namespace NzbDrone.Core.Indexers.Definitions
Passkey = ""; Passkey = "";
} }
[FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2, Label = "Passkey", Advanced = false, HelpText = "Site Passkey")] [FieldDefinition(2, Label = "Passkey", Advanced = false, HelpText = "Site Passkey")]
public string Passkey { get; set; } public string Passkey { get; set; }
[FieldDefinition(3)] public override NzbDroneValidationResult Validate()
public IndexerBaseSettings BaseSettings { get; set; } = new IndexerBaseSettings();
public NzbDroneValidationResult Validate()
{ {
return new NzbDroneValidationResult(Validator.Validate(this)); return new NzbDroneValidationResult(Validator.Validate(this));
} }

@ -11,6 +11,7 @@ using NzbDrone.Common.Extensions;
using NzbDrone.Common.Http; using NzbDrone.Common.Http;
using NzbDrone.Core.Annotations; using NzbDrone.Core.Annotations;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.Indexers.Settings;
using NzbDrone.Core.IndexerSearch.Definitions; using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
@ -277,38 +278,13 @@ namespace NzbDrone.Core.Indexers.Definitions
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; } public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
} }
public class SceneTimeSettingsValidator : AbstractValidator<SceneTimeSettings> public class SceneTimeSettings : CookieTorrentBaseSettings
{ {
public SceneTimeSettingsValidator()
{
RuleFor(c => c.Cookie).NotEmpty();
}
}
public class SceneTimeSettings : IIndexerSettings
{
private static readonly SceneTimeSettingsValidator Validator = new SceneTimeSettingsValidator();
public SceneTimeSettings() public SceneTimeSettings()
{ {
Cookie = "";
} }
[FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2, Label = "Cookie", HelpText = "Login cookie from website")]
public string Cookie { get; set; }
[FieldDefinition(3, Label = "FreeLeech Only", Type = FieldType.Checkbox, Advanced = true, HelpText = "Search Freeleech torrents only")] [FieldDefinition(3, Label = "FreeLeech Only", Type = FieldType.Checkbox, Advanced = true, HelpText = "Search Freeleech torrents only")]
public bool FreeLeechOnly { get; set; } public bool FreeLeechOnly { get; set; }
[FieldDefinition(4)]
public IndexerBaseSettings BaseSettings { get; set; } = new IndexerBaseSettings();
public NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));
}
} }
} }

@ -1,59 +0,0 @@
using System;
using System.Collections.Generic;
using NLog;
using NzbDrone.Common.Http;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.Indexers.Definitions.UNIT3D;
using NzbDrone.Core.Messaging.Events;
namespace NzbDrone.Core.Indexers.Definitions
{
[Obsolete("Moved to YML for Cardigann v3")]
public class ShareIsland : Unit3dBase
{
public override string Name => "ShareIsland";
public override string[] IndexerUrls => new string[] { "https://shareisland.org/" };
public override string Description => "A general italian tracker.";
public override string Language => "it-IT";
public override IndexerPrivacy Privacy => IndexerPrivacy.Private;
public ShareIsland(IIndexerHttpClient httpClient, IEventAggregator eventAggregator, IIndexerStatusService indexerStatusService, IConfigService configService, Logger logger)
: base(httpClient, eventAggregator, indexerStatusService, configService, logger)
{
}
protected override IndexerCapabilities SetCapabilities()
{
var caps = new IndexerCapabilities
{
TvSearchParams = new List<TvSearchParam>
{
TvSearchParam.Q, TvSearchParam.Season, TvSearchParam.Ep, TvSearchParam.ImdbId, TvSearchParam.TvdbId
},
MovieSearchParams = new List<MovieSearchParam>
{
MovieSearchParam.Q, MovieSearchParam.ImdbId, MovieSearchParam.TmdbId
},
MusicSearchParams = new List<MusicSearchParam>
{
MusicSearchParam.Q
},
BookSearchParams = new List<BookSearchParam>
{
BookSearchParam.Q
}
};
caps.Categories.AddCategoryMapping(1, NewznabStandardCategory.Movies, "Movie");
caps.Categories.AddCategoryMapping(2, NewznabStandardCategory.TV, "Serie TV");
caps.Categories.AddCategoryMapping(15, NewznabStandardCategory.BooksEBook, "Ebook");
caps.Categories.AddCategoryMapping(17, NewznabStandardCategory.BooksMags, "Riviste e Giornali");
caps.Categories.AddCategoryMapping(19, NewznabStandardCategory.XXX, "XXX");
caps.Categories.AddCategoryMapping(3, NewznabStandardCategory.Audio, "Music");
caps.Categories.AddCategoryMapping(7, NewznabStandardCategory.PCGames, "Games");
caps.Categories.AddCategoryMapping(23, NewznabStandardCategory.PC, "Software");
return caps;
}
}
}

@ -10,6 +10,7 @@ using NzbDrone.Common.Http;
using NzbDrone.Core.Annotations; using NzbDrone.Core.Annotations;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.Indexers.Exceptions; using NzbDrone.Core.Indexers.Exceptions;
using NzbDrone.Core.Indexers.Settings;
using NzbDrone.Core.IndexerSearch.Definitions; using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
@ -18,7 +19,7 @@ using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.Definitions namespace NzbDrone.Core.Indexers.Definitions
{ {
public class Shizaproject : TorrentIndexerBase<ShizaprojectSettings> public class Shizaproject : TorrentIndexerBase<NoAuthTorrentBaseSettings>
{ {
public override string Name => "ShizaProject"; public override string Name => "ShizaProject";
public override string[] IndexerUrls => new string[] { "https://shiza-project.com/" }; public override string[] IndexerUrls => new string[] { "https://shiza-project.com/" };
@ -69,7 +70,7 @@ namespace NzbDrone.Core.Indexers.Definitions
public class ShizaprojectRequestGenerator : IIndexerRequestGenerator public class ShizaprojectRequestGenerator : IIndexerRequestGenerator
{ {
public ShizaprojectSettings Settings { get; set; } public NoAuthTorrentBaseSettings Settings { get; set; }
public IndexerCapabilities Capabilities { get; set; } public IndexerCapabilities Capabilities { get; set; }
public ShizaprojectRequestGenerator() public ShizaprojectRequestGenerator()
@ -172,10 +173,10 @@ namespace NzbDrone.Core.Indexers.Definitions
public class ShizaprojectParser : IParseIndexerResponse public class ShizaprojectParser : IParseIndexerResponse
{ {
private readonly ShizaprojectSettings _settings; private readonly NoAuthTorrentBaseSettings _settings;
private readonly IndexerCapabilitiesCategories _categories; private readonly IndexerCapabilitiesCategories _categories;
public ShizaprojectParser(ShizaprojectSettings settings, IndexerCapabilitiesCategories categories) public ShizaprojectParser(NoAuthTorrentBaseSettings settings, IndexerCapabilitiesCategories categories)
{ {
_settings = settings; _settings = settings;
_categories = categories; _categories = categories;
@ -266,29 +267,6 @@ namespace NzbDrone.Core.Indexers.Definitions
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; } public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
} }
public class ShizaprojectSettingsValidator : AbstractValidator<ShizaprojectSettings>
{
public ShizaprojectSettingsValidator()
{
}
}
public class ShizaprojectSettings : IIndexerSettings
{
private static readonly ShizaprojectSettingsValidator Validator = new ShizaprojectSettingsValidator();
[FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2)]
public IndexerBaseSettings BaseSettings { get; set; } = new IndexerBaseSettings();
public NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));
}
}
public class ShizaprojectReleasesResponse public class ShizaprojectReleasesResponse
{ {
public ShizaprojectData Data { get; set; } public ShizaprojectData Data { get; set; }

@ -8,6 +8,7 @@ using NLog;
using NzbDrone.Common.Http; using NzbDrone.Common.Http;
using NzbDrone.Core.Annotations; using NzbDrone.Core.Annotations;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.Indexers.Settings;
using NzbDrone.Core.IndexerSearch.Definitions; using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Parser.Model; using NzbDrone.Core.Parser.Model;
@ -16,7 +17,7 @@ using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.Definitions namespace NzbDrone.Core.Indexers.Definitions
{ {
public class ShowRSS : TorrentIndexerBase<ShowRSSSettings> public class ShowRSS : TorrentIndexerBase<NoAuthTorrentBaseSettings>
{ {
public override string Name => "ShowRSS"; public override string Name => "ShowRSS";
public override string[] IndexerUrls => new string[] { "https://showrss.info/" }; public override string[] IndexerUrls => new string[] { "https://showrss.info/" };
@ -62,7 +63,7 @@ namespace NzbDrone.Core.Indexers.Definitions
public class ShowRSSRequestGenerator : IIndexerRequestGenerator public class ShowRSSRequestGenerator : IIndexerRequestGenerator
{ {
public ShowRSSSettings Settings { get; set; } public NoAuthTorrentBaseSettings Settings { get; set; }
public IndexerCapabilities Capabilities { get; set; } public IndexerCapabilities Capabilities { get; set; }
public ShowRSSRequestGenerator() public ShowRSSRequestGenerator()
@ -123,10 +124,10 @@ namespace NzbDrone.Core.Indexers.Definitions
public class ShowRSSParser : IParseIndexerResponse public class ShowRSSParser : IParseIndexerResponse
{ {
private readonly ShowRSSSettings _settings; private readonly NoAuthTorrentBaseSettings _settings;
private string BrowseUrl => _settings.BaseUrl + "browse/"; private string BrowseUrl => _settings.BaseUrl + "browse/";
public ShowRSSParser(ShowRSSSettings settings) public ShowRSSParser(NoAuthTorrentBaseSettings settings)
{ {
_settings = settings; _settings = settings;
} }
@ -179,24 +180,4 @@ namespace NzbDrone.Core.Indexers.Definitions
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; } public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
} }
public class ShowRSSSettingsValidator : AbstractValidator<ShowRSSSettings>
{
}
public class ShowRSSSettings : IIndexerSettings
{
private static readonly ShowRSSSettingsValidator Validator = new ShowRSSSettingsValidator();
[FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2)]
public IndexerBaseSettings BaseSettings { get; set; } = new IndexerBaseSettings();
public NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));
}
}
} }

@ -16,6 +16,7 @@ using NzbDrone.Core.Annotations;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.Exceptions; using NzbDrone.Core.Exceptions;
using NzbDrone.Core.Indexers.Exceptions; using NzbDrone.Core.Indexers.Exceptions;
using NzbDrone.Core.Indexers.Settings;
using NzbDrone.Core.IndexerSearch.Definitions; using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
@ -406,7 +407,7 @@ namespace NzbDrone.Core.Indexers.Definitions
} }
} }
public class SpeedAppSettings : IIndexerSettings public class SpeedAppSettings : NoAuthTorrentBaseSettings
{ {
private static readonly SpeedAppSettingsValidator Validator = new (); private static readonly SpeedAppSettingsValidator Validator = new ();
@ -416,9 +417,6 @@ namespace NzbDrone.Core.Indexers.Definitions
Password = ""; Password = "";
} }
[FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2, Label = "Email", HelpText = "Site Email", Privacy = PrivacyLevel.UserName)] [FieldDefinition(2, Label = "Email", HelpText = "Site Email", Privacy = PrivacyLevel.UserName)]
public string Email { get; set; } public string Email { get; set; }
@ -428,10 +426,7 @@ namespace NzbDrone.Core.Indexers.Definitions
[FieldDefinition(4, Label = "API Key", Hidden = HiddenType.Hidden)] [FieldDefinition(4, Label = "API Key", Hidden = HiddenType.Hidden)]
public string ApiKey { get; set; } public string ApiKey { get; set; }
[FieldDefinition(5)] public override NzbDroneValidationResult Validate()
public IndexerBaseSettings BaseSettings { get; set; } = new IndexerBaseSettings();
public NzbDroneValidationResult Validate()
{ {
return new NzbDroneValidationResult(Validator.Validate(this)); return new NzbDroneValidationResult(Validator.Validate(this));
} }

@ -14,6 +14,7 @@ using NzbDrone.Common.Http;
using NzbDrone.Core.Annotations; using NzbDrone.Core.Annotations;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.Indexers.Exceptions; using NzbDrone.Core.Indexers.Exceptions;
using NzbDrone.Core.Indexers.Settings;
using NzbDrone.Core.IndexerSearch.Definitions; using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
@ -22,7 +23,7 @@ using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.Definitions namespace NzbDrone.Core.Indexers.Definitions
{ {
public class SpeedCD : TorrentIndexerBase<SpeedCDSettings> public class SpeedCD : TorrentIndexerBase<UserPassTorrentBaseSettings>
{ {
public override string Name => "SpeedCD"; public override string Name => "SpeedCD";
public override string[] IndexerUrls => new string[] public override string[] IndexerUrls => new string[]
@ -181,7 +182,7 @@ namespace NzbDrone.Core.Indexers.Definitions
public class SpeedCDRequestGenerator : IIndexerRequestGenerator public class SpeedCDRequestGenerator : IIndexerRequestGenerator
{ {
public SpeedCDSettings Settings { get; set; } public UserPassTorrentBaseSettings Settings { get; set; }
public IndexerCapabilities Capabilities { get; set; } public IndexerCapabilities Capabilities { get; set; }
public Encoding Encoding { get; set; } public Encoding Encoding { get; set; }
@ -271,10 +272,10 @@ namespace NzbDrone.Core.Indexers.Definitions
public class SpeedCDParser : IParseIndexerResponse public class SpeedCDParser : IParseIndexerResponse
{ {
private readonly SpeedCDSettings _settings; private readonly UserPassTorrentBaseSettings _settings;
private readonly IndexerCapabilitiesCategories _categories; private readonly IndexerCapabilitiesCategories _categories;
public SpeedCDParser(SpeedCDSettings settings, IndexerCapabilitiesCategories categories) public SpeedCDParser(UserPassTorrentBaseSettings settings, IndexerCapabilitiesCategories categories)
{ {
_settings = settings; _settings = settings;
_categories = categories; _categories = categories;
@ -332,41 +333,4 @@ namespace NzbDrone.Core.Indexers.Definitions
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; } public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
} }
public class SpeedCDSettingsValidator : AbstractValidator<SpeedCDSettings>
{
public SpeedCDSettingsValidator()
{
RuleFor(c => c.Username).NotEmpty();
RuleFor(c => c.Password).NotEmpty();
}
}
public class SpeedCDSettings : IIndexerSettings
{
private static readonly SpeedCDSettingsValidator Validator = new SpeedCDSettingsValidator();
public SpeedCDSettings()
{
Username = "";
Password = "";
}
[FieldDefinition(1, Label = "Base Url", HelpText = "Select which baseurl Prowlarr will use for requests to the site", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls")]
public string BaseUrl { get; set; }
[FieldDefinition(2, Label = "Username", HelpText = "Site Username", Privacy = PrivacyLevel.UserName)]
public string Username { get; set; }
[FieldDefinition(3, Label = "Password", HelpText = "Site Password", Privacy = PrivacyLevel.Password, Type = FieldType.Password)]
public string Password { get; set; }
[FieldDefinition(4)]
public IndexerBaseSettings BaseSettings { get; set; } = new IndexerBaseSettings();
public NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));
}
}
} }

@ -11,6 +11,7 @@ using NzbDrone.Common.Http;
using NzbDrone.Core.Annotations; using NzbDrone.Core.Annotations;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.Indexers.Exceptions; using NzbDrone.Core.Indexers.Exceptions;
using NzbDrone.Core.Indexers.Settings;
using NzbDrone.Core.IndexerSearch.Definitions; using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
@ -19,7 +20,7 @@ using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.Definitions namespace NzbDrone.Core.Indexers.Definitions
{ {
public class SubsPlease : TorrentIndexerBase<SubsPleaseSettings> public class SubsPlease : TorrentIndexerBase<NoAuthTorrentBaseSettings>
{ {
public override string Name => "SubsPlease"; public override string Name => "SubsPlease";
public override string[] IndexerUrls => new[] public override string[] IndexerUrls => new[]
@ -67,7 +68,7 @@ namespace NzbDrone.Core.Indexers.Definitions
public class SubsPleaseRequestGenerator : IIndexerRequestGenerator public class SubsPleaseRequestGenerator : IIndexerRequestGenerator
{ {
public SubsPleaseSettings Settings { get; set; } public NoAuthTorrentBaseSettings Settings { get; set; }
public IndexerCapabilities Capabilities { get; set; } public IndexerCapabilities Capabilities { get; set; }
private IEnumerable<IndexerRequest> GetSearchRequests(string term) private IEnumerable<IndexerRequest> GetSearchRequests(string term)
@ -159,10 +160,10 @@ namespace NzbDrone.Core.Indexers.Definitions
public class SubsPleaseParser : IParseIndexerResponse public class SubsPleaseParser : IParseIndexerResponse
{ {
private readonly SubsPleaseSettings _settings; private readonly NoAuthTorrentBaseSettings _settings;
private readonly IndexerCapabilitiesCategories _categories; private readonly IndexerCapabilitiesCategories _categories;
public SubsPleaseParser(SubsPleaseSettings settings, IndexerCapabilitiesCategories categories) public SubsPleaseParser(NoAuthTorrentBaseSettings settings, IndexerCapabilitiesCategories categories)
{ {
_settings = settings; _settings = settings;
_categories = categories; _categories = categories;
@ -237,26 +238,6 @@ namespace NzbDrone.Core.Indexers.Definitions
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; } public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
} }
public class SubsPleaseSettingsValidator : AbstractValidator<SubsPleaseSettings>
{
}
public class SubsPleaseSettings : IIndexerSettings
{
private static readonly SubsPleaseSettingsValidator Validator = new SubsPleaseSettingsValidator();
[FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2)]
public IndexerBaseSettings BaseSettings { get; set; } = new IndexerBaseSettings();
public NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));
}
}
public class SubPleaseRelease public class SubPleaseRelease
{ {
public string Time { get; set; } public string Time { get; set; }

@ -1,354 +0,0 @@
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Globalization;
using System.Linq;
using FluentValidation;
using Newtonsoft.Json;
using NLog;
using NzbDrone.Common.Extensions;
using NzbDrone.Common.Http;
using NzbDrone.Core.Annotations;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Parser;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.Definitions
{
[Obsolete("Moved to YML for Cardigann v3")]
public class SuperBits : TorrentIndexerBase<SuperBitsSettings>
{
public override string Name => "SuperBits";
public override string[] IndexerUrls => new string[] { "https://superbits.org/" };
public override string Description => "Superbits is a SWEDISH Private Torrent Tracker for MOVIES / TV / GENERAL";
public override DownloadProtocol Protocol => DownloadProtocol.Torrent;
public override IndexerPrivacy Privacy => IndexerPrivacy.Private;
public override IndexerCapabilities Capabilities => SetCapabilities();
public SuperBits(IIndexerHttpClient httpClient, IEventAggregator eventAggregator, IIndexerStatusService indexerStatusService, IConfigService configService, Logger logger)
: base(httpClient, eventAggregator, indexerStatusService, configService, logger)
{
}
public override IIndexerRequestGenerator GetRequestGenerator()
{
return new SuperBitsRequestGenerator() { Settings = Settings, Capabilities = Capabilities };
}
public override IParseIndexerResponse GetParser()
{
return new SuperBitsParser(Settings, Capabilities.Categories);
}
protected override IDictionary<string, string> GetCookies()
{
return CookieUtil.CookieHeaderToDictionary(Settings.Cookie);
}
private IndexerCapabilities SetCapabilities()
{
var caps = new IndexerCapabilities
{
TvSearchParams = new List<TvSearchParam>
{
TvSearchParam.Q, TvSearchParam.Season, TvSearchParam.Ep
},
MovieSearchParams = new List<MovieSearchParam>
{
MovieSearchParam.Q, MovieSearchParam.ImdbId
},
MusicSearchParams = new List<MusicSearchParam>
{
MusicSearchParam.Q
},
BookSearchParams = new List<BookSearchParam>
{
BookSearchParam.Q
}
};
caps.Categories.AddCategoryMapping(1, NewznabStandardCategory.MoviesDVD, "DVD-R Swesub");
caps.Categories.AddCategoryMapping(2, NewznabStandardCategory.TV, "DVD-R TV");
caps.Categories.AddCategoryMapping(3, NewznabStandardCategory.BooksEBook, "eBok");
caps.Categories.AddCategoryMapping(4, NewznabStandardCategory.MoviesHD, "Film 1080");
caps.Categories.AddCategoryMapping(5, NewznabStandardCategory.Movies3D, "Film 3D");
caps.Categories.AddCategoryMapping(6, NewznabStandardCategory.MoviesHD, "Film 720");
caps.Categories.AddCategoryMapping(7, NewznabStandardCategory.MoviesBluRay, "Film Bluray");
caps.Categories.AddCategoryMapping(8, NewznabStandardCategory.TV, "Svensk TV");
caps.Categories.AddCategoryMapping(9, NewznabStandardCategory.AudioAudiobook, "Ljudböcker");
caps.Categories.AddCategoryMapping(10, NewznabStandardCategory.AudioVideo, "Musikvideos");
caps.Categories.AddCategoryMapping(11, NewznabStandardCategory.BooksMags, "E-tidningar");
caps.Categories.AddCategoryMapping(12, NewznabStandardCategory.Audio, "Musik");
caps.Categories.AddCategoryMapping(13, NewznabStandardCategory.Other, "Omslag");
caps.Categories.AddCategoryMapping(14, NewznabStandardCategory.Other, "Övrigt");
caps.Categories.AddCategoryMapping(15, NewznabStandardCategory.PCGames, "PC-Spel");
caps.Categories.AddCategoryMapping(16, NewznabStandardCategory.PC0day, "Program");
caps.Categories.AddCategoryMapping(17, NewznabStandardCategory.ConsolePS3, "PS3");
caps.Categories.AddCategoryMapping(18, NewznabStandardCategory.TV, "TV");
caps.Categories.AddCategoryMapping(19, NewznabStandardCategory.ConsoleWii, "Wii");
caps.Categories.AddCategoryMapping(20, NewznabStandardCategory.ConsoleXBox, "Xbox");
caps.Categories.AddCategoryMapping(21, NewznabStandardCategory.MoviesOther, "Xvid");
caps.Categories.AddCategoryMapping(22, NewznabStandardCategory.XXX, "XXX");
caps.Categories.AddCategoryMapping(24, NewznabStandardCategory.MoviesUHD, "Film 4K");
caps.Categories.AddCategoryMapping(26, NewznabStandardCategory.TV, "TV DK");
caps.Categories.AddCategoryMapping(27, NewznabStandardCategory.TV, "TV NO");
caps.Categories.AddCategoryMapping(28, NewznabStandardCategory.TV, "TV FI");
return caps;
}
}
public class SuperBitsRequestGenerator : IIndexerRequestGenerator
{
public SuperBitsSettings Settings { get; set; }
public IndexerCapabilities Capabilities { get; set; }
public SuperBitsRequestGenerator()
{
}
private IEnumerable<IndexerRequest> GetPagedRequests(string term, int[] categories, string imdbId = null)
{
var searchUrl = Settings.BaseUrl + "api/v1/torrents";
// And this was option one from
// https://github.com/Jackett/Jackett/pull/7166#discussion_r376817517
var queryCollection = new NameValueCollection();
var searchString = term;
queryCollection.Add("extendedSearch", "false");
queryCollection.Add("freeleech", "false");
queryCollection.Add("index", "0");
queryCollection.Add("limit", "100");
queryCollection.Add("order", "desc");
queryCollection.Add("page", "search");
if (imdbId.IsNotNullOrWhiteSpace())
{
queryCollection.Add("searchText", imdbId);
}
else
{
queryCollection.Add("searchText", searchString);
}
queryCollection.Add("sort", "d");
queryCollection.Add("section", "all");
queryCollection.Add("stereoscopic", "false");
queryCollection.Add("sweaudio", "false");
queryCollection.Add("swesub", "false");
queryCollection.Add("watchview", "false");
searchUrl += "?" + queryCollection.GetQueryString();
foreach (var cat in Capabilities.Categories.MapTorznabCapsToTrackers(categories))
{
searchUrl += "&categories[]=" + cat;
}
var request = new IndexerRequest(searchUrl, HttpAccept.Json);
request.HttpRequest.Headers.Add("Referer", Settings.BaseUrl);
yield return request;
}
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories, searchCriteria.FullImdbId));
return pageableRequests;
}
public IndexerPageableRequestChain GetSearchRequests(MusicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories));
return pageableRequests;
}
public IndexerPageableRequestChain GetSearchRequests(TvSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedTvSearchString), searchCriteria.Categories, searchCriteria.FullImdbId));
return pageableRequests;
}
public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories));
return pageableRequests;
}
public IndexerPageableRequestChain GetSearchRequests(BasicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories));
return pageableRequests;
}
public Func<IDictionary<string, string>> GetCookies { get; set; }
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
}
public class SuperBitsParser : IParseIndexerResponse
{
private readonly SuperBitsSettings _settings;
private readonly IndexerCapabilitiesCategories _categories;
public SuperBitsParser(SuperBitsSettings settings, IndexerCapabilitiesCategories categories)
{
_settings = settings;
_categories = categories;
}
public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse)
{
var torrentInfos = new List<TorrentInfo>();
var json = JsonConvert.DeserializeObject<dynamic>(indexerResponse.Content);
foreach (var row in json ?? Enumerable.Empty<dynamic>())
{
var release = new TorrentInfo();
var descriptions = new List<string>();
var tags = new List<string>();
release.MinimumRatio = 1.1;
release.MinimumSeedTime = 172800; // 48 hours
release.Title = row.name;
release.Categories = _categories.MapTrackerCatToNewznab(row.category.ToString());
release.Size = row.size;
release.Seeders = row.seeders;
release.Peers = row.leechers + release.Seeders;
release.PublishDate = DateTime.ParseExact(row.added.ToString() + " +01:00", "yyyy-MM-dd HH:mm:ss zzz", CultureInfo.InvariantCulture);
release.Files = row.numfiles;
release.Grabs = row.times_completed;
release.InfoUrl = _settings.BaseUrl + "torrent/" + row.id.ToString() + "/";
release.Guid = release.InfoUrl;
release.DownloadUrl = _settings.BaseUrl + "api/v1/torrents/download/" + row.id.ToString();
if (row.frileech == 1)
{
release.DownloadVolumeFactor = 0;
}
else
{
release.DownloadVolumeFactor = 1;
}
release.UploadVolumeFactor = 1;
if (!string.IsNullOrWhiteSpace(row.customcover.ToString()))
{
release.PosterUrl = _settings.BaseUrl + row.customcover;
}
if (row.imdbid2 != null && row.imdbid2.ToString().StartsWith("tt"))
{
release.ImdbId = ParseUtil.CoerceInt(row.imdbid2.ToString().Substring(2));
descriptions.Add("Title: " + row.title);
descriptions.Add("Year: " + row.year);
descriptions.Add("Genres: " + row.genres);
descriptions.Add("Tagline: " + row.tagline);
descriptions.Add("Cast: " + row.cast);
descriptions.Add("Rating: " + row.rating);
descriptions.Add("Plot: " + row.plot);
release.PosterUrl = _settings.BaseUrl + "img/imdb/" + row.imdbid2 + ".jpg";
}
if ((int)row.p2p == 1)
{
tags.Add("P2P");
}
if ((int)row.pack == 1)
{
tags.Add("Pack");
}
if ((int)row.reqid != 0)
{
tags.Add("Request");
}
if ((int)row.sweaudio != 0)
{
tags.Add("Swedish audio");
}
if ((int)row.swesub != 0)
{
tags.Add("Swedish subtitles");
}
if (tags.Count > 0)
{
descriptions.Add("Tags: " + string.Join(", ", tags));
}
var preDate = row.preDate.ToString();
if (!string.IsNullOrWhiteSpace(preDate) && preDate != "1970-01-01 01:00:00")
{
descriptions.Add("PRE: " + preDate);
}
descriptions.Add("Section: " + row.section);
//release.Description = string.Join("<br>\n", descriptions);
torrentInfos.Add(release);
}
return torrentInfos.ToArray();
}
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
}
public class SuperBitsSettingsValidator : AbstractValidator<SuperBitsSettings>
{
public SuperBitsSettingsValidator()
{
RuleFor(c => c.Cookie).NotEmpty();
}
}
public class SuperBitsSettings : IIndexerSettings
{
private static readonly SuperBitsSettingsValidator Validator = new SuperBitsSettingsValidator();
public SuperBitsSettings()
{
Cookie = "";
}
[FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2, Label = "Cookie", HelpText = "Site Cookie")]
public string Cookie { get; set; }
[FieldDefinition(3)]
public IndexerBaseSettings BaseSettings { get; set; } = new IndexerBaseSettings();
public NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));
}
}
}

@ -15,6 +15,7 @@ using NzbDrone.Common.Http;
using NzbDrone.Core.Annotations; using NzbDrone.Core.Annotations;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.Indexers.Exceptions; using NzbDrone.Core.Indexers.Exceptions;
using NzbDrone.Core.Indexers.Settings;
using NzbDrone.Core.IndexerSearch.Definitions; using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
@ -24,7 +25,7 @@ using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.Definitions namespace NzbDrone.Core.Indexers.Definitions
{ {
[Obsolete("Remove per Site Request Prowlarr Issue 573")] [Obsolete("Remove per Site Request Prowlarr Issue 573")]
public class TVVault : TorrentIndexerBase<TVVaultSettings> public class TVVault : TorrentIndexerBase<UserPassTorrentBaseSettings>
{ {
public override string Name => "TVVault"; public override string Name => "TVVault";
public override string[] IndexerUrls => new[] { "https://tv-vault.me/" }; public override string[] IndexerUrls => new[] { "https://tv-vault.me/" };
@ -136,7 +137,7 @@ namespace NzbDrone.Core.Indexers.Definitions
public class TVVaultRequestGenerator : IIndexerRequestGenerator public class TVVaultRequestGenerator : IIndexerRequestGenerator
{ {
public TVVaultSettings Settings { get; set; } public UserPassTorrentBaseSettings Settings { get; set; }
public IndexerCapabilities Capabilities { get; set; } public IndexerCapabilities Capabilities { get; set; }
public string BaseUrl { get; set; } public string BaseUrl { get; set; }
@ -230,10 +231,10 @@ namespace NzbDrone.Core.Indexers.Definitions
public class TVVaultParser : IParseIndexerResponse public class TVVaultParser : IParseIndexerResponse
{ {
private readonly TVVaultSettings _settings; private readonly UserPassTorrentBaseSettings _settings;
private readonly IndexerCapabilitiesCategories _categories; private readonly IndexerCapabilitiesCategories _categories;
public TVVaultParser(TVVaultSettings settings, IndexerCapabilitiesCategories categories) public TVVaultParser(UserPassTorrentBaseSettings settings, IndexerCapabilitiesCategories categories)
{ {
_settings = settings; _settings = settings;
_categories = categories; _categories = categories;
@ -304,41 +305,4 @@ namespace NzbDrone.Core.Indexers.Definitions
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; } public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
} }
public class TVVaultSettingsValidator : AbstractValidator<TVVaultSettings>
{
public TVVaultSettingsValidator()
{
RuleFor(c => c.Username).NotEmpty();
RuleFor(c => c.Password).NotEmpty();
}
}
public class TVVaultSettings : IIndexerSettings
{
private static readonly TVVaultSettingsValidator Validator = new TVVaultSettingsValidator();
public TVVaultSettings()
{
Username = "";
Password = "";
}
[FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2, Label = "Username", HelpText = "Site Username", Privacy = PrivacyLevel.UserName)]
public string Username { get; set; }
[FieldDefinition(3, Label = "Password", HelpText = "Site Password", Privacy = PrivacyLevel.Password, Type = FieldType.Password)]
public string Password { get; set; }
[FieldDefinition(4)]
public IndexerBaseSettings BaseSettings { get; set; } = new IndexerBaseSettings();
public NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));
}
}
} }

@ -1,322 +0,0 @@
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Text;
using Newtonsoft.Json;
using NLog;
using NzbDrone.Common.Http;
using NzbDrone.Core.Annotations;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Parser;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.Definitions
{
[Obsolete("Moved to YML for Cardigann v3")]
public class ThePirateBay : TorrentIndexerBase<ThePirateBaySettings>
{
public override string Name => "ThePirateBay";
public override string[] IndexerUrls => new string[] { "https://thepiratebay.org/" };
public override string Description => "Pirate Bay(TPB) is the galaxys most resilient Public BitTorrent site";
public override string Language => "en-US";
public override Encoding Encoding => Encoding.UTF8;
public override DownloadProtocol Protocol => DownloadProtocol.Torrent;
public override IndexerPrivacy Privacy => IndexerPrivacy.Public;
public override IndexerCapabilities Capabilities => SetCapabilities();
public ThePirateBay(IIndexerHttpClient httpClient, IEventAggregator eventAggregator, IIndexerStatusService indexerStatusService, IConfigService configService, Logger logger)
: base(httpClient, eventAggregator, indexerStatusService, configService, logger)
{
}
public override IIndexerRequestGenerator GetRequestGenerator()
{
return new ThePirateBayRequestGenerator() { Capabilities = Capabilities };
}
public override IParseIndexerResponse GetParser()
{
return new ThePirateBayParser(Capabilities.Categories, Settings);
}
private IndexerCapabilities SetCapabilities()
{
var caps = new IndexerCapabilities
{
TvSearchParams = new List<TvSearchParam>
{
TvSearchParam.Q, TvSearchParam.Season, TvSearchParam.Ep
},
MovieSearchParams = new List<MovieSearchParam>
{
MovieSearchParam.Q
},
MusicSearchParams = new List<MusicSearchParam>
{
MusicSearchParam.Q
},
BookSearchParams = new List<BookSearchParam>
{
BookSearchParam.Q
}
};
caps.Categories.AddCategoryMapping(100, NewznabStandardCategory.Audio, "Audio");
caps.Categories.AddCategoryMapping(101, NewznabStandardCategory.Audio, "Music");
caps.Categories.AddCategoryMapping(102, NewznabStandardCategory.AudioAudiobook, "Audio Books");
caps.Categories.AddCategoryMapping(103, NewznabStandardCategory.Audio, "Sound Clips");
caps.Categories.AddCategoryMapping(104, NewznabStandardCategory.AudioLossless, "FLAC");
caps.Categories.AddCategoryMapping(199, NewznabStandardCategory.AudioOther, "Audio Other");
caps.Categories.AddCategoryMapping(200, NewznabStandardCategory.Movies, "Video");
caps.Categories.AddCategoryMapping(201, NewznabStandardCategory.Movies, "Movies");
caps.Categories.AddCategoryMapping(202, NewznabStandardCategory.Movies, "Movies");
caps.Categories.AddCategoryMapping(203, NewznabStandardCategory.AudioVideo, "Music Videos");
caps.Categories.AddCategoryMapping(204, NewznabStandardCategory.MoviesOther, "Movie Clips");
caps.Categories.AddCategoryMapping(205, NewznabStandardCategory.TV, "TV");
caps.Categories.AddCategoryMapping(206, NewznabStandardCategory.TVOther, "Handheld");
caps.Categories.AddCategoryMapping(207, NewznabStandardCategory.MoviesHD, "HD - Movies");
caps.Categories.AddCategoryMapping(208, NewznabStandardCategory.TVHD, "HD - TV shows");
caps.Categories.AddCategoryMapping(209, NewznabStandardCategory.Movies3D, "3D");
caps.Categories.AddCategoryMapping(299, NewznabStandardCategory.MoviesOther, "Video Other");
caps.Categories.AddCategoryMapping(300, NewznabStandardCategory.PC, "Applications");
caps.Categories.AddCategoryMapping(301, NewznabStandardCategory.PC, "Windows");
caps.Categories.AddCategoryMapping(302, NewznabStandardCategory.PCMac, "Mac");
caps.Categories.AddCategoryMapping(303, NewznabStandardCategory.PC, "UNIX");
caps.Categories.AddCategoryMapping(304, NewznabStandardCategory.PCMobileOther, "Handheld");
caps.Categories.AddCategoryMapping(305, NewznabStandardCategory.PCMobileiOS, "IOS (iPad/iPhone)");
caps.Categories.AddCategoryMapping(306, NewznabStandardCategory.PCMobileAndroid, "Android");
caps.Categories.AddCategoryMapping(399, NewznabStandardCategory.PC, "Other OS");
caps.Categories.AddCategoryMapping(400, NewznabStandardCategory.Console, "Games");
caps.Categories.AddCategoryMapping(401, NewznabStandardCategory.PCGames, "PC");
caps.Categories.AddCategoryMapping(402, NewznabStandardCategory.PCMac, "Mac");
caps.Categories.AddCategoryMapping(403, NewznabStandardCategory.ConsolePS4, "PSx");
caps.Categories.AddCategoryMapping(404, NewznabStandardCategory.ConsoleXBox, "XBOX360");
caps.Categories.AddCategoryMapping(405, NewznabStandardCategory.ConsoleWii, "Wii");
caps.Categories.AddCategoryMapping(406, NewznabStandardCategory.ConsoleOther, "Handheld");
caps.Categories.AddCategoryMapping(407, NewznabStandardCategory.ConsoleOther, "IOS (iPad/iPhone)");
caps.Categories.AddCategoryMapping(408, NewznabStandardCategory.ConsoleOther, "Android");
caps.Categories.AddCategoryMapping(499, NewznabStandardCategory.ConsoleOther, "Games Other");
caps.Categories.AddCategoryMapping(500, NewznabStandardCategory.XXX, "Porn");
caps.Categories.AddCategoryMapping(501, NewznabStandardCategory.XXX, "Movies");
caps.Categories.AddCategoryMapping(502, NewznabStandardCategory.XXXDVD, "Movies DVDR");
caps.Categories.AddCategoryMapping(503, NewznabStandardCategory.XXXImageSet, "Pictures");
caps.Categories.AddCategoryMapping(504, NewznabStandardCategory.XXX, "Games");
caps.Categories.AddCategoryMapping(505, NewznabStandardCategory.XXX, "HD - Movies");
caps.Categories.AddCategoryMapping(506, NewznabStandardCategory.XXX, "Movie Clips");
caps.Categories.AddCategoryMapping(599, NewznabStandardCategory.XXXOther, "Porn other");
caps.Categories.AddCategoryMapping(600, NewznabStandardCategory.Other, "Other");
caps.Categories.AddCategoryMapping(601, NewznabStandardCategory.Books, "E-books");
caps.Categories.AddCategoryMapping(602, NewznabStandardCategory.BooksComics, "Comics");
caps.Categories.AddCategoryMapping(603, NewznabStandardCategory.Books, "Pictures");
caps.Categories.AddCategoryMapping(604, NewznabStandardCategory.Books, "Covers");
caps.Categories.AddCategoryMapping(605, NewznabStandardCategory.Books, "Physibles");
caps.Categories.AddCategoryMapping(699, NewznabStandardCategory.BooksOther, "Other Other");
return caps;
}
}
public class ThePirateBayRequestGenerator : IIndexerRequestGenerator
{
public IndexerCapabilities Capabilities { get; set; }
private static string ApiUrl => "https://apibay.org/";
public ThePirateBayRequestGenerator()
{
}
private IEnumerable<IndexerRequest> GetPagedRequests(string term, int[] categories, bool rssSearch)
{
if (rssSearch)
{
yield return new IndexerRequest($"{ApiUrl.TrimEnd('/')}/precompiled/data_top100_recent.json", HttpAccept.Html);
}
else
{
var cats = Capabilities.Categories.MapTorznabCapsToTrackers(categories);
var queryStringCategories = string.Join(
",",
cats.Count == 0
? Capabilities.Categories.GetTrackerCategories()
: cats);
var queryCollection = new NameValueCollection
{
{ "q", term },
{ "cat", queryStringCategories }
};
var searchUrl = string.Format("{0}/q.php?{1}", ApiUrl.TrimEnd('/'), queryCollection.GetQueryString());
var request = new IndexerRequest(searchUrl, HttpAccept.Json);
yield return request;
}
}
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories, searchCriteria.RssSearch));
return pageableRequests;
}
public IndexerPageableRequestChain GetSearchRequests(MusicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories, searchCriteria.RssSearch));
return pageableRequests;
}
public IndexerPageableRequestChain GetSearchRequests(TvSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedTvSearchString), searchCriteria.Categories, searchCriteria.RssSearch));
return pageableRequests;
}
public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories, searchCriteria.RssSearch));
return pageableRequests;
}
public IndexerPageableRequestChain GetSearchRequests(BasicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories, searchCriteria.RssSearch));
return pageableRequests;
}
public Func<IDictionary<string, string>> GetCookies { get; set; }
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
}
public class ThePirateBayParser : IParseIndexerResponse
{
private readonly ThePirateBaySettings _settings;
private readonly IndexerCapabilitiesCategories _categories;
public ThePirateBayParser(IndexerCapabilitiesCategories categories, ThePirateBaySettings settings)
{
_settings = settings;
_categories = categories;
}
public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse)
{
var torrentInfos = new List<ReleaseInfo>();
var queryResponseItems = JsonConvert.DeserializeObject<List<ThePirateBayTorrent>>(indexerResponse.Content);
// The API returns a single item to represent a state of no results. Avoid returning this result.
if (queryResponseItems.Count == 1 && queryResponseItems.First().Id == 0)
{
return torrentInfos;
}
foreach (var item in queryResponseItems)
{
var details = item.Id == 0 ? null : $"{_settings.BaseUrl}description.php?id={item.Id}";
var imdbId = string.IsNullOrEmpty(item.Imdb) ? null : ParseUtil.GetImdbID(item.Imdb);
var torrentItem = new TorrentInfo
{
Title = item.Name,
Categories = _categories.MapTrackerCatToNewznab(item.Category.ToString()),
Guid = details,
InfoUrl = details,
InfoHash = item.InfoHash, // magnet link is auto generated from infohash
PublishDate = DateTimeUtil.UnixTimestampToDateTime(item.Added),
Seeders = item.Seeders,
Peers = item.Seeders + item.Leechers,
Size = item.Size,
Files = item.NumFiles,
DownloadVolumeFactor = 0,
UploadVolumeFactor = 1,
ImdbId = imdbId.GetValueOrDefault()
};
if (item.InfoHash != null)
{
torrentItem.MagnetUrl = MagnetLinkBuilder.BuildPublicMagnetLink(item.InfoHash, item.Name);
}
torrentInfos.Add(torrentItem);
}
return torrentInfos.ToArray();
}
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
}
public class ThePirateBaySettings : IIndexerSettings
{
[FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2)]
public IndexerBaseSettings BaseSettings { get; set; } = new IndexerBaseSettings();
public NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult();
}
}
public class ThePirateBayTorrent
{
[JsonProperty("id")]
public long Id { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("info_hash")]
public string InfoHash { get; set; }
[JsonProperty("leechers")]
public int Leechers { get; set; }
[JsonProperty("seeders")]
public int Seeders { get; set; }
[JsonProperty("num_files")]
public int NumFiles { get; set; }
[JsonProperty("size")]
public long Size { get; set; }
[JsonProperty("username")]
public string Username { get; set; }
[JsonProperty("added")]
public long Added { get; set; }
[JsonProperty("status")]
public string Status { get; set; }
[JsonProperty("category")]
public long Category { get; set; }
[JsonProperty("imdb")]
public string Imdb { get; set; }
}
}

@ -8,6 +8,7 @@ using NzbDrone.Common.Extensions;
using NzbDrone.Common.Http; using NzbDrone.Common.Http;
using NzbDrone.Core.Annotations; using NzbDrone.Core.Annotations;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.Indexers.Settings;
using NzbDrone.Core.IndexerSearch.Definitions; using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
@ -16,7 +17,7 @@ using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.Definitions namespace NzbDrone.Core.Indexers.Definitions
{ {
public class TorrentDay : TorrentIndexerBase<TorrentDaySettings> public class TorrentDay : TorrentIndexerBase<CookieTorrentBaseSettings>
{ {
public override string Name => "TorrentDay"; public override string Name => "TorrentDay";
@ -134,7 +135,7 @@ namespace NzbDrone.Core.Indexers.Definitions
public class TorrentDayRequestGenerator : IIndexerRequestGenerator public class TorrentDayRequestGenerator : IIndexerRequestGenerator
{ {
public TorrentDaySettings Settings { get; set; } public CookieTorrentBaseSettings Settings { get; set; }
public IndexerCapabilities Capabilities { get; set; } public IndexerCapabilities Capabilities { get; set; }
public TorrentDayRequestGenerator() public TorrentDayRequestGenerator()
@ -218,10 +219,10 @@ namespace NzbDrone.Core.Indexers.Definitions
public class TorrentDayParser : IParseIndexerResponse public class TorrentDayParser : IParseIndexerResponse
{ {
private readonly TorrentDaySettings _settings; private readonly CookieTorrentBaseSettings _settings;
private readonly IndexerCapabilitiesCategories _categories; private readonly IndexerCapabilitiesCategories _categories;
public TorrentDayParser(TorrentDaySettings settings, IndexerCapabilitiesCategories categories) public TorrentDayParser(CookieTorrentBaseSettings settings, IndexerCapabilitiesCategories categories)
{ {
_settings = settings; _settings = settings;
_categories = categories; _categories = categories;
@ -274,36 +275,4 @@ namespace NzbDrone.Core.Indexers.Definitions
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; } public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
} }
public class TorrentDaySettingsValidator : AbstractValidator<TorrentDaySettings>
{
public TorrentDaySettingsValidator()
{
RuleFor(c => c.Cookie).NotEmpty();
}
}
public class TorrentDaySettings : IIndexerSettings
{
private static readonly TorrentDaySettingsValidator Validator = new TorrentDaySettingsValidator();
public TorrentDaySettings()
{
Cookie = "";
}
[FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2, Label = "Cookie", HelpText = "Site Cookie")]
public string Cookie { get; set; }
[FieldDefinition(3)]
public IndexerBaseSettings BaseSettings { get; set; } = new IndexerBaseSettings();
public NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));
}
}
} }

@ -1,380 +0,0 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using FluentValidation;
using Newtonsoft.Json;
using NLog;
using NzbDrone.Common.Extensions;
using NzbDrone.Common.Http;
using NzbDrone.Core.Annotations;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Parser;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.Definitions
{
[Obsolete("Moved to YML for Cardigann v3")]
public class TorrentLeech : TorrentIndexerBase<TorrentLeechSettings>
{
public override string Name => "TorrentLeech";
public override string[] IndexerUrls => new string[] { "https://www.torrentleech.org/" };
public override string Description => "This is what happens when you seed";
private string LoginUrl => Settings.BaseUrl + "user/account/login/";
public override DownloadProtocol Protocol => DownloadProtocol.Torrent;
public override IndexerPrivacy Privacy => IndexerPrivacy.Private;
public override IndexerCapabilities Capabilities => SetCapabilities();
public TorrentLeech(IIndexerHttpClient httpClient, IEventAggregator eventAggregator, IIndexerStatusService indexerStatusService, IConfigService configService, Logger logger)
: base(httpClient, eventAggregator, indexerStatusService, configService, logger)
{
}
public override IIndexerRequestGenerator GetRequestGenerator()
{
return new TorrentLeechRequestGenerator() { Settings = Settings, Capabilities = Capabilities };
}
public override IParseIndexerResponse GetParser()
{
return new TorrentLeechParser(Settings, Capabilities.Categories);
}
protected override async Task DoLogin()
{
var requestBuilder = new HttpRequestBuilder(LoginUrl)
{
LogResponseContent = true
};
requestBuilder.Method = HttpMethod.Post;
requestBuilder.PostProcess += r => r.RequestTimeout = TimeSpan.FromSeconds(15);
var cookies = Cookies;
Cookies = null;
var authLoginRequest = requestBuilder
.AddFormParameter("username", Settings.Username)
.AddFormParameter("password", Settings.Password)
.SetHeader("Content-Type", "multipart/form-data")
.Build();
var response = await ExecuteAuth(authLoginRequest);
cookies = response.GetCookies();
UpdateCookies(cookies, DateTime.Now + TimeSpan.FromDays(30));
_logger.Debug("TorrentLeech authentication succeeded.");
}
protected override bool CheckIfLoginNeeded(HttpResponse httpResponse)
{
if (httpResponse.Content.Contains("/user/account/login"))
{
return true;
}
return false;
}
private IndexerCapabilities SetCapabilities()
{
var caps = new IndexerCapabilities
{
TvSearchParams = new List<TvSearchParam>
{
// Torrentleech does technically support ImdbId Search but only with no other params
// ImdbId + S/E search returns unrelated results
TvSearchParam.Q, TvSearchParam.Season, TvSearchParam.Ep
},
MovieSearchParams = new List<MovieSearchParam>
{
MovieSearchParam.Q, MovieSearchParam.ImdbId
},
MusicSearchParams = new List<MusicSearchParam>
{
MusicSearchParam.Q
},
BookSearchParams = new List<BookSearchParam>
{
BookSearchParam.Q
}
};
caps.Categories.AddCategoryMapping(1, NewznabStandardCategory.Movies, "Movies");
caps.Categories.AddCategoryMapping(8, NewznabStandardCategory.MoviesSD, "Movies Cam");
caps.Categories.AddCategoryMapping(9, NewznabStandardCategory.MoviesSD, "Movies TS/TC");
caps.Categories.AddCategoryMapping(11, NewznabStandardCategory.MoviesSD, "Movies DVDRip/DVDScreener");
caps.Categories.AddCategoryMapping(12, NewznabStandardCategory.MoviesDVD, "Movies DVD-R");
caps.Categories.AddCategoryMapping(13, NewznabStandardCategory.MoviesBluRay, "Movies Bluray");
caps.Categories.AddCategoryMapping(14, NewznabStandardCategory.MoviesHD, "Movies BlurayRip");
caps.Categories.AddCategoryMapping(15, NewznabStandardCategory.Movies, "Movies Boxsets");
caps.Categories.AddCategoryMapping(29, NewznabStandardCategory.TVDocumentary, "Documentaries");
caps.Categories.AddCategoryMapping(47, NewznabStandardCategory.MoviesUHD, "Movies 4K");
caps.Categories.AddCategoryMapping(36, NewznabStandardCategory.MoviesForeign, "Movies Foreign");
caps.Categories.AddCategoryMapping(37, NewznabStandardCategory.MoviesWEBDL, "Movies WEBRip");
caps.Categories.AddCategoryMapping(43, NewznabStandardCategory.MoviesHD, "Movies HDRip");
caps.Categories.AddCategoryMapping(2, NewznabStandardCategory.TV, "TV");
caps.Categories.AddCategoryMapping(26, NewznabStandardCategory.TVSD, "TV Episodes");
caps.Categories.AddCategoryMapping(27, NewznabStandardCategory.TV, "TV Boxsets");
caps.Categories.AddCategoryMapping(32, NewznabStandardCategory.TVHD, "TV Episodes HD");
caps.Categories.AddCategoryMapping(44, NewznabStandardCategory.TVForeign, "TV Foreign");
caps.Categories.AddCategoryMapping(3, NewznabStandardCategory.PCGames, "Games");
caps.Categories.AddCategoryMapping(17, NewznabStandardCategory.PCGames, "Games PC");
caps.Categories.AddCategoryMapping(18, NewznabStandardCategory.ConsoleXBox, "Games XBOX");
caps.Categories.AddCategoryMapping(19, NewznabStandardCategory.ConsoleXBox360, "Games XBOX360");
caps.Categories.AddCategoryMapping(40, NewznabStandardCategory.ConsoleXBoxOne, "Games XBOXONE");
caps.Categories.AddCategoryMapping(20, NewznabStandardCategory.ConsolePS3, "Games PS2");
caps.Categories.AddCategoryMapping(21, NewznabStandardCategory.ConsolePS3, "Games Mac");
caps.Categories.AddCategoryMapping(22, NewznabStandardCategory.ConsolePSP, "Games PSP");
caps.Categories.AddCategoryMapping(28, NewznabStandardCategory.ConsoleWii, "Games Wii");
caps.Categories.AddCategoryMapping(30, NewznabStandardCategory.ConsoleNDS, "Games Nintendo DS");
caps.Categories.AddCategoryMapping(39, NewznabStandardCategory.ConsolePS4, "Games PS4");
caps.Categories.AddCategoryMapping(42, NewznabStandardCategory.PCMac, "Games Mac");
caps.Categories.AddCategoryMapping(48, NewznabStandardCategory.ConsoleOther, "Games Nintendo Switch");
caps.Categories.AddCategoryMapping(4, NewznabStandardCategory.Audio, "Music");
caps.Categories.AddCategoryMapping(16, NewznabStandardCategory.AudioVideo, "Music videos");
caps.Categories.AddCategoryMapping(31, NewznabStandardCategory.Audio, "Audio");
caps.Categories.AddCategoryMapping(7, NewznabStandardCategory.TV, "Animation");
caps.Categories.AddCategoryMapping(34, NewznabStandardCategory.TVAnime, "TV Anime");
caps.Categories.AddCategoryMapping(35, NewznabStandardCategory.TV, "TV Cartoons");
caps.Categories.AddCategoryMapping(5, NewznabStandardCategory.Books, "Books");
caps.Categories.AddCategoryMapping(45, NewznabStandardCategory.BooksEBook, "Books EBooks");
caps.Categories.AddCategoryMapping(46, NewznabStandardCategory.BooksComics, "Books Comics");
caps.Categories.AddCategoryMapping(6, NewznabStandardCategory.PC, "Apps");
caps.Categories.AddCategoryMapping(23, NewznabStandardCategory.PCISO, "PC ISO");
caps.Categories.AddCategoryMapping(24, NewznabStandardCategory.PCMac, "PC Mac");
caps.Categories.AddCategoryMapping(25, NewznabStandardCategory.PCMobileOther, "PC Mobile");
caps.Categories.AddCategoryMapping(33, NewznabStandardCategory.PC0day, "PC 0-day");
caps.Categories.AddCategoryMapping(38, NewznabStandardCategory.Other, "Education");
return caps;
}
}
public class TorrentLeechRequestGenerator : IIndexerRequestGenerator
{
public TorrentLeechSettings Settings { get; set; }
public IndexerCapabilities Capabilities { get; set; }
public TorrentLeechRequestGenerator()
{
}
private IEnumerable<IndexerRequest> GetPagedRequests(string term, int[] categories, string imdbId = null)
{
var searchString = Regex.Replace(term, @"(^|\s)-", " ");
var searchUrl = Settings.BaseUrl + "torrents/browse/list/";
if (Settings.FreeLeechOnly)
{
searchUrl += "facets/tags%3AFREELEECH/";
}
if (imdbId.IsNotNullOrWhiteSpace())
{
searchUrl += "imdbID/" + imdbId + "/";
}
else if (!string.IsNullOrWhiteSpace(searchString))
{
searchUrl += "exact/1/query/" + WebUtility.UrlEncode(searchString) + "/";
}
var cats = Capabilities.Categories.MapTorznabCapsToTrackers(categories);
if (cats.Count > 0)
{
searchUrl += "categories/" + string.Join(",", cats);
}
else
{
searchUrl += "newfilter/2"; // include 0day and music
}
var request = new IndexerRequest(searchUrl, HttpAccept.Rss);
yield return request;
}
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SearchTerm), searchCriteria.Categories, searchCriteria.FullImdbId));
return pageableRequests;
}
public IndexerPageableRequestChain GetSearchRequests(MusicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SearchTerm), searchCriteria.Categories));
return pageableRequests;
}
public IndexerPageableRequestChain GetSearchRequests(TvSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedTvSearchString), searchCriteria.Categories));
return pageableRequests;
}
public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SearchTerm), searchCriteria.Categories));
return pageableRequests;
}
public IndexerPageableRequestChain GetSearchRequests(BasicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SearchTerm), searchCriteria.Categories));
return pageableRequests;
}
public Func<IDictionary<string, string>> GetCookies { get; set; }
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
}
public class TorrentLeechParser : IParseIndexerResponse
{
private readonly TorrentLeechSettings _settings;
private readonly IndexerCapabilitiesCategories _categories;
public TorrentLeechParser(TorrentLeechSettings settings, IndexerCapabilitiesCategories categories)
{
_settings = settings;
_categories = categories;
}
public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse)
{
var torrentInfos = new List<TorrentInfo>();
var rows = JsonConvert.DeserializeObject<dynamic>(indexerResponse.Content).torrentList;
foreach (var row in rows ?? Enumerable.Empty<dynamic>())
{
var title = row.name.ToString();
var torrentId = row.fid.ToString();
var details = new Uri(_settings.BaseUrl + "torrent/" + torrentId);
var link = new Uri(_settings.BaseUrl + "download/" + torrentId + "/" + row.filename);
var publishDate = DateTime.ParseExact(row.addedTimestamp.ToString(), "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal);
var seeders = (int)row.seeders;
var leechers = (int)row.leechers;
var grabs = (int)row.completed;
var size = (long)row.size;
var cats = _categories.MapTrackerCatToNewznab(((int)row.categoryID).ToString());
var imdb = (string)row.imdbID;
var imdbId = 0;
if (imdb.Length > 2)
{
imdbId = int.Parse(imdb.Substring(2));
}
// freeleech #6579 #6624 #7367
string dlMultiplier = row.download_multiplier.ToString();
var dlVolumeFactor = dlMultiplier.IsNullOrWhiteSpace() ? 1 : ParseUtil.CoerceInt(dlMultiplier);
var release = new TorrentInfo
{
Title = title,
InfoUrl = details.AbsoluteUri,
Guid = details.AbsoluteUri,
DownloadUrl = link.AbsoluteUri,
PublishDate = publishDate,
Categories = cats,
Size = size,
Grabs = grabs,
Seeders = seeders,
Peers = seeders + leechers,
ImdbId = imdbId,
UploadVolumeFactor = 1,
DownloadVolumeFactor = dlVolumeFactor,
MinimumRatio = 1,
MinimumSeedTime = 864000 // 10 days for registered users, less for upgraded users
};
torrentInfos.Add(release);
}
return torrentInfos.ToArray();
}
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
}
public class TorrentLeechSettingsValidator : AbstractValidator<TorrentLeechSettings>
{
public TorrentLeechSettingsValidator()
{
RuleFor(c => c.Username).NotEmpty();
RuleFor(c => c.Password).NotEmpty();
RuleFor(c => c.VipExpiration).Must(c => c.IsValidDate())
.When(c => c.VipExpiration.IsNotNullOrWhiteSpace())
.WithMessage("Correctly formatted date is required");
RuleFor(c => c.VipExpiration).Must(c => c.IsFutureDate())
.When(c => c.VipExpiration.IsNotNullOrWhiteSpace())
.WithMessage("Must be a future date");
}
}
public class TorrentLeechSettings : IIndexerSettings
{
private static readonly TorrentLeechSettingsValidator Validator = new TorrentLeechSettingsValidator();
public TorrentLeechSettings()
{
Username = "";
Password = "";
}
[FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2, Label = "Username", HelpText = "Site Username", Privacy = PrivacyLevel.UserName)]
public string Username { get; set; }
[FieldDefinition(3, Label = "Password", HelpText = "Site Password", Privacy = PrivacyLevel.Password, Type = FieldType.Password)]
public string Password { get; set; }
[FieldDefinition(4, Label = "FreeLeech Only", Type = FieldType.Checkbox, Advanced = true, HelpText = "Search Freeleech torrents only")]
public bool FreeLeechOnly { get; set; }
[FieldDefinition(5, Label = "VIP Expiration", HelpText = "Enter date (yyyy-mm-dd) for VIP Expiration or blank, Prowlarr will notify 1 week from expiration of VIP")]
public string VipExpiration { get; set; }
[FieldDefinition(6)]
public IndexerBaseSettings BaseSettings { get; set; } = new IndexerBaseSettings();
public NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));
}
}
}

@ -1,246 +0,0 @@
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Net;
using System.Text;
using FluentValidation;
using Newtonsoft.Json;
using NLog;
using NzbDrone.Common.Http;
using NzbDrone.Core.Annotations;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.Indexers.Exceptions;
using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Parser;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.Definitions
{
[Obsolete("Moved to YML for Cardigann v3")]
public class TorrentParadiseMl : TorrentIndexerBase<TorrentParadiseMlSettings>
{
public override string Name => "TorrentParadiseMl";
public override string[] IndexerUrls => new[] { "https://torrent-paradise.ml/" };
public override string Language => "en-US";
public override string Description => "The most innovative torrent site";
public override Encoding Encoding => Encoding.UTF8;
public override DownloadProtocol Protocol => DownloadProtocol.Torrent;
public override IndexerPrivacy Privacy => IndexerPrivacy.Public;
public override IndexerCapabilities Capabilities => SetCapabilities();
public TorrentParadiseMl(IIndexerHttpClient httpClient, IEventAggregator eventAggregator, IIndexerStatusService indexerStatusService, IConfigService configService, Logger logger)
: base(httpClient, eventAggregator, indexerStatusService, configService, logger)
{
}
public override IIndexerRequestGenerator GetRequestGenerator()
{
return new TorrentParadiseMlRequestGenerator() { Settings = Settings, Capabilities = Capabilities };
}
public override IParseIndexerResponse GetParser()
{
return new TorrentParadiseMlParser(Settings);
}
private IndexerCapabilities SetCapabilities()
{
var caps = new IndexerCapabilities
{
TvSearchParams = new List<TvSearchParam>
{
TvSearchParam.Q, TvSearchParam.Season, TvSearchParam.Ep
},
MovieSearchParams = new List<MovieSearchParam>
{
MovieSearchParam.Q
},
MusicSearchParams = new List<MusicSearchParam>
{
MusicSearchParam.Q
},
BookSearchParams = new List<BookSearchParam>
{
BookSearchParam.Q
}
};
caps.Categories.AddCategoryMapping(8000, NewznabStandardCategory.Other);
return caps;
}
}
public class TorrentParadiseMlRequestGenerator : IIndexerRequestGenerator
{
public TorrentParadiseMlSettings Settings { get; set; }
public IndexerCapabilities Capabilities { get; set; }
public TorrentParadiseMlRequestGenerator()
{
}
private IEnumerable<IndexerRequest> GetPagedRequests(string term)
{
var searchTerm = term;
if (string.IsNullOrWhiteSpace(searchTerm))
{
searchTerm = DateTime.Now.Year.ToString();
}
var qc = new NameValueCollection
{
{ "q", searchTerm }
};
var searchUrl = string.Format("{0}/api/search?{1}", Settings.BaseUrl.TrimEnd('/'), qc.GetQueryString());
var request = new IndexerRequest(searchUrl, HttpAccept.Json);
yield return request;
}
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm)));
return pageableRequests;
}
public IndexerPageableRequestChain GetSearchRequests(MusicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm)));
return pageableRequests;
}
public IndexerPageableRequestChain GetSearchRequests(TvSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedTvSearchString)));
return pageableRequests;
}
public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm)));
return pageableRequests;
}
public IndexerPageableRequestChain GetSearchRequests(BasicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm)));
return pageableRequests;
}
public Func<IDictionary<string, string>> GetCookies { get; set; }
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
}
public class TorrentParadiseMlParser : IParseIndexerResponse
{
private readonly TorrentParadiseMlSettings _settings;
public TorrentParadiseMlParser(TorrentParadiseMlSettings settings)
{
_settings = settings;
}
public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse)
{
var torrentInfos = new List<ReleaseInfo>();
if (indexerResponse.HttpResponse.StatusCode != HttpStatusCode.OK)
{
// Remove cookie cache
CookiesUpdater(null, null);
throw new IndexerException(indexerResponse, $"Unexpected response status {indexerResponse.HttpResponse.StatusCode} code from API request");
}
var results = JsonConvert.DeserializeObject<List<TorrentParadiseResult>>(indexerResponse.Content);
if (results == null)
{
return torrentInfos;
}
foreach (var result in results)
{
var magnetUrl = MagnetLinkBuilder.BuildPublicMagnetLink(result.Id, result.Text);
var release = new TorrentInfo
{
Title = result.Text,
Size = result.Size,
Seeders = result.Seeders,
Peers = result.Seeders + result.Leechers,
InfoHash = result.Id,
Guid = magnetUrl,
MagnetUrl = magnetUrl,
PublishDate = DateTime.UtcNow,
InfoUrl = _settings.BaseUrl,
DownloadVolumeFactor = 0,
UploadVolumeFactor = 1,
Categories = new List<IndexerCategory> { NewznabStandardCategory.Other }
};
torrentInfos.Add(release);
}
return torrentInfos.ToArray();
}
private class TorrentParadiseResult
{
public string Id { get; set; }
public string Text { get; set; }
[JsonProperty(PropertyName = "len")]
public long? Size { get; set; }
[JsonProperty(PropertyName = "s")]
public int? Seeders { get; set; }
[JsonProperty(PropertyName = "l")]
public int? Leechers { get; set; }
}
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
}
public class TorrentParadiseMlSettingsValidator : AbstractValidator<TorrentParadiseMlSettings>
{
}
public class TorrentParadiseMlSettings : IIndexerSettings
{
private static readonly TorrentParadiseMlSettingsValidator Validator = new TorrentParadiseMlSettingsValidator();
[FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2)]
public IndexerBaseSettings BaseSettings { get; set; } = new IndexerBaseSettings();
public NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));
}
}
}

@ -1,39 +1,20 @@
using FluentValidation; using FluentValidation;
using NzbDrone.Core.Annotations; using NzbDrone.Core.Annotations;
using NzbDrone.Core.Indexers.Settings;
using NzbDrone.Core.Validation; using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.TorrentPotato namespace NzbDrone.Core.Indexers.TorrentPotato
{ {
public class TorrentPotatoSettingsValidator : AbstractValidator<TorrentPotatoSettings> public class TorrentPotatoSettings : NoAuthTorrentBaseSettings
{ {
public TorrentPotatoSettingsValidator()
{
}
}
public class TorrentPotatoSettings : IIndexerSettings
{
private static readonly TorrentPotatoSettingsValidator Validator = new TorrentPotatoSettingsValidator();
public TorrentPotatoSettings() public TorrentPotatoSettings()
{ {
} }
[FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2, Label = "Username", HelpText = "Indexer Username", Privacy = PrivacyLevel.UserName)] [FieldDefinition(2, Label = "Username", HelpText = "Indexer Username", Privacy = PrivacyLevel.UserName)]
public string User { get; set; } public string User { get; set; }
[FieldDefinition(3, Label = "Passkey", HelpText = "Indexer Password", Privacy = PrivacyLevel.Password, Type = FieldType.Password)] [FieldDefinition(3, Label = "Passkey", HelpText = "Indexer Password", Privacy = PrivacyLevel.Password, Type = FieldType.Password)]
public string Passkey { get; set; } public string Passkey { get; set; }
[FieldDefinition(4)]
public IndexerBaseSettings BaseSettings { get; set; } = new IndexerBaseSettings();
public NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));
}
} }
} }

@ -1,378 +0,0 @@
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using AngleSharp.Html.Parser;
using FluentValidation;
using Newtonsoft.Json.Linq;
using NLog;
using NzbDrone.Common.Http;
using NzbDrone.Core.Annotations;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.Indexers.Exceptions;
using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Parser;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.Definitions
{
[Obsolete("Moved to YML for Cardigann v3")]
public class TorrentSeeds : TorrentIndexerBase<TorrentSeedsSettings>
{
public override string Name => "TorrentSeeds";
public override string[] IndexerUrls => new string[] { "https://torrentseeds.org/" };
public override string Description => "TorrentSeeds is a Private site for MOVIES / TV / GENERAL";
private string LoginUrl => Settings.BaseUrl + "takelogin.php";
private string CaptchaUrl => Settings.BaseUrl + "simpleCaptcha.php?numImages=1";
private string TokenUrl => Settings.BaseUrl + "login.php";
public override DownloadProtocol Protocol => DownloadProtocol.Torrent;
public override IndexerPrivacy Privacy => IndexerPrivacy.Private;
public override IndexerCapabilities Capabilities => SetCapabilities();
public TorrentSeeds(IIndexerHttpClient httpClient, IEventAggregator eventAggregator, IIndexerStatusService indexerStatusService, IConfigService configService, Logger logger)
: base(httpClient, eventAggregator, indexerStatusService, configService, logger)
{
}
public override IIndexerRequestGenerator GetRequestGenerator()
{
return new TorrentSeedsRequestGenerator() { Settings = Settings, Capabilities = Capabilities };
}
public override IParseIndexerResponse GetParser()
{
return new TorrentSeedsParser(Settings, Capabilities.Categories);
}
protected override async Task DoLogin()
{
var requestBuilder = new HttpRequestBuilder(LoginUrl)
{
LogResponseContent = true
};
Cookies = null;
var loginPage = await ExecuteAuth(new HttpRequest(CaptchaUrl));
var json1 = JObject.Parse(loginPage.Content);
var captchaSelection = json1["images"][0]["hash"];
requestBuilder.Method = HttpMethod.Post;
requestBuilder.PostProcess += r => r.RequestTimeout = TimeSpan.FromSeconds(15);
requestBuilder.SetCookies(loginPage.GetCookies());
var authLoginRequest = requestBuilder
.AddFormParameter("username", Settings.Username)
.AddFormParameter("password", Settings.Password)
.AddFormParameter("submitme", "X")
.AddFormParameter("captchaSelection", (string)captchaSelection)
.SetHeader("Content-Type", "multipart/form-data")
.Build();
var response = await ExecuteAuth(authLoginRequest);
if (CheckIfLoginNeeded(response))
{
throw new IndexerAuthException("TorrentSeeds Login Failed");
}
var cookies = response.GetCookies();
UpdateCookies(cookies, DateTime.Now + TimeSpan.FromDays(30));
_logger.Debug("TorrentSeeds authentication succeeded.");
}
protected override bool CheckIfLoginNeeded(HttpResponse httpResponse)
{
if ((httpResponse.HasHttpRedirect && httpResponse.Headers.GetSingleValue("Location").Contains("/login.php?")) ||
(!httpResponse.HasHttpRedirect && !httpResponse.Content.Contains("/logout.php?")))
{
return true;
}
return false;
}
private IndexerCapabilities SetCapabilities()
{
var caps = new IndexerCapabilities
{
TvSearchParams = new List<TvSearchParam>
{
TvSearchParam.Q, TvSearchParam.Season, TvSearchParam.Ep
},
MovieSearchParams = new List<MovieSearchParam>
{
MovieSearchParam.Q
},
MusicSearchParams = new List<MusicSearchParam>
{
MusicSearchParam.Q
},
BookSearchParams = new List<BookSearchParam>
{
BookSearchParam.Q
}
};
caps.Categories.AddCategoryMapping(37, NewznabStandardCategory.TVAnime, "Anime/HD");
caps.Categories.AddCategoryMapping(9, NewznabStandardCategory.TVAnime, "Anime/SD");
caps.Categories.AddCategoryMapping(72, NewznabStandardCategory.TVAnime, "Anime/UHD");
caps.Categories.AddCategoryMapping(13, NewznabStandardCategory.PC0day, "Apps/0DAY");
caps.Categories.AddCategoryMapping(27, NewznabStandardCategory.Books, "Apps/Bookware");
caps.Categories.AddCategoryMapping(1, NewznabStandardCategory.PCISO, "Apps/ISO");
caps.Categories.AddCategoryMapping(73, NewznabStandardCategory.AudioAudiobook, "Music/Audiobooks");
caps.Categories.AddCategoryMapping(47, NewznabStandardCategory.ConsoleOther, "Console/NSW");
caps.Categories.AddCategoryMapping(8, NewznabStandardCategory.ConsolePS3, "Console/PS3");
caps.Categories.AddCategoryMapping(30, NewznabStandardCategory.ConsolePS4, "Console/PS4");
caps.Categories.AddCategoryMapping(71, NewznabStandardCategory.ConsolePS4, "Console/PS5");
caps.Categories.AddCategoryMapping(7, NewznabStandardCategory.ConsolePSP, "Console/PSP");
caps.Categories.AddCategoryMapping(70, NewznabStandardCategory.ConsolePSVita, "Console/PSV");
caps.Categories.AddCategoryMapping(16, NewznabStandardCategory.ConsoleWii, "Console/WII");
caps.Categories.AddCategoryMapping(29, NewznabStandardCategory.ConsoleWiiU, "Console/WIIU");
caps.Categories.AddCategoryMapping(17, NewznabStandardCategory.ConsoleXBox360, "Console/XBOX360");
caps.Categories.AddCategoryMapping(32, NewznabStandardCategory.BooksEBook, "E-books");
caps.Categories.AddCategoryMapping(63, NewznabStandardCategory.ConsoleOther, "Games/DOX");
caps.Categories.AddCategoryMapping(2, NewznabStandardCategory.PCGames, "Games/ISO");
caps.Categories.AddCategoryMapping(12, NewznabStandardCategory.PCGames, "Games/PC Rips");
caps.Categories.AddCategoryMapping(31, NewznabStandardCategory.MoviesBluRay, "Movies/Bluray");
caps.Categories.AddCategoryMapping(50, NewznabStandardCategory.MoviesBluRay, "Movies/Bluray-UHD");
caps.Categories.AddCategoryMapping(3, NewznabStandardCategory.MoviesDVD, "Movies/DVDR");
caps.Categories.AddCategoryMapping(69, NewznabStandardCategory.MoviesForeign, "Movies/DVDR-Foreign");
caps.Categories.AddCategoryMapping(19, NewznabStandardCategory.MoviesHD, "Movies/HD");
caps.Categories.AddCategoryMapping(39, NewznabStandardCategory.MoviesForeign, "Movies/HD-Foreign");
caps.Categories.AddCategoryMapping(74, NewznabStandardCategory.MoviesHD, "Movies/Remuxes");
caps.Categories.AddCategoryMapping(25, NewznabStandardCategory.MoviesSD, "Movies/SD");
caps.Categories.AddCategoryMapping(62, NewznabStandardCategory.MoviesForeign, "Movies/SD-Foreign");
caps.Categories.AddCategoryMapping(49, NewznabStandardCategory.MoviesUHD, "Movies/UHD");
caps.Categories.AddCategoryMapping(76, NewznabStandardCategory.MoviesForeign, "Movies/UHD-Foreign");
caps.Categories.AddCategoryMapping(33, NewznabStandardCategory.AudioLossless, "Music/FLAC");
caps.Categories.AddCategoryMapping(28, NewznabStandardCategory.AudioOther, "Music/MBluRay-Rips");
caps.Categories.AddCategoryMapping(34, NewznabStandardCategory.AudioOther, "Music/MDVDR");
caps.Categories.AddCategoryMapping(4, NewznabStandardCategory.AudioMP3, "Music/MP3");
caps.Categories.AddCategoryMapping(20, NewznabStandardCategory.AudioVideo, "Music/MVID");
caps.Categories.AddCategoryMapping(77, NewznabStandardCategory.TVAnime, "Anime/Packs");
caps.Categories.AddCategoryMapping(78, NewznabStandardCategory.BooksEBook, "Books/Packs");
caps.Categories.AddCategoryMapping(80, NewznabStandardCategory.MoviesHD, "Movies/HD-Packs");
caps.Categories.AddCategoryMapping(81, NewznabStandardCategory.MoviesHD, "Movies/Remux-Packs");
caps.Categories.AddCategoryMapping(79, NewznabStandardCategory.MoviesSD, "Movies/SD-Packs");
caps.Categories.AddCategoryMapping(68, NewznabStandardCategory.Audio, "Music/Packs");
caps.Categories.AddCategoryMapping(67, NewznabStandardCategory.TVHD, "TV/HD-Packs");
caps.Categories.AddCategoryMapping(82, NewznabStandardCategory.TVHD, "TV/Remux-Packs");
caps.Categories.AddCategoryMapping(65, NewznabStandardCategory.TVSD, "TV/SD-Packs");
caps.Categories.AddCategoryMapping(84, NewznabStandardCategory.TVUHD, "TV/UHD-Packs");
caps.Categories.AddCategoryMapping(85, NewznabStandardCategory.XXX, "XXX/Packs");
caps.Categories.AddCategoryMapping(23, NewznabStandardCategory.TVSD, "TV/DVDR");
caps.Categories.AddCategoryMapping(26, NewznabStandardCategory.TVHD, "TV/HD");
caps.Categories.AddCategoryMapping(64, NewznabStandardCategory.TVForeign, "TV/HD-Foreign");
caps.Categories.AddCategoryMapping(11, NewznabStandardCategory.TVHD, "TV/HD-Retail");
caps.Categories.AddCategoryMapping(36, NewznabStandardCategory.TVSport, "TV/HD-Sport");
caps.Categories.AddCategoryMapping(18, NewznabStandardCategory.TVSD, "TV/SD");
caps.Categories.AddCategoryMapping(86, NewznabStandardCategory.TVForeign, "TV/SD-Foreign");
caps.Categories.AddCategoryMapping(24, NewznabStandardCategory.TVSD, "TV/SD-Retail");
caps.Categories.AddCategoryMapping(35, NewznabStandardCategory.TVSport, "TV/SD-Sport");
caps.Categories.AddCategoryMapping(61, NewznabStandardCategory.TVUHD, "TV/UHD");
caps.Categories.AddCategoryMapping(87, NewznabStandardCategory.TVForeign, "TV/UHD-Foreign");
caps.Categories.AddCategoryMapping(53, NewznabStandardCategory.XXX, "XXX/HD");
caps.Categories.AddCategoryMapping(88, NewznabStandardCategory.XXXImageSet, "XXX/Image-Sets");
caps.Categories.AddCategoryMapping(57, NewznabStandardCategory.XXX, "XXX/Paysite");
caps.Categories.AddCategoryMapping(6, NewznabStandardCategory.XXX, "XXX/SD");
return caps;
}
}
public class TorrentSeedsRequestGenerator : IIndexerRequestGenerator
{
public TorrentSeedsSettings Settings { get; set; }
public IndexerCapabilities Capabilities { get; set; }
public TorrentSeedsRequestGenerator()
{
}
private IEnumerable<IndexerRequest> GetPagedRequests(string term, int[] categories)
{
// remove operator characters
var cleanSearchString = Regex.Replace(term.Trim(), "[ _.+-]+", " ", RegexOptions.Compiled);
var searchUrl = Settings.BaseUrl + "browse_elastic.php";
var queryCollection = new NameValueCollection
{
{ "search_in", "name" },
{ "search_mode", "all" },
{ "order_by", "added" },
{ "order_way", "desc" }
};
if (!string.IsNullOrWhiteSpace(cleanSearchString))
{
queryCollection.Add("query", cleanSearchString);
}
foreach (var cat in Capabilities.Categories.MapTorznabCapsToTrackers(categories))
{
queryCollection.Add($"cat[{cat}]", "1");
}
searchUrl += "?" + queryCollection.GetQueryString();
var request = new IndexerRequest(searchUrl, HttpAccept.Html);
yield return request;
}
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories));
return pageableRequests;
}
public IndexerPageableRequestChain GetSearchRequests(MusicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories));
return pageableRequests;
}
public IndexerPageableRequestChain GetSearchRequests(TvSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedTvSearchString), searchCriteria.Categories));
return pageableRequests;
}
public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories));
return pageableRequests;
}
public IndexerPageableRequestChain GetSearchRequests(BasicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories));
return pageableRequests;
}
public Func<IDictionary<string, string>> GetCookies { get; set; }
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
}
public class TorrentSeedsParser : IParseIndexerResponse
{
private readonly TorrentSeedsSettings _settings;
private readonly IndexerCapabilitiesCategories _categories;
public TorrentSeedsParser(TorrentSeedsSettings settings, IndexerCapabilitiesCategories categories)
{
_settings = settings;
_categories = categories;
}
public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse)
{
var torrentInfos = new List<TorrentInfo>();
var parser = new HtmlParser();
var dom = parser.ParseDocument(indexerResponse.Content);
var rows = dom.QuerySelectorAll("table.table-bordered > tbody > tr[class*=\"torrent_row_\"]");
foreach (var row in rows)
{
var release = new TorrentInfo();
release.MinimumRatio = 1;
release.MinimumSeedTime = 72 * 60 * 60;
var qCatLink = row.QuerySelector("a[href^=\"/browse_elastic.php?cat=\"]");
var catStr = qCatLink.GetAttribute("href").Split('=')[1];
release.Categories = _categories.MapTrackerCatToNewznab(catStr);
var qDetailsLink = row.QuerySelector("a[href^=\"/details.php?id=\"]");
var qDetailsTitle = row.QuerySelector("td:has(a[href^=\"/details.php?id=\"]) b");
release.Title = qDetailsTitle.TextContent.Trim();
var qDlLink = row.QuerySelector("a[href^=\"/download.php?torrent=\"]");
release.DownloadUrl = _settings.BaseUrl + qDlLink.GetAttribute("href").TrimStart('/');
release.InfoUrl = _settings.BaseUrl + qDetailsLink.GetAttribute("href").TrimStart('/');
release.Guid = release.InfoUrl;
var qColumns = row.QuerySelectorAll("td");
release.Files = ParseUtil.CoerceInt(qColumns[3].TextContent);
release.PublishDate = DateTimeUtil.FromUnknown(qColumns[5].TextContent);
release.Size = ParseUtil.GetBytes(qColumns[6].TextContent);
release.Grabs = ParseUtil.CoerceInt(qColumns[7].TextContent.Replace("Times", ""));
release.Seeders = ParseUtil.CoerceInt(qColumns[8].TextContent);
release.Peers = ParseUtil.CoerceInt(qColumns[9].TextContent) + release.Seeders;
var qImdb = row.QuerySelector("a[href*=\"www.imdb.com\"]");
if (qImdb != null)
{
var deRefUrl = qImdb.GetAttribute("href");
release.ImdbId = ParseUtil.GetImdbID(WebUtility.UrlDecode(deRefUrl).Split('/').Last()) ?? 0;
}
release.DownloadVolumeFactor = row.QuerySelector("span.freeleech") != null ? 0 : 1;
release.UploadVolumeFactor = 1;
torrentInfos.Add(release);
}
return torrentInfos.ToArray();
}
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
}
public class TorrentSeedsSettingsValidator : AbstractValidator<TorrentSeedsSettings>
{
public TorrentSeedsSettingsValidator()
{
RuleFor(c => c.Username).NotEmpty();
RuleFor(c => c.Password).NotEmpty();
}
}
public class TorrentSeedsSettings : IIndexerSettings
{
private static readonly TorrentSeedsSettingsValidator Validator = new TorrentSeedsSettingsValidator();
public TorrentSeedsSettings()
{
Username = "";
Password = "";
}
[FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2, Label = "Username", HelpText = "Site Username", Privacy = PrivacyLevel.UserName)]
public string Username { get; set; }
[FieldDefinition(3, Label = "Password", HelpText = "Site Password", Privacy = PrivacyLevel.Password, Type = FieldType.Password)]
public string Password { get; set; }
[FieldDefinition(4)]
public IndexerBaseSettings BaseSettings { get; set; } = new IndexerBaseSettings();
public NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));
}
}
}

@ -10,6 +10,7 @@ using NLog;
using NzbDrone.Common.Http; using NzbDrone.Common.Http;
using NzbDrone.Core.Annotations; using NzbDrone.Core.Annotations;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.Indexers.Settings;
using NzbDrone.Core.IndexerSearch.Definitions; using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
@ -330,7 +331,7 @@ namespace NzbDrone.Core.Indexers.Definitions
} }
} }
public class TorrentSyndikatSettings : IIndexerSettings public class TorrentSyndikatSettings : NoAuthTorrentBaseSettings
{ {
private static readonly TorrentSyndikatSettingsValidator Validator = new TorrentSyndikatSettingsValidator(); private static readonly TorrentSyndikatSettingsValidator Validator = new TorrentSyndikatSettingsValidator();
@ -340,9 +341,6 @@ namespace NzbDrone.Core.Indexers.Definitions
ReleaseTypes = new List<int>(); ReleaseTypes = new List<int>();
} }
[FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2, Label = "API Key", Privacy = PrivacyLevel.ApiKey, HelpText = "Site API Key")] [FieldDefinition(2, Label = "API Key", Privacy = PrivacyLevel.ApiKey, HelpText = "Site API Key")]
public string ApiKey { get; set; } public string ApiKey { get; set; }
@ -352,10 +350,7 @@ namespace NzbDrone.Core.Indexers.Definitions
[FieldDefinition(4, Label = "Release Types", Type = FieldType.Select, SelectOptions = typeof(TorrentSyndikatReleaseTypes))] [FieldDefinition(4, Label = "Release Types", Type = FieldType.Select, SelectOptions = typeof(TorrentSyndikatReleaseTypes))]
public IEnumerable<int> ReleaseTypes { get; set; } public IEnumerable<int> ReleaseTypes { get; set; }
[FieldDefinition(5)] public override NzbDroneValidationResult Validate()
public IndexerBaseSettings BaseSettings { get; set; } = new IndexerBaseSettings();
public NzbDroneValidationResult Validate()
{ {
return new NzbDroneValidationResult(Validator.Validate(this)); return new NzbDroneValidationResult(Validator.Validate(this));
} }

@ -9,6 +9,7 @@ using NzbDrone.Common.Extensions;
using NzbDrone.Common.Http; using NzbDrone.Common.Http;
using NzbDrone.Core.Annotations; using NzbDrone.Core.Annotations;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.Indexers.Settings;
using NzbDrone.Core.IndexerSearch.Definitions; using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
@ -17,7 +18,7 @@ using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.Definitions namespace NzbDrone.Core.Indexers.Definitions
{ {
public class TorrentsCSV : TorrentIndexerBase<TorrentsCSVSettings> public class TorrentsCSV : TorrentIndexerBase<NoAuthTorrentBaseSettings>
{ {
public override string Name => "TorrentsCSV"; public override string Name => "TorrentsCSV";
public override string[] IndexerUrls => new[] { "https://torrents-csv.ml/" }; public override string[] IndexerUrls => new[] { "https://torrents-csv.ml/" };
@ -66,7 +67,7 @@ namespace NzbDrone.Core.Indexers.Definitions
public class TorrentsCSVRequestGenerator : IIndexerRequestGenerator public class TorrentsCSVRequestGenerator : IIndexerRequestGenerator
{ {
public TorrentsCSVSettings Settings { get; set; } public NoAuthTorrentBaseSettings Settings { get; set; }
public IndexerCapabilities Capabilities { get; set; } public IndexerCapabilities Capabilities { get; set; }
public TorrentsCSVRequestGenerator() public TorrentsCSVRequestGenerator()
@ -137,9 +138,9 @@ namespace NzbDrone.Core.Indexers.Definitions
public class TorrentsCSVParser : IParseIndexerResponse public class TorrentsCSVParser : IParseIndexerResponse
{ {
private readonly TorrentsCSVSettings _settings; private readonly NoAuthTorrentBaseSettings _settings;
public TorrentsCSVParser(TorrentsCSVSettings settings) public TorrentsCSVParser(NoAuthTorrentBaseSettings settings)
{ {
_settings = settings; _settings = settings;
} }
@ -193,24 +194,4 @@ namespace NzbDrone.Core.Indexers.Definitions
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; } public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
} }
public class TorrentsCSVSettingsValidator : AbstractValidator<TorrentsCSVSettings>
{
}
public class TorrentsCSVSettings : IIndexerSettings
{
private static readonly TorrentsCSVSettingsValidator Validator = new TorrentsCSVSettingsValidator();
[FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2)]
public IndexerBaseSettings BaseSettings { get; set; } = new IndexerBaseSettings();
public NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));
}
}
} }

@ -1,5 +1,6 @@
using FluentValidation; using FluentValidation;
using NzbDrone.Core.Annotations; using NzbDrone.Core.Annotations;
using NzbDrone.Core.Indexers.Settings;
using NzbDrone.Core.Validation; using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.Definitions.UNIT3D namespace NzbDrone.Core.Indexers.Definitions.UNIT3D
@ -12,7 +13,7 @@ namespace NzbDrone.Core.Indexers.Definitions.UNIT3D
} }
} }
public class Unit3dSettings : IIndexerSettings public class Unit3dSettings : NoAuthTorrentBaseSettings
{ {
private static readonly Unit3dSettingsValidator Validator = new Unit3dSettingsValidator(); private static readonly Unit3dSettingsValidator Validator = new Unit3dSettingsValidator();
@ -20,16 +21,10 @@ namespace NzbDrone.Core.Indexers.Definitions.UNIT3D
{ {
} }
[FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2, Label = "API Key", HelpText = "Site API Key generated in My Security", Privacy = PrivacyLevel.ApiKey)] [FieldDefinition(2, Label = "API Key", HelpText = "Site API Key generated in My Security", Privacy = PrivacyLevel.ApiKey)]
public string ApiKey { get; set; } public string ApiKey { get; set; }
[FieldDefinition(3)] public override NzbDroneValidationResult Validate()
public IndexerBaseSettings BaseSettings { get; set; } = new IndexerBaseSettings();
public NzbDroneValidationResult Validate()
{ {
return new NzbDroneValidationResult(Validator.Validate(this)); return new NzbDroneValidationResult(Validator.Validate(this));
} }

@ -1,9 +1,10 @@
using NzbDrone.Core.Annotations; using NzbDrone.Core.Annotations;
using NzbDrone.Core.Indexers.Settings;
using NzbDrone.Core.Validation; using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.Definitions.Xthor namespace NzbDrone.Core.Indexers.Definitions.Xthor
{ {
public class XthorSettings : IIndexerSettings public class XthorSettings : NoAuthTorrentBaseSettings
{ {
private static readonly XthorSettingsValidator Validator = new XthorSettingsValidator(); private static readonly XthorSettingsValidator Validator = new XthorSettingsValidator();
@ -22,9 +23,6 @@ namespace NzbDrone.Core.Indexers.Definitions.Xthor
MaxPages = 1; MaxPages = 1;
} }
[FieldDefinition(1, Label = "Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2, Label = "Passkey", Privacy = PrivacyLevel.Password, Type = FieldType.Password, HelpText = "Site Passkey")] [FieldDefinition(2, Label = "Passkey", Privacy = PrivacyLevel.Password, Type = FieldType.Password, HelpText = "Site Passkey")]
public string Passkey { get; set; } public string Passkey { get; set; }
@ -55,11 +53,9 @@ namespace NzbDrone.Core.Indexers.Definitions.Xthor
[FieldDefinition(11, Label = "How many pages do you want to follow?", Type = FieldType.Select, SelectOptions = typeof(XthorPagesNumber), HelpText = "(not recommended) you can increase max pages to follow when making a request. But be aware that this API is very buggy on tracker side, most of time, results of next pages are same as the first page. Even if we deduplicate rows, you will loose performance for the same results.", Advanced = true)] [FieldDefinition(11, Label = "How many pages do you want to follow?", Type = FieldType.Select, SelectOptions = typeof(XthorPagesNumber), HelpText = "(not recommended) you can increase max pages to follow when making a request. But be aware that this API is very buggy on tracker side, most of time, results of next pages are same as the first page. Even if we deduplicate rows, you will loose performance for the same results.", Advanced = true)]
public int MaxPages { get; set; } public int MaxPages { get; set; }
public NzbDroneValidationResult Validate() public override NzbDroneValidationResult Validate()
{ {
return new NzbDroneValidationResult(Validator.Validate(this)); return new NzbDroneValidationResult(Validator.Validate(this));
} }
public IndexerBaseSettings BaseSettings { get; set; } = new IndexerBaseSettings();
} }
} }

@ -1,308 +0,0 @@
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Globalization;
using System.Text;
using FluentValidation;
using Newtonsoft.Json.Linq;
using NLog;
using NzbDrone.Common.Extensions;
using NzbDrone.Common.Http;
using NzbDrone.Core.Annotations;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Parser;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.Definitions
{
[Obsolete("Moved to YML for Cardigann v3")]
public class YTS : TorrentIndexerBase<YTSSettings>
{
public override string Name => "YTS";
public override string[] IndexerUrls => new string[] { "https://yts.mx/" };
public override string Language => "en-US";
public override string Description => "YTS is a Public torrent site specialising in HD movies of small size";
public override Encoding Encoding => Encoding.GetEncoding("windows-1252");
public override DownloadProtocol Protocol => DownloadProtocol.Torrent;
public override IndexerPrivacy Privacy => IndexerPrivacy.Public;
public override TimeSpan RateLimit => TimeSpan.FromSeconds(2.5);
public override IndexerCapabilities Capabilities => SetCapabilities();
public YTS(IIndexerHttpClient httpClient, IEventAggregator eventAggregator, IIndexerStatusService indexerStatusService, IConfigService configService, Logger logger)
: base(httpClient, eventAggregator, indexerStatusService, configService, logger)
{
}
public override IIndexerRequestGenerator GetRequestGenerator()
{
return new YTSRequestGenerator() { Settings = Settings, Capabilities = Capabilities };
}
public override IParseIndexerResponse GetParser()
{
return new YTSParser(Settings, Capabilities.Categories);
}
private IndexerCapabilities SetCapabilities()
{
var caps = new IndexerCapabilities
{
TvSearchParams = new List<TvSearchParam>
{
},
MovieSearchParams = new List<MovieSearchParam> { MovieSearchParam.Q, MovieSearchParam.ImdbId },
MusicSearchParams = new List<MusicSearchParam>
{
},
BookSearchParams = new List<BookSearchParam>
{
}
};
caps.Categories.AddCategoryMapping(45, NewznabStandardCategory.MoviesHD, "Movies/x264/720p");
caps.Categories.AddCategoryMapping(44, NewznabStandardCategory.MoviesHD, "Movies/x264/1080p");
caps.Categories.AddCategoryMapping(46, NewznabStandardCategory.MoviesUHD, "Movies/x264/2160p");
caps.Categories.AddCategoryMapping(47, NewznabStandardCategory.Movies3D, "Movies/x264/3D");
return caps;
}
}
public class YTSRequestGenerator : IIndexerRequestGenerator
{
public YTSSettings Settings { get; set; }
public IndexerCapabilities Capabilities { get; set; }
public YTSRequestGenerator()
{
}
private IEnumerable<IndexerRequest> GetPagedRequests(string term, int[] categories, string imdbId = null)
{
var searchUrl = string.Format("{0}/api/v2/list_movies.json", Settings.BaseUrl.TrimEnd('/'));
var searchString = term;
var queryCollection = new NameValueCollection
{
// without this the API sometimes returns nothing
{ "sort", "date_added" },
{ "limit", "50" }
};
if (imdbId.IsNotNullOrWhiteSpace())
{
queryCollection.Add("query_term", imdbId);
}
else if (!string.IsNullOrWhiteSpace(searchString))
{
searchString = searchString.Replace("'", ""); // ignore ' (e.g. search for america's Next Top Model)
queryCollection.Add("query_term", searchString);
}
searchUrl = searchUrl + "?" + queryCollection.GetQueryString();
var request = new IndexerRequest(searchUrl, HttpAccept.Html);
yield return request;
}
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories, searchCriteria.FullImdbId));
return pageableRequests;
}
public IndexerPageableRequestChain GetSearchRequests(MusicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
return pageableRequests;
}
public IndexerPageableRequestChain GetSearchRequests(TvSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
return pageableRequests;
}
public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
return pageableRequests;
}
public IndexerPageableRequestChain GetSearchRequests(BasicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories));
return pageableRequests;
}
public Func<IDictionary<string, string>> GetCookies { get; set; }
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
}
public class YTSParser : IParseIndexerResponse
{
private readonly YTSSettings _settings;
private readonly IndexerCapabilitiesCategories _categories;
public YTSParser(YTSSettings settings, IndexerCapabilitiesCategories categories)
{
_settings = settings;
_categories = categories;
}
public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse)
{
var torrentInfos = new List<ReleaseInfo>();
var contentString = indexerResponse.Content;
// returned content might start with an html error message, remove it first
var jsonStart = contentString.IndexOf('{');
var jsonContentStr = contentString.Remove(0, jsonStart);
var jsonContent = JObject.Parse(jsonContentStr);
var result = jsonContent.Value<string>("status");
// query was not successful
if (result != "ok")
{
return new List<ReleaseInfo>();
}
var dataItems = jsonContent.Value<JToken>("data");
var movieCount = dataItems.Value<int>("movie_count");
// no results found in query
if (movieCount < 1)
{
return new List<ReleaseInfo>();
}
var movies = dataItems.Value<JToken>("movies");
if (movies == null)
{
return new List<ReleaseInfo>();
}
foreach (var movie in movies)
{
var torrents = movie.Value<JArray>("torrents");
if (torrents == null)
{
continue;
}
foreach (var torrent in torrents)
{
var release = new TorrentInfo();
// append type: BRRip or WEBRip, resolves #3558 via #4577
var type = torrent.Value<string>("type");
switch (type)
{
case "web":
type = "WEBRip";
break;
default:
type = "BRRip";
break;
}
var quality = torrent.Value<string>("quality");
var title = movie.Value<string>("title").Replace(":", "").Replace(' ', '.');
var year = movie.Value<int>("year");
release.Title = $"{title}.{year}.{quality}.{type}-YTS";
var imdb = movie.Value<string>("imdb_code");
release.ImdbId = ParseUtil.GetImdbID(imdb).Value;
release.InfoHash = torrent.Value<string>("hash"); // magnet link is auto generated from infohash
// ex: 2015-08-16 21:25:08 +0000
var dateStr = torrent.Value<string>("date_uploaded");
var dateTime = DateTime.ParseExact(dateStr, "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture);
release.PublishDate = DateTime.SpecifyKind(dateTime, DateTimeKind.Utc).ToLocalTime();
release.DownloadUrl = torrent.Value<string>("url");
release.Seeders = torrent.Value<int>("seeds");
release.Peers = torrent.Value<int>("peers") + release.Seeders;
release.Size = torrent.Value<long>("size_bytes");
release.DownloadVolumeFactor = 0;
release.UploadVolumeFactor = 1;
release.InfoUrl = movie.Value<string>("url");
release.PosterUrl = new Uri(movie.Value<string>("large_cover_image")).AbsoluteUri;
release.Guid = release.DownloadUrl;
// map the quality to a newznab category for torznab compatibility (for Radarr, etc)
switch (quality)
{
case "720p":
release.Categories = _categories.MapTrackerCatToNewznab("45");
break;
case "1080p":
release.Categories = _categories.MapTrackerCatToNewznab("44");
break;
case "2160p":
release.Categories = _categories.MapTrackerCatToNewznab("46");
break;
case "3D":
release.Categories = _categories.MapTrackerCatToNewznab("47");
break;
default:
release.Categories = _categories.MapTrackerCatToNewznab("45");
break;
}
if (release == null)
{
continue;
}
torrentInfos.Add(release);
}
}
return torrentInfos.ToArray();
}
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
}
public class YTSSettingsValidator : AbstractValidator<YTSSettings>
{
}
public class YTSSettings : IIndexerSettings
{
private static readonly YTSSettingsValidator Validator = new YTSSettingsValidator();
[FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2)]
public IndexerBaseSettings BaseSettings { get; set; } = new IndexerBaseSettings();
public NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));
}
}
}

@ -17,6 +17,7 @@ using NzbDrone.Common.Http;
using NzbDrone.Core.Annotations; using NzbDrone.Core.Annotations;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.Indexers.Exceptions; using NzbDrone.Core.Indexers.Exceptions;
using NzbDrone.Core.Indexers.Settings;
using NzbDrone.Core.IndexerSearch.Definitions; using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
@ -25,7 +26,7 @@ using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.Definitions namespace NzbDrone.Core.Indexers.Definitions
{ {
public class ZonaQ : TorrentIndexerBase<ZonaQSettings> public class ZonaQ : TorrentIndexerBase<UserPassTorrentBaseSettings>
{ {
public override string Name => "ZonaQ"; public override string Name => "ZonaQ";
public override string[] IndexerUrls => new string[] { "https://www.zonaq.pw/" }; public override string[] IndexerUrls => new string[] { "https://www.zonaq.pw/" };
@ -234,7 +235,7 @@ namespace NzbDrone.Core.Indexers.Definitions
public class ZonaQRequestGenerator : IIndexerRequestGenerator public class ZonaQRequestGenerator : IIndexerRequestGenerator
{ {
public ZonaQSettings Settings { get; set; } public UserPassTorrentBaseSettings Settings { get; set; }
public IndexerCapabilities Capabilities { get; set; } public IndexerCapabilities Capabilities { get; set; }
public ZonaQRequestGenerator() public ZonaQRequestGenerator()
@ -316,10 +317,10 @@ namespace NzbDrone.Core.Indexers.Definitions
public class ZonaQParser : IParseIndexerResponse public class ZonaQParser : IParseIndexerResponse
{ {
private readonly ZonaQSettings _settings; private readonly UserPassTorrentBaseSettings _settings;
private readonly IndexerCapabilitiesCategories _categories; private readonly IndexerCapabilitiesCategories _categories;
public ZonaQParser(ZonaQSettings settings, IndexerCapabilitiesCategories categories) public ZonaQParser(UserPassTorrentBaseSettings settings, IndexerCapabilitiesCategories categories)
{ {
_settings = settings; _settings = settings;
_categories = categories; _categories = categories;
@ -397,41 +398,4 @@ namespace NzbDrone.Core.Indexers.Definitions
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; } public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
} }
public class ZonaQSettingsValidator : AbstractValidator<ZonaQSettings>
{
public ZonaQSettingsValidator()
{
RuleFor(c => c.Username).NotEmpty();
RuleFor(c => c.Password).NotEmpty();
}
}
public class ZonaQSettings : IIndexerSettings
{
private static readonly ZonaQSettingsValidator Validator = new ZonaQSettingsValidator();
public ZonaQSettings()
{
Username = "";
Password = "";
}
[FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2, Label = "Username", HelpText = "Site Username", Privacy = PrivacyLevel.UserName)]
public string Username { get; set; }
[FieldDefinition(3, Label = "Password", HelpText = "Site Password", Privacy = PrivacyLevel.Password, Type = FieldType.Password)]
public string Password { get; set; }
[FieldDefinition(4)]
public IndexerBaseSettings BaseSettings { get; set; } = new IndexerBaseSettings();
public NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));
}
}
} }

@ -0,0 +1,38 @@
using FluentValidation;
using NzbDrone.Core.Annotations;
using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.Settings
{
public class CookieTorrentBaseSettings : IIndexerSettings
{
public class CookieBaseSettingsValidator : AbstractValidator<CookieTorrentBaseSettings>
{
public CookieBaseSettingsValidator()
{
RuleFor(c => c.Cookie).NotEmpty();
}
}
private static readonly CookieBaseSettingsValidator Validator = new CookieBaseSettingsValidator();
public CookieTorrentBaseSettings()
{
Cookie = "";
}
[FieldDefinition(1, Label = "Base Url", HelpText = "Select which baseurl Prowlarr will use for requests to the site", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls")]
public string BaseUrl { get; set; }
[FieldDefinition(2, Label = "Cookie", HelpText = "Site Cookie", Privacy = PrivacyLevel.Password, Type = FieldType.Password)]
public string Cookie { get; set; }
[FieldDefinition(3)]
public IndexerBaseSettings BaseSettings { get; set; } = new IndexerBaseSettings();
public NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));
}
}
}

@ -0,0 +1,26 @@
using FluentValidation;
using NzbDrone.Core.Annotations;
using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.Settings
{
public class NoAuthSettingsValidator : AbstractValidator<NoAuthTorrentBaseSettings>
{
}
public class NoAuthTorrentBaseSettings : IIndexerSettings
{
private static readonly NoAuthSettingsValidator Validator = new NoAuthSettingsValidator();
[FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2)]
public IndexerBaseSettings BaseSettings { get; set; } = new IndexerBaseSettings();
public virtual NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));
}
}
}

@ -0,0 +1,43 @@
using FluentValidation;
using NzbDrone.Core.Annotations;
using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.Settings
{
public class UserPassTorrentBaseSettings : IIndexerSettings
{
public class UserPassBaseSettingsValidator : AbstractValidator<UserPassTorrentBaseSettings>
{
public UserPassBaseSettingsValidator()
{
RuleFor(c => c.Username).NotEmpty();
RuleFor(c => c.Password).NotEmpty();
}
}
private static readonly UserPassBaseSettingsValidator Validator = new UserPassBaseSettingsValidator();
public UserPassTorrentBaseSettings()
{
Username = "";
Password = "";
}
[FieldDefinition(1, Label = "Base Url", HelpText = "Select which baseurl Prowlarr will use for requests to the site", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls")]
public string BaseUrl { get; set; }
[FieldDefinition(2, Label = "Username", HelpText = "Site Username", Privacy = PrivacyLevel.UserName)]
public string Username { get; set; }
[FieldDefinition(3, Label = "Password", HelpText = "Site Password", Privacy = PrivacyLevel.Password, Type = FieldType.Password)]
public string Password { get; set; }
[FieldDefinition(4)]
public IndexerBaseSettings BaseSettings { get; set; } = new IndexerBaseSettings();
public NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));
}
}
}
Loading…
Cancel
Save