mirror of
https://github.com/Radarr/Radarr
synced 2026-01-25 08:53:02 +01:00
feat(indexer): add MyAnonamouse indexer for books and audiobooks
This commit is contained in:
parent
6328e72c96
commit
2bf1fe4367
6 changed files with 583 additions and 0 deletions
35
src/NzbDrone.Core/Indexers/MyAnonamouse/MyAnonamouse.cs
Normal file
35
src/NzbDrone.Core/Indexers/MyAnonamouse/MyAnonamouse.cs
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
using System.Collections.Generic;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Http;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.MediaTypes;
|
||||
using NzbDrone.Core.Parser;
|
||||
|
||||
namespace NzbDrone.Core.Indexers.MyAnonamouse
|
||||
{
|
||||
public class MyAnonamouse : HttpIndexerBase<MyAnonamouseSettings>
|
||||
{
|
||||
public override string Name => "MyAnonamouse";
|
||||
public override DownloadProtocol Protocol => DownloadProtocol.Torrent;
|
||||
public override bool SupportsRss => true;
|
||||
public override bool SupportsSearch => true;
|
||||
public override int PageSize => 100;
|
||||
|
||||
public override IEnumerable<MediaType> SupportedMediaTypes => new[] { MediaType.Book, MediaType.Audiobook };
|
||||
|
||||
public MyAnonamouse(IHttpClient httpClient, IIndexerStatusService indexerStatusService, IConfigService configService, IParsingService parsingService, Logger logger)
|
||||
: base(httpClient, indexerStatusService, configService, parsingService, logger)
|
||||
{
|
||||
}
|
||||
|
||||
public override IIndexerRequestGenerator GetRequestGenerator()
|
||||
{
|
||||
return new MyAnonamouseRequestGenerator(Settings, _logger);
|
||||
}
|
||||
|
||||
public override IParseIndexerResponse GetParser()
|
||||
{
|
||||
return new MyAnonamouseParser(Settings);
|
||||
}
|
||||
}
|
||||
}
|
||||
59
src/NzbDrone.Core/Indexers/MyAnonamouse/MyAnonamouseApi.cs
Normal file
59
src/NzbDrone.Core/Indexers/MyAnonamouse/MyAnonamouseApi.cs
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace NzbDrone.Core.Indexers.MyAnonamouse
|
||||
{
|
||||
public class MyAnonamouseResponse
|
||||
{
|
||||
public string Error { get; set; }
|
||||
public IReadOnlyCollection<MyAnonamouseTorrent> Data { get; set; }
|
||||
public string Message { get; set; }
|
||||
}
|
||||
|
||||
public class MyAnonamouseTorrent
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string Title { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "author_info")]
|
||||
public string AuthorInfo { get; set; }
|
||||
|
||||
public string Description { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "lang_code")]
|
||||
public string LanguageCode { get; set; }
|
||||
|
||||
public string Filetype { get; set; }
|
||||
public bool Vip { get; set; }
|
||||
public bool Free { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "personal_freeleech")]
|
||||
public bool PersonalFreeLeech { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "fl_vip")]
|
||||
public bool FreeVip { get; set; }
|
||||
|
||||
public string Category { get; set; }
|
||||
public string Added { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "times_completed")]
|
||||
public int Grabs { get; set; }
|
||||
|
||||
public int Seeders { get; set; }
|
||||
public int Leechers { get; set; }
|
||||
public int NumFiles { get; set; }
|
||||
public string Size { get; set; }
|
||||
}
|
||||
|
||||
public class MyAnonamouseBuyFreeleechResponse
|
||||
{
|
||||
public bool Success { get; set; }
|
||||
public string Error { get; set; }
|
||||
}
|
||||
|
||||
public class MyAnonamouseUserDataResponse
|
||||
{
|
||||
[JsonProperty(PropertyName = "classname")]
|
||||
public string UserClass { get; set; }
|
||||
}
|
||||
}
|
||||
188
src/NzbDrone.Core/Indexers/MyAnonamouse/MyAnonamouseParser.cs
Normal file
188
src/NzbDrone.Core/Indexers/MyAnonamouse/MyAnonamouseParser.cs
Normal file
|
|
@ -0,0 +1,188 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using Newtonsoft.Json;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Common.Http;
|
||||
using NzbDrone.Core.Indexers.Exceptions;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
|
||||
namespace NzbDrone.Core.Indexers.MyAnonamouse
|
||||
{
|
||||
public class MyAnonamouseParser : IParseIndexerResponse
|
||||
{
|
||||
private readonly MyAnonamouseSettings _settings;
|
||||
|
||||
public MyAnonamouseParser(MyAnonamouseSettings settings)
|
||||
{
|
||||
_settings = settings;
|
||||
}
|
||||
|
||||
public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse)
|
||||
{
|
||||
var torrentInfos = new List<ReleaseInfo>();
|
||||
|
||||
if (indexerResponse.HttpResponse.StatusCode == HttpStatusCode.Forbidden)
|
||||
{
|
||||
throw new IndexerException(indexerResponse, "[403 Forbidden] - mam_id expired or invalid");
|
||||
}
|
||||
|
||||
if (indexerResponse.HttpResponse.StatusCode != HttpStatusCode.OK)
|
||||
{
|
||||
throw new IndexerException(indexerResponse,
|
||||
"Unexpected response status {0} code from API request",
|
||||
indexerResponse.HttpResponse.StatusCode);
|
||||
}
|
||||
|
||||
var jsonResponse = JsonConvert.DeserializeObject<MyAnonamouseResponse>(indexerResponse.Content);
|
||||
|
||||
if (jsonResponse.Error.IsNotNullOrWhiteSpace() && jsonResponse.Error.StartsWithIgnoreCase("Nothing returned, out of"))
|
||||
{
|
||||
return torrentInfos;
|
||||
}
|
||||
|
||||
if (jsonResponse.Data == null)
|
||||
{
|
||||
throw new IndexerException(indexerResponse,
|
||||
"Unexpected response content: {0}",
|
||||
jsonResponse.Message ?? "Check the logs for more information");
|
||||
}
|
||||
|
||||
foreach (var item in jsonResponse.Data)
|
||||
{
|
||||
var id = item.Id;
|
||||
var title = item.Title;
|
||||
|
||||
if (item.AuthorInfo != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var authorInfo = JsonConvert.DeserializeObject<Dictionary<string, string>>(item.AuthorInfo);
|
||||
var author = authorInfo?.Take(5).Select(v => v.Value).Join(", ");
|
||||
|
||||
if (author.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
title += " by " + author;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
var flags = new List<string>();
|
||||
|
||||
if (item.LanguageCode.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
flags.Add(item.LanguageCode);
|
||||
}
|
||||
|
||||
if (item.Filetype.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
flags.Add(item.Filetype.ToUpper());
|
||||
}
|
||||
|
||||
if (flags.Count > 0)
|
||||
{
|
||||
title += " [" + flags.Join(" / ") + "]";
|
||||
}
|
||||
|
||||
if (item.Vip)
|
||||
{
|
||||
title += " [VIP]";
|
||||
}
|
||||
|
||||
var isFreeLeech = item.Free || item.PersonalFreeLeech || item.FreeVip;
|
||||
|
||||
torrentInfos.Add(new TorrentInfo
|
||||
{
|
||||
Guid = $"MyAnonamouse-{id}",
|
||||
Title = title,
|
||||
Size = ParseSize(item.Size),
|
||||
DownloadUrl = GetDownloadUrl(id),
|
||||
InfoUrl = GetInfoUrl(id),
|
||||
Seeders = item.Seeders,
|
||||
Peers = item.Leechers + item.Seeders,
|
||||
PublishDate = ParseDate(item.Added),
|
||||
IndexerFlags = GetIndexerFlags(isFreeLeech)
|
||||
});
|
||||
}
|
||||
|
||||
return torrentInfos;
|
||||
}
|
||||
|
||||
private static IndexerFlags GetIndexerFlags(bool isFreeLeech)
|
||||
{
|
||||
IndexerFlags flags = 0;
|
||||
|
||||
if (isFreeLeech)
|
||||
{
|
||||
flags |= IndexerFlags.G_Freeleech;
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
private static long ParseSize(string sizeString)
|
||||
{
|
||||
if (sizeString.IsNullOrWhiteSpace())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (long.TryParse(sizeString, out var size))
|
||||
{
|
||||
return size;
|
||||
}
|
||||
|
||||
var parts = sizeString.Trim().Split(' ');
|
||||
if (parts.Length != 2 || !double.TryParse(parts[0], NumberStyles.Any, CultureInfo.InvariantCulture, out var value))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
var unit = parts[1].ToUpperInvariant();
|
||||
return unit switch
|
||||
{
|
||||
"B" => (long)value,
|
||||
"KB" => (long)(value * 1024),
|
||||
"MB" => (long)(value * 1024 * 1024),
|
||||
"GB" => (long)(value * 1024 * 1024 * 1024),
|
||||
"TB" => (long)(value * 1024 * 1024 * 1024 * 1024),
|
||||
_ => 0
|
||||
};
|
||||
}
|
||||
|
||||
private static DateTime ParseDate(string dateString)
|
||||
{
|
||||
if (DateTime.TryParseExact(dateString, "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal, out var date))
|
||||
{
|
||||
return date.ToLocalTime();
|
||||
}
|
||||
|
||||
return DateTime.UtcNow;
|
||||
}
|
||||
|
||||
private string GetDownloadUrl(int torrentId)
|
||||
{
|
||||
var url = new HttpUri(_settings.BaseUrl)
|
||||
.CombinePath("/tor/download.php")
|
||||
.AddQueryParam("tid", torrentId);
|
||||
|
||||
return url.FullUri;
|
||||
}
|
||||
|
||||
private string GetInfoUrl(int torrentId)
|
||||
{
|
||||
var url = new HttpUri(_settings.BaseUrl)
|
||||
.CombinePath("/t/")
|
||||
.CombinePath(torrentId.ToString());
|
||||
|
||||
return url.FullUri;
|
||||
}
|
||||
|
||||
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,190 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Text.RegularExpressions;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Common.Http;
|
||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||
|
||||
namespace NzbDrone.Core.Indexers.MyAnonamouse
|
||||
{
|
||||
public class MyAnonamouseRequestGenerator : IIndexerRequestGenerator
|
||||
{
|
||||
private static readonly Regex SanitizeSearchQueryRegex = new ("[^\\w]+", RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
||||
|
||||
public MyAnonamouseSettings Settings { get; set; }
|
||||
|
||||
private readonly Logger _logger;
|
||||
|
||||
public MyAnonamouseRequestGenerator(MyAnonamouseSettings settings, Logger logger)
|
||||
{
|
||||
Settings = settings;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public virtual IndexerPageableRequestChain GetRecentRequests()
|
||||
{
|
||||
var pageableRequests = new IndexerPageableRequestChain();
|
||||
pageableRequests.Add(GetPagedRequests(string.Empty));
|
||||
return pageableRequests;
|
||||
}
|
||||
|
||||
public virtual IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
|
||||
{
|
||||
return new IndexerPageableRequestChain();
|
||||
}
|
||||
|
||||
public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria)
|
||||
{
|
||||
var pageableRequests = new IndexerPageableRequestChain();
|
||||
var searchTerm = BuildSearchTerm(searchCriteria);
|
||||
|
||||
if (searchTerm.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
pageableRequests.Add(GetPagedRequests(searchTerm));
|
||||
}
|
||||
|
||||
return pageableRequests;
|
||||
}
|
||||
|
||||
public IndexerPageableRequestChain GetSearchRequests(AudiobookSearchCriteria searchCriteria)
|
||||
{
|
||||
var pageableRequests = new IndexerPageableRequestChain();
|
||||
var searchTerm = BuildSearchTerm(searchCriteria);
|
||||
|
||||
if (searchTerm.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
pageableRequests.Add(GetPagedRequests(searchTerm));
|
||||
}
|
||||
|
||||
return pageableRequests;
|
||||
}
|
||||
|
||||
private string BuildSearchTerm(SearchCriteriaBase searchCriteria)
|
||||
{
|
||||
var terms = new List<string>();
|
||||
|
||||
if (searchCriteria is BookSearchCriteria bookCriteria)
|
||||
{
|
||||
if (bookCriteria.Author.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
terms.Add(bookCriteria.Author);
|
||||
}
|
||||
|
||||
if (bookCriteria.Title.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
terms.Add(bookCriteria.Title);
|
||||
}
|
||||
}
|
||||
else if (searchCriteria is AudiobookSearchCriteria audiobookCriteria)
|
||||
{
|
||||
if (audiobookCriteria.Author.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
terms.Add(audiobookCriteria.Author);
|
||||
}
|
||||
|
||||
if (audiobookCriteria.Title.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
terms.Add(audiobookCriteria.Title);
|
||||
}
|
||||
}
|
||||
|
||||
return string.Join(" ", terms);
|
||||
}
|
||||
|
||||
private IEnumerable<IndexerRequest> GetPagedRequests(string term)
|
||||
{
|
||||
var sanitizedTerm = SanitizeSearchQueryRegex.Replace(term, " ").Trim();
|
||||
|
||||
if (term.IsNotNullOrWhiteSpace() && sanitizedTerm.IsNullOrWhiteSpace())
|
||||
{
|
||||
_logger.Debug("Search term is empty after sanitization, skipping. Original: '{0}'", term);
|
||||
yield break;
|
||||
}
|
||||
|
||||
var searchType = Settings.SearchType switch
|
||||
{
|
||||
(int)MyAnonamouseSearchType.Active => "active",
|
||||
(int)MyAnonamouseSearchType.Freeleech => "fl",
|
||||
(int)MyAnonamouseSearchType.FreeleechOrVip => "fl-VIP",
|
||||
(int)MyAnonamouseSearchType.Vip => "VIP",
|
||||
(int)MyAnonamouseSearchType.NotVip => "nVIP",
|
||||
_ => "all"
|
||||
};
|
||||
|
||||
var parameters = new NameValueCollection
|
||||
{
|
||||
{ "tor[text]", sanitizedTerm },
|
||||
{ "tor[searchType]", searchType },
|
||||
{ "tor[srchIn][title]", "true" },
|
||||
{ "tor[srchIn][author]", "true" },
|
||||
{ "tor[srchIn][narrator]", "true" },
|
||||
{ "tor[searchIn]", "torrents" },
|
||||
{ "tor[sortType]", "default" },
|
||||
{ "tor[perpage]", "100" },
|
||||
{ "tor[startNumber]", "0" },
|
||||
{ "thumbnails", "1" },
|
||||
{ "description", "1" }
|
||||
};
|
||||
|
||||
if (Settings.SearchInDescription)
|
||||
{
|
||||
parameters.Set("tor[srchIn][description]", "true");
|
||||
}
|
||||
|
||||
if (Settings.SearchInSeries)
|
||||
{
|
||||
parameters.Set("tor[srchIn][series]", "true");
|
||||
}
|
||||
|
||||
if (Settings.SearchInFilenames)
|
||||
{
|
||||
parameters.Set("tor[srchIn][filenames]", "true");
|
||||
}
|
||||
|
||||
parameters.Set("tor[cat][]", "0");
|
||||
|
||||
var searchUrl = Settings.BaseUrl.TrimEnd('/') + "/tor/js/loadSearchJSONbasic.php";
|
||||
|
||||
if (parameters.Count > 0)
|
||||
{
|
||||
searchUrl += "?" + parameters.ToQueryString();
|
||||
}
|
||||
|
||||
var requestBuilder = new HttpRequestBuilder(searchUrl)
|
||||
.Accept(HttpAccept.Json);
|
||||
|
||||
var cookies = GetCookies?.Invoke();
|
||||
|
||||
if (cookies != null && cookies.TryGetValue("mam_id", out var mamId) && mamId.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
requestBuilder.SetCookies(cookies);
|
||||
}
|
||||
else if (Settings.MamId.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
requestBuilder.SetCookies(new Dictionary<string, string> { { "mam_id", Settings.MamId } });
|
||||
}
|
||||
|
||||
yield return new IndexerRequest(requestBuilder.Build());
|
||||
}
|
||||
|
||||
public Func<IDictionary<string, string>> GetCookies { get; set; }
|
||||
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
|
||||
}
|
||||
|
||||
internal static class NameValueCollectionExtensions
|
||||
{
|
||||
public static string ToQueryString(this NameValueCollection nvc)
|
||||
{
|
||||
var items = new List<string>();
|
||||
|
||||
foreach (var key in nvc.AllKeys)
|
||||
{
|
||||
items.Add($"{Uri.EscapeDataString(key)}={Uri.EscapeDataString(nvc[key])}");
|
||||
}
|
||||
|
||||
return string.Join("&", items);
|
||||
}
|
||||
}
|
||||
}
|
||||
101
src/NzbDrone.Core/Indexers/MyAnonamouse/MyAnonamouseSettings.cs
Normal file
101
src/NzbDrone.Core/Indexers/MyAnonamouse/MyAnonamouseSettings.cs
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Equ;
|
||||
using FluentValidation;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using NzbDrone.Core.Languages;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Core.Validation;
|
||||
|
||||
namespace NzbDrone.Core.Indexers.MyAnonamouse
|
||||
{
|
||||
public class MyAnonamouseSettingsValidator : AbstractValidator<MyAnonamouseSettings>
|
||||
{
|
||||
public MyAnonamouseSettingsValidator()
|
||||
{
|
||||
RuleFor(c => c.BaseUrl).ValidRootUrl();
|
||||
RuleFor(c => c.MamId).NotEmpty();
|
||||
RuleFor(c => c.SeedCriteria).SetValidator(_ => new SeedCriteriaSettingsValidator());
|
||||
}
|
||||
}
|
||||
|
||||
public class MyAnonamouseSettings : PropertywiseEquatable<MyAnonamouseSettings>, ITorrentIndexerSettings
|
||||
{
|
||||
private static readonly MyAnonamouseSettingsValidator Validator = new ();
|
||||
|
||||
public MyAnonamouseSettings()
|
||||
{
|
||||
BaseUrl = "https://www.myanonamouse.net";
|
||||
MinimumSeeders = IndexerDefaults.MINIMUM_SEEDERS;
|
||||
SearchType = (int)MyAnonamouseSearchType.All;
|
||||
SearchInDescription = false;
|
||||
SearchInSeries = false;
|
||||
SearchInFilenames = false;
|
||||
MultiLanguages = Array.Empty<int>();
|
||||
FailDownloads = Array.Empty<int>();
|
||||
RequiredFlags = Array.Empty<int>();
|
||||
}
|
||||
|
||||
[FieldDefinition(0, Label = "IndexerSettingsApiUrl", Advanced = true, HelpText = "IndexerSettingsApiUrlHelpText")]
|
||||
public string BaseUrl { get; set; }
|
||||
|
||||
[FieldDefinition(1, Label = "IndexerMyAnonamouseMamId", Type = FieldType.Textbox, Privacy = PrivacyLevel.ApiKey, HelpText = "IndexerMyAnonamouseMamIdHelpText")]
|
||||
public string MamId { get; set; }
|
||||
|
||||
[FieldDefinition(2, Label = "IndexerMyAnonamouseSearchType", Type = FieldType.Select, SelectOptions = typeof(MyAnonamouseSearchType), HelpText = "IndexerMyAnonamouseSearchTypeHelpText")]
|
||||
public int SearchType { get; set; }
|
||||
|
||||
[FieldDefinition(3, Label = "IndexerMyAnonamouseSearchInDescription", Type = FieldType.Checkbox, HelpText = "IndexerMyAnonamouseSearchInDescriptionHelpText", Advanced = true)]
|
||||
public bool SearchInDescription { get; set; }
|
||||
|
||||
[FieldDefinition(4, Label = "IndexerMyAnonamouseSearchInSeries", Type = FieldType.Checkbox, HelpText = "IndexerMyAnonamouseSearchInSeriesHelpText", Advanced = true)]
|
||||
public bool SearchInSeries { get; set; }
|
||||
|
||||
[FieldDefinition(5, Label = "IndexerMyAnonamouseSearchInFilenames", Type = FieldType.Checkbox, HelpText = "IndexerMyAnonamouseSearchInFilenamesHelpText", Advanced = true)]
|
||||
public bool SearchInFilenames { get; set; }
|
||||
|
||||
[FieldDefinition(6, Type = FieldType.Number, Label = "IndexerSettingsMinimumSeeders", HelpText = "IndexerSettingsMinimumSeedersHelpText", Advanced = true)]
|
||||
public int MinimumSeeders { get; set; }
|
||||
|
||||
[FieldDefinition(7)]
|
||||
public SeedCriteriaSettings SeedCriteria { get; set; } = new ();
|
||||
|
||||
[FieldDefinition(8, Type = FieldType.Checkbox, Label = "IndexerSettingsRejectBlocklistedTorrentHashes", HelpText = "IndexerSettingsRejectBlocklistedTorrentHashesHelpText", Advanced = true)]
|
||||
public bool RejectBlocklistedTorrentHashesWhileGrabbing { get; set; }
|
||||
|
||||
[FieldDefinition(9, Type = FieldType.Select, SelectOptions = typeof(RealLanguageFieldConverter), Label = "IndexerSettingsMultiLanguageRelease", HelpText = "IndexerSettingsMultiLanguageReleaseHelpText", Advanced = true)]
|
||||
public IEnumerable<int> MultiLanguages { get; set; }
|
||||
|
||||
[FieldDefinition(10, Type = FieldType.Select, SelectOptions = typeof(FailDownloads), Label = "IndexerSettingsFailDownloads", HelpText = "IndexerSettingsFailDownloadsHelpText", Advanced = true)]
|
||||
public IEnumerable<int> FailDownloads { get; set; }
|
||||
|
||||
[FieldDefinition(11, Type = FieldType.Select, SelectOptions = typeof(IndexerFlags), Label = "IndexerSettingsRequiredFlags", HelpText = "IndexerSettingsRequiredFlagsHelpText", HelpLink = "https://wiki.servarr.com/radarr/settings#indexer-flags", Advanced = true)]
|
||||
public IEnumerable<int> RequiredFlags { get; set; }
|
||||
|
||||
public NzbDroneValidationResult Validate()
|
||||
{
|
||||
return new NzbDroneValidationResult(Validator.Validate(this));
|
||||
}
|
||||
}
|
||||
|
||||
public enum MyAnonamouseSearchType
|
||||
{
|
||||
[FieldOption("All Torrents")]
|
||||
All = 0,
|
||||
|
||||
[FieldOption("Only Active")]
|
||||
Active = 1,
|
||||
|
||||
[FieldOption("Freeleech")]
|
||||
Freeleech = 2,
|
||||
|
||||
[FieldOption("Freeleech or VIP")]
|
||||
FreeleechOrVip = 3,
|
||||
|
||||
[FieldOption("VIP")]
|
||||
Vip = 4,
|
||||
|
||||
[FieldOption("Not VIP")]
|
||||
NotVip = 5
|
||||
}
|
||||
}
|
||||
|
|
@ -879,6 +879,16 @@
|
|||
"IndexerJackettAll": "Indexers using the unsupported Jackett 'all' endpoint: {indexerNames}",
|
||||
"IndexerLongTermStatusCheckAllClientMessage": "All indexers are unavailable due to failures for more than 6 hours",
|
||||
"IndexerLongTermStatusCheckSingleClientMessage": "Indexers unavailable due to failures for more than 6 hours: {indexerNames}",
|
||||
"IndexerMyAnonamouseMamId": "Mam Id",
|
||||
"IndexerMyAnonamouseMamIdHelpText": "Mam Session Id (found in Preferences > Security)",
|
||||
"IndexerMyAnonamouseSearchInDescription": "Search in Description",
|
||||
"IndexerMyAnonamouseSearchInDescriptionHelpText": "Include torrent description in search",
|
||||
"IndexerMyAnonamouseSearchInFilenames": "Search in Filenames",
|
||||
"IndexerMyAnonamouseSearchInFilenamesHelpText": "Include filenames in search",
|
||||
"IndexerMyAnonamouseSearchInSeries": "Search in Series",
|
||||
"IndexerMyAnonamouseSearchInSeriesHelpText": "Include series information in search",
|
||||
"IndexerMyAnonamouseSearchType": "Search Type",
|
||||
"IndexerMyAnonamouseSearchTypeHelpText": "Specify the desired search type",
|
||||
"IndexerNewznabSettingsAdditionalParametersHelpText": "Additional Newznab parameters",
|
||||
"IndexerNewznabSettingsCategoriesHelpText": "Drop down list, at least one category must be selected.",
|
||||
"IndexerNyaaSettingsAdditionalParametersHelpText": "Please note if you change the category you will have to add required/restricted rules about the subgroups to avoid foreign language releases.",
|
||||
|
|
|
|||
Loading…
Reference in a new issue