2020-02-09 02:35:16 +00:00
|
|
|
using System;
|
2019-02-16 01:19:05 +00:00
|
|
|
using System.Collections.Generic;
|
|
|
|
using System.Collections.Specialized;
|
2020-05-03 23:35:52 +00:00
|
|
|
using System.Diagnostics.CodeAnalysis;
|
2019-02-16 01:19:05 +00:00
|
|
|
using System.Linq;
|
|
|
|
using System.Threading.Tasks;
|
2023-07-07 10:33:50 +00:00
|
|
|
using Jackett.Common.Extensions;
|
2019-02-16 01:19:05 +00:00
|
|
|
using Jackett.Common.Models;
|
|
|
|
using Jackett.Common.Models.IndexerConfig;
|
|
|
|
using Jackett.Common.Services.Interfaces;
|
|
|
|
using Jackett.Common.Utils;
|
|
|
|
using Jackett.Common.Utils.Clients;
|
|
|
|
using Newtonsoft.Json.Linq;
|
|
|
|
using NLog;
|
|
|
|
|
2020-02-09 02:35:16 +00:00
|
|
|
namespace Jackett.Common.Indexers
|
|
|
|
{
|
2020-05-03 23:35:52 +00:00
|
|
|
[ExcludeFromCodeCoverage]
|
2023-03-09 14:06:12 +00:00
|
|
|
public class TorrentsCSV : IndexerBase
|
2020-02-09 02:35:16 +00:00
|
|
|
{
|
2023-03-09 14:06:12 +00:00
|
|
|
public override string Id => "torrentscsv";
|
|
|
|
public override string Name => "Torrents.csv";
|
|
|
|
public override string Description => "Torrents.csv is a self-hostable, open source torrent search engine and database";
|
2024-01-11 02:13:11 +00:00
|
|
|
public override string SiteLink { get; protected set; } = "https://torrents-csv.com/";
|
|
|
|
public override string[] LegacySiteLinks => new[]
|
|
|
|
{
|
|
|
|
"https://torrents-csv.ml/",
|
|
|
|
};
|
2023-03-09 14:06:12 +00:00
|
|
|
public override string Language => "en-US";
|
|
|
|
public override string Type => "public";
|
|
|
|
|
2023-03-10 11:20:29 +00:00
|
|
|
public override TorznabCapabilities TorznabCaps => SetCapabilities();
|
|
|
|
|
2020-06-07 00:11:41 +00:00
|
|
|
private string SearchEndpoint => SiteLink + "service/search";
|
2019-02-16 01:19:05 +00:00
|
|
|
|
2020-05-05 07:09:53 +00:00
|
|
|
private new ConfigurationData configData => base.configData;
|
|
|
|
|
2023-03-10 11:20:29 +00:00
|
|
|
public TorrentsCSV(IIndexerConfigurationService configService, WebClient wc, Logger l, IProtectionService ps, ICacheService cs)
|
|
|
|
: base(configService: configService,
|
2020-05-05 07:09:53 +00:00
|
|
|
client: wc,
|
|
|
|
logger: l,
|
|
|
|
p: ps,
|
2020-12-11 22:14:21 +00:00
|
|
|
cacheService: cs,
|
2020-05-05 07:09:53 +00:00
|
|
|
configData: new ConfigurationData())
|
2020-02-09 02:35:16 +00:00
|
|
|
{
|
2023-03-10 11:20:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private TorznabCapabilities SetCapabilities()
|
|
|
|
{
|
|
|
|
var caps = new TorznabCapabilities
|
|
|
|
{
|
|
|
|
TvSearchParams = new List<TvSearchParam>
|
|
|
|
{
|
|
|
|
TvSearchParam.Q, TvSearchParam.Season, TvSearchParam.Ep
|
|
|
|
},
|
|
|
|
MovieSearchParams = new List<MovieSearchParam>
|
|
|
|
{
|
|
|
|
MovieSearchParam.Q
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2020-05-05 07:09:53 +00:00
|
|
|
// torrents.csv doesn't return categories
|
2023-03-10 11:20:29 +00:00
|
|
|
caps.Categories.AddCategoryMapping(1, TorznabCatType.Other);
|
|
|
|
|
|
|
|
return caps;
|
2019-02-16 01:19:05 +00:00
|
|
|
}
|
|
|
|
|
2023-03-10 11:20:29 +00:00
|
|
|
|
2020-02-09 02:35:16 +00:00
|
|
|
public override async Task<IndexerConfigurationStatus> ApplyConfiguration(JToken configJson)
|
|
|
|
{
|
2020-12-11 23:12:40 +00:00
|
|
|
LoadValuesFromJson(configJson);
|
2020-02-09 02:35:16 +00:00
|
|
|
var releases = await PerformQuery(new TorznabQuery());
|
2019-02-16 01:19:05 +00:00
|
|
|
|
2020-05-05 07:09:53 +00:00
|
|
|
await ConfigureIfOK(string.Empty, releases.Any(),
|
|
|
|
() => throw new Exception("Error: 0 results found!"));
|
2019-02-16 01:19:05 +00:00
|
|
|
|
|
|
|
return IndexerConfigurationStatus.Completed;
|
|
|
|
}
|
|
|
|
|
2021-05-16 18:13:54 +00:00
|
|
|
protected override async Task<IEnumerable<ReleaseInfo>> PerformQuery(TorznabQuery query)
|
|
|
|
{
|
2020-02-09 02:35:16 +00:00
|
|
|
var releases = new List<ReleaseInfo>();
|
|
|
|
var searchString = query.GetQueryString();
|
2020-10-17 10:27:50 +00:00
|
|
|
|
2023-07-07 10:33:50 +00:00
|
|
|
// not supported
|
|
|
|
if (searchString.IsNullOrWhiteSpace())
|
2020-10-17 10:27:50 +00:00
|
|
|
{
|
|
|
|
releases.Add(new ReleaseInfo
|
|
|
|
{
|
|
|
|
Title = "[NOT IMPLEMENTED] Empty search is unsupported in this indexer",
|
|
|
|
Guid = new Uri(SiteLink),
|
2020-11-08 02:11:27 +00:00
|
|
|
Details = new Uri(SiteLink),
|
2020-10-17 10:27:50 +00:00
|
|
|
MagnetUri = new Uri("magnet:?xt=urn:btih:3333333333333333333333333333333333333333"), // unknown torrent
|
|
|
|
Category = new List<int> { TorznabCatType.Other.ID },
|
|
|
|
PublishDate = new DateTime(),
|
2020-10-18 13:14:52 +00:00
|
|
|
Grabs = 0,
|
|
|
|
Seeders = 0,
|
|
|
|
Peers = 0,
|
|
|
|
DownloadVolumeFactor = 0,
|
2020-10-19 21:19:10 +00:00
|
|
|
UploadVolumeFactor = 1
|
2020-10-17 10:27:50 +00:00
|
|
|
});
|
2023-07-07 10:33:50 +00:00
|
|
|
|
2020-10-17 10:27:50 +00:00
|
|
|
return releases;
|
|
|
|
}
|
|
|
|
|
2023-07-07 10:33:50 +00:00
|
|
|
// search needs at least 3 characters
|
|
|
|
if (searchString.IsNotNullOrWhiteSpace() && searchString.Length < 3)
|
|
|
|
{
|
|
|
|
return releases;
|
|
|
|
}
|
2019-02-16 01:19:05 +00:00
|
|
|
|
2020-05-05 07:09:53 +00:00
|
|
|
var qc = new NameValueCollection
|
2020-03-26 22:15:28 +00:00
|
|
|
{
|
2020-10-17 10:27:50 +00:00
|
|
|
{ "size", "100" },
|
|
|
|
{ "q", searchString }
|
2020-03-26 22:15:28 +00:00
|
|
|
};
|
2019-02-16 01:19:05 +00:00
|
|
|
|
2020-10-17 10:27:50 +00:00
|
|
|
var searchUrl = SearchEndpoint + "?" + qc.GetQueryString();
|
2020-06-11 15:09:27 +00:00
|
|
|
var response = await RequestWithCookiesAndRetryAsync(searchUrl);
|
2023-07-07 10:33:50 +00:00
|
|
|
|
2020-02-09 02:35:16 +00:00
|
|
|
try
|
|
|
|
{
|
2023-07-07 10:33:50 +00:00
|
|
|
var jsonContent = JArray.Parse(response.ContentString);
|
2019-02-16 01:19:05 +00:00
|
|
|
|
2020-02-09 02:35:16 +00:00
|
|
|
foreach (var torrent in jsonContent)
|
|
|
|
{
|
|
|
|
if (torrent == null)
|
2023-07-07 10:33:50 +00:00
|
|
|
{
|
2020-02-09 02:35:16 +00:00
|
|
|
throw new Exception("Error: No data returned!");
|
2023-07-07 10:33:50 +00:00
|
|
|
}
|
2020-02-09 02:35:16 +00:00
|
|
|
|
2023-07-07 10:33:50 +00:00
|
|
|
var infoHash = torrent.Value<string>("infohash");
|
2020-05-05 07:09:53 +00:00
|
|
|
var title = torrent.Value<string>("name");
|
|
|
|
var size = torrent.Value<long>("size_bytes");
|
2023-07-07 10:33:50 +00:00
|
|
|
var seeders = torrent.Value<int?>("seeders") ?? 0;
|
|
|
|
var leechers = torrent.Value<int?>("leechers") ?? 0;
|
|
|
|
var grabs = torrent.Value<int?>("completed") ?? 0;
|
|
|
|
var publishDate = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc).AddSeconds(torrent.Value<long>("created_unix"));
|
2020-05-05 07:09:53 +00:00
|
|
|
|
2020-03-26 22:15:28 +00:00
|
|
|
var release = new ReleaseInfo
|
|
|
|
{
|
2020-05-05 07:09:53 +00:00
|
|
|
Title = title,
|
2023-07-07 10:33:50 +00:00
|
|
|
Details = new Uri($"{SiteLink.TrimEnd('/')}/search/{title}"), // there is no details link
|
2020-11-02 17:01:06 +00:00
|
|
|
Guid = new Uri($"magnet:?xt=urn:btih:{infoHash}"),
|
|
|
|
InfoHash = infoHash, // magnet link is auto generated from infohash
|
2020-05-05 07:09:53 +00:00
|
|
|
Category = new List<int> { TorznabCatType.Other.ID },
|
|
|
|
PublishDate = publishDate,
|
|
|
|
Size = size,
|
2020-03-26 22:15:28 +00:00
|
|
|
Grabs = grabs,
|
2020-05-05 07:09:53 +00:00
|
|
|
Seeders = seeders,
|
|
|
|
Peers = leechers + seeders,
|
|
|
|
DownloadVolumeFactor = 0,
|
2020-10-19 21:19:10 +00:00
|
|
|
UploadVolumeFactor = 1
|
2020-03-26 22:15:28 +00:00
|
|
|
};
|
|
|
|
|
2020-02-09 02:35:16 +00:00
|
|
|
releases.Add(release);
|
2019-02-16 01:19:05 +00:00
|
|
|
}
|
2020-02-09 02:35:16 +00:00
|
|
|
}
|
|
|
|
catch (Exception ex)
|
|
|
|
{
|
2020-06-09 17:36:57 +00:00
|
|
|
OnParseError(response.ContentString, ex);
|
2019-02-16 01:19:05 +00:00
|
|
|
}
|
2023-07-07 10:33:50 +00:00
|
|
|
|
|
|
|
return releases
|
|
|
|
.OrderByDescending(o => o.PublishDate)
|
|
|
|
.ToArray();
|
2019-02-16 01:19:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|