Compare commits

...

54 Commits

Author SHA1 Message Date
kaso17
861a33f4af DataScene: fix free detection 2017-08-29 15:36:57 +02:00
kaso17
57c52d9eb2 2 Fast 4 You: fix whitespaces 2017-08-29 15:33:51 +02:00
kaso17
f574dedbe8 GigaTorrents: add search error detection 2017-08-29 15:33:19 +02:00
kaso17
a6d2ecffbb DataScene: fix definition 2017-08-29 15:33:00 +02:00
kaso17
300354ef13 update DataFolder description 2017-08-29 14:12:05 +02:00
kaso17
4a519226f5 2 Fast 4 You: remove Nouveau flag from titles 2017-08-29 11:56:41 +02:00
kaso17
6a4f6e3638 ReleaseInfo: ignore Origin during JSON serialization 2017-08-29 11:56:10 +02:00
kaso17
157b042c0a Merge branch 'master' of https://github.com/Jackett/Jackett.git 2017-08-29 10:53:39 +02:00
kaso17
9385218c9d Demonoid: ignore more ads 2017-08-29 10:53:32 +02:00
thebluepotato
7482e8d9c4 Make T411v2 public (#1740)
I'm 99% sure that since they've resurrected they're fully public (no login needed, no ratio, etc.) and since even Jackett isn't asking for login info, it should be reflected here.
2017-08-28 19:03:25 +02:00
kaso17
5501d282de Merge branch 'master' of https://github.com/Jackett/Jackett.git 2017-08-28 18:55:03 +02:00
kaso17
123bb4af5f add tracker and category to location.hash 2017-08-28 18:54:57 +02:00
halali
4d36dae634 Add CzTorrent tracker (#1739) 2017-08-28 17:32:16 +02:00
kaso17
eac11ab807 add SpeedTorrent Reloaded tracker 2017-08-28 15:49:44 +02:00
kaso17
b6892f1dc6 Dragon World (DTW): remove (dead) 2017-08-28 14:51:33 +02:00
thebluepotato
0695b8f84e Fix instructions for certificates on macOS (#1737)
* Fix instructions for certificates on macOS

* Remove an awful double space

* README cleanup

* Updated command
2017-08-28 14:37:47 +02:00
thebluepotato
04995f1a10 Fixes for 3 French trackers (#1736)
Non-critical fixes:
 - NextTorrent and Zetorrents: error in logs when no results were
returned from search
 - T411v2: improved selector to disregard VPN add in search results
2017-08-28 13:01:51 +02:00
kaso17
44d9b3ecc8 Norbits: fix download links 2017-08-28 12:51:04 +02:00
kaso17
a311509b7c Norbits: fix temp directory path generation 2017-08-28 12:50:42 +02:00
kaso17
0db4229bd4 Merge branch 'master' of https://github.com/Jackett/Jackett.git 2017-08-28 11:42:37 +02:00
kaso17
441aad5a18 Demonoid: ignore ad lines 2017-08-28 11:42:28 +02:00
thebluepotato
d8d911abf8 Add a script to install Jackett as service on macOS (#1705)
* Add instructions tu run Jackett as service on macOS

* Changed restart logic

* Replace plist with install script

* Update README and add some more checks

* Fix README

* Move and rename script

* Include script inside project

* README corrections and cleanup

* Slight improvement of the script

Put `launchctl remove` earlier so it has the time to quit the service before testing if it's still running.
2017-08-28 11:05:41 +02:00
kaso17
7423e3f5bc add workaround for mono relative redirect bug 2017-08-28 11:01:45 +02:00
kaso17
48fea35645 Merge branch 'master' of https://github.com/Jackett/Jackett 2017-08-24 12:29:57 +02:00
kaso17
cef72f11d0 manual search: improve error handling (#1717)
* manual search: improve error handling

* add index changes
2017-08-24 12:28:41 +02:00
kaso17
ad3039b70f Best Friends: remove (dead) 2017-08-24 12:05:18 +02:00
kaso17
73d590cebd include stacktrace in error 2017-08-24 12:02:38 +02:00
kaso17
1d0790471f Karagarga: fix download attempt 2017-08-24 10:48:11 +02:00
kaso17
3b3048aa01 Merge branch 'master' of https://github.com/Jackett/Jackett.git 2017-08-24 10:21:29 +02:00
kaso17
183fb56b0a Gazelle: improve isPersonalFreeleech handling 2017-08-24 10:21:20 +02:00
kaso17
466be31e6f Best Friends: remove (dead) 2017-08-24 10:13:41 +02:00
Khogniak
db42bc944b Fixed typo in regex 2017-08-23 11:39:34 +02:00
Khogniak
102e7338f9 Make regex case incesitive 2017-08-23 11:39:34 +02:00
Khogniak
01b30b0743 Added option to normalize release name 2017-08-23 11:39:34 +02:00
kaso17
947dbac485 SceneAccess: fix long titles 2017-08-23 11:37:54 +02:00
kaso17
0d29e85c80 Kapaki: fix error on no results 2017-08-22 19:26:56 +02:00
kaso17
89a28e2e95 myAmity: fix login detection 2017-08-22 19:17:47 +02:00
kaso17
66b2c20b42 ImmortalSeed: fix error on no results 2017-08-22 19:17:47 +02:00
kaso17
e6035bcaa5 Hardbay: fix error on no results 2017-08-22 19:17:47 +02:00
kaso17
68aac78360 EoT-Forum: update URL 2017-08-22 19:17:47 +02:00
kaso17
4b02141250 BTNext: fix error on no results 2017-08-22 19:17:47 +02:00
kaso17
8e1d321817 BroadcastTheNet: fix error on no results 2017-08-22 19:17:47 +02:00
kaso17
3354d37aa3 TorrentNetwork: fix typo 2017-08-22 17:46:58 +02:00
kaso17
7675214092 TorrentNetwork: fix indexer 2017-08-22 17:43:39 +02:00
kaso17
7af8e1916e Tasmanit: use wildcards for search 2017-08-22 13:34:21 +02:00
kaso17
6d4720e58f Hounddawgs: add support for alternative time format 2017-08-22 11:00:10 +02:00
kaso17
9928815777 fix cookie fallback login 2017-08-21 15:02:36 +02:00
kaso17
a7d65fedfb PotatoFeed: fix potatoenabled flag 2017-08-21 15:02:06 +02:00
kaso17
464b142130 Waffles: fix download 2017-08-21 14:07:44 +02:00
kaso17
e1bcdce019 Merge branch 'master' of https://github.com/Jackett/Jackett.git 2017-08-21 13:06:57 +02:00
kaso17
ced9bad4f8 BroadcastTheNet: various improvements 2017-08-21 13:06:44 +02:00
thebluepotato
c6140d7eef fix(indexers): updated browse page endpoint (#1696)
They changed the url for the latest torrents once again…
2017-08-21 11:17:17 +02:00
thebluepotato
97f4a9de5d fix(indexers): updated t411v2 definition (#1694) 2017-08-20 17:00:21 +02:00
thebluepotato
be1f6a43a7 fix(indexers): kat clone (#1693)
kat.how -> thekat.se
fixes #1607
2017-08-20 16:56:55 +02:00
50 changed files with 1507 additions and 1321 deletions

View File

@@ -1,4 +1,4 @@
# Jackett
# Jackett
[![GitHub issues](https://img.shields.io/github/issues/Jackett/Jackett.svg?maxAge=60&style=flat-square)](https://github.com/Jackett/Jackett/issues)
[![GitHub pull requests](https://img.shields.io/github/issues-pr/Jackett/Jackett.svg?maxAge=60&style=flat-square)](https://github.com/Jackett/Jackett/pulls)
@@ -18,7 +18,7 @@ Developer note: The software implements the [Torznab](https://github.com/Sonarr/
#### Supported Systems
* Windows using .NET 4.5
* Linux and OSX using Mono 4 (mono 3 is no longer supported).
* Linux and macOS using Mono 4 (mono 3 is no longer supported).
### Supported Public Trackers
* Anidex
@@ -30,7 +30,7 @@ Developer note: The software implements the [Torznab](https://github.com/Sonarr/
* Il Corsaro Nero <!-- maintained by bonny1992 -->
* Isohunt
* KickAssTorrent
* KickAssTorrent (kat.how clone)
* KickAssTorrent (thekat.se clone)
* LimeTorrents
* NextTorrent
* Nyaa.si
@@ -69,7 +69,6 @@ Developer note: The software implements the [Torznab](https://github.com/Sonarr/
* B2S-Share
* BakaBT [![(invite needed)][inviteneeded]](#)
* bB
* Best Friends
* BeyondHD
* BIGTorrent
* Bit-City Reloaded
@@ -82,7 +81,7 @@ Developer note: The software implements the [Torznab](https://github.com/Sonarr/
* Blu-bits
* BlueBird
* Blutopia
* BroadcastTheNet [![(invite needed)][inviteneeded]](#)
* BroadcastTheNet
* BrokenStones
* BTNext
* Carpathians
@@ -92,13 +91,13 @@ Developer note: The software implements the [Torznab](https://github.com/Sonarr/
* CinemaZ
* Classix
* CZTeam
* CzTorrent
* DanishBits
* DataScene
* Deildu
* Demonoid
* Diablo Torrent
* DigitalHive
* Dragon World (DTW)
* Dragonworld Reloaded
* Dream Team
* EoT-Forum
@@ -190,6 +189,7 @@ Developer note: The software implements the [Torznab](https://github.com/Sonarr/
* Shazbat
* Shellife
* SpeedCD
* SpeedTorrent Reloaded
* SportsCult
* SportHD
* Superbits
@@ -272,14 +272,21 @@ Jackett can also be run from the command line if you would like to see log messa
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/)
## Installation on OSX
1. Install [Mono 4](http://www.mono-project.com/download/#download-mac) or better (version 4.8 is recommended)
* Setup ssl support by running
```
https://curl.haxx.se/ca/cacert.pem
cert-sync --user ~/Downloads/cacert.pem
```
1. 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 --debug JackettConsole.exe`.
## Installation on macOS
### Prerequisites
Install [Mono 4](http://www.mono-project.com/download/#download-mac) or better (version 4.8 is recommended).
* Setup ssl support by running `curl -sS https://curl.haxx.se/ca/cacert.pem | cert-sync --user /dev/stdin`
### Install as service
1. Download and extract the latest `Jackett.Binaries.Mono.tar.gz` release from the [releases page](https://github.com/Jackett/Jackett/releases).
2. In Terminal, run the install script from the extracted directory using `./install_service_macos.sh`
The service will start on each logon. You can always stop it by running `launchctl unload ~/Library/LaunchAgents/org.user.Jackett.plist` from Terminal. You can start it again it using `launchctl load ~/Library/LaunchAgents/org.user.Jackett.plist`.
Logs are stored as usual under `~/.config/Jackett/log.txt`.
### Run without installing as a service
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 --debug JackettConsole.exe`.
## Installation using Docker
Detailed instructions are available at [LinuxServer.io Jackett Docker](https://hub.docker.com/r/linuxserver/jackett/). The Jackett Docker is highly recommended, especially if you are having Mono stability issues or having issues running Mono on your system eg. QNAP, Synology. Thanks to [LinuxServer.io](https://linuxserver.io)
@@ -297,16 +304,16 @@ Jackett is available as beta package from [SynoCommunity](https://synocommunity.
If you're using mono this is often caused by missing ca-certificates.
Try reimporting the certificates in this case:
`wget -O - https://curl.haxx.se/ca/cacert.pem | cert-sync /dev/stdin`
- On Linux: `wget -O - https://curl.haxx.se/ca/cacert.pem | cert-sync /dev/stdin`
- On macOS: `curl -sS https://curl.haxx.se/ca/cacert.pem | cert-sync --user /dev/stdin`
As a option of last resort you can disable certificate validation using the `--IgnoreSslErrors true` option but it's not recommended to use it as it enables Man-in-the-middle attacks on your connections.
* __Enable logging__
You can get additional logging with the command line switches `-t -l` or by enabeling `Enhanced logging` via the web interface.
You can get additional logging with the command line switches `-t -l` or by enabling `Enhanced logging` via the web interface.
Please post logs if you are unable to resolve your issue with these switches ensuring to remove your username/password/cookies.
The logfiles (log.txt/updater.txt) are stored in `%ProgramData%\Jackett` on Windows and `~/.config/Jackett/` on Linux/OSX.
The logfiles (log.txt/updater.txt) are stored in `%ProgramData%\Jackett` on Windows and `~/.config/Jackett/` on Linux/macOS.
## Creating an issue
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.

View File

@@ -60,7 +60,7 @@ namespace Jackett.Console
[Option('n', "IgnoreSslErrors", HelpText = "[true/false] 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\\\"")]
[Option('d', "DataFolder", HelpText = "Specify the location of the data folder (Must be admin on Windows) eg. --DataFolder=\"D:\\Your Data\\Jackett\\\". Don't use this on Unix (mono) systems. On Unix just adjust the HOME directory of the user to the datedir or set the XDG_CONFIG_HOME environment variable.")]
public string DataFolder { get; set; }
[Option(HelpText = "Don't restart after update")]

View File

@@ -153,6 +153,9 @@
<ItemGroup>
<None Include="App.config" />
<None Include="packages.config" />
<Content Include="install_service_macos.sh">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\CurlSharp\CurlSharp.csproj">
@@ -182,4 +185,4 @@
<Target Name="AfterBuild">
</Target>
-->
</Project>
</Project>

View File

@@ -0,0 +1,67 @@
#!/bin/bash
# Stop and unload the service if it's running
launchctl remove org.user.Jackett
# Check if we're running from Jackett's directory
if [ ! -f ./JackettConsole.exe ]; then
echo "Couldn't locate JackettConsole.exe. Are you running from the right directory?"
exit 1
fi
jackettdir="$(pwd)"
# Check if mono is installed
command -v mono >/dev/null 2>&1 || { echo >&2 "Jackett requires Mono but it's not installed. Aborting."; exit 1; }
monodir="$(dirname $(command -v mono))"
# Check that no other service called Jackett is already running
if [[ $(launchctl list | grep org.user.Jackett) ]]; then
echo "Jackett already seems to be running as a service. Please stop it before running this script again."
exit 1
fi
# Write the plist to LaunchAgents
cat >~/Library/LaunchAgents/org.user.Jackett.plist <<EOL
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>EnvironmentVariables</key>
<dict>
<key>PATH</key>
<string>/usr/bin:/bin:/usr/sbin:/sbin:${monodir}</string>
</dict>
<key>KeepAlive</key>
<true/>
<key>Label</key>
<string>org.user.Jackett</string>
<key>ProgramArguments</key>
<array>
<string>${monodir}/mono</string>
<string>--debug</string>
<string>JackettConsole.exe</string>
<string>--NoRestart</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>WorkingDirectory</key>
<string>${jackettdir}</string>
</dict>
</plist>
EOL
# Run the agent
launchctl load ~/Library/LaunchAgents/org.user.Jackett.plist
# Check that it's running
if [[ $(launchctl list | grep org.user.Jackett) ]]; then
echo "Agent successfully installed and launched!"
else
cat << EOL
Could not launch agent. The installation might have failed.
Please open an issue on https://github.com/Jackett/Jackett/issues and paste following information:
Mono directory: \`${monodir}\`
Jackett directory: \`${jackettdir}\`
EOL
fi

View File

@@ -190,6 +190,7 @@ namespace Jackett.Updater
"Definitions/nachtwerk.yml",
"Definitions/leparadisdunet.yml",
"Definitions/qctorrent.yml",
"Definitions/dragonworld.yml",
};
foreach (var oldFIle in oldFiles)

View File

@@ -42,12 +42,9 @@ $(document).ready(function () {
});
function openSearchIfNecessary() {
var parser = document.createElement('a');
parser.href = window.location.href;
if (parser.hash.startsWith("#search")) {
var query = parser.hash.split('=')[1];
showSearch(null, query);
const hashArgs = location.hash.substring(1).split('&').reduce((prev, item) => Object.assign({ [item.split('=')[0]]: (item.split('=').length < 2 ? undefined : decodeURIComponent(item.split('=')[1])) }, prev), {});
if ("search" in hashArgs) {
showSearch(hashArgs.tracker, hashArgs.search, hashArgs.category);
}
}
@@ -371,6 +368,7 @@ function prepareSearchButtons(element) {
var $btn = $(btn);
var id = $btn.data("id");
$btn.click(function() {
window.location.hash = "search&tracker=" + id;
showSearch(id);
});
});
@@ -725,7 +723,7 @@ function updateReleasesRow(row)
}
}
function showSearch(selectedIndexer, query) {
function showSearch(selectedIndexer, query, category) {
$('#select-indexer-modal').remove();
var releaseTemplate = Handlebars.compile($("#jackett-search").html());
var releaseDialog = $(releaseTemplate({
@@ -788,7 +786,7 @@ function showSearch(selectedIndexer, query) {
Tracker: releaseDialog.find('#searchTracker').val().replace("'", "").replace("'", ""),
};
window.location.hash = "search=" + searchString;
window.location.hash = $.param({ search: queryObj.Query, tracker: queryObj.Tracker, category: queryObj.Category});
$('#jackett-search-perform').html($('#spinner').html());
$('#searchResults div.dataTables_filter input').val("");
@@ -824,8 +822,12 @@ function showSearch(selectedIndexer, query) {
clearSearchResultTable($('#searchResults'));
releaseDialog.modal("show");
if (category !== undefined) {
$('#searchCategory').val(category);
}
if (query !== undefined) {
queryField.value = decodeURIComponent(query);
queryField.value = query;
searchButton.click();
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -19,6 +19,7 @@ using Jackett.Utils;
using Jackett.Utils.Clients;
using Newtonsoft.Json;
using NLog;
using Jackett.Models.DTO;
namespace Jackett.Controllers.V20
{
@@ -154,20 +155,67 @@ namespace Jackett.Controllers.V20
[HttpGet]
public async Task<Models.DTO.ManualSearchResult> Results([FromUri]Models.DTO.ApiSearch request)
{
var manualResult = new ManualSearchResult();
var trackers = IndexerService.GetAllIndexers().Where(t => t.IsConfigured);
if (CurrentIndexer.ID != "all")
trackers = trackers.Where(t => t.ID == CurrentIndexer.ID).ToList();
trackers = trackers.Where(t => t.IsConfigured && t.CanHandleQuery(CurrentQuery));
trackers = trackers.Where(t => t.CanHandleQuery(CurrentQuery));
var tasks = trackers.ToList().Select(t => t.ResultsForQuery(CurrentQuery)).ToList();
var aggregateTask = Task.WhenAll(tasks);
await aggregateTask;
var results = tasks.Where(t => t.Status == TaskStatus.RanToCompletion).Where(t => t.Result.Count() > 0).SelectMany(t =>
try
{
var searchResults = t.Result;
var indexer = searchResults.First().Origin;
var aggregateTask = Task.WhenAll(tasks);
await aggregateTask;
}
catch (AggregateException aex)
{
foreach (var ex in aex.InnerExceptions)
{
logger.Error(ex);
}
}
catch (Exception ex)
{
logger.Error(ex);
}
manualResult.Indexers = tasks.Select(t =>
{
var resultIndexer = new ManualSearchResultIndexer();
IIndexer indexer = null;
if (t.Status == TaskStatus.RanToCompletion)
{
resultIndexer.Status = ManualSearchResultIndexerStatus.OK;
resultIndexer.Results = t.Result.Releases.Count();
resultIndexer.Error = null;
indexer = t.Result.Indexer;
}
else if (t.Exception.InnerException is IndexerException)
{
resultIndexer.Status = ManualSearchResultIndexerStatus.Error;
resultIndexer.Results = 0;
resultIndexer.Error = ((IndexerException)t.Exception.InnerException).ToString();
indexer = ((IndexerException)t.Exception.InnerException).Indexer;
}
else
{
resultIndexer.Status = ManualSearchResultIndexerStatus.Unknown;
resultIndexer.Results = 0;
resultIndexer.Error = null;
}
if (indexer != null)
{
resultIndexer.ID = indexer.ID;
resultIndexer.Name = indexer.DisplayName;
}
return resultIndexer;
}).ToList();
manualResult.Results = tasks.Where(t => t.Status == TaskStatus.RanToCompletion).Where(t => t.Result.Releases.Count() > 0).SelectMany(t =>
{
var searchResults = t.Result.Releases;
var indexer = t.Result.Indexer;
cacheService.CacheRssResults(indexer, searchResults);
return searchResults.Select(result =>
@@ -181,17 +229,7 @@ namespace Jackett.Controllers.V20
});
}).OrderByDescending(d => d.PublishDate).ToList();
ConfigureCacheResults(results);
var manualResult = new Models.DTO.ManualSearchResult()
{
Results = results,
Indexers = trackers.Select(t => t.DisplayName).ToList()
};
if (manualResult.Indexers.Count() == 0)
manualResult.Indexers = new List<string>() { "None" };
ConfigureCacheResults(manualResult.Results);
logger.Info(string.Format("Manual search for \"{0}\" on {1} with {2} results.", CurrentQuery.SanitizedSearchTerm, string.Join(", ", manualResult.Indexers), manualResult.Results.Count()));
return manualResult;
@@ -236,7 +274,7 @@ namespace Jackett.Controllers.V20
}
}
var releases = await CurrentIndexer.ResultsForQuery(CurrentQuery);
var result = await CurrentIndexer.ResultsForQuery(CurrentQuery);
// Some trackers do not support multiple category filtering so filter the releases that match manually.
int? newItemCount = null;
@@ -244,19 +282,19 @@ namespace Jackett.Controllers.V20
// Cache non query results
if (string.IsNullOrEmpty(CurrentQuery.SanitizedSearchTerm))
{
newItemCount = cacheService.GetNewItemCount(CurrentIndexer, releases);
cacheService.CacheRssResults(CurrentIndexer, releases);
newItemCount = cacheService.GetNewItemCount(CurrentIndexer, result.Releases);
cacheService.CacheRssResults(CurrentIndexer, result.Releases);
}
// Log info
var logBuilder = new StringBuilder();
if (newItemCount != null)
{
logBuilder.AppendFormat("Found {0} ({1} new) releases from {2}", releases.Count(), newItemCount, CurrentIndexer.DisplayName);
logBuilder.AppendFormat("Found {0} ({1} new) releases from {2}", result.Releases.Count(), newItemCount, CurrentIndexer.DisplayName);
}
else
{
logBuilder.AppendFormat("Found {0} releases from {1}", releases.Count(), CurrentIndexer.DisplayName);
logBuilder.AppendFormat("Found {0} releases from {1}", result.Releases.Count(), CurrentIndexer.DisplayName);
}
if (!string.IsNullOrWhiteSpace(CurrentQuery.SanitizedSearchTerm))
@@ -278,7 +316,7 @@ namespace Jackett.Controllers.V20
ImageDescription = CurrentIndexer.DisplayName
});
var proxiedReleases = releases.Select(r => AutoMapper.Mapper.Map<ReleaseInfo>(r)).Select(r =>
var proxiedReleases = result.Releases.Select(r => AutoMapper.Mapper.Map<ReleaseInfo>(r)).Select(r =>
{
r.Link = serverService.ConvertToProxyLink(r.Link, serverUrl, r.Origin.ID, "dl", r.Title + ".torrent");
return r;
@@ -316,20 +354,20 @@ namespace Jackett.Controllers.V20
[JsonResponse]
public async Task<Models.DTO.TorrentPotatoResponse> Potato([FromUri]Models.DTO.TorrentPotatoRequest request)
{
var releases = await CurrentIndexer.ResultsForQuery(CurrentQuery);
var result = await CurrentIndexer.ResultsForQuery(CurrentQuery);
// Cache non query results
if (string.IsNullOrEmpty(CurrentQuery.SanitizedSearchTerm))
cacheService.CacheRssResults(CurrentIndexer, releases);
cacheService.CacheRssResults(CurrentIndexer, result.Releases);
// Log info
if (string.IsNullOrWhiteSpace(CurrentQuery.SanitizedSearchTerm))
logger.Info($"Found {releases.Count()} torrentpotato releases from {CurrentIndexer.DisplayName}");
logger.Info($"Found {result.Releases.Count()} torrentpotato releases from {CurrentIndexer.DisplayName}");
else
logger.Info($"Found {releases.Count()} torrentpotato releases from {CurrentIndexer.DisplayName} for: {CurrentQuery.GetQueryString()}");
logger.Info($"Found {result.Releases.Count()} torrentpotato releases from {CurrentIndexer.DisplayName} for: {CurrentQuery.GetQueryString()}");
var serverUrl = string.Format("{0}://{1}:{2}{3}", Request.RequestUri.Scheme, Request.RequestUri.Host, Request.RequestUri.Port, serverService.BasePath());
var potatoReleases = releases.Where(r => r.Link != null || r.MagnetUri != null).Select(r =>
var potatoReleases = result.Releases.Where(r => r.Link != null || r.MagnetUri != null).Select(r =>
{
var release = AutoMapper.Mapper.Map<ReleaseInfo>(r);
release.Link = serverService.ConvertToProxyLink(release.Link, serverUrl, CurrentIndexer.ID, "dl", release.Title + ".torrent");

View File

@@ -112,6 +112,9 @@
args: ["torrents-details.php", "download.php"]
title:
selector: a[href^="torrents-details.php?id="]
filters:
- name: replace
args: [" - (Nouveau!)", ""]
category:
selector: a[href^="torrents.php?cat="]
attribute: href

View File

@@ -120,7 +120,7 @@
search_type: "name"
searchin: "title"
error:
- selector: div.error
- selector: div.error:not(:contains("Não existem resultados encontrados."))
rows:
selector: table#torrents_table_classic > tbody > tr:has(td.torrent_name)
fields:

View File

@@ -0,0 +1,125 @@
---
site: cztorrent
name: CzTorrent
language: cs-cz
type: semi-private
encoding: UTF-8
links:
- https://tracker.cztorrent.net/
caps:
categorymappings:
- {id: 1, cat: Movies, desc: "Filmy"}
- {id: 25, cat: TV, desc: "Seriály"}
- {id: 23, cat: TV/Documentary, desc: "Filmy - dokument"}
- {id: 22, cat: PC, desc: "Aplikace"}
- {id: 36, cat: Movies/3D, desc: "Filmy - 3D"}
- {id: 35, cat: Movies/Other, desc: "Filmy - anime"}
- {id: 37, cat: Movies/BluRay, desc: "Filmy - Blu-ray"}
- {id: 11, cat: Movies/DVD, desc: "Filmy - DVD"}
- {id: 30, cat: Movies/DVD, desc: "Filmy - DVD full"}
- {id: 5, cat: Movies, desc: "Filmy - kreslené"}
- {id: 31, cat: Movies/HD, desc: "HD"}
- {id: 38, cat: Movies/HD, desc: "HD-LQ"}
- {id: 3, cat: PC/Games, desc: "Hry"}
- {id: 2, cat: Audio, desc: "Hudba"}
- {id: 34, cat: Audio/Video, desc: "Hudba DVD/HD"}
- {id: 6, cat: Books, desc: "Knihy"}
- {id: 13, cat: Console, desc: "Konzole"}
- {id: 32, cat: Audio, desc: "Mluvené slovo"}
- {id: 16, cat: PC/Phone-Other, desc: "Mobil, PDA"}
- {id: 4, cat: Other, desc: "Ostatní"}
- {id: 29, cat: Audio, desc: "Soundtrack"}
- {id: 19, cat: Audio/Video, desc: "Videoklipy"}
- {id: 24, cat: XXX, desc: "xXx"}
modes:
search: [q]
tv-search: [q, season, ep]
movie-search: [q]
login:
path: /login-page
method: form
form: form[action^="/login"]
inputs:
username: "{{ .Config.username }}"
password: "{{ .Config.password }}"
persistent_login: "1"
error:
- selector: div.error
test:
path: /torrents
search:
path: /torrents
inputs:
$raw: "{{range .Categories}}c{{.}}=1&{{end}}"
s: "{{ .Keywords }}"
t: "1"
rows:
selector: tr.torr_hover
fields:
title:
selector: td.detaily a
filters:
- name: re_replace
args: [".*? / ", ""]
category:
selector: td:nth-child(2)
case:
":contains(\"Filmy\")": 1
":contains(\"Seriály\")": 25
":contains(\"Filmy - dokument\")": 23
":contains(\"Aplikace\")": 22
":contains(\"Filmy - 3D\")": 36
":contains(\"Filmy - anime\")": 35
":contains(\"Filmy - Blu-ray\")": 37
":contains(\"Filmy - DVD\")": 11
":contains(\"Filmy - DVD full\")": 30
":contains(\"Filmy - kreslené\")": 5
":contains(\"HD\")": 31
":contains(\"HD-LQ\")": 38
":contains(\"Hry\")": 3
":contains(\"Hudba\")": 2
":contains(\"Hudba DVD/HD\")": 34
":contains(\"Knihy\")": 6
":contains(\"Konzole\")": 13
":contains(\"Mluvené slovo\")": 32
":contains(\"Mobil, PDA\")": 16
":contains(\"Ostatní\")": 4
":contains(\"Soundtrack\")": 29
":contains(\"Videoklipy\")": 19
":contains(\"xXx\")": 24
details:
selector: td.detaily a
attribute: href
download:
selector: td.download a
attribute: href
size:
selector: td.detaily
filters:
- name: split
args: [ "|", 0 ]
- name: regexp
args: "Velikost: (.+?) ?$"
date:
selector: td:nth-child(4)
filters:
- name: split
args: [ "|", 1 ]
- name: regexp
args: "Přidán: (.+?) ?$"
- name: append
args: " +02:00"
seeders:
selector: td:nth-child(7) span
leechers:
selector: td:nth-child(8) span
downloadvolumefactor:
case:
"*": "1"
uploadvolumefactor:
case:
"*": "1"

View File

@@ -67,7 +67,7 @@
search: "{{ .Query.Keywords }}"
incldead: 1
rows:
selector: tr:has(a.tname)
selector: div.ncls > table > tbody > tr:has(a.tname)
fields:
title-attribute:
selector: a.tname
@@ -86,7 +86,7 @@
- name: querystring
args: cat
download:
selector: a[href^="/download.php/"]
selector: a[href^="/download.php/"], a[href^="/downloadd.php/"] # some releases use a download link with two d's
attribute: href
grabs:
selector: td:nth-child(8)
@@ -97,10 +97,9 @@
selector: td:nth-child(7)
date:
selector: td:nth-child(2) > right > div:has(font:contains("Uploaded"))
remove: div > font
filters:
- name: trim
args: ":"
- name: replace
args: ["Uploaded: ", ""]
seeders:
selector: td:nth-child(9)
leechers:
@@ -117,7 +116,7 @@
attribute: href
downloadvolumefactor:
case:
"img[src=\"pic/free.gif\"]": "0"
"img[src=\"pic/free.png\"]": "0"
"*": "1"
uploadvolumefactor:
case:

View File

@@ -1,154 +0,0 @@
---
site: dragonworld
name: Dragon World (DTW)
language: de-de
type: private
encoding: UTF-8
links:
- http://dtw.sytes.net/
caps:
categorymappings:
# Dokumentation
- {id: 46, cat: TV/Documentary, desc: "Dokumentation"}
- {id: 55, cat: TV/Documentary, desc: "Dokumentation/HD"}
- {id: 56, cat: TV/Documentary, desc: "Dokumentation/SD"}
# Ebooks
- {id: 36, cat: Books, desc: "Ebooks"}
- {id: 37, cat: Books, desc: "Ebooks"}
- {id: 38, cat: Books, desc: "Ebooks/Hoerspiele/Hoerbuecher"}
# Games
- {id: 21, cat: Console, desc: "Games"}
- {id: 24, cat: Console/Other, desc: "Games/Nintendo"}
- {id: 22, cat: PC/Games, desc: "Games/PC"}
- {id: 23, cat: Console/PS4, desc: "Games/Playstation"}
- {id: 25, cat: Console/Xbox, desc: "Games/Xbox"}
# Kinder
- {id: 10, cat: Other, desc: "Kinder"}
- {id: 14, cat: Other, desc: "Kinder/Diverses"}
- {id: 12, cat: Movies, desc: "Kinder/Filme"}
- {id: 11, cat: PC/Games, desc: "Kinder/Games"}
- {id: 13, cat: Audio, desc: "Kinder/Musik"}
# Movies
- {id: 15, cat: Movies, desc: "Movies"}
- {id: 50, cat: Movies/3D, desc: "Movies/3D"}
- {id: 48, cat: Movies/HD, desc: "Movies/HD"}
- {id: 53, cat: Movies/HD, desc: "Movies/HD Pack"}
- {id: 45, cat: Movies/HD, desc: "Movies/Remuxe"}
- {id: 17, cat: Movies/SD, desc: "Movies/SD"}
- {id: 54, cat: Movies/SD, desc: "Movies/SD Pack"}
# Musik
- {id: 4, cat: Audio, desc: "Musik"}
- {id: 57, cat: Audio, desc: "Musik/Album"}
- {id: 8, cat: Audio/Lossless, desc: "Musik/Flac"}
- {id: 7, cat: Audio/MP3, desc: "Musik/Mp3"}
- {id: 9, cat: Audio/Video, desc: "Musik/Video"}
# Serien
- {id: 26, cat: TV, desc: "Serien"}
- {id: 27, cat: TV/HD, desc: "Serien/HD"}
- {id: 28, cat: TV/SD, desc: "Serien/SD"}
# Software
- {id: 29, cat: PC/0day, desc: "Software"}
- {id: 32, cat: PC/0day, desc: "Software/Diverses"}
- {id: 31, cat: PC/Mac, desc: "Software/Mac"}
- {id: 30, cat: PC/0day, desc: "Software/Windows"}
# Sport
- {id: 39, cat: TV/Sport, desc: "Sport"}
- {id: 40, cat: TV/Sport, desc: "Sport HD"}
- {id: 58, cat: TV/Sport, desc: "Sport SD"}
# XXX
- {id: 33, cat: XXX, desc: "XXX"}
- {id: 34, cat: XXX, desc: "XXX/HD"}
- {id: 35, cat: XXX, desc: "XXX/SD"}
modes:
search: [q]
tv-search: [q, season, ep]
movie-search: [q]
login:
path: takelogin.php
method: post
inputs:
username: "{{ .Config.username }}"
password: "{{ .Config.password }}"
error:
- selector: table:has(td:contains("Ein Fehler ist aufgetreten"))
test:
path: browse.php
selector: a[href*="/logout.php"]
download:
before:
path: "takethanks.php"
method: "post"
inputs:
torrentid: "{{ .DownloadUri.Query.id }}"
search:
path: browse.php
keywordsfilters:
- name: re_replace
args: ["[^a-zA-Z0-9]+", "%"]
inputs:
do: "search"
keywords: "{{ .Keywords }}"
search_type: "t_name"
category: "0" # multi cat search not supported
include_dead_torrents: "yes"
rows:
selector: table#sortabletable > tbody > tr:has(a[href*="/details.php?id="])
filters:
- name: andmatch
args: 66
fields:
download:
selector: a[href*="/download.php?id="]
attribute: href
magnet:
selector: a[href^="magnet:"]
attribute: href
title:
selector: a[href*="/details.php?id="]
title:
selector: div.tooltip-content > div
optional: true
details:
selector: a[href*="/details.php?id="]
attribute: href
category:
selector: a[href*="/browse.php?category="]
attribute: href
filters:
- name: querystring
args: category
banner:
selector: div.tooltip-content > img
attribute: src
optional: true
size:
selector: td:nth-child(5)
grabs:
selector: td:nth-child(6)
seeders:
selector: td:nth-child(7)
leechers:
selector: td:nth-child(8)
downloadvolumefactor:
case:
img[alt^="OnlyUp Torrent"]: "0"
img[alt^="50% "]: "0.5"
"*": "1"
uploadvolumefactor:
case:
img[alt^="multi2 Torrent"]: "2"
"*": "1"
date:
selector: "td:nth-child(2) > div:has(span[style=\"float: right;\"])"
remove: span
filters:
- name: append
args: " +01:00"
- name: dateparse
args: "02-01-2006 15:04 -07:00"

View File

@@ -6,7 +6,7 @@
type: private
encoding: windows-1252
links:
- http://eot-forum.net
- https://eot-forum.net
caps:
categorymappings:

View File

@@ -70,6 +70,8 @@
blah: "0"
rows:
selector: table#torrenttable > tbody > tr:has()
error:
- selector: div.content:contains("Meg van vonva a letöltési jogod")
fields:
download:
selector: a[href^="/details.php?id="]

View File

@@ -77,7 +77,7 @@
search_type: "name"
searchin: "title"
error:
- selector: div#show_error
- selector: div#show_error:not(:contains("Ουπς! Λάθος!Δεν βρέθηκαν αποτελέσματα."))
rows:
selector: div#content > div.torrent-box[id^="torrent_"]
filters:

View File

@@ -30,9 +30,6 @@
test:
path: index.php
download:
selector: a[href^="download.php?id="]
search:
path: browse.php
inputs:
@@ -47,11 +44,8 @@
title:
selector: td:nth-child(2) span
download:
selector: a[href^="details.php?id="]
selector: a[href^="down.php"]
attribute: href
filters:
- name: replace
args: ["details.php?id=", "download.php?id="]
details:
selector: a[href^="details.php?id="]
attribute: href

4
src/Jackett/Definitions/kickasstorrent-kathow.yml Normal file → Executable file
View File

@@ -1,11 +1,11 @@
---
site: kickasstorrent-kathow
name: KickAssTorrent (kat.how)
name: KickAssTorrent (thekat.se)
language: en-us
type: public
encoding: UTF-8
links:
- https://kat.how
- https://thekat.se
caps:
categories:

2
src/Jackett/Definitions/kickasstorrent.yml Normal file → Executable file
View File

@@ -88,7 +88,7 @@
settings: []
search:
path: "/new/{{if .Query.Keywords}}search-torrents.php{{else}}torrents.php{{end}}"
path: "/new/{{if .Query.Keywords}}search-torrents.php{{else}}index.php{{end}}"
inputs:
$raw: "{{range .Categories}}c{{.}}=1&{{end}}"
search: "\"{{ .Query.Keywords }}\""

4
src/Jackett/Definitions/nexttorrent.yml Normal file → Executable file
View File

@@ -24,7 +24,7 @@
search:
path: "recherche/{{ .Query.Keywords }}"
rows:
selector: div.listing-torrent > table tbody tr
selector: div.listing-torrent > table tbody tr:has(a)
fields:
site_date:
selector: td:nth-child(1) a
@@ -85,4 +85,4 @@
downloadvolumefactor:
text: "0"
uploadvolumefactor:
text: "1"
text: "1"

View File

@@ -0,0 +1,122 @@
---
site: speedtorrentreloaded
name: SpeedTorrent Reloaded
language: de-de
type: private
encoding: UTF-8
links:
- https://speedtorrent-tracker.mine.nu/
caps:
categorymappings:
- {id: 201, cat: Movies/HD, desc: "Filme: HD 720P / 1080P"}
- {id: 103, cat: Movies/DVD, desc: "Filme: DVD"}
- {id: 104, cat: Movies/DVD, desc: "Filme: HD2DVD"}
- {id: 137, cat: Audio/Video, desc: "Musik: Video"}
- {id: 106, cat: Movies/SD, desc: "Filme: DVDRip"}
- {id: 107, cat: Movies/SD, desc: "Filme: BDRip "}
- {id: 108, cat: Movies/3D, desc: "Filme: 3D"}
- {id: 109, cat: Movies/BluRay, desc: "Filme: Blue Ray"}
- {id: 111, cat: Movies/SD, desc: "Filme: SD"}
- {id: 112, cat: Movies/Other, desc: "Filme: TV/HDTV"}
- {id: 203, cat: XXX, desc: "Erotik: XXX PDF"}
- {id: 116, cat: Console, desc: "Spiele: Konsolen"}
- {id: 117, cat: PC/Games, desc: "Spiele: Windows / Mac"}
- {id: 126, cat: PC/0day, desc: "Software: Mac / Linux"}
- {id: 120, cat: Audio/Other, desc: "Musik: Alben/Sampler "}
- {id: 121, cat: TV/SD, desc: "Serien: SD"}
- {id: 123, cat: TV/Documentary, desc: "Doku: sonstige"}
- {id: 124, cat: Console/Other, desc: "Spiele: sonstige"}
- {id: 125, cat: PC/0day, desc: "Software: Windows"}
- {id: 129, cat: PC/Phone-Other, desc: "Software: Handy / Navi / Sonst"}
- {id: 131, cat: TV/HD, desc: "Serien: HD"}
- {id: 132, cat: TV, desc: "Serien: Packs"}
- {id: 135, cat: Audio, desc: "Musik: Discographie"}
- {id: 138, cat: TV/Documentary, desc: "Doku: HD"}
- {id: 139, cat: TV/Documentary, desc: "Doku: x264"}
- {id: 141, cat: Audio/Audiobook, desc: "A/Ebook: Hoerbook"}
- {id: 142, cat: Books, desc: "A/Ebook: EBooks"}
- {id: 143, cat: Books, desc: "sonstige:PDF"}
- {id: 144, cat: XXX, desc: "Erotik: XXX Pics"}
- {id: 202, cat: TV/Sport, desc: "Sport"}
- {id: 204, cat: XXX, desc: "XXX-Games"}
- {id: 205, cat: Movies/SD, desc: "International-SD"}
- {id: 206, cat: movies/HD, desc: "International-HD"}
modes:
search: [q]
tv-search: [q, season, ep]
movie-search: [q]
login:
path: takelogin.php
method: post
inputs:
username: "{{ .Config.username }}"
password: "{{ .Config.password }}"
test:
path: browse.php
search:
path: browse.php
inputs:
$raw: "{{range .Categories}}c{{.}}=1&{{end}}"
search: "{{ .Query.Keywords }}"
incldead: "1"
orderby: "added"
sort: desc
rows:
selector: table.tableinborder > tbody > tr > td > table.tableinborder > tbody > tr:has(a[href^="details.php"])
fields:
title:
selector: a[href^="details.php"]
banner:
selector: a[href^="details.php"][onmouseover]
attribute: onmouseover
filters:
- name: regexp
args: "<img src=(.*)>')"
category:
selector: a[href^="browse.php?cat="]
attribute: href
filters:
- name: querystring
args: cat
details:
selector: a[href^="details.php"]
attribute: href
comments:
selector: a[href*="&tocomm="]
attribute: href
download:
selector: a[href^="download.php"]
attribute: href
files:
selector: td:nth-child(2) > table > tbody > tr:nth-child(2) > td:nth-child(1) > b:nth-child(2)
grabs:
selector: td:nth-child(2) > table > tbody > tr:nth-child(2) > td:nth-child(3) > b:nth-child(1)
size:
selector: td:nth-child(2) > table > tbody > tr:nth-child(2) > td:nth-child(1) > b:nth-child(1)
filters:
- name: replace
args: [".", ""]
- name: replace
args: [",", "."]
seeders:
selector: td:nth-child(2) > table > tbody > tr:nth-child(2) > td:nth-child(2) > b:nth-child(1)
leechers:
selector: td:nth-child(2) > table > tbody > tr:nth-child(2) > td:nth-child(2) > b:nth-child(3)
date:
selector: td:nth-child(2) > table > tbody > tr:nth-child(2) > td:nth-child(5)
filters:
- name: append
args: " +2:00"
- name: dateparse
args: "02.01.2006 15:04:05 -07:00"
downloadvolumefactor:
case:
img[title="OnlyUp"]: "0"
"*": "1"
uploadvolumefactor:
case:
"*": "1"

37
src/Jackett/Definitions/t411v2.yml Normal file → Executable file
View File

@@ -2,14 +2,21 @@
site: t411v2
name: t411 v2
language: fr-fr
type: semi-private
type: public
encoding: UTF-8
links:
- https://t411.si
caps:
categorymappings:
- {id: 1, cat: Movies}
- {id: 2, cat: TV}
- {id: 1, cat: Movies, desc: Films}
- {id: 2, cat: TV, desc: Séries}
- {id: 3, cat: TV/Anime, desc: Animes}
- {id: 4, cat: Audio, desc: Musique}
- {id: 5, cat: Books, desc: Ebooks}
- {id: 6, cat: PC/0day, desc: Logiciels}
- {id: 7, cat: PC/Games, desc: Jeux}
- {id: 8, cat: TV/Documentary, desc: Documentaires}
- {id: 9, cat: XXX, desc: XXX}
modes:
search: [q]
tv-search: [q, season, ep]
@@ -21,17 +28,23 @@
search:
path: /torrents/search/?search={{ .Keywords}}
rows:
selector: div.isItem
selector: tr.isItem.isItemDesk
fields:
category:
selector: td.m-cat > a
attribute: href
filters:
- name: querystring
args: category
site_date:
selector: div.gname a
selector: td.m-name > a
filters:
# date is at the end of the title, so we get it and name it
# site_date
- name: regexp
args: "(\\w+)$"
title:
selector: div.gname a
selector: td.m-name > a
filters:
# now we put the date at the right place according scene
# naming rules using .Result.site_date
@@ -45,13 +58,13 @@
- name: re_replace
args: ["(\\w+)$", ""]
details:
selector: div.gname a
selector: td.m-name > a
attribute: href
download:
selector: div.gname a
selector: td.m-name > a
attribute: href
size:
selector: div.gsmall:nth-child(5) span
selector: td.m-taille > span
filters:
- name: re_replace
args: [ "\\.(\\w+) K", "$1X00"]
@@ -68,19 +81,19 @@
seeders:
text: 0
seeders:
selector: div.gsmall:nth-child(6)
selector: td.m-seeders > span
optional: true
leechers:
text: 0
leechers:
selector: div.gsmall:nth-child(7)
selector: td.m-leechers > span
optional: true
downloadvolumefactor:
text: "0"
uploadvolumefactor:
text: "1"
date:
selector: div.gsmall:nth-child(4) span
selector: td.m-age > span
filters:
- name: replace
args: [ " jours", " days"]

View File

@@ -71,6 +71,9 @@
keywords: "{{ .Keywords }}"
search_type: "t_name"
include_dead_torrents: "yes"
keywordsfilters:
- name: re_replace
args: ["[^a-zA-Z0-9]+", "%"]
rows:
selector: table#sortabletable > tbody > tr:has(a[href])
fields:

View File

@@ -110,9 +110,6 @@
test:
path: index.php
download:
selector: a[href^="download.php?id="]
search:
path: browse.php
inputs:
@@ -130,11 +127,8 @@
title:
selector: td:nth-child(2)
download:
selector: a[href^="/details.php?id="]
selector: a[href^="/download.php/"]
attribute: href
filters:
- name: replace
args: ["/details.php?id=", "/download.php?id="]
details:
selector: a[href^="/details.php?id="]
attribute: href

View File

@@ -43,6 +43,10 @@
- name: password
type: password
label: Password
- name: filter_title
type: checkbox
label: Try to normalize releases names by moving year after the title
default: false
login:
path: "/user/login"
method: post
@@ -93,8 +97,23 @@
args: [ " an", " year"]
- name: append
args: " ago"
title:
title_normal:
selector: "a.torrent-name"
title_filtered:
selector: "a.torrent-name"
filters:
- name: re_replace
args: ["(?i)^(?:(.+?)((?:[\\.\\-\\s_\\[]+(?:imax|(?:dvd|bd|tv)(?:rip|scr)|bluray(?:\\-?rip)?|720\\s*p?|1080\\s*p?|vof?|vost(?:fr)?|multi|vf(?:f|q)?[1-3]?|(?:true)?french|eng?)[\\.\\-\\s_\\]]*)*)([\\(\\[]?(?:20|1[7-9])\\d{2}[\\)\\]]?)(.*)$|(.*))$", "$1 $3 $2 $4 $5"]
- name: replace
args: [".", " "]
- name: trim
- name: re_replace
args: ["(?i)\\s(mkv|avi|divx|xvid|mp4)$", ""]
- name: re_replace
args: ["(\\s{2,5})", " "]
- name: trim
title:
text: "{{if .Config.filter_title }}{{ .Result.title_filtered }}{{else}}{{ .Result.title_normal }}{{end}}"
details:
selector: "a.torrent-name"
attribute: href

4
src/Jackett/Definitions/zetorrents.yml Normal file → Executable file
View File

@@ -24,7 +24,7 @@
search:
path: "/recherche/{{ .Query.Keywords }}"
rows:
selector: div.content-list-torrent > table tbody tr
selector: div.content-list-torrent > table tbody tr:has(a)
fields:
site_date:
selector: td:nth-child(1) a
@@ -85,4 +85,4 @@
downloadvolumefactor:
text: "0"
uploadvolumefactor:
text: "1"
text: "1"

View File

@@ -0,0 +1,30 @@
using Jackett.Indexers;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Jackett
{
class IndexerException : Exception
{
public IIndexer Indexer { get; protected set; }
public IndexerException(IIndexer Indexer, string message, Exception innerException)
: base(message, innerException)
{
this.Indexer = Indexer;
}
public IndexerException(IIndexer Indexer, string message)
: this(Indexer, message, null)
{
}
public IndexerException(IIndexer Indexer, Exception innerException)
: this(Indexer, "Exception (" + Indexer.ID + "): " + innerException.Message, innerException)
{
}
}
}

View File

@@ -228,7 +228,8 @@ namespace Jackett.Indexers.Abstract
{
release.DownloadVolumeFactor = 0;
}
if ((bool)torrent["isPersonalFreeleech"])
var isPersonalFreeleech = (bool?)torrent["isPersonalFreeleech"];
if (isPersonalFreeleech != null && isPersonalFreeleech == true)
{
release.DownloadVolumeFactor = 0;
}

View File

@@ -219,23 +219,30 @@ namespace Jackett.Indexers
public abstract Task<IndexerConfigurationStatus> ApplyConfiguration(JToken configJson);
public virtual async Task<IEnumerable<ReleaseInfo>> ResultsForQuery(TorznabQuery query)
public virtual async Task<IndexerResult> ResultsForQuery(TorznabQuery query)
{
if (!CanHandleQuery(query))
return new ReleaseInfo[0];
var results = await PerformQuery(query);
results = FilterResults(query, results);
results = results.Select(r =>
try
{
r.Origin = this;
if (!CanHandleQuery(query))
return new IndexerResult(this, new ReleaseInfo[0]);
var results = await PerformQuery(query);
results = FilterResults(query, results);
results = results.Select(r =>
{
r.Origin = this;
// Some trackers do not keep their clocks up to date and can be ~20 minutes out!
if (r.PublishDate > DateTime.Now)
r.PublishDate = DateTime.Now;
return r;
});
// Some trackers do not keep their clocks up to date and can be ~20 minutes out!
if (r.PublishDate > DateTime.Now)
r.PublishDate = DateTime.Now;
return r;
});
return results;
return new IndexerResult(this, results);
}
catch (Exception ex)
{
throw new IndexerException(this, ex);
}
}
protected abstract Task<IEnumerable<ReleaseInfo>> PerformQuery(TorznabQuery query);
}
@@ -667,12 +674,12 @@ namespace Jackett.Indexers
return releases;
}
public override async Task<IEnumerable<ReleaseInfo>> ResultsForQuery(TorznabQuery query)
public override async Task<IndexerResult> ResultsForQuery(TorznabQuery query)
{
var results = await base.ResultsForQuery(query);
results = CleanLinks(results);
var result = await base.ResultsForQuery(query);
result.Releases = CleanLinks(result.Releases);
return results;
return result;
}
protected virtual Uri UncleanLink(Uri link)

View File

@@ -1,234 +0,0 @@
using Jackett.Utils.Clients;
using NLog;
using Jackett.Services;
using Jackett.Utils;
using Jackett.Models;
using System.Threading.Tasks;
using Newtonsoft.Json.Linq;
using System.Collections.Generic;
using CsQuery;
using System;
using System.Globalization;
using Jackett.Models.IndexerConfig;
using System.Collections.Specialized;
using System.Text;
namespace Jackett.Indexers
{
public class BestFriends : BaseWebIndexer
{
string LoginUrl { get { return SiteLink + "login.php"; } }
string TakeLoginUrl { get { return SiteLink + "takelogin.php"; } }
string BrowseUrl { get { return SiteLink + "browse.php"; } }
new ConfigurationDataCaptchaLogin configData
{
get { return (ConfigurationDataCaptchaLogin)base.configData; }
set { base.configData = value; }
}
public BestFriends(IIndexerConfigurationService configService, IWebClient wc, Logger l, IProtectionService ps)
: base(name: "Best Friends",
description: "A German general tracker.",
link: "http://bf.mine.nu/",
caps: TorznabUtil.CreateDefaultTorznabTVCaps(),
configService: configService,
client: wc,
logger: l,
p: ps,
configData: new ConfigurationDataCaptchaLogin())
{
Encoding = Encoding.GetEncoding("iso-8859-1");
Language = "de-de";
Type = "private";
AddCategoryMapping(18, TorznabCatType.TVAnime); // Anime
AddCategoryMapping(8, TorznabCatType.PCMac); // Appz MAC
AddCategoryMapping(9, TorznabCatType.PC); // Appz other
AddCategoryMapping(7, TorznabCatType.PC); // Appz Windows
AddCategoryMapping(23, TorznabCatType.TVDocumentary); // Dokumentationen
AddCategoryMapping(32, TorznabCatType.Movies3D); // DVD 3D
AddCategoryMapping(15, TorznabCatType.Books); // eBooks
AddCategoryMapping(12, TorznabCatType.PCGames); // Games PC
AddCategoryMapping(37, TorznabCatType.PCPhoneOther); // Handy_Mobile
AddCategoryMapping(24, TorznabCatType.TVHD); // HDTV
AddCategoryMapping(22, TorznabCatType.AudioAudiobook); // Hörbücher
AddCategoryMapping(1, TorznabCatType.MoviesHD); // Movies 1080p/1080i
AddCategoryMapping(31, TorznabCatType.Movies3D); // Movies 3D
AddCategoryMapping(2, TorznabCatType.MoviesHD); // Movies 720p/720i
AddCategoryMapping(21, TorznabCatType.MoviesBluRay); // Movies BluRay
AddCategoryMapping(5, TorznabCatType.MoviesDVD); // Movies DVD/HDDVD
AddCategoryMapping(6, TorznabCatType.MoviesSD); // Movies M/SVCD/Other
AddCategoryMapping(4, TorznabCatType.MoviesSD); // Movies XVID/DIVX/h.264
AddCategoryMapping(10, TorznabCatType.Audio); // Music
AddCategoryMapping(25, TorznabCatType.AudioVideo); // Musikvideo
AddCategoryMapping(29, TorznabCatType.ConsoleNDS); // Nintendo DS
AddCategoryMapping(16, TorznabCatType.Other); // other
AddCategoryMapping(13, TorznabCatType.ConsolePS4); // Playstation
AddCategoryMapping(28, TorznabCatType.TVHD); // Serien HD
AddCategoryMapping(11, TorznabCatType.TVSD); // Serien XviD
AddCategoryMapping(33, TorznabCatType.Other); // Specials
AddCategoryMapping(30, TorznabCatType.TVSport); // Sport
AddCategoryMapping(19, TorznabCatType.TVOTHER); // TVRip
AddCategoryMapping(38, TorznabCatType.TVDocumentary); // US Dokus
AddCategoryMapping(20, TorznabCatType.MoviesForeign); // US Movies
AddCategoryMapping(14, TorznabCatType.TVFOREIGN); // US Serien
AddCategoryMapping(36, TorznabCatType.Other); // Wallpaper
AddCategoryMapping(26, TorznabCatType.ConsoleWii); // Wii
AddCategoryMapping(27, TorznabCatType.ConsoleXbox360); // Xbox 360
AddCategoryMapping(3, TorznabCatType.XXX); // XXX
}
public override async Task<ConfigurationData> GetConfigurationForSetup()
{
var loginPage = await RequestStringWithCookies(LoginUrl, string.Empty);
CQ dom = loginPage.Content;
CQ qCaptchaImg = dom.Find("td.tablea > img").First();
var CaptchaUrl = SiteLink + qCaptchaImg.Attr("src");
var captchaImage = await RequestBytesWithCookies(CaptchaUrl, loginPage.Cookies);
configData.CaptchaImage.Value = captchaImage.Content;
configData.CaptchaCookie.Value = loginPage.Cookies;
return configData;
}
public override async Task<IndexerConfigurationStatus> ApplyConfiguration(JToken configJson)
{
LoadValuesFromJson(configJson);
var pairs1 = new Dictionary<string, string>
{
{ "proofcode", configData.CaptchaText.Value }
};
var cookies = configData.CaptchaCookie.Value;
var result1 = await RequestLoginAndFollowRedirect(LoginUrl, pairs1, cookies, true, null, LoginUrl, true);
if(result1.Content == null || !result1.Content.Contains("takelogin.php"))
{
CQ dom = result1.Content;
var errorMessage = dom["#login_error"].Text().Trim();
errorMessage = result1.Content;
throw new ExceptionWithConfigData(errorMessage, configData);
}
var pairs2 = new Dictionary<string, string>
{
{ "username", configData.Username.Value },
{ "password", configData.Password.Value }
};
var result = await RequestLoginAndFollowRedirect(TakeLoginUrl, pairs2, result1.Cookies, true, null, LoginUrl, true);
await ConfigureIfOK(result.Cookies, result.Content != null && result.Content.Contains("logout.php"), () =>
{
CQ dom = result.Content;
var errorMessage = dom["#login_error"].Text().Trim();
errorMessage = result.Content;
throw new ExceptionWithConfigData(errorMessage, configData);
});
return IndexerConfigurationStatus.RequiresTesting;
}
protected override async Task<IEnumerable<ReleaseInfo>> PerformQuery(TorznabQuery query)
{
TimeZoneInfo.TransitionTime startTransition = TimeZoneInfo.TransitionTime.CreateFloatingDateRule(new DateTime(1, 1, 1, 3, 0, 0), 3, 5, DayOfWeek.Sunday);
TimeZoneInfo.TransitionTime endTransition = TimeZoneInfo.TransitionTime.CreateFloatingDateRule(new DateTime(1, 1, 1, 4, 0, 0), 10, 5, DayOfWeek.Sunday);
TimeSpan delta = new TimeSpan(1, 0, 0);
TimeZoneInfo.AdjustmentRule adjustment = TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule(new DateTime(1999, 10, 1), DateTime.MaxValue.Date, delta, startTransition, endTransition);
TimeZoneInfo.AdjustmentRule[] adjustments = { adjustment };
TimeZoneInfo germanyTz = TimeZoneInfo.CreateCustomTimeZone("W. Europe Standard Time", new TimeSpan(1, 0, 0), "(GMT+01:00) W. Europe Standard Time", "W. Europe Standard Time", "W. Europe DST Time", adjustments);
var releases = new List<ReleaseInfo>();
var searchString = query.GetQueryString();
var searchUrl = BrowseUrl;
var queryCollection = new NameValueCollection();
queryCollection.Add("showsearch", "1");
queryCollection.Add("incldead", "1");
queryCollection.Add("blah", "0");
queryCollection.Add("orderby", "added");
queryCollection.Add("sort", "desc");
if (!string.IsNullOrWhiteSpace(searchString))
{
queryCollection.Add("search", searchString);
}
foreach (var cat in MapTorznabCapsToTrackers(query))
{
queryCollection.Add("c" + cat, "1");
}
searchUrl += "?" + queryCollection.GetQueryString();
var response = await RequestStringWithCookiesAndRetry(searchUrl, null, BrowseUrl);
var results = response.Content;
try
{
CQ dom = results;
var rows = dom["table.tableinborder > tbody > tr:has(td.tableb)"];
foreach (var row in rows)
{
var release = new ReleaseInfo();
release.MinimumRatio = 0.75;
release.MinimumSeedTime = 0;
var qRow = row.Cq();
var qDetailsLink = qRow.Find("a[href^=details.php?id=]").First();
release.Title = qDetailsLink.Attr("title");
if (!query.MatchQueryStringAND(release.Title))
continue;
var qCatLink = qRow.Find("a[href^=browse.php?cat=]").First();
// use negative indexes as if a user has "Wartezeit" there's an extra column after the title
var qSeeders = qRow.Find("td:nth-last-child(4)");
var qLeechers = qRow.Find("td:nth-last-child(3)");
var qDateStr = qRow.Find("td:nth-last-child(7)");
var qSize = qRow.Find("td:nth-last-child(6)");
var torrentId = qDetailsLink.Attr("href").Replace("&hit=1", "").Split('=')[1];
var catStr = qCatLink.Attr("href").Split('=')[1];
release.Category = MapTrackerCatToNewznab(catStr);
release.Link = new Uri(SiteLink + "download.php?torrent="+torrentId);
release.Comments = new Uri(SiteLink + qDetailsLink.Attr("href"));
release.Guid = release.Link;
var sizeStr = qSize.Text();
release.Size = ReleaseInfo.GetBytes(sizeStr.Replace(",", "."));
release.Seeders = ParseUtil.CoerceInt(qSeeders.Text());
release.Peers = ParseUtil.CoerceInt(qLeechers.Text()) + release.Seeders;
var dateStr = qDateStr.Text();
var dateGerman = DateTime.SpecifyKind(DateTime.ParseExact(dateStr, "dd.MM.yyyyHH:mm:ss", CultureInfo.InvariantCulture), DateTimeKind.Unspecified);
DateTime pubDateUtc = TimeZoneInfo.ConvertTimeToUtc(dateGerman, germanyTz);
release.PublishDate = pubDateUtc;
var files = qRow.Find("td:nth-last-child(9)").Text();
release.Files = ParseUtil.CoerceInt(files);
var grabs = qRow.Find("td:nth-last-child(5)").Text();
release.Grabs = ParseUtil.CoerceInt(grabs);
if (qRow.Find("font[color=\"red\"]:contains(OnlyUp)").Length >= 1)
release.DownloadVolumeFactor = 0;
else
release.DownloadVolumeFactor = 1;
release.UploadVolumeFactor = 1;
releases.Add(release);
}
}
catch (Exception ex)
{
OnParseError(results, ex);
}
return releases;
}
}
}

View File

@@ -27,9 +27,9 @@ namespace Jackett.Indexers
public BroadcastTheNet(IIndexerConfigurationService configService, IWebClient wc, Logger l, IProtectionService ps)
: base(name: "BroadcastTheNet",
description: "Needs no description..",
description: null,
link: "https://broadcasthe.net/",
caps: TorznabUtil.CreateDefaultTorznabTVCaps(),
caps: new TorznabCapabilities(),
configService: configService,
client: wc,
logger: l,
@@ -39,6 +39,16 @@ namespace Jackett.Indexers
Encoding = Encoding.UTF8;
Language = "en-us";
Type = "private";
TorznabCaps.LimitsDefault = 100;
TorznabCaps.LimitsMax = 1000;
AddCategoryMapping("SD", TorznabCatType.TVSD, "SD");
AddCategoryMapping("720p", TorznabCatType.TVHD, "720p");
AddCategoryMapping("1080p", TorznabCatType.TVHD, "1080p");
AddCategoryMapping("1080i", TorznabCatType.TVHD, "1080i");
AddCategoryMapping("2160p", TorznabCatType.TVHD, "2160p");
AddCategoryMapping("Portable Device", TorznabCatType.TVSD, "Portable Device");
}
public override async Task<IndexerConfigurationStatus> ApplyConfiguration(JToken configJson)
@@ -76,13 +86,17 @@ namespace Jackett.Indexers
protected override async Task<IEnumerable<ReleaseInfo>> PerformQuery(TorznabQuery query)
{
var searchString = query.GetQueryString();
var btnResults = query.Limit;
if (btnResults == 0)
btnResults = (int)TorznabCaps.LimitsDefault;
var btnOffset = query.Offset;
var releases = new List<ReleaseInfo>();
var parameters = new JArray();
parameters.Add(new JValue(configData.Key.Value));
parameters.Add(new JValue(searchString.Trim()));
parameters.Add(new JValue(100));
parameters.Add(new JValue(0));
parameters.Add(new JValue(btnResults));
parameters.Add(new JValue(btnOffset));
var response = await PostDataWithCookiesAndRetry(APIBASE, null, null, null, new Dictionary<string, string>()
{
{ "Accept", "application/json-rpc, application/json"},
@@ -93,17 +107,19 @@ namespace Jackett.Indexers
{
var btnResponse = JsonConvert.DeserializeObject<BTNRPCResponse>(response.Content);
if (btnResponse != null && btnResponse.Result != null)
if (btnResponse != null && btnResponse.Result != null && btnResponse.Result.Torrents != null)
{
foreach (var itemKey in btnResponse.Result.Torrents)
{
var descriptions = new List<string>();
var btnResult = itemKey.Value;
var item = new ReleaseInfo();
if (!string.IsNullOrEmpty(btnResult.SeriesBanner))
item.BannerUrl = new Uri(btnResult.SeriesBanner);
item.Category = new List<int> { TorznabCatType.TV.ID };
item.Comments = new Uri($"https://broadcasthe.net/torrents.php?id={btnResult.GroupID}&torrentid={btnResult.TorrentID}");
item.Description = btnResult.ReleaseName;
item.Category = MapTrackerCatToNewznab(btnResult.Resolution);
if (item.Category.Count == 0) // default to TV
item.Category.Add(TorznabCatType.TV.ID);
item.Comments = new Uri($"{SiteLink}torrents.php?id={btnResult.GroupID}&torrentid={btnResult.TorrentID}");
item.Guid = new Uri(btnResult.DownloadURL);
if (!string.IsNullOrWhiteSpace(btnResult.ImdbID))
item.Imdb = ParseUtil.CoerceLong(btnResult.ImdbID);
@@ -116,6 +132,29 @@ namespace Jackett.Indexers
item.Size = btnResult.Size;
item.TVDBId = btnResult.TvdbID;
item.Title = btnResult.ReleaseName;
item.UploadVolumeFactor = 1;
item.DownloadVolumeFactor = 0; // ratioless
item.Grabs = btnResult.Snatched;
if (!string.IsNullOrWhiteSpace(btnResult.Series))
descriptions.Add("Series: " + btnResult.Series);
if (!string.IsNullOrWhiteSpace(btnResult.GroupName))
descriptions.Add("Group Name: " + btnResult.GroupName);
if (!string.IsNullOrWhiteSpace(btnResult.Source))
descriptions.Add("Source: " + btnResult.Source);
if (!string.IsNullOrWhiteSpace(btnResult.Container))
descriptions.Add("Container: " + btnResult.Container);
if (!string.IsNullOrWhiteSpace(btnResult.Codec))
descriptions.Add("Codec: " + btnResult.Codec);
if (!string.IsNullOrWhiteSpace(btnResult.Resolution))
descriptions.Add("Resolution: " + btnResult.Resolution);
if (!string.IsNullOrWhiteSpace(btnResult.Origin))
descriptions.Add("Origin: " + btnResult.Origin);
if (!string.IsNullOrWhiteSpace(btnResult.Series))
descriptions.Add("Youtube Trailer: <a href=\"" + btnResult.YoutubeTrailer + "\">" + btnResult.YoutubeTrailer + "</a>");
item.Description = string.Join("<br />\n", descriptions);
releases.Add(item);
}
}

View File

@@ -106,6 +106,10 @@ namespace Jackett.Indexers
{
// ex: "Monday, Jun 01, 2015", "Monday, Aug 03, 2015"
var dateStr = rowA.Cq().Text().Trim().Replace("Added on ", "");
if (string.IsNullOrWhiteSpace(dateStr) || dateStr == "Sponsored links" || dateStr.StartsWith("!function")) // ignore ads
{
continue;
}
if (dateStr.ToLowerInvariant().Contains("today"))
lastDateTime = DateTime.Now;
else

View File

@@ -90,50 +90,53 @@ namespace Jackett.Indexers
{
//var json = JArray.Parse(results.Content);
dynamic json = JsonConvert.DeserializeObject<dynamic>(results.Content);
foreach (var row in json)
{
var release = new ReleaseInfo();
var descriptions = new List<string>();
var tags = new List<string>();
release.MinimumRatio = 0.5;
release.MinimumSeedTime = 0;
release.Title = row.name;
release.Category = new List<int> { TorznabCatType.Audio.ID };
release.Size = row.size;
release.Seeders = row.seeders;
release.Peers = row.leechers + release.Seeders;
release.PublishDate = DateTime.ParseExact(row.added.ToString() + " +01:00", "yyyy-MM-dd HH:mm:ss zzz", CultureInfo.InvariantCulture);
release.Files = row.numfiles;
release.Grabs = row.times_completed;
release.Comments = new Uri(SiteLink + "torrent/" + row.id.ToString() + "/");
release.Link = new Uri(SiteLink + "api/v1/torrents/download/" + row.id.ToString());
if (row.frileech == 1)
release.DownloadVolumeFactor = 0;
else
release.DownloadVolumeFactor = 0.33;
release.UploadVolumeFactor = 1;
if ((int)row.p2p == 1)
tags.Add("P2P");
if ((int)row.pack == 1)
tags.Add("Pack");
if ((int)row.reqid != 0)
tags.Add("Archive");
if ((int)row.flac != 0)
if (json != null) // no results
{
foreach (var row in json)
{
tags.Add("FLAC");
release.Category = new List<int> { TorznabCatType.AudioLossless.ID };
var release = new ReleaseInfo();
var descriptions = new List<string>();
var tags = new List<string>();
release.MinimumRatio = 0.5;
release.MinimumSeedTime = 0;
release.Title = row.name;
release.Category = new List<int> { TorznabCatType.Audio.ID };
release.Size = row.size;
release.Seeders = row.seeders;
release.Peers = row.leechers + release.Seeders;
release.PublishDate = DateTime.ParseExact(row.added.ToString() + " +01:00", "yyyy-MM-dd HH:mm:ss zzz", CultureInfo.InvariantCulture);
release.Files = row.numfiles;
release.Grabs = row.times_completed;
release.Comments = new Uri(SiteLink + "torrent/" + row.id.ToString() + "/");
release.Link = new Uri(SiteLink + "api/v1/torrents/download/" + row.id.ToString());
if (row.frileech == 1)
release.DownloadVolumeFactor = 0;
else
release.DownloadVolumeFactor = 0.33;
release.UploadVolumeFactor = 1;
if ((int)row.p2p == 1)
tags.Add("P2P");
if ((int)row.pack == 1)
tags.Add("Pack");
if ((int)row.reqid != 0)
tags.Add("Archive");
if ((int)row.flac != 0)
{
tags.Add("FLAC");
release.Category = new List<int> { TorznabCatType.AudioLossless.ID };
}
if (tags.Count > 0)
descriptions.Add("Tags: " + string.Join(", ", tags));
release.Description = string.Join("<br>\n", descriptions);
releases.Add(release);
}
if (tags.Count > 0)
descriptions.Add("Tags: " + string.Join(", ", tags));
release.Description = string.Join("<br>\n", descriptions);
releases.Add(release);
}
}
catch (Exception ex)

View File

@@ -151,8 +151,11 @@ namespace Jackett.Indexers
var cat = catUrl.Substring(catUrl.LastIndexOf('[') + 1).Trim(']');
release.Category = MapTrackerCatToNewznab(cat);
// support both date format (profile settings)
var qAdded = row.ChildElements.ElementAt(4).ChildElements.ElementAt(0).Cq();
var addedStr = qAdded.Attr("title");
if (!addedStr.Contains(","))
addedStr = qAdded.Text();
release.PublishDate = DateTime.ParseExact(addedStr, "MMM dd yyyy, HH:mm", CultureInfo.InvariantCulture);
var overlayScript = qRow.Find("script:contains(\"var overlay\")").Text();

View File

@@ -10,6 +10,18 @@ using System.Web.UI.WebControls;
namespace Jackett.Indexers
{
public class IndexerResult
{
public IIndexer Indexer { get; set; }
public IEnumerable<ReleaseInfo> Releases { get; set; }
public IndexerResult(IIndexer Indexer, IEnumerable<ReleaseInfo> Releases)
{
this.Indexer = Indexer;
this.Releases = Releases;
}
}
public interface IIndexer
{
string SiteLink { get; }
@@ -39,7 +51,7 @@ namespace Jackett.Indexers
void Unconfigure();
Task<IEnumerable<ReleaseInfo>> ResultsForQuery(TorznabQuery query);
Task<IndexerResult> ResultsForQuery(TorznabQuery query);
bool CanHandleQuery(TorznabQuery query);
}

View File

@@ -115,7 +115,7 @@ namespace Jackett.Indexers
{
CQ dom = results.Content;
var rows = dom["#sortabletable tr"];
var rows = dom["#sortabletable tr:has(a[href*=\"details.php?id=\"])"];
foreach (var row in rows.Skip(1))
{
var release = new ReleaseInfo();

View File

@@ -27,25 +27,32 @@ namespace Jackett.Indexers.Meta
return Task.FromResult(IndexerConfigurationStatus.Completed);
}
public override async Task<IEnumerable<ReleaseInfo>> ResultsForQuery(TorznabQuery query)
public override async Task<IndexerResult> ResultsForQuery(TorznabQuery query)
{
if (!CanHandleQuery(query))
return new ReleaseInfo[0];
var results = await PerformQuery(query);
var correctedResults = results.Select(r =>
try
{
if (r.PublishDate > DateTime.Now)
r.PublishDate = DateTime.Now;
return r;
});
if (!CanHandleQuery(query))
return new IndexerResult(this, new ReleaseInfo[0]);
var results = await PerformQuery(query);
var correctedResults = results.Select(r =>
{
if (r.PublishDate > DateTime.Now)
r.PublishDate = DateTime.Now;
return r;
});
return correctedResults;
return new IndexerResult(this, correctedResults);
}
catch (Exception ex)
{
throw new IndexerException(this, ex);
}
}
protected override async Task<IEnumerable<ReleaseInfo>> PerformQuery(TorznabQuery query)
{
var indexers = validIndexers;
IEnumerable<Task<IEnumerable<ReleaseInfo>>> supportedTasks = indexers.Where(i => i.CanHandleQuery(query)).Select(i => i.ResultsForQuery(query)).ToList(); // explicit conversion to List to execute LINQ query
IEnumerable<Task<IndexerResult>> supportedTasks = indexers.Where(i => i.CanHandleQuery(query)).Select(i => i.ResultsForQuery(query)).ToList(); // explicit conversion to List to execute LINQ query
var fallbackStrategies = fallbackStrategyProvider.FallbackStrategiesForQuery(query);
var fallbackQueries = fallbackStrategies.Select(async f => await f.FallbackQueries()).SelectMany(t => t.Result);
@@ -72,7 +79,7 @@ namespace Jackett.Indexers.Meta
logger.Error(aggregateTask.Exception, "Error during request in metaindexer " + ID);
}
var unorderedResult = aggregateTask.Result.Flatten();
var unorderedResult = aggregateTask.Result.Select(r => r.Releases).Flatten();
var resultFilters = resultFilterProvider.FiltersForQuery(query);
var filteredResults = resultFilters.Select(async f => await f.FilterResults(unorderedResult)).SelectMany(t => t.Result);
var uniqueFilteredResults = filteredResults.Distinct();

View File

@@ -16,6 +16,7 @@ using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using NLog;
using System.Text;
using System.IO;
namespace Jackett.Indexers
{
@@ -33,7 +34,7 @@ namespace Jackett.Indexers
private bool Latency => ConfigData.Latency.Value;
private bool DevMode => ConfigData.DevMode.Value;
private bool CacheMode => ConfigData.HardDriveCache.Value;
private static string Directory => System.IO.Path.GetTempPath() + "Jackett\\" + MethodBase.GetCurrentMethod().DeclaringType?.Name + "\\";
private static string Directory => Path.Combine(Path.GetTempPath(), "Jackett", MethodBase.GetCurrentMethod().DeclaringType?.Name);
private readonly Dictionary<string, string> _emulatedBrowserHeaders = new Dictionary<string, string>();
private CQ _fDom;
@@ -49,7 +50,6 @@ namespace Jackett.Indexers
client: w,
logger: l,
p: ps,
downloadBase: "https://norbits.net/download.php?id=",
configData: new ConfigurationDataNorbits())
{
Encoding = Encoding.GetEncoding("iso-8859-1");

View File

@@ -129,8 +129,7 @@ namespace Jackett.Indexers
release.MinimumRatio = 1;
release.MinimumSeedTime = 129600;
release.Title = qRow.Find(".ttr_name > a").Text();
release.Description = release.Title;
release.Title = qRow.Find(".ttr_name > a").Attr("title");
release.Guid = new Uri(SiteLink + qRow.Find(".ttr_name > a").Attr("href"));
release.Comments = release.Guid;
release.Link = new Uri(SiteLink + qRow.Find(".td_dl > a").Attr("href"));

View File

@@ -6,19 +6,24 @@ using Jackett.Models;
using System.Threading.Tasks;
using Newtonsoft.Json.Linq;
using System.Collections.Generic;
using CsQuery;
using System;
using System.Globalization;
using Jackett.Models.IndexerConfig;
using System.Collections.Specialized;
using System.Text;
using Newtonsoft.Json;
using static Jackett.Models.IndexerConfig.ConfigurationData;
namespace Jackett.Indexers
{
public class TorrentNetwork : BaseWebIndexer
{
string LoginUrl { get { return SiteLink + "takelogin.php"; } }
string BrowseUrl { get { return SiteLink + "browse.php"; } }
string APIUrl { get { return SiteLink + "api/"; } }
private string passkey;
private Dictionary<string, string> APIHeaders = new Dictionary<string, string>()
{
{"Content-Type", "application/json"},
};
new ConfigurationDataBasicLoginWithRSSAndDisplay configData
{
@@ -28,9 +33,9 @@ namespace Jackett.Indexers
public TorrentNetwork(IIndexerConfigurationService configService, IWebClient wc, Logger l, IProtectionService ps)
: base(name: "Torrent Network",
description: "A German general tracker.",
description: null,
link: "https://tntracker.org/",
caps: TorznabUtil.CreateDefaultTorznabTVCaps(),
caps: new TorznabCapabilities(),
configService: configService,
client: wc,
logger: l,
@@ -41,51 +46,93 @@ namespace Jackett.Indexers
Language = "de-de";
Type = "private";
AddCategoryMapping(1, TorznabCatType.AudioAudiobook); // aBook
AddCategoryMapping(4, TorznabCatType.PCMac); // App|Mac
AddCategoryMapping(5, TorznabCatType.PC); // App|Win
AddCategoryMapping(7, TorznabCatType.TVDocumentary); // Docu|HD
AddCategoryMapping(6, TorznabCatType.TVDocumentary); // Docu|SD
AddCategoryMapping(8, TorznabCatType.Books); // eBook
AddCategoryMapping(10, TorznabCatType.PCGames); // Game|PC
AddCategoryMapping(13, TorznabCatType.ConsolePS4); // Game|PSX
AddCategoryMapping(12, TorznabCatType.ConsoleWii); // Game|Wii
AddCategoryMapping(14, TorznabCatType.ConsoleXbox); // Game|XBOX
AddCategoryMapping(30, TorznabCatType.Other); // Misc
AddCategoryMapping(17, TorznabCatType.MoviesHD); // Movie|DE|1080p
AddCategoryMapping(20, TorznabCatType.MoviesHD); // Movie|DE|2160p
AddCategoryMapping(36, TorznabCatType.Movies3D); // Movie|DE|3D
AddCategoryMapping(18, TorznabCatType.MoviesHD); // Movie|DE|720p
AddCategoryMapping(34, TorznabCatType.TVAnime); // Movie|DE|Anime
AddCategoryMapping(19, TorznabCatType.MoviesBluRay); // Movie|DE|BluRay
AddCategoryMapping(45, TorznabCatType.Movies); // Movie|DE|Remux
AddCategoryMapping(24, TorznabCatType.MoviesSD); // Movie|DE|SD
AddCategoryMapping(39, TorznabCatType.Movies); // Movie|EN/JP|Anime
AddCategoryMapping(43, TorznabCatType.MoviesHD); // Movie|EN|1080p
AddCategoryMapping(37, TorznabCatType.MoviesHD); // Movie|EN|2160p
AddCategoryMapping(35, TorznabCatType.MoviesHD); // Movie|EN|720p
AddCategoryMapping(38, TorznabCatType.MoviesBluRay); // Movie|EN|BluRay
AddCategoryMapping(46, TorznabCatType.Movies); // Movie|EN|Remux
AddCategoryMapping(22, TorznabCatType.MoviesSD); // Movie|EN|SD
AddCategoryMapping(44, TorznabCatType.AudioLossless); // Music|Flac
AddCategoryMapping(25, TorznabCatType.AudioMP3); // Music|MP3
AddCategoryMapping(26, TorznabCatType.AudioVideo); // Music|Video
AddCategoryMapping(31, TorznabCatType.TVSport); // Sport
AddCategoryMapping(2, TorznabCatType.TVAnime); // TV|DE|Anime
AddCategoryMapping(28, TorznabCatType.TVHD); // TV|DE|HD
AddCategoryMapping(16, TorznabCatType.TV); // TV|DE|Pack
AddCategoryMapping(27, TorznabCatType.TVSD); // TV|DE|SD
AddCategoryMapping(41, TorznabCatType.TVAnime); // TV|EN/JP|Anime
AddCategoryMapping(40, TorznabCatType.TVHD); // TV|EN|HD
AddCategoryMapping(42, TorznabCatType.TV); // TV|EN|Pack
AddCategoryMapping(29, TorznabCatType.TVSD); // TV|EN|SD
AddCategoryMapping(33, TorznabCatType.XXX); // XXX|HD
AddCategoryMapping(32, TorznabCatType.XXX); // XXX|SD
configData.AddDynamic("token", new HiddenItem() { Name = "token" });
configData.AddDynamic("passkey", new HiddenItem() { Name = "passkey" });
AddCategoryMapping(24, TorznabCatType.MoviesSD, "Movies GER/SD");
AddCategoryMapping(18, TorznabCatType.MoviesHD, "Movies GER/720p");
AddCategoryMapping(17, TorznabCatType.MoviesHD, "Movies GER/1080p");
AddCategoryMapping(20, TorznabCatType.MoviesHD, "Movies GER/2160p");
AddCategoryMapping(45, TorznabCatType.MoviesOther, "Movies GER/Remux");
AddCategoryMapping(19, TorznabCatType.MoviesBluRay, "Movies GER/BluRay");
AddCategoryMapping(34, TorznabCatType.TVAnime, "Movies GER/Anime");
AddCategoryMapping(36, TorznabCatType.Movies3D, "Movies GER/3D");
AddCategoryMapping(22, TorznabCatType.MoviesSD, "Movies ENG/SD");
AddCategoryMapping(35, TorznabCatType.MoviesHD, "Movies ENG/720p");
AddCategoryMapping(43, TorznabCatType.MoviesHD, "Movies ENG/1080p");
AddCategoryMapping(37, TorznabCatType.MoviesHD, "Movies ENG/2160p");
AddCategoryMapping(46, TorznabCatType.MoviesOther, "Movies ENG/Remux");
AddCategoryMapping(38, TorznabCatType.MoviesBluRay, "Movies ENG/BluRay");
AddCategoryMapping(39, TorznabCatType.TVAnime, "Movies ENG/Anime");
AddCategoryMapping(27, TorznabCatType.TVSD, "Series GER/SD");
AddCategoryMapping(28, TorznabCatType.TVHD, "Series GER/HD");
AddCategoryMapping(2, TorznabCatType.TVAnime, "Series GER/Anime");
AddCategoryMapping(16, TorznabCatType.TV, "Series GER/Pack");
AddCategoryMapping(6, TorznabCatType.TVDocumentary, "Docu/SD");
AddCategoryMapping(7, TorznabCatType.TVDocumentary, "Docu/HD");
AddCategoryMapping(29, TorznabCatType.TVSD, "Series ENG/SD");
AddCategoryMapping(40, TorznabCatType.TVHD, "Series ENG/HD");
AddCategoryMapping(41, TorznabCatType.TVAnime, "Series ENG/Anime");
AddCategoryMapping(42, TorznabCatType.TV, "Series ENG/Pack");
AddCategoryMapping(31, TorznabCatType.TVSport, "Sport");
AddCategoryMapping(10, TorznabCatType.PCGames, "Games/Win");
AddCategoryMapping(12, TorznabCatType.ConsoleWii, "Games/Wii");
AddCategoryMapping(13, TorznabCatType.ConsolePS4, "Games/PSX");
AddCategoryMapping(14, TorznabCatType.ConsoleXbox, "Games/XBOX");
AddCategoryMapping(4, TorznabCatType.PCMac, "Apps/Mac");
AddCategoryMapping(5, TorznabCatType.PC0day, "Apps/Win");
AddCategoryMapping(1, TorznabCatType.AudioAudiobook, "Misc/aBook");
AddCategoryMapping(8, TorznabCatType.Books, "Misc/eBook");
AddCategoryMapping(30, TorznabCatType.Other, "Misc/Sonstiges");
AddCategoryMapping(44, TorznabCatType.AudioLossless, "Musik/Flac");
AddCategoryMapping(25, TorznabCatType.AudioMP3, "Musik/MP3");
AddCategoryMapping(26, TorznabCatType.AudioVideo, "Musik/Video");
AddCategoryMapping(32, TorznabCatType.XXX, "XXX/XXX");
AddCategoryMapping(33, TorznabCatType.XXX, "XXX/XXX|HD");
}
public override void LoadValuesFromJson(JToken jsonConfig, bool useProtectionService = false)
{
base.LoadValuesFromJson(jsonConfig, useProtectionService);
var tokenItem = (HiddenItem)configData.GetDynamic("token");
if (tokenItem != null)
{
var token = tokenItem.Value;
if (!string.IsNullOrWhiteSpace(token))
APIHeaders["Authorization"] = token;
}
var passkeyItem = (HiddenItem)configData.GetDynamic("passkey");
if (passkeyItem != null)
{
passkey = passkeyItem.Value;
}
}
private async Task<dynamic> SendAPIRequest(string endpoint, object data)
{
var jsonData = JsonConvert.SerializeObject(data);
var result = await PostDataWithCookies(APIUrl + endpoint, null, null, SiteLink, APIHeaders, jsonData);
if (!result.Content.StartsWith("{")) // not JSON => error
throw new ExceptionWithConfigData(result.Content, configData);
dynamic json = JsonConvert.DeserializeObject<dynamic>(result.Content);
return json;
}
public override async Task<IndexerConfigurationStatus> ApplyConfiguration(JToken configJson)
{
LoadValuesFromJson(configJson);
APIHeaders.Remove("Authorization"); // remove any token from the headers
var pairs = new Dictionary<string, string>
{
@@ -93,113 +140,100 @@ namespace Jackett.Indexers
{ "password", configData.Password.Value }
};
var result = await RequestLoginAndFollowRedirect(LoginUrl, pairs, null, true, null, LoginUrl, true);
await ConfigureIfOK(result.Cookies, result.Content != null && result.Content.Contains("logout.php"), () =>
var json = await SendAPIRequest("auth", pairs);
string token = json.token;
APIHeaders["Authorization"] = token;
var curuser = await SendAPIRequest("curuser", null);
var passkeyItem = (HiddenItem)configData.GetDynamic("passkey");
passkeyItem.Value = curuser.passkey;
var tokenItem = (HiddenItem)configData.GetDynamic("token");
tokenItem.Value = token;
await ConfigureIfOK("", token.Length > 0, () =>
{
CQ dom = result.Content;
var errorMessage = dom["table.tableinborder"].Html();
errorMessage = result.Content;
throw new ExceptionWithConfigData(errorMessage, configData);
throw new ExceptionWithConfigData(json.ToString(), configData);
});
return IndexerConfigurationStatus.RequiresTesting;
}
protected override async Task<IEnumerable<ReleaseInfo>> PerformQuery(TorznabQuery query)
{
TimeZoneInfo.TransitionTime startTransition = TimeZoneInfo.TransitionTime.CreateFloatingDateRule(new DateTime(1, 1, 1, 3, 0, 0), 3, 5, DayOfWeek.Sunday);
TimeZoneInfo.TransitionTime endTransition = TimeZoneInfo.TransitionTime.CreateFloatingDateRule(new DateTime(1, 1, 1, 4, 0, 0), 10, 5, DayOfWeek.Sunday);
TimeSpan delta = new TimeSpan(1, 0, 0);
TimeZoneInfo.AdjustmentRule adjustment = TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule(new DateTime(1999, 10, 1), DateTime.MaxValue.Date, delta, startTransition, endTransition);
TimeZoneInfo.AdjustmentRule[] adjustments = { adjustment };
TimeZoneInfo germanyTz = TimeZoneInfo.CreateCustomTimeZone("W. Europe Standard Time", new TimeSpan(1, 0, 0), "(GMT+01:00) W. Europe Standard Time", "W. Europe Standard Time", "W. Europe DST Time", adjustments);
var releases = new List<ReleaseInfo>();
var searchUrl = "browse";
var searchString = query.GetQueryString();
var searchUrl = BrowseUrl;
var queryCollection = new NameValueCollection();
queryCollection.Add("incldead", "1");
queryCollection.Add("_by", "0");
queryCollection.Add("sort", "4");
queryCollection.Add("type", "desc");
queryCollection.Add("orderC", "4");
queryCollection.Add("orderD", "desc");
queryCollection.Add("start", "0");
queryCollection.Add("length", "100");
if (!string.IsNullOrWhiteSpace(searchString))
{
queryCollection.Add("search", searchString);
}
foreach (var cat in MapTorznabCapsToTrackers(query))
{
queryCollection.Add("c" + cat, "1");
}
var cats = MapTorznabCapsToTrackers(query);
if (cats.Count > 0)
queryCollection.Add("cats", string.Join(",", cats));
searchUrl += "?" + queryCollection.GetQueryString();
var response = await RequestStringWithCookies(searchUrl);
var results = response.Content;
var result = await SendAPIRequest(searchUrl, null);
try
{
CQ dom = results;
var rows = dom["table[border=1] > tbody > tr:has(td.torrenttable)"];
if (result["error"] != null)
throw new Exception(result["error"].ToString());
foreach (var row in rows)
var data = (JArray)result.data;
foreach (JArray torrent in data)
{
var release = new ReleaseInfo();
release.MinimumRatio = 0.8;
release.MinimumSeedTime = 48 * 60 * 60;
var qRow = row.Cq();
release.Category = MapTrackerCatToNewznab(torrent[0].ToString());
release.Title = torrent[1].ToString();
var torrentID = (long)torrent[2];
release.Comments = new Uri(SiteLink + "torrent/" + torrentID);
release.Guid = release.Comments;
release.Link = new Uri(SiteLink + "sdownload/" + torrentID + "/" + passkey);
release.PublishDate = DateTimeUtil.UnixTimestampToDateTime((double)torrent[3]).ToLocalTime();
//var preDelaySeconds = (long)torrent[4];
release.Size = (long)torrent[5];
release.Seeders = (int)torrent[6];
release.Peers = release.Seeders + (int)torrent[7];
//var imdbRating = (double)torrent[8] / 10;
var genres = (string)torrent[9];
if (!string.IsNullOrWhiteSpace(genres))
release.Description = "Genres: " + genres;
var qDetailsLink = qRow.Find("a[href^=details.php?id=]").First();
var qTitle = qDetailsLink.Find("b").First();
release.Title = qTitle.Text();
var qCatLink = qRow.Find("a[href^=browse.php?cat=]").First();
var qDLLink = qRow.Find("a.download").First();
var qSeeders = qRow.Find("td.torrenttable:eq(7)");
var qLeechers = qRow.Find("td.torrenttable:eq(8)");
var qDateStr = qRow.Find("td.torrenttable:eq(4)").First();
var qSize = qRow.Find("td.torrenttable:eq(5)").First();
var catStr = qCatLink.Attr("href").Split('=')[1].Split('\'')[0];
release.Category = MapTrackerCatToNewznab(catStr);
release.Link = new Uri(SiteLink + qDLLink.Attr("href"));
release.Comments = new Uri(SiteLink + qDetailsLink.Attr("href"));
release.Guid = release.Link;
var sizeStr = qSize.Text();
release.Size = ReleaseInfo.GetBytes(sizeStr);
release.Seeders = ParseUtil.CoerceInt(qSeeders.Text());
release.Peers = ParseUtil.CoerceInt(qLeechers.Text()) + release.Seeders;
var dateStr = qDateStr.Text().Trim();
DateTime dateGerman = DateTime.SpecifyKind(DateTime.ParseExact(dateStr, "MMM d yyyy HH:mm", CultureInfo.InvariantCulture), DateTimeKind.Unspecified);
DateTime pubDateUtc = TimeZoneInfo.ConvertTimeToUtc(dateGerman, germanyTz);
release.PublishDate = pubDateUtc.ToLocalTime();
var files = qRow.Find("td:nth-child(4)").Text();
release.Files = ParseUtil.CoerceInt(files);
var grabs = qRow.Find("td:nth-child(8)").Get(0).FirstChild.ToString();
release.Grabs = ParseUtil.CoerceInt(grabs);
if (qRow.Find("img[src=\"pic/torrent_ou.gif\"]").Length >= 1)
var DownloadVolumeFlag = (long)torrent[10];
release.UploadVolumeFactor = 1;
if (DownloadVolumeFlag == 2) // Only Up
release.DownloadVolumeFactor = 0;
else if (qRow.Find("font[color=\"gray\"]:contains(50% Down)").Length >= 1)
else if (DownloadVolumeFlag == 1) // 50 % Down
release.DownloadVolumeFactor = 0.5;
else
else if (DownloadVolumeFlag == 0)
release.DownloadVolumeFactor = 1;
release.UploadVolumeFactor = 1;
release.Grabs = (long)torrent[11];
// 12/13/14 unknown, probably IDs/name of the uploader
//var row12 = (long)torrent[12];
//var row13 = (string)torrent[13];
//var row14 = (long)torrent[14];
releases.Add(release);
}
}
catch (Exception ex)
{
OnParseError(results, ex);
OnParseError(result.ToString(), ex);
}
return releases;

View File

@@ -113,7 +113,7 @@ namespace Jackett.Indexers
searchUrl += "?" + queryCollection.GetQueryString();
var response = await RequestStringWithCookies(searchUrl);
if (response.IsRedirect || response.Cookies.Contains("pass=deleted;"))
if (response.IsRedirect || response.Cookies != null && response.Cookies.Contains("pass=deleted;"))
{
// re-login
await ApplyConfiguration(null);

View File

@@ -173,6 +173,7 @@
<ItemGroup>
<Compile Include="AuthenticationException.cs" />
<Compile Include="CacheControlAttribute.cs" />
<Compile Include="IndexerException.cs" />
<Compile Include="Controllers\BlackholeController.cs" />
<Compile Include="Controllers\DownloadController.cs" />
<Compile Include="Engine.cs" />
@@ -207,7 +208,6 @@
<Compile Include="Indexers\Andraste.cs" />
<Compile Include="Indexers\TorrentHeaven.cs" />
<Compile Include="Indexers\NewRealWorld.cs" />
<Compile Include="Indexers\BestFriends.cs" />
<Compile Include="Indexers\BitCityReloaded.cs" />
<Compile Include="Indexers\FunFile.cs" />
<Compile Include="Indexers\GhostCity.cs" />

View File

@@ -5,5 +5,8 @@ namespace Jackett.Models.DTO
{
public string id { get; set; }
public string value { get; set; }
public string cookie { get; set; } // for cookie alternative login (captcha needed + remote host)
public string challenge { get; set; } // for reCaptcha V1 compatibility
public string version { get; set; } // for reCaptcha V1 compatibility
}
}

View File

@@ -35,7 +35,7 @@ namespace Jackett.Models.DTO
site_link = indexer.SiteLink;
language = indexer.Language;
last_error = indexer.LastError;
potatoenabled = indexer.TorznabCaps.Categories.Select(c => c.ID).Any(i => i == TorznabCatType.Movies.ID);
potatoenabled = indexer.TorznabCaps.Categories.Any(i => TorznabCatType.Movies.Contains(i));
alternativesitelinks = indexer.AlternativeSiteLinks;

View File

@@ -7,9 +7,20 @@ using System.Threading.Tasks;
namespace Jackett.Models.DTO
{
public enum ManualSearchResultIndexerStatus { Unknown = 0, Error = 1, OK = 2 };
public class ManualSearchResultIndexer
{
public string ID { get; set; }
public string Name { get; set; }
public ManualSearchResultIndexerStatus Status { get; set; }
public int Results { get; set; }
public string Error { get; set; }
}
public class ManualSearchResult
{
public IEnumerable<TrackerCacheResult> Results { get; set; }
public IEnumerable<string> Indexers { get; set; }
public IList<ManualSearchResultIndexer> Indexers { get; set; }
}
}

View File

@@ -3,6 +3,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using Jackett.Indexers;
using Newtonsoft.Json;
namespace Jackett.Models
{
@@ -32,6 +33,7 @@ namespace Jackett.Models
public long? MinimumSeedTime { get; set; }
public double? DownloadVolumeFactor { get; set; }
public double? UploadVolumeFactor { get; set; }
[JsonIgnore] // don't export the Origin to the manul search API, otherwise each result line contains a full recursive indexer JSON structure
public IIndexer Origin;
public double? Gain

View File

@@ -207,11 +207,11 @@ namespace Jackett.Services
browseQuery.QueryType = "search";
browseQuery.SearchTerm = "";
browseQuery.IsTest = true;
var results = await indexer.ResultsForQuery(browseQuery);
logger.Info(string.Format("Found {0} releases from {1}", results.Count(), indexer.DisplayName));
if (results.Count() == 0)
var result = await indexer.ResultsForQuery(browseQuery);
logger.Info(string.Format("Found {0} releases from {1}", result.Releases.Count(), indexer.DisplayName));
if (result.Releases.Count() == 0)
throw new Exception("Found no results while trying to browse this tracker");
cacheService.CacheRssResults(indexer, results);
cacheService.CacheRssResults(indexer, result.Releases);
}
public void DeleteIndexer(string name)

View File

@@ -43,6 +43,7 @@ namespace Jackett
json["result"] = "error";
json["error"] = msg;
json["stacktrace"] = exception.StackTrace;
var response = actionExecutedContext.Request.CreateResponse();
response.Content = new JsonContent(json);

View File

@@ -196,6 +196,15 @@ namespace Jackett.Utils.Clients
{
result.RedirectingTo = response.Headers.Location.ToString();
}
// Mono won't add the baseurl to relative redirects.
// e.g. a "Location: /index.php" header will result in the Uri "file:///index.php"
// See issue #1200
if (result.RedirectingTo != null && result.RedirectingTo.StartsWith("file://"))
{
var newRedirectingTo = result.RedirectingTo.Replace("file://", request.RequestUri.Scheme + "://" + request.RequestUri.Host);
logger.Debug("[MONO relative redirect bug] Rewriting relative redirect URL from " + result.RedirectingTo + " to " + newRedirectingTo);
result.RedirectingTo = newRedirectingTo;
}
result.Status = response.StatusCode;
// Compatiblity issue between the cookie format and httpclient

View File

@@ -207,6 +207,15 @@ namespace Jackett.Utils.Clients
{
result.RedirectingTo = response.Headers.Location.ToString();
}
// Mono won't add the baseurl to relative redirects.
// e.g. a "Location: /index.php" header will result in the Uri "file:///index.php"
// See issue #1200
if (result.RedirectingTo != null && result.RedirectingTo.StartsWith("file://"))
{
var newRedirectingTo = result.RedirectingTo.Replace("file://", request.RequestUri.Scheme + "://" + request.RequestUri.Host);
logger.Debug("[MONO relative redirect bug] Rewriting relative redirect URL from " + result.RedirectingTo + " to " + newRedirectingTo);
result.RedirectingTo = newRedirectingTo;
}
result.Status = response.StatusCode;
// Compatiblity issue between the cookie format and httpclient