2020-10-16 22:14:10 +00:00
|
|
|
using System;
|
|
|
|
using System.Collections.Generic;
|
|
|
|
using System.Collections.Specialized;
|
|
|
|
using System.Diagnostics.CodeAnalysis;
|
|
|
|
using System.Linq;
|
|
|
|
using System.Net;
|
|
|
|
using System.Text;
|
2021-02-20 21:17:46 +00:00
|
|
|
using System.Text.RegularExpressions;
|
2021-05-16 18:13:54 +00:00
|
|
|
using System.Threading.Tasks;
|
2020-10-16 22:14:10 +00:00
|
|
|
using Jackett.Common.Models;
|
|
|
|
using Jackett.Common.Models.IndexerConfig.Bespoke;
|
|
|
|
using Jackett.Common.Services.Interfaces;
|
|
|
|
using Jackett.Common.Utils;
|
|
|
|
using Newtonsoft.Json.Linq;
|
|
|
|
using NLog;
|
|
|
|
|
|
|
|
namespace Jackett.Common.Indexers
|
|
|
|
{
|
|
|
|
[ExcludeFromCodeCoverage]
|
|
|
|
public class AniLibria : BaseWebIndexer
|
|
|
|
{
|
2021-02-20 21:17:46 +00:00
|
|
|
private static readonly Regex _EpisodeRegex = new Regex(@"(?:[SsEe]?\d{1,4}){1,2}$");
|
|
|
|
|
2020-12-11 22:14:21 +00:00
|
|
|
public AniLibria(IIndexerConfigurationService configService, Utils.Clients.WebClient wc, Logger l, IProtectionService ps, ICacheService cs)
|
2020-10-16 22:14:10 +00:00
|
|
|
: base(id: "AniLibria",
|
|
|
|
name: "AniLibria",
|
|
|
|
description: "AniLibria is a Public torrent tracker for anime, voiced on russian by AniLibria team",
|
|
|
|
link: "https://www.anilibria.tv/",
|
2020-10-18 20:47:36 +00:00
|
|
|
caps: new TorznabCapabilities
|
|
|
|
{
|
|
|
|
TvSearchParams = new List<TvSearchParam>
|
|
|
|
{
|
|
|
|
TvSearchParam.Q, TvSearchParam.Season, TvSearchParam.Ep
|
|
|
|
}
|
|
|
|
},
|
2020-10-16 22:14:10 +00:00
|
|
|
configService: configService,
|
|
|
|
client: wc,
|
|
|
|
logger: l,
|
|
|
|
p: ps,
|
2020-12-11 22:14:21 +00:00
|
|
|
cacheService: cs,
|
2020-10-16 22:14:10 +00:00
|
|
|
configData: new ConfigurationDataAniLibria())
|
|
|
|
{
|
|
|
|
Encoding = Encoding.UTF8;
|
|
|
|
Language = "ru-ru";
|
|
|
|
Type = "public";
|
|
|
|
|
|
|
|
// Configure the category mappings
|
|
|
|
AddCategoryMapping(1, TorznabCatType.TVAnime, "Anime");
|
|
|
|
}
|
2020-10-18 13:05:59 +00:00
|
|
|
|
|
|
|
private ConfigurationDataAniLibria Configuration => (ConfigurationDataAniLibria)configData;
|
2020-10-16 22:14:10 +00:00
|
|
|
|
|
|
|
public override async Task<IndexerConfigurationStatus> ApplyConfiguration(JToken configJson)
|
|
|
|
{
|
|
|
|
LoadValuesFromJson(configJson);
|
|
|
|
var releases = await PerformQuery(new TorznabQuery());
|
|
|
|
|
|
|
|
await ConfigureIfOK(string.Empty, releases.Any(), () =>
|
|
|
|
throw new Exception("Could not find releases from this URL"));
|
|
|
|
|
|
|
|
return IndexerConfigurationStatus.Completed;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the search string is empty use the latest releases
|
|
|
|
protected override async Task<IEnumerable<ReleaseInfo>> PerformQuery(TorznabQuery query)
|
|
|
|
=> query.IsTest || string.IsNullOrWhiteSpace(query.SearchTerm)
|
|
|
|
? await FetchNewReleases()
|
|
|
|
: await PerformSearch(query);
|
2020-10-18 13:05:59 +00:00
|
|
|
|
2020-10-16 22:14:10 +00:00
|
|
|
private async Task<IEnumerable<ReleaseInfo>> PerformSearch(TorznabQuery query)
|
|
|
|
{
|
2021-02-20 21:17:46 +00:00
|
|
|
var title = _EpisodeRegex.Replace(query.SearchTerm, string.Empty).TrimEnd();
|
2020-10-16 22:14:10 +00:00
|
|
|
var queryParameters = new NameValueCollection
|
|
|
|
{
|
2021-02-20 21:17:46 +00:00
|
|
|
{ "filter", "names,poster.url,code,torrents.list,season.year" },
|
|
|
|
{ "limit", "100" }
|
2020-10-16 22:14:10 +00:00
|
|
|
};
|
2021-02-20 21:17:46 +00:00
|
|
|
var response = await RequestWithCookiesAndRetryAsync(Configuration.ApiLink.Value + "/searchTitles?" + queryParameters.GetQueryString() + "&search=" + Uri.EscapeDataString(title));
|
2020-10-18 13:05:59 +00:00
|
|
|
if (response.Status != HttpStatusCode.OK)
|
2020-10-16 22:14:10 +00:00
|
|
|
throw new WebException($"AniLibria search returned unexpected result. Expected 200 OK but got {response.Status}.", WebExceptionStatus.ProtocolError);
|
2020-10-18 13:05:59 +00:00
|
|
|
|
2020-10-16 22:14:10 +00:00
|
|
|
var results = ParseApiResults(response.ContentString);
|
2021-05-16 18:13:54 +00:00
|
|
|
return results.Where(release => query.MatchQueryStringAND(release.Title, null, title));
|
|
|
|
;
|
2020-10-16 22:14:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private async Task<IEnumerable<ReleaseInfo>> FetchNewReleases()
|
|
|
|
{
|
|
|
|
var queryParameters = new NameValueCollection
|
|
|
|
{
|
|
|
|
{ "limit", "100" },
|
2020-10-19 21:19:10 +00:00
|
|
|
{ "filter", "names,poster.url,code,torrents.list,season.year" }
|
2020-10-16 22:14:10 +00:00
|
|
|
};
|
|
|
|
var response = await RequestWithCookiesAndRetryAsync(Configuration.ApiLink.Value + "/getUpdates?" + queryParameters.GetQueryString());
|
2020-10-18 13:05:59 +00:00
|
|
|
if (response.Status != HttpStatusCode.OK)
|
2020-10-16 22:14:10 +00:00
|
|
|
throw new WebException($"AniLibria search returned unexpected result. Expected 200 OK but got {response.Status}.", WebExceptionStatus.ProtocolError);
|
|
|
|
|
|
|
|
return ParseApiResults(response.ContentString);
|
|
|
|
}
|
|
|
|
|
2021-05-16 18:13:54 +00:00
|
|
|
private string composeTitle(dynamic json)
|
|
|
|
{
|
2020-10-16 22:14:10 +00:00
|
|
|
var title = json.names.ru;
|
|
|
|
title += " / " + json.names.en;
|
|
|
|
if (json.alternative is string)
|
|
|
|
title += " / " + json.names.alternative;
|
|
|
|
title += " " + json.season.year;
|
|
|
|
return title;
|
|
|
|
}
|
|
|
|
|
|
|
|
private List<ReleaseInfo> ParseApiResults(string json)
|
|
|
|
{
|
|
|
|
var releases = new List<ReleaseInfo>();
|
2021-05-16 18:13:54 +00:00
|
|
|
foreach (dynamic r in JArray.Parse(json))
|
|
|
|
{
|
2020-10-18 13:05:59 +00:00
|
|
|
var baseRelease = new ReleaseInfo
|
|
|
|
{
|
|
|
|
Title = composeTitle(r),
|
2020-11-07 23:43:33 +00:00
|
|
|
Poster = new Uri(Configuration.StaticLink.Value + r.poster.url),
|
2020-11-08 02:11:27 +00:00
|
|
|
Details = new Uri(SiteLink + "/release/" + r.code + ".html"),
|
2020-10-18 13:05:59 +00:00
|
|
|
DownloadVolumeFactor = 0,
|
|
|
|
UploadVolumeFactor = 1,
|
2021-05-16 18:13:54 +00:00
|
|
|
Category = new[]
|
2020-10-18 13:05:59 +00:00
|
|
|
{
|
|
|
|
TorznabCatType.TVAnime.ID
|
|
|
|
}
|
|
|
|
};
|
2021-05-16 18:13:54 +00:00
|
|
|
foreach (var t in r.torrents.list)
|
|
|
|
{
|
2020-10-16 22:14:10 +00:00
|
|
|
var release = (ReleaseInfo)baseRelease.Clone();
|
|
|
|
release.Title += " [" + t.quality["string"] + "] - " + t.series["string"];
|
|
|
|
release.Size = t.total_size;
|
|
|
|
release.Seeders = t.seeders;
|
|
|
|
release.Peers = t.leechers + t.seeders;
|
|
|
|
release.Grabs = t.downloads;
|
|
|
|
release.Link = new Uri(SiteLink + t.url);
|
2020-10-18 13:05:59 +00:00
|
|
|
release.Guid = new Uri(SiteLink + t.url);
|
|
|
|
release.PublishDate = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc).AddSeconds(Convert.ToDouble(t.uploaded_timestamp)).ToLocalTime();
|
2020-10-16 22:14:10 +00:00
|
|
|
releases.Add(release);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return releases;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|