Compare commits

...

23 Commits

Author SHA1 Message Date
Joel Gillman
cac185f747 Update README.md for Linux/OSX installation (#424) 2016-08-05 21:58:56 +10:00
Thomas Gillen
6d0d502bd3 Add music categories to AnimeBytes indexer (#418) 2016-08-05 21:58:29 +10:00
Superpiffer
ccde6fb53b TorrentLeech: Fix login (#412) (#414)
* Fix login #412

* Update TorrentLeech.cs
2016-08-05 21:57:43 +10:00
flightlevel
2afce9f2d9 BeyondHD; Fix Recaptcha (#409)
BeyondHD; Fix Recaptcha
2016-07-27 14:50:53 +10:00
flightlevel
2647457706 SpeedCd: Update URL (#408)
SpeedCd: Update URL
2016-07-27 14:14:57 +10:00
kobik
ac5e69a3b2 New indexer - Hebits.net (#406)
* Added Hebits.net as an indexer - a private Israel tracker

* Added new indexer Hebits to the readme file

* Deleted debug messages leftovers
2016-07-27 14:08:06 +10:00
d2dyno
45fb2a27c3 Updated BeyondHD URL (#390)
Updated BeyondHD to new URL.
2016-07-04 21:58:33 +10:00
Umur Kontacı
fb3d7ae81b Fix builds on case-sensitive filesystems (#377) 2016-06-26 20:32:48 +10:00
Codehhh
9b62e8af71 Add PTP as a new Indexer (#373)
* Added PassThePopcorn Indexer

* Fixed PTP Indexer
2016-06-23 20:34:19 +10:00
flightlevel
3f292b5e47 Freshon: Fix Urls (#374)
Freshon: Fix Urls
2016-06-23 20:28:08 +10:00
Chris Mattera
bd2abddb09 Modified to use new download URL format (#369) 2016-06-21 19:28:55 +10:00
Joel Gillman
5135748d1d Update "issues page" link in README (#358)
The "issues page" link in the Contributing section was pointing to the old repo! I just updated.
2016-06-08 08:53:38 +02:00
flightlevel
0fc3d224ab Allow Custom Data Folder (#355)
Allow Custom Data Folder
2016-05-28 19:40:55 +10:00
flightlevel
ac07cc34cd SpeedCD: Fix Login (#354)
SpeedCD: Fix Login
2016-05-28 19:40:39 +10:00
flightlevel
3730e05f20 TorrentDay: Add Audio (#353)
TorrentDay: Add Audio
2016-05-28 19:40:16 +10:00
flightlevel
2644fd813e Bluetigers fix SSL issue (#346) 2016-05-18 20:33:37 +10:00
flightlevel
ece16d1075 TransmitheNet: Fix Titles with extension (#343) 2016-05-17 23:25:26 +10:00
Fredrik Löwenhamn
3b13fa84a4 Fixed saving alphaRatio json (#342) 2016-05-17 23:04:15 +10:00
flightlevel
cda5ea3207 Update README.md 2016-05-14 22:44:49 +10:00
flightlevel
0746616b43 Revert "SSL Fix by default, Now use TLS (1.2, 1.1, 1) by default" (#339) 2016-05-14 22:42:16 +10:00
JigSaw
28199ab4be SSL Fix by default, Added support of TLS 1.1 & 1.2 (#337)
* SSL Fix by default, Now use TLS (1.2, 1.1, 1) by default
* Workaround to use TLS 1.2 & 1.1 on Mono < 4.3
2016-05-14 00:46:56 +02:00
JigSaw
b29c578adb Fixed FADN Provider (#336)
New Search Engine Template
2016-05-13 23:41:10 +02:00
smarshallsay
b42f2a0972 Deal with carriage return in date string (#325) 2016-04-30 21:48:52 +10:00
22 changed files with 550 additions and 89 deletions

View File

@@ -34,10 +34,12 @@ Developer note: The software implements the [Torznab](https://github.com/Sonarr/
* Fuzer
* HD-Space
* HD-Torrents
* Hebits
* Hounddawgs
* ILoveTorrents
* Immortalseed
* IPTorrents
* PassThePopcorn
* MoreThanTV
* MyAnonamouse
* NCore
@@ -56,6 +58,7 @@ Developer note: The software implements the [Torznab](https://github.com/Sonarr/
* TorrentDay
* TorrentLeech
* TorrentShack
* TransmitheNet
* TV Chaos UK
* World-In-HD
* XSpeeds
@@ -73,7 +76,7 @@ Jackett can also be run from the command line using JackettConsole.exe if you wo
* Debian/Ubunutu: apt-get install libcurl-dev
* Redhat/Fedora: yum install libcurl-devel
* For other distros see the [Curl docs](http://curl.haxx.se/dlwiz/?type=devel).
3. Download and extract the latest ```.tar.gz``` release from the [releases page](https://github.com/Jackett/Jackett/releases) and run Jackett using mono with the command "mono JackettConsole.exe".
3. Download and extract the latest `Jackett.Binaries.Mono.tar.gz` release from the [releases page](https://github.com/Jackett/Jackett/releases) and run Jackett using mono with the command `mono JackettConsole.exe`.
Detailed instructions for [Ubuntu 14.x](http://www.htpcguides.com/install-jackett-on-ubuntu-14-x-for-custom-torrents-in-sonarr/) and [Ubuntu 15.x](http://www.htpcguides.com/install-jackett-ubuntu-15-x-for-custom-torrents-in-sonarr/)
@@ -98,7 +101,7 @@ You can get additional logging with the switches "-t -l". Please post logs if y
Please supply as much information about the problem you are experiencing as possible. Your issue has a much greater chance of being resolved if logs are supplied so that we can see what is going on. Creating an issue with '### isn't working' doesn't help anyone to fix the problem.
### 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. We currently only support private trackers.
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/Jackett/Jackett/issues). It is recommended to use Visual studio 2015 when making code changes in this project. We currently only support private trackers.
### Screenshots

View File

@@ -60,6 +60,9 @@ namespace Jackett.Console
[Option('n', "IgnoreSslErrors", HelpText = "[true/false] Linux Libcurl - Ignores invalid SSL certificates")]
public bool? IgnoreSslErrors { get; set; }
[Option('d', "DataFolder", HelpText = "Specify the location of the data folder (Must be admin on Windows) eg. --DataFolder=\"D:\\Your Data\\Jackett\\\"")]
public string DataFolder { get; set; }
[ParserState]
public IParserState LastParserState { get; set; }
}

View File

@@ -99,6 +99,13 @@ namespace JackettConsole
Engine.Logger.Info("Curl will ignore SSL certificate errors.");
}
// Choose Data Folder
if (!string.IsNullOrWhiteSpace(options.DataFolder))
{
Startup.CustomDataFolder = options.DataFolder.Replace("\"", string.Empty).Replace("'", string.Empty).Replace(@"\\", @"\");
Engine.Logger.Info("Jackett Data will be stored in: " + Startup.CustomDataFolder);
}
/* ====== Actions ===== */
// Install service

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

View File

@@ -56,13 +56,18 @@ namespace Jackett.Indexers
AddCategoryMapping(23, TorznabCatType.Audio);
}
new ConfigurationDataBasicLogin configData
{
get { return (ConfigurationDataBasicLogin)base.configData; }
set { base.configData = value; }
}
public async Task<IndexerConfigurationStatus> ApplyConfiguration(JToken configJson)
{
var incomingConfig = new ConfigurationDataBasicLogin();
incomingConfig.LoadValuesFromJson(configJson);
configData.LoadValuesFromJson(configJson);
var pairs = new Dictionary<string, string> {
{ "username", incomingConfig.Username.Value },
{ "password", incomingConfig.Password.Value },
{ "username", configData.Username.Value },
{ "password", configData.Password.Value },
{ "login", "Login" },
{ "keeplogged", "1" }
};
@@ -74,7 +79,7 @@ namespace Jackett.Indexers
CQ dom = response.Content;
dom["#loginform > table"].Remove();
var errorMessage = dom["#loginform"].Text().Trim().Replace("\n\t", " ");
throw new ExceptionWithConfigData(errorMessage, (ConfigurationData)incomingConfig);
throw new ExceptionWithConfigData(errorMessage, configData);
});
return IndexerConfigurationStatus.RequiresTesting;
}

View File

@@ -24,8 +24,15 @@ namespace Jackett.Indexers
{
public class AnimeBytes : BaseIndexer, IIndexer
{
enum SearchType
{
Video,
Audio
}
private string LoginUrl { get { return SiteLink + "user/login"; } }
private string SearchUrl { get { return SiteLink + "torrents.php?"; } }
private string MusicSearchUrl { get { return SiteLink + "torrents2.php?"; } }
public bool AllowRaws { get { return configData.IncludeRaw.Value; } }
public bool InsertSeason { get { return configData.InsertSeason!=null && configData.InsertSeason.Value; } }
@@ -46,7 +53,10 @@ namespace Jackett.Indexers
TorznabCatType.BooksComics,
TorznabCatType.ConsolePSP,
TorznabCatType.ConsoleOther,
TorznabCatType.PCGames),
TorznabCatType.PCGames,
TorznabCatType.AudioMP3,
TorznabCatType.AudioLossless,
TorznabCatType.AudioOther),
logger: l,
p: ps,
configData: new ConfigurationDataAnimeBytes())
@@ -139,8 +149,16 @@ namespace Jackett.Indexers
{
// The result list
var releases = new List<ReleaseInfo>();
if (ContainsMusicCategories(query.Categories))
{
foreach (var result in await GetResults(SearchType.Audio, query.SanitizedSearchTerm))
{
releases.Add(result);
}
}
foreach (var result in await GetResults(StripEpisodeNumber(query.SanitizedSearchTerm)))
foreach (var result in await GetResults(SearchType.Video, StripEpisodeNumber(query.SanitizedSearchTerm)))
{
releases.Add(result);
}
@@ -148,31 +166,45 @@ namespace Jackett.Indexers
return releases.ToArray();
}
public async Task<IEnumerable<ReleaseInfo>> GetResults(string searchTerm)
private bool ContainsMusicCategories(int[] categories)
{
var music = new[]
{
TorznabCatType.Audio.ID,
TorznabCatType.AudioMP3.ID,
TorznabCatType.AudioLossless.ID,
TorznabCatType.AudioOther.ID,
TorznabCatType.AudioForeign.ID
};
return categories.Length == 0 || music.Any(categories.Contains);
}
private async Task<IEnumerable<ReleaseInfo>> GetResults(SearchType searchType, string searchTerm)
{
var cleanSearchTerm = HttpUtility.UrlEncode(searchTerm);
// The result list
var releases = new List<ReleaseInfo>();
var queryUrl = searchType == SearchType.Video ? SearchUrl : MusicSearchUrl;
// Only include the query bit if its required as hopefully the site caches the non query page
if (!string.IsNullOrWhiteSpace(searchTerm))
{
queryUrl += string.Format("searchstr={0}&action=advanced&search_type=title&year=&year2=&tags=&tags_type=0&sort=time_added&way=desc&hentai=2&releasegroup=&epcount=&epcount2=&artbooktitle=", cleanSearchTerm);
}
// Check cache first so we don't query the server for each episode when searching for each episode in a series.
lock (cache)
{
// Remove old cache items
CleanCache();
var cachedResult = cache.Where(i => i.Query == searchTerm).FirstOrDefault();
var cachedResult = cache.Where(i => i.Query == queryUrl).FirstOrDefault();
if (cachedResult != null)
return cachedResult.Results.Select(s => (ReleaseInfo)s.Clone()).ToArray();
}
var queryUrl = SearchUrl;
// Only include the query bit if its required as hopefully the site caches the non query page
if (!string.IsNullOrWhiteSpace(searchTerm))
{
queryUrl += string.Format("searchstr={0}&action=advanced&search_type=title&year=&year2=&tags=&tags_type=0&sort=time_added&way=desc&hentai=2&releasegroup=&epcount=&epcount2=&artbooktitle=", cleanSearchTerm);
}
// Get the content from the tracker
var response = await RequestStringWithCookiesAndRetry(queryUrl);
CQ dom = response.Content;
@@ -191,7 +223,11 @@ namespace Jackett.Indexers
var seriesCq = series.Cq();
var synonyms = new List<string>();
var mainTitle = seriesCq.Find(".group_title strong a").First().Text().Trim();
string mainTitle;
if (searchType == SearchType.Video)
mainTitle = seriesCq.Find(".group_title strong a").First().Text().Trim();
else
mainTitle = seriesCq.Find(".group_title strong").Text().Trim();
var yearStr = seriesCq.Find(".group_title strong").First().Text().Trim().Replace("]", "").Trim();
int yearIndex = yearStr.LastIndexOf("[");
@@ -282,33 +318,52 @@ namespace Jackett.Indexers
release.Guid = new Uri(SiteLink + infoLink.Attributes.GetAttribute("href") + "&nh=" + StringUtil.Hash(title)); // Sonarr should dedupe on this url - allow a url per name.
release.Link = new Uri(downloadLink.Attributes.GetAttribute("href"), UriKind.Relative);
var category = seriesCq.Find("a[title=\"View Torrent\"]").Text().Trim();
if (category == "TV Series")
release.Category = TorznabCatType.TVAnime.ID;
// Ignore these categories as they'll cause hell with the matcher
// TV Special, OVA, ONA, DVD Special, BD Special
if (category == "Movie")
release.Category = TorznabCatType.Movies.ID;
if (category == "Manga" || category == "Oneshot" || category == "Anthology" || category == "Manhwa" || category == "Manhua" || category == "Light Novel")
release.Category = TorznabCatType.BooksComics.ID;
if (category == "Novel" || category == "Artbook")
release.Category = TorznabCatType.BooksComics.ID;
if (category == "Game" || category == "Visual Novel")
string category = null;
if (searchType == SearchType.Video)
{
var description = rowCq.Find(".torrent_properties a:eq(1)").Text();
if (description.Contains(" PSP "))
release.Category = TorznabCatType.ConsolePSP.ID;
if (description.Contains("PSX"))
release.Category = TorznabCatType.ConsoleOther.ID;
if (description.Contains(" NES "))
release.Category = TorznabCatType.ConsoleOther.ID;
if (description.Contains(" PC "))
release.Category = TorznabCatType.PCGames.ID;
category = seriesCq.Find("a[title=\"View Torrent\"]").Text().Trim();
if (category == "TV Series")
release.Category = TorznabCatType.TVAnime.ID;
// Ignore these categories as they'll cause hell with the matcher
// TV Special, OVA, ONA, DVD Special, BD Special
if (category == "Movie")
release.Category = TorznabCatType.Movies.ID;
if (category == "Manga" || category == "Oneshot" || category == "Anthology" || category == "Manhwa" || category == "Manhua" || category == "Light Novel")
release.Category = TorznabCatType.BooksComics.ID;
if (category == "Novel" || category == "Artbook")
release.Category = TorznabCatType.BooksComics.ID;
if (category == "Game" || category == "Visual Novel")
{
var description = rowCq.Find(".torrent_properties a:eq(1)").Text();
if (description.Contains(" PSP "))
release.Category = TorznabCatType.ConsolePSP.ID;
if (description.Contains("PSX"))
release.Category = TorznabCatType.ConsoleOther.ID;
if (description.Contains(" NES "))
release.Category = TorznabCatType.ConsoleOther.ID;
if (description.Contains(" PC "))
release.Category = TorznabCatType.PCGames.ID;
}
}
if (searchType == SearchType.Audio)
{
category = seriesCq.Find(".group_img .cat a").Text();
if (category == "Single" || category == "Album" || category == "Compilation" || category == "Soundtrack" || category == "Remix CD")
{
var description = rowCq.Find(".torrent_properties a:eq(1)").Text();
if (description.Contains(" Lossless "))
release.Category = TorznabCatType.AudioLossless.ID;
else if (description.Contains("MP3"))
release.Category = TorznabCatType.AudioMP3.ID;
else
release.Category = TorznabCatType.AudioOther.ID;
}
}
@@ -386,7 +441,7 @@ namespace Jackett.Indexers
// Add to the cache
lock (cache)
{
cache.Add(new CachedQueryResult(searchTerm, releases));
cache.Add(new CachedQueryResult(queryUrl, releases));
}
return releases.Select(s => (ReleaseInfo)s.Clone());

View File

@@ -30,7 +30,7 @@ namespace Jackett.Indexers
public BeyondHD(IIndexerManagerService i, Logger l, IWebClient w, IProtectionService ps)
: base(name: "BeyondHD",
description: "Without BeyondHD, your HDTV is just a TV",
link: "https://beyondhd.me/",
link: "https://beyond-hd.me/",
caps: new TorznabCapabilities(),
manager: i,
client: w,
@@ -79,7 +79,7 @@ namespace Jackett.Indexers
public override async Task<ConfigurationData> GetConfigurationForSetup()
{
var loginPage = await RequestStringWithCookies(LoginUrl, string.Empty);
string recaptchaSiteKey = new Regex(@"loginwidget', \{[\s]{4,30}'sitekey' : '([0-9A-Za-z]{5,60})',[\s]{4,30}'theme'").Match(loginPage.Content).Groups[1].ToString().Trim();
string recaptchaSiteKey = new Regex(@"loginwidget', \{[\s]{4,30}'sitekey' : '([0-9A-Za-z-]{5,60})',[\s]{4,30}'theme'").Match(loginPage.Content).Groups[1].ToString().Trim();
var result = new ConfigurationDataRecaptchaLogin();
result.CookieHeader.Value = loginPage.Cookies;
result.Captcha.SiteKey = recaptchaSiteKey;

View File

@@ -23,7 +23,7 @@ namespace Jackett.Indexers
{
private string LoginUrl { get { return SiteLink + "takelogin.php"; } }
private string SearchUrl { get { return SiteLink + "torrents.php?"; } }
private string DownloadUrl { get { return SiteLink + "download.php?/{0}/dl.torrent"; } }
private string DownloadUrl { get { return SiteLink + "download.php?id={0}"; } }
new ConfigurationDataBasicLogin configData
{

View File

@@ -392,16 +392,8 @@ namespace Jackett.Indexers
var id = ParseUtil.CoerceInt(Regex.Match(tRow.Find("td:eq(1) > div:first > a").Attr("name"), @"\d+").Value);
Output("ID: " + id);
// Check if torrent is not nuked by tracker or rulez, can't download it
if (tRow.Find("td:eq(2) > a").Length == 0)
{
// Next item
Output("Torrent is nuked, we can't download it, going to next torrent...");
continue;
}
// Release Name
var name = tRow.Find("td:eq(2) > a").Attr("title").Substring(24).Trim();
// Release Name -- Can be truncated ... Need FIX on tracker's side !
var name = tRow.Find("td:eq(1) > div > a:eq(2)").Text().Trim();
Output("Release: " + name);
// Category
@@ -410,35 +402,31 @@ namespace Jackett.Indexers
Output("Category: " + MapTrackerCatToNewznab(categoryId.ToString()) + " (" + categoryId + " - " + categoryName + ")");
// Seeders
var seeders = ParseUtil.CoerceInt(Regex.Match(tRow.Find("td:eq(5) > div > font").Select(s => Regex.Replace(s.ToString(), "<.*?>", string.Empty)).ToString(), @"\d+").Value);
var seeders = ParseUtil.CoerceInt(Regex.Match(tRow.Find("td:eq(4) > div > font > a").Text(), @"\d+").Value);
Output("Seeders: " + seeders);
// Leechers
var leechers = ParseUtil.CoerceInt(Regex.Match(tRow.Find("td:eq(6) > div > font").Text(), @"\d+").Value);
var leechers = ParseUtil.CoerceInt(Regex.Match(tRow.Find("td:eq(5) > div > font").Text(), @"\d+").Value);
Output("Leechers: " + leechers);
// Completed
var completed = ParseUtil.CoerceInt(Regex.Match(tRow.Find("td:eq(4)").Text(), @"\d+").Value);
Output("Completed: " + completed);
// Files
var files = 1;
if (tRow.Find("td:eq(3) > a").Length == 1)
{
files = ParseUtil.CoerceInt(Regex.Match(tRow.Find("td:eq(3) > a").Text(), @"\d+").Value);
}
var files = ParseUtil.CoerceInt(Regex.Match(tRow.Find("td:eq(2)").Text(), @"\d+").Value);
Output("Files: " + files);
// Comments
var comments = ParseUtil.CoerceInt(Regex.Match(tRow.Find("td:eq(3)").Text(), @"\d+").Value);
Output("Comments: " + files);
// Health
var percent = ParseUtil.CoerceInt(Regex.Match(tRow.Find("td:eq(7) > img").Attr("src"), @"\d+").Value) * 10;
var percent = ParseUtil.CoerceInt(Regex.Match(tRow.Find("td:eq(6) > img").Attr("src"), @"\d+").Value) * 10;
Output("Health: " + percent + "%");
// Size
var humanSize = tRow.Find("td:eq(8)").Text().ToLowerInvariant();
var humanSize = tRow.Find("td:eq(7)").Text().ToLowerInvariant();
var size = ReleaseInfo.GetBytes(humanSize);
Output("Size: " + humanSize + " (" + size + " bytes)");
// Date & IMDB & Genre
// Date & Genre
var infosData = tRow.Find("td:eq(1) > div:last").Text();
var infosList = Regex.Split(infosData, "\\|").ToList();
var infosTorrent = infosList.Select(s => s.Split(new[] { ':' }, 2)[1].Trim()).ToList();

View File

@@ -105,9 +105,9 @@ namespace Jackett.Indexers
release.MinimumSeedTime = 172800;
release.Title = qLink.Attr("title");
release.Description = release.Title;
release.Guid = new Uri(SiteLink + qLink.Attr("href"));
release.Guid = new Uri(SiteLink + qLink.Attr("href").TrimStart('/'));
release.Comments = release.Guid;
release.Link = new Uri(SiteLink + qRow.Find("td.table_links > a").First().Attr("href"));
release.Link = new Uri(SiteLink + qRow.Find("td.table_links > a").First().Attr("href").TrimStart('/'));
release.Category = TvCategoryParser.ParseTvShowQuality(release.Title);
release.Seeders = ParseUtil.CoerceInt(qRow.Find("td.table_seeders").Text().Trim());

View File

@@ -0,0 +1,144 @@
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.Threading.Tasks;
using System.Web;
using Jackett.Models.IndexerConfig;
using System.Text.RegularExpressions;
namespace Jackett.Indexers
{
public class Hebits : BaseIndexer, IIndexer
{
private string LoginUrl { get { return SiteLink + "login.php"; } }
private string LoginPostUrl { get { return SiteLink + "takeloginAjax.php"; } }
private string SearchUrl { get { return SiteLink + "browse.php?sort=4&type=desc"; } }
new ConfigurationDataBasicLogin configData
{
get { return (ConfigurationDataBasicLogin)base.configData; }
set { base.configData = value; }
}
public Hebits(IIndexerManagerService i, Logger l, IWebClient wc, IProtectionService ps)
: base(name: "Hebits",
description: "The Israeli Tracker",
link: "https://hebits.net/",
caps: TorznabUtil.CreateDefaultTorznabTVCaps(),
manager: i,
client: wc,
logger: l,
p: ps,
downloadBase: "https://hebits.net/",
configData: new ConfigurationDataBasicLogin())
{
AddCategoryMapping(19, TorznabCatType.MoviesSD);
AddCategoryMapping(25, TorznabCatType.MoviesOther); // Israeli Content
AddCategoryMapping(20, TorznabCatType.MoviesDVD);
AddCategoryMapping(36, TorznabCatType.MoviesBluRay);
AddCategoryMapping(27, TorznabCatType.MoviesHD);
AddCategoryMapping(7, TorznabCatType.TVSD); // Israeli SDTV
AddCategoryMapping(24, TorznabCatType.TVSD); // English SDTV
AddCategoryMapping(1, TorznabCatType.TVHD); // Israel HDTV
AddCategoryMapping(37, TorznabCatType.TVHD); // Israel HDTV
}
public async Task<IndexerConfigurationStatus> ApplyConfiguration(JToken configJson)
{
configData.LoadValuesFromJson(configJson);
var pairs = new Dictionary<string, string> {
{ "username", configData.Username.Value },
{ "password", configData.Password.Value }
};
// Get inital cookies
CookieHeader = string.Empty;
var result = await RequestLoginAndFollowRedirect(LoginPostUrl, pairs, CookieHeader, true, null, SiteLink);
await ConfigureIfOK(result.Cookies, result.Content != null && result.Content.Contains("OK"), () =>
{
CQ dom = result.Content;
var messageEl = dom["#errorMsg"].Last();
var errorMessage = messageEl.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;
if (!string.IsNullOrWhiteSpace(searchString))
{
searchUrl += "&search=" + HttpUtility.UrlEncode(searchString);
}
string.Format(SearchUrl, HttpUtility.UrlEncode(searchString));
var cats = MapTorznabCapsToTrackers(query);
if (cats.Count > 0)
{
foreach (var cat in cats)
{
searchUrl += "&c" + cat + "=1";
}
}
var results = await RequestStringWithCookiesAndRetry(searchUrl);
try
{
CQ dom = results.Content;
CQ qRows = dom[".browse > div > div"];
foreach (var row in qRows)
{
var release = new ReleaseInfo();
var qRow = row.Cq();
var debug = qRow.Html();
release.MinimumRatio = 1;
release.MinimumSeedTime = 172800;
release.Title = qRow.Find(".bTitle").Text().Split('/')[1].Trim();
release.Link = new Uri(SiteLink + qRow.Find("a").Attr("href"));
release.Guid = release.Link;
var dateString = qRow.Find("div:last-child").Text().Trim();
var pattern = "\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}";
var match = Regex.Match(dateString, pattern);
if (match.Success)
{
release.PublishDate = DateTime.ParseExact(match.Value, "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture);
}
var sizeStr = qRow.Find(".bSize").Text();
release.Size = ReleaseInfo.GetBytes(sizeStr);
release.Seeders = ParseUtil.CoerceInt(qRow.Find(".bUping").Text().Trim());
release.Peers = release.Seeders + ParseUtil.CoerceInt(qRow.Find(".bDowning").Text().Trim());
releases.Add(release);
}
}
catch (Exception ex)
{
OnParseError(results.Content, ex);
}
return releases;
}
}
}

View File

@@ -0,0 +1,167 @@
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.Threading.Tasks;
using System.Web;
using Jackett.Models.IndexerConfig;
namespace Jackett.Indexers
{
public class PassThePopcorn : BaseIndexer, IIndexer
{
private string LoginUrl { get { return "https://tls.passthepopcorn.me/ajax.php?action=login"; } }
private string indexUrl { get { return "https://tls.passthepopcorn.me/ajax.php?action=login"; } }
private string SearchUrl { get { return "https://tls.passthepopcorn.me/torrents.php"; } }
private string DetailURL { get { return "https://tls.passthepopcorn.me/torrents.php?torrentid="; } }
private string AuthKey { get; set; }
new ConfigurationDataBasicLoginWithFilterAndPasskey configData
{
get { return (ConfigurationDataBasicLoginWithFilterAndPasskey)base.configData; }
set { base.configData = value; }
}
public PassThePopcorn(IIndexerManagerService i, Logger l, IWebClient c, IProtectionService ps)
: base(name: "PassThePopcorn",
description: "PassThePopcorn",
link: "https://passthepopcorn.me/",
caps: new TorznabCapabilities(),
manager: i,
client: c,
logger: l,
p: ps,
configData: new ConfigurationDataBasicLoginWithFilterAndPasskey(@"Enter filter options below to restrict search results.
Separate options with a space if using more than one option.<br>Filter options available:
<br><code>GoldenPopcorn</code><br><code>Scene</code><br><code>Checked</code>"))
{
AddCategoryMapping(1, TorznabCatType.Movies);
AddCategoryMapping(1, TorznabCatType.MoviesForeign);
AddCategoryMapping(1, TorznabCatType.MoviesOther);
AddCategoryMapping(1, TorznabCatType.MoviesSD);
AddCategoryMapping(1, TorznabCatType.MoviesHD);
AddCategoryMapping(1, TorznabCatType.Movies3D);
AddCategoryMapping(1, TorznabCatType.MoviesBluRay);
AddCategoryMapping(1, TorznabCatType.MoviesDVD);
AddCategoryMapping(1, TorznabCatType.MoviesWEBDL);
}
public async Task<IndexerConfigurationStatus> ApplyConfiguration(JToken configJson)
{
configData.LoadValuesFromJson(configJson);
await DoLogin();
return IndexerConfigurationStatus.RequiresTesting;
}
private async Task DoLogin()
{
var pairs = new Dictionary<string, string> {
{ "username", configData.Username.Value },
{ "password", configData.Password.Value },
{ "passkey", configData.Passkey.Value },
{ "keeplogged", "1" },
{ "login", "Log In!" }
};
var response = await RequestLoginAndFollowRedirect(LoginUrl, pairs, null, true, indexUrl, SiteLink);
JObject js_response = JObject.Parse(response.Content);
await ConfigureIfOK(response.Cookies, response.Content != null && (string)js_response["Result"] != "Error", () =>
{
// Landing page wil have "Result":"Error" if log in fails
string errorMessage = (string)js_response["Message"];
throw new ExceptionWithConfigData(errorMessage, configData);
});
}
public async Task<IEnumerable<ReleaseInfo>> PerformQuery(TorznabQuery query)
{
await DoLogin();
var releases = new List<ReleaseInfo>();
bool configGoldenPopcornOnly = configData.FilterString.Value.ToLowerInvariant().Contains("goldenpopcorn");
bool configSceneOnly = configData.FilterString.Value.ToLowerInvariant().Contains("scene");
bool configCheckedOnly = configData.FilterString.Value.ToLowerInvariant().Contains("checked");
string movieListSearchUrl;
if (string.IsNullOrEmpty(query.GetQueryString()))
movieListSearchUrl = string.Format("{0}?json=noredirect", SearchUrl);
else
{
if (!string.IsNullOrEmpty(query.ImdbID))
{
movieListSearchUrl = string.Format("{0}?json=noredirect&searchstr={1}", SearchUrl, HttpUtility.UrlEncode(query.ImdbID));
}
else
{
movieListSearchUrl = string.Format("{0}?json=noredirect&searchstr={1}", SearchUrl, HttpUtility.UrlEncode(query.GetQueryString()));
}
}
var results = await RequestStringWithCookiesAndRetry(movieListSearchUrl);
try
{
//Iterate over the releases for each movie
JObject js_results = JObject.Parse(results.Content);
foreach (var movie in js_results["Movies"])
{
string movie_title = (string) movie["Title"];
long movie_imdbid = long.Parse((string)movie["ImdbId"]);
string movie_groupid = (string)movie["GroupId"];
foreach (var torrent in movie["Torrents"])
{
var release = new ReleaseInfo();
release.Title = movie_title;
release.Description = release.Title;
release.Imdb = movie_imdbid;
release.Comments = new Uri(string.Format("{0}?id={1}", SearchUrl, HttpUtility.UrlEncode(movie_groupid)));
release.Guid = release.Comments;
release.Size = long.Parse((string)torrent["Size"]);
release.Seeders = int.Parse((string)torrent["Seeders"]);
release.Peers = int.Parse((string)torrent["Leechers"]);
release.PublishDate = DateTime.ParseExact((string)torrent["UploadTime"], "yyyy-MM-dd HH:mm:ss",
CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal).ToLocalTime();
release.Link = new Uri(string.Format("{0}?action=download&id={1}&authkey={2}&torrent_pass={3}",
SearchUrl, HttpUtility.UrlEncode((string)torrent["Id"]), HttpUtility.UrlEncode(AuthKey), HttpUtility.UrlEncode(configData.Passkey.Value)));
release.MinimumRatio = 1;
release.MinimumSeedTime = 345600;
release.Category = 2000;
bool golden, scene, check;
bool.TryParse((string)torrent["GoldenPopcorn"], out golden);
bool.TryParse((string)torrent["Scene"], out scene);
bool.TryParse((string)torrent["Checked"], out check);
if (configGoldenPopcornOnly && !golden)
{
continue; //Skip release if user only wants GoldenPopcorn
}
if (configSceneOnly && !scene)
{
continue; //Skip release if user only wants Scene
}
if (configCheckedOnly && !check)
{
continue; //Skip release if user only wants Checked
}
releases.Add(release);
}
}
}
catch (Exception ex)
{
OnParseError(results.Content, ex);
}
return releases;
}
}
}

View File

@@ -17,7 +17,7 @@ namespace Jackett.Indexers
{
public class SpeedCD : BaseIndexer, IIndexer
{
private string LoginUrl { get { return SiteLink + "take.login.php"; } }
private string LoginUrl { get { return SiteLink + "takeElogin.php"; } }
private string SearchUrl { get { return SiteLink + "browse.php"; } }
new ConfigurationDataBasicLogin configData
@@ -35,7 +35,8 @@ namespace Jackett.Indexers
client: wc,
logger: l,
p: ps,
configData: new ConfigurationDataBasicLogin())
configData: new ConfigurationDataBasicLogin(@"Speed.Cd have increased their security. If you are having problems please check the security tab in your Speed.Cd profile.
eg. Geo Locking, your seedbox may be in a different country to the one where you login via your web browser"))
{
AddCategoryMapping("1", TorznabCatType.MoviesOther);
AddCategoryMapping("42", TorznabCatType.Movies);
@@ -70,24 +71,39 @@ namespace Jackett.Indexers
public async Task<IndexerConfigurationStatus> ApplyConfiguration(JToken configJson)
{
configData.LoadValuesFromJson(configJson);
await DoLogin();
return IndexerConfigurationStatus.RequiresTesting;
}
private async Task DoLogin()
{
var pairs = new Dictionary<string, string> {
{ "username", configData.Username.Value },
{ "password", configData.Password.Value },
};
var result = await RequestLoginAndFollowRedirect(LoginUrl, pairs, null, true, null, SiteLink);
await ConfigureIfOK(result.Cookies, result.Content != null && result.Content.Contains("logout.php"), () =>
await ConfigureIfOK(result.Cookies, result.Content != null && result.Content.Contains("/browse.php"), () =>
{
CQ dom = result.Content;
var errorMessage = dom["h5"].First().Text().Trim();
var errorMessage = dom.Text();
throw new ExceptionWithConfigData(errorMessage, configData);
});
return IndexerConfigurationStatus.RequiresTesting;
}
public async Task<IEnumerable<ReleaseInfo>> PerformQuery(TorznabQuery query)
{
var loggedInCheck = await RequestStringWithCookies(SearchUrl);
if (!loggedInCheck.Content.Contains("/logout.php"))
{
//Cookie appears to expire after a period of time or logging in to the site via browser
await DoLogin();
}
var releases = new List<ReleaseInfo>();
NameValueCollection qParams = new NameValueCollection();

View File

@@ -61,9 +61,12 @@ namespace Jackett.Indexers
AddCategoryMapping(44, TorznabCatType.MoviesSD);
AddCategoryMapping(1, TorznabCatType.MoviesSD);
// Music foreign
// Music packs
// Music videos
// Music
AddCategoryMapping(17, TorznabCatType.AudioMP3);
AddCategoryMapping(44, TorznabCatType.AudioLossless);
AddCategoryMapping(23, TorznabCatType.AudioForeign);
AddCategoryMapping(41, TorznabCatType.AudioOther);
AddCategoryMapping(16, TorznabCatType.AudioVideo);
AddCategoryMapping(4, TorznabCatType.PCGames);
// ps3

View File

@@ -82,6 +82,12 @@ namespace Jackett.Indexers
public async Task<IndexerConfigurationStatus> ApplyConfiguration(JToken configJson)
{
configData.LoadValuesFromJson(configJson);
await DoLogin();
return IndexerConfigurationStatus.RequiresTesting;
}
private async Task DoLogin()
{
var pairs = new Dictionary<string, string> {
{ "username", configData.Username.Value },
{ "password", configData.Password.Value },
@@ -97,11 +103,17 @@ namespace Jackett.Indexers
var errorMessage = messageEl.Text().Trim();
throw new ExceptionWithConfigData(errorMessage, configData);
});
return IndexerConfigurationStatus.RequiresTesting;
}
public async Task<IEnumerable<ReleaseInfo>> PerformQuery(TorznabQuery query)
{
var loggedInCheck = await RequestStringWithCookies(SearchUrl);
if (!loggedInCheck.Content.Contains("/logout.php"))
{
//Cookie appears to expire after a period of time or logging in to the site via browser
await DoLogin();
}
var releases = new List<ReleaseInfo>();
var searchString = query.GetQueryString();
var searchUrl = SearchUrl;
@@ -151,6 +163,10 @@ namespace Jackett.Indexers
release.Link = new Uri(SiteLink + qRow.Find(".quickdownload > a").Attr("href").Substring(1));
var dateString = qRow.Find(".name")[0].InnerText.Trim().Replace(" ", string.Empty).Replace("Addedinon", string.Empty);
//Fix for issue 2016-04-30
dateString = dateString.Replace("\r", "").Replace("\n", "");
//"2015-04-25 23:38:12"
//"yyyy-MMM-dd hh:mm:ss"
release.PublishDate = DateTime.ParseExact(dateString, "yyyy-MM-ddHH:mm:ss", CultureInfo.InvariantCulture);

View File

@@ -101,7 +101,10 @@ namespace Jackett.Indexers
}
else
{
title = title.Remove(title.LastIndexOf("."));
if (title.Length > 5 && title.Substring(title.Length - 5).Contains("."))
{
title = title.Remove(title.LastIndexOf("."));
}
}
release.Title = title;

View File

@@ -186,7 +186,9 @@
<Compile Include="Controllers\TorznabController.cs" />
<Compile Include="Controllers\DownloadController.cs" />
<Compile Include="Engine.cs" />
<Compile Include="Indexers\Hebits.cs" />
<Compile Include="Indexers\MyAnonamouse.cs" />
<Compile Include="Indexers\PassThePopcorn.cs" />
<Compile Include="Indexers\Xthor.cs" />
<Compile Include="Indexers\PhxBit.cs" />
<Compile Include="Indexers\AlphaRatio.cs" />
@@ -217,7 +219,7 @@
<Compile Include="Indexers\ImmortalSeed.cs" />
<Compile Include="Indexers\FileList.cs" />
<Compile Include="Indexers\Abstract\AvistazTracker.cs" />
<Compile Include="Indexers\FrenchAdn.cs" />
<Compile Include="Indexers\FrenchADN.cs" />
<Compile Include="Indexers\TransmitheNet.cs" />
<Compile Include="Indexers\WiHD.cs" />
<Compile Include="Indexers\XSpeeds.cs" />
@@ -227,8 +229,9 @@
<Compile Include="Models\IndexerConfig\Bespoke\ConfigurationDataPhxBit.cs" />
<Compile Include="Models\IndexerConfig\Bespoke\ConfigurationDataBlueTigers.cs" />
<Compile Include="Models\IndexerConfig\Bespoke\ConfigurationDataAbnormal.cs" />
<Compile Include="Models\IndexerConfig\Bespoke\ConfigurationDataFrenchAdn.cs" />
<Compile Include="Models\IndexerConfig\Bespoke\ConfigurationDataFrenchADN.cs" />
<Compile Include="Models\IndexerConfig\Bespoke\ConfigurationDataWiHD.cs" />
<Compile Include="Models\IndexerConfig\ConfigurationDataBasicLoginWithFilterAndPasskey.cs" />
<Compile Include="Models\IndexerConfig\ConfigurationDataBasicLoginWithFilter.cs" />
<Compile Include="Models\IndexerConfig\ConfigurationDataAPIKey.cs" />
<Compile Include="Models\IndexerConfig\ConfigurationDataBasicLoginWithRSSAndDisplay.cs" />
@@ -621,6 +624,9 @@
<Content Include="Content\setup_indexer.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\logos\hebits.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Models\TorznabCatType.tt">
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>TorznabCatType.generated.cs</LastGenOutput>

View File

@@ -0,0 +1,32 @@
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Jackett.Models.IndexerConfig
{
public class ConfigurationDataBasicLoginWithFilterAndPasskey : ConfigurationData
{
public StringItem Username { get; private set; }
public StringItem Password { get; private set; }
public StringItem Passkey { get; private set; }
public DisplayItem FilterExample { get; private set; }
public StringItem FilterString { get; private set; }
public ConfigurationDataBasicLoginWithFilterAndPasskey(string FilterInstructions)
{
Username = new StringItem { Name = "Username" };
Password = new StringItem { Name = "Password" };
Passkey = new StringItem { Name = "Passkey" };
FilterExample = new DisplayItem(FilterInstructions)
{
Name = ""
};
FilterString = new StringItem { Name = "Filters (optional)" };
}
}
}

View File

@@ -213,6 +213,11 @@ namespace Jackett.Services
/// <returns></returns>
public static string GetAppDataFolderStatic()
{
if (!string.IsNullOrWhiteSpace(Startup.CustomDataFolder))
{
return Startup.CustomDataFolder;
}
if (System.Environment.OSVersion.Platform == PlatformID.Unix)
{
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Jackett");

View File

@@ -58,6 +58,12 @@ namespace Jackett
set;
}
public static string CustomDataFolder
{
get;
set;
}
public static string BasePath
{
get;

View File

@@ -46,6 +46,8 @@ namespace Jackett.Utils.Clients
private async Task<WebClientByteResult> Run(WebRequest webRequest)
{
ServicePointManager.SecurityProtocol = (SecurityProtocolType)192 | (SecurityProtocolType)768 | (SecurityProtocolType)3072;
var cookies = new CookieContainer();
if (!string.IsNullOrEmpty(webRequest.Cookies))
{