2020-04-20 23:57:17 +00:00
|
|
|
using System;
|
|
|
|
using System.Collections.Generic;
|
|
|
|
using System.Collections.Specialized;
|
2020-05-03 23:35:52 +00:00
|
|
|
using System.Diagnostics.CodeAnalysis;
|
2020-04-20 23:57:17 +00:00
|
|
|
using System.Linq;
|
|
|
|
using System.Text;
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
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;
|
|
|
|
using Newtonsoft.Json.Linq;
|
|
|
|
using NLog;
|
|
|
|
|
|
|
|
namespace Jackett.Common.Indexers
|
|
|
|
{
|
2020-05-03 23:35:52 +00:00
|
|
|
[ExcludeFromCodeCoverage]
|
2020-04-20 23:57:17 +00:00
|
|
|
public class Milkie : BaseWebIndexer
|
|
|
|
{
|
|
|
|
private string TorrentsEndpoint => SiteLink + "api/v1/torrents";
|
|
|
|
|
2020-04-21 23:19:53 +00:00
|
|
|
private new ConfigurationDataAPIKey configData => (ConfigurationDataAPIKey)base.configData;
|
2020-04-20 23:57:17 +00:00
|
|
|
|
|
|
|
public Milkie(IIndexerConfigurationService configService, WebClient wc, Logger l, IProtectionService ps)
|
2020-05-11 19:59:28 +00:00
|
|
|
: base(id: "milkie",
|
|
|
|
name: "Milkie",
|
2020-04-21 23:19:53 +00:00
|
|
|
description: "Milkie.cc (ME) is private torrent tracker for 0day / general",
|
|
|
|
link: "https://milkie.cc/",
|
|
|
|
caps: new TorznabCapabilities(),
|
|
|
|
configService: configService,
|
|
|
|
client: wc,
|
|
|
|
logger: l,
|
|
|
|
p: ps,
|
|
|
|
configData: new ConfigurationDataAPIKey())
|
2020-04-20 23:57:17 +00:00
|
|
|
{
|
|
|
|
Encoding = Encoding.UTF8;
|
|
|
|
Language = "en-us";
|
|
|
|
Type = "private";
|
|
|
|
|
|
|
|
AddCategoryMapping("1", TorznabCatType.Movies, "Movies");
|
|
|
|
AddCategoryMapping("2", TorznabCatType.TV, "TV");
|
|
|
|
AddCategoryMapping("3", TorznabCatType.Audio, "Music");
|
2020-04-26 02:36:37 +00:00
|
|
|
AddCategoryMapping("4", TorznabCatType.PCGames, "Games");
|
2020-04-20 23:57:17 +00:00
|
|
|
AddCategoryMapping("5", TorznabCatType.Books, "Ebook");
|
2020-04-26 02:36:37 +00:00
|
|
|
AddCategoryMapping("6", TorznabCatType.PC, "Apps");
|
2020-04-20 23:57:17 +00:00
|
|
|
AddCategoryMapping("7", TorznabCatType.XXX, "Adult");
|
|
|
|
}
|
|
|
|
|
|
|
|
public override async Task<IndexerConfigurationStatus> ApplyConfiguration(JToken configJson)
|
|
|
|
{
|
|
|
|
LoadValuesFromJson(configJson);
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
var results = await PerformQuery(new TorznabQuery());
|
2020-04-21 23:19:53 +00:00
|
|
|
if (!results.Any())
|
2020-04-20 23:57:17 +00:00
|
|
|
throw new Exception("Testing returned no results!");
|
|
|
|
|
|
|
|
IsConfigured = true;
|
|
|
|
SaveConfig();
|
|
|
|
return IndexerConfigurationStatus.Completed;
|
|
|
|
}
|
|
|
|
catch (Exception e)
|
|
|
|
{
|
|
|
|
IsConfigured = false;
|
|
|
|
throw new ExceptionWithConfigData(e.Message, configData);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected override async Task<IEnumerable<ReleaseInfo>> PerformQuery(TorznabQuery query)
|
|
|
|
{
|
2020-04-21 23:19:53 +00:00
|
|
|
var qc = new NameValueCollection
|
2020-04-20 23:57:17 +00:00
|
|
|
{
|
|
|
|
{ "ps", "100" }
|
|
|
|
};
|
|
|
|
|
|
|
|
if (!string.IsNullOrWhiteSpace(query.SearchTerm))
|
2020-04-21 23:19:53 +00:00
|
|
|
qc.Add("query", query.SearchTerm);
|
2020-04-20 23:57:17 +00:00
|
|
|
|
|
|
|
if (query.HasSpecifiedCategories)
|
2020-04-21 23:19:53 +00:00
|
|
|
qc.Add("categories", string.Join(",", MapTorznabCapsToTrackers(query)));
|
2020-04-20 23:57:17 +00:00
|
|
|
|
2020-04-21 23:19:53 +00:00
|
|
|
var endpoint = TorrentsEndpoint + "?" + qc.GetQueryString();
|
|
|
|
var headers = new Dictionary<string, string>
|
|
|
|
{
|
|
|
|
{ "x-milkie-auth", configData.Key.Value }
|
|
|
|
};
|
|
|
|
var jsonResponse = await RequestStringWithCookies(endpoint, headers: headers);
|
2020-04-20 23:57:17 +00:00
|
|
|
|
|
|
|
var releases = new List<ReleaseInfo>();
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
2020-06-09 17:36:57 +00:00
|
|
|
var response = JsonConvert.DeserializeObject<MilkieResponse>(jsonResponse.ContentString);
|
2020-04-20 23:57:17 +00:00
|
|
|
|
|
|
|
var dlQueryParams = new NameValueCollection
|
|
|
|
{
|
|
|
|
{ "key", configData.Key.Value }
|
|
|
|
};
|
|
|
|
|
|
|
|
foreach (var torrent in response.Torrents)
|
|
|
|
{
|
|
|
|
var link = new Uri($"{TorrentsEndpoint}/{torrent.Id}/torrent?{dlQueryParams.GetQueryString()}");
|
|
|
|
var comments = new Uri($"{SiteLink}browse/{torrent.Id}");
|
2020-04-21 23:19:53 +00:00
|
|
|
var publishDate = DateTimeUtil.FromUnknown(torrent.CreatedAt);
|
2020-04-20 23:57:17 +00:00
|
|
|
|
|
|
|
var release = new ReleaseInfo()
|
|
|
|
{
|
|
|
|
Title = torrent.ReleaseName,
|
|
|
|
Link = link,
|
|
|
|
Comments = comments,
|
|
|
|
Guid = comments,
|
2020-04-21 23:19:53 +00:00
|
|
|
PublishDate = publishDate,
|
2020-04-20 23:57:17 +00:00
|
|
|
Category = MapTrackerCatToNewznab(torrent.Category.ToString()),
|
2020-04-21 23:19:53 +00:00
|
|
|
Size = torrent.Size,
|
2020-04-20 23:57:17 +00:00
|
|
|
Seeders = torrent.Seeders,
|
|
|
|
Peers = torrent.Seeders + torrent.PartialSeeders + torrent.Leechers,
|
|
|
|
Grabs = torrent.Downloaded,
|
|
|
|
UploadVolumeFactor = 1,
|
|
|
|
DownloadVolumeFactor = 0,
|
|
|
|
MinimumRatio = 1,
|
2020-04-21 23:19:53 +00:00
|
|
|
MinimumSeedTime = 172800 // 48 hours
|
2020-04-20 23:57:17 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
releases.Add(release);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch(Exception ex)
|
|
|
|
{
|
2020-06-09 17:36:57 +00:00
|
|
|
OnParseError(jsonResponse.ContentString, ex);
|
2020-04-20 23:57:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return releases;
|
|
|
|
}
|
|
|
|
|
|
|
|
private class MilkieResponse
|
|
|
|
{
|
|
|
|
public int Hits { get; set; }
|
|
|
|
public int Took { get; set; }
|
|
|
|
public MilkieTorrent[] Torrents { get; set; }
|
|
|
|
}
|
|
|
|
|
|
|
|
private 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; }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|