Only allow private trackers

This commit is contained in:
WhatFox
2015-11-18 20:00:26 +00:00
parent 44aa33a7e0
commit 61a8585e43
20 changed files with 35 additions and 1801 deletions

View File

@@ -2,12 +2,10 @@
This project is a new fork and is recruiting development help. If you are able to help out please contact us.
#### Overview
This software creates a [Torznab](https://github.com/Sonarr/Sonarr/wiki/Implementing-a-Torznab-indexer) (with [nZEDb](https://github.com/nZEDb/nZEDb/blob/master/docs/newznab_api_specification.txt) category numbering) and [TorrentPotato](https://github.com/RuudBurger/CouchPotatoServer/wiki/Couchpotato-torrent-provider) API server on your machine. Torznab enables software such as [Sonarr](https://sonarr.tv) to access data from your favorite indexers in a similar fashion to rss but with added features such as searching. TorrentPotato is an interface accessible to [CouchPotato](https://couchpota.to/).
Jackett works as a proxy server: it translates queries from apps (Sonarr, SickRage, CouchPotato, Mylar, etc) into tracker-site-specific http queries, parses the html response, then sends results back to the requesting software. This allows for getting recent uploads (like RSS) and performing searches. Jackett is a single repository of maintained indexer scraping & translation logic - removing the burden from other apps.
We were previously focused on TV but are working on extending searches to allow for searching other items such as movies, comics, and music.
Developer note: The software implments the [Torznab](https://github.com/Sonarr/Sonarr/wiki/Implementing-a-Torznab-indexer) (with [nZEDb](https://github.com/nZEDb/nZEDb/blob/master/docs/newznab_api_specification.txt) category numbering) and [TorrentPotato](https://github.com/RuudBurger/CouchPotatoServer/wiki/Couchpotato-torrent-provider) APIs.
#### Supported Systems
@@ -15,47 +13,38 @@ We were previously focused on TV but are working on extending searches to allow
* Linux and OSX using Mono 4 (v3 should work but you may experience crashes).
#### Supported Trackers
* [AlphaRatio](https://alpharatio.cc/)
* [AnimeBytes](https://animebytes.tv/)
* [AnimeTorrents](http://animetorrents.me/)
* [Avistaz](https://avistaz.to/)
* [BakaBT](http://bakabt.me/)
* [bB](http://reddit.com/r/baconbits)
* [BeyondHD](https://beyondhd.me/)
* [BIT-HDTV](https://www.bit-hdtv.com)
* [BitMeTV](http://www.bitmetv.org/)
* [BlueTigers](https://www.bluetigers.ca/)
* [BTN](http://broadcasthe.net)
* [Demonoid](http://www.demonoid.pw/)
* [EuTorrents](https://eutorrents.to/)
* [FileList](http://filelist.ro/)
* [FrenchTorrentDb](http://www.frenchtorrentdb.com/)
* [Freshon](https://freshon.tv/)
* [HD-Space](https://hd-space.org/)
* [HD-Torrents.org](https://hd-torrents.org/)
* [Immortalseed.me](http://immortalseed.me)
* [IPTorrents](https://iptorrents.com/)
* [MoreThan.tv](https://morethan.tv/)
* [NextGen](https://nxtgn.org/)
* [pretome](https://pretome.info)
* [PrivateHD](https://privatehd.to/)
* [RARBG](https://rarbg.to/)
* [RuTor](http://rutor.org/)
* [SceneAccess](https://sceneaccess.eu/login)
* [SceneTime](https://www.scenetime.com/)
* [Shazbat](www.shazbat.tv/login)
* [ShowRSS](https://showrss.info/)
* [Strike](https://getstrike.net/)
* [T411](http://www.t411.io/)
* [TehConnection](https://tehconnection.eu/)
* [The Pirate Bay](https://thepiratebay.se/)
* [TorrentBytes](https://www.torrentbytes.net/)
* [TorrentDay](https://torrentday.eu/)
* [TorrentLeech](http://www.torrentleech.org/)
* [TorrentShack](http://torrentshack.me/)
* [Torrentz](https://torrentz.eu/)
* [TV Chaos UK](https://tvchaosuk.com/)
#### Supported Private Trackers
* AlphaRatio
* AnimeBytes
* Avistaz
* BakaBT
* bB
* BeyondHD
* BIT-HDTV
* BitMeTV
* BlueTigers
* BTN
* EuTorrents
* FileList
* Freshon
* HD-Space
* HD-Torrents
* Immortalseed
* IPTorrents
* MoreThan
* NextGen
* Pretome
* PrivateHD
* SceneAccess
* SceneTime
* Shazbat
* Strike
* TehConnection
* TorrentBytes
* TorrentDay
* TorrentLeech
* TorrentShack
* TV Chaos UK
#### Installation on Windows
@@ -97,7 +86,7 @@ Try running with the "--SSLFix true" if you are on Redhat/Fedora/NNS based libcu
You can get additional logging with the switches "-t -l". Please post logs if you are unable to resolve your issue with these switches ensuring to remove your username/password/cookies.
### Contributing
All contributions are welcome just send a pull request. Jackett's framework allows our team (and any other volunteering dev) to implement new trackers in an hour or two. If you'd like support for a new tracker but are not a developer then feel free to leave a request on the [issues page](https://github.com/zone117x/Jackett/issues). It is recommended to use Visual studio 2015 when making code changes in this project.
All contributions are welcome just send a pull request. Jackett's framework allows our team (and any other volunteering dev) to implement new trackers in an hour or two. If you'd like support for a new tracker but are not a developer then feel free to leave a request on the [issues page](https://github.com/zone117x/Jackett/issues). It is recommended to use Visual studio 2015 when making code changes in this project. We currently only support private trackers.
### Screenshots

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

View File

@@ -1,176 +0,0 @@
using CsQuery;
using Jackett.Models;
using Jackett.Services;
using Jackett.Utils;
using Jackett.Utils.Clients;
using Newtonsoft.Json.Linq;
using NLog;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using Jackett.Models.IndexerConfig;
using System.Collections.Specialized;
using System.Globalization;
namespace Jackett.Indexers
{
public class AnimeTorrents : BaseIndexer, IIndexer
{
private string LoginUrl { get { return SiteLink + "login.php"; } }
private string SearchUrl { get { return SiteLink + "ajax/torrents_data.php"; } }
private string SearchUrlReferer { get { return SiteLink + "torrents.php?cat=0&searchin=filename&search="; } }
new ConfigurationDataBasicLogin configData
{
get { return (ConfigurationDataBasicLogin)base.configData; }
set { base.configData = value; }
}
public AnimeTorrents(IIndexerManagerService i, HttpWebClient c, Logger l, IProtectionService ps)
: base(name: "AnimeTorrents",
description: "Definitive source for anime and manga",
link: "http://animetorrents.me/",
caps: new TorznabCapabilities(),
manager: i,
client: c, // Forced HTTP client for custom headers
logger: l,
p: ps,
configData: new ConfigurationDataBasicLogin())
{
AddCategoryMapping(1, TorznabCatType.MoviesSD); // Anime Movie
AddCategoryMapping(6, TorznabCatType.MoviesHD); // Anime Movie HD
AddCategoryMapping(2, TorznabCatType.TVAnime); // Anime Series
AddCategoryMapping(7, TorznabCatType.TVAnime); // Anime Series HD
AddCategoryMapping(5, TorznabCatType.XXXDVD); // Hentai (censored)
AddCategoryMapping(9, TorznabCatType.XXXDVD); // Hentai (censored) HD
AddCategoryMapping(4, TorznabCatType.XXXDVD); // Hentai (un-censored)
AddCategoryMapping(8, TorznabCatType.XXXDVD); // Hentai (un-censored) HD
AddCategoryMapping(13, TorznabCatType.BooksForeign); // Light Novel
AddCategoryMapping(3, TorznabCatType.BooksComics); // Manga
AddCategoryMapping(10, TorznabCatType.BooksComics); // Manga 18+
AddCategoryMapping(11, TorznabCatType.TVAnime); // OVA
AddCategoryMapping(12, TorznabCatType.TVAnime); // OVA HD
AddCategoryMapping(14, TorznabCatType.BooksComics); // Doujin Anime
AddCategoryMapping(15, TorznabCatType.XXXDVD); // Doujin Anime 18+
AddCategoryMapping(16, TorznabCatType.AudioForeign); // Doujin Music
AddCategoryMapping(17, TorznabCatType.BooksComics); // Doujinshi
AddCategoryMapping(18, TorznabCatType.BooksComics); // Doujinshi 18+
AddCategoryMapping(19, TorznabCatType.Audio); // OST
}
public async Task<IndexerConfigurationStatus> ApplyConfiguration(JToken configJson)
{
configData.LoadValuesFromJson(configJson);
var pairs = new Dictionary<string, string> {
{ "username", configData.Username.Value },
{ "password", configData.Password.Value },
{ "form", "login" },
{ "rememberme[]", "1" }
};
var loginPage = await RequestStringWithCookiesAndRetry(LoginUrl, null, null);
var result = await RequestLoginAndFollowRedirect(LoginUrl, pairs, loginPage.Cookies, true, SearchUrl, SiteLink);
await ConfigureIfOK(result.Cookies, result.Content != null && result.Content.Contains("logout.php"), () =>
{
CQ dom = result.Content;
var errorMessage = dom[".ui-state-error"].Text().Trim();
throw new ExceptionWithConfigData(errorMessage, configData);
});
return IndexerConfigurationStatus.RequiresTesting;
}
public async Task<IEnumerable<ReleaseInfo>> PerformQuery(TorznabQuery query)
{
var releases = new List<ReleaseInfo>();
var searchString = query.GetQueryString();
var searchUrl = SearchUrl;
var queryCollection = new NameValueCollection();
queryCollection.Add("total", "146"); // Not sure what this is about but its required!
var cat = "0";
var queryCats = MapTorznabCapsToTrackers(query);
if (queryCats.Count == 1)
{
cat = queryCats.First().ToString();
}
queryCollection.Add("cat", cat);
queryCollection.Add("searchin", "filename");
queryCollection.Add("search", searchString);
queryCollection.Add("page", "1");
searchUrl += "?" + queryCollection.GetQueryString();
var extraHeaders = new Dictionary<string, string>()
{
{ "X-Requested-With", "XMLHttpRequest" }
};
var response = await RequestStringWithCookiesAndRetry(searchUrl, null, SearchUrlReferer, extraHeaders);
var results = response.Content;
try
{
CQ dom = results;
var rows = dom["tr"];
foreach (var row in rows.Skip(1))
{
var release = new ReleaseInfo();
var qRow = row.Cq();
var qTitleLink = qRow.Find("td:eq(1) a:eq(0)").First();
release.Title = qTitleLink.Find("strong").Text().Trim();
// If we search an get no results, we still get a table just with no info.
if (string.IsNullOrWhiteSpace(release.Title))
{
break;
}
release.Description = release.Title;
release.Guid = new Uri(qTitleLink.Attr("href"));
release.Comments = release.Guid;
var dateString = qRow.Find("td:eq(4)").Text();
release.PublishDate = DateTime.ParseExact(dateString, "dd MMM yy", CultureInfo.InvariantCulture);
var qLink = qRow.Find("td:eq(2) a");
release.Link = new Uri(qLink.Attr("href"));
var sizeStr = qRow.Find("td:eq(5)").Text();
release.Size = ReleaseInfo.GetBytes(sizeStr);
var connections = qRow.Find("td:eq(7)").Text().Trim().Split("/".ToCharArray(),StringSplitOptions.RemoveEmptyEntries);
release.Seeders = ParseUtil.CoerceInt(connections[0].Trim());
release.Peers = ParseUtil.CoerceInt(connections[1].Trim()) + release.Seeders;
var rCat = row.Cq().Find("td:eq(0) a").First().Attr("href");
var rCatIdx = rCat.IndexOf("cat=");
if (rCatIdx > -1)
{
rCat = rCat.Substring(rCatIdx + 4);
}
release.Category = MapTrackerCatToNewznab(rCat);
releases.Add(release);
}
}
catch (Exception ex)
{
OnParseError(results, ex);
}
return releases;
}
}
}

View File

@@ -1,196 +0,0 @@
using CsQuery;
using Jackett.Models;
using Jackett.Services;
using Jackett.Utils;
using Jackett.Utils.Clients;
using Newtonsoft.Json.Linq;
using NLog;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using Jackett.Models.IndexerConfig;
namespace Jackett.Indexers
{
public class BakaBT : BaseIndexer, IIndexer
{
public string SearchUrl { get { return SiteLink + "browse.php?only=0&hentai=1&incomplete=1&lossless=1&hd=1&multiaudio=1&bonus=1&c1=1&reorder=1&q="; } }
public string LoginUrl { get { return SiteLink + "login.php"; } }
new ConfigurationDataBasicLogin configData
{
get { return (ConfigurationDataBasicLogin)base.configData; }
set { base.configData = value; }
}
public BakaBT(IIndexerManagerService i, IWebClient wc, Logger l, IProtectionService ps)
: base(name: "BakaBT",
description: "Anime Community",
link: "http://bakabt.me/",
caps: new TorznabCapabilities(TorznabCatType.TVAnime),
manager: i,
client: wc,
logger: l,
p: ps,
configData: new ConfigurationDataBasicLogin())
{
}
public async Task<IndexerConfigurationStatus> ApplyConfiguration(JToken configJson)
{
configData.LoadValuesFromJson(configJson);
var loginForm = await webclient.GetString(new Utils.Clients.WebRequest()
{
Url = LoginUrl,
Type = RequestType.GET
});
var pairs = new Dictionary<string, string> {
{ "username", configData.Username.Value },
{ "password", configData.Password.Value },
{ "returnto", "/index.php" }
};
var response = await RequestLoginAndFollowRedirect(LoginUrl, pairs, loginForm.Cookies, true, null, SiteLink);
var responseContent = response.Content;
await ConfigureIfOK(response.Cookies, responseContent.Contains("<a href=\"logout.php\">Logout</a>"), () =>
{
CQ dom = responseContent;
var messageEl = dom[".error"].First();
var errorMessage = messageEl.Text().Trim();
throw new ExceptionWithConfigData(errorMessage, configData);
});
return IndexerConfigurationStatus.RequiresTesting;
}
public async Task<IEnumerable<ReleaseInfo>> PerformQuery(TorznabQuery query)
{
// This tracker only deals with full seasons so chop off the episode/season number if we have it D:
if (!string.IsNullOrWhiteSpace(query.SearchTerm))
{
var splitindex = query.SearchTerm.LastIndexOf(' ');
if (splitindex > -1)
query.SearchTerm = query.SearchTerm.Substring(0, splitindex);
}
var releases = new List<ReleaseInfo>();
var searchString = query.SanitizedSearchTerm;
var episodeSearchUrl = SearchUrl + HttpUtility.UrlEncode(searchString);
var response = await RequestStringWithCookiesAndRetry(episodeSearchUrl);
try
{
CQ dom = response.Content;
var rows = dom[".torrents tr.torrent"];
foreach (var row in rows)
{
var qRow = row.Cq();
var qTitleLink = qRow.Find("a.title").First();
var title = qTitleLink.Text().Trim();
// Insert before the release info
var taidx = title.IndexOf('(');
var tbidx = title.IndexOf('[');
if (taidx == -1)
taidx = title.Length;
if (tbidx == -1)
tbidx = title.Length;
var titleSplit = Math.Min(taidx, tbidx);
var titleSeries = title.Substring(0, titleSplit);
var releaseInfo = title.Substring(titleSplit);
// For each over each pipe deliminated name
foreach (var name in titleSeries.Split("|".ToCharArray(), StringSplitOptions.RemoveEmptyEntries))
{
var release = new ReleaseInfo();
release.Title = (name + releaseInfo).Trim();
// Ensure the season is defined as this tracker only deals with full seasons
if (release.Title.IndexOf("Season") == -1)
{
// Insert before the release info
var aidx = release.Title.IndexOf('(');
var bidx = release.Title.IndexOf('[');
if (aidx == -1)
aidx = release.Title.Length;
if (bidx == -1)
bidx = release.Title.Length;
var insertPoint = Math.Min(aidx, bidx);
release.Title = release.Title.Substring(0, insertPoint) + "Season 1 " + release.Title.Substring(insertPoint);
}
release.Description = release.Title;
release.Guid = new Uri(SiteLink + qTitleLink.Attr("href"));
release.Comments = release.Guid;
release.Link = new Uri(SiteLink + qRow.Find(".peers a").First().Attr("href"));
release.Seeders = int.Parse(qRow.Find(".peers a").Get(0).InnerText);
release.Peers = release.Seeders + int.Parse(qRow.Find(".peers a").Get(1).InnerText);
release.MinimumRatio = 1;
var size = qRow.Find(".size").First().Text();
release.Size = ReleaseInfo.GetBytes(size);
//22 Jul 15
var dateStr = qRow.Find(".added").First().Text().Replace("'", string.Empty);
if (dateStr.Split(' ')[0].Length == 1)
dateStr = "0" + dateStr;
if (string.Equals(dateStr, "yesterday", StringComparison.InvariantCultureIgnoreCase))
{
release.PublishDate = DateTime.Now.AddDays(-1);
}
else if (string.Equals(dateStr, "today", StringComparison.InvariantCultureIgnoreCase))
{
release.PublishDate = DateTime.Now;
}
else
{
release.PublishDate = DateTime.ParseExact(dateStr, "dd MMM yy", CultureInfo.InvariantCulture);
}
releases.Add(release);
}
}
}
catch (Exception ex)
{
OnParseError(response.Content, ex);
}
return releases;
}
public override async Task<byte[]> Download(Uri link)
{
var downloadPage = await RequestStringWithCookies(link.ToString());
CQ dom = downloadPage.Content;
var downloadLink = dom.Find(".download_link").First().Attr("href");
if (string.IsNullOrWhiteSpace(downloadLink))
{
throw new Exception("Unable to find download link.");
}
var response = await RequestBytesWithCookies(SiteLink + downloadLink);
return response.Content;
}
}
}

View File

@@ -1,233 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Jackett.Models;
using Newtonsoft.Json.Linq;
using NLog;
using Jackett.Utils;
using System.Net;
using System.Net.Http;
using CsQuery;
using System.Web;
using Jackett.Services;
using Jackett.Utils.Clients;
using System.Text.RegularExpressions;
using Jackett.Models.IndexerConfig;
using System.Globalization;
using Newtonsoft.Json;
using Jackett.Models.IndexerConfig.Bespoke;
namespace Jackett.Indexers
{
public class RuTor : BaseIndexer, IIndexer
{
private string SearchUrl { get { return SiteLink + "search/0/{0}/000/0/{1}"; } }
private string BrowseUrl { get { return SiteLink + "browse/0/{0}/0/0"; } }
readonly static string defaultSiteLink = "http://rutor.org/";
new ConfigurationDataRuTor configData
{
get { return (ConfigurationDataRuTor)base.configData; }
set { base.configData = value; }
}
public RuTor(IIndexerManagerService i, Logger l, IWebClient wc, IProtectionService ps)
: base(name: "RUTor",
description: "Свободный торрент трекер",
link: "http://rutor.org/",
caps: TorznabUtil.CreateDefaultTorznabTVCaps(),
manager: i,
client: wc,
logger: l,
p: ps,
configData: new ConfigurationDataRuTor(defaultSiteLink))
{
TorznabCaps.Categories.Add(TorznabCatType.TVAnime);
TorznabCaps.Categories.Add(TorznabCatType.Movies);
TorznabCaps.Categories.Add(TorznabCatType.Audio);
TorznabCaps.Categories.Add(TorznabCatType.Books);
}
public async Task<IndexerConfigurationStatus> ApplyConfiguration(JToken configJson)
{
configData.LoadValuesFromJson(configJson);
var oldConfig = configData;
var releases = await PerformQuery(new TorznabQuery());
await ConfigureIfOK(string.Empty, releases.Count() > 0, () =>
{
configData = oldConfig;
throw new Exception("Could not find releases from this URL");
});
return IndexerConfigurationStatus.RequiresTesting;
}
protected override void SaveConfig()
{
indexerService.SaveConfig(this as IIndexer, JsonConvert.SerializeObject(configData));
}
// Override to load legacy config format
public override void LoadFromSavedConfiguration(JToken jsonConfig)
{
var json = jsonConfig.ToString();
configData = JsonConvert.DeserializeObject<ConfigurationDataRuTor>(json);
IsConfigured = true;
}
private readonly int CAT_ANY = 0;
private readonly int CAT_FOREIGN_MOVIE = 1;
// private readonly int CAT_OUR_MOVIES = 5;
// private readonly int CAT_POP_SCIFI_MOVIES = 12;
private readonly int CAT_TV_SERIES = 4;
// private readonly int CAT_TV = 6;
// private readonly int CAT_ANIMATION = 7;
private readonly int CAT_ANIME = 10;
private readonly int CAT_MUSIC = 2;
// private readonly int CAT_GAMES = 8;
// private readonly int CAT_SOFTWARE = 9;
// private readonly int CAT_SPORTS_HEALTH = 13;
// private readonly int CAT_HUMOR = 15;
// private readonly int CAT_ECONOMY_LIFE = 14;
private readonly int CAT_BOOKS = 11;
// private readonly int CAT_OTHER = 3;
public async Task<IEnumerable<ReleaseInfo>> PerformQuery(TorznabQuery query)
{
var releases = new List<ReleaseInfo>();
var searchString = query.GetQueryString();
var searchCategory = CAT_ANY;
if (query.Categories.Contains(TorznabCatType.TV.ID) ||
query.Categories.Contains(TorznabCatType.TVHD.ID) ||
query.Categories.Contains(TorznabCatType.TVSD.ID))
{
searchCategory = CAT_TV_SERIES;
}
if ((searchCategory == CAT_ANY) &&
(query.Categories.Contains(TorznabCatType.Movies.ID) ||
query.Categories.Contains(TorznabCatType.MoviesForeign.ID) ||
query.Categories.Contains(TorznabCatType.MoviesHD.ID) ||
query.Categories.Contains(TorznabCatType.MoviesSD.ID)))
{
searchCategory = CAT_FOREIGN_MOVIE;
}
if ((searchCategory == CAT_ANY) &&
(query.Categories.Contains(TorznabCatType.TVAnime.ID)))
{
searchCategory = CAT_ANIME;
}
if ((searchCategory == CAT_ANY) &&
(query.Categories.Contains(TorznabCatType.Books.ID)))
{
searchCategory = CAT_BOOKS;
}
if ((searchCategory == CAT_ANY) &&
(query.Categories.Contains(TorznabCatType.Audio.ID) ||
query.Categories.Contains(TorznabCatType.AudioLossless.ID) ||
query.Categories.Contains(TorznabCatType.AudioMP3.ID)))
{
searchCategory = CAT_MUSIC;
}
string queryUrl = string.Empty;
if (string.IsNullOrWhiteSpace(searchString))
{
queryUrl = string.Format(BrowseUrl, searchCategory);
}
else
{
queryUrl = string.Format(SearchUrl, searchCategory, HttpUtility.UrlEncode(searchString.Trim()));
}
var results = await RequestStringWithCookiesAndRetry(queryUrl, string.Empty);
try
{
CQ dom = results.Content;
var rows = dom["#index table tr"];
foreach (var row in rows.Skip(1))
{
var release = new ReleaseInfo();
release.MinimumRatio = 1;
release.MinimumSeedTime = 172800;
var date = StringUtil.StripNonAlphaNumeric(row.Cq().Find("td:eq(0)").Text().Trim()
.Replace("Янв", "01")
.Replace("Фев", "02")
.Replace("Мар", "03")
.Replace("Апр", "04")
.Replace("Май", "05")
.Replace("Июн", "06")
.Replace("Июл", "07")
.Replace("Авг", "08")
.Replace("Сен", "09")
.Replace("Окт", "10")
.Replace("Ноя", "11")
.Replace("Дек", "12"));
release.PublishDate = DateTime.ParseExact(date, "ddMMyy", CultureInfo.InvariantCulture);
var hasTorrent = row.Cq().Find("td:eq(1) a").Length == 3;
var titleIndex = 1;
if (hasTorrent)
titleIndex++;
release.Title = row.Cq().Find("td:eq(1) a:eq(" + titleIndex + ")").Text().Trim();
if (configData.StripRussian.Value)
{
var split = release.Title.IndexOf('/');
if (split > -1)
{
release.Title = release.Title.Substring(split + 1).Trim();
}
}
release.Description = release.Title;
var hasComments = row.Cq().Find("td:eq(2) img").Length > 0;
var sizeCol = 2;
if (hasComments)
sizeCol++;
var sizeStr = StringUtil.StripRegex(row.Cq().Find("td:eq(" + sizeCol + ")").Text(), "[^a-zA-Z0-9\\. -]", " ").Trim();
string[] sizeSplit = sizeStr.Split(' ');
release.Size = ReleaseInfo.GetBytes(sizeSplit[1].ToLower(), ParseUtil.CoerceFloat(sizeSplit[0]));
release.Seeders = ParseUtil.CoerceInt(row.Cq().Find(".green").Text().Trim());
release.Peers = ParseUtil.CoerceInt(row.Cq().Find(".red").Text().Trim()) + release.Seeders;
release.Guid = new Uri(configData.Url.Value + row.Cq().Find("td:eq(1) a:eq(" + titleIndex + ")").Attr("href").Substring(1));
release.Comments = release.Guid;
if (hasTorrent)
{
release.Link = new Uri(row.Cq().Find("td:eq(1) a:eq(0)").Attr("href"));
release.MagnetUri = new Uri(row.Cq().Find("td:eq(1) a:eq(1)").Attr("href"));
}
else
{
release.MagnetUri = new Uri(row.Cq().Find("td:eq(1) a:eq(0)").Attr("href"));
}
releases.Add(release);
}
}
catch (Exception ex)
{
OnParseError(results.Content, ex);
}
return releases;
}
}
}

View File

@@ -1,187 +0,0 @@
using Jackett.Models;
using Jackett.Models.IndexerConfig;
using Jackett.Services;
using Jackett.Utils.Clients;
using Newtonsoft.Json.Linq;
using NLog;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
namespace Jackett.Indexers
{
public class Rarbg : BaseIndexer, IIndexer
{
readonly static string defaultSiteLink = "https://torrentapi.org/";
private Uri BaseUri
{
get { return new Uri(configData.Url.Value); }
set { configData.Url.Value = value.ToString(); }
}
private string ApiEndpoint { get { return BaseUri + "pubapi_v2.php"; } }
private string TokenUrl { get { return ApiEndpoint + "?get_token=get_token"; } }
private string SearchUrl { get { return ApiEndpoint + "?app_id=jackett_v{0}&mode={1}&format=json_extended&search_string={2}&token={3}"; } }
new ConfigurationDataUrl configData
{
get { return (ConfigurationDataUrl)base.configData; }
set { base.configData = value; }
}
private DateTime lastTokenFetch;
private string token;
readonly TimeSpan TOKEN_DURATION = TimeSpan.FromMinutes(10);
private bool HasValidToken { get { return !string.IsNullOrEmpty(token) && lastTokenFetch > DateTime.Now - TOKEN_DURATION; } }
Dictionary<string, int> categoryLabels;
public Rarbg(IIndexerManagerService i, IWebClient wc, Logger l, IProtectionService ps)
: base(name: "RARBG",
description: "RARBG",
link: defaultSiteLink,
caps: new TorznabCapabilities(),
manager: i,
client: wc,
logger: l,
p: ps,
configData: new ConfigurationDataUrl(defaultSiteLink))
{
categoryLabels = new Dictionary<string, int>();
AddCat(4, TorznabCatType.XXX, "XXX (18+)");
AddCat(14, TorznabCatType.MoviesSD, "Movies/XVID");
AddCat(48, TorznabCatType.MoviesHD, "Movies/XVID/720");
AddCat(17, TorznabCatType.MoviesSD, "Movies/x264");
AddCat(44, TorznabCatType.MoviesHD, "Movies/x264/1080");
AddCat(45, TorznabCatType.MoviesHD, "Movies/x264/720");
AddCat(47, TorznabCatType.Movies3D, "Movies/x264/3D");
AddCat(42, TorznabCatType.MoviesBluRay, "Movies/Full BD");
AddCat(46, TorznabCatType.MoviesBluRay, "Movies/BD Remux");
AddCat(18, TorznabCatType.TVSD, "TV Episodes");
AddCat(41, TorznabCatType.TVHD, "TV HD Episodes");
AddCat(23, TorznabCatType.AudioMP3, "Music/MP3");
AddCat(25, TorznabCatType.AudioLossless, "Music/FLAC");
AddCat(27, TorznabCatType.PCGames, "Games/PC ISO");
AddCat(28, TorznabCatType.PCGames, "Games/PC RIP");
AddCat(40, TorznabCatType.ConsolePS3, "Games/PS3");
AddCat(32, TorznabCatType.ConsoleXbox360, "Games/XBOX-360");
AddCat(33, TorznabCatType.PCISO, "Software/PC ISO");
AddCat(35, TorznabCatType.BooksEbook, "e-Books");
}
void AddCat(int cat, TorznabCategory catType, string label)
{
AddCategoryMapping(cat, catType);
categoryLabels.Add(label, cat);
}
async Task CheckToken()
{
if (!HasValidToken)
{
var result = await RequestStringWithCookiesAndRetry(TokenUrl);
var json = JObject.Parse(result.Content);
token = json.Value<string>("token");
lastTokenFetch = DateTime.Now;
}
}
public async Task<IndexerConfigurationStatus> ApplyConfiguration(JToken configJson)
{
configData.LoadValuesFromJson(configJson);
var releases = await PerformQuery(new TorznabQuery());
await ConfigureIfOK(string.Empty, releases.Count() > 0, () =>
{
throw new Exception("Could not find releases from this URL");
});
return IndexerConfigurationStatus.Completed;
}
public Task<IEnumerable<ReleaseInfo>> PerformQuery(TorznabQuery query)
{
return PerformQuery(query, 0);
}
public async Task<IEnumerable<ReleaseInfo>> PerformQuery(TorznabQuery query, int attempts = 0)
{
await CheckToken();
var releases = new List<ReleaseInfo>();
var queryStr = HttpUtility.UrlEncode(query.GetQueryString());
var mode = string.IsNullOrEmpty(queryStr) ? "list" : "search";
var episodeSearchUrl = string.Format(SearchUrl, Engine.ConfigService.GetVersion(), mode, queryStr, token);
var cats = string.Join(";", MapTorznabCapsToTrackers(query));
if (!string.IsNullOrEmpty(cats))
{
episodeSearchUrl += "&category=" + cats;
}
var response = await RequestStringWithCookiesAndRetry(episodeSearchUrl, string.Empty);
try
{
var jsonContent = JObject.Parse(response.Content);
int errorCode = jsonContent.Value<int>("error_code");
if (errorCode == 20) // no results found
{
return releases.ToArray();
}
if (errorCode > 0) // too many requests per second
{
if (attempts < 3)
{
await Task.Delay(TimeSpan.FromSeconds(2));
return await PerformQuery(query, ++attempts);
}
else
{
throw new Exception(jsonContent.Value<string>("error"));
}
}
foreach (var item in jsonContent.Value<JArray>("torrent_results"))
{
var release = new ReleaseInfo();
release.Title = item.Value<string>("title");
release.Description = release.Title;
release.Category = MapTrackerCatToNewznab(categoryLabels[item.Value<string>("category")].ToString());
release.MagnetUri = new Uri(item.Value<string>("download"));
release.InfoHash = release.MagnetUri.ToString().Split(':')[3].Split('&')[0];
release.Comments = new Uri(item.Value<string>("info_page"));
release.Guid = release.Comments;
// ex: 2015-08-16 21:25:08 +0000
var dateStr = item.Value<string>("pubdate").Replace(" +0000", "");
var dateTime = DateTime.ParseExact(dateStr, "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture);
release.PublishDate = DateTime.SpecifyKind(dateTime, DateTimeKind.Utc).ToLocalTime();
release.Seeders = item.Value<int>("seeders");
release.Peers = item.Value<int>("leechers") + release.Seeders;
release.Size = item.Value<long>("size");
releases.Add(release);
}
}
catch (Exception ex)
{
OnParseError(response.Content, ex);
}
return releases.ToArray();
}
}
}

View File

@@ -1,132 +0,0 @@
using Jackett.Models;
using Jackett.Services;
using Jackett.Utils;
using Jackett.Utils.Clients;
using Newtonsoft.Json.Linq;
using NLog;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Xml;
using Jackett.Models.IndexerConfig;
namespace Jackett.Indexers
{
public class ShowRSS : BaseIndexer, IIndexer
{
readonly static string defaultSiteLink = "http://showrss.info/";
private Uri BaseUri
{
get { return new Uri(configData.Url.Value); }
set { configData.Url.Value = value.ToString(); }
}
private string SearchAllUrl { get { return BaseUri + "feeds/all.rss"; } }
new ConfigurationDataUrl configData
{
get { return (ConfigurationDataUrl)base.configData; }
set { base.configData = value; }
}
public ShowRSS(IIndexerManagerService i, Logger l, IWebClient wc, IProtectionService ps)
: base(name: "ShowRSS",
description: "showRSS is a service that allows you to keep track of your favorite TV shows",
link: defaultSiteLink,
caps: TorznabUtil.CreateDefaultTorznabTVCaps(),
manager: i,
client: wc,
logger: l,
p: ps,
configData: new ConfigurationDataUrl(defaultSiteLink))
{
}
public async Task<IndexerConfigurationStatus> ApplyConfiguration(JToken configJson)
{
configData.LoadValuesFromJson(configJson);
var releases = await PerformQuery(new TorznabQuery());
await ConfigureIfOK(string.Empty, releases.Count() > 0, () =>
{
throw new Exception("Could not find releases from this URL");
});
return IndexerConfigurationStatus.RequiresTesting;
}
// Override to load legacy config format
public override void LoadFromSavedConfiguration(JToken jsonConfig)
{
if (jsonConfig is JObject)
{
BaseUri = new Uri(jsonConfig.Value<string>("base_url"));
SaveConfig();
IsConfigured = true;
return;
}
base.LoadFromSavedConfiguration(jsonConfig);
}
public override Task<byte[]> Download(Uri link)
{
throw new NotImplementedException();
}
public async Task<IEnumerable<ReleaseInfo>> PerformQuery(TorznabQuery query)
{
var releases = new List<ReleaseInfo>();
var episodeSearchUrl = string.Format(SearchAllUrl);
var result = await RequestStringWithCookiesAndRetry(episodeSearchUrl, string.Empty);
var xmlDoc = new XmlDocument();
try
{
xmlDoc.LoadXml(result.Content);
ReleaseInfo release;
string serie_title;
foreach (XmlNode node in xmlDoc.GetElementsByTagName("item"))
{
release = new ReleaseInfo();
release.MinimumRatio = 1;
release.MinimumSeedTime = 172800;
serie_title = node.SelectSingleNode(".//*[local-name()='rawtitle']").InnerText;
release.Title = serie_title;
release.Comments = new Uri(node.SelectSingleNode("link").InnerText);
int category = 0;
int.TryParse(node.SelectSingleNode("title").InnerText, out category);
release.Category = category;
var test = node.SelectSingleNode("enclosure");
release.Guid = new Uri(test.Attributes["url"].Value);
release.PublishDate = DateTime.Parse(node.SelectSingleNode("pubDate").InnerText, CultureInfo.InvariantCulture);
release.Description = node.SelectSingleNode("description").InnerText;
release.InfoHash = node.SelectSingleNode("description").InnerText;
release.Size = 0;
release.Seeders = 1;
release.Peers = 1;
release.MagnetUri = new Uri(node.SelectSingleNode("link").InnerText);
releases.Add(release);
}
}
catch (Exception ex)
{
OnParseError(result.Content, ex);
}
return releases;
}
}
}

View File

@@ -1,173 +0,0 @@
using Jackett.Models;
using Jackett.Services;
using Jackett.Utils;
using Jackett.Utils.Clients;
using Newtonsoft.Json.Linq;
using NLog;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using Jackett.Models.IndexerConfig;
using System.Collections.Specialized;
using Jackett.Models.IndexerConfig.Bespoke;
namespace Jackett.Indexers
{
public class Strike : BaseIndexer, IIndexer
{
readonly static string defaultSiteLink = "https://getstrike.net/";
private Uri BaseUri
{
get { return new Uri(configData.Url.Value); }
set { configData.Url.Value = value.ToString(); }
}
private string SearchUrl { get { return BaseUri + "api/v2/torrents/search/?phrase={0}"; } }
private string DownloadUrl { get { return BaseUri + "torrents/api/download/{0}.torrent"; } }
new ConfigurationDataStrike configData
{
get { return (ConfigurationDataStrike)base.configData; }
set { base.configData = value; }
}
public Strike(IIndexerManagerService i, Logger l, IWebClient wc, IProtectionService ps)
: base(name: "Strike",
description: "Torrent search engine",
link: defaultSiteLink,
caps: new TorznabCapabilities(),
manager: i,
client: wc,
logger: l,
p: ps,
configData: new ConfigurationDataStrike(defaultSiteLink))
{
AddCategoryMapping("Anime", TorznabCatType.TVAnime);
AddCategoryMapping("Applications", TorznabCatType.PC);
AddCategoryMapping("Books", TorznabCatType.Books);
AddCategoryMapping("Games", TorznabCatType.PCGames);
AddCategoryMapping("Movies", TorznabCatType.Movies);
AddCategoryMapping("TV", TorznabCatType.TV);
AddCategoryMapping("XXX", TorznabCatType.XXX);
AddCategoryMapping("Music", TorznabCatType.Audio);
/*AddCategoryMapping("Movies:Highres Movies", TorznabCatType.MoviesHD);
AddCategoryMapping("Movies:3D Movies", TorznabCatType.Movies3D);
AddCategoryMapping("Books:Ebooks", TorznabCatType.BooksEbook);
AddCategoryMapping("Books:Comics", TorznabCatType.BooksComics);
AddCategoryMapping("Books:Audio Books", TorznabCatType.AudioAudiobook);
AddCategoryMapping("Games:XBOX360", TorznabCatType.ConsoleXbox360);
AddCategoryMapping("Games:Wii", TorznabCatType.ConsoleWii);
AddCategoryMapping("Games:PSP", TorznabCatType.ConsolePSP);
AddCategoryMapping("Games:PS3", TorznabCatType.ConsolePS3);
AddCategoryMapping("Games:PC", TorznabCatType.PCGames);
AddCategoryMapping("Games:Android", TorznabCatType.PCPhoneAndroid);
AddCategoryMapping("Music:Mp3", TorznabCatType.AudioMP3);*/
}
public async Task<IndexerConfigurationStatus> ApplyConfiguration(JToken configJson)
{
configData.LoadValuesFromJson(configJson);
var releases = await PerformQuery(new TorznabQuery());
await ConfigureIfOK(string.Empty, releases.Count() > 0, () =>
{
throw new Exception("Could not find releases from this URL");
});
return IndexerConfigurationStatus.Completed;
}
// Override to load legacy config format
public override void LoadFromSavedConfiguration(JToken jsonConfig)
{
if (jsonConfig is JObject)
{
BaseUri = new Uri(jsonConfig.Value<string>("base_url"));
SaveConfig();
IsConfigured = true;
return;
}
base.LoadFromSavedConfiguration(jsonConfig);
}
public async Task<IEnumerable<ReleaseInfo>> PerformQuery(TorznabQuery query)
{
List<ReleaseInfo> releases = new List<ReleaseInfo>();
var queryString = query.GetQueryString();
var searchTerm = string.IsNullOrEmpty(queryString) ? DateTime.Now.Year.ToString() : queryString;
var episodeSearchUrl = string.Format(SearchUrl, HttpUtility.UrlEncode(searchTerm));
var trackerCategories = MapTorznabCapsToTrackers(query, mapChildrenCatsToParent: true);
// This tracker can only search one cat at a time, otherwise search all and filter results
if (trackerCategories.Count == 1)
{
episodeSearchUrl += "&category=" + trackerCategories[0];
}
var results = await RequestStringWithCookiesAndRetry(episodeSearchUrl, string.Empty);
try
{
var jResults = JObject.Parse(results.Content);
foreach (JObject result in (JArray)jResults["torrents"])
{
var release = new ReleaseInfo();
release.MinimumRatio = 1;
release.MinimumSeedTime = 172800;
if (trackerCategories.Count > 0 && !trackerCategories.Contains((string)result["torrent_category"]))
{
continue;
}
release.Category = MapTrackerCatToNewznab((string)result["torrent_category"]);
release.Title = (string)result["torrent_title"];
release.Description = release.Title;
release.Seeders = (int)result["seeds"];
release.Peers = (int)result["leeches"] + release.Seeders;
release.Size = (long)result["size"];
// "Apr 2, 2015", "Apr 12, 2015" (note the spacing)
// some are unix timestamps, some are not.. :/
var dateString = string.Join(" ", ((string)result["upload_date"]).Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries));
float dateVal;
if (ParseUtil.TryCoerceFloat(dateString, out dateVal))
release.PublishDate = DateTimeUtil.UnixTimestampToDateTime(dateVal);
else
release.PublishDate = DateTime.ParseExact(dateString, "MMM d, yyyy", CultureInfo.InvariantCulture);
release.Guid = new Uri((string)result["page"]);
release.Comments = release.Guid;
release.InfoHash = (string)result["torrent_hash"];
release.MagnetUri = new Uri((string)result["magnet_uri"]);
release.Link = new Uri(string.Format(DownloadUrl, release.InfoHash));
releases.Add(release);
}
}
catch (Exception ex)
{
OnParseError(results.Content, ex);
}
return releases;
}
public override Task<byte[]> Download(Uri link)
{
throw new NotImplementedException();
}
}
}

View File

@@ -1,249 +0,0 @@
using Jackett.Models;
using Jackett.Services;
using Jackett.Utils;
using Jackett.Utils.Clients;
using Newtonsoft.Json.Linq;
using NLog;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using Jackett.Models.IndexerConfig;
namespace Jackett.Indexers
{
public class T411 : BaseIndexer, IIndexer
{
private readonly string CommentsUrl = "";
const string ApiUrl = "http://api.t411.in";
const string AuthUrl = ApiUrl + "/auth";
const string SearchUrl = ApiUrl + "/torrents/search/{0}";
const string DownloadUrl = ApiUrl + "/torrents/download/{0}";
HttpClientHandler handler;
HttpClient client;
new ConfigurationDataLoginTokin configData
{
get { return (ConfigurationDataLoginTokin)base.configData; }
set { base.configData = value; }
}
public T411(IIndexerManagerService i, Logger l, IWebClient wc, IProtectionService ps)
: base(name: "T411",
description: "French Torrent Tracker",
link: "http://www.t411.in/",
caps: TorznabUtil.CreateDefaultTorznabTVCaps(),
manager: i,
client: wc,
logger: l,
p: ps,
configData: new ConfigurationDataLoginTokin())
{
CommentsUrl = SiteLink + "/torrents/{0}";
IsConfigured = false;
handler = new HttpClientHandler
{
AllowAutoRedirect = true
};
client = new HttpClient(handler);
AddCategoryMapping("Film\\/Vidéo", TorznabCatType.Movies);
AddCategoryMapping("Vidéo-clips", TorznabCatType.Other);
AddCategoryMapping("Série TV", TorznabCatType.TV);
AddCategoryMapping("Animation", TorznabCatType.TVAnime);
AddCategoryMapping("Film", TorznabCatType.Movies);
AddCategoryMapping("Concert", TorznabCatType.AudioVideo);
AddCategoryMapping("Documentaire", TorznabCatType.Audio);
AddCategoryMapping("Spectacle", TorznabCatType.TV);
AddCategoryMapping("Sport", TorznabCatType.TVSport);
AddCategoryMapping("Animation Série", TorznabCatType.TVAnime);
AddCategoryMapping("Emission TV", TorznabCatType.TV);
AddCategoryMapping("Application", TorznabCatType.PC0day);
AddCategoryMapping("Linux", TorznabCatType.PC);
AddCategoryMapping("MacOS", TorznabCatType.PCMac);
AddCategoryMapping("Windows", TorznabCatType.PC);
AddCategoryMapping("Smartphone", TorznabCatType.PCPhoneOther);
AddCategoryMapping("Tablette", TorznabCatType.PCPhoneOther);
AddCategoryMapping("Autre", TorznabCatType.PC);
AddCategoryMapping("Formation", TorznabCatType.PC);
AddCategoryMapping("Emulation", TorznabCatType.PC);
AddCategoryMapping("Emulateurs", TorznabCatType.PC);
AddCategoryMapping("Roms", TorznabCatType.PC);
AddCategoryMapping("GPS", TorznabCatType.Other);
AddCategoryMapping("Applications", TorznabCatType.Other);
AddCategoryMapping("Cartes", TorznabCatType.Other);
AddCategoryMapping("Divers", TorznabCatType.Other);
AddCategoryMapping("Audio", TorznabCatType.Audio);
AddCategoryMapping("Karaoke", TorznabCatType.Audio);
AddCategoryMapping("Samples", TorznabCatType.Audio);
AddCategoryMapping("Musique", TorznabCatType.Audio);
AddCategoryMapping("Podcast Radio", TorznabCatType.Audio);
AddCategoryMapping("eBook", TorznabCatType.BooksEbook);
AddCategoryMapping("Audio", TorznabCatType.AudioAudiobook);
AddCategoryMapping("Bds", TorznabCatType.AudioVideo);
AddCategoryMapping("Comics", TorznabCatType.BooksComics);
AddCategoryMapping("Livres", TorznabCatType.Books);
AddCategoryMapping("Mangas", TorznabCatType.BooksForeign);
AddCategoryMapping("Presse", TorznabCatType.BooksMagazines);
AddCategoryMapping("xXx", TorznabCatType.XXX);
AddCategoryMapping("eBooks", TorznabCatType.XXXImageset);
AddCategoryMapping("Jeux vidéo", TorznabCatType.XXX);
AddCategoryMapping("Video", TorznabCatType.XXXDVD);
//AddCategoryMapping("Animation", TorznabCatType.XXX); Used above :/
AddCategoryMapping("Jeu vidéo", TorznabCatType.PCGames);
AddCategoryMapping("Linux", TorznabCatType.PCGames);
AddCategoryMapping("MacOS", TorznabCatType.PCGames);
// AddCategoryMapping("Windows", TorznabCatType.PCGames); Used above :/
AddCategoryMapping("Nintendo", TorznabCatType.Console);
AddCategoryMapping("Sony", TorznabCatType.Console);
AddCategoryMapping("Microsoft", TorznabCatType.PCGames);
AddCategoryMapping("Smartphone", TorznabCatType.PCPhoneOther);
AddCategoryMapping("Tablette", TorznabCatType.PCPhoneOther);
AddCategoryMapping("Autre", TorznabCatType.Other);
AddCategoryMapping("Jeux vidéo", TorznabCatType.Other);
}
async Task<string> GetAuthToken(bool forceFetch = false)
{
if (!forceFetch && configData.LastTokenFetchDateTime > DateTime.Now - TimeSpan.FromHours(48))
{
return configData.ApiToken.Value;
}
var pairs = new Dictionary<string, string> {
{ "username", configData.Username.Value },
{ "password", configData.Password.Value }
};
var content = new FormUrlEncodedContent(pairs);
var response = await client.PostAsync(AuthUrl, content);
var responseContent = await response.Content.ReadAsStringAsync();
var jsonResponse = JObject.Parse(responseContent);
if (jsonResponse["error"] != null)
{
throw new ApplicationException((string)jsonResponse["error"]);
}
configData.ApiToken.Value = (string)jsonResponse["token"];
configData.LastTokenFetchDateTime = DateTime.Now;
return configData.ApiToken.Value;
}
public async Task<IndexerConfigurationStatus> ApplyConfiguration(JToken configJson)
{
configData.LoadValuesFromJson(configJson);
Exception tokenFetchEx = null;
try
{
await GetAuthToken(true);
}
catch (Exception ex)
{
tokenFetchEx = new ExceptionWithConfigData(ex.Message, configData);
}
await ConfigureIfOK(string.Empty, tokenFetchEx == null, () =>
{
throw tokenFetchEx;
});
return IndexerConfigurationStatus.RequiresTesting;
}
// Override to load legacy config format
public override void LoadFromSavedConfiguration(JToken jsonConfig)
{
if (jsonConfig is JObject)
{
configData.ApiToken.Value = jsonConfig.Value<string>("token"); ;
configData.Username.Value = jsonConfig.Value<string>("username");
configData.Password.Value = jsonConfig.Value<string>("password");
SaveConfig();
IsConfigured = true;
return;
}
base.LoadFromSavedConfiguration(jsonConfig);
}
public async Task<IEnumerable<ReleaseInfo>> PerformQuery(TorznabQuery query)
{
var releases = new List<ReleaseInfo>();
var searchTerm = string.IsNullOrEmpty(query.SanitizedSearchTerm) ? "%20" : query.SanitizedSearchTerm;
var searchString = searchTerm + " " + query.GetEpisodeSearchString();
var episodeSearchUrl = string.Format(SearchUrl, HttpUtility.UrlEncode(searchString));
var message = new HttpRequestMessage();
message.Method = HttpMethod.Get;
message.RequestUri = new Uri(episodeSearchUrl);
message.Headers.TryAddWithoutValidation("Authorization", await GetAuthToken());
var response = await client.SendAsync(message);
var results = await response.Content.ReadAsStringAsync();
var jsonResult = JObject.Parse(results);
try
{
var items = (JArray)jsonResult["torrents"];
foreach (var item in items)
{
var release = new ReleaseInfo();
release.MinimumRatio = 1;
release.MinimumSeedTime = 172800;
var torrentId = (string)item["id"];
release.Link = new Uri(string.Format(DownloadUrl, torrentId));
release.Title = (string)item["name"];
release.Description = release.Title;
release.Comments = new Uri(string.Format(CommentsUrl, (string)item["rewritename"]));
release.Guid = release.Comments;
var dateUtc = DateTime.ParseExact((string)item["added"], "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture);
release.PublishDate = DateTime.SpecifyKind(dateUtc, DateTimeKind.Utc).ToLocalTime();
release.Seeders = ParseUtil.CoerceInt((string)item["seeders"]);
release.Peers = ParseUtil.CoerceInt((string)item["leechers"]) + release.Seeders;
release.Size = ParseUtil.CoerceLong((string)item["size"]);
release.Category = MapTrackerCatToNewznab((string)item["categoryname"]);
releases.Add(release);
}
}
catch (Exception ex)
{
OnParseError(results, ex);
}
return releases;
}
public override async Task<byte[]> Download(Uri link)
{
var message = new HttpRequestMessage();
message.Method = HttpMethod.Get;
message.RequestUri = link;
message.Headers.TryAddWithoutValidation("Authorization", await GetAuthToken());
var response = await client.SendAsync(message);
return await response.Content.ReadAsByteArrayAsync();
}
}
}

View File

@@ -1,161 +0,0 @@
using CsQuery;
using Jackett.Models;
using Jackett.Services;
using Jackett.Utils;
using Jackett.Utils.Clients;
using Newtonsoft.Json.Linq;
using NLog;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Web;
using Jackett.Models.IndexerConfig;
namespace Jackett.Indexers
{
public class ThePirateBay : BaseIndexer, IIndexer
{
readonly static string defaultSiteLink = "https://thepiratebay.mn/";
private Uri BaseUri
{
get { return new Uri(configData.Url.Value); }
set { configData.Url.Value = value.ToString(); }
}
private string SearchUrl { get { return BaseUri + "search/{0}/0/99/208,205"; } }
private string RecentUrl { get { return BaseUri + "recent"; } }
new ConfigurationDataUrl configData
{
get { return (ConfigurationDataUrl)base.configData; }
set { base.configData = value; }
}
public ThePirateBay(IIndexerManagerService i, Logger l, IWebClient wc, IProtectionService ps)
: base(name: "The Pirate Bay",
description: "The worlds largest bittorrent indexer",
link: defaultSiteLink,
caps: TorznabUtil.CreateDefaultTorznabTVCaps(),
manager: i,
client: wc,
logger: l,
p: ps,
configData: new ConfigurationDataUrl(defaultSiteLink))
{
}
public async Task<IndexerConfigurationStatus> ApplyConfiguration(JToken configJson)
{
configData.LoadValuesFromJson(configJson);
var releases = await PerformQuery(new TorznabQuery());
await ConfigureIfOK(string.Empty, releases.Count() > 0, () =>
{
throw new Exception("Could not find releases from this URL");
});
return IndexerConfigurationStatus.Completed;
}
// Override to load legacy config format
public override void LoadFromSavedConfiguration(JToken jsonConfig)
{
if (jsonConfig is JObject)
{
BaseUri = new Uri(jsonConfig.Value<string>("base_url"));
SaveConfig();
IsConfigured = true;
return;
}
base.LoadFromSavedConfiguration(jsonConfig);
}
public async Task<IEnumerable<ReleaseInfo>> PerformQuery(TorznabQuery query)
{
var releases = new List<ReleaseInfo>();
var queryStr = HttpUtility.UrlEncode(query.GetQueryString());
var episodeSearchUrl = string.IsNullOrWhiteSpace(queryStr) ? RecentUrl : string.Format(SearchUrl, queryStr);
var response = await RequestStringWithCookiesAndRetry(episodeSearchUrl, string.Empty);
try
{
CQ dom = response.Content;
var rows = dom["#searchResult > tbody > tr"];
foreach (var row in rows)
{
if (row.ChildElements.Count() < 2)
continue;
var release = new ReleaseInfo();
CQ qRow = row.Cq();
CQ qLink = qRow.Find(".detName > .detLink").First();
release.MinimumRatio = 1;
release.MinimumSeedTime = 172800;
release.Title = qLink.Text().Trim();
release.Description = release.Title;
release.Comments = new Uri(BaseUri + qLink.Attr("href").TrimStart('/'));
release.Guid = release.Comments;
var downloadCol = row.ChildElements.ElementAt(1).Cq().Children("a");
release.MagnetUri = new Uri(downloadCol.Attr("href"));
release.InfoHash = release.MagnetUri.ToString().Split(':')[3].Split('&')[0];
var descString = qRow.Find(".detDesc").Text().Trim();
var descParts = descString.Split(',');
var timeString = descParts[0].Split(' ')[1];
if (timeString.Contains(" ago"))
{
release.PublishDate = (DateTime.Now - TimeSpan.FromMinutes(ParseUtil.CoerceInt(timeString.Split(' ')[0])));
}
else if (timeString.Contains("Today"))
{
release.PublishDate = (DateTime.UtcNow - TimeSpan.FromHours(2) - TimeSpan.Parse(timeString.Split(' ')[1])).ToLocalTime();
}
else if (timeString.Contains("Y-day"))
{
release.PublishDate = (DateTime.UtcNow - TimeSpan.FromHours(26) - TimeSpan.Parse(timeString.Split(' ')[1])).ToLocalTime();
}
else if (timeString.Contains(':'))
{
var utc = DateTime.ParseExact(timeString, "MM-dd HH:mm", CultureInfo.InvariantCulture) - TimeSpan.FromHours(2);
release.PublishDate = DateTime.SpecifyKind(utc, DateTimeKind.Utc).ToLocalTime();
}
else
{
var utc = DateTime.ParseExact(timeString, "MM-dd yyyy", CultureInfo.InvariantCulture) - TimeSpan.FromHours(2);
release.PublishDate = DateTime.SpecifyKind(utc, DateTimeKind.Utc).ToLocalTime();
}
release.Size = ReleaseInfo.GetBytes(descParts[1]);
release.Seeders = ParseUtil.CoerceInt(row.ChildElements.ElementAt(2).Cq().Text());
release.Peers = ParseUtil.CoerceInt(row.ChildElements.ElementAt(3).Cq().Text()) + release.Seeders;
releases.Add(release);
}
}
catch (Exception ex)
{
OnParseError(response.Content, ex);
}
return releases.ToArray();
}
public override Task<byte[]> Download(Uri link)
{
throw new NotImplementedException();
}
}
}

View File

@@ -1,212 +0,0 @@
using Jackett.Models;
using Jackett.Services;
using Jackett.Utils;
using Jackett.Utils.Clients;
using Newtonsoft.Json.Linq;
using NLog;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using System.Web;
using System.Windows.Forms;
using System.Xml;
using System.Linq;
using Jackett.Models.IndexerConfig;
namespace Jackett.Indexers
{
public class Torrentz : BaseIndexer, IIndexer
{
readonly static string defaultSiteLink = "https://torrentz.eu/";
private Uri BaseUri
{
get { return new Uri(configData.Url.Value); }
set { configData.Url.Value = value.ToString(); }
}
private string SearchUrl { get { return BaseUri + "feed_verifiedP?f={0}"; } }
new ConfigurationDataUrl configData
{
get { return (ConfigurationDataUrl)base.configData; }
set { base.configData = value; }
}
public Torrentz(IIndexerManagerService i, Logger l, IWebClient wc, IProtectionService ps)
: base(name: "Torrentz",
description: "Torrentz is a meta-search engine and a Multisearch. This means we just search other search engines.",
link: defaultSiteLink,
caps: TorznabUtil.CreateDefaultTorznabTVCaps(),
manager: i,
client: wc,
logger: l,
p: ps,
configData: new ConfigurationDataUrl(defaultSiteLink))
{
}
public async Task<IndexerConfigurationStatus> ApplyConfiguration(JToken configJson)
{
configData.LoadValuesFromJson(configJson);
var releases = await PerformQuery(new TorznabQuery());
await ConfigureIfOK(string.Empty, releases.Count() > 0, () =>
{
throw new Exception("Could not find releases from this URL");
});
return IndexerConfigurationStatus.Completed;
}
// Override to load legacy config format
public override void LoadFromSavedConfiguration(JToken jsonConfig)
{
if (jsonConfig is JObject)
{
BaseUri = new Uri(jsonConfig.Value<string>("base_url"));
SaveConfig();
IsConfigured = true;
return;
}
base.LoadFromSavedConfiguration(jsonConfig);
}
public async Task<IEnumerable<ReleaseInfo>> PerformQuery(TorznabQuery query)
{
var releases = new List<ReleaseInfo>();
var searchString = query.GetQueryString();
var episodeSearchUrl = string.Format(SearchUrl, HttpUtility.UrlEncode(searchString.Trim()));
var xmlDoc = new XmlDocument();
string xml = string.Empty;
var result = await RequestStringWithCookiesAndRetry(episodeSearchUrl);
try
{
xmlDoc.LoadXml(result.Content);
ReleaseInfo release;
TorrentzHelper td;
string serie_title;
foreach (XmlNode node in xmlDoc.GetElementsByTagName("item"))
{
release = new ReleaseInfo();
release.MinimumRatio = 1;
release.MinimumSeedTime = 172800;
serie_title = node.SelectSingleNode("title").InnerText;
release.Title = serie_title;
release.Comments = new Uri(node.SelectSingleNode("link").InnerText);
int category = 0;
int.TryParse(node.SelectSingleNode("category").InnerText, out category);
release.Category = category;
release.Guid = new Uri(node.SelectSingleNode("guid").InnerText);
release.PublishDate = DateTime.Parse(node.SelectSingleNode("pubDate").InnerText, CultureInfo.InvariantCulture);
td = new TorrentzHelper(node.SelectSingleNode("description").InnerText);
release.Description = td.Description;
release.InfoHash = td.hash;
release.Size = td.Size;
release.Seeders = td.Seeders;
release.Peers = td.Peers + release.Seeders;
release.MagnetUri = TorrentzHelper.createMagnetLink(td.hash, serie_title);
releases.Add(release);
}
}
catch (Exception ex)
{
OnParseError(xml, ex);
}
return releases;
}
public override Task<byte[]> Download(Uri link)
{
throw new NotImplementedException();
}
}
public class TorrentzHelper
{
public TorrentzHelper(string description)
{
this.Description = description;
if (null == description)
{
this.Description = "";
this.Size = 0;
this.Peers = 0;
this.Seeders = 0;
this.hash = "";
}
else
FillProperties();
}
public static Uri createMagnetLink(string hash, string title)
{
string MagnetLink = "magnet:?xt=urn:btih:{0}&dn={1}&tr={2}";
string Trackers = WebUtility.UrlEncode("udp://tracker.publicbt.com:80&tr=udp://tracker.openbittorrent.com:80&tr=udp://tracker.ccc.de:80&tr=udp://tracker.istole.it:80");
title = WebUtility.UrlEncode(title);
return new Uri(string.Format(MagnetLink, hash, title, Trackers));
}
private void FillProperties()
{
string description = this.Description;
int counter = 0;
while (description.Contains(" "))
{
int nextSpace = description.IndexOf(": ") + 1;
int secondSpace;
if (counter != 0)
secondSpace = description.IndexOf(" ", nextSpace + 1);
else
secondSpace = description.IndexOf(": ", nextSpace + 2) - description.IndexOf(" ", nextSpace);
string val;
if (secondSpace == -1)
{
val = description.Substring(nextSpace).Trim();
description = string.Empty;
}
else
{
val = description.Substring(nextSpace, secondSpace - nextSpace).Trim();
description = description.Substring(secondSpace);
}
switch (counter)
{
case 0:
this.Size = ReleaseInfo.GetBytes(val);
break;
case 1:
this.Seeders = ParseUtil.CoerceInt(val.Contains(",") ? val.Remove(val.IndexOf(","), 1) : val);
break;
case 2:
this.Peers = ParseUtil.CoerceInt(val.Contains(",") ? val.Remove(val.IndexOf(","), 1) : val);
break;
case 3:
this.hash = val;
break;
}
counter++;
}
}
public string Description { get; set; }
public long Size { get; set; }
public int Seeders { get; set; }
public int Peers { get; set; }
public string hash { get; set; }
}
}

View File

@@ -190,7 +190,6 @@
<Compile Include="Indexers\BlueTigers.cs" />
<Compile Include="Indexers\EuTorrents.cs" />
<Compile Include="Indexers\Avistaz.cs" />
<Compile Include="Indexers\BakaBT.cs" />
<Compile Include="Indexers\BaseIndexer.cs" />
<Compile Include="Indexers\BB.cs" />
<Compile Include="Indexers\BeyondHD.cs" />
@@ -212,15 +211,12 @@
<Compile Include="Indexers\ImmortalSeed.cs" />
<Compile Include="Indexers\FileList.cs" />
<Compile Include="Indexers\Abstract\AvistazTracker.cs" />
<Compile Include="Indexers\AnimeTorrents.cs" />
<Compile Include="Models\IndexerConfig\Bespoke\ConfigurationDataBlueTigers.cs" />
<Compile Include="Models\IndexerConfig\ConfigurationDataBasicLoginWithFilter.cs" />
<Compile Include="Models\IndexerConfig\ConfigurationDataAPIKey.cs" />
<Compile Include="Models\ManualSearchResult.cs" />
<Compile Include="Indexers\Rarbg.cs" />
<Compile Include="Indexers\TVChaosUK.cs" />
<Compile Include="Indexers\NCore.cs" />
<Compile Include="Indexers\RuTor.cs" />
<Compile Include="Indexers\TorrentBytes.cs" />
<Compile Include="Indexers\IPTorrents.cs" />
<Compile Include="Indexers\MoreThanTV.cs" />
@@ -228,15 +224,10 @@
<Compile Include="Indexers\PrivateHD.cs" />
<Compile Include="Indexers\SceneAccess.cs" />
<Compile Include="Indexers\SceneTime.cs" />
<Compile Include="Indexers\ShowRSS.cs" />
<Compile Include="Indexers\SpeedCD.cs" />
<Compile Include="Indexers\Strike.cs" />
<Compile Include="Indexers\T411.cs" />
<Compile Include="Indexers\ThePirateBay.cs" />
<Compile Include="Indexers\TorrentDay.cs" />
<Compile Include="Indexers\TorrentLeech.cs" />
<Compile Include="Indexers\TorrentShack.cs" />
<Compile Include="Indexers\Torrentz.cs" />
<Compile Include="JackettProtectedAttribute.cs" />
<Compile Include="Models\CachedLog.cs" />
<Compile Include="Models\CachedResult.cs" />
@@ -437,15 +428,9 @@
<Content Include="Content\logos\animebytes.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\logos\animetorrents.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\logos\avistaz.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\logos\bakabt.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\logos\bb.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -500,12 +485,6 @@
<Content Include="Content\logos\privatehd.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\logos\rarbg.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\logos\rutor.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\logos\sceneaccess.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -515,15 +494,9 @@
<Content Include="Content\logos\shazbat.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\logos\showrss.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\logos\speedcd.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\logos\t411.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\logos\tehconnection.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -584,18 +557,9 @@
<Content Include="Content\logos\morethantv.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\logos\strike.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\logos\thepiratebay.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\logos\torrentleech.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\logos\torrentz.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\logos\tvchaosuk.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>