Compare commits

...

56 Commits

Author SHA1 Message Date
Garfield69
28b53d8fb1 add boxingtorrents a Private site for boxing. resolves #7323 2020-02-28 19:13:21 +13:00
Garfield69
8a94d689b8 add exkinoray a Russian semi-private site. resolves #7318 2020-02-28 16:46:50 +13:00
gwenvador
ad00e49fe2 generationfree: new login (again!) (#7350) #7341 2020-02-28 16:39:19 +13:00
gwenvador
888361f46f Update generationfree.yml (#7347)
Change login username to correct value
2020-02-27 09:19:09 -06:00
Garfield69
edc4c31fa6 add ttsweb a private site. resolves #7301 2020-02-27 18:40:38 +13:00
Garfield69
a1dde973fb generationfree: site's login has changed. resolves #7341 2020-02-27 16:37:32 +13:00
Garfield69
525f58eb1d xwtorrents: Site's login has changed. resolves #7339 2020-02-27 16:37:07 +13:00
Sen Jiang
124fbf7c1b webui: Optimize favicon.ico with leanify (#7334)
leanify -i 1000 favicon.ico
variation on #7307
2020-02-27 07:30:21 +13:00
Cory
b9b10e4e91 core: Fix IsEmptyOrNull to return true when IsNull (#7338) resolves #7333 2020-02-27 07:24:36 +13:00
Garfield69
427b556869 btdb: fix title / details selector. resolves #7335 2020-02-27 07:22:04 +13:00
Garfield69
04f9f2dfe7 newstudio: fix SxxExx processing. resolves #7331 2020-02-26 20:51:52 +13:00
Garfield69
d8e7a63768 add filmsclub a Russian semi-private site. resolves #7289 2020-02-26 19:10:41 +13:00
Diego Heras
2f694147a1 lostfilm: Remove CsQuery and use AngleSharp instead #7292 (#7328)
also add missing torznab fields not available from results
2020-02-26 09:04:36 +13:00
Diego Heras
c339d54aed core: fix compilation warning (#7329) 2020-02-26 08:48:27 +13:00
Garfield69
58974623de tvchaosuk: update for unit3d 2.2.7 resolves #7327 2020-02-26 08:01:24 +13:00
Cory
889a8da4e5 Convert functions and properties to expression bodies when able (#7312)
Convert functions and properties to expression bodies when able
2020-02-25 10:08:03 -06:00
Garfield69
2f91d99e19 icetorrent: fix login. resolves #7321
update categories
fix imdb selector
fix files selector
2020-02-25 20:00:02 +13:00
Garfield69
65e93ce137 azure-pipeline: add replace for GitHub release attachements upload. 2020-02-25 18:51:27 +13:00
Jorman
0784e0784c btdb: fetch up to 100 rows (#7319) 2020-02-25 18:23:54 +13:00
Diego Heras
963616fe07 Revert "webui: reduce favicon.ico size. removed 256px, 128px, 64px icons (#7307)" (#7315)
This reverts commit d82c11650c.
2020-02-25 08:18:33 +13:00
Garfield69
e407067c8b add bteye a public dht crawler. resolves #7247 2020-02-25 08:13:00 +13:00
tide4cw
a8ba61fc9d Add torrentview a Korean public site. (#7313) 2020-02-24 20:05:57 +13:00
Garfield69
bbc360be00 add erzsebet a semi-rpivate Russian 3x site. resolves #7252 2020-02-24 17:48:07 +13:00
Diego Heras
d82c11650c webui: reduce favicon.ico size. removed 256px, 128px, 64px icons (#7307) 2020-02-24 09:42:27 +13:00
Diego Heras
6067a4ff73 core: add logger trace with proxy information (#7306) 2020-02-24 09:39:49 +13:00
Diego Heras
8c344b2917 core: reduce log traces in info level. add start/stop log traces (#7305) 2020-02-24 09:38:59 +13:00
Diego Heras
62769325b4 core: increase log size to 2 MB (#7303) 2020-02-24 09:33:51 +13:00
Diego Heras
a96b3841b0 webui: improve server logs modal (#7302) 2020-02-24 09:31:01 +13:00
Garfield69
a3dcb0455a btdb: new layout. resolves #7308 2020-02-24 09:27:15 +13:00
Diego Heras
5d808e006d webui: fix search encode in url hash. resolves #7265 (#7299) 2020-02-23 16:30:57 +13:00
fnk93
694c39503b The Resurrection: Fix multiple logins (#7298) 2020-02-23 08:44:41 +13:00
Diego Heras
12b2de2725 iptorrents: remove login with user/pass. resolves #7063 resolves #6850 resolves #6485 resolves #6402 resolves #4624 (#7294) 2020-02-23 08:34:14 +13:00
Diego Heras
d806bb18a2 core: improve cookie configuration help (#7293) 2020-02-23 08:31:38 +13:00
Sen Jiang
5a02bb9c27 btschool: use cookie (#7290)
Got all kinds of error using username and password
2020-02-23 08:29:00 +13:00
Garfield69
a3dc1b295b bitspyder: fix login. resolves #7287
also add sort options in config
2020-02-22 13:36:28 +13:00
Garfield69
471ab7f204 btnext: add info note about classic theme. #7208
also add sort options to the config.
and update the categories.
add movie-search.
2020-02-22 11:06:13 +13:00
Garfield69
bdcdd78cee torrent9clone: new domain .pl resolves #7282 2020-02-22 10:33:07 +13:00
junglebus
966c64c48e No longer manually install ChromeDriver (#7271) 2020-02-22 08:03:15 +13:00
Patrick Koenig
d5724f2f63 Change cookie SameSite from None to Lax (#7269) 2020-02-22 08:02:28 +13:00
Garfield69
3ecdbfe7f4 gay-torrentsorg: now private again. resolves #7268 2020-02-21 12:55:10 +13:00
Garfield69
b1ad8ed0bf hddolby: is now private. resolves #7267 2020-02-21 12:48:57 +13:00
junglebus
3a35e4e40a Windows service and Tray: NET Core only (#7258)
We no longer need to support NET461 for Tray and Windows service since these are for Windows users only
2020-02-21 08:55:45 +13:00
junglebus
0d58b2d63f Don't check cert store on Mono 6 (#7260) resolves #7223 2020-02-21 07:55:46 +13:00
junglebus
3c596c978c Stop building on Appveyor (#7259)
Now that we are successfully building and releasing on Azure Pipelines, there is no need to build on Appveyor as well
2020-02-21 07:06:12 +13:00
Garfield69
cc2a69cc77 film-paleis: gone private #7254
also requires thanks before download
2020-02-20 21:07:16 +13:00
Garfield69
7627671900 torrentcsv: fix empty search error. resolves #7255 2020-02-20 17:28:27 +13:00
Garfield69
4a4af3d8c8 r4e: update for unit3d 2.2.7 resolves #7257
plus add new categories
add posters
2020-02-20 17:01:55 +13:00
Jonas Stendahl
950d38a651 Add codec and medium filters to HDBits API (#7209)
* Add codec and medium filters to HDBits API

* Add checkboxes support to CardigannIndexer

* Expose multi-select as template variable

* update datestamp to force cache refresh

Co-authored-by: garfield69 <garfield69@outlook.com>
2020-02-20 09:23:55 +13:00
Garfield69
49d4c3248c remove vanila, now using mediaget client. #4003 2020-02-20 07:33:09 +13:00
Garfield69
3da168ef6c prostylex: now semi-private. resolves #7248 2020-02-20 07:23:28 +13:00
Garfield69
d4da96559f moviesdvdr: new domain .co. #7244 2020-02-19 07:40:41 +13:00
Garfield69
084c89d9db prostylex: prevent task cancelled by using cookie. 2020-02-18 14:03:19 +13:00
Jonas Stendahl
6a913f79d4 TorrentLeech: Add support for IMDb search (#7235) 2020-02-18 10:29:32 +13:00
fnk93
938c1f1de0 The Resurrection: Changed parameter name for categories (#7234) 2020-02-18 06:23:12 +13:00
Garfield69
480f2ebfeb hdtorrentsit: switch to https #7221 2020-02-17 21:49:48 +13:00
Garfield69
b32869badd greekteam: switch to https: #7221 2020-02-17 21:04:45 +13:00
184 changed files with 2368 additions and 4188 deletions

View File

@@ -39,6 +39,7 @@ Developer note: The software implements the [Torznab](https://github.com/Sonarr/
* BitTorrent.AM
* BTDB
* BTDIGG
* BTeye
* BT.etree
* BTSOW
* Cili180
@@ -121,6 +122,7 @@ Developer note: The software implements the [Torznab](https://github.com/Sonarr/
* TorrentProject2
* TorrentQuest
* Torrents.csv
* TorrentView
* TorrentWal
* Torrentz2
* Underverse
@@ -143,8 +145,10 @@ Developer note: The software implements the [Torznab](https://github.com/Sonarr/
* Deildu
* DXP (Deaf Experts)
* EniaHD
* Erzsebet
* ExKinoRay
* ExtremlymTorrents
* Film-Paleis
* FilmsClub
* Gay-Torrents.net
* Gay-Torrents.org
* HamsterStudio
@@ -171,7 +175,6 @@ Developer note: The software implements the [Torznab](https://github.com/Sonarr/
* Torrents-Local
* TribalMixes
* Union Fansub
* Vanila
* YggTorrent (YGG)
* Ztracker
</details>
@@ -220,6 +223,7 @@ Developer note: The software implements the [Torznab](https://github.com/Sonarr/
* BJ-Share (BJ)
* BlueBird
* Blutopia (BLU)
* Boxing Torrents
* Brasil Tracker
* BroadcastTheNet (BTN)
* BroadCity
@@ -272,6 +276,7 @@ Developer note: The software implements the [Torznab](https://github.com/Sonarr/
* FeedUrNeed (FuN)
* Femdomcult
* FileList (FL)
* Film-Paleis
* FinVip
* FocusX
* FreeTorrent
@@ -457,6 +462,7 @@ Developer note: The software implements the [Torznab](https://github.com/Sonarr/
* ToTheGlory
* TranceTraffic
* Trezzor
* TTsWEB
* TurkTorrent (TT)
* TV Chaos UK (TVCUK)
* TV-Vault

View File

@@ -1,47 +0,0 @@
version: 0.12.{build}
skip_tags: true
image:
- Ubuntu
- Visual Studio 2019
environment:
APPVEYOR_YML_DISABLE_PS_LINUX: true
CAKE_SETTINGS_SKIPPACKAGEVERSIONCHECK: true
configuration: Release
assembly_info:
patch: true
file: '**\AssemblyInfo.*'
assembly_version: '{version}'
assembly_file_version: '{version}'
assembly_informational_version: '{version}'
dotnet_csproj:
patch: true
file: '**\*.csproj'
version: '{version}'
package_version: '{version}'
assembly_version: '{version}'
file_version: '{version}'
informational_version: '{version}'
build_script:
- ps: .\build.ps1 --target=Windows-Appveyor
- sh: ./build.sh --target=Linux
test: off
before_deploy:
- ps: ${env:release_description} = ( Get-Content -LiteralPath BuildOutput/ReleaseNotes.txt -Encoding UTF8 ) -join "`n";
deploy:
- provider: GitHub
tag: v$(APPVEYOR_BUILD_VERSION)
description: $(release_description)
auth_token:
secure: hOg+16YTIbq4kO9u4D1YVOTbWDqgCX6mAQYMbnmBBSw2CiUsZh7OKbupoUb3FtWa
artifact: /^(?:(?![Ee]xperimental).)*$/
draft: true
force_update: true
on:
branch: master
notifications:
- provider: Webhook
url: https://skyhook.glitch.me/api/webhooks/346588605843767297/_VWi5abKliaWsBmQO7AX69tD28FhqSLjKyLBwkSwwT13uyWJQHx5TSWK_iAs-0RzmyvZ/appveyor
method: POST
on_build_success: true
on_build_failure: true
on_build_status_changed: true

View File

@@ -321,24 +321,6 @@ stages:
if [[ "$(artifactName)" == *"macOS"* ]]; then sudo ./install_service_macos; fi
if [[ "$(artifactName)" == *"LinuxAMDx64"* ]]; then sudo ./install_service_systemd.sh; fi
#Remove this task once ChromeDriver is deployed to Ubuntu image https://github.com/actions/virtual-environments/issues/9
- task: Bash@3
displayName: Install ChromeDriver (Linux and Mono)
condition: and(succeeded(), eq(variables['imageName'], 'ubuntu-latest'))
inputs:
targetType: inline
script: |
CHROME_VERSION=$(google-chrome --version | cut -f 3 -d ' ' | cut -d '.' -f 1) \
&& CHROMEDRIVER_RELEASE=$(curl --location --fail --retry 3 http://chromedriver.storage.googleapis.com/LATEST_RELEASE_${CHROME_VERSION}) \
&& curl --silent --show-error --location --fail --retry 3 --output /tmp/chromedriver_linux64.zip "http://chromedriver.storage.googleapis.com/$CHROMEDRIVER_RELEASE/chromedriver_linux64.zip" \
&& cd /tmp \
&& unzip chromedriver_linux64.zip \
&& rm -rf chromedriver_linux64.zip \
&& sudo mv chromedriver /usr/local/bin/chromedriver \
&& sudo chmod +x /usr/local/bin/chromedriver \
&& chromedriver --version
echo "##vso[task.setvariable variable=CHROMEWEBDRIVER]/usr/local/bin"
- task: UseDotNet@2
displayName: Install .NET Core SDK
inputs:
@@ -381,6 +363,7 @@ stages:
tag: v$(Build.BuildNumber)
title: v$(Build.BuildNumber)
assets: $(Build.ArtifactStagingDirectory)/drop/*
assetUploadMode: replace
isDraft: true
addChangeLog: true
compareWith: lastNonDraftRelease

View File

@@ -1,510 +0,0 @@
#tool nuget:?package=NUnit.ConsoleRunner
#addin nuget:?package=Cake.Git
//////////////////////////////////////////////////////////////////////
// ARGUMENTS
//////////////////////////////////////////////////////////////////////
var target = Argument("target", "Default");
var configuration = Argument("configuration", "Debug");
//////////////////////////////////////////////////////////////////////
// PREPARATION
//////////////////////////////////////////////////////////////////////
// Define directories.
var workingDir = MakeAbsolute(Directory("./"));
string artifactsDirName = "Artifacts";
string testResultsDirName = "TestResults";
string netCoreFramework = "netcoreapp3.1";
string serverProjectPath = "./src/Jackett.Server/Jackett.Server.csproj";
string updaterProjectPath = "./src/Jackett.Updater/Jackett.Updater.csproj";
//////////////////////////////////////////////////////////////////////
// TASKS
//////////////////////////////////////////////////////////////////////
Task("Info")
.Does(() =>
{
Information(@"Jackett Cake build script starting...");
Information(@"Requires InnoSetup and C:\msys64 to be present for packaging (Pre-installed on AppVeyor) on Windows");
Information(@"Working directory is: " + workingDir);
if (IsRunningOnWindows())
{
Information("Platform is Windows");
}
else
{
Information("Platform is Linux, Windows builds will be skipped");
}
});
Task("Clean")
.IsDependentOn("Info")
.Does(() =>
{
CleanDirectories("./src/**/obj");
CleanDirectories("./src/**/bin");
CleanDirectories("./BuildOutput");
CleanDirectories("./" + artifactsDirName);
CleanDirectories("./" + testResultsDirName);
CreateDirectory("./" + artifactsDirName);
Information("Clean completed");
});
Task("Build-Full-Framework")
.IsDependentOn("Clean")
.Does(() =>
{
NuGetRestore("./src/Jackett.sln");
var buildSettings = new MSBuildSettings()
.SetConfiguration(configuration)
.UseToolVersion(MSBuildToolVersion.VS2019);
MSBuild("./src/Jackett.sln", buildSettings);
});
Task("Run-Unit-Tests")
.IsDependentOn("Build-Full-Framework")
.Does(() =>
{
CreateDirectory("./" + testResultsDirName);
var resultsFile = $"./{testResultsDirName}/JackettTestResult.xml";
NUnit3("./src/**/bin/" + configuration + "/net461/*.Test.dll", new NUnit3Settings
{
Results = new[] { new NUnit3Result { FileName = resultsFile } }
});
if (AppVeyor.IsRunningOnAppVeyor && IsRunningOnWindows())
{
AppVeyor.UploadTestResults(resultsFile, AppVeyorTestResultsType.NUnit3);
}
});
Task("Package-Windows-Full-Framework")
.IsDependentOn("Run-Unit-Tests")
.Does(() =>
{
string buildOutputPath = "./BuildOutput/net461/win7-x86/Jackett";
DotNetCorePublish(serverProjectPath, "net461", "win7-x86", buildOutputPath);
CopyFiles("./src/Jackett.Service/bin/" + configuration + "/net461" + "/JackettService.*", buildOutputPath);
CopyFiles("./src/Jackett.Tray/bin/" + configuration + "/net461" + "/JackettTray.*", buildOutputPath);
CopyFiles("./src/Jackett.Updater/bin/" + configuration + "/net461" + "/JackettUpdater.*", buildOutputPath);
Zip("./BuildOutput/net461/win7-x86", $"./{artifactsDirName}/Jackett.Binaries.Windows.zip");
//InnoSetup
string sourceFolder = MakeAbsolute(Directory(buildOutputPath)).ToString();
InnoSetupSettings settings = new InnoSetupSettings();
settings.OutputDirectory = workingDir + "/" + artifactsDirName;
//Can remove below line once Cake is updated for InnoSetup 6 - https://github.com/cake-build/cake/pull/2565
settings.ToolPath = @"C:\Program Files (x86)\Inno Setup 6\ISCC.exe";
settings.Defines = new Dictionary<string, string>
{
{ "MyFileForVersion", sourceFolder + "/Jackett.Common.dll" },
{ "MySourceFolder", sourceFolder },
{ "MyOutputFilename", "Jackett.Installer.Windows" },
};
InnoSetup("./Installer.iss", settings);
});
Task("Package-Mono-Full-Framework")
.IsDependentOn("Run-Unit-Tests")
.Does(() =>
{
string buildOutputPath = "./BuildOutput/net461/linux-x64/Jackett";
DotNetCorePublish(serverProjectPath, "net461", "linux-x64", buildOutputPath);
CopyFiles("./src/Jackett.Updater/bin/" + configuration + "/net461" + "/JackettUpdater.*", buildOutputPath); //builds against multiple frameworks
CopyFileToDirectory("./install_service_systemd_mono.sh", buildOutputPath);
CopyFileToDirectory("./Upstart.config", buildOutputPath);
//There is an issue with Mono 5.8 (fixed in Mono 5.12) where its expecting to use its own patched version of System.Net.Http.dll, instead of the version supplied in folder
//https://github.com/dotnet/corefx/issues/19914
//https://bugzilla.xamarin.com/show_bug.cgi?id=60315
//The workaround is to delete System.Net.Http.dll and patch the .exe.config file
DeleteFile(buildOutputPath + "/System.Net.Http.dll");
var configFile = File(buildOutputPath + "/JackettConsole.exe.config");
XmlPoke(configFile, "configuration/runtime/*[name()='assemblyBinding']/*[name()='dependentAssembly']/*[name()='assemblyIdentity'][@name='System.Net.Http']/../*[name()='bindingRedirect']/@newVersion", "4.0.0.0");
//Mono on FreeBSD doesn't like the bundled System.Runtime.InteropServices.RuntimeInformation
//https://github.com/dotnet/corefx/issues/23989
//https://github.com/Jackett/Jackett/issues/3547
DeleteFile(buildOutputPath + "/System.Runtime.InteropServices.RuntimeInformation.dll");
CheckForGzipAndTar();
Gzip("./BuildOutput/net461/linux-x64", $"./{artifactsDirName}", "Jackett", "Jackett.Binaries.Mono.tar.gz");
});
Task("Package-DotNetCore-macOS")
.IsDependentOn("Clean")
.Does(() =>
{
string runtimeId = "osx-x64";
string buildOutputPath = $"./BuildOutput/{netCoreFramework}/{runtimeId}/Jackett";
string updaterOutputPath = buildOutputPath + "/Updater";
DotNetCorePublish(serverProjectPath, netCoreFramework, runtimeId, buildOutputPath);
DotNetCorePublish(updaterProjectPath, netCoreFramework, runtimeId, updaterOutputPath);
CopyFiles(updaterOutputPath + "/JackettUpdater*", buildOutputPath);
DeleteDirectory(updaterOutputPath, new DeleteDirectorySettings {Recursive = true, Force = true});
CopyFileToDirectory("./install_service_macos", buildOutputPath);
Gzip($"./BuildOutput/{netCoreFramework}/{runtimeId}", $"./{artifactsDirName}", "Jackett", "Jackett.Binaries.macOS.tar.gz");
});
Task("Package-DotNetCore-LinuxAMDx64")
.IsDependentOn("Clean")
.Does(() =>
{
string runtimeId = "linux-x64";
string buildOutputPath = $"./BuildOutput/{netCoreFramework}/{runtimeId}/Jackett";
string updaterOutputPath = buildOutputPath + "/Updater";
DotNetCorePublish(serverProjectPath, netCoreFramework, runtimeId, buildOutputPath);
DotNetCorePublish(updaterProjectPath, netCoreFramework, runtimeId, updaterOutputPath);
CopyFiles(updaterOutputPath + "/JackettUpdater*", buildOutputPath);
DeleteDirectory(updaterOutputPath, new DeleteDirectorySettings {Recursive = true, Force = true});
CopyFileToDirectory("./install_service_systemd.sh", buildOutputPath);
CopyFileToDirectory("./jackett_launcher.sh", buildOutputPath);
Gzip($"./BuildOutput/{netCoreFramework}/{runtimeId}", $"./{artifactsDirName}", "Jackett", "Jackett.Binaries.LinuxAMDx64.tar.gz");
});
Task("Package-DotNetCore-LinuxARM32")
.IsDependentOn("Clean")
.Does(() =>
{
string runtimeId = "linux-arm";
string buildOutputPath = $"./BuildOutput/{netCoreFramework}/{runtimeId}/Jackett";
string updaterOutputPath = buildOutputPath + "/Updater";
DotNetCorePublish(serverProjectPath, netCoreFramework, runtimeId, buildOutputPath);
DotNetCorePublish(updaterProjectPath, netCoreFramework, runtimeId, updaterOutputPath);
CopyFiles(updaterOutputPath + "/JackettUpdater*", buildOutputPath);
DeleteDirectory(updaterOutputPath, new DeleteDirectorySettings {Recursive = true, Force = true});
CopyFileToDirectory("./install_service_systemd.sh", buildOutputPath);
CopyFileToDirectory("./jackett_launcher.sh", buildOutputPath);
Gzip($"./BuildOutput/{netCoreFramework}/{runtimeId}", $"./{artifactsDirName}", "Jackett", "Jackett.Binaries.LinuxARM32.tar.gz");
});
Task("Package-DotNetCore-LinuxARM64")
.IsDependentOn("Clean")
.Does(() =>
{
string runtimeId = "linux-arm64";
string buildOutputPath = $"./BuildOutput/{netCoreFramework}/{runtimeId}/Jackett";
string updaterOutputPath = buildOutputPath + "/Updater";
DotNetCorePublish(serverProjectPath, netCoreFramework, runtimeId, buildOutputPath);
DotNetCorePublish(updaterProjectPath, netCoreFramework, runtimeId, updaterOutputPath);
CopyFiles(updaterOutputPath + "/JackettUpdater*", buildOutputPath);
DeleteDirectory(updaterOutputPath, new DeleteDirectorySettings {Recursive = true, Force = true});
CopyFileToDirectory("./install_service_systemd.sh", buildOutputPath);
CopyFileToDirectory("./jackett_launcher.sh", buildOutputPath);
Gzip($"./BuildOutput/{netCoreFramework}/{runtimeId}", $"./{artifactsDirName}", "Jackett", "Jackett.Binaries.LinuxARM64.tar.gz");
});
Task("Appveyor-Push-Artifacts")
.IsDependentOn("Clean")
.Does(() =>
{
if (AppVeyor.IsRunningOnAppVeyor)
{
foreach (var file in GetFiles(workingDir + $"/{artifactsDirName}/*"))
{
AppVeyor.UploadArtifact(file.FullPath);
}
}
else
{
Information(@"Skipping artifact push as not running in AppVeyor Windows Environment");
}
});
Task("Release-Notes")
.IsDependentOn("Clean")
.Does(() =>
{
string latestTag = GitDescribe(".", false, GitDescribeStrategy.Tags, 0);
Information($"Latest tag is: {latestTag}" + Environment.NewLine);
List<GitCommit> relevantCommits = new List<GitCommit>();
var commitCollection = GitLog("./", 50);
foreach(GitCommit commit in commitCollection)
{
var commitTag = GitDescribe(".", commit.Sha, false, GitDescribeStrategy.Tags, 0);
if (commitTag == latestTag)
{
relevantCommits.Add(commit);
}
else
{
break;
}
}
relevantCommits = relevantCommits.AsEnumerable().Reverse().Skip(1).ToList();
if (relevantCommits.Count() > 0)
{
List<string> notesList = new List<string>();
foreach(GitCommit commit in relevantCommits)
{
notesList.Add($"{commit.MessageShort} (Thank you @{commit.Author.Name})");
}
string buildNote = String.Join(Environment.NewLine, notesList);
Information(buildNote);
System.IO.File.WriteAllLines(workingDir + "/BuildOutput/ReleaseNotes.txt", notesList.ToArray());
}
else
{
Information($"No commit messages found to create release notes");
}
});
Task("Windows-Environment-Dev")
.IsDependentOn("Package-Windows-Full-Framework")
.IsDependentOn("Package-Mono-Full-Framework")
.IsDependentOn("Package-DotNetCore-macOS")
.IsDependentOn("Package-DotNetCore-LinuxAMDx64")
.IsDependentOn("Package-DotNetCore-LinuxARM32")
.IsDependentOn("Package-DotNetCore-LinuxARM64")
.IsDependentOn("Appveyor-Push-Artifacts")
.IsDependentOn("Release-Notes")
.Does(() =>
{
Information("Windows-Environment Task Completed");
});
Task("Windows-Environment-Appveyor")
.IsDependentOn("Package-Windows-Full-Framework")
.IsDependentOn("Package-Mono-Full-Framework")
.IsDependentOn("Appveyor-Push-Artifacts")
.IsDependentOn("Release-Notes")
.Does(() =>
{
Information("Windows-Environment Task Completed");
});
Task("Linux-Environment")
.IsDependentOn("Package-DotNetCore-macOS")
.IsDependentOn("Package-DotNetCore-LinuxAMDx64")
.IsDependentOn("Package-DotNetCore-LinuxARM32")
.IsDependentOn("Package-DotNetCore-LinuxARM64")
.IsDependentOn("Appveyor-Push-Artifacts")
.IsDependentOn("Release-Notes")
.Does(() =>
{
Information("Linux-Environment Task Completed");
});
private void RunMsysCommand(string utility, string utilityArguments)
{
var msysDir = @"C:\msys64\usr\bin\";
var utilityProcess = msysDir + utility + ".exe";
Information("MSYS2 Utility: " + utility);
Information("MSYS2 Directory: " + msysDir);
Information("Utility Location: " + utilityProcess);
Information("Utility Arguments: " + utilityArguments);
IEnumerable<string> redirectedStandardOutput;
IEnumerable<string> redirectedErrorOutput;
var exitCodeWithArgument =
StartProcess(
utilityProcess,
new ProcessSettings {
Arguments = utilityArguments,
WorkingDirectory = msysDir,
RedirectStandardOutput = true
},
out redirectedStandardOutput,
out redirectedErrorOutput
);
Information(utility + " output:" + Environment.NewLine + string.Join(Environment.NewLine, redirectedStandardOutput.ToArray()));
// Throw exception if anything was written to the standard error.
if (redirectedErrorOutput != null && redirectedErrorOutput.Any())
{
throw new Exception(
string.Format(
utility + " Errors ocurred: {0}",
string.Join(", ", redirectedErrorOutput)));
}
Information(utility + " Exit code: {0}", exitCodeWithArgument);
}
private string RelativeWinPathToFullPath(string relativePath)
{
return (workingDir + relativePath.TrimStart('.'));
}
private void RunLinuxCommand(string file, string arg)
{
var startInfo = new System.Diagnostics.ProcessStartInfo()
{
Arguments = arg,
FileName = file,
UseShellExecute = true
};
var process = System.Diagnostics.Process.Start(startInfo);
process.WaitForExit();
}
private void Gzip(string sourceFolder, string outputDirectory, string tarCdirectoryOption, string outputFileName)
{
var tarFileName = outputFileName.Remove(outputFileName.Length - 3, 3);
if (IsRunningOnWindows())
{
var fullSourcePath = RelativeWinPathToFullPath(sourceFolder);
var tarArguments = @"--force-local -cvf " + fullSourcePath + "/" + tarFileName + " -C " + fullSourcePath + $" {tarCdirectoryOption} --mode ='755'";
var gzipArguments = @"-k " + fullSourcePath + "/" + tarFileName;
RunMsysCommand("tar", tarArguments);
RunMsysCommand("gzip", gzipArguments);
MoveFile($"{sourceFolder}/{tarFileName}.gz", $"{outputDirectory}/{tarFileName}.gz");
}
else
{
RunLinuxCommand("find", MakeAbsolute(Directory(sourceFolder)) + @" -type d -exec chmod 755 {} \;");
RunLinuxCommand("find", MakeAbsolute(Directory(sourceFolder)) + @" -type f -exec chmod 644 {} \;");
RunLinuxCommand("chmod", $"755 {MakeAbsolute(Directory(sourceFolder))}/Jackett/jackett");
RunLinuxCommand("chmod", $"755 {MakeAbsolute(Directory(sourceFolder))}/Jackett/JackettUpdater");
string macOsServiceScript = MakeAbsolute(Directory(sourceFolder)) + "/Jackett/install_service_macos";
if (FileExists(macOsServiceScript))
{
RunLinuxCommand("chmod", $"755 {macOsServiceScript}");
}
string systemdMonoScript = MakeAbsolute(Directory(sourceFolder)) + "/Jackett/install_service_systemd_mono.sh";
if (FileExists(systemdMonoScript))
{
RunLinuxCommand("chmod", $"755 {systemdMonoScript}");
}
string systemdScript = MakeAbsolute(Directory(sourceFolder)) + "/Jackett/install_service_systemd.sh";
if (FileExists(systemdScript))
{
RunLinuxCommand("chmod", $"755 {systemdScript}");
}
string launcherScript = MakeAbsolute(Directory(sourceFolder)) + "/Jackett/jackett_launcher.sh";
if (FileExists(launcherScript))
{
RunLinuxCommand("chmod", $"755 {launcherScript}");
}
RunLinuxCommand("tar", $"-C {sourceFolder} -zcvf {outputDirectory}/{tarFileName}.gz {tarCdirectoryOption}");
}
}
private void CheckForGzipAndTar()
{
if (FileExists(@"C:\msys64\usr\bin\tar.exe") && FileExists(@"C:\msys64\usr\bin\gzip.exe"))
{
Information("tar.exe and gzip.exe were found");
}
else
{
throw new Exception("tar.exe and gzip.exe were NOT found");
}
}
private void DotNetCorePublish(string projectPath, string framework, string runtime, string outputPath)
{
bool publishSingleFile = false;
if (publishSingleFile && framework != "net461")
{
var settings = new DotNetCorePublishSettings
{
Framework = framework,
Runtime = runtime,
OutputDirectory = outputPath,
ArgumentCustomization = args=>args.Append("/p:PublishSingleFile=true")
};
DotNetCorePublish(projectPath, settings);
}
else
{
var settings = new DotNetCorePublishSettings
{
Framework = framework,
Runtime = runtime,
OutputDirectory = outputPath
};
DotNetCorePublish(projectPath, settings);
}
}
//////////////////////////////////////////////////////////////////////
// TASK TARGETS
//////////////////////////////////////////////////////////////////////
Task("Default")
.IsDependentOn("Windows-Environment-Dev")
.Does(() =>
{
Information("Default Task Completed");
});
Task("Windows-Appveyor")
.IsDependentOn("Windows-Environment-Appveyor")
.Does(() =>
{
Information("Windows Appveyor Task Completed");
});
Task("Linux")
.IsDependentOn("Linux-Environment")
.Does(() =>
{
Information("Linux Task Completed");
});
//////////////////////////////////////////////////////////////////////
// EXECUTION
//////////////////////////////////////////////////////////////////////
RunTarget(target);

242
build.ps1
View File

@@ -1,242 +0,0 @@
##########################################################################
# This is the Cake bootstrapper script for PowerShell.
# This file was downloaded from https://github.com/cake-build/resources
# Feel free to change this file to fit your needs.
##########################################################################
<#
.SYNOPSIS
This is a Powershell script to bootstrap a Cake build.
.DESCRIPTION
This Powershell script will download NuGet if missing, restore NuGet tools (including Cake)
and execute your Cake build script with the parameters you provide.
.PARAMETER Script
The build script to execute.
.PARAMETER Target
The build script target to run.
.PARAMETER Configuration
The build configuration to use.
.PARAMETER Verbosity
Specifies the amount of information to be displayed.
.PARAMETER ShowDescription
Shows description about tasks.
.PARAMETER DryRun
Performs a dry run.
.PARAMETER SkipToolPackageRestore
Skips restoring of packages.
.PARAMETER ScriptArgs
Remaining arguments are added here.
.LINK
https://cakebuild.net
#>
[CmdletBinding()]
Param(
[string]$Script = "build.cake",
[string]$Target,
[string]$Configuration,
[ValidateSet("Quiet", "Minimal", "Normal", "Verbose", "Diagnostic")]
[string]$Verbosity,
[switch]$ShowDescription,
[Alias("WhatIf", "Noop")]
[switch]$DryRun,
[switch]$SkipToolPackageRestore,
[Parameter(Position=0,Mandatory=$false,ValueFromRemainingArguments=$true)]
[string[]]$ScriptArgs
)
# Attempt to set highest encryption available for SecurityProtocol.
# PowerShell will not set this by default (until maybe .NET 4.6.x). This
# will typically produce a message for PowerShell v2 (just an info
# message though)
try {
# Set TLS 1.2 (3072), then TLS 1.1 (768), then TLS 1.0 (192), finally SSL 3.0 (48)
# Use integers because the enumeration values for TLS 1.2 and TLS 1.1 won't
# exist in .NET 4.0, even though they are addressable if .NET 4.5+ is
# installed (.NET 4.5 is an in-place upgrade).
[System.Net.ServicePointManager]::SecurityProtocol = 3072 -bor 768 -bor 192 -bor 48
} catch {
Write-Output 'Unable to set PowerShell to use TLS 1.2 and TLS 1.1 due to old .NET Framework installed. If you see underlying connection closed or trust errors, you may need to upgrade to .NET Framework 4.5+ and PowerShell v3'
}
[Reflection.Assembly]::LoadWithPartialName("System.Security") | Out-Null
function MD5HashFile([string] $filePath)
{
if ([string]::IsNullOrEmpty($filePath) -or !(Test-Path $filePath -PathType Leaf))
{
return $null
}
[System.IO.Stream] $file = $null;
[System.Security.Cryptography.MD5] $md5 = $null;
try
{
$md5 = [System.Security.Cryptography.MD5]::Create()
$file = [System.IO.File]::OpenRead($filePath)
return [System.BitConverter]::ToString($md5.ComputeHash($file))
}
finally
{
if ($file -ne $null)
{
$file.Dispose()
}
}
}
function GetProxyEnabledWebClient
{
$wc = New-Object System.Net.WebClient
$proxy = [System.Net.WebRequest]::GetSystemWebProxy()
$proxy.Credentials = [System.Net.CredentialCache]::DefaultCredentials
$wc.Proxy = $proxy
return $wc
}
Write-Host "Preparing to run build script..."
if(!$PSScriptRoot){
$PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent
}
$TOOLS_DIR = Join-Path $PSScriptRoot "tools"
$ADDINS_DIR = Join-Path $TOOLS_DIR "Addins"
$MODULES_DIR = Join-Path $TOOLS_DIR "Modules"
$NUGET_EXE = Join-Path $TOOLS_DIR "nuget.exe"
$CAKE_EXE = Join-Path $TOOLS_DIR "Cake/Cake.exe"
$NUGET_URL = "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe"
$PACKAGES_CONFIG = Join-Path $TOOLS_DIR "packages.config"
$PACKAGES_CONFIG_MD5 = Join-Path $TOOLS_DIR "packages.config.md5sum"
$ADDINS_PACKAGES_CONFIG = Join-Path $ADDINS_DIR "packages.config"
$MODULES_PACKAGES_CONFIG = Join-Path $MODULES_DIR "packages.config"
# Make sure tools folder exists
if ((Test-Path $PSScriptRoot) -and !(Test-Path $TOOLS_DIR)) {
Write-Verbose -Message "Creating tools directory..."
New-Item -Path $TOOLS_DIR -Type directory | out-null
}
# Make sure that packages.config exist.
if (!(Test-Path $PACKAGES_CONFIG)) {
Write-Verbose -Message "Downloading packages.config..."
try {
$wc = GetProxyEnabledWebClient
$wc.DownloadFile("https://cakebuild.net/download/bootstrapper/packages", $PACKAGES_CONFIG)
} catch {
Throw "Could not download packages.config."
}
}
# Try find NuGet.exe in path if not exists
if (!(Test-Path $NUGET_EXE)) {
Write-Verbose -Message "Trying to find nuget.exe in PATH..."
$existingPaths = $Env:Path -Split ';' | Where-Object { (![string]::IsNullOrEmpty($_)) -and (Test-Path $_ -PathType Container) }
$NUGET_EXE_IN_PATH = Get-ChildItem -Path $existingPaths -Filter "nuget.exe" | Select -First 1
if ($NUGET_EXE_IN_PATH -ne $null -and (Test-Path $NUGET_EXE_IN_PATH.FullName)) {
Write-Verbose -Message "Found in PATH at $($NUGET_EXE_IN_PATH.FullName)."
$NUGET_EXE = $NUGET_EXE_IN_PATH.FullName
}
}
# Try download NuGet.exe if not exists
if (!(Test-Path $NUGET_EXE)) {
Write-Verbose -Message "Downloading NuGet.exe..."
try {
$wc = GetProxyEnabledWebClient
$wc.DownloadFile($NUGET_URL, $NUGET_EXE)
} catch {
Throw "Could not download NuGet.exe."
}
}
# Save nuget.exe path to environment to be available to child processed
$ENV:NUGET_EXE = $NUGET_EXE
# Restore tools from NuGet?
if(-Not $SkipToolPackageRestore.IsPresent) {
Push-Location
Set-Location $TOOLS_DIR
# Check for changes in packages.config and remove installed tools if true.
[string] $md5Hash = MD5HashFile($PACKAGES_CONFIG)
if((!(Test-Path $PACKAGES_CONFIG_MD5)) -Or
($md5Hash -ne (Get-Content $PACKAGES_CONFIG_MD5 ))) {
Write-Verbose -Message "Missing or changed package.config hash..."
Get-ChildItem -Exclude packages.config,nuget.exe,Cake.Bakery |
Remove-Item -Recurse
}
Write-Verbose -Message "Restoring tools from NuGet..."
$NuGetOutput = Invoke-Expression "&`"$NUGET_EXE`" install -ExcludeVersion -OutputDirectory `"$TOOLS_DIR`""
if ($LASTEXITCODE -ne 0) {
Throw "An error occurred while restoring NuGet tools."
}
else
{
$md5Hash | Out-File $PACKAGES_CONFIG_MD5 -Encoding "ASCII"
}
Write-Verbose -Message ($NuGetOutput | out-string)
Pop-Location
}
# Restore addins from NuGet
if (Test-Path $ADDINS_PACKAGES_CONFIG) {
Push-Location
Set-Location $ADDINS_DIR
Write-Verbose -Message "Restoring addins from NuGet..."
$NuGetOutput = Invoke-Expression "&`"$NUGET_EXE`" install -ExcludeVersion -OutputDirectory `"$ADDINS_DIR`""
if ($LASTEXITCODE -ne 0) {
Throw "An error occurred while restoring NuGet addins."
}
Write-Verbose -Message ($NuGetOutput | out-string)
Pop-Location
}
# Restore modules from NuGet
if (Test-Path $MODULES_PACKAGES_CONFIG) {
Push-Location
Set-Location $MODULES_DIR
Write-Verbose -Message "Restoring modules from NuGet..."
$NuGetOutput = Invoke-Expression "&`"$NUGET_EXE`" install -ExcludeVersion -OutputDirectory `"$MODULES_DIR`""
if ($LASTEXITCODE -ne 0) {
Throw "An error occurred while restoring NuGet modules."
}
Write-Verbose -Message ($NuGetOutput | out-string)
Pop-Location
}
# Make sure that Cake has been installed.
if (!(Test-Path $CAKE_EXE)) {
Throw "Could not find Cake.exe at $CAKE_EXE"
}
# Build Cake arguments
$cakeArguments = @("$Script");
if ($Target) { $cakeArguments += "-target=$Target" }
if ($Configuration) { $cakeArguments += "-configuration=$Configuration" }
if ($Verbosity) { $cakeArguments += "-verbosity=$Verbosity" }
if ($ShowDescription) { $cakeArguments += "-showdescription" }
if ($DryRun) { $cakeArguments += "-dryrun" }
$cakeArguments += $ScriptArgs
# Start Cake
Write-Host "Running build script..."
&$CAKE_EXE $cakeArguments
exit $LASTEXITCODE

117
build.sh
View File

@@ -1,117 +0,0 @@
#!/usr/bin/env bash
##########################################################################
# This is the Cake bootstrapper script for Linux and OS X.
# This file was downloaded from https://github.com/cake-build/resources
# Feel free to change this file to fit your needs.
##########################################################################
# Define directories.
SCRIPT_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
TOOLS_DIR=$SCRIPT_DIR/tools
ADDINS_DIR=$TOOLS_DIR/Addins
MODULES_DIR=$TOOLS_DIR/Modules
NUGET_EXE=$TOOLS_DIR/nuget.exe
CAKE_EXE=$TOOLS_DIR/Cake/Cake.exe
PACKAGES_CONFIG=$TOOLS_DIR/packages.config
PACKAGES_CONFIG_MD5=$TOOLS_DIR/packages.config.md5sum
ADDINS_PACKAGES_CONFIG=$ADDINS_DIR/packages.config
MODULES_PACKAGES_CONFIG=$MODULES_DIR/packages.config
# Define md5sum or md5 depending on Linux/OSX
MD5_EXE=
if [[ "$(uname -s)" == "Darwin" ]]; then
MD5_EXE="md5 -r"
else
MD5_EXE="md5sum"
fi
# Define default arguments.
SCRIPT="build.cake"
CAKE_ARGUMENTS=()
# Parse arguments.
for i in "$@"; do
case $1 in
-s|--script) SCRIPT="$2"; shift ;;
--) shift; CAKE_ARGUMENTS+=("$@"); break ;;
*) CAKE_ARGUMENTS+=("$1") ;;
esac
shift
done
# Make sure the tools folder exist.
if [ ! -d "$TOOLS_DIR" ]; then
mkdir "$TOOLS_DIR"
fi
# Make sure that packages.config exist.
if [ ! -f "$TOOLS_DIR/packages.config" ]; then
echo "Downloading packages.config..."
curl -Lsfo "$TOOLS_DIR/packages.config" https://cakebuild.net/download/bootstrapper/packages
if [ $? -ne 0 ]; then
echo "An error occurred while downloading packages.config."
exit 1
fi
fi
# Download NuGet if it does not exist.
if [ ! -f "$NUGET_EXE" ]; then
echo "Downloading NuGet..."
curl -Lsfo "$NUGET_EXE" https://dist.nuget.org/win-x86-commandline/latest/nuget.exe
if [ $? -ne 0 ]; then
echo "An error occurred while downloading nuget.exe."
exit 1
fi
fi
# Restore tools from NuGet.
pushd "$TOOLS_DIR" >/dev/null
if [ ! -f "$PACKAGES_CONFIG_MD5" ] || [ "$( cat "$PACKAGES_CONFIG_MD5" | sed 's/\r$//' )" != "$( $MD5_EXE "$PACKAGES_CONFIG" | awk '{ print $1 }' )" ]; then
find . -type d ! -name . ! -name 'Cake.Bakery' | xargs rm -rf
fi
mono "$NUGET_EXE" install -ExcludeVersion
if [ $? -ne 0 ]; then
echo "Could not restore NuGet tools."
exit 1
fi
$MD5_EXE "$PACKAGES_CONFIG" | awk '{ print $1 }' >| "$PACKAGES_CONFIG_MD5"
popd >/dev/null
# Restore addins from NuGet.
if [ -f "$ADDINS_PACKAGES_CONFIG" ]; then
pushd "$ADDINS_DIR" >/dev/null
mono "$NUGET_EXE" install -ExcludeVersion
if [ $? -ne 0 ]; then
echo "Could not restore NuGet addins."
exit 1
fi
popd >/dev/null
fi
# Restore modules from NuGet.
if [ -f "$MODULES_PACKAGES_CONFIG" ]; then
pushd "$MODULES_DIR" >/dev/null
mono "$NUGET_EXE" install -ExcludeVersion
if [ $? -ne 0 ]; then
echo "Could not restore NuGet modules."
exit 1
fi
popd >/dev/null
fi
# Make sure that Cake has been installed.
if [ ! -f "$CAKE_EXE" ]; then
echo "Could not find Cake.exe at '$CAKE_EXE'."
exit 1
fi
# Start Cake
exec mono "$CAKE_EXE" $SCRIPT "${CAKE_ARGUMENTS[@]}"

View File

@@ -286,9 +286,7 @@ namespace DateTimeRoutines
/// <param name="parsed_time">parsed date-time output</param>
/// <returns>true if time was found, else false</returns>
public static bool TryParseTime(this string str, DateTimeFormat default_format, out ParsedDateTime parsed_time)
{
return TryParseTime(str, default_format, out parsed_time, null);
}
=> TryParseTime(str, default_format, out parsed_time, null);
/// <summary>
/// Tries to find date and/or time within the passed string and return it as ParsedDateTime object.

View File

@@ -2,6 +2,7 @@
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<LangVersion>8</LangVersion>
</PropertyGroup>
</Project>

View File

@@ -55,6 +55,14 @@ body {
max-width: 255px;
}
.setup-item-inputcheckbox label {
padding: 0 1.5em;
}
.setup-item-inputcheckbox input {
height: 20px;
}
.setup-item-inputbool input {
max-width: 100px;
height: 20px;
@@ -175,6 +183,12 @@ hr {
border-bottom: 1px solid #ddd;
}
.jackettlog-narrowcol {
width: 1px;
white-space: nowrap;
vertical-align: top;
}
.jackettlogWarn {
background-color: #FFFF8E !important;
}
@@ -202,11 +216,15 @@ pre {
font-size: 13px;
line-height: 1.42857143;
color: #333;
word-break: break-all;
word-wrap: break-word;
background-color: transparent;
border: 0;
border-radius: 0;
word-break: normal;
white-space: pre-wrap; /* Since CSS 2.1 */
white-space: -moz-pre-wrap; /* Mozilla, since 1999 */
white-space: -pre-wrap; /* Opera 4-6 */
white-space: -o-pre-wrap; /* Opera 7 */
word-wrap: break-word; /* Internet Explorer 5.5+ */
}
.modal-open .modal {
@@ -277,7 +295,7 @@ table td.fit{
.tooltip-inner img {
max-width: 250px;
height: auto;
height: auto;
}
.type-public {

View File

@@ -32,7 +32,15 @@ $(document).ready(function () {
return opts.fn(this);
else
return opts.inverse(this);
});
});
Handlebars.registerHelper('if_in', function(elem, list, opts) {
if(list.indexOf(elem) > -1) {
return opts.fn(this);
}
return opts.inverse(this);
});
var index = window.location.pathname.indexOf("/UI");
var pathPrefix = window.location.pathname.substr(0, index);
@@ -43,7 +51,12 @@ $(document).ready(function () {
});
function openSearchIfNecessary() {
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), {});
const hashArgs = location.hash.substring(1).split('&').reduce((prev, item) =>
Object.assign({
[item.split('=')[0]]: (item.split('=').length < 2 ?
undefined :
decodeURIComponent(item.split('=')[1].replace(/\+/g,'%20')))
}, prev), {});
if ("search" in hashArgs) {
showSearch(hashArgs.tracker, hashArgs.search, hashArgs.category);
}
@@ -608,6 +621,11 @@ function getConfigModalJson(configForm) {
case "inputbool":
itemEntry.value = $el.find(".setup-item-inputbool input").is(":checked");
break;
case "inputcheckbox":
itemEntry.values = [];
$el.find(".setup-item-inputcheckbox input:checked").each(function () {
itemEntry.values.push($(this).val());
});
case "inputselect":
itemEntry.value = $el.find(".setup-item-inputselect select").val();
break;
@@ -762,7 +780,7 @@ function updateReleasesRow(row)
}
function showSearch(selectedIndexer, query, category) {
var selectedIndexers = []
var selectedIndexers = [];
if (selectedIndexer)
selectedIndexers = selectedIndexer.split(",");
$('#select-indexer-modal').remove();
@@ -829,7 +847,11 @@ function showSearch(selectedIndexer, query, category) {
Tracker: releaseDialog.find('#searchTracker').val()
};
window.location.hash = $.param({ search: queryObj.Query, tracker: queryObj.Tracker.join(","), category: queryObj.Category.join(",") });
window.location.hash = Object.entries({
search: encodeURIComponent(queryObj.Query).replace(/%20/g,'+'),
tracker: queryObj.Tracker.join(","),
category: queryObj.Category.join(",")
}).map(([k, v], i) => k + '=' + v).join('&');
$('#jackett-search-perform').html($('#spinner').html());
$('#searchResults div.dataTables_filter input').val("");
@@ -877,7 +899,7 @@ function showSearch(selectedIndexer, query, category) {
enableCaseInsensitiveFiltering: true,
nonSelectedText: 'All'
});
if (category !== undefined) {
searchCategory.val(category.split(","));
@@ -1155,8 +1177,8 @@ function bindUIButtons() {
var jackett_port = Number($("#jackett-port").val());
var jackett_basepathoverride = $("#jackett-basepathoverride").val();
var jackett_external = $("#jackett-allowext").is(':checked');
var jackett_update = $("#jackett-allowupdate").is(':checked');
var jackett_prerelease = $("#jackett-prerelease").is(':checked');
var jackett_update = $("#jackett-allowupdate").is(':checked');
var jackett_prerelease = $("#jackett-prerelease").is(':checked');
var jackett_logging = $("#jackett-logging").is(':checked');
var jackett_omdb_key = $("#jackett-omdbkey").val();
var jackett_omdb_url = $("#jackett-omdburl").val();

View File

@@ -175,6 +175,12 @@ hr {
border-bottom: 1px solid #ddd;
}
.jackettlog-narrowcol {
width: 1px;
white-space: nowrap;
vertical-align: top;
}
.jackettlogWarn {
background-color: #FFFF8E !important;
}
@@ -202,11 +208,15 @@ pre {
font-size: 13px;
line-height: 1.42857143;
color: #333;
word-break: break-all;
word-wrap: break-word;
background-color: transparent;
border: 0;
border-radius: 0;
word-break: normal;
white-space: pre-wrap; /* Since CSS 2.1 */
white-space: -moz-pre-wrap; /* Mozilla, since 1999 */
white-space: -pre-wrap; /* Opera 4-6 */
white-space: -o-pre-wrap; /* Opera 7 */
word-wrap: break-word; /* Internet Explorer 5.5+ */
}
.modal-open .modal {
@@ -276,7 +286,7 @@ table td.fit{
.tooltip-inner img {
max-width: 250px;
height: auto;
height: auto;
}
.type-public {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 361 KiB

After

Width:  |  Height:  |  Size: 101 KiB

View File

@@ -34,8 +34,8 @@
<link rel="stylesheet" type="text/css" href="../bootstrap/bootstrap.min.css?changed=2017083001">
<link rel="stylesheet" type="text/css" href="../animate.css?changed=2017083001">
<link rel="stylesheet" type="text/css" href="../custom.css?changed=20200102" media="only screen and (min-device-width: 480px)">
<link rel="stylesheet" type="text/css" href="../custom_mobile.css?changed=20200102" media="only screen and (max-device-width: 480px)">
<link rel="stylesheet" type="text/css" href="../custom.css?changed=20200223" media="only screen and (min-device-width: 480px)">
<link rel="stylesheet" type="text/css" href="../custom_mobile.css?changed=20200223" media="only screen and (max-device-width: 480px)">
<link rel="stylesheet" type="text/css" href="../css/jquery.dataTables.min.css?changed=2017083001">
<link rel="stylesheet" type="text/css" href="../css/bootstrap-multiselect.css?changed=2017083001" />
<link rel="stylesheet" type="text/css" href="../css/font-awesome.min.css?changed=2017083001">
@@ -52,11 +52,11 @@
</div>
<hr />
<div id="can-upgrade-from-mono" hidden class="alert alert-info" role="alert">
<div id="can-upgrade-from-mono" hidden class="alert alert-info" role="alert">
<strong>Standalone version of Jackett is now available - Mono not required</strong> <br>
To upgrade to the standalone version of Jackett, <a href="https://github.com/Jackett/Jackett#install-on-linux-amdx64" target="_blank" class="alert-link">click here</a> for install instructions.
Upgrading is straight forward, simply install the standalone version and your indexers/configuration will carry over.
Benefits include: increased performance, improved stability and no dependency on Mono.
To upgrade to the standalone version of Jackett, <a href="https://github.com/Jackett/Jackett#install-on-linux-amdx64" target="_blank" class="alert-link">click here</a> for install instructions.
Upgrading is straight forward, simply install the standalone version and your indexers/configuration will carry over.
Benefits include: increased performance, improved stability and no dependency on Mono.
</div>
<div class="pull-right">
@@ -235,6 +235,19 @@
{{/if}}
</div>
</script>
<script id="setup-item-inputcheckbox" type="text/x-handlebars-template">
<div class="setup-item-inputcheckbox">
{{#each options}}
<div class="checkbox"><label>
{{#if_in @key ../values}}
<input type="checkbox" data-id="{{../../id}}" class="form-control" value="{{@key}}" checked />
{{else}}
<input type="checkbox" data-id="{{../../id}}" class="form-control" value="{{@key}}" />
{{/if_in}}
{{this}}</label></div>
{{/each}}
</div>
</script>
<script id="setup-item-inputselect" type="text/x-handlebars-template">
<div class="setup-item-inputselect">
<select class="form-control" data-id="{{id}}">
@@ -603,16 +616,16 @@
<table class="dataTable compact cell-border hover stripe">
<thead>
<tr>
<th style="width: 200px">When</th>
<th style="width: 80px">Level</th>
<th>Date</th>
<th>Level</th>
<th>Message</th>
</tr>
</thead>
<tbody>
{{#each logs}}
<tr class="jackettlog{{Level}}">
<td>{{dateFormat When}}</td>
<td>{{Level}}</td>
<td class="jackettlog-narrowcol">{{dateFormat When}}</td>
<td class="jackettlog-narrowcol">{{Level}}</td>
<td><pre>{{Message}}</pre></td>
</tr>
{{/each}}
@@ -678,6 +691,6 @@
</script>
<script type="text/javascript" src="../libs/api.js?changed=2017083001"></script>
<script type="text/javascript" src="../custom.js?changed=20200102"></script>
<script type="text/javascript" src="../custom.js?changed=20200222"></script>
</body>
</html>

View File

@@ -1,11 +1,11 @@

Handlebars.registerHelper('dateFormat', function (context, block) {
if (window.moment) {
var f = block.hash.format || "MMM DD, YYYY hh:mm:ss A";
var f = block.hash.format || "YYYY-MM-DD HH:mm:ss";
return moment(context).format(f); //had to remove Date(context)
} else {
return context; // moment plugin not available. return data as is.
};
}
});
Handlebars.registerHelper('jacketTimespan', function (context, block) {
@@ -22,7 +22,7 @@ Handlebars.registerHelper('jacketTimespan', function (context, block) {
if (hours < 48) {
return Math.round(hours) + 'h ago';
}
var days = timeSpan.asDays();
if (days < 365) {
return Math.round(days) + 'd ago';
@@ -34,4 +34,4 @@ Handlebars.registerHelper('jacketTimespan', function (context, block) {
Handlebars.registerHelper('jacketSize', function (context, block) {
return filesize(context, { round: 1 });
});
});

View File

@@ -16,7 +16,7 @@
<link href="../bootstrap/bootstrap.min.css" rel="stylesheet">
<link href="../animate.css" rel="stylesheet">
<link href="../custom.css" rel="stylesheet">
<link href="../custom.css?changed=20200223" rel="stylesheet">
<title>Jackett</title>
</head>

View File

@@ -6,6 +6,8 @@
type: private
encoding: windows-1252
links:
- https://bitspyder.net/
legacylinks:
- http://bitspyder.net/
caps:
@@ -47,9 +49,34 @@
modes:
search: [q]
settings:
- name: username
type: text
label: Username
- name: password
type: password
label: Password
- name: sort
type: select
label: Sort requested from site
default: "8"
options:
"8": "created"
"6": "seeders"
"4": "size"
"1": "title"
- name: type
type: select
label: Order requested from site
default: "desc"
options:
"desc": "desc"
"asc": "asc"
login:
path: processf.php
method: post
path: login.php
method: form
form: form
inputs:
username: "{{ .Config.username }}"
password: "{{ .Config.password }}"
@@ -61,17 +88,20 @@
search:
paths:
- path: browse.php
method: post
inputs:
search: "{{ .Keywords }}"
# 0 active 1 incldead 2 onlydead
incldead: 1
# 0 title 1 default
scope: 1
sort: "{{ .Config.sort }}"
type: "{{ .Config.type }}"
rows:
selector: table > tbody > tr[class]
filters:
- name: andmatch
fields:
# there are two styles, we support both
title:
@@ -101,7 +131,7 @@
selector: td.rowcol:nth-child(7):has(br), td.clear:nth-child(4)
filters:
- name: regexp
args: ([\d,]+)
args: (\d+)
seeders:
selector: td.rowcol:nth-last-child(3)
leechers:
@@ -138,3 +168,4 @@
description:
optional: true
selector: font[color="#990000"]
# custom v4

View File

@@ -0,0 +1,133 @@
---
site: boxingtorrents
name: Boxing Torrents
description: "Boxing Torrents is a Private Torrent Tracker for BOXING"
language: en-us
type: private
encoding: UTF-8
links:
- https://tc-boxing.com/
caps:
categorymappings:
- {id: 15, cat: TV/Sport, desc: "3D"}
- {id: 9, cat: TV/Sport, desc: "Amateur - Full"}
- {id: 16, cat: TV/Sport, desc: "Blu-ray"}
- {id: 13, cat: TV/Sport, desc: "Career Set"}
- {id: 8, cat: TV/Sport, desc: "DVD"}
- {id: 10, cat: TV/Sport, desc: "Foreign - Excellent"}
- {id: 11, cat: TV/Sport, desc: "Foreign - Fair"}
- {id: 6, cat: TV/Sport, desc: "Foreign - Good"}
- {id: 12, cat: TV/Sport, desc: "Foreign - Poor"}
- {id: 1, cat: TV/Sport, desc: "Full - Excellent"}
- {id: 3, cat: TV/Sport, desc: "Full - Fair"}
- {id: 2, cat: TV/Sport, desc: "Full - Good"}
- {id: 4, cat: TV/Sport, desc: "Full - Poor"}
- {id: 14, cat: TV/Sport, desc: "HD"}
- {id: 7, cat: TV/Sport, desc: "Misc"}
modes:
search: [q]
tv-search: [q, season, ep]
settings:
- name: username
type: text
label: Username
- name: password
type: password
label: Password
- name: sort
type: select
label: Sort requested from site
default: "added"
options:
"added": "created"
"seeders": "seeders"
"size": "size"
"name": "title"
- name: type
type: select
label: Order requested from site
default: "DESC"
options:
"DESC": "desc"
"ASC": "asc"
- name: info_download
type: info
label: "Download Restrictions"
default: "You must have uploaded at least 10GB before you are able to access all torrent sizes. Until then, you are restricted to torrents no larger than 2.5GB."
login:
path: takelogin.php
method: post
inputs:
username: "{{ .Config.username }}"
password: "{{ .Config.password }}"
error:
- selector: td.embedded:contains("Login failed!")
test:
path: browse.php
selector: a[href="logout.php"]
download:
selector: a[href^="download.php"]
attribute: href
search:
paths:
# https://tc-boxing.com/browse.php?c16=1&c8=1&c14=1&incldead=1
# https://tc-boxing.com/browse.php?search=tyson&cat=0&incldead=1
- path: browse.php
inputs:
$raw: "{{ if .Categories }}{{ range .Categories }}c{{.}}=1&{{end}}{{else}}cat=0{{end}}"
# 0 active 1 incldead 2 onlydead
incldead: 1
search: "{{ .Keywords }}"
sort: "{{ .Config.sort }}"
d: "{{ .Config.type }}"
rows:
selector: table[border="1"][cellspacing="0"][cellpadding="5"] tr:has(a[href^="details.php?id="])
fields:
category:
selector: a[href^="browse.php?cat="]
attribute: href
filters:
- name: querystring
args: cat
title:
selector: a[href^="details.php?id="]
details:
selector: a[href^="details.php?id="]
attribute: href
download:
selector: a[href^="details.php?id="]
attribute: href
files:
selector: td:nth-last-child(8)
date:
selector: td:nth-last-child(6)
filters:
- name: dateparse
args: "2006-01-0215:04:05"
size:
selector: td:nth-last-child(5)
grabs:
selector: td:nth-last-child(4)
filters:
- name: regexp
args: (\d+)
seeders:
selector: td:nth-last-child(3)
leechers:
selector: td:nth-last-child(2)
downloadvolumefactor:
case:
"b:contains(\"FreeLeech\")": 0
"*": 1
uploadvolumefactor:
text: 1
# engine n/a

View File

@@ -33,39 +33,57 @@
options:
"time": "created"
"length": "size"
"popular": "seeders"
"seeders": "seeders"
search:
paths:
- path: "{{ if .Keywords }}?s={{ .Keywords }}&sort={{ .Config.sort }}{{else}}recent?sort={{ .Config.sort }}{{end}}"
- path: "{{ if .Keywords }}search/{{ .Keywords }}/{{else}}recent{{end}}?sort={{ .Config.sort }}"
- path: "{{ if .Keywords }}search/{{ .Keywords }}/{{else}}recent{{end}}?sort={{ .Config.sort }}&page=2"
- path: "{{ if .Keywords }}search/{{ .Keywords }}/{{else}}recent{{end}}?sort={{ .Config.sort }}&page=3"
- path: "{{ if .Keywords }}search/{{ .Keywords }}/{{else}}recent{{end}}?sort={{ .Config.sort }}&page=4"
- path: "{{ if .Keywords }}search/{{ .Keywords }}/{{else}}recent{{end}}?sort={{ .Config.sort }}&page=5"
rows:
selector: li[class$="item"]
selector: div.media
fields:
title:
selector: h2[class$="title"] a[href*="/torrent/"]
attribute: title
category:
text: 1
title:
selector: a[href*="/torrent/"]
details:
selector: h2[class$="title"] a[href*="/torrent/"]
selector: a[href*="/torrent/"]
attribute: href
download:
selector: a[href$=".torrent"]
attribute: href
magnet:
selector: div[class$="info"] a[href^="magnet:?xt="]
selector: a[href^="magnet:?xt="]
attribute: href
banner:
selector: a.img-thumbnail img
attribute: src
filters:
- name: replace
args: ["https://btdb.io/assets/img/placeholder.png", ""]
size:
selector: div[class$="info"] span:nth-of-type(1)
selector: small:nth-of-type(1) strong
files:
selector: div[class$="info"] span:nth-of-type(2)
selector: small:nth-of-type(2) strong
seeders:
selector: small:nth-of-type(3) strong
filters:
- name: replace
args: [",", ""]
leechers:
selector: small:nth-of-type(4) strong
filters:
- name: replace
args: [",", ""]
date:
selector: div[class$="info"] span:nth-of-type(3)
selector: small:nth-of-type(5) strong
filters:
- name: timeago
seeders:
selector: div[class$="info"] span:nth-of-type(4)
leechers:
selector: div[class$="info"] span:nth-of-type(5)
downloadvolumefactor:
text: 0
uploadvolumefactor:

View File

@@ -0,0 +1,68 @@
---
site: bteye
name: BTeye
description: "BTeye is a Public BitTorrent DHT search engine."
language: en-us
type: public
encoding: UTF-8
links:
- https://www.bteye.org/
caps:
categories:
1: Other
modes:
search: [q]
tv-search: [q, season, ep]
movie-search: [q]
settings:
- name: info
type: info
default: BTeye does not use categories. In your software Indexer settings, set the category to 100001.
download:
selector: a[href^="magnet:?xt="]
attribute: href
search:
# https://www.bteye.org/q/2020
paths:
- path: "q/{{ if .Keywords }}{{ .Keywords }}{{else}}2020{{end}}"
rows:
selector: div.plist
filters:
- name: andmatch
fields:
category:
text: 1
title:
selector: div.pname a
attribute: title
details:
selector: div.pname a
attribute: href
download:
selector: div.pname a
attribute: href
date:
selector: div.plink b:nth-of-type(3)
filters:
- name: dateparse
args: "2006-01-02"
files:
selector: div.plink b:nth-of-type(2)
size:
selector: div.plink b:nth-of-type(1)
seeders:
text: 1
leechers:
text: 1
downloadvolumefactor:
text: 0
uploadvolumefactor:
text: 1
# engine n/a

View File

@@ -7,6 +7,7 @@
encoding: UTF-8
links:
- http://tracker.btnext.com/
# note: the site forces http, https is not supported
caps:
categorymappings:
@@ -15,67 +16,76 @@
- {id: 89, cat: Console, desc: "Games"}
- {id: 87, cat: TV, desc: "Series"}
- {id: 93, cat: Audio, desc: "Musica"}
- {id: 108, cat: Movies, desc: "ViP"}
- {id: 1, cat: Movies, desc: "Movies"}
- {id: 70, cat: Movies/3D, desc: "3D"}
- {id: 71, cat: Movies/Sd, desc: "480p"}
- {id: 72, cat: Movies/BluRay, desc: "BD-R"}
- {id: 31, cat: Movies/HD, desc: "BDRIP/BRRip"}
- {id: 16, cat: Movies/SD, desc: "CAM"}
- {id: 74, cat: Movies/DVD, desc: "DvD-R"}
- {id: 17, cat: Movies/HD, desc: "HD"}
- {id: 91, cat: Movies/Other, desc: "Kids"}
- {id: 76, cat: Movies, desc: "Packs"}
- {id: 77, cat: Movies/WEBDL, desc: "WEB-DL"}
- {id: 14, cat: Movies/SD, desc: "DVDRip/XViD"}
- {id: 85, cat: Movies/DVD, desc: "Custom-DVDR"}
- {id: 96, cat: Movies/HD, desc: "4K"}
- {id: 6, cat: PC, desc: "Applications"}
- {id: 18, cat: PC/ISO, desc: "PC Applications"}
- {id: 19, cat: PC/Mac, desc: "Macintosh Applications"}
- {id: 34, cat: PC/ISO, desc: "Linux Applications"}
- {id: 7, cat: Audio, desc: "Music"}
- {id: 20, cat: Audio/Video, desc: "MVideo"}
- {id: 21, cat: Audio/MP3, desc: "Mp3"}
- {id: 33, cat: Audio/Other, desc: "Mp4"}
- {id: 32, cat: Audio/Lossless, desc: "FLAC"}
- {id: 2, cat: Console, desc: "Games"}
- {id: 78, cat: PC/Games, desc: "Linux"}
- {id: 79, cat: PC/Mac, desc: "MacOSX"}
- {id: 28, cat: Console/NDS, desc: "Nintendo DS"}
- {id: 27, cat: PC/Games, desc: "PC/Windows"}
- {id: 80, cat: Console/PS3, desc: "PS2"}
- {id: 81, cat: Console/PS3, desc: "PS3"}
- {id: 82, cat: Console/PS4, desc: "PS4"}
- {id: 83, cat: Console/PSP, desc: "PSP"}
- {id: 95, cat: Console/PSVita, desc: "PSVITA"}
- {id: 4, cat: Console/Wii, desc: "Wii"}
- {id: 26, cat: Console/Xbox360, desc: "XBOX360"}
- {id: 84, cat: Console/Xbox, desc: "XONE"}
- {id: 70, cat: Movies/3D, desc: "Movies 3D"}
- {id: 71, cat: Movies/SD, desc: "Movies 480p"}
- {id: 72, cat: Movies/BluRay, desc: "Movies BD-R"}
- {id: 31, cat: Movies/HD, desc: "Movies BDRIP/BRRip"}
- {id: 16, cat: Movies/SD, desc: "Movies CAM"}
- {id: 74, cat: Movies/DVD, desc: "Movies DvD-R"}
- {id: 76, cat: Movies, desc: "Movies Packs"}
- {id: 91, cat: Movies/Other, desc: "Movies Kids"}
- {id: 77, cat: Movies/WEBDL, desc: "Movies WEB-DL"}
- {id: 85, cat: Movies/DVD, desc: "Movies Custom-DVDR"}
- {id: 14, cat: Movies/SD, desc: "Movies DVDRip/XViD"}
- {id: 98, cat: Movies/Other, desc: "Movies Juvenil"}
- {id: 104, cat: Movies/UHD, desc: "Movies Bluray-UHD"}
- {id: 102, cat: Movies/HD, desc: "Movies HD-720p"}
- {id: 101, cat: Movies/HD, desc: "Movies HD-1080p"}
- {id: 103, cat: Movies/UHD, desc: "Movies HD-2160p"}
- {id: 42, cat: TV, desc: "TV Series"}
- {id: 45, cat: TV/Documentary, desc: "Documentaries"}
- {id: 46, cat: TV/Sport, desc: "Sports"}
- {id: 47, cat: TV/HD, desc: "TV-Bluray"}
- {id: 48, cat: TV/SD, desc: "TV-Dvd-R"}
- {id: 49, cat: TV/SD, desc: "TV-DVDRiP"}
- {id: 50, cat: TV, desc: "TV-Packs"}
- {id: 92, cat: TV/Anime, desc: "TV-Kids"}
- {id: 52, cat: TV/SD, desc: "TV-SDx264"}
- {id: 53, cat: TV/WEB-DL, desc: "TV-WEB-DL"}
- {id: 55, cat: TV/HD, desc: "TV-X264"}
- {id: 47, cat: TV/HD, desc: "TV Bluray"}
- {id: 48, cat: TV/SD, desc: "TV Dvd-R"}
- {id: 49, cat: TV/SD, desc: "TV DVDRiP"}
- {id: 50, cat: TV, desc: "TV Packs"}
- {id: 92, cat: TV, desc: "TV Kids"}
- {id: 112, cat: TV, desc: "TV Juvenil"}
- {id: 52, cat: TV/SD, desc: "TV SDx264"}
- {id: 53, cat: TV/WEB-DL, desc: "TV WEB-DL"}
- {id: 55, cat: TV/HD, desc: "TV X264"}
- {id: 56, cat: TV/SD, desc: "TV-XViD"}
- {id: 44, cat: TV, desc: "Miscellaneous"}
- {id: 51, cat: TV/Anime, desc: "Anime"}
- {id: 54, cat: Audio/Audiobook, desc: "Audiobook"}
- {id: 57, cat: Books, desc: "E-Books"}
- {id: 58, cat: Books/Comics, desc: "Comics"}
- {id: 59, cat: Books, desc: "Educational"}
- {id: 60, cat: Books, desc: "Magazines/Journals"}
- {id: 7, cat: Audio, desc: "Music"}
- {id: 20, cat: Audio/Video, desc: "Music MVideo"}
- {id: 21, cat: Audio/MP3, desc: "Music MP3"}
- {id: 33, cat: Audio/Other, desc: "Music MP4"}
- {id: 32, cat: Audio/Lossless, desc: "Music FLAC"}
- {id: 2, cat: Console, desc: "Games"}
- {id: 78, cat: PC/Games, desc: "Games Linux"}
- {id: 79, cat: PC/Mac, desc: "Games MacOSX"}
- {id: 28, cat: Console/NDS, desc: "Games Nintendo DS"}
- {id: 27, cat: PC/Games, desc: "Games PC/Windows"}
- {id: 80, cat: Console/PS3, desc: "Games PS2"}
- {id: 81, cat: Console/PS3, desc: "Games PS3"}
- {id: 82, cat: Console/PS4, desc: "Games PS4"}
- {id: 83, cat: Console/PSP, desc: "Games PSP"}
- {id: 95, cat: Console/PSVita, desc: "Games PSVITA"}
- {id: 4, cat: Console/Wii, desc: "Games Wii"}
- {id: 26, cat: Console/Xbox360, desc: "Games XBOX360"}
- {id: 84, cat: Console/Xbox, desc: "Games XONE"}
- {id: 6, cat: PC, desc: "Applications"}
- {id: 18, cat: PC/ISO, desc: "Applications PC"}
- {id: 19, cat: PC/Mac, desc: "Applications Macintosh"}
- {id: 34, cat: PC/ISO, desc: "Applications Linux"}
- {id: 44, cat: Other, desc: "Miscellaneous"}
- {id: 54, cat: Audio/Audiobook, desc: "Books Audiobook"}
- {id: 57, cat: Books, desc: "Books E-Books"}
- {id: 58, cat: Books/Comics, desc: "Books Comics"}
- {id: 59, cat: Books, desc: "Books Educational"}
- {id: 60, cat: Books, desc: "Books Magazines/Journals"}
- {id: 61, cat: Other, desc: "Pics/Wallpapers"}
- {id: 62, cat: PC/Phone-Android, desc: "Android"}
- {id: 63, cat: PC/Phone-IOS, desc: "iOS"}
- {id: 66, cat: PC/Phone-Other, desc: "WindowsPhone"}
- {id: 90, cat: Other, desc: "GPS"}
- {id: 68, cat: Other, desc: "Others"}
- {id: 100, cat: Other, desc: "Revistas"}
- {id: 109, cat: TV/Anime, desc: "Anime"}
- {id: 51, cat: TV/Anime, desc: "Anime Filmes"}
- {id: 99, cat: TV/Anime, desc: "Anime Hentai"}
- {id: 110, cat: TV/Anime, desc: "Anime TV Séries"}
- {id: 41, cat: XXX, desc: "XXX"}
- {id: 64, cat: XXX, desc: "XXX-Magazines"}
- {id: 65, cat: XXX, desc: "XXX-Movies"}
@@ -85,6 +95,34 @@
modes:
search: [q]
tv-search: [q, season, ep]
movie-search: [q]
settings:
- name: username
type: text
label: Username
- name: password
type: password
label: Password
- name: info
type: info
label: Layout
default: "<ol><li>Only the English Classic profile is supported.<li>Make sure to set the <b>Torrent Listing (Lista de Torrents)</b> option in your profile to <b>Classic (Clássico)</b><li>Using the <i>Moderna</i> theme will prevent results.</ol>"
- name: sort
type: select
label: Sort requested from site
default: "added"
options:
"added": "created"
"seeders": "seeders"
"size": "size"
- name: type
type: select
label: Order requested from site
default: "desc"
options:
"desc": "desc"
"asc": "asc"
login:
path: ?p=home&pid=1
@@ -92,7 +130,7 @@
form: form#loginbox_form
submitpath: /ajax/login.php
inputs:
action: "login"
action: login
loginbox_membername: "{{ .Config.username }}"
loginbox_password: "{{ .Config.password }}"
loginbox_remember: 1
@@ -121,6 +159,8 @@
keywords: "{{ .Keywords }}"
search_type: name
searchin: title
"sortOptions[sortBy]": "{{ .Config.sort }}"
"sortOptions[sortOrder]": "{{ .Config.type }}"
error:
- selector: div.error:not(:contains("Não existem resultados encontrados.")):not(:contains("There are no results found."))

View File

@@ -27,24 +27,23 @@
tv-search: [q, season, ep, imdbid]
movie-search: [q, imdbid]
settings:
- name: cookie
type: text
label: Cookie
- name: info
type: info
label: How to get the Cookie
default: "<ol><li>Login to this tracker in your browser<li>Open the <b>DevTools</b> panel by pressing <b>F12</b><li>Select the <b>Network</b> tab<li>Click on the <b>Doc</b> button<li>Refresh the page by pressing <b>F5</b><li>Select the <b>Headers</b> tab<li>Find 'cookie:' in the <b>Request Headers</b> section<li>Copy & paste the whole cookie string to here</ol>"
login:
path: login.php
method: form
form: form[action="takelogin.php"]
captcha:
type: image
selector: img[alt="CAPTCHA"]
input: imagestring
method: cookie
inputs:
username: "{{ .Config.username }}"
password: "{{ .Config.password }}"
error:
- selector: td.embedded:has(h2:contains("登錄失敗"))
- selector: td.embedded:has(h2:contains("失败"))
cookie: "{{ .Config.cookie }}"
test:
path: index.php
selector: a[href="logout.php"]
search:
paths:
- path: torrents.php

View File

@@ -0,0 +1,199 @@
---
site: erzsebet
name: Erzsebet
description: "Erzsebet is a RUSSIAN Semi-Private Torrent Tracker for 3X"
language: ru-ru
type: semi-private
encoding: UTF-8
links:
- https://erzsebet.org/
caps:
categorymappings:
- {id: 9, cat: XXX, desc: "Feature, Vignettes, Classic / Фильмы с сюжетом и Классичес..."}
- {id: 11, cat: XXX, desc: "Gonzo & All Sex / Гонзо-фильмы и Фильмы без сюжета"}
- {id: 13, cat: XXX, desc: "All Girl & Solo / Лесбо-фильмы"}
- {id: 12, cat: XXX, desc: "Ethnic-Themed / Этнические фильмы"}
- {id: 176, cat: XXX, desc: "Mobile, Pocket РС & Phone / Фильмы для моби..."}
- {id: 157, cat: XXX, desc: "Full Length Movies Packs / Паки фильмов"}
- {id: 16, cat: XXX, desc: "Feature, Vignettes, Classic (HD) / Фильмы с сюжет..."}
- {id: 18, cat: XXX, desc: "Gonzo & All Sex, All Girl & Solo, Ethnic-Themed..."}
- {id: 180, cat: XXX, desc: "Full Length Movies (DVD) / Фильмы (DVD)"}
- {id: 246, cat: XXX, desc: "Full Length Movies (Blu-Ray) / Фильмы (Blu-Ray)"}
- {id: 48, cat: XXX, desc: "Clips (various) / Порно Разное"}
- {id: 32, cat: XXX, desc: "SiteRip's & Movie Scenes / Сайтрипы и сцены ..."}
- {id: 45, cat: XXX, desc: "SiteRip's & Movie Scenes (HD) / Сайтрипы и сцены..."}
- {id: 177, cat: XXX, desc: "3D & Virtual Reality Videos (VR) / Видео в 3D и..."}
- {id: 43, cat: XXX, desc: "Actresses Clips Packs / Паки по актрисам"}
- {id: 39, cat: XXX, desc: "SiteRip's Packs / Паки сайтрипов"}
- {id: 52, cat: XXX, desc: "Russian Clips (various) / Порно Разное с русскими актрисам..."}
- {id: 53, cat: XXX, desc: "Russian SiteRip's & Movie Scenes / Сайтрип..."}
- {id: 54, cat: XXX, desc: "Russian SiteRip's & Movie Scenes (HD) / Сайтрипы..."}
- {id: 56, cat: XXX, desc: "Russian Full Length Movies / Русские полнометражные фильмы"}
- {id: 50, cat: XXX, desc: "Russian Clips Packs / Паки русского и по русским актрисам"}
- {id: 59, cat: XXX, desc: "Amateur Picture / Любительское фото"}
- {id: 58, cat: XXX, desc: "Amateur Video & WebCams / Любительское видео"}
- {id: 128, cat: XXX, desc: "Amateur Packs / Паки любительского"}
- {id: 129, cat: XXX, desc: "Bukkake, Glory Hole, Cumshot Compilation, BlowGangBang ..."}
- {id: 130, cat: XXX, desc: "Squirting & Lesbian Bukkake / Лесбо и соло сквиртинг"}
- {id: 120, cat: XXX, desc: "Fisting, Dildo & Toys / Фистинг, фаллоимита..."}
- {id: 131, cat: XXX, desc: "LegalPorno.com / Сайтрипы студии Legal Porno "}
- {id: 64, cat: XXX, desc: "BDSM / БДСМ"}
- {id: 65, cat: XXX, desc: "Fetish / Фетиш"}
- {id: 66, cat: XXX, desc: "Peeing / Мочеиспускание"}
- {id: 67, cat: XXX, desc: "Pregnant / Беременные"}
- {id: 68, cat: XXX, desc: "Femdom & Strapon / Женское доминирование и страпон"}
- {id: 71, cat: XXX, desc: "Kaviar Movies / Копрофилия"}
- {id: 81, cat: XXX, desc: "Picture Gallery / Порнофотографии"}
- {id: 80, cat: XXX, desc: "Misc & Special Interest Picture / Тематичес..."}
- {id: 79, cat: XXX, desc: "Magazines, Comix & Artwork / Журналы, ком..."}
- {id: 78, cat: XXX, desc: "Picture Packs / Паки фотографий"}
- {id: 178, cat: XXX, desc: "Erotic Video Library / Эротические студии (видео)"}
- {id: 85, cat: XXX, desc: "Adult Games / Порноигры"}
- {id: 83, cat: XXX, desc: "Hentai, Manga & Cartoons / Хентай, Манга и Мультфильм..."}
- {id: 89, cat: XXX, desc: "Japanese Porn / Японское порно"}
- {id: 188, cat: XXX, desc: "Erotic Movies, Documentary & Reality / Эротически..."}
- {id: 219, cat: XXX, desc: "Cinema / Зарубежный Кинематограф"}
- {id: 218, cat: XXX, desc: "Cinema Series / Зарубежные сериалы"}
- {id: 217, cat: XXX, desc: "Cinema (Russian) / Кинематограф СССР, России и бы..."}
- {id: 216, cat: XXX, desc: "Russian Series / Русские сериалы"}
- {id: 215, cat: XXX, desc: "Cartoons & Anime / Мультфильмы и Аниме"}
- {id: 214, cat: XXX, desc: "Music (Audio) / Музыка (Аудио)"}
- {id: 213, cat: XXX, desc: "Music (Video) / Музыка (Видео)"}
- {id: 212, cat: XXX, desc: "Games / Игры"}
- {id: 211, cat: XXX, desc: "Soft / Софт"}
- {id: 210, cat: XXX, desc: "Various / Разное"}
- {id: 205, cat: XXX, desc: "Shemale Transsexual / Транссексуалы"}
- {id: 204, cat: XXX, desc: "Bisexual / Бисексуалы"}
- {id: 206, cat: XXX, desc: "Gay Clips & Movie Scenes / Ролики, SiteRip'ы..."}
- {id: 208, cat: XXX, desc: "Full Length Gay Movies / Полнометражные гей-фильмы"}
- {id: 209, cat: XXX, desc: "Gay Magazines, Photo, Rest / Гей-журналы, фото, разное"}
- {id: 125, cat: XXX, desc: "Archive / Архив"}
modes:
search: [q]
settings:
- name: username
type: text
label: Username
- name: password
type: password
label: Password
- name: sort
type: select
label: Sort requested from site
default: "1"
options:
"1": "created"
"10": "seeders"
"7": "size"
"2": "title"
- name: type
type: select
label: Order requested from site
default: "2"
options:
"2": "desc"
"1": "asc"
login:
path: login.php
method: form
form: form[action="login.php"]
inputs:
login_username: "{{ .Config.username }}"
login_password: "{{ .Config.password }}"
autologin: 1
error:
- selector: table.error
test:
path: index.php
selector: a[href="./login.php?logout=1"]
search:
paths:
- path: tracker.php
keywordsfilters:
- name: diacritics
args: replace
- name: re_replace # S01 to сезон 1
args: ["(?i)\\bS0*(\\d+)\\b", "сезон $1"]
- name: re_replace # S01E01 to сезон 1 серии 1
args: ["(?i)\\bS0*(\\d+)E0*(\\d+)\\b", "сезон $1 серии $2"]
inputs:
$raw: "{{ if .Categories }}{{ range .Categories }}f[]={{.}}&{{end}}{{else}}f[]=-1{{end}}"
prev_allw: 1
prev_a: 0
prev_dla: 0
prev_dlc: 0
prev_dld: 0
prev_dlw: 0
prev_my: 0
prev_new: 0
prev_sd: 0
prev_da: 1
prev_dc: 0
prev_df: 1
prev_ds: 0
prev_tor_type: 0
o: "{{ .Config.sort }}"
s: "{{ .Config.type }}"
# show category
dc: 0
# show forum
df: 1
# show author
da: 1
# show speed
ds: 0
# -1=all time
tm: -1
# seed not seen -1=disregard
sns: -1
# group releases -1=not selected
srg: -1
# title search
nm: "{{ .Keywords }}"
# find a username
pn: ""
# search by partial word
allw: 0
rows:
selector: tr[id^="tor_"]:has(a[href^="./dl.php?id="])
fields:
category:
selector: a.gen
attribute: href
filters:
- name: querystring
args: f
title:
selector: a.tLink
details:
selector: a.tLink
attribute: href
download:
selector: a[href^="./dl.php?id="]
attribute: href
magnet:
optional: true
selector: a[href^="magnet:?xt="]
attribute: href
size:
selector: td:nth-child(6) > u
seeders:
selector: td.seedmed > b
leechers:
selector: td.leechmed > b
grabs:
selector: td:nth-child(9)
date:
selector: td:last-child > u
downloadvolumefactor:
text: 1
uploadvolumefactor:
text: 1
# TorrentPier

View File

@@ -0,0 +1,186 @@
---
site: exkinoray
name: ExKinoRay
description: "ExKinoRay is a RUSSIAN Semi-Private Torrent Tracker for MOVIES / TV"
language: ru-ru
type: semi-private
encoding: UTF-8
links:
- http://exkinoray.tv/ # site forces http, does not support https
caps:
categorymappings:
- {id: 92, cat: TV, desc: "Кино Сериал"}
- {id: 46, cat: Movies, desc: "Кино Комедия"}
- {id: 47, cat: Movies, desc: "Кино Боевик"}
- {id: 48, cat: Movies, desc: "Кино Военный"}
- {id: 49, cat: Movies, desc: "Кино Вестерн"}
- {id: 50, cat: Movies, desc: "Кино Триллер"}
- {id: 51, cat: Movies, desc: "Кино Детектив"}
- {id: 52, cat: Movies, desc: "Кино Драма"}
- {id: 53, cat: Movies, desc: "Кино Мелодрама"}
- {id: 54, cat: Movies, desc: "Кино Индийское"}
- {id: 55, cat: Movies, desc: "Кино Азиатское"}
- {id: 59, cat: Movies, desc: "Кино Фантастика"}
- {id: 60, cat: Movies, desc: "Кино Фэнтези"}
- {id: 61, cat: Movies, desc: "Кино Ужас"}
- {id: 62, cat: Movies, desc: "Кино Мистика"}
- {id: 63, cat: Movies, desc: "Кино Приключения"}
- {id: 64, cat: Movies, desc: "Кино Наше кино"}
- {id: 65, cat: Movies, desc: "Кино Исторический"}
- {id: 66, cat: TV/Documentary, desc: "Кино Документальный"}
- {id: 67, cat: TV/Sport, desc: "Кино Спорт"}
- {id: 68, cat: Movies, desc: "Кино Семейный"}
- {id: 69, cat: Movies, desc: "Кино Детский"}
- {id: 70, cat: Movies, desc: "Кино Классика"}
- {id: 71, cat: Movies, desc: "Кино Концерт"}
- {id: 72, cat: TV, desc: "Кино ТВ-шоу"}
- {id: 73, cat: Movies, desc: "Кино Театр, опера"}
- {id: 74, cat: Movies, desc: "Кино Мюзикл"}
- {id: 75, cat: Movies, desc: "Кино Эротика"}
- {id: 77, cat: TV, desc: "Мульт Буржуйский"}
- {id: 78, cat: TV, desc: "Мульт Русский"}
- {id: 79, cat: TV/Anime, desc: "Мульт Аниме"}
- {id: 80, cat: Audio, desc: "Музыка Буржуйская"}
- {id: 81, cat: Audio, desc: "Музыка Русская"}
- {id: 82, cat: Audio, desc: "Музыка Сборники"}
- {id: 83, cat: Audio/Audiobook, desc: "Другое Аудио книги"}
- {id: 84, cat: Audio/Video, desc: "Другое Видеоклипы"}
- {id: 85, cat: PC/Games, desc: "Другое Игры"}
- {id: 86, cat: PC/0day, desc: "Другое Программы"}
- {id: 87, cat: Console/Xbox, desc: "Другое XBox"}
- {id: 88, cat: Console/PSP, desc: "Другое PSP"}
- {id: 89, cat: Books/Magazines, desc: "Другое Журналы"}
- {id: 90, cat: Other, desc: "Другое Графика"}
- {id: 93, cat: Other, desc: "Другое Библиотека"}
- {id: 94, cat: Console/PS3, desc: "Другое PS3"}
modes:
search: [q]
tv-search: [q, season, ep]
movie-search: [q]
settings:
- name: username
type: text
label: Username
- name: password
type: password
label: Password
- name: striprussian
type: checkbox
label: Strip Russian Letters
default: false
- name: sort
type: select
label: Sort requested from site
default: "4"
options:
"4": "created"
"7": "seeders"
"5": "size"
- name: type
type: select
label: Order requested from site
default: "desc"
options:
"desc": "desc"
"asc": "asc"
- name: info_search
type: info
label: "Searching with Season / Episode (S01E01)"
default: "The web site does support season/episode searching. To allow some results for Sonarr, these are stripped from the keywords."
login:
path: takelogin.php
method: post
inputs:
username: "{{ .Config.username }}"
password: "{{ .Config.password }}"
autologin: 1
returnto: "index.php"
error:
- selector: td.embedded:contains("Ошибка входа")
test:
path: index.php
selector: a[href="logout.php"]
search:
paths:
# http://exkinoray.tv/browse.php?search=&incldead=1&cat=0
- path: browse.php
keywordsfilters:
# the site does not support season/episode searching in the title.
- name: re_replace # strip S01
args: ["(?i)\\bS0*(\\d+)\\b", ""]
- name: re_replace # strip S01E01
args: ["(?i)\\bS0*(\\d+)E0*(\\d+)\\b", ""]
inputs:
$raw: "{{ if .Categories }}{{ range .Categories }}c{{.}}=1&{{end}}{{else}}cat=0{{end}}"
# 0 active 1 incldead 2 onlydead 4 noseeds (isn't this == onlydead?)
incldead: 1
search: "{{ .Keywords }}"
sort: "{{ .Config.sort }}"
type: "{{ .Config.type }}"
rows:
selector: table.begins > tbody > tr:has(a[href^="details.php?id="])
fields:
category:
selector: a[href^="browse.php?cat="]
attribute: href
filters:
- name: querystring
args: cat
title:
selector: a[href^="details.php?id="]
filters:
# Женские секреты (1 сезон: 1-4 серии из 12) Жіночі секрети | 2020 | HDTVRip (720p)
# Мандалорец (1 сезон: 1-8 серии из 8) | The Mandalorian | 2019 | WEB-DL (720p)
# Война семей (1-14 серии из 20) | 2019 | WEB-DLRip (AVC)
# normalize to SXXEYY format
- name: replace
args: [" | ", " "]
- name: re_replace
args: ["\\((\\d+)\\s+[Сс]езон:\\s+(?:(\\d+-*\\d*)\\s+[Сс]ери[ия]\\s+.*\\d+)\\)(.*)\\s([12][0-9]{3})\\s(.*)", "$3 - S$1E$2 - rus $5"]
- name: re_replace
args: ["\\((?:(\\d+-*\\d*)\\s+[Сс]ери[ия]\\s+.*\\d+)\\)(.*)\\s([12][0-9]{3})\\s(.*)", "$2 - S1E$1 - rus $4"]
- name: re_replace
args: ["(\\([А-Яа-яЁё\\W]+\\))|(^[А-Яа-яЁё\\W\\d]+\\/ )|([а-яА-ЯЁё \\-]+,+)|([а-яА-ЯЁё]+)", "{{ if .Config.striprussian }}{{ else }}$1$2$3$4{{ end }}"]
- name: re_replace
args: ["\\((\\d+p)\\)", "$1"]
- name: re_replace
args: [" - ", " "]
- name: replace
args: ["-Rip", "Rip"]
- name: replace
args: ["WEB-DL", "WEBDL"]
- name: replace
args: ["WEBDLRip", "WEBDL"]
- name: replace
args: ["HDTVRip", "HDTV"]
details:
selector: a[href^="details.php?id="]
attribute: href
download:
selector: a[href^="download.php?id="]
attribute: href
date:
selector: td:nth-child(2) i
filters:
- name: dateparse
args: "2006-01-02 15:04:03"
files:
selector: td:nth-child(3)
size:
selector: td:nth-child(5)
seeders:
selector: td:nth-child(6)
leechers:
selector: td:nth-child(7)
downloadvolumefactor:
text: 0
uploadvolumefactor:
text: 1
# engine n/a

View File

@@ -1,9 +1,9 @@
---
site: film-paleis
name: Film-Paleis
description: "Film-Paleis is a DUTCH Semi-Private Torrent Tracker for MOVIES / TV / GENERAL"
description: "Film-Paleis is a DUTCH Private Torrent Tracker for MOVIES / TV / GENERAL"
language: nl-NL
type: semi-private
type: private
encoding: UTF-8
links:
- https://www.film-paleis.me/
@@ -39,6 +39,21 @@
tv-search: [q, season, ep]
movie-search: [q]
settings:
- name: username
type: text
label: Username
- name: password
type: password
label: Password
- name: thankyou
type: text
label: Thank You Comment
- name: info
type: info
label: Thank you comment
default: This site requires you to leave a Thank You comment before you can download. Enter your personalised comment above. Minimum of at least 10 characters.
login:
path: takelogin.php
method: post
@@ -51,6 +66,18 @@
path: /
selector: a[href="logout.php"]
download:
before:
path: comment.php
method: post
inputs:
action: add
tid: "{{ .DownloadUri.Query.id }}"
text: "{{ .Config.thankyou }}"
submit: Opslaan
selector: a[href^="download.php?id="]
attribute: href
search:
paths:
- path: browse.php
@@ -79,9 +106,6 @@
download:
selector: a[href^="details.php?id="]
attribute: href
filters:
- name: replace
args: ["details", "download"]
size:
selector: td:nth-child(4) table tr td:nth-child(2)
filters:

View File

@@ -0,0 +1,147 @@
---
site: filmsclub
name: FilmsClub
description: "FilmsClub is a RUSSIAN Semi-Private Torrent Tracker for MOVIES / TV"
language: ru-ru
type: semi-private
encoding: UTF-8
links:
- https://films.club/
caps:
categorymappings:
- {id: 1, cat: Movies, desc: "Зарубежное кино (Foreign cinema)"}
- {id: 2, cat: Movies, desc: "Российское кино (Russian cinema)"}
- {id: 3, cat: TV, desc: "Сериалы (Series)"}
- {id: 4, cat: TV/Documentary, desc: "Документальное кино (Docs)"}
- {id: 5, cat: TV/Anime, desc: "Аниме (Anime)"}
- {id: 6, cat: TV, desc: "Мультфильмы (Cartoons)"}
modes:
search: [q]
tv-search: [q, season, ep]
movie-search: [q]
settings:
- name: username
type: text
label: Username
- name: password
type: password
label: Password
- name: striprussian
type: checkbox
label: Strip Russian Letters
default: false
- name: info_search
type: info
label: "Searching with Season / Episode (S01E01)"
default: "The web site does support season/episode searching as they are not part of the title. To allow some results for Sonarr, these are stripped from the keywords."
login:
path: /
method: form
form: form#enterForm
submitpath: login/
inputs:
username: "{{ .Config.username }}"
password: "{{ .Config.password }}"
error:
- selector: div.error
test:
path: /
selector: div.user-login
search:
paths:
# https://films.club/torrent/list/?f=0&name=mandalorian&description=&year=&page_size=100
# https://films.club/torrent/list/?f=0&name=&description=&year=&category=1&category=2&category=3&category=4&category=5&category=6
- path: torrent/list/
keywordsfilters:
# the site does not support season/episode searching in the title, they are not part of title. searching description for them does not work either.
- name: re_replace # strip S01
args: ["(?i)\\bS0*(\\d+)\\b", ""]
- name: re_replace # strip S01E01
args: ["(?i)\\bS0*(\\d+)E0*(\\d+)\\b", ""]
inputs:
$raw: "{{ if .Categories }}{{ range .Categories }}category={{.}}&{{end}}{{else}}{{end}}"
f: 0
page_size: 100
name: "{{ .Keywords }}"
description: ""
year: ""
rows:
selector: table.torrents-table > tbody > tr
fields:
category:
selector: td.category
case:
"div:contains(\"Зарубежное\")": 1
"div:contains(\"Российское\")": 2
"div:contains(\"Сериалы\")": 3
"div:contains(\"Документальное \")": 4
"div:contains(\"Аниме\")": 5
"div:contains(\"Мультфильмы\")": 6
title:
selector: a[href^="/torrent/"]
filters:
# normalize to SXXEYY format
- name: re_replace
args: ["[\\:\\-\\/\\|]", " "]
- name: re_replace
args: ["(.*)[CСcс]езон\\s+(\\d+).+[CСcс]ери[ия]\\s+(\\d+)\\s+(\\d+).+(.*)", "$1 S$2E$3-$4 rus $5"]
- name: re_replace
args: ["(.*)[CСcс]езон\\s+(\\d+)(.*)", "$1 S$2 rus $3"]
- name: re_replace
args: ["(\\([А-Яа-яЁё\\W]+\\))|(^[А-Яа-яЁё\\W\\d]+\\/ )|([а-яА-ЯЁё \\-]+,+)|([а-яА-ЯЁё]+)", "{{ if .Config.striprussian }}{{ else }}$1$2$3$4{{ end }}"]
- name: replace
args: [" Rip", "Rip"]
- name: replace
args: ["WEB DL", "WEBDL"]
- name: replace
args: ["WEBDLRip", "WEBDL"]
- name: replace
args: ["HDTVRip", "HDTV"]
details:
selector: a[href^="/torrent/"]
attribute: href
download:
selector: a[href$="/download/"]
attribute: href
banner:
selector: td.image div img
attribute: src
date:
selector: div.added
filters:
- name: regexp
args: "Добавлено:(.+?)$"
- name: dateparse
args: "02.01.2006, 15:04"
size:
selector: td.size
filters:
- name: replace
args: [",", "."]
- name: replace
args: ["ТБ", "TB"]
- name: replace
args: ["ГБ", "GB"]
- name: replace
args: ["МБ", "MB"]
- name: replace
args: ["КБ", "KB"]
seeders:
selector: td.peers span.up
leechers:
selector: td.peers span.down
grabs:
selector: td.stat
downloadvolumefactor:
text: 0
uploadvolumefactor:
text: 1
# engine n/a

View File

@@ -1,11 +1,9 @@
---
# By LA5T for https://gay-torrents.org (29.07.2018 22:55 UTC+2)
#
site: gay-torrentsorg
name: gay-torrents.org
description: "Gay-Torrents.org is a Private Torrent Tracker for GAY XXX"
language: en-us
type: semi-private
type: private
encoding: UTF-8
links:
- https://gay-torrents.org/
@@ -148,4 +146,5 @@
"*": 1
uploadvolumefactor:
case:
"*": 1
"*": 1
# engine tbd

View File

@@ -162,10 +162,10 @@
path: account-login.php
method: post
inputs:
username: "{{ .Config.username }}"
login_name: "{{ .Config.username }}"
password: "{{ .Config.password }}"
error:
- selector: td.tboxhead
- selector: td#msgError
test:
path: index.php
selector: a[href="account-logout.php"]

View File

@@ -6,6 +6,8 @@
type: private
encoding: windows-1253
links:
- https://www.greek-team.cc/
legacylinks:
- http://www.greek-team.cc/
caps:

View File

@@ -1,9 +1,9 @@
---
site: hddolby
name: HDDolby
description: "HD Dolby is a CHINESE Semi-Private Torrent Tracker for HD MOVIES / TV / GENERAL"
description: "HD Dolby is a CHINESE Private Torrent Tracker for HD MOVIES / TV / GENERAL"
language: zh-cn
type: semi-private
type: private
encoding: UTF-8
links:
- https://www.hddolby.com/

View File

@@ -6,9 +6,10 @@
type: private
encoding: UTF-8
links:
- http://hdtorrents.xyz/
- https://hdtorrents.xyz/
legacylinks:
- http://hdtorrents.it/
- http://hdtorrents.xyz/
caps:
categorymappings:

View File

@@ -16,12 +16,12 @@
- {id: 23, cat: Books, desc: "Cartoons"}
- {id: 73, cat: Audio/Video, desc: "Concert/Videoclip"}
- {id: 75, cat: Other, desc: "Diverse"}
- {id: 69, cat: Books, desc: "Documentare"}
- {id: 51, cat: TV/Documentary, desc: "Documentaries"}
- {id: 69, cat: TV/Documentary, desc: "Docs RO"}
- {id: 51, cat: TV/Documentary, desc: "Docs"}
- {id: 43, cat: Books, desc: "eBooks"}
- {id: 63, cat: Movies/DVD, desc: "Filme DVD"}
- {id: 65, cat: Movies/HD, desc: "Filme HD"}
- {id: 64, cat: Movies/SD, desc: "Filme Xvid"}
- {id: 64, cat: Movies/SD, desc: "Filme SD"}
- {id: 40, cat: Console, desc: "Games/Console"}
- {id: 26, cat: PC/Games, desc: "Games/PC"}
- {id: 38, cat: PC/Phone-Other, desc: "Mobile"}
@@ -45,24 +45,52 @@
- {id: 87, cat: Other, desc: "TUTS"}
- {id: 33, cat: TV/SD, desc: "TV Episodes"}
- {id: 34, cat: TV/HD, desc: "TVHD Episodes"}
- {id: 9, cat: XXX, desc: "XXX"}
- {id: 9, cat: XXX, desc: "XXX Video"}
- {id: 11, cat: XXX, desc: "XXX Magazine"}
- {id: 58, cat: XXX, desc: "XXX Pictures"}
modes:
search: [q]
tv-search: [q, season, ep, imdbid]
movie-search: [q, imdbid]
settings:
- name: username
type: text
label: Username
- name: password
type: password
label: Password
# causes server 500 errors
# - name: sort
# type: select
# label: Sort requested from site
# default: "date"
# options:
# "date": "created"
# "seeders": "seeders"
# "size": "size"
# - name: type
# type: select
# label: Order requested from site
# default: "DESC"
# options:
# "DESC": "desc"
# "ASC": "asc"
login:
path: login.php
path: login
method: form
form: form
inputs:
username: "{{ .Config.username }}"
password: "{{ .Config.password }}"
_remember_me: on
error:
- selector: div.alert:contains("failed")
test:
path: browse.php
path: /
selector: a[href^="/logout?_csrf_token="]
ratio:
text: -1
@@ -70,46 +98,49 @@
search:
paths:
- path: browse.php
categorymappings: ["!", 9]
categorymappings: ["!", 9, 11, 58]
- path: browseadult.php
categorymappings: [9]
categorymappings: [9, 11, 58]
inputs:
$raw: "{{ range .Categories }}c{{.}}=1&{{end}}"
search: "{{ if .Query.IMDBID }}{{ .Query.IMDBIDShort }}{{else}}{{ .Keywords }}{{end}}"
# 0 onlyalive 3 rosubbed 4 requested
incldead: 1
search_by: "{{ if .Query.IMDBID }}imdb{{else}}name{{end}}"
# by: "{{ .Config.sort }}"
# ord: "{{ .Config.type }}"
rows:
selector: table.table-striped > tbody > tr:has(a[href^="details.php?id="])
fields:
title:
selector: a[href^="details.php?id="]
details:
selector: a[href^="details.php?id="]
attribute: href
category:
selector: a[href^="?cat="]
attribute: href
filters:
- name: querystring
args: cat
title:
selector: a[href^="details.php?id="]
details:
selector: a[href^="details.php?id="]
attribute: href
banner:
attribute: rel
imdb:
selector: a[href*="www.imdb.com/title/"]
selector: a[href*="www.imdb.com"]
optional: true
attribute: href
download:
selector: a[href^="download.php"]
attribute: href
files:
selector: a[href$="filelist=1#filelist"]
selector: a[href$="#filelist"]
filters:
- name: regexp
args: (\d+)
size: # some users's have an extra column after the size/files and before the seeders column (Issue #2243)
selector: td:has(a[href$="filelist=1#filelist"])
selector: td:has(a[href$="#filelist"])
remove: a
date:
selector: td > small:has(i.fa-clock), td > span.small:has(i.fa-clock)

View File

@@ -6,6 +6,8 @@
type: public
encoding: UTF-8
links:
- https://www.moviesdvdr.co/
legacylinks:
- https://www.moviesdvdr.me/
caps:

View File

@@ -54,10 +54,14 @@
title:
selector: a[href^="./viewtopic.php?t="] > b
filters:
- name: re_replace
args: ["\\b(\\d)\\b", "0$1"]
- name: re_replace
args: [".+Сезон\\s+(\\d+)(?:.+Серия\\s+(\\d+))*[\\s\\S]*\\/\\s+(.+)\\s+\\(\\d+\\)\\s+(\\S*)\\s*(\\w*\\d*).*", "$3 - S$1E$2 - rus $5 $4 newstudio"]
- name: re_replace
args: ["\\bS(\\d{1})\\b", "S0$1"]
- name: re_replace
args: ["\\bS(\\d{1})", "S0$1"]
- name: re_replace
args: ["\\bS(\\d+)E(\\d{1})\\b", "S$1E0$2"]
- name: replace
args: ["WEBDLRip","WEBDL"]
- name: replace

View File

@@ -73,10 +73,14 @@
title:
selector: a[href^="./viewtopic.php?t="] > b
filters:
- name: re_replace
args: ["\\b(\\d)\\b", "0$1"]
- name: re_replace
args: [".+Сезон\\s+(\\d+)(?:.+Серия\\s+(\\d+))*[\\s\\S]*\\/\\s+(.+)\\s+\\(\\d+\\)\\s+(\\S*)\\s*(\\w*\\d*).*", "$3 - S$1E$2 - rus $5 $4 newstudio"]
- name: re_replace
args: ["\\bS(\\d{1})\\b", "S0$1"]
- name: re_replace
args: ["\\bS(\\d{1})", "S0$1"]
- name: re_replace
args: ["\\bS(\\d+)E(\\d{1})\\b", "S$1E0$2"]
- name: replace
args: ["WEBDLRip","WEBDL"]
- name: replace

View File

@@ -1,9 +1,9 @@
---
site: prostylex
name: ProStyleX
description: "ProStyleX is a Public torrent site for 0Day and General"
description: "ProStyleX is a Semi-Private torrent site for 0Day and General"
language: en-us
type: public
type: semi-private
encoding: UTF-8
links:
- https://prostylex.org/
@@ -72,6 +72,12 @@
movie-search: [q]
settings:
- name: username
type: text
label: Username
- name: password
type: password
label: Password
- name: sort
type: select
label: Sort requested from site
@@ -89,6 +95,18 @@
"desc": "desc"
"asc": "asc"
login:
path: account-login.php
method: post
inputs:
username: "{{ .Config.username }}"
password: "{{ .Config.password }}"
remember: yes
error:
- selector: div.myFrame:contains("Access Denied")
test:
path: torrents-search.php
download:
selector: a[href^="magnet:?"]
attribute: href

View File

@@ -16,6 +16,7 @@
- {id: 2, cat: TV/Sport, desc: "Documentaries TV"}
- {id: 3, cat: TV/Sport, desc: "DTM"}
- {id: 22, cat: TV/Sport, desc: "Formula 2"}
- {id: 23, cat: TV/Sport, desc: "Formula E"}
- {id: 24, cat: TV/Sport, desc: "Misc"}
- {id: 25, cat: TV/Sport, desc: "Other Bikes"}
- {id: 26, cat: TV/Sport, desc: "MotoGP 2-3-E"}
@@ -42,6 +43,8 @@
- {id: 76, cat: TV/Sport, desc: "ARCA"}
- {id: 77, cat: TV/Sport, desc: "Blancpain GT"}
- {id: 78, cat: TV/Sport, desc: "Porsche Supercup"}
- {id: 79, cat: TV/Sport, desc: "TV Series"}
- {id: 80, cat: TV/Sport, desc: "Touring Cars"}
modes:
search: [q]
@@ -95,7 +98,7 @@
search:
paths:
- path: filterTorrents
- path: torrents/filter
inputs:
$raw: "{{ range .Categories }}categories[]={{.}}&{{end}}"
search: "{{ if .Query.IMDBID }}{{else}}{{ .Keywords }}{{end}}"
@@ -118,7 +121,7 @@
attribute: href
filters:
- name: regexp
args: "/categories/.*?\\.(\\d+)"
args: "/categories/(\\d+)"
title:
selector: a.view-torrent
download:
@@ -127,6 +130,13 @@
details:
selector: a.view-torrent
attribute: href
banner:
optional: true
selector: div.torrent-poster img
attribute: src
filters:
- name: replace
args: ["https://via.placeholder.com/600x900", ""]
comments:
selector: a[href*="#comments"]
attribute: href
@@ -195,4 +205,4 @@
i[class*="fa-globe text-green"]: 2 # Global Double Upload
i[class*="fa-certificate text-pink"]: 2 # Featured Torrent
"*": 1
# UNIT3D 1.9.4
# UNIT3D 2.2.7

View File

@@ -22,7 +22,7 @@
- {id: 15, cat: TV/SD, desc: "Folgen SD"}
- {id: 16, cat: TV/HD, desc: "Folgen HD"}
- {id: 17, cat: TV/SD, desc: "Staffeln SD"}
- {id: 18, cat: TV/HD, desc: "Staffeln SD"}
- {id: 18, cat: TV/HD, desc: "Staffeln HD"}
- {id: 19, cat: Audio/Lossless, desc: "Flac"}
- {id: 20, cat: Audio/MP3, "Packs Mp3"}
- {id: 21, cat: Audio/MP3, desc: "Mixe Mp3"}
@@ -75,16 +75,24 @@
# "asc": "asc"
login:
path: sbg_login_new.php
method: form
path: index.php?page=login
method: post
inputs:
uid: "{{ .Config.username }}"
pwd: "{{ .Config.password }}"
error:
- selector: div.altertBoxStyle:contains("Passwort falsch")
- selector: div.altertBoxStyle:contains("Benutzername falsch")
- selector: body[onLoad^="makeAlert('"]
message:
selector: body[onLoad^="makeAlert('"]
attribute: onLoad
filters:
- name: replace
args: ["makeAlert('Error' , '", ""]
- name: replace
args: ["');", ""]
test:
path: index.php
selector: a[href="logout.php"]
download:
selector: a[href^="download.php?id="]
@@ -94,10 +102,9 @@
paths:
- path: index.php
inputs:
#$raw: "&categories={{ range .Categories }}{{.}};{{end}}"
$raw: "&categories={{ join .Categories \";\"}}{{end}}"
search: "{{ .Query.Keywords }}"
page: "torrents"
search: "{{ .Keywords }}"
category: "{{ if .Categories }}{{ range .Categories }}{{.}};{{end}}{{else}}0{{end}}"
options: 0
active: 0
rows:

View File

@@ -7,7 +7,7 @@
encoding: UTF-8
followredirect: true
links:
- https://www.torrent9.so/
- https://www.torrent9.pl/
legacylinks:
- https://www.torrents9.pw/
@@ -31,6 +31,7 @@
- https://www.t9.re/
- https://www.t9.vc/
- https://www.torrent9.ai/
- https://www.torrent9.so/
caps:
categorymappings:

View File

@@ -0,0 +1,82 @@
---
site: torrentview
name: TorrentView
description: "Torrent View (토렌트뷰) is a Public KOREAN tracker for Korean media."
language: ko-KR
type: public
encoding: UTF-8
links:
- https://torrentview3.net/
legacylinks:
- https://torrentview.net/
caps:
categorymappings:
- {id: "mov", cat: Movies, desc: "토렌트영화 (Movies)"}
- {id: "enter", cat: TV, desc: "예능 (TV Variety Shows)"}
- {id: "drama", cat: TV, desc: "드라마 (TV Dramas)"}
- {id: "tv", cat: TV/Documentary, desc: "시사 (Documentaries)"}
- {id: "netflix", cat: TV, desc: "넷플릭스 (Netflix, Disney+, etc.)"}
- {id: "util", cat: PC, desc: "토렌트유틸 (Utilities)"}
- {id: "ani", cat: TV/Anime, desc: "애니 (Anime)"}
- {id: "music", cat: Audio, desc: "음원 (Music)"}
modes:
search: [q]
settings: []
download:
selector: a[href^="magnet:?xt="]
attribute: href
search:
paths:
# https://torrentview3.net/bbs/search.php?srows=10&gr_id=&sfl=wr_subject&stx=test&sop=and
- path: "bbs/search.php"
inputs:
# number of rows
srows: 100
# category: all
gr_id: ""
# search in: title
sfl: wr_subject
stx: "{{ if .Keywords }}{{ .Keywords }}{{else}}금요일{{end}}"
# search operand: or, and
sop: and
rows:
selector: div.search-media > div.media
fields:
category:
selector: div.media-content > a[href^="./board.php"]
attribute: href
filters:
- name: querystring
args: bo_table
title:
selector: div.media-content > a[href^="./board.php"] > span
details:
selector: div.media-content > a[href^="./board.php"]
attribute: href
download:
selector: div.media-content > a[href^="./board.php"]
attribute: href
date:
selector: time
attribute: datetime
filters:
- name: dateparse
args: "2006-01-02T15:04:05+09:00"
size:
text: "512 MB"
seeders:
text: 1
leechers:
text: 1
downloadvolumefactor:
text: 0
uploadvolumefactor:
text: 1
# engine n/a

View File

@@ -0,0 +1,191 @@
---
site: ttsweb
name: TTsWeb
description: "TTsWeb is a Private Torrent Tracker for MOVIES / TV / GENERAL"
language: en
type: private
encoding: UTF-8
links:
- https://ttsweb.org/
caps:
categorymappings:
- {id: 10, cat: PC/0day, desc: "Apps 0day"}
- {id: 26, cat: PC, desc: "Apps Linux"}
- {id: 30, cat: PC/Mac, desc: "Apps Mac"}
- {id: 39, cat: PC/Phone-Other, desc: "Apps Mobile"}
- {id: 9, cat: PC, desc: "Apps PC"}
- {id: 56, cat: Console/PSP, desc: "Games PSP"}
- {id: 52, cat: Console/NDS, desc: "Games DS"}
- {id: 27, cat: PC/Games, desc: "Games Linux"}
- {id: 28, cat: PC/Games, desc: "Games Mac"}
- {id: 40, cat: Console/Other, desc: "Games Mobile"}
- {id: 34, cat: PC/Games, desc: "Games PC"}
- {id: 14, cat: Console/PS3, desc: "Games PS3"}
- {id: 12, cat: Console/Wii, desc: "Games Wii"}
- {id: 13, cat: Console/Xbox 360, desc: "Games Xbox360"}
- {id: 41, cat: Audio/Audiobook, desc: "Books AudioBooks"}
- {id: 11, cat: Books/Ebook, desc: "Books EBooks"}
- {id: 74, cat: Books/Other, desc: "Books Misc"}
- {id: 64, cat: Movies/3D, desc: "Movies 3D Bluray"}
- {id: 29, cat: Movies/BluRay, desc: "Movies Bluray"}
- {id: 33, cat: Movies, desc: "Movies CAM TS"}
- {id: 18, cat: Movies/DVD, desc: "Movies DVDR"}
- {id: 70, cat: Movies/HD, desc: "Movies HD"}
- {id: 38, cat: Movies/HD, desc: "Movies HD H265"}
- {id: 75, cat: Movies, desc: "Movies Old"}
- {id: 71, cat: Movies, desc: "Movies Packs"}
- {id: 73, cat: Movies, desc: "Movies Remux"}
- {id: 15, cat: Movies/SD, desc: "Movies SD"}
- {id: 65, cat: Movies/WEBDL, desc: "Movies WEB-DL"}
- {id: 77, cat: TV, desc: "TV Movies"}
- {id: 19, cat: Audio/Lossless, desc: "Music FLAC"}
- {id: 72, cat: Audio/Lossless, desc: "Music FLAC Packs"}
- {id: 20, cat: Audio/MP3, desc: "Music MP3"}
- {id: 63, cat: Audio/MP3, desc: "Music MP3 Packs"}
- {id: 36, cat: Audio/Other, desc: "Music Misc"}
- {id: 22, cat: Audio/Video, desc: "Music MVID"}
- {id: 81, cat: TV/Sport, desc: "TV Sport HD"}
- {id: 83, cat: TV/Sport, desc: "TV Sport Packs"}
- {id: 82, cat: TV/Sport, desc: "TV Sport SD"}
- {id: 16, cat: TV/Anime, desc: "TV Anime"}
- {id: 32, cat: TV/HD, desc: "TV Bluray"}
- {id: 23, cat: TV/Documentary, desc: "TV Docs"}
- {id: 35, cat: TV/HD, desc: "TV HD X264"}
- {id: 37, cat: TV/HD, desc: "TV HD H265"}
- {id: 47, cat: TV, desc: "TV Packs"}
- {id: 31, cat: TV, desc: "TV Rips"}
- {id: 24, cat: TV/SD, desc: "TV SD X264"}
- {id: 66, cat: TV/WEB-DL, desc: "TV WEB-DL"}
modes:
search: [q]
tv-search: [q, season, ep]
movie-search: [q]
settings:
- name: username
type: text
label: Username
- name: password
type: password
label: Password
- name: sort
type: select
label: Sort requested from site
default: "4"
options:
"4": "created"
"7": "seeders"
"5": "size"
"1": "title"
- name: type
type: select
label: Order requested from site
default: "desc"
options:
"desc": "desc"
"asc": "asc"
login:
path: takelogin.php
method: post
inputs:
username: "{{ .Config.username }}"
password: "{{ .Config.password }}"
use_ssl: 1
submitme: "X"
error:
- selector: table.main:contains("Login failed!")
test:
path: /
selector: a[href^="logout.php?hash_please="]
search:
paths:
# uses cats1[]=10 or cats3[]=20 which cannot be supported
- path: browse.php
inputs:
search: "{{.Keywords}}"
# title descr genre all
searchin: title
# 0 active 1 incldead 2 onlydead
incldead: 1
sort: "{{ .Config.sort }}"
type: "{{ .Config.type }}"
rows:
selector: table[border="1"][cellspacing="0"][cellpadding="5"] tr:has(a[href^="details.php?id="]):has(a[href^="browse.php?cat="])
filters:
- name: andmatch
fields:
category:
selector: a[href^="browse.php?cat="]
attribute: href
filters:
- name: querystring
args: cat
title:
selector: a[href^="details.php?id="]
attribute: onmouseover
filters:
- name: regexp
args: "<b>(.*?)</b>"
details:
selector: a[href^="details.php?id="]
attribute: href
download:
selector: a[href^="download.php?torrent="]
attribute: href
banner:
selector: a[href^="details.php?id="]
attribute: onmouseover
optional: true
filters:
- name: regexp
args: "src=\\\\\'(.+?)\\\\\'"
- name: replace
args: ["./pic/noposter.png", ""]
imdb:
selector: a[href*="imdb.com/title/tt"]
attribute: href
optional: true
files:
selector: td:nth-last-child(8)
# 2 flavours of dates
date:
# Today<br> 10:20 AM
# Yesterday<br> 08:03 PM
optional: true
selector: td:nth-last-child(6):contains("day")
filters:
- name: fuzzytime
date:
# Feb 4 2019<br> 10:20 AM
optional: true
selector: td:nth-last-child(6):not(:contains("day"))
filters:
- name: dateparse
args: "Jan 2 2006 03:04 PM"
size:
selector: td:nth-last-child(5)
grabs:
selector: td:nth-last-child(4)
filters:
- name: regexp
args: (\d+)
seeders:
selector: td:nth-last-child(3)
leechers:
selector: td:nth-last-child(2)
downloadvolumefactor:
case:
img[src="./pic/icons2/free.gif"]: 0
img[src="./pic/icons2/silver.gif"]: 0.5
"*": 1
uploadvolumefactor:
case:
img[src="./pic/icons2/doubleseed.gif"]: 2
"*": 1
# U-232 V3.5

View File

@@ -118,13 +118,6 @@
filters:
- name: replace
args: ["https://via.placeholder.com/600x900", ""]
description:
# add a little extra to the banner
selector: a[href*="/categories/"] div i
attribute: data-original-title
filters:
- name: replace
args: [" torrent", ""]
comments:
selector: a[href*="#comments"]
attribute: href
@@ -193,4 +186,4 @@
i[class*="fa-globe text-green"]: 2 # Global Double Upload
i[class*="fa-certificate text-pink"]: 2 # Featured Torrent
"*": 1
# UNIT3D 2.2.6
# UNIT3D 2.2.7

File diff suppressed because it is too large Load Diff

View File

@@ -94,11 +94,12 @@
"asc": "asc"
login:
path: tlogin.php
path: takelogin.php
method: post
inputs:
username: "{{ .Config.username }}"
password: "{{ .Config.password }}"
returnto: "/"
error:
- selector: table.main:contains("Login failed!")
message:

View File

@@ -9,9 +9,7 @@ namespace Jackett.Common
public ConfigurationData ConfigData { get; private set; }
public ExceptionWithConfigData(string message, ConfigurationData data)
: base(message)
{
ConfigData = data;
}
=> ConfigData = data;
}
}

View File

@@ -44,14 +44,8 @@ namespace Jackett.Common.Helpers
}
}
public static void DumpToJson(this CookieContainer cookies, string uri, JToken json)
{
DumpToJson(cookies, new Uri(uri), json);
}
public static void DumpToJson(this CookieContainer cookies, string uri, JToken json) => DumpToJson(cookies, new Uri(uri), json);
public static void DumpToJson(this CookieContainer cookies, Uri uri, JToken json)
{
json["cookie_header"] = cookies.GetCookieHeader(uri);
}
public static void DumpToJson(this CookieContainer cookies, Uri uri, JToken json) => json["cookie_header"] = cookies.GetCookieHeader(uri);
}
}

View File

@@ -9,9 +9,7 @@ namespace Jackett.Common
public IndexerException(IIndexer Indexer, string message, Exception innerException)
: base(message, innerException)
{
this.Indexer = Indexer;
}
=> this.Indexer = Indexer;
public IndexerException(IIndexer Indexer, string message)
: this(Indexer, message, null)

View File

@@ -27,15 +27,15 @@ namespace Jackett.Common.Indexers
/// </summary>
public class Abnormal : BaseCachingWebIndexer
{
private string LoginUrl { get { return SiteLink + "login.php"; } }
private string SearchUrl { get { return SiteLink + "torrents.php"; } }
private string TorrentCommentUrl { get { return TorrentDescriptionUrl; } }
private string TorrentDescriptionUrl { get { return SiteLink + "torrents.php?id="; } }
private string TorrentDownloadUrl { get { return SiteLink + "torrents.php?action=download&id={id}&authkey={auth_key}&torrent_pass={torrent_pass}"; } }
private string ReplaceMulti { get { return ConfigData.ReplaceMulti.Value; } }
private bool Latency { get { return ConfigData.Latency.Value; } }
private bool DevMode { get { return ConfigData.DevMode.Value; } }
private bool CacheMode { get { return ConfigData.HardDriveCache.Value; } }
private string LoginUrl => SiteLink + "login.php";
private string SearchUrl => SiteLink + "torrents.php";
private string TorrentCommentUrl => TorrentDescriptionUrl;
private string TorrentDescriptionUrl => SiteLink + "torrents.php?id=";
private string TorrentDownloadUrl => SiteLink + "torrents.php?action=download&id={id}&authkey={auth_key}&torrent_pass={torrent_pass}";
private string ReplaceMulti => ConfigData.ReplaceMulti.Value;
private bool Latency => ConfigData.Latency.Value;
private bool DevMode => ConfigData.DevMode.Value;
private bool CacheMode => ConfigData.HardDriveCache.Value;
private static string Directory => Path.Combine(Path.GetTempPath(), Assembly.GetExecutingAssembly().GetName().Name.ToLower(), MethodBase.GetCurrentMethod().DeclaringType?.Name.ToLower());
private readonly Dictionary<string, string> emulatedBrowserHeaders = new Dictionary<string, string>();
@@ -43,8 +43,8 @@ namespace Jackett.Common.Indexers
private ConfigurationDataAbnormal ConfigData
{
get { return (ConfigurationDataAbnormal)configData; }
set { base.configData = value; }
get => (ConfigurationDataAbnormal)configData;
set => base.configData = value;
}
public Abnormal(IIndexerConfigurationService configService, Utils.Clients.WebClient w, Logger l, IProtectionService ps)
@@ -633,12 +633,8 @@ namespace Jackett.Common.Indexers
/// Find torrent rows in search pages
/// </summary>
/// <returns>JQuery Object</returns>
private CQ findTorrentRows()
{
// Return all occurencis of torrents found
return fDom[".torrent_table > tbody > tr"].Not(".colhead");
}
// Return all occurences of torrents found
private CQ findTorrentRows() => fDom[".torrent_table > tbody > tr"].Not(".colhead");
/// <summary>
/// Output message for logging or developpment (console)

View File

@@ -15,12 +15,12 @@ namespace Jackett.Common.Indexers.Abstract
public abstract class CouchPotatoTracker : BaseWebIndexer
{
protected string endpoint;
protected string APIUrl { get { return SiteLink + endpoint; } }
protected string APIUrl => SiteLink + endpoint;
private new ConfigurationDataUserPasskey configData
{
get { return (ConfigurationDataUserPasskey)base.configData; }
set { base.configData = value; }
get => (ConfigurationDataUserPasskey)base.configData;
set => base.configData = value;
}
public CouchPotatoTracker(IIndexerConfigurationService configService, WebClient client, Logger logger, IProtectionService p, ConfigurationDataUserPasskey configData, string name, string description, string link, string endpoint)
@@ -47,11 +47,8 @@ namespace Jackett.Common.Indexers.Abstract
return await Task.FromResult(IndexerConfigurationStatus.RequiresTesting);
}
protected virtual string GetSearchString(TorznabQuery query)
{
// can be overriden to alter the search string
return query.GetQueryString();
}
// can be overriden to alter the search string
protected virtual string GetSearchString(TorznabQuery query) => query.GetQueryString();
protected override async Task<IEnumerable<ReleaseInfo>> PerformQuery(TorznabQuery query)
{
@@ -96,10 +93,12 @@ namespace Jackett.Common.Indexers.Abstract
{
foreach (JObject r in json["results"])
{
var release = new ReleaseInfo();
release.Title = (string)r["release_name"];
release.Comments = new Uri((string)r["details_url"]);
release.Link = new Uri((string)r["download_url"]);
var release = new ReleaseInfo
{
Title = (string)r["release_name"],
Comments = new Uri((string)r["details_url"]),
Link = new Uri((string)r["download_url"])
};
release.Guid = release.Link;
release.Imdb = ParseUtil.GetImdbID((string)r["imdb_id"]);
var freeleech = (bool)r["freeleech"];

View File

@@ -18,10 +18,10 @@ namespace Jackett.Common.Indexers.Abstract
{
public abstract class GazelleTracker : BaseWebIndexer
{
protected string LoginUrl { get { return SiteLink + "login.php"; } }
protected string APIUrl { get { return SiteLink + "ajax.php"; } }
protected string DownloadUrl { get { return SiteLink + "torrents.php?action=download&usetoken=" + (useTokens ? "1" : "0") + "&id="; } }
protected string DetailsUrl { get { return SiteLink + "torrents.php?torrentid="; } }
protected string LoginUrl => SiteLink + "login.php";
protected string APIUrl => SiteLink + "ajax.php";
protected string DownloadUrl => SiteLink + "torrents.php?action=download&usetoken=" + (useTokens ? "1" : "0") + "&id=";
protected string DetailsUrl => SiteLink + "torrents.php?torrentid=";
protected bool supportsFreeleechTokens;
protected bool imdbInTags;
protected bool supportsCategories = true; // set to false if the tracker doesn't include the categories in the API search results
@@ -30,8 +30,8 @@ namespace Jackett.Common.Indexers.Abstract
private new ConfigurationDataBasicLogin configData
{
get { return (ConfigurationDataBasicLogin)base.configData; }
set { base.configData = value; }
get => (ConfigurationDataBasicLogin)base.configData;
set => base.configData = value;
}
public GazelleTracker(IIndexerConfigurationService configService, Utils.Clients.WebClient webClient, Logger logger, IProtectionService protectionService, string name, string desc, string link, bool supportsFreeleechTokens, bool imdbInTags = false, bool has2Fa = false)
@@ -138,10 +138,7 @@ namespace Jackett.Common.Indexers.Abstract
}
// hook to adjust the search term
protected virtual string GetSearchTerm(TorznabQuery query)
{
return query.GetQueryString();
}
protected virtual string GetSearchTerm(TorznabQuery query) => query.GetQueryString();
protected override async Task<IEnumerable<ReleaseInfo>> PerformQuery(TorznabQuery query)
{
@@ -269,10 +266,7 @@ namespace Jackett.Common.Indexers.Abstract
}
// hook to add/modify the parsed information, return false to exclude the torrent from the results
protected virtual bool ReleaseInfoPostParse(ReleaseInfo release, JObject torrent, JObject result)
{
return true;
}
protected virtual bool ReleaseInfoPostParse(ReleaseInfo release, JObject torrent, JObject result) => true;
private void FillReleaseInfoFromJson(ReleaseInfo release, JObject torrent)
{

View File

@@ -7,17 +7,11 @@ namespace Jackett.Common.Indexers
{
public class AlphaRatio : GazelleTracker
{
public AlphaRatio(IIndexerConfigurationService configService, Utils.Clients.WebClient webClient, Logger logger, IProtectionService protectionService)
: base(name: "AlphaRatio",
desc: "AlphaRatio (AR) is a Private Torrent Tracker for 0DAY / GENERAL",
link: "https://alpharatio.cc/",
configService: configService,
logger: logger,
protectionService: protectionService,
webClient: webClient,
supportsFreeleechTokens: true,
imdbInTags: true
)
public AlphaRatio(IIndexerConfigurationService configService, Utils.Clients.WebClient webClient, Logger logger,
IProtectionService protectionService) : base(
name: "AlphaRatio", desc: "AlphaRatio (AR) is a Private Torrent Tracker for 0DAY / GENERAL",
link: "https://alpharatio.cc/", configService: configService, logger: logger,
protectionService: protectionService, webClient: webClient, supportsFreeleechTokens: true, imdbInTags: true)
{
Language = "en-us";
Type = "private";
@@ -55,9 +49,7 @@ namespace Jackett.Common.Indexers
AddCategoryMapping(30, TorznabCatType.Other, "Misc");
}
protected override string GetSearchTerm(TorznabQuery query)
{
return query.GetQueryString().Replace(".", " "); // Alpharatio can't handle dots in the searchstr
}
// Alpharatio can't handle dots in the searchstr
protected override string GetSearchTerm(TorznabQuery query) => query.GetQueryString().Replace(".", " ");
}
}

View File

@@ -83,8 +83,8 @@ namespace Jackett.Common.Indexers
private ConfigurationDataAniDub Configuration
{
get { return (ConfigurationDataAniDub)configData; }
set { configData = value; }
get => (ConfigurationDataAniDub)configData;
set => configData = value;
}
/// <summary>
@@ -134,18 +134,11 @@ namespace Jackett.Common.Indexers
return await base.Download(link);
}
// If the search string is empty use the latest releases
protected override async Task<IEnumerable<ReleaseInfo>> PerformQuery(TorznabQuery query)
{
// If the search string is empty use the latest releases
if (query.IsTest || query.SearchTerm.IsNullOrEmptyOrWhitespace())
{
return await FetchNewReleases();
}
else
{
return await PerformSearch(query);
}
}
=> query.IsTest || query.SearchTerm.IsNullOrEmptyOrWhitespace()
? await FetchNewReleases()
: await PerformSearch(query);
private async Task EnsureAuthorized()
{
@@ -258,11 +251,8 @@ namespace Jackett.Common.Indexers
return releases;
}
private static string GetReleaseGuid(string url, IElement tabNode)
{
// Appending id to differentiate between different quality versions
return QueryHelpers.AddQueryString(url, "id", GetTorrentId(tabNode));
}
// Appending id to differentiate between different quality versions
private static string GetReleaseGuid(string url, IElement tabNode) => QueryHelpers.AddQueryString(url, "id", GetTorrentId(tabNode));
private static int GetReleaseLeechers(IElement tabNode)
{
@@ -443,15 +433,9 @@ namespace Jackett.Common.Indexers
return defaultSeason;
}
private string StripRussianTitle(string title)
{
if (Configuration.StripRussianTitle.Value)
{
return StripRussianTitleRegex.Value.Replace(title, string.Empty);
}
return title;
}
private string StripRussianTitle(string title) => Configuration.StripRussianTitle.Value
? StripRussianTitleRegex.Value.Replace(title, string.Empty)
: title;
private static string FixBookInfo(string title) =>
title.Replace("[Главы ", "[");

View File

@@ -19,17 +19,17 @@ namespace Jackett.Common.Indexers
{
public class AnimeBytes : BaseCachingWebIndexer
{
private string ScrapeUrl { get { return SiteLink + "scrape.php"; } }
private string TorrentsUrl { get { return SiteLink + "torrents.php"; } }
public bool AllowRaws { get { return configData.IncludeRaw.Value; } }
public bool PadEpisode { get { return configData.PadEpisode != null && configData.PadEpisode.Value; } }
public bool AddSynonyms { get { return configData.AddSynonyms.Value; } }
public bool FilterSeasonEpisode { get { return configData.FilterSeasonEpisode.Value; } }
private string ScrapeUrl => SiteLink + "scrape.php";
private string TorrentsUrl => SiteLink + "torrents.php";
public bool AllowRaws => configData.IncludeRaw.Value;
public bool PadEpisode => configData.PadEpisode != null && configData.PadEpisode.Value;
public bool AddSynonyms => configData.AddSynonyms.Value;
public bool FilterSeasonEpisode => configData.FilterSeasonEpisode.Value;
private new ConfigurationDataAnimeBytes configData
{
get { return (ConfigurationDataAnimeBytes)base.configData; }
set { base.configData = value; }
get => (ConfigurationDataAnimeBytes)base.configData;
set => base.configData = value;
}
public AnimeBytes(IIndexerConfigurationService configService, Utils.Clients.WebClient client, Logger l, IProtectionService ps)
@@ -74,12 +74,10 @@ namespace Jackett.Common.Indexers
AddCategoryMapping("printedtype[artbook]", TorznabCatType.BooksComics, "Artbook");
}
// Prevent filtering
protected override IEnumerable<ReleaseInfo> FilterResults(TorznabQuery query, IEnumerable<ReleaseInfo> input) =>
protected override IEnumerable<ReleaseInfo> FilterResults(TorznabQuery query, IEnumerable<ReleaseInfo> input)
{
// Prevent filtering
return input;
}
input;
public override async Task<IndexerConfigurationStatus> ApplyConfiguration(JToken configJson)
{
@@ -365,24 +363,26 @@ namespace Jackett.Common.Indexers
releaseTitle = string.Format("{0}{1} {2} {3}", releasegroup, title, releaseInfo, infoString);
}
var release = new ReleaseInfo();
release.MinimumRatio = 1;
release.MinimumSeedTime = MinimumSeedTime;
release.Title = releaseTitle;
release.Comments = CommentsLinkUri;
release.Guid = new Uri(CommentsLinkUri + "&nh=" + StringUtil.Hash(title)); // Sonarr should dedupe on this url - allow a url per name.
release.Link = LinkUri;
release.BannerUrl = ImageUrl;
release.PublishDate = PublushDate;
release.Category = Category;
release.Description = Description;
release.Size = Size;
release.Seeders = Seeders;
release.Peers = Peers;
release.Grabs = Snatched;
release.Files = FileCount;
release.DownloadVolumeFactor = RawDownMultiplier;
release.UploadVolumeFactor = RawUpMultiplier;
var release = new ReleaseInfo
{
MinimumRatio = 1,
MinimumSeedTime = MinimumSeedTime,
Title = releaseTitle,
Comments = CommentsLinkUri,
Guid = new Uri(CommentsLinkUri + "&nh=" + StringUtil.Hash(title)), // Sonarr should dedupe on this url - allow a url per name.
Link = LinkUri,
BannerUrl = ImageUrl,
PublishDate = PublushDate,
Category = Category,
Description = Description,
Size = Size,
Seeders = Seeders,
Peers = Peers,
Grabs = Snatched,
Files = FileCount,
DownloadVolumeFactor = RawDownMultiplier,
UploadVolumeFactor = RawUpMultiplier
};
releases.Add(release);
}

View File

@@ -19,14 +19,14 @@ namespace Jackett.Common.Indexers
{
public class AnimeTorrents : BaseWebIndexer
{
private string LoginUrl { get { return SiteLink + "login.php"; } }
private string SearchUrl { get { return SiteLink + "ajax/torrents_data.php"; } }
private string SearchUrlReferer { get { return SiteLink + "torrents.php?cat=0&searchin=filename&search="; } }
private string LoginUrl => SiteLink + "login.php";
private string SearchUrl => SiteLink + "ajax/torrents_data.php";
private string SearchUrlReferer => SiteLink + "torrents.php?cat=0&searchin=filename&search=";
private new ConfigurationDataBasicLogin configData
{
get { return (ConfigurationDataBasicLogin)base.configData; }
set { base.configData = value; }
get => (ConfigurationDataBasicLogin)base.configData;
set => base.configData = value;
}
public AnimeTorrents(IIndexerConfigurationService configService, WebClient c, Logger l, IProtectionService ps)

View File

@@ -20,15 +20,15 @@ namespace Jackett.Common.Indexers
public class BB : BaseWebIndexer
{
private string BaseUrl { get { return StringUtil.FromBase64("aHR0cHM6Ly9iYWNvbmJpdHMub3JnLw=="); } }
private Uri BaseUri { get { return new Uri(BaseUrl); } }
private string LoginUrl { get { return BaseUri + "login.php"; } }
private string SearchUrl { get { return BaseUri + "torrents.php?searchtags=&tags_type=0&order_by=s3&order_way=desc&disablegrouping=1&"; } }
private string BaseUrl => StringUtil.FromBase64("aHR0cHM6Ly9iYWNvbmJpdHMub3JnLw==");
private Uri BaseUri => new Uri(BaseUrl);
private string LoginUrl => BaseUri + "login.php";
private string SearchUrl => BaseUri + "torrents.php?searchtags=&tags_type=0&order_by=s3&order_way=desc&disablegrouping=1&";
private new ConfigurationDataBasicLogin configData
{
get { return (ConfigurationDataBasicLogin)base.configData; }
set { base.configData = value; }
get => (ConfigurationDataBasicLogin)base.configData;
set => base.configData = value;
}
public BB(IIndexerConfigurationService configService, WebClient w, Logger l, IProtectionService ps)

View File

@@ -22,8 +22,8 @@ namespace Jackett.Common.Indexers
private new ConfigurationDataBasicLogin configData
{
get { return (ConfigurationDataBasicLogin)base.configData; }
set { base.configData = value; }
get => (ConfigurationDataBasicLogin)base.configData;
set => base.configData = value;
}
public BakaBT(IIndexerConfigurationService configService, Utils.Clients.WebClient wc, Logger l, IProtectionService ps)

View File

@@ -18,10 +18,7 @@ namespace Jackett.Common.Indexers
{
public abstract class BaseIndexer : IIndexer
{
public static string GetIndexerID(Type type)
{
return type.Name.ToLowerInvariant().StripNonAlphaNumeric();
}
public static string GetIndexerID(Type type) => type.Name.ToLowerInvariant().StripNonAlphaNumeric();
public string SiteLink { get; protected set; }
public virtual string[] LegacySiteLinks { get; protected set; }
@@ -31,7 +28,7 @@ namespace Jackett.Common.Indexers
public string DisplayName { get; protected set; }
public string Language { get; protected set; }
public string Type { get; protected set; }
public virtual string ID { get { return GetIndexerID(GetType()); } }
public virtual string ID => GetIndexerID(GetType());
[JsonConverter(typeof(EncodingJsonConverter))]
public Encoding Encoding { get; protected set; }
@@ -45,13 +42,13 @@ namespace Jackett.Common.Indexers
protected string CookieHeader
{
get { return configData.CookieHeader.Value; }
set { configData.CookieHeader.Value = value; }
get => configData.CookieHeader.Value;
set => configData.CookieHeader.Value = value;
}
public string LastError
{
get { return configData.LastError.Value; }
get => configData.LastError.Value;
set
{
var SaveNeeded = configData.LastError.Value != value && IsConfigured;
@@ -82,10 +79,7 @@ namespace Jackett.Common.Indexers
LoadValuesFromJson(null);
}
public virtual Task<ConfigurationData> GetConfigurationForSetup()
{
return Task.FromResult<ConfigurationData>(configData);
}
public virtual Task<ConfigurationData> GetConfigurationForSetup() => Task.FromResult<ConfigurationData>(configData);
public virtual void ResetBaseConfig()
{
@@ -93,10 +87,7 @@ namespace Jackett.Common.Indexers
IsConfigured = false;
}
public virtual void SaveConfig()
{
configurationService.Save(this as IIndexer, configData.ToJson(protectionService, forDisplay: false));
}
public virtual void SaveConfig() => configurationService.Save(this as IIndexer, configData.ToJson(protectionService, forDisplay: false));
protected void LoadLegacyCookieConfig(JToken jsonConfig)
{
@@ -273,10 +264,9 @@ namespace Jackett.Common.Indexers
if (query.Categories.Length == 0)
return results;
var filteredResults = results.Where(result =>
{
return result.Category.IsEmptyOrNull() || query.Categories.Intersect(result.Category).Any() || TorznabCatType.QueryContainsParentCategory(query.Categories, result.Category);
});
var filteredResults = results.Where(
result => result.Category.IsEmptyOrNull() || query.Categories.Intersect(result.Category).Any() ||
TorznabCatType.QueryContainsParentCategory(query.Categories, result.Category));
return filteredResults;
}
@@ -372,10 +362,7 @@ namespace Jackett.Common.Indexers
// minimal constructor used by e.g. cardigann generic indexer
protected BaseWebIndexer(IIndexerConfigurationService configService, WebClient client, Logger logger, IProtectionService p)
: base("", "/", "", configService, logger, null, p)
{
webclient = client;
}
: base("", "/", "", configService, logger, null, p) => webclient = client;
public virtual async Task<byte[]> Download(Uri link)
{
@@ -671,10 +658,7 @@ namespace Jackett.Common.Indexers
}
}
protected List<string> GetAllTrackerCategories()
{
return categoryMapping.Select(x => x.TrackerCategory).ToList();
}
protected List<string> GetAllTrackerCategories() => categoryMapping.Select(x => x.TrackerCategory).ToList();
protected void AddCategoryMapping(string trackerCategory, TorznabCategory newznabCategory, string trackerCategoryDesc = null)
{
@@ -703,10 +687,7 @@ namespace Jackett.Common.Indexers
}
}
protected void AddCategoryMapping(int trackerCategory, TorznabCategory newznabCategory, string trackerCategoryDesc = null)
{
AddCategoryMapping(trackerCategory.ToString(), newznabCategory, trackerCategoryDesc);
}
protected void AddCategoryMapping(int trackerCategory, TorznabCategory newznabCategory, string trackerCategoryDesc = null) => AddCategoryMapping(trackerCategory.ToString(), newznabCategory, trackerCategoryDesc);
protected void AddMultiCategoryMapping(TorznabCategory newznabCategory, params int[] trackerCategories)
{

View File

@@ -17,14 +17,14 @@ namespace Jackett.Common.Indexers
{
public class BitCityReloaded : BaseWebIndexer
{
private string LoginUrl { get { return SiteLink + "login/index.php"; } }
private string BrowseUrl { get { return SiteLink + "uebersicht.php"; } }
private string LoginUrl => SiteLink + "login/index.php";
private string BrowseUrl => SiteLink + "uebersicht.php";
private readonly TimeZoneInfo germanyTz = TimeZoneInfo.CreateCustomTimeZone("W. Europe Standard Time", new TimeSpan(1, 0, 0), "W. Europe Standard Time", "W. Europe Standard Time");
private new ConfigurationDataBasicLoginWithRSSAndDisplay configData
{
get { return (ConfigurationDataBasicLoginWithRSSAndDisplay)base.configData; }
set { base.configData = value; }
get => (ConfigurationDataBasicLoginWithRSSAndDisplay)base.configData;
set => base.configData = value;
}
public BitCityReloaded(IIndexerConfigurationService configService, WebClient wc, Logger l, IProtectionService ps)

View File

@@ -18,15 +18,15 @@ namespace Jackett.Common.Indexers
{
public class BitHdtv : BaseWebIndexer
{
private string LoginUrl { get { return SiteLink + "login.php"; } }
private string TakeLoginUrl { get { return SiteLink + "takelogin.php"; } }
private string SearchUrl { get { return SiteLink + "torrents.php?"; } }
private string DownloadUrl { get { return SiteLink + "download.php?id={0}"; } }
private string LoginUrl => SiteLink + "login.php";
private string TakeLoginUrl => SiteLink + "takelogin.php";
private string SearchUrl => SiteLink + "torrents.php?";
private string DownloadUrl => SiteLink + "download.php?id={0}";
private new ConfigurationDataRecaptchaLogin configData
{
get { return (ConfigurationDataRecaptchaLogin)base.configData; }
set { base.configData = value; }
get => (ConfigurationDataRecaptchaLogin)base.configData;
set => base.configData = value;
}
public BitHdtv(IIndexerConfigurationService configService, WebClient w, Logger l, IProtectionService ps)

View File

@@ -22,8 +22,8 @@ namespace Jackett.Common.Indexers
private new ConfigurationDataAPIKey configData
{
get { return (ConfigurationDataAPIKey)base.configData; }
set { base.configData = value; }
get => (ConfigurationDataAPIKey)base.configData;
set => base.configData = value;
}
public BroadcastTheNet(IIndexerConfigurationService configService, WebClient wc, Logger l, IProtectionService ps)

View File

@@ -26,7 +26,7 @@ namespace Jackett.Common.Indexers
public class CardigannIndexer : BaseWebIndexer
{
protected IndexerDefinition Definition;
public override string ID { get { return (Definition != null ? Definition.Site : GetIndexerID(GetType())); } }
public override string ID => (Definition != null ? Definition.Site : GetIndexerID(GetType()));
protected WebClientStringResult landingResult;
protected IHtmlDocument landingResultDocument;
@@ -35,8 +35,8 @@ namespace Jackett.Common.Indexers
private new ConfigurationData configData
{
get { return base.configData; }
set { base.configData = value; }
get => base.configData;
set => base.configData = value;
}
protected readonly string[] OptionalFileds = new string[] { "imdb", "rageid", "tvdbid", "banner" };
@@ -118,6 +118,14 @@ namespace Jackett.Common.Indexers
case "text":
item = new StringItem { Value = Setting.Default };
break;
case "multi-select":
if (Setting.Options == null)
{
throw new Exception("Options must be given for the 'multi-select' type.");
}
item = new CheckboxItem(Setting.Options) { Values = Setting.Defaults };
break;
case "select":
if (Setting.Options == null)
{
@@ -201,21 +209,30 @@ namespace Jackett.Common.Indexers
variables[".Config.sitelink"] = SiteLink;
foreach (var Setting in Definition.Settings)
{
string value;
var item = configData.GetDynamic(Setting.Name);
if (item.GetType() == typeof(BoolItem))
// CheckBox item is an array of strings
if (item.GetType() == typeof(CheckboxItem))
{
value = (((BoolItem)item).Value == true ? "true" : "");
}
else if (item.GetType() == typeof(SelectItem))
{
value = ((SelectItem)item).Value;
variables[".Config." + Setting.Name] = ((CheckboxItem)item).Values;
}
else
{
value = ((StringItem)item).Value;
string value;
if (item.GetType() == typeof(BoolItem))
{
value = (((BoolItem)item).Value == true ? "true" : "");
}
else if (item.GetType() == typeof(SelectItem))
{
value = ((SelectItem)item).Value;
}
else
{
value = ((StringItem)item).Value;
}
variables[".Config." + Setting.Name] = value;
}
variables[".Config." + Setting.Name] = value;
}
return variables;
}
@@ -747,15 +764,9 @@ namespace Jackett.Common.Indexers
return null;
}
protected string getRedirectDomainHint(WebClientByteResult result)
{
return getRedirectDomainHint(result.Request.Url, result.RedirectingTo);
}
protected string getRedirectDomainHint(WebClientByteResult result) => getRedirectDomainHint(result.Request.Url, result.RedirectingTo);
protected string getRedirectDomainHint(WebClientStringResult result)
{
return getRedirectDomainHint(result.Request.Url, result.RedirectingTo);
}
protected string getRedirectDomainHint(WebClientStringResult result) => getRedirectDomainHint(result.Request.Url, result.RedirectingTo);
protected async Task<bool> TestLogin()
{
@@ -1171,13 +1182,7 @@ namespace Jackett.Common.Indexers
return applyFilters(ParseUtil.NormalizeSpace(value), Selector.Filters, variables);
}
protected Uri resolvePath(string path, Uri currentUrl = null)
{
if (currentUrl == null)
currentUrl = new Uri(SiteLink);
return new Uri(currentUrl, path);
}
protected Uri resolvePath(string path, Uri currentUrl = null) => new Uri(currentUrl ?? new Uri(SiteLink), path);
protected override async Task<IEnumerable<ReleaseInfo>> PerformQuery(TorznabQuery query)
{
@@ -1235,7 +1240,7 @@ namespace Jackett.Common.Indexers
variables[".Query.Keywords"] = string.Join(" ", KeywordTokens);
variables[".Keywords"] = applyFilters((string)variables[".Query.Keywords"], Search.Keywordsfilters);
// TODO: prepare queries first and then send them parallel
// TODO: prepare queries first and then send them parallel
var SearchPaths = Search.Paths;
foreach (var SearchPath in SearchPaths)
{

View File

@@ -16,8 +16,6 @@ namespace Jackett.Common.Indexers
protectionService: protectionService,
webClient: webClient
)
{
Type = "private";
}
=> Type = "private";
}
}

View File

@@ -19,8 +19,8 @@ namespace Jackett.Common.Indexers
private new ConfigurationDataUserPasskey configData
{
get { return (ConfigurationDataUserPasskey)base.configData; }
set { base.configData = value; }
get => (ConfigurationDataUserPasskey)base.configData;
set => base.configData = value;
}
public DanishBits(IIndexerConfigurationService configService, WebClient c, Logger l, IProtectionService ps)

View File

@@ -17,14 +17,14 @@ namespace Jackett.Common.Indexers
{
public class DigitalHive : BaseWebIndexer
{
private string SearchUrl { get { return SiteLink + "browse.php"; } }
private string LoginUrl { get { return SiteLink + "login.php?returnto=%2F"; } }
private string AjaxLoginUrl { get { return SiteLink + "takelogin.php"; } }
private string SearchUrl => SiteLink + "browse.php";
private string LoginUrl => SiteLink + "login.php?returnto=%2F";
private string AjaxLoginUrl => SiteLink + "takelogin.php";
private new ConfigurationDataRecaptchaLogin configData
{
get { return (ConfigurationDataRecaptchaLogin)base.configData; }
set { base.configData = value; }
get => (ConfigurationDataRecaptchaLogin)base.configData;
set => base.configData = value;
}
public DigitalHive(IIndexerConfigurationService configService, WebClient w, Logger l, IProtectionService ps)

View File

@@ -18,17 +18,15 @@ namespace Jackett.Common.Indexers
{
internal class EliteTracker : BaseWebIndexer
{
private string LoginUrl
{ get { return SiteLink + "takelogin.php"; } }
private string BrowseUrl
{ get { return SiteLink + "browse.php"; } }
private string LoginUrl => SiteLink + "takelogin.php";
private string BrowseUrl => SiteLink + "browse.php";
private bool TorrentHTTPSMode => configData.TorrentHTTPSMode.Value;
private string ReplaceMulti => configData.ReplaceMulti.Value;
private new ConfigurationDataEliteTracker configData
{
get { return (ConfigurationDataEliteTracker)base.configData; }
set { base.configData = value; }
get => (ConfigurationDataEliteTracker)base.configData;
set => base.configData = value;
}
public EliteTracker(IIndexerConfigurationService configService, WebClient webClient, Logger logger, IProtectionService protectionService)

View File

@@ -23,13 +23,13 @@ namespace Jackett.Common.Indexers
"http://filelist.ro/",
};
private string LoginUrl { get { return SiteLink + "takelogin.php"; } }
private string BrowseUrl { get { return SiteLink + "browse.php"; } }
private string LoginUrl => SiteLink + "takelogin.php";
private string BrowseUrl => SiteLink + "browse.php";
private new ConfigurationDataFileList configData
{
get { return (ConfigurationDataFileList)base.configData; }
set { base.configData = value; }
get => (ConfigurationDataFileList)base.configData;
set => base.configData = value;
}
public FileList(IIndexerConfigurationService configService, WebClient wc, Logger l, IProtectionService ps)

View File

@@ -16,13 +16,13 @@ namespace Jackett.Common.Indexers
{
public class FunFile : BaseWebIndexer
{
private string SearchUrl { get { return SiteLink + "browse.php"; } }
private string LoginUrl { get { return SiteLink + "takelogin.php"; } }
private string SearchUrl => SiteLink + "browse.php";
private string LoginUrl => SiteLink + "takelogin.php";
private new ConfigurationDataBasicLoginWithRSSAndDisplay configData
{
get { return (ConfigurationDataBasicLoginWithRSSAndDisplay)base.configData; }
set { base.configData = value; }
get => (ConfigurationDataBasicLoginWithRSSAndDisplay)base.configData;
set => base.configData = value;
}
public FunFile(IIndexerConfigurationService configService, WebClient w, Logger l, IProtectionService ps)

View File

@@ -23,14 +23,14 @@ namespace Jackett.Common.Indexers
"https://fuzer.me/",
};
private string SearchUrl { get { return SiteLink + "browse.php"; } }
private string LoginUrl { get { return SiteLink + "login.php"; } }
private string SearchUrl => SiteLink + "browse.php";
private string LoginUrl => SiteLink + "login.php";
private const int MAXPAGES = 3;
private new ConfigurationDataRecaptchaLogin configData
{
get { return (ConfigurationDataRecaptchaLogin)base.configData; }
set { base.configData = value; }
get => (ConfigurationDataRecaptchaLogin)base.configData;
set => base.configData = value;
}
public Fuzer(IIndexerConfigurationService configService, Utils.Clients.WebClient w, Logger l, IProtectionService ps)

View File

@@ -18,13 +18,13 @@ namespace Jackett.Common.Indexers
{
public class GazelleGames : BaseWebIndexer
{
private string LoginUrl { get { return SiteLink + "login.php"; } }
private string BrowseUrl { get { return SiteLink + "torrents.php"; } }
private string LoginUrl => SiteLink + "login.php";
private string BrowseUrl => SiteLink + "torrents.php";
private new ConfigurationDataCookie configData
{
get { return (ConfigurationDataCookie)base.configData; }
set { base.configData = value; }
get => (ConfigurationDataCookie)base.configData;
set => base.configData = value;
}
public GazelleGames(IIndexerConfigurationService configService, WebClient wc, Logger l, IProtectionService ps)

View File

@@ -24,8 +24,8 @@ namespace Jackett.Common.Indexers
private new ConfigurationDataBasicLogin configData
{
get { return (ConfigurationDataBasicLogin)base.configData; }
set { base.configData = value; }
get => (ConfigurationDataBasicLogin)base.configData;
set => base.configData = value;
}
public GimmePeers(IIndexerConfigurationService configService, WebClient wc, Logger l, IProtectionService ps)

View File

@@ -4,7 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Jackett.Common.Models;
using Jackett.Common.Models.IndexerConfig;
using Jackett.Common.Models.IndexerConfig.Bespoke;
using Jackett.Common.Services.Interfaces;
using Jackett.Common.Utils;
using Jackett.Common.Utils.Clients;
@@ -15,12 +15,12 @@ namespace Jackett.Common.Indexers
{
public class HDBitsApi : BaseWebIndexer
{
private string APIUrl { get { return SiteLink + "api/"; } }
private string APIUrl => SiteLink + "api/";
private new ConfigurationDataUserPasskey configData
private new ConfigurationDataHDBitsApi configData
{
get { return (ConfigurationDataUserPasskey)base.configData; }
set { base.configData = value; }
get => (ConfigurationDataHDBitsApi)base.configData;
set => base.configData = value;
}
public HDBitsApi(IIndexerConfigurationService configService, WebClient wc, Logger l, IProtectionService ps)
@@ -32,7 +32,7 @@ namespace Jackett.Common.Indexers
client: wc,
logger: l,
p: ps,
configData: new ConfigurationDataUserPasskey())
configData: new ConfigurationDataHDBitsApi())
{
Encoding = Encoding.UTF8;
Language = "en-us";
@@ -99,6 +99,26 @@ namespace Jackett.Common.Indexers
}
}
if (configData.Codecs.Values.Length > 0)
{
requestData["codec"] = new JArray();
foreach (var codec in configData.Codecs.Values)
{
requestData["codec"].Add(new JValue(int.Parse(codec)));
}
}
if (configData.Mediums.Values.Length > 0)
{
requestData["medium"] = new JArray();
foreach (var medium in configData.Mediums.Values)
{
requestData["medium"].Add(new JValue(int.Parse(medium)));
}
}
requestData["limit"] = 100;
var response = await MakeApiRequest("torrents", requestData);

View File

@@ -26,8 +26,8 @@ namespace Jackett.Common.Indexers
private new ConfigurationDataBasicLoginWithEmail configData
{
get { return (ConfigurationDataBasicLoginWithEmail)base.configData; }
set { base.configData = value; }
get => (ConfigurationDataBasicLoginWithEmail)base.configData;
set => base.configData = value;
}
public HDOlimpo(IIndexerConfigurationService configService, WebClient w, Logger l, IProtectionService ps)

View File

@@ -19,13 +19,13 @@ namespace Jackett.Common.Indexers
{
public class HDSpace : BaseWebIndexer
{
private string LoginUrl { get { return SiteLink + "index.php?page=login"; } }
private string SearchUrl { get { return SiteLink + "index.php?page=torrents&"; } }
private string LoginUrl => SiteLink + "index.php?page=login";
private string SearchUrl => SiteLink + "index.php?page=torrents&";
private new ConfigurationDataBasicLogin configData
{
get { return (ConfigurationDataBasicLogin)base.configData; }
set { base.configData = value; }
get => (ConfigurationDataBasicLogin)base.configData;
set => base.configData = value;
}
public HDSpace(IIndexerConfigurationService configService, WebClient wc, Logger l, IProtectionService ps)

View File

@@ -17,15 +17,15 @@ namespace Jackett.Common.Indexers
{
public class HDTorrents : BaseWebIndexer
{
private string SearchUrl { get { return SiteLink + "torrents.php?"; } }
private string LoginUrl { get { return SiteLink + "login.php"; } }
private string SearchUrl => SiteLink + "torrents.php?";
private string LoginUrl => SiteLink + "login.php";
private const int MAXPAGES = 3;
public override string[] AlternativeSiteLinks { get; protected set; } = new string[] { "https://hdts.ru/", "https://hd-torrents.org/", "https://hd-torrents.net/", "https://hd-torrents.me/" };
private new ConfigurationDataBasicLogin configData
{
get { return (ConfigurationDataBasicLogin)base.configData; }
set { base.configData = value; }
get => (ConfigurationDataBasicLogin)base.configData;
set => base.configData = value;
}
public HDTorrents(IIndexerConfigurationService configService, WebClient w, Logger l, IProtectionService ps)
@@ -92,11 +92,9 @@ namespace Jackett.Common.Indexers
var result = await RequestLoginAndFollowRedirect(LoginUrl, pairs, loginPage.Cookies, true, null, LoginUrl);
await ConfigureIfOK(result.Cookies, result.Content != null && result.Content.Contains("If your browser doesn't have javascript enabled"), () =>
{
var errorMessage = "Couldn't login";
throw new ExceptionWithConfigData(errorMessage, configData);
});
await ConfigureIfOK(
result.Cookies, result.Content?.Contains("If your browser doesn't have javascript enabled") == true,
() => throw new ExceptionWithConfigData("Couldn't login", configData));
return IndexerConfigurationStatus.RequiresTesting;
}

View File

@@ -17,14 +17,14 @@ namespace Jackett.Common.Indexers
{
public class Hebits : BaseWebIndexer
{
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"; } }
private string LoginUrl => SiteLink + "login.php";
private string LoginPostUrl => SiteLink + "takeloginAjax.php";
private string SearchUrl => SiteLink + "browse.php?sort=4&type=desc";
private new ConfigurationDataBasicLogin configData
{
get { return (ConfigurationDataBasicLogin)base.configData; }
set { base.configData = value; }
get => (ConfigurationDataBasicLogin)base.configData;
set => base.configData = value;
}
public Hebits(IIndexerConfigurationService configService, Utils.Clients.WebClient wc, Logger l, IProtectionService ps)

View File

@@ -19,7 +19,7 @@ namespace Jackett.Common.Indexers
{
internal class HorribleSubs : BaseWebIndexer
{
private string ApiEndpoint { get { return SiteLink + "api.php"; } }
private string ApiEndpoint => SiteLink + "api.php";
public override string[] LegacySiteLinks { get; protected set; } = new string[] {
"http://horriblesubs.info/"

View File

@@ -10,7 +10,6 @@ using Jackett.Common.Models;
using Jackett.Common.Models.IndexerConfig;
using Jackett.Common.Services.Interfaces;
using Jackett.Common.Utils;
using Jackett.Common.Utils.Clients;
using Newtonsoft.Json.Linq;
using NLog;
@@ -18,8 +17,6 @@ namespace Jackett.Common.Indexers
{
public class IPTorrents : BaseWebIndexer
{
private string LoginUrl => SiteLink + "login.php";
private string TakeLoginUrl => SiteLink + "take_login.php";
private string BrowseUrl => SiteLink + "t";
public override string[] AlternativeSiteLinks { get; protected set; } = {
@@ -45,9 +42,9 @@ namespace Jackett.Common.Indexers
"https://ipt.world/",
};
private new ConfigurationDataRecaptchaLogin configData
private new ConfigurationDataCookie configData
{
get => (ConfigurationDataRecaptchaLogin)base.configData;
get => (ConfigurationDataCookie)base.configData;
set => base.configData = value;
}
@@ -60,7 +57,7 @@ namespace Jackett.Common.Indexers
client: wc,
logger: l,
p: ps,
configData: new ConfigurationDataRecaptchaLogin())
configData: new ConfigurationDataCookie())
{
Encoding = Encoding.UTF8;
Language = "en-us";
@@ -142,83 +139,26 @@ namespace Jackett.Common.Indexers
AddCategoryMapping(84, TorznabCatType.XXXImageset, "XXX/Pics/Wallpapers");
}
public override async Task<ConfigurationData> GetConfigurationForSetup()
{
var loginPage = await RequestStringWithCookies(LoginUrl, string.Empty);
CQ cq = loginPage.Content;
var captcha = cq.Find(".g-recaptcha");
if (captcha.Any())
{
var result = configData;
result.CookieHeader.Value = loginPage.Cookies;
result.Captcha.SiteKey = captcha.Attr("data-sitekey");
result.Captcha.Version = "2";
return result;
}
else
{
var result = new ConfigurationDataBasicLogin
{
SiteLink = { Value = configData.SiteLink.Value },
Instructions = { Value = configData.Instructions.Value },
Username = { Value = configData.Username.Value },
Password = { Value = configData.Password.Value },
CookieHeader = { Value = loginPage.Cookies }
};
return result;
}
}
public override async Task<IndexerConfigurationStatus> ApplyConfiguration(JToken configJson)
{
LoadValuesFromJson(configJson);
var pairs = new Dictionary<string, string> {
{ "username", configData.Username.Value },
{ "password", configData.Password.Value },
{ "g-recaptcha-response", configData.Captcha.Value }
};
if (!string.IsNullOrWhiteSpace(configData.Captcha.Cookie))
CookieHeader = configData.Cookie.Value;
try
{
CookieHeader = configData.Captcha.Cookie;
try
{
var results = await PerformQuery(new TorznabQuery());
if (!results.Any())
throw new Exception("Your cookie did not work");
var results = await PerformQuery(new TorznabQuery());
if (!results.Any())
throw new Exception("Your cookie did not work");
IsConfigured = true;
SaveConfig();
return IndexerConfigurationStatus.Completed;
}
catch (Exception e)
{
IsConfigured = false;
throw new Exception("Your cookie did not work: " + e.Message);
}
IsConfigured = true;
SaveConfig();
return IndexerConfigurationStatus.Completed;
}
var request = new Utils.Clients.WebRequest()
catch (Exception e)
{
Url = TakeLoginUrl,
Type = RequestType.POST,
Referer = SiteLink,
Encoding = Encoding,
PostData = pairs
};
var response = await webclient.GetString(request);
var firstCallCookies = response.Cookies;
// Redirect to ? then to /t
await FollowIfRedirect(response, request.Url, null, firstCallCookies);
await ConfigureIfOK(firstCallCookies, response.Content.Contains("/lout.php"), () =>
{
CQ dom = response.Content;
var messageEl = dom["body > div"].First();
var errorMessage = messageEl.Any() ? messageEl.Text().Trim() : response.Content;
throw new ExceptionWithConfigData(errorMessage, configData);
});
return IndexerConfigurationStatus.RequiresTesting;
IsConfigured = false;
throw new Exception("Your cookie did not work: " + e.Message);
}
}
protected override async Task<IEnumerable<ReleaseInfo>> PerformQuery(TorznabQuery query)

View File

@@ -17,9 +17,9 @@ namespace Jackett.Common.Indexers
{
public class ImmortalSeed : BaseWebIndexer
{
private string BrowsePage { get { return SiteLink + "browse.php"; } }
private string LoginUrl { get { return SiteLink + "takelogin.php"; } }
private string QueryString { get { return "?do=search&keywords={0}&search_type=t_name&category=0&include_dead_torrents=no"; } }
private string BrowsePage => SiteLink + "browse.php";
private string LoginUrl => SiteLink + "takelogin.php";
private string QueryString => "?do=search&keywords={0}&search_type=t_name&category=0&include_dead_torrents=no";
public override string[] LegacySiteLinks { get; protected set; } = new string[] {
"http://immortalseed.me/",
@@ -27,8 +27,8 @@ namespace Jackett.Common.Indexers
private new ConfigurationDataBasicLogin configData
{
get { return (ConfigurationDataBasicLogin)base.configData; }
set { base.configData = value; }
get => (ConfigurationDataBasicLogin)base.configData;
set => base.configData = value;
}
public ImmortalSeed(IIndexerConfigurationService configService, Utils.Clients.WebClient wc, Logger l, IProtectionService ps)

View File

@@ -8,7 +8,6 @@ using System.Text.RegularExpressions;
using System.Threading.Tasks;
using AngleSharp.Dom;
using AngleSharp.Html.Parser;
using CsQuery;
using Jackett.Common.Models;
using Jackett.Common.Models.IndexerConfig;
using Jackett.Common.Services.Interfaces;
@@ -24,20 +23,20 @@ namespace Jackett.Common.Indexers
private static readonly Regex parsePlayEpisodeRegex = new Regex("PlayEpisode\\('(?<id>\\d{1,3})(?<season>\\d{3})(?<episode>\\d{3})'\\)", RegexOptions.Compiled | RegexOptions.IgnoreCase);
private static readonly Regex parseReleaseDetailsRegex = new Regex("Видео:\\ (?<quality>.+).\\ Размер:\\ (?<size>.+).\\ Перевод", RegexOptions.Compiled | RegexOptions.IgnoreCase);
private string LoginUrl { get { return SiteLink + "login"; } }
private string LoginUrl => SiteLink + "login";
// http://www.lostfilm.tv/login
private string ApiUrl { get { return SiteLink + "ajaxik.php"; } }
private string ApiUrl => SiteLink + "ajaxik.php";
// http://www.lostfilm.tv/new
private string DiscoveryUrl { get { return SiteLink + "new"; } }
private string DiscoveryUrl => SiteLink + "new";
// http://www.lostfilm.tv/search?q=breaking+bad
private string SearchUrl { get { return SiteLink + "search"; } }
private string SearchUrl => SiteLink + "search";
// PlayEpisode function produce urls like this:
// https://www.lostfilm.tv/v_search.php?c=119&s=5&e=16
private string ReleaseUrl { get { return SiteLink + "v_search.php"; } }
private string ReleaseUrl => SiteLink + "v_search.php";
internal class TrackerUrlDetails
@@ -63,6 +62,7 @@ namespace Jackett.Common.Indexers
episode = match.Groups["episode"].Value.TrimStart('0');
}
// TODO: see if query.GetEpisodeString() is sufficient
internal string GetEpisodeString()
{
var result = string.Empty;
@@ -83,8 +83,8 @@ namespace Jackett.Common.Indexers
private new ConfigurationDataCaptchaLogin configData
{
get { return (ConfigurationDataCaptchaLogin)base.configData; }
set { base.configData = value; }
get => (ConfigurationDataCaptchaLogin)base.configData;
set => base.configData = value;
}
public LostFilm(IIndexerConfigurationService configService, WebClient wc, Logger l, IProtectionService ps)
@@ -107,12 +107,13 @@ namespace Jackett.Common.Indexers
{
// looks like after some failed login attempts there's a captcha
var loginPage = await RequestStringWithCookies(LoginUrl, string.Empty);
CQ dom = loginPage.Content;
var qCaptchaImg = dom.Find("img#captcha_pictcha").First();
if (qCaptchaImg.Length == 1)
var parser = new HtmlParser();
var document = parser.ParseDocument(loginPage.Content);
var qCaptchaImg = document.QuerySelector("img#captcha_pictcha");
if (qCaptchaImg != null)
{
var CaptchaUrl = SiteLink + qCaptchaImg.Attr("src");
var captchaImage = await RequestBytesWithCookies(CaptchaUrl, loginPage.Cookies);
var captchaUrl = SiteLink + qCaptchaImg.GetAttribute("src");
var captchaImage = await RequestBytesWithCookies(captchaUrl, loginPage.Cookies);
configData.CaptchaImage.Value = captchaImage.Content;
}
else
@@ -719,6 +720,14 @@ namespace Jackett.Common.Indexers
sizeString = sizeString.Replace("КБ", "KB"); // untested
release.Size = ReleaseInfo.GetBytes(sizeString);
// add missing torznab fields not available from results
release.Seeders = 1;
release.Peers = 2;
release.DownloadVolumeFactor = 0;
release.UploadVolumeFactor = 1;
release.MinimumRatio = 1;
release.MinimumSeedTime = 172800; // 48 hours
logger.Debug("> Add: " + release.Title);
releases.Add(release);
}

View File

@@ -31,10 +31,7 @@ namespace Jackett.Common.Indexers.Meta
return base.CanHandleQuery(query);
}
public override Task<IndexerConfigurationStatus> ApplyConfiguration(JToken configJson)
{
return Task.FromResult(IndexerConfigurationStatus.Completed);
}
public override Task<IndexerConfigurationStatus> ApplyConfiguration(JToken configJson) => Task.FromResult(IndexerConfigurationStatus.Completed);
public override async Task<IndexerResult> ResultsForQuery(TorznabQuery query)
{
@@ -102,32 +99,11 @@ namespace Jackett.Common.Indexers.Meta
return result;
}
public override TorznabCapabilities TorznabCaps
{
get
{
return validIndexers.Select(i => i.TorznabCaps).Aggregate(new TorznabCapabilities(), TorznabCapabilities.Concat);
}
}
public override TorznabCapabilities TorznabCaps => validIndexers.Select(i => i.TorznabCaps).Aggregate(new TorznabCapabilities(), TorznabCapabilities.Concat);
public override bool IsConfigured
{
get
{
return Indexers != null;
}
}
public override bool IsConfigured => Indexers != null;
private IEnumerable<IIndexer> validIndexers
{
get
{
if (Indexers == null)
return null;
return Indexers.Where(i => i.IsConfigured && filterFunc(i));
}
}
private IEnumerable<IIndexer> validIndexers => Indexers?.Where(i => i.IsConfigured && filterFunc(i));
public IEnumerable<IIndexer> Indexers;

View File

@@ -19,18 +19,12 @@ namespace Jackett.Common.Indexers.Meta
public class NoFallbackStrategy : IFallbackStrategy
{
public Task<IEnumerable<TorznabQuery>> FallbackQueries()
{
return Task.FromResult<IEnumerable<TorznabQuery>>(new List<TorznabQuery>());
}
public Task<IEnumerable<TorznabQuery>> FallbackQueries() => Task.FromResult<IEnumerable<TorznabQuery>>(new List<TorznabQuery>());
}
public class NoFallbackStrategyProvider : IFallbackStrategyProvider
{
public IEnumerable<IFallbackStrategy> FallbackStrategiesForQuery(TorznabQuery query)
{
return (new NoFallbackStrategy()).ToEnumerable();
}
public IEnumerable<IFallbackStrategy> FallbackStrategiesForQuery(TorznabQuery query) => (new NoFallbackStrategy()).ToEnumerable();
}
public class ImdbFallbackStrategy : IFallbackStrategy
@@ -44,9 +38,8 @@ namespace Jackett.Common.Indexers.Meta
public async Task<IEnumerable<TorznabQuery>> FallbackQueries()
{
if (titles == null)
titles = (await resolver.MovieForId(query.ImdbID.ToNonNull())).Title?.ToEnumerable() ?? Enumerable.Empty<string>();
return titles.Select(t => query.CreateFallback(t));
titles ??= (await resolver.MovieForId(query.ImdbID.ToNonNull())).Title?.ToEnumerable() ?? Enumerable.Empty<string>();
return titles.Select(query.CreateFallback);
}
private readonly IImdbResolver resolver;
@@ -56,10 +49,7 @@ namespace Jackett.Common.Indexers.Meta
public class ImdbFallbackStrategyProvider : IFallbackStrategyProvider
{
public ImdbFallbackStrategyProvider(IImdbResolver resolver)
{
this.resolver = resolver;
}
public ImdbFallbackStrategyProvider(IImdbResolver resolver) => this.resolver = resolver;
public IEnumerable<IFallbackStrategy> FallbackStrategiesForQuery(TorznabQuery query)
{

View File

@@ -8,13 +8,7 @@ namespace Jackett.Common.Indexers.Meta
{
public class AggregateIndexer : BaseMetaIndexer
{
public override string ID
{
get
{
return "all";
}
}
public override string ID => "all";
public AggregateIndexer(IFallbackStrategyProvider fallbackStrategyProvider, IResultFilterProvider resultFilterProvider, IIndexerConfigurationService configService, WebClient wc, Logger l, IProtectionService ps)
: base("AggregateSearch", "This feed includes all configured trackers", fallbackStrategyProvider, resultFilterProvider, configService, wc, l, new ConfigurationData(), ps, x => true)
{

View File

@@ -30,7 +30,8 @@ namespace Jackett.Common.Indexers.Meta
long? imdbId = null;
try
{
var normalizedImdbId = string.Concat(query.ImdbID.Where(c => char.IsDigit(c)));
// Convert from try/catch to long.TryParse since we're not handling the failure
var normalizedImdbId = string.Concat(query.ImdbID.Where(char.IsDigit));
imdbId = long.Parse(normalizedImdbId);
}
catch
@@ -70,11 +71,8 @@ namespace Jackett.Common.Indexers.Meta
return filteredResults;
}
private static string RemoveSpecialChars(string title)
{
// TODO improve character replacement with invalid chars
return title.Replace(":", "");
}
// TODO improve character replacement with invalid chars
private static string RemoveSpecialChars(string title) => title.Replace(":", "");
private static IEnumerable<string> GenerateTitleVariants(string title)
{
@@ -94,26 +92,17 @@ namespace Jackett.Common.Indexers.Meta
public class NoFilter : IResultFilter
{
public Task<IEnumerable<ReleaseInfo>> FilterResults(IEnumerable<ReleaseInfo> results)
{
return Task.FromResult(results);
}
public Task<IEnumerable<ReleaseInfo>> FilterResults(IEnumerable<ReleaseInfo> results) => Task.FromResult(results);
}
public class NoResultFilterProvider : IResultFilterProvider
{
public IEnumerable<IResultFilter> FiltersForQuery(TorznabQuery query)
{
return (new NoFilter()).ToEnumerable();
}
public IEnumerable<IResultFilter> FiltersForQuery(TorznabQuery query) => (new NoFilter()).ToEnumerable();
}
public class ImdbTitleResultFilterProvider : IResultFilterProvider
{
public ImdbTitleResultFilterProvider(IImdbResolver resolver)
{
this.resolver = resolver;
}
public ImdbTitleResultFilterProvider(IImdbResolver resolver) => this.resolver = resolver;
public IEnumerable<IResultFilter> FiltersForQuery(TorznabQuery query)
{

View File

@@ -18,13 +18,13 @@ namespace Jackett.Common.Indexers
{
public class Myanonamouse : BaseWebIndexer
{
private string LoginUrl { get { return SiteLink + "takelogin.php"; } }
private string SearchUrl { get { return SiteLink + "tor/js/loadSearchJSONbasic.php"; } }
private string LoginUrl => SiteLink + "takelogin.php";
private string SearchUrl => SiteLink + "tor/js/loadSearchJSONbasic.php";
private new ConfigurationDataMyAnonamouse configData
{
get { return (ConfigurationDataMyAnonamouse)base.configData; }
set { base.configData = value; }
get => (ConfigurationDataMyAnonamouse)base.configData;
set => base.configData = value;
}
public Myanonamouse(IIndexerConfigurationService configService, WebClient c, Logger l, IProtectionService ps)

View File

@@ -18,14 +18,14 @@ namespace Jackett.Common.Indexers
{
public class NCore : BaseWebIndexer
{
private string LoginUrl { get { return SiteLink + "login.php"; } }
private string SearchUrl { get { return SiteLink + "torrents.php"; } }
private string LoginUrl => SiteLink + "login.php";
private string SearchUrl => SiteLink + "torrents.php";
private readonly string[] LanguageCats = new string[] { "xvidser", "dvdser", "hdser", "xvid", "dvd", "dvd9", "hd", "mp3", "lossless", "ebook" };
private new ConfigurationDataNCore configData
{
get { return (ConfigurationDataNCore)base.configData; }
set { base.configData = value; }
get => (ConfigurationDataNCore)base.configData;
set => base.configData = value;
}
public NCore(IIndexerConfigurationService configService, WebClient wc, Logger l, IProtectionService ps)

View File

@@ -17,13 +17,13 @@ namespace Jackett.Common.Indexers
{
public class NewRealWorld : BaseWebIndexer
{
private string LoginUrl { get { return SiteLink + "login.php"; } }
private string BrowseUrl { get { return SiteLink + "browse.php"; } }
private string LoginUrl => SiteLink + "login.php";
private string BrowseUrl => SiteLink + "browse.php";
private new ConfigurationDataBasicLoginWithRSSAndDisplay configData
{
get { return (ConfigurationDataBasicLoginWithRSSAndDisplay)base.configData; }
set { base.configData = value; }
get => (ConfigurationDataBasicLoginWithRSSAndDisplay)base.configData;
set => base.configData = value;
}
public NewRealWorld(IIndexerConfigurationService configService, WebClient wc, Logger l, IProtectionService ps)

View File

@@ -49,10 +49,7 @@ namespace Jackett.Common.Indexers
Score = copyFrom.Score;
}
public override object Clone()
{
return new NewpctRelease(this);
}
public override object Clone() => new NewpctRelease(this);
}
private class DownloadMatcher
@@ -156,10 +153,8 @@ namespace Jackett.Common.Indexers
configData.LoadValuesFromJson(configJson);
var releases = await PerformQuery(new TorznabQuery());
await ConfigureIfOK(string.Empty, releases.Count() > 0, () =>
{
throw new Exception("Could not find releases from this URL");
});
await ConfigureIfOK(string.Empty, releases.Any(), () =>
throw new Exception("Could not find releases from this URL"));
return IndexerConfigurationStatus.Completed;
}
@@ -837,13 +832,10 @@ namespace Jackett.Common.Indexers
}
}
private ReleaseType ReleaseTypeFromQuality(string quality)
{
if (quality.Trim().ToLower().StartsWith("hdtv"))
return ReleaseType.TV;
else
return ReleaseType.Movie;
}
private static ReleaseType ReleaseTypeFromQuality(string quality) =>
quality.Trim().ToLower().StartsWith("hdtv")
? ReleaseType.TV
: ReleaseType.Movie;
private NewpctRelease GetReleaseFromData(ReleaseType releaseType, string title, string detailsUrl, string quality, string language, long size, DateTime publishDate)
{

View File

@@ -18,13 +18,13 @@ namespace Jackett.Common.Indexers
{
public class Partis : BaseWebIndexer
{
private string LoginUrl { get { return SiteLink + "user/login/"; } }
private string SearchUrl { get { return SiteLink + "torrent/show/"; } }
private string LoginUrl => SiteLink + "user/login/";
private string SearchUrl => SiteLink + "torrent/show/";
private new ConfigurationDataBasicLogin configData
{
get { return (ConfigurationDataBasicLogin)base.configData; }
set { base.configData = value; }
get => (ConfigurationDataBasicLogin)base.configData;
set => base.configData = value;
}
public Partis(IIndexerConfigurationService configService, WebClient wc, Logger l, IProtectionService ps)
@@ -141,7 +141,7 @@ namespace Jackett.Common.Indexers
results = await RequestStringWithCookies(searchUrl, null, SearchUrl, heder);
await FollowIfRedirect(results, null, null, null, true);
/// are we logged in?
// are we logged in?
if (!results.Content.Contains("/odjava"))
{
await ApplyConfiguration(null);

View File

@@ -17,16 +17,16 @@ namespace Jackett.Common.Indexers
{
public class PassThePopcorn : BaseWebIndexer
{
private string LoginUrl { get { return "https://passthepopcorn.me/ajax.php?action=login"; } }
private string indexUrl { get { return "https://passthepopcorn.me/ajax.php?action=login"; } }
private string SearchUrl { get { return "https://passthepopcorn.me/torrents.php"; } }
private string DetailURL { get { return "https://passthepopcorn.me/torrents.php?torrentid="; } }
private string LoginUrl => "https://passthepopcorn.me/ajax.php?action=login";
private string indexUrl => "https://passthepopcorn.me/ajax.php?action=login";
private string SearchUrl => "https://passthepopcorn.me/torrents.php";
private string DetailURL => "https://passthepopcorn.me/torrents.php?torrentid=";
private string AuthKey { get; set; }
private new ConfigurationDataAPILoginWithUserAndPasskeyAndFilter configData
{
get { return (ConfigurationDataAPILoginWithUserAndPasskeyAndFilter)base.configData; }
set { base.configData = value; }
get => (ConfigurationDataAPILoginWithUserAndPasskeyAndFilter)base.configData;
set => base.configData = value;
}
public PassThePopcorn(IIndexerConfigurationService configService, Utils.Clients.WebClient c, Logger l, IProtectionService ps)

View File

@@ -17,15 +17,13 @@ namespace Jackett.Common.Indexers
{
public class PiXELHD : BaseWebIndexer
{
private string LoginUrl
{ get { return SiteLink + "login.php"; } }
private string BrowseUrl
{ get { return SiteLink + "torrents.php"; } }
private string LoginUrl => SiteLink + "login.php";
private string BrowseUrl => SiteLink + "torrents.php";
private new ConfigurationDataCaptchaLogin configData
{
get { return (ConfigurationDataCaptchaLogin)base.configData; }
set { base.configData = value; }
get => (ConfigurationDataCaptchaLogin)base.configData;
set => base.configData = value;
}
private string input_captcha = null;

View File

@@ -18,16 +18,16 @@ namespace Jackett.Common.Indexers
{
public class PirateTheNet : BaseWebIndexer
{
private string SearchUrl { get { return SiteLink + "torrentsutils.php"; } }
private string LoginUrl { get { return SiteLink + "takelogin.php"; } }
private string CaptchaUrl { get { return SiteLink + "simpleCaptcha.php?numImages=1"; } }
private string SearchUrl => SiteLink + "torrentsutils.php";
private string LoginUrl => SiteLink + "takelogin.php";
private string CaptchaUrl => SiteLink + "simpleCaptcha.php?numImages=1";
private readonly TimeZoneInfo germanyTz = TimeZoneInfo.CreateCustomTimeZone("W. Europe Standard Time", new TimeSpan(1, 0, 0), "W. Europe Standard Time", "W. Europe Standard Time");
private readonly List<string> categories = new List<string>() { "1080P", "720P", "BDRip", "BluRay", "BRRip", "DVDR", "DVDRip", "FLAC", "MP3", "MP4", "Packs", "R5", "Remux", "TVRip", "WebRip" };
private new ConfigurationDataBasicLoginWithRSSAndDisplay configData
{
get { return (ConfigurationDataBasicLoginWithRSSAndDisplay)base.configData; }
set { base.configData = value; }
get => (ConfigurationDataBasicLoginWithRSSAndDisplay)base.configData;
set => base.configData = value;
}
public PirateTheNet(IIndexerConfigurationService configService, WebClient w, Logger l, IProtectionService ps)

View File

@@ -15,9 +15,9 @@ namespace Jackett.Common.Indexers
{
public class PolishTracker : BaseWebIndexer
{
private string LoginUrl { get { return SiteLink + "login"; } }
private string TorrentApiUrl { get { return SiteLink + "apitorrents"; } }
private string CDNUrl { get { return "https://cdn.pte.nu/"; } }
private string LoginUrl => SiteLink + "login";
private string TorrentApiUrl => SiteLink + "apitorrents";
private string CDNUrl => "https://cdn.pte.nu/";
public override string[] LegacySiteLinks { get; protected set; } = new string[] {
"https://polishtracker.net/",
@@ -25,8 +25,8 @@ namespace Jackett.Common.Indexers
private new ConfigurationDataBasicLoginWithEmail configData
{
get { return (ConfigurationDataBasicLoginWithEmail)base.configData; }
set { base.configData = value; }
get => (ConfigurationDataBasicLoginWithEmail)base.configData;
set => base.configData = value;
}
public PolishTracker(IIndexerConfigurationService configService, WebClient wc, Logger l, IProtectionService ps)

View File

@@ -18,16 +18,16 @@ namespace Jackett.Common.Indexers
{
public class Pretome : BaseWebIndexer
{
private string LoginUrl { get { return SiteLink + "takelogin.php"; } }
private string LoginReferer { get { return SiteLink + "index.php?cat=1"; } }
private string SearchUrl { get { return SiteLink + "browse.php"; } }
private string LoginUrl => SiteLink + "takelogin.php";
private string LoginReferer => SiteLink + "index.php?cat=1";
private string SearchUrl => SiteLink + "browse.php";
private readonly List<CategoryMapping> resultMapping = new List<CategoryMapping>();
private new ConfigurationDataPinNumber configData
{
get { return (ConfigurationDataPinNumber)base.configData; }
set { base.configData = value; }
get => (ConfigurationDataPinNumber)base.configData;
set => base.configData = value;
}
public Pretome(IIndexerConfigurationService configService, WebClient wc, Logger l, IProtectionService ps)

View File

@@ -16,8 +16,6 @@ namespace Jackett.Common.Indexers
protectionService: protectionService,
webClient: webClient
)
{
Type = "private";
}
=> Type = "private";
}
}

View File

@@ -24,16 +24,16 @@ namespace Jackett.Common.Indexers
private Uri BaseUri
{
get { return new Uri(configData.Url.Value); }
set { configData.Url.Value = value.ToString(); }
get => new Uri(configData.Url.Value);
set => configData.Url.Value = value.ToString();
}
private string ApiEndpoint { get { return BaseUri + "pubapi_v2.php"; } }
private string ApiEndpoint => BaseUri + "pubapi_v2.php";
private new ConfigurationDataUrl configData
{
get { return (ConfigurationDataUrl)base.configData; }
set { base.configData = value; }
get => (ConfigurationDataUrl)base.configData;
set => base.configData = value;
}
private DateTime lastTokenFetch;
@@ -44,7 +44,7 @@ namespace Jackett.Common.Indexers
private readonly TimeSpan TOKEN_DURATION = TimeSpan.FromMinutes(10);
private bool HasValidToken { get { return !string.IsNullOrEmpty(token) && lastTokenFetch > DateTime.Now - TOKEN_DURATION; } }
private bool HasValidToken => !string.IsNullOrEmpty(token) && lastTokenFetch > DateTime.Now - TOKEN_DURATION;
public Rarbg(IIndexerConfigurationService configService, Utils.Clients.WebClient wc, Logger l, IProtectionService ps)
: base(name: "RARBG",
@@ -145,10 +145,7 @@ namespace Jackett.Common.Indexers
return IndexerConfigurationStatus.Completed;
}
protected override async Task<IEnumerable<ReleaseInfo>> PerformQuery(TorznabQuery query)
{
return await PerformQuery(query, 0);
}
protected override async Task<IEnumerable<ReleaseInfo>> PerformQuery(TorznabQuery query) => await PerformQuery(query, 0);
private async Task<IEnumerable<ReleaseInfo>> PerformQuery(TorznabQuery query, int attempts)
{

View File

@@ -19,17 +19,17 @@ namespace Jackett.Common.Indexers
{
public class RevolutionTT : BaseWebIndexer
{
private string LandingPageURL { get { return SiteLink + "login.php"; } }
private string LoginUrl { get { return SiteLink + "takelogin.php"; } }
private string GetRSSKeyUrl { get { return SiteLink + "getrss.php"; } }
private string RSSUrl { get { return SiteLink + "rss.php?feed=dl&passkey="; } }
private string SearchUrl { get { return SiteLink + "browse.php"; } }
private string DetailsURL { get { return SiteLink + "details.php?id={0}&hit=1"; } }
private string LandingPageURL => SiteLink + "login.php";
private string LoginUrl => SiteLink + "takelogin.php";
private string GetRSSKeyUrl => SiteLink + "getrss.php";
private string RSSUrl => SiteLink + "rss.php?feed=dl&passkey=";
private string SearchUrl => SiteLink + "browse.php";
private string DetailsURL => SiteLink + "details.php?id={0}&hit=1";
private new ConfigurationDataBasicLoginWithRSS configData
{
get { return (ConfigurationDataBasicLoginWithRSS)base.configData; }
set { base.configData = value; }
get => (ConfigurationDataBasicLoginWithRSS)base.configData;
set => base.configData = value;
}
public RevolutionTT(IIndexerConfigurationService configService, Utils.Clients.WebClient wc, Logger l, IProtectionService ps)

View File

@@ -17,12 +17,12 @@ namespace Jackett.Common.Indexers
{
public class SceneHD : BaseWebIndexer
{
private string SearchUrl { get { return SiteLink + "browse.php"; } }
private string SearchUrl => SiteLink + "browse.php";
private new ConfigurationDataCookie configData
{
get { return (ConfigurationDataCookie)base.configData; }
set { base.configData = value; }
get => (ConfigurationDataCookie)base.configData;
set => base.configData = value;
}
public SceneHD(IIndexerConfigurationService configService, WebClient c, Logger l, IProtectionService ps)

View File

@@ -19,16 +19,16 @@ namespace Jackett.Common.Indexers
{
public class SceneTime : BaseWebIndexer
{
private string StartPageUrl { get { return SiteLink + "login.php"; } }
private string LoginUrl { get { return SiteLink + "takelogin.php"; } }
private string SearchUrl { get { return SiteLink + "browse.php"; } }
private string DownloadUrl { get { return SiteLink + "download.php/{0}/download.torrent"; } }
private string StartPageUrl => SiteLink + "login.php";
private string LoginUrl => SiteLink + "takelogin.php";
private string SearchUrl => SiteLink + "browse.php";
private string DownloadUrl => SiteLink + "download.php/{0}/download.torrent";
private new ConfigurationDataSceneTime configData
{
get { return (ConfigurationDataSceneTime)base.configData; }
set { base.configData = value; }
get => (ConfigurationDataSceneTime)base.configData;
set => base.configData = value;
}
public SceneTime(IIndexerConfigurationService configService, WebClient w, Logger l, IProtectionService ps)

View File

@@ -17,16 +17,16 @@ namespace Jackett.Common.Indexers
{
public class Shazbat : BaseWebIndexer
{
private string LoginUrl { get { return SiteLink + "login"; } }
private string SearchUrl { get { return SiteLink + "search"; } }
private string TorrentsUrl { get { return SiteLink + "torrents"; } }
private string ShowUrl { get { return SiteLink + "show?id="; } }
private string RSSProfile { get { return SiteLink + "rss_feeds"; } }
private string LoginUrl => SiteLink + "login";
private string SearchUrl => SiteLink + "search";
private string TorrentsUrl => SiteLink + "torrents";
private string ShowUrl => SiteLink + "show?id=";
private string RSSProfile => SiteLink + "rss_feeds";
private new ConfigurationDataBasicLoginWithRSS configData
{
get { return (ConfigurationDataBasicLoginWithRSS)base.configData; }
set { base.configData = value; }
get => (ConfigurationDataBasicLoginWithRSS)base.configData;
set => base.configData = value;
}
public Shazbat(IIndexerConfigurationService configService, WebClient c, Logger l, IProtectionService ps)
@@ -62,10 +62,8 @@ namespace Jackett.Common.Indexers
var firstRequest = await RequestStringWithCookiesAndRetry(LoginUrl);
var result = await RequestLoginAndFollowRedirect(LoginUrl, pairs, null, true, null, LoginUrl);
await ConfigureIfOK(result.Cookies, result.Content != null && result.Content.Contains("glyphicon-log-out"), () =>
{
throw new ExceptionWithConfigData("The username and password entered do not match.", configData);
});
await ConfigureIfOK(result.Cookies, result.Content != null && result.Content.Contains("glyphicon-log-out"),
() => throw new ExceptionWithConfigData("The username and password entered do not match.", configData));
var rssProfile = await RequestStringWithCookiesAndRetry(RSSProfile);
CQ rssDom = rssProfile.Content;

View File

@@ -17,15 +17,15 @@ namespace Jackett.Common.Indexers
{
public class ShowRSS : BaseWebIndexer
{
private string SearchAllUrl { get { return SiteLink + "other/all.rss"; } }
private string SearchAllUrl => SiteLink + "other/all.rss";
public override string[] LegacySiteLinks { get; protected set; } = new string[] {
"http://showrss.info/",
};
private new ConfigurationData configData
{
get { return base.configData; }
set { base.configData = value; }
get => base.configData;
set => base.configData = value;
}
public ShowRSS(IIndexerConfigurationService configService, WebClient wc, Logger l, IProtectionService ps)
@@ -49,18 +49,13 @@ namespace Jackett.Common.Indexers
configData.LoadValuesFromJson(configJson);
var releases = await PerformQuery(new TorznabQuery());
await ConfigureIfOK(string.Empty, releases.Count() > 0, () =>
{
throw new Exception("Could not find releases from this URL");
});
await ConfigureIfOK(string.Empty, releases.Any(),
() => throw new Exception("Could not find releases from this URL"));
return IndexerConfigurationStatus.RequiresTesting;
}
public override Task<byte[]> Download(Uri link)
{
throw new NotImplementedException();
}
public override Task<byte[]> Download(Uri link) => throw new NotImplementedException();
protected override async Task<IEnumerable<ReleaseInfo>> PerformQuery(TorznabQuery query)
{

View File

@@ -18,13 +18,13 @@ namespace Jackett.Common.Indexers
{
public class SpeedCD : BaseWebIndexer
{
private string LoginUrl { get { return SiteLink + "take_login.php"; } }
private string SearchUrl { get { return SiteLink + "browse.php"; } }
private string LoginUrl => SiteLink + "take_login.php";
private string SearchUrl => SiteLink + "browse.php";
private new ConfigurationDataBasicLogin configData
{
get { return (ConfigurationDataBasicLogin)base.configData; }
set { base.configData = value; }
get => (ConfigurationDataBasicLogin)base.configData;
set => base.configData = value;
}
public SpeedCD(IIndexerConfigurationService configService, WebClient wc, Logger l, IProtectionService ps)
@@ -167,6 +167,8 @@ namespace Jackett.Common.Indexers
var cat = torrentData.Find("img[class^='Tcat']").First().Parent().Attr("href").Trim().Remove(0, 5);
long.TryParse(cat, out var category);
// This fixes the mixed initializer issue, so it's just inconsistent in the code base.
// https://github.com/Jackett/Jackett/pull/7166#discussion_r376817517
var release = new ReleaseInfo();
release.Title = title;

Some files were not shown because too many files have changed in this diff Show More