mirror of
https://github.com/Jackett/Jackett.git
synced 2025-09-14 16:04:11 +02:00
Compare commits
23 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
cac185f747 | ||
![]() |
6d0d502bd3 | ||
![]() |
ccde6fb53b | ||
![]() |
2afce9f2d9 | ||
![]() |
2647457706 | ||
![]() |
ac5e69a3b2 | ||
![]() |
45fb2a27c3 | ||
![]() |
fb3d7ae81b | ||
![]() |
9b62e8af71 | ||
![]() |
3f292b5e47 | ||
![]() |
bd2abddb09 | ||
![]() |
5135748d1d | ||
![]() |
0fc3d224ab | ||
![]() |
ac07cc34cd | ||
![]() |
3730e05f20 | ||
![]() |
2644fd813e | ||
![]() |
ece16d1075 | ||
![]() |
3b13fa84a4 | ||
![]() |
cda5ea3207 | ||
![]() |
0746616b43 | ||
![]() |
28199ab4be | ||
![]() |
b29c578adb | ||
![]() |
b42f2a0972 |
@@ -34,10 +34,12 @@ Developer note: The software implements the [Torznab](https://github.com/Sonarr/
|
|||||||
* Fuzer
|
* Fuzer
|
||||||
* HD-Space
|
* HD-Space
|
||||||
* HD-Torrents
|
* HD-Torrents
|
||||||
|
* Hebits
|
||||||
* Hounddawgs
|
* Hounddawgs
|
||||||
* ILoveTorrents
|
* ILoveTorrents
|
||||||
* Immortalseed
|
* Immortalseed
|
||||||
* IPTorrents
|
* IPTorrents
|
||||||
|
* PassThePopcorn
|
||||||
* MoreThanTV
|
* MoreThanTV
|
||||||
* MyAnonamouse
|
* MyAnonamouse
|
||||||
* NCore
|
* NCore
|
||||||
@@ -56,6 +58,7 @@ Developer note: The software implements the [Torznab](https://github.com/Sonarr/
|
|||||||
* TorrentDay
|
* TorrentDay
|
||||||
* TorrentLeech
|
* TorrentLeech
|
||||||
* TorrentShack
|
* TorrentShack
|
||||||
|
* TransmitheNet
|
||||||
* TV Chaos UK
|
* TV Chaos UK
|
||||||
* World-In-HD
|
* World-In-HD
|
||||||
* XSpeeds
|
* 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
|
* Debian/Ubunutu: apt-get install libcurl-dev
|
||||||
* Redhat/Fedora: yum install libcurl-devel
|
* Redhat/Fedora: yum install libcurl-devel
|
||||||
* For other distros see the [Curl docs](http://curl.haxx.se/dlwiz/?type=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/)
|
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.
|
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
|
### 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
|
### Screenshots
|
||||||
|
@@ -60,6 +60,9 @@ namespace Jackett.Console
|
|||||||
[Option('n', "IgnoreSslErrors", HelpText = "[true/false] Linux Libcurl - Ignores invalid SSL certificates")]
|
[Option('n', "IgnoreSslErrors", HelpText = "[true/false] Linux Libcurl - Ignores invalid SSL certificates")]
|
||||||
public bool? IgnoreSslErrors { get; set; }
|
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]
|
[ParserState]
|
||||||
public IParserState LastParserState { get; set; }
|
public IParserState LastParserState { get; set; }
|
||||||
}
|
}
|
||||||
|
@@ -99,6 +99,13 @@ namespace JackettConsole
|
|||||||
Engine.Logger.Info("Curl will ignore SSL certificate errors.");
|
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 ===== */
|
/* ====== Actions ===== */
|
||||||
|
|
||||||
// Install service
|
// Install service
|
||||||
|
BIN
src/Jackett/Content/logos/hebits.png
Normal file
BIN
src/Jackett/Content/logos/hebits.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 11 KiB |
BIN
src/Jackett/Content/logos/passthepopcorn.png
Normal file
BIN
src/Jackett/Content/logos/passthepopcorn.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 19 KiB |
@@ -56,13 +56,18 @@ namespace Jackett.Indexers
|
|||||||
AddCategoryMapping(23, TorznabCatType.Audio);
|
AddCategoryMapping(23, TorznabCatType.Audio);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
new ConfigurationDataBasicLogin configData
|
||||||
|
{
|
||||||
|
get { return (ConfigurationDataBasicLogin)base.configData; }
|
||||||
|
set { base.configData = value; }
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<IndexerConfigurationStatus> ApplyConfiguration(JToken configJson)
|
public async Task<IndexerConfigurationStatus> ApplyConfiguration(JToken configJson)
|
||||||
{
|
{
|
||||||
var incomingConfig = new ConfigurationDataBasicLogin();
|
configData.LoadValuesFromJson(configJson);
|
||||||
incomingConfig.LoadValuesFromJson(configJson);
|
|
||||||
var pairs = new Dictionary<string, string> {
|
var pairs = new Dictionary<string, string> {
|
||||||
{ "username", incomingConfig.Username.Value },
|
{ "username", configData.Username.Value },
|
||||||
{ "password", incomingConfig.Password.Value },
|
{ "password", configData.Password.Value },
|
||||||
{ "login", "Login" },
|
{ "login", "Login" },
|
||||||
{ "keeplogged", "1" }
|
{ "keeplogged", "1" }
|
||||||
};
|
};
|
||||||
@@ -74,7 +79,7 @@ namespace Jackett.Indexers
|
|||||||
CQ dom = response.Content;
|
CQ dom = response.Content;
|
||||||
dom["#loginform > table"].Remove();
|
dom["#loginform > table"].Remove();
|
||||||
var errorMessage = dom["#loginform"].Text().Trim().Replace("\n\t", " ");
|
var errorMessage = dom["#loginform"].Text().Trim().Replace("\n\t", " ");
|
||||||
throw new ExceptionWithConfigData(errorMessage, (ConfigurationData)incomingConfig);
|
throw new ExceptionWithConfigData(errorMessage, configData);
|
||||||
});
|
});
|
||||||
return IndexerConfigurationStatus.RequiresTesting;
|
return IndexerConfigurationStatus.RequiresTesting;
|
||||||
}
|
}
|
||||||
|
@@ -24,8 +24,15 @@ namespace Jackett.Indexers
|
|||||||
{
|
{
|
||||||
public class AnimeBytes : BaseIndexer, IIndexer
|
public class AnimeBytes : BaseIndexer, IIndexer
|
||||||
{
|
{
|
||||||
|
enum SearchType
|
||||||
|
{
|
||||||
|
Video,
|
||||||
|
Audio
|
||||||
|
}
|
||||||
|
|
||||||
private string LoginUrl { get { return SiteLink + "user/login"; } }
|
private string LoginUrl { get { return SiteLink + "user/login"; } }
|
||||||
private string SearchUrl { get { return SiteLink + "torrents.php?"; } }
|
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 AllowRaws { get { return configData.IncludeRaw.Value; } }
|
||||||
public bool InsertSeason { get { return configData.InsertSeason!=null && configData.InsertSeason.Value; } }
|
public bool InsertSeason { get { return configData.InsertSeason!=null && configData.InsertSeason.Value; } }
|
||||||
|
|
||||||
@@ -46,7 +53,10 @@ namespace Jackett.Indexers
|
|||||||
TorznabCatType.BooksComics,
|
TorznabCatType.BooksComics,
|
||||||
TorznabCatType.ConsolePSP,
|
TorznabCatType.ConsolePSP,
|
||||||
TorznabCatType.ConsoleOther,
|
TorznabCatType.ConsoleOther,
|
||||||
TorznabCatType.PCGames),
|
TorznabCatType.PCGames,
|
||||||
|
TorznabCatType.AudioMP3,
|
||||||
|
TorznabCatType.AudioLossless,
|
||||||
|
TorznabCatType.AudioOther),
|
||||||
logger: l,
|
logger: l,
|
||||||
p: ps,
|
p: ps,
|
||||||
configData: new ConfigurationDataAnimeBytes())
|
configData: new ConfigurationDataAnimeBytes())
|
||||||
@@ -139,8 +149,16 @@ namespace Jackett.Indexers
|
|||||||
{
|
{
|
||||||
// The result list
|
// The result list
|
||||||
var releases = new List<ReleaseInfo>();
|
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);
|
releases.Add(result);
|
||||||
}
|
}
|
||||||
@@ -148,31 +166,45 @@ namespace Jackett.Indexers
|
|||||||
return releases.ToArray();
|
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);
|
var cleanSearchTerm = HttpUtility.UrlEncode(searchTerm);
|
||||||
|
|
||||||
// The result list
|
// The result list
|
||||||
var releases = new List<ReleaseInfo>();
|
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.
|
// Check cache first so we don't query the server for each episode when searching for each episode in a series.
|
||||||
lock (cache)
|
lock (cache)
|
||||||
{
|
{
|
||||||
// Remove old cache items
|
// Remove old cache items
|
||||||
CleanCache();
|
CleanCache();
|
||||||
|
|
||||||
var cachedResult = cache.Where(i => i.Query == searchTerm).FirstOrDefault();
|
var cachedResult = cache.Where(i => i.Query == queryUrl).FirstOrDefault();
|
||||||
if (cachedResult != null)
|
if (cachedResult != null)
|
||||||
return cachedResult.Results.Select(s => (ReleaseInfo)s.Clone()).ToArray();
|
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
|
// Get the content from the tracker
|
||||||
var response = await RequestStringWithCookiesAndRetry(queryUrl);
|
var response = await RequestStringWithCookiesAndRetry(queryUrl);
|
||||||
CQ dom = response.Content;
|
CQ dom = response.Content;
|
||||||
@@ -191,7 +223,11 @@ namespace Jackett.Indexers
|
|||||||
var seriesCq = series.Cq();
|
var seriesCq = series.Cq();
|
||||||
|
|
||||||
var synonyms = new List<string>();
|
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();
|
var yearStr = seriesCq.Find(".group_title strong").First().Text().Trim().Replace("]", "").Trim();
|
||||||
int yearIndex = yearStr.LastIndexOf("[");
|
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.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);
|
release.Link = new Uri(downloadLink.Attributes.GetAttribute("href"), UriKind.Relative);
|
||||||
|
|
||||||
var category = seriesCq.Find("a[title=\"View Torrent\"]").Text().Trim();
|
string category = null;
|
||||||
if (category == "TV Series")
|
if (searchType == SearchType.Video)
|
||||||
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();
|
category = seriesCq.Find("a[title=\"View Torrent\"]").Text().Trim();
|
||||||
if (description.Contains(" PSP "))
|
if (category == "TV Series")
|
||||||
release.Category = TorznabCatType.ConsolePSP.ID;
|
release.Category = TorznabCatType.TVAnime.ID;
|
||||||
if (description.Contains("PSX"))
|
|
||||||
release.Category = TorznabCatType.ConsoleOther.ID;
|
// Ignore these categories as they'll cause hell with the matcher
|
||||||
if (description.Contains(" NES "))
|
// TV Special, OVA, ONA, DVD Special, BD Special
|
||||||
release.Category = TorznabCatType.ConsoleOther.ID;
|
|
||||||
if (description.Contains(" PC "))
|
if (category == "Movie")
|
||||||
release.Category = TorznabCatType.PCGames.ID;
|
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
|
// Add to the cache
|
||||||
lock (cache)
|
lock (cache)
|
||||||
{
|
{
|
||||||
cache.Add(new CachedQueryResult(searchTerm, releases));
|
cache.Add(new CachedQueryResult(queryUrl, releases));
|
||||||
}
|
}
|
||||||
|
|
||||||
return releases.Select(s => (ReleaseInfo)s.Clone());
|
return releases.Select(s => (ReleaseInfo)s.Clone());
|
||||||
|
@@ -30,7 +30,7 @@ namespace Jackett.Indexers
|
|||||||
public BeyondHD(IIndexerManagerService i, Logger l, IWebClient w, IProtectionService ps)
|
public BeyondHD(IIndexerManagerService i, Logger l, IWebClient w, IProtectionService ps)
|
||||||
: base(name: "BeyondHD",
|
: base(name: "BeyondHD",
|
||||||
description: "Without BeyondHD, your HDTV is just a TV",
|
description: "Without BeyondHD, your HDTV is just a TV",
|
||||||
link: "https://beyondhd.me/",
|
link: "https://beyond-hd.me/",
|
||||||
caps: new TorznabCapabilities(),
|
caps: new TorznabCapabilities(),
|
||||||
manager: i,
|
manager: i,
|
||||||
client: w,
|
client: w,
|
||||||
@@ -79,7 +79,7 @@ namespace Jackett.Indexers
|
|||||||
public override async Task<ConfigurationData> GetConfigurationForSetup()
|
public override async Task<ConfigurationData> GetConfigurationForSetup()
|
||||||
{
|
{
|
||||||
var loginPage = await RequestStringWithCookies(LoginUrl, string.Empty);
|
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();
|
var result = new ConfigurationDataRecaptchaLogin();
|
||||||
result.CookieHeader.Value = loginPage.Cookies;
|
result.CookieHeader.Value = loginPage.Cookies;
|
||||||
result.Captcha.SiteKey = recaptchaSiteKey;
|
result.Captcha.SiteKey = recaptchaSiteKey;
|
||||||
|
@@ -23,7 +23,7 @@ namespace Jackett.Indexers
|
|||||||
{
|
{
|
||||||
private string LoginUrl { get { return SiteLink + "takelogin.php"; } }
|
private string LoginUrl { get { return SiteLink + "takelogin.php"; } }
|
||||||
private string SearchUrl { get { return SiteLink + "torrents.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
|
new ConfigurationDataBasicLogin configData
|
||||||
{
|
{
|
||||||
|
@@ -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);
|
var id = ParseUtil.CoerceInt(Regex.Match(tRow.Find("td:eq(1) > div:first > a").Attr("name"), @"\d+").Value);
|
||||||
Output("ID: " + id);
|
Output("ID: " + id);
|
||||||
|
|
||||||
// Check if torrent is not nuked by tracker or rulez, can't download it
|
// Release Name -- Can be truncated ... Need FIX on tracker's side !
|
||||||
if (tRow.Find("td:eq(2) > a").Length == 0)
|
var name = tRow.Find("td:eq(1) > div > a:eq(2)").Text().Trim();
|
||||||
{
|
|
||||||
// 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();
|
|
||||||
Output("Release: " + name);
|
Output("Release: " + name);
|
||||||
|
|
||||||
// Category
|
// Category
|
||||||
@@ -410,35 +402,31 @@ namespace Jackett.Indexers
|
|||||||
Output("Category: " + MapTrackerCatToNewznab(categoryId.ToString()) + " (" + categoryId + " - " + categoryName + ")");
|
Output("Category: " + MapTrackerCatToNewznab(categoryId.ToString()) + " (" + categoryId + " - " + categoryName + ")");
|
||||||
|
|
||||||
// Seeders
|
// 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);
|
Output("Seeders: " + seeders);
|
||||||
|
|
||||||
// Leechers
|
// 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);
|
Output("Leechers: " + leechers);
|
||||||
|
|
||||||
// Completed
|
|
||||||
var completed = ParseUtil.CoerceInt(Regex.Match(tRow.Find("td:eq(4)").Text(), @"\d+").Value);
|
|
||||||
Output("Completed: " + completed);
|
|
||||||
|
|
||||||
// Files
|
// Files
|
||||||
var files = 1;
|
var files = ParseUtil.CoerceInt(Regex.Match(tRow.Find("td:eq(2)").Text(), @"\d+").Value);
|
||||||
if (tRow.Find("td:eq(3) > a").Length == 1)
|
|
||||||
{
|
|
||||||
files = ParseUtil.CoerceInt(Regex.Match(tRow.Find("td:eq(3) > a").Text(), @"\d+").Value);
|
|
||||||
}
|
|
||||||
Output("Files: " + files);
|
Output("Files: " + files);
|
||||||
|
|
||||||
|
// Comments
|
||||||
|
var comments = ParseUtil.CoerceInt(Regex.Match(tRow.Find("td:eq(3)").Text(), @"\d+").Value);
|
||||||
|
Output("Comments: " + files);
|
||||||
|
|
||||||
// Health
|
// 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 + "%");
|
Output("Health: " + percent + "%");
|
||||||
|
|
||||||
// Size
|
// Size
|
||||||
var humanSize = tRow.Find("td:eq(8)").Text().ToLowerInvariant();
|
var humanSize = tRow.Find("td:eq(7)").Text().ToLowerInvariant();
|
||||||
var size = ReleaseInfo.GetBytes(humanSize);
|
var size = ReleaseInfo.GetBytes(humanSize);
|
||||||
Output("Size: " + humanSize + " (" + size + " bytes)");
|
Output("Size: " + humanSize + " (" + size + " bytes)");
|
||||||
|
|
||||||
// Date & IMDB & Genre
|
// Date & Genre
|
||||||
var infosData = tRow.Find("td:eq(1) > div:last").Text();
|
var infosData = tRow.Find("td:eq(1) > div:last").Text();
|
||||||
var infosList = Regex.Split(infosData, "\\|").ToList();
|
var infosList = Regex.Split(infosData, "\\|").ToList();
|
||||||
var infosTorrent = infosList.Select(s => s.Split(new[] { ':' }, 2)[1].Trim()).ToList();
|
var infosTorrent = infosList.Select(s => s.Split(new[] { ':' }, 2)[1].Trim()).ToList();
|
||||||
|
@@ -105,9 +105,9 @@ namespace Jackett.Indexers
|
|||||||
release.MinimumSeedTime = 172800;
|
release.MinimumSeedTime = 172800;
|
||||||
release.Title = qLink.Attr("title");
|
release.Title = qLink.Attr("title");
|
||||||
release.Description = release.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.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.Category = TvCategoryParser.ParseTvShowQuality(release.Title);
|
||||||
|
|
||||||
release.Seeders = ParseUtil.CoerceInt(qRow.Find("td.table_seeders").Text().Trim());
|
release.Seeders = ParseUtil.CoerceInt(qRow.Find("td.table_seeders").Text().Trim());
|
||||||
|
144
src/Jackett/Indexers/Hebits.cs
Normal file
144
src/Jackett/Indexers/Hebits.cs
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
167
src/Jackett/Indexers/PassThePopcorn.cs
Normal file
167
src/Jackett/Indexers/PassThePopcorn.cs
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -17,7 +17,7 @@ namespace Jackett.Indexers
|
|||||||
{
|
{
|
||||||
public class SpeedCD : BaseIndexer, IIndexer
|
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"; } }
|
private string SearchUrl { get { return SiteLink + "browse.php"; } }
|
||||||
|
|
||||||
new ConfigurationDataBasicLogin configData
|
new ConfigurationDataBasicLogin configData
|
||||||
@@ -35,7 +35,8 @@ namespace Jackett.Indexers
|
|||||||
client: wc,
|
client: wc,
|
||||||
logger: l,
|
logger: l,
|
||||||
p: ps,
|
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("1", TorznabCatType.MoviesOther);
|
||||||
AddCategoryMapping("42", TorznabCatType.Movies);
|
AddCategoryMapping("42", TorznabCatType.Movies);
|
||||||
@@ -70,24 +71,39 @@ namespace Jackett.Indexers
|
|||||||
public async Task<IndexerConfigurationStatus> ApplyConfiguration(JToken configJson)
|
public async Task<IndexerConfigurationStatus> ApplyConfiguration(JToken configJson)
|
||||||
{
|
{
|
||||||
configData.LoadValuesFromJson(configJson);
|
configData.LoadValuesFromJson(configJson);
|
||||||
|
|
||||||
|
await DoLogin();
|
||||||
|
|
||||||
|
return IndexerConfigurationStatus.RequiresTesting;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task DoLogin()
|
||||||
|
{
|
||||||
var pairs = new Dictionary<string, string> {
|
var pairs = new Dictionary<string, string> {
|
||||||
{ "username", configData.Username.Value },
|
{ "username", configData.Username.Value },
|
||||||
{ "password", configData.Password.Value },
|
{ "password", configData.Password.Value },
|
||||||
};
|
};
|
||||||
|
|
||||||
var result = await RequestLoginAndFollowRedirect(LoginUrl, pairs, null, true, null, SiteLink);
|
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;
|
CQ dom = result.Content;
|
||||||
var errorMessage = dom["h5"].First().Text().Trim();
|
var errorMessage = dom.Text();
|
||||||
throw new ExceptionWithConfigData(errorMessage, configData);
|
throw new ExceptionWithConfigData(errorMessage, configData);
|
||||||
});
|
});
|
||||||
|
|
||||||
return IndexerConfigurationStatus.RequiresTesting;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<IEnumerable<ReleaseInfo>> PerformQuery(TorznabQuery query)
|
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 releases = new List<ReleaseInfo>();
|
||||||
|
|
||||||
NameValueCollection qParams = new NameValueCollection();
|
NameValueCollection qParams = new NameValueCollection();
|
||||||
|
@@ -61,9 +61,12 @@ namespace Jackett.Indexers
|
|||||||
AddCategoryMapping(44, TorznabCatType.MoviesSD);
|
AddCategoryMapping(44, TorznabCatType.MoviesSD);
|
||||||
AddCategoryMapping(1, TorznabCatType.MoviesSD);
|
AddCategoryMapping(1, TorznabCatType.MoviesSD);
|
||||||
|
|
||||||
// Music foreign
|
// Music
|
||||||
// Music packs
|
AddCategoryMapping(17, TorznabCatType.AudioMP3);
|
||||||
// Music videos
|
AddCategoryMapping(44, TorznabCatType.AudioLossless);
|
||||||
|
AddCategoryMapping(23, TorznabCatType.AudioForeign);
|
||||||
|
AddCategoryMapping(41, TorznabCatType.AudioOther);
|
||||||
|
AddCategoryMapping(16, TorznabCatType.AudioVideo);
|
||||||
|
|
||||||
AddCategoryMapping(4, TorznabCatType.PCGames);
|
AddCategoryMapping(4, TorznabCatType.PCGames);
|
||||||
// ps3
|
// ps3
|
||||||
|
@@ -82,6 +82,12 @@ namespace Jackett.Indexers
|
|||||||
public async Task<IndexerConfigurationStatus> ApplyConfiguration(JToken configJson)
|
public async Task<IndexerConfigurationStatus> ApplyConfiguration(JToken configJson)
|
||||||
{
|
{
|
||||||
configData.LoadValuesFromJson(configJson);
|
configData.LoadValuesFromJson(configJson);
|
||||||
|
await DoLogin();
|
||||||
|
return IndexerConfigurationStatus.RequiresTesting;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task DoLogin()
|
||||||
|
{
|
||||||
var pairs = new Dictionary<string, string> {
|
var pairs = new Dictionary<string, string> {
|
||||||
{ "username", configData.Username.Value },
|
{ "username", configData.Username.Value },
|
||||||
{ "password", configData.Password.Value },
|
{ "password", configData.Password.Value },
|
||||||
@@ -97,11 +103,17 @@ namespace Jackett.Indexers
|
|||||||
var errorMessage = messageEl.Text().Trim();
|
var errorMessage = messageEl.Text().Trim();
|
||||||
throw new ExceptionWithConfigData(errorMessage, configData);
|
throw new ExceptionWithConfigData(errorMessage, configData);
|
||||||
});
|
});
|
||||||
return IndexerConfigurationStatus.RequiresTesting;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<IEnumerable<ReleaseInfo>> PerformQuery(TorznabQuery query)
|
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 releases = new List<ReleaseInfo>();
|
||||||
var searchString = query.GetQueryString();
|
var searchString = query.GetQueryString();
|
||||||
var searchUrl = SearchUrl;
|
var searchUrl = SearchUrl;
|
||||||
@@ -151,6 +163,10 @@ namespace Jackett.Indexers
|
|||||||
release.Link = new Uri(SiteLink + qRow.Find(".quickdownload > a").Attr("href").Substring(1));
|
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);
|
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"
|
//"2015-04-25 23:38:12"
|
||||||
//"yyyy-MMM-dd hh:mm:ss"
|
//"yyyy-MMM-dd hh:mm:ss"
|
||||||
release.PublishDate = DateTime.ParseExact(dateString, "yyyy-MM-ddHH:mm:ss", CultureInfo.InvariantCulture);
|
release.PublishDate = DateTime.ParseExact(dateString, "yyyy-MM-ddHH:mm:ss", CultureInfo.InvariantCulture);
|
||||||
|
@@ -101,7 +101,10 @@ namespace Jackett.Indexers
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
title = title.Remove(title.LastIndexOf("."));
|
if (title.Length > 5 && title.Substring(title.Length - 5).Contains("."))
|
||||||
|
{
|
||||||
|
title = title.Remove(title.LastIndexOf("."));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
release.Title = title;
|
release.Title = title;
|
||||||
|
@@ -186,7 +186,9 @@
|
|||||||
<Compile Include="Controllers\TorznabController.cs" />
|
<Compile Include="Controllers\TorznabController.cs" />
|
||||||
<Compile Include="Controllers\DownloadController.cs" />
|
<Compile Include="Controllers\DownloadController.cs" />
|
||||||
<Compile Include="Engine.cs" />
|
<Compile Include="Engine.cs" />
|
||||||
|
<Compile Include="Indexers\Hebits.cs" />
|
||||||
<Compile Include="Indexers\MyAnonamouse.cs" />
|
<Compile Include="Indexers\MyAnonamouse.cs" />
|
||||||
|
<Compile Include="Indexers\PassThePopcorn.cs" />
|
||||||
<Compile Include="Indexers\Xthor.cs" />
|
<Compile Include="Indexers\Xthor.cs" />
|
||||||
<Compile Include="Indexers\PhxBit.cs" />
|
<Compile Include="Indexers\PhxBit.cs" />
|
||||||
<Compile Include="Indexers\AlphaRatio.cs" />
|
<Compile Include="Indexers\AlphaRatio.cs" />
|
||||||
@@ -217,7 +219,7 @@
|
|||||||
<Compile Include="Indexers\ImmortalSeed.cs" />
|
<Compile Include="Indexers\ImmortalSeed.cs" />
|
||||||
<Compile Include="Indexers\FileList.cs" />
|
<Compile Include="Indexers\FileList.cs" />
|
||||||
<Compile Include="Indexers\Abstract\AvistazTracker.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\TransmitheNet.cs" />
|
||||||
<Compile Include="Indexers\WiHD.cs" />
|
<Compile Include="Indexers\WiHD.cs" />
|
||||||
<Compile Include="Indexers\XSpeeds.cs" />
|
<Compile Include="Indexers\XSpeeds.cs" />
|
||||||
@@ -227,8 +229,9 @@
|
|||||||
<Compile Include="Models\IndexerConfig\Bespoke\ConfigurationDataPhxBit.cs" />
|
<Compile Include="Models\IndexerConfig\Bespoke\ConfigurationDataPhxBit.cs" />
|
||||||
<Compile Include="Models\IndexerConfig\Bespoke\ConfigurationDataBlueTigers.cs" />
|
<Compile Include="Models\IndexerConfig\Bespoke\ConfigurationDataBlueTigers.cs" />
|
||||||
<Compile Include="Models\IndexerConfig\Bespoke\ConfigurationDataAbnormal.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\Bespoke\ConfigurationDataWiHD.cs" />
|
||||||
|
<Compile Include="Models\IndexerConfig\ConfigurationDataBasicLoginWithFilterAndPasskey.cs" />
|
||||||
<Compile Include="Models\IndexerConfig\ConfigurationDataBasicLoginWithFilter.cs" />
|
<Compile Include="Models\IndexerConfig\ConfigurationDataBasicLoginWithFilter.cs" />
|
||||||
<Compile Include="Models\IndexerConfig\ConfigurationDataAPIKey.cs" />
|
<Compile Include="Models\IndexerConfig\ConfigurationDataAPIKey.cs" />
|
||||||
<Compile Include="Models\IndexerConfig\ConfigurationDataBasicLoginWithRSSAndDisplay.cs" />
|
<Compile Include="Models\IndexerConfig\ConfigurationDataBasicLoginWithRSSAndDisplay.cs" />
|
||||||
@@ -621,6 +624,9 @@
|
|||||||
<Content Include="Content\setup_indexer.html">
|
<Content Include="Content\setup_indexer.html">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
|
<Content Include="Content\logos\hebits.png">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
<Content Include="Models\TorznabCatType.tt">
|
<Content Include="Models\TorznabCatType.tt">
|
||||||
<Generator>TextTemplatingFileGenerator</Generator>
|
<Generator>TextTemplatingFileGenerator</Generator>
|
||||||
<LastGenOutput>TorznabCatType.generated.cs</LastGenOutput>
|
<LastGenOutput>TorznabCatType.generated.cs</LastGenOutput>
|
||||||
|
@@ -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)" };
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@@ -213,6 +213,11 @@ namespace Jackett.Services
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static string GetAppDataFolderStatic()
|
public static string GetAppDataFolderStatic()
|
||||||
{
|
{
|
||||||
|
if (!string.IsNullOrWhiteSpace(Startup.CustomDataFolder))
|
||||||
|
{
|
||||||
|
return Startup.CustomDataFolder;
|
||||||
|
}
|
||||||
|
|
||||||
if (System.Environment.OSVersion.Platform == PlatformID.Unix)
|
if (System.Environment.OSVersion.Platform == PlatformID.Unix)
|
||||||
{
|
{
|
||||||
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Jackett");
|
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Jackett");
|
||||||
|
@@ -58,6 +58,12 @@ namespace Jackett
|
|||||||
set;
|
set;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static string CustomDataFolder
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
public static string BasePath
|
public static string BasePath
|
||||||
{
|
{
|
||||||
get;
|
get;
|
||||||
|
@@ -46,6 +46,8 @@ namespace Jackett.Utils.Clients
|
|||||||
|
|
||||||
private async Task<WebClientByteResult> Run(WebRequest webRequest)
|
private async Task<WebClientByteResult> Run(WebRequest webRequest)
|
||||||
{
|
{
|
||||||
|
ServicePointManager.SecurityProtocol = (SecurityProtocolType)192 | (SecurityProtocolType)768 | (SecurityProtocolType)3072;
|
||||||
|
|
||||||
var cookies = new CookieContainer();
|
var cookies = new CookieContainer();
|
||||||
if (!string.IsNullOrEmpty(webRequest.Cookies))
|
if (!string.IsNullOrEmpty(webRequest.Cookies))
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user