Compare commits

...

41 Commits

Author SHA1 Message Date
Qstick c2c12297bd Fixed: Persist columns for search page 2021-07-08 20:49:15 -04:00
bakerboy448 81cbdab5eb New: (Indexer) SubsPlease Alt Links 2021-07-07 23:04:14 -04:00
Servarr 9ee5a3e94b Translated using Weblate (Hungarian) (#300)
Currently translated at 100.0% (425 of 425 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (425 of 425 strings)

Translated using Weblate (Portuguese)

Currently translated at 85.4% (363 of 425 strings)

Translated using Weblate (French)

Currently translated at 100.0% (425 of 425 strings)

Translated using Weblate (German)

Currently translated at 92.4% (393 of 425 strings)

Translated using Weblate (Portuguese)

Currently translated at 84.4% (359 of 425 strings)

Translated using Weblate (Portuguese)

Currently translated at 84.4% (359 of 425 strings)

Co-authored-by: Csaba <csab0825@gmail.com>
Co-authored-by: Lizandra Candido da Silva <lizandra.c.s@gmail.com>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: foXaCe <foxace66@gmail.com>
Co-authored-by: reloxx <reloxx@interia.pl>
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/de/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/fr/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/hu/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/pt/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/pt_BR/
Translation: Servarr/Prowlarr

Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: Csaba <csab0825@gmail.com>
Co-authored-by: Lizandra Candido da Silva <lizandra.c.s@gmail.com>
Co-authored-by: foXaCe <foxace66@gmail.com>
Co-authored-by: reloxx <reloxx@interia.pl>
2021-07-07 00:55:40 -05:00
Qstick a570fd2a8f New: Advanced settings toggle in indexer edit/add modal 2021-07-05 13:12:06 -04:00
Lagicrus 5cffb10e08 Fixed: If no categories are passed in, flag up a unknown error (#311)
* If no categories are passed in, flag up a unknown error

* Pass back in default props to deal with undefined issues
2021-07-05 08:42:51 -04:00
Qstick b11bf284dc New: (IPTorrents) Add freeleech only option
Fixes #314
2021-07-05 08:41:29 -04:00
Robin Dadswell 5c4c042b2e Updated movieService reference for App Sync Profile Service dependency on Indexer Factory 2021-07-04 22:26:35 -04:00
Qstick d1cb744efd Update azuresync.yml
[skip ci]
2021-07-01 21:59:49 -04:00
bakerboy448 79b910a80c Fixed: Cleanse BHD APIKey from logs 2021-07-01 16:22:57 -05:00
bakerboy448 01e08e0c31 fix radarr reference in contributing [skip ci] 2021-07-01 16:21:38 -05:00
Junkbite dd3c9c268e allow empty catergories on indexer search 2021-06-30 21:57:53 -04:00
bakerboy448 725f738ee1 Fixed: Clarify redirect wording 2021-06-30 10:43:33 -05:00
Qstick 22c738f43e Prevent sync jobs from running in parallel
[skip ci]
2021-06-29 21:53:16 -04:00
Qstick e45f88473c Fixed: (Anthelion) Null BaseUrl and better error message on auth fail
Fixes #295
2021-06-28 23:04:10 -04:00
Qstick 889591d0b1 Fixed: (HDSpace) Use query params 2021-06-28 22:43:30 -04:00
Qstick fe8247df8a Fixed: (HDSpace) Auth failure and Name 2021-06-28 21:36:05 -04:00
bakerboy448 7a5721bcee typo fix 2021-06-28 20:26:34 -05:00
bakerboy448 eea5c3e9a4 Fixed: Cleanse Pwd from logs 2021-06-28 12:22:47 -05:00
Qstick f55493c9a9 New: (Indexer) HD-Space 2021-06-27 21:40:43 -04:00
bakerboy448 79618adaf9 New: (Indexer) Add IPTorrents Alt Links
as of Jackett 4524c18d39251c677bec1d4d8f75f71c6c6ac010
2021-06-27 19:32:31 -04:00
Qstick af13d6ed80 Fixed: Not using correct BaseUrl if changed between tests 2021-06-27 18:15:18 -04:00
Qstick 38c09277d9 New: Alternative Site Links 2021-06-27 01:58:37 -04:00
Qstick 1fb693d066 Update azuresync.yml
[skip ci]
2021-06-26 18:04:48 -04:00
Qstick 7414a2f690 Update azuresync.yml
[skip ci]
2021-06-26 17:59:12 -04:00
Qstick 000590bcf7 Update azuresync.yml
[skip ci]
2021-06-26 17:57:00 -04:00
Qstick d5d6625a63 Update azuresync.yml
[skip ci]
2021-06-26 17:16:12 -04:00
Qstick 00f33cb48f Set area and sub-area on azure sync
[skip ci]
2021-06-26 17:09:23 -04:00
Qstick fd265c5734 Update azure-pipelines.yml 2021-06-26 14:58:58 -04:00
Qstick 316543b9aa Change Azure to Agile Config
[skip ci]
2021-06-26 11:07:51 -04:00
Qstick 117ebcff2d Fix default azure board buckets
[skip ci]
2021-06-26 10:55:13 -04:00
Qstick aab394b2c8 Update azuresync.yml
[skip ci]
2021-06-26 10:51:14 -04:00
Qstick 6ae520c061 Test Azure Boards sync 2021-06-26 10:47:23 -04:00
bakerboy448 dfb254d2dc Fixed: Default Branch is now Develop 2021-06-26 06:36:55 -05:00
Weblate 07c03b0a12 Translated using Weblate (Portuguese)
Currently translated at 83.7% (356 of 425 strings)

Translated using Weblate (German)

Currently translated at 92.7% (394 of 425 strings)

Co-authored-by: Lizandra Candido da Silva <lizandra.c.s@gmail.com>
Co-authored-by: reloxx <reloxx@interia.pl>
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/de/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/pt/
Translation: Servarr/Prowlarr
2021-06-26 07:14:03 -04:00
bakerboy448 eb0cf2d5f6 bug update [skip ci] 2021-06-26 05:48:17 -05:00
Servarr 69c04ebe7a Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (425 of 425 strings)

Translated using Weblate (Portuguese)

Currently translated at 83.7% (356 of 425 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 0.9% (4 of 425 strings)

Co-authored-by: Lizandra Candido da Silva <lizandra.c.s@gmail.com>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: angelsky11 <angelsky11@gmail.com>
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/pt/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/pt_BR/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/zh_Hans/
Translation: Servarr/Prowlarr

Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: Lizandra Candido da Silva <lizandra.c.s@gmail.com>
Co-authored-by: angelsky11 <angelsky11@gmail.com>
2021-06-25 20:02:41 -05:00
bakerboy448 135db6d2ff Fixed: Cleanse additional AuthKey instances in logs 2021-06-24 19:27:32 -05:00
bakerboy448 c3deace9e6 Fixed: Incorrectly cleansing usetoken param 2021-06-24 18:56:15 -05:00
Qstick 9042594b14 Update FUNDING.yml to include GitHub sponsors 2021-06-24 19:52:20 -04:00
bakerboy448 44df0f5c3d Fixed: NZBGet Settings hint mentions Sabnzbd 2021-06-24 11:02:23 -05:00
bakerboy448 7b9446eb35 fix template formatting [skip ci] 2021-06-23 23:55:10 -05:00
132 changed files with 1188 additions and 664 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
# These are supported funding model platforms # These are supported funding model platforms
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] github: Prowlarr # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: # Replace with a single Patreon username patreon: # Replace with a single Patreon username
open_collective: prowlarr open_collective: prowlarr
ko_fi: # Replace with a single Ko-fi username ko_fi: # Replace with a single Ko-fi username
+1
View File
@@ -35,3 +35,4 @@ assignees: ''
Turn on Trace logs under Settings -> General and wait for the bug to occur again. Turn on Trace logs under Settings -> General and wait for the bug to occur again.
**Upload the full log file here (or another site (e.g. pastebin) and link it). Issues will be closed, if they do not include this!** **Upload the full log file here (or another site (e.g. pastebin) and link it). Issues will be closed, if they do not include this!**
<!-- Trace logs are named Prowlarr.trace.txt or Prowlarr.trace.#.txt and will contain "trace" in them--> <!-- Trace logs are named Prowlarr.trace.txt or Prowlarr.trace.#.txt and will contain "trace" in them-->
<!-- Please see the Wiki for how to provide proper and useful trace log files https://wiki.servarr.com/prowlarr/troubleshooting#logging-and-log-files -->
+1
View File
@@ -5,6 +5,7 @@ YES | NO
A few sentences describing the overall goals of the pull request's commits. A few sentences describing the overall goals of the pull request's commits.
#### Screenshot (if UI related) #### Screenshot (if UI related)
#### Todos #### Todos
- [ ] Tests - [ ] Tests
- [ ] Translation Keys - [ ] Translation Keys
+41
View File
@@ -0,0 +1,41 @@
name: Sync issue to Azure DevOps work item
on:
issues:
types:
[opened, edited, deleted, closed, reopened, labeled, unlabeled, assigned]
concurrency: azuresync-${{ github.event.issue.number }}
jobs:
alert:
runs-on: ubuntu-latest
steps:
- uses: danhellem/github-actions-issue-to-work-item@master
if: "${{ contains(github.event.issue.labels.*.name, 'Type: Bug') == true }}"
env:
ado_token: "${{ secrets.ADO_PERSONAL_ACCESS_TOKEN }}"
github_token: "${{ github.token }}"
ado_organization: "Servarr"
ado_project: "Servarr"
ado_area_path: "Servarr\\Prowlarr"
ado_wit: "Bug"
ado_new_state: "New"
ado_active_state: "Active"
ado_close_state: "Closed"
ado_bypassrules: true
log_level: 100
- uses: danhellem/github-actions-issue-to-work-item@master
if: "${{ contains(github.event.issue.labels.*.name, 'Type: Bug') == false }}"
env:
ado_token: "${{ secrets.ADO_PERSONAL_ACCESS_TOKEN }}"
github_token: "${{ github.token }}"
ado_organization: "Servarr"
ado_project: "Servarr"
ado_area_path: "Servarr\\Prowlarr"
ado_wit: "User Story"
ado_new_state: "New"
ado_active_state: "Active"
ado_close_state: "Closed"
ado_bypassrules: true
log_level: 100
+1 -1
View File
@@ -27,7 +27,7 @@ Setup guides, FAQ, the more information we have on the [wiki](https://wiki.serva
### Contributing Code ### ### Contributing Code ###
- If you're adding a new, already requested feature, please comment on [Github Issues](https://github.com/Prowlarr/Prowlarr/issues "Github Issues") so work is not duplicated (If you want to add something not already on there, please talk to us first) - If you're adding a new, already requested feature, please comment on [Github Issues](https://github.com/Prowlarr/Prowlarr/issues "Github Issues") so work is not duplicated (If you want to add something not already on there, please talk to us first)
- Rebase from Radarr's develop branch, don't merge - Rebase from Prowlarr's develop branch, don't merge
- Make meaningful commits, or squash them - Make meaningful commits, or squash them
- Feel free to make a pull request before work is complete, this will let us see where its at and make comments/suggest improvements - Feel free to make a pull request before work is complete, this will let us see where its at and make comments/suggest improvements
- Reach out to us on the discord if you have any questions - Reach out to us on the discord if you have any questions
+1 -1
View File
@@ -879,7 +879,7 @@ stages:
artifactName: 'WindowsAutomationScreenshots' artifactName: 'WindowsAutomationScreenshots'
targetPath: $(Build.SourcesDirectory) targetPath: $(Build.SourcesDirectory)
- checkout: none - checkout: none
- powershell: | - pwsh: |
iex ((New-Object System.Net.WebClient).DownloadString('https://raw.githubusercontent.com/Servarr/AzureDiscordNotify/master/DiscordNotify.ps1')) iex ((New-Object System.Net.WebClient).DownloadString('https://raw.githubusercontent.com/Servarr/AzureDiscordNotify/master/DiscordNotify.ps1'))
env: env:
SYSTEM_ACCESSTOKEN: $(System.AccessToken) SYSTEM_ACCESSTOKEN: $(System.AccessToken)
@@ -13,6 +13,7 @@ import ModalContent from 'Components/Modal/ModalContent';
import ModalFooter from 'Components/Modal/ModalFooter'; import ModalFooter from 'Components/Modal/ModalFooter';
import ModalHeader from 'Components/Modal/ModalHeader'; import ModalHeader from 'Components/Modal/ModalHeader';
import { inputTypes, kinds } from 'Helpers/Props'; import { inputTypes, kinds } from 'Helpers/Props';
import AdvancedSettingsButton from 'Settings/AdvancedSettingsButton';
import translate from 'Utilities/String/translate'; import translate from 'Utilities/String/translate';
import styles from './EditIndexerModalContent.css'; import styles from './EditIndexerModalContent.css';
@@ -31,6 +32,7 @@ function EditIndexerModalContent(props) {
onSavePress, onSavePress,
onTestPress, onTestPress,
onDeleteIndexerPress, onDeleteIndexerPress,
onAdvancedSettingsPress,
...otherProps ...otherProps
} = props; } = props;
@@ -165,6 +167,12 @@ function EditIndexerModalContent(props) {
</Button> </Button>
} }
<AdvancedSettingsButton
advancedSettings={advancedSettings}
onAdvancedSettingsPress={onAdvancedSettingsPress}
showLabel={false}
/>
<SpinnerErrorButton <SpinnerErrorButton
isSpinning={isTesting} isSpinning={isTesting}
error={saveError} error={saveError}
@@ -204,6 +212,7 @@ EditIndexerModalContent.propTypes = {
onModalClose: PropTypes.func.isRequired, onModalClose: PropTypes.func.isRequired,
onSavePress: PropTypes.func.isRequired, onSavePress: PropTypes.func.isRequired,
onTestPress: PropTypes.func.isRequired, onTestPress: PropTypes.func.isRequired,
onAdvancedSettingsPress: PropTypes.func.isRequired,
onDeleteIndexerPress: PropTypes.func onDeleteIndexerPress: PropTypes.func
}; };
@@ -3,6 +3,7 @@ import React, { Component } from 'react';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { createSelector } from 'reselect'; import { createSelector } from 'reselect';
import { saveIndexer, setIndexerFieldValue, setIndexerValue, testIndexer } from 'Store/Actions/indexerActions'; import { saveIndexer, setIndexerFieldValue, setIndexerValue, testIndexer } from 'Store/Actions/indexerActions';
import { toggleAdvancedSettings } from 'Store/Actions/settingsActions';
import createIndexerSchemaSelector from 'Store/Selectors/createIndexerSchemaSelector'; import createIndexerSchemaSelector from 'Store/Selectors/createIndexerSchemaSelector';
import EditIndexerModalContent from './EditIndexerModalContent'; import EditIndexerModalContent from './EditIndexerModalContent';
@@ -23,7 +24,8 @@ const mapDispatchToProps = {
setIndexerValue, setIndexerValue,
setIndexerFieldValue, setIndexerFieldValue,
saveIndexer, saveIndexer,
testIndexer testIndexer,
toggleAdvancedSettings
}; };
class EditIndexerModalContentConnector extends Component { class EditIndexerModalContentConnector extends Component {
@@ -56,6 +58,11 @@ class EditIndexerModalContentConnector extends Component {
this.props.testIndexer({ id: this.props.id }); this.props.testIndexer({ id: this.props.id });
} }
onAdvancedSettingsPress = () => {
console.log('settings');
this.props.toggleAdvancedSettings();
}
// //
// Render // Render
@@ -65,6 +72,7 @@ class EditIndexerModalContentConnector extends Component {
{...this.props} {...this.props}
onSavePress={this.onSavePress} onSavePress={this.onSavePress}
onTestPress={this.onTestPress} onTestPress={this.onTestPress}
onAdvancedSettingsPress={this.onAdvancedSettingsPress}
onInputChange={this.onInputChange} onInputChange={this.onInputChange}
onFieldChange={this.onFieldChange} onFieldChange={this.onFieldChange}
/> />
@@ -80,6 +88,7 @@ EditIndexerModalContentConnector.propTypes = {
item: PropTypes.object.isRequired, item: PropTypes.object.isRequired,
setIndexerValue: PropTypes.func.isRequired, setIndexerValue: PropTypes.func.isRequired,
setIndexerFieldValue: PropTypes.func.isRequired, setIndexerFieldValue: PropTypes.func.isRequired,
toggleAdvancedSettings: PropTypes.func.isRequired,
saveIndexer: PropTypes.func.isRequired, saveIndexer: PropTypes.func.isRequired,
testIndexer: PropTypes.func.isRequired, testIndexer: PropTypes.func.isRequired,
onModalClose: PropTypes.func.isRequired onModalClose: PropTypes.func.isRequired
@@ -71,7 +71,7 @@ class IndexerIndexRow extends Component {
const { const {
id, id,
name, name,
baseUrl, indexerUrls,
enable, enable,
redirect, redirect,
tags, tags,
@@ -248,7 +248,7 @@ class IndexerIndexRow extends Component {
className={styles.externalLink} className={styles.externalLink}
name={icons.EXTERNAL_LINK} name={icons.EXTERNAL_LINK}
title={'Website'} title={'Website'}
to={baseUrl.replace('api.', '')} to={indexerUrls[0].replace('api.', '')}
/> />
<IconButton <IconButton
@@ -289,7 +289,7 @@ class IndexerIndexRow extends Component {
IndexerIndexRow.propTypes = { IndexerIndexRow.propTypes = {
id: PropTypes.number.isRequired, id: PropTypes.number.isRequired,
baseUrl: PropTypes.string.isRequired, indexerUrls: PropTypes.arrayOf(PropTypes.string).isRequired,
protocol: PropTypes.string.isRequired, protocol: PropTypes.string.isRequired,
privacy: PropTypes.string.isRequired, privacy: PropTypes.string.isRequired,
priority: PropTypes.number.isRequired, priority: PropTypes.number.isRequired,
@@ -1,10 +1,22 @@
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import React from 'react'; import React from 'react';
import Label from 'Components/Label'; import Label from 'Components/Label';
import { kinds, tooltipPositions } from 'Helpers/Props';
import Tooltip from '../../Components/Tooltip/Tooltip';
function CategoryLabel({ categories }) { function CategoryLabel({ categories }) {
const sortedCategories = categories.filter((cat) => cat.name !== undefined).sort((c) => c.id); const sortedCategories = categories.filter((cat) => cat.name !== undefined).sort((c) => c.id);
if (categories?.length === 0) {
return (
<Tooltip
anchor={<Label kind={kinds.DANGER}>Unknown</Label>}
tooltip="Please report this issue to the GitHub as this shouldn't be happening"
position={tooltipPositions.LEFT}
/>
);
}
return ( return (
<span> <span>
{ {
@@ -20,6 +32,10 @@ function CategoryLabel({ categories }) {
); );
} }
CategoryLabel.defaultProps = {
categories: []
};
CategoryLabel.propTypes = { CategoryLabel.propTypes = {
categories: PropTypes.arrayOf(PropTypes.object).isRequired categories: PropTypes.arrayOf(PropTypes.object).isRequired
}; };
@@ -10,7 +10,8 @@ import styles from './AdvancedSettingsButton.css';
function AdvancedSettingsButton(props) { function AdvancedSettingsButton(props) {
const { const {
advancedSettings, advancedSettings,
onAdvancedSettingsPress onAdvancedSettingsPress,
showLabel
} = props; } = props;
return ( return (
@@ -43,18 +44,27 @@ function AdvancedSettingsButton(props) {
/> />
</span> </span>
<div className={styles.labelContainer}> {
<div className={styles.label}> showLabel &&
{advancedSettings ? translate('HideAdvanced') : translate('ShowAdvanced')} <div className={styles.labelContainer}>
</div> <div className={styles.label}>
</div> {advancedSettings ? translate('HideAdvanced') : translate('ShowAdvanced')}
</div>
</div>
}
</Link> </Link>
); );
} }
AdvancedSettingsButton.propTypes = { AdvancedSettingsButton.propTypes = {
advancedSettings: PropTypes.bool.isRequired, advancedSettings: PropTypes.bool.isRequired,
onAdvancedSettingsPress: PropTypes.func.isRequired onAdvancedSettingsPress: PropTypes.func.isRequired,
showLabel: PropTypes.bool.isRequired
};
AdvancedSettingsButton.defaultProps = {
showLabel: true
}; };
export default AdvancedSettingsButton; export default AdvancedSettingsButton;
+2 -1
View File
@@ -202,7 +202,8 @@ export const defaultState = {
export const persistState = [ export const persistState = [
'releases.customFilters', 'releases.customFilters',
'releases.selectedFilterKey' 'releases.selectedFilterKey',
'releases.columns'
]; ];
// //
@@ -19,6 +19,9 @@ namespace NzbDrone.Common.Test.InstrumentationTests
[TestCase(@"http://nzb.su/getnzb/2b51db35e1912ffc138825a12b9933d2.nzb&i=37292&r=2b51db35e1910123321025a12b9933d2")] [TestCase(@"http://nzb.su/getnzb/2b51db35e1912ffc138825a12b9933d2.nzb&i=37292&r=2b51db35e1910123321025a12b9933d2")]
[TestCase(@"https://horrorcharnel.org/takeloginhorror.php: username=mySecret&password=mySecret&use_sslvalue==&perm_ssl=1&submitme=X&use_ssl=1&returnto=%2F&captchaSelection=1230456")] [TestCase(@"https://horrorcharnel.org/takeloginhorror.php: username=mySecret&password=mySecret&use_sslvalue==&perm_ssl=1&submitme=X&use_ssl=1&returnto=%2F&captchaSelection=1230456")]
[TestCase(@"https://torrentdb.net/login: _token=2b51db35e1912ffc138825a12b9933d2&username=mySecret&password=mySecret&remember=on")] [TestCase(@"https://torrentdb.net/login: _token=2b51db35e1912ffc138825a12b9933d2&username=mySecret&password=mySecret&remember=on")]
[TestCase(@" var authkey = ""2b51db35e1910123321025a12b9933d2"";")]
[TestCase(@"https://hd-space.org/index.php?page=login: uid=mySecret&pwd=mySecret")]
[TestCase(@"https://beyond-hd.me/api/torrents/2b51db35e1912ffc138825a12b9933d2")]
// NzbGet // NzbGet
[TestCase(@"{ ""Name"" : ""ControlUsername"", ""Value"" : ""mySecret"" }, { ""Name"" : ""ControlPassword"", ""Value"" : ""mySecret"" }, ")] [TestCase(@"{ ""Name"" : ""ControlUsername"", ""Value"" : ""mySecret"" }, { ""Name"" : ""ControlPassword"", ""Value"" : ""mySecret"" }, ")]
@@ -90,5 +93,14 @@ namespace NzbDrone.Common.Test.InstrumentationTests
cleansedMessage.Should().Be(message); cleansedMessage.Should().Be(message);
} }
[TestCase(@"&useToken=2b51db35e1910123321025a12b9933d2")]
[TestCase(@"&useToken=2b51db35e1910123321025a12b9933d2")]
public void should_not_clean_usetoken(string message)
{
var cleansedMessage = CleanseLogMessage.Cleanse(message);
cleansedMessage.Should().Be(message);
}
} }
} }
@@ -11,13 +11,15 @@ namespace NzbDrone.Common.Instrumentation
private static readonly Regex[] CleansingRules = new[] private static readonly Regex[] CleansingRules = new[]
{ {
// Url // Url
new Regex(@"(?<=\?|&|: |;)(apikey|token|passkey|auth|authkey|user|uid|api|[a-z_]*apikey|account|passwd)=(?<secret>[^&=]+?)(?= |&|$)", RegexOptions.Compiled | RegexOptions.IgnoreCase), new Regex(@"(?<=\?|&|: |;)(apikey|token|passkey|auth|authkey|user|uid|api|[a-z_]*apikey|account|passwd|pwd)=(?<secret>[^&=]+?)(?= |&|$)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
new Regex(@"(?<=\?|&| )[^=]*?(_?token|username|passwo?rd)=(?<secret>[^&=]+?)(?= |&|$)", RegexOptions.Compiled | RegexOptions.IgnoreCase), new Regex(@"(?<=\?|&| )[^=]*?(_?(?<!use)token|username|passwo?rd)=(?<secret>[^&=]+?)(?= |&|$)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
new Regex(@"torrentleech\.org/(?!rss)(?<secret>[0-9a-z]+)", RegexOptions.Compiled | RegexOptions.IgnoreCase), new Regex(@"torrentleech\.org/(?!rss)(?<secret>[0-9a-z]+)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
new Regex(@"torrentleech\.org/rss/download/[0-9]+/(?<secret>[0-9a-z]+)", RegexOptions.Compiled | RegexOptions.IgnoreCase), new Regex(@"torrentleech\.org/rss/download/[0-9]+/(?<secret>[0-9a-z]+)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
new Regex(@"iptorrents\.com/[/a-z0-9?&;]*?(?:[?&;](u|tp)=(?<secret>[^&=;]+?))+(?= |;|&|$)", RegexOptions.Compiled | RegexOptions.IgnoreCase), new Regex(@"iptorrents\.com/[/a-z0-9?&;]*?(?:[?&;](u|tp)=(?<secret>[^&=;]+?))+(?= |;|&|$)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
new Regex(@"/fetch/[a-z0-9]{32}/(?<secret>[a-z0-9]{32})", RegexOptions.Compiled), new Regex(@"/fetch/[a-z0-9]{32}/(?<secret>[a-z0-9]{32})", RegexOptions.Compiled),
new Regex(@"getnzb.*?(?<=\?|&)(r)=(?<secret>[^&=]+?)(?= |&|$)", RegexOptions.Compiled | RegexOptions.IgnoreCase), new Regex(@"getnzb.*?(?<=\?|&)(r)=(?<secret>[^&=]+?)(?= |&|$)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
new Regex(@"(?<=authkey = "")(?<secret>[^&=]+?)(?="")", RegexOptions.Compiled | RegexOptions.IgnoreCase),
new Regex(@"(?<=beyond-hd\.[a-z]+/api/torrents/)(?<secret>[^&=][a-z0-9]+)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
// Path // Path
new Regex(@"""C:\\Users\\(?<secret>[^\""]+?)(\\|$)", RegexOptions.Compiled | RegexOptions.IgnoreCase), new Regex(@"""C:\\Users\\(?<secret>[^\""]+?)(\\|$)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
@@ -19,7 +19,8 @@ namespace NzbDrone.Core.Test.IndexerTests.FileListTests
Subject.Settings = new FileListSettings() Subject.Settings = new FileListSettings()
{ {
Passkey = "abcd", Passkey = "abcd",
Username = "somename" Username = "somename",
BaseUrl = "https://filelist.io"
}; };
Subject.Capabilities = new IndexerCapabilities Subject.Capabilities = new IndexerCapabilities
@@ -54,8 +55,6 @@ namespace NzbDrone.Core.Test.IndexerTests.FileListTests
SearchTerm = "Star Wars", SearchTerm = "Star Wars",
Categories = new int[] { 2000 } Categories = new int[] { 2000 }
}; };
Subject.BaseUrl = "https://filelist.io";
} }
private void MovieWithoutIMDB() private void MovieWithoutIMDB()
@@ -10,7 +10,8 @@ namespace NzbDrone.Core.Test.IndexerTests
public class TestIndexer : UsenetIndexerBase<TestIndexerSettings> public class TestIndexer : UsenetIndexerBase<TestIndexerSettings>
{ {
public override string Name => "Test Indexer"; public override string Name => "Test Indexer";
public override string BaseUrl => "http://testindexer.com"; public override string[] IndexerUrls => new string[] { "http://testindexer.com" };
public override string Description => "";
public override DownloadProtocol Protocol => DownloadProtocol.Usenet; public override DownloadProtocol Protocol => DownloadProtocol.Usenet;
@@ -1,12 +1,10 @@
using System; using System;
using System.Collections.Generic;
using NzbDrone.Core.Indexers; using NzbDrone.Core.Indexers;
using NzbDrone.Core.ThingiProvider;
using NzbDrone.Core.Validation; using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Test.IndexerTests namespace NzbDrone.Core.Test.IndexerTests
{ {
public class TestIndexerSettings : IProviderConfig public class TestIndexerSettings : IIndexerSettings
{ {
public NzbDroneValidationResult Validate() public NzbDroneValidationResult Validate()
{ {
@@ -1,11 +1,7 @@
using System; using System;
using System.Linq;
using System.Xml.Linq;
using NzbDrone.Common.Disk; using NzbDrone.Common.Disk;
using NzbDrone.Common.EnvironmentInfo; using NzbDrone.Common.EnvironmentInfo;
using NzbDrone.Common.Extensions; using NzbDrone.Common.Extensions;
using NzbDrone.Core.Lifecycle;
using NzbDrone.Core.Messaging.Events;
namespace NzbDrone.Core.Authentication namespace NzbDrone.Core.Authentication
{ {
@@ -180,7 +180,7 @@ namespace NzbDrone.Core.Configuration
public bool AnalyticsEnabled => GetValueBoolean("AnalyticsEnabled", true, persist: false); public bool AnalyticsEnabled => GetValueBoolean("AnalyticsEnabled", true, persist: false);
// TODO: Change back to "master" for the first stable release. // TODO: Change back to "master" for the first stable release.
public string Branch => GetValue("Branch", "nightly").ToLowerInvariant(); public string Branch => GetValue("Branch", "develop").ToLowerInvariant();
public string LogLevel => GetValue("LogLevel", "info").ToLowerInvariant(); public string LogLevel => GetValue("LogLevel", "info").ToLowerInvariant();
public string ConsoleLogLevel => GetValue("ConsoleLogLevel", string.Empty, persist: false); public string ConsoleLogLevel => GetValue("ConsoleLogLevel", string.Empty, persist: false);
@@ -33,7 +33,7 @@ namespace NzbDrone.Core.Configuration
var releaseInfoPath = Path.Combine(bin, "release_info"); var releaseInfoPath = Path.Combine(bin, "release_info");
PackageUpdateMechanism = UpdateMechanism.BuiltIn; PackageUpdateMechanism = UpdateMechanism.BuiltIn;
DefaultBranch = "nightly"; DefaultBranch = "develop";
if (Path.GetFileName(bin) == "bin" && diskProvider.FileExists(packageInfoPath)) if (Path.GetFileName(bin) == "bin" && diskProvider.FileExists(packageInfoPath))
{ {
@@ -1,6 +1,3 @@
using System;
using System.Collections.Generic;
using System.Data;
using FluentMigrator; using FluentMigrator;
using NzbDrone.Core.Datastore.Migration.Framework; using NzbDrone.Core.Datastore.Migration.Framework;
@@ -1,5 +1,4 @@
using FluentMigrator; using FluentMigrator;
using Newtonsoft.Json.Linq;
using NzbDrone.Core.Datastore.Migration.Framework; using NzbDrone.Core.Datastore.Migration.Framework;
namespace NzbDrone.Core.Datastore.Migration namespace NzbDrone.Core.Datastore.Migration
+1 -1
View File
@@ -46,7 +46,7 @@ namespace NzbDrone.Core.Datastore
.Ignore(i => i.Description) .Ignore(i => i.Description)
.Ignore(i => i.Language) .Ignore(i => i.Language)
.Ignore(i => i.Encoding) .Ignore(i => i.Encoding)
.Ignore(i => i.BaseUrl) .Ignore(i => i.IndexerUrls)
.Ignore(i => i.Protocol) .Ignore(i => i.Protocol)
.Ignore(i => i.Privacy) .Ignore(i => i.Privacy)
.Ignore(i => i.SupportsRss) .Ignore(i => i.SupportsRss)
@@ -41,10 +41,10 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
[FieldDefinition(1, Label = "Port", Type = FieldType.Textbox)] [FieldDefinition(1, Label = "Port", Type = FieldType.Textbox)]
public int Port { get; set; } public int Port { get; set; }
[FieldDefinition(2, Label = "Use SSL", Type = FieldType.Checkbox, HelpText = "Use secure connection when connecting to Sabnzbd")] [FieldDefinition(2, Label = "Use SSL", Type = FieldType.Checkbox, HelpText = "Use secure connection when connecting to NZBGet")]
public bool UseSsl { get; set; } public bool UseSsl { get; set; }
[FieldDefinition(3, Label = "Url Base", Type = FieldType.Textbox, Advanced = true, HelpText = "Adds a prefix to the nzbget url, e.g. http://[host]:[port]/[urlBase]/jsonrpc")] [FieldDefinition(3, Label = "Url Base", Type = FieldType.Textbox, Advanced = true, HelpText = "Adds a prefix to the NZBGet url, e.g. http://[host]:[port]/[urlBase]/jsonrpc")]
public string UrlBase { get; set; } public string UrlBase { get; set; }
[FieldDefinition(4, Label = "Username", Type = FieldType.Textbox, Privacy = PrivacyLevel.UserName)] [FieldDefinition(4, Label = "Username", Type = FieldType.Textbox, Privacy = PrivacyLevel.UserName)]
@@ -6,7 +6,6 @@ using FluentValidation.Results;
using NLog; using NLog;
using NzbDrone.Common.Disk; using NzbDrone.Common.Disk;
using NzbDrone.Common.Extensions; using NzbDrone.Common.Extensions;
using NzbDrone.Common.Http;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.Indexers; using NzbDrone.Core.Indexers;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
@@ -1,5 +1,4 @@
using System; using System;
using System.Net;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using MonoTorrent; using MonoTorrent;
@@ -1,6 +1,5 @@
using System; using System;
using NzbDrone.Common.Exceptions; using NzbDrone.Common.Exceptions;
using NzbDrone.Core.Parser.Model;
namespace NzbDrone.Core.Exceptions namespace NzbDrone.Core.Exceptions
{ {
@@ -1,5 +1,4 @@
using System; using System;
using NzbDrone.Core.Parser.Model;
namespace NzbDrone.Core.Exceptions namespace NzbDrone.Core.Exceptions
{ {
@@ -10,7 +10,7 @@ namespace NzbDrone.Core.Indexers.Definitions
public class Aither : Unit3dBase public class Aither : Unit3dBase
{ {
public override string Name => "Aither"; public override string Name => "Aither";
public override string BaseUrl => "https://aither.cc/"; public override string[] IndexerUrls => new string[] { "https://aither.cc/" };
public override string Description => "Aither is a Private Torrent Tracker for HD MOVIES / TV"; public override string Description => "Aither is a Private Torrent Tracker for HD MOVIES / TV";
public override string Language => "en-us"; public override string Language => "en-us";
public override IndexerPrivacy Privacy => IndexerPrivacy.Private; public override IndexerPrivacy Privacy => IndexerPrivacy.Private;
@@ -9,7 +9,7 @@ namespace NzbDrone.Core.Indexers.Definitions
public class AlphaRatio : Gazelle.Gazelle public class AlphaRatio : Gazelle.Gazelle
{ {
public override string Name => "AlphaRatio"; public override string Name => "AlphaRatio";
public override string BaseUrl => "https://alpharatio.cc/"; public override string[] IndexerUrls => new string[] { "https://alpharatio.cc/" };
public override string Description => "AlphaRatio(AR) is a Private Torrent Tracker for 0DAY / GENERAL"; public override string Description => "AlphaRatio(AR) is a Private Torrent Tracker for 0DAY / GENERAL";
public override IndexerPrivacy Privacy => IndexerPrivacy.Private; public override IndexerPrivacy Privacy => IndexerPrivacy.Private;
@@ -25,8 +25,7 @@ namespace NzbDrone.Core.Indexers.Definitions
Settings = Settings, Settings = Settings,
HttpClient = _httpClient, HttpClient = _httpClient,
Logger = _logger, Logger = _logger,
Capabilities = Capabilities, Capabilities = Capabilities
BaseUrl = BaseUrl
}; };
} }
@@ -18,7 +18,6 @@ using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
using NzbDrone.Core.Parser.Model; using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.ThingiProvider;
using NzbDrone.Core.Validation; using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.Definitions namespace NzbDrone.Core.Indexers.Definitions
@@ -26,7 +25,7 @@ namespace NzbDrone.Core.Indexers.Definitions
public class AnimeBytes : TorrentIndexerBase<AnimeBytesSettings> public class AnimeBytes : TorrentIndexerBase<AnimeBytesSettings>
{ {
public override string Name => "AnimeBytes"; public override string Name => "AnimeBytes";
public override string BaseUrl => "https://animebytes.tv/"; public override string[] IndexerUrls => new string[] { "https://animebytes.tv/" };
public override string Description => "Powered by Tentacles"; public override string Description => "Powered by Tentacles";
public override string Language => "en-us"; public override string Language => "en-us";
public override Encoding Encoding => Encoding.UTF8; public override Encoding Encoding => Encoding.UTF8;
@@ -41,12 +40,12 @@ namespace NzbDrone.Core.Indexers.Definitions
public override IIndexerRequestGenerator GetRequestGenerator() public override IIndexerRequestGenerator GetRequestGenerator()
{ {
return new AnimeBytesRequestGenerator() { Settings = Settings, Capabilities = Capabilities, BaseUrl = BaseUrl }; return new AnimeBytesRequestGenerator() { Settings = Settings, Capabilities = Capabilities };
} }
public override IParseIndexerResponse GetParser() public override IParseIndexerResponse GetParser()
{ {
return new AnimeBytesParser(Settings, Capabilities.Categories, BaseUrl); return new AnimeBytesParser(Settings, Capabilities.Categories);
} }
protected override bool CheckIfLoginNeeded(HttpResponse httpResponse) protected override bool CheckIfLoginNeeded(HttpResponse httpResponse)
@@ -101,7 +100,6 @@ namespace NzbDrone.Core.Indexers.Definitions
{ {
public AnimeBytesSettings Settings { get; set; } public AnimeBytesSettings Settings { get; set; }
public IndexerCapabilities Capabilities { get; set; } public IndexerCapabilities Capabilities { get; set; }
public string BaseUrl { get; set; }
public AnimeBytesRequestGenerator() public AnimeBytesRequestGenerator()
{ {
@@ -109,7 +107,7 @@ namespace NzbDrone.Core.Indexers.Definitions
private IEnumerable<IndexerRequest> GetPagedRequests(string searchType, string term, int[] categories) private IEnumerable<IndexerRequest> GetPagedRequests(string searchType, string term, int[] categories)
{ {
var searchUrl = string.Format("{0}/scrape.php", BaseUrl.TrimEnd('/')); var searchUrl = string.Format("{0}/scrape.php", Settings.BaseUrl.TrimEnd('/'));
var queryCollection = new NameValueCollection var queryCollection = new NameValueCollection
{ {
@@ -189,13 +187,11 @@ namespace NzbDrone.Core.Indexers.Definitions
{ {
private readonly AnimeBytesSettings _settings; private readonly AnimeBytesSettings _settings;
private readonly IndexerCapabilitiesCategories _categories; private readonly IndexerCapabilitiesCategories _categories;
private readonly string _baseUrl;
public AnimeBytesParser(AnimeBytesSettings settings, IndexerCapabilitiesCategories categories, string baseUrl) public AnimeBytesParser(AnimeBytesSettings settings, IndexerCapabilitiesCategories categories)
{ {
_settings = settings; _settings = settings;
_categories = categories; _categories = categories;
_baseUrl = baseUrl;
} }
public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse) public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse)
@@ -323,7 +319,7 @@ namespace NzbDrone.Core.Indexers.Definitions
var uploadTimeString = (string)torrent["UploadTime"]; var uploadTimeString = (string)torrent["UploadTime"];
var uploadTime = DateTime.ParseExact(uploadTimeString, "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture); var uploadTime = DateTime.ParseExact(uploadTimeString, "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture);
var publishDate = DateTime.SpecifyKind(uploadTime, DateTimeKind.Utc).ToLocalTime(); var publishDate = DateTime.SpecifyKind(uploadTime, DateTimeKind.Utc).ToLocalTime();
var details = new Uri(_baseUrl + "torrent/" + torrentId + "/group"); var details = new Uri(_settings.BaseUrl + "torrent/" + torrentId + "/group");
var size = (long)torrent["Size"]; var size = (long)torrent["Size"];
var snatched = (int)torrent["Snatched"]; var snatched = (int)torrent["Snatched"];
var seeders = (int)torrent["Seeders"]; var seeders = (int)torrent["Seeders"];
@@ -484,7 +480,7 @@ namespace NzbDrone.Core.Indexers.Definitions
} }
} }
public class AnimeBytesSettings : IProviderConfig public class AnimeBytesSettings : IIndexerSettings
{ {
private static readonly AnimeBytesSettingsValidator Validator = new AnimeBytesSettingsValidator(); private static readonly AnimeBytesSettingsValidator Validator = new AnimeBytesSettingsValidator();
@@ -494,10 +490,13 @@ namespace NzbDrone.Core.Indexers.Definitions
Username = ""; Username = "";
} }
[FieldDefinition(1, Label = "Passkey", Privacy = PrivacyLevel.Password, Type = FieldType.Password, HelpText = "Site Passkey")] [FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2, Label = "Passkey", Privacy = PrivacyLevel.Password, Type = FieldType.Password, HelpText = "Site Passkey")]
public string Passkey { get; set; } public string Passkey { get; set; }
[FieldDefinition(1, Label = "Username", HelpText = "Site Username", Type = FieldType.Textbox, Privacy = PrivacyLevel.UserName)] [FieldDefinition(3, Label = "Username", HelpText = "Site Username", Privacy = PrivacyLevel.UserName)]
public string Username { get; set; } public string Username { get; set; }
public NzbDroneValidationResult Validate() public NzbDroneValidationResult Validate()
@@ -16,7 +16,6 @@ using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
using NzbDrone.Core.Parser.Model; using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.ThingiProvider;
using NzbDrone.Core.Validation; using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.Definitions namespace NzbDrone.Core.Indexers.Definitions
@@ -25,8 +24,9 @@ namespace NzbDrone.Core.Indexers.Definitions
{ {
public override string Name => "AnimeTorrents"; public override string Name => "AnimeTorrents";
public override string BaseUrl => "https://animetorrents.me/"; public override string[] IndexerUrls => new string[] { "https://animetorrents.me/" };
private string LoginUrl => BaseUrl + "login.php"; public override string Description => "Definitive source for anime and manga";
private string LoginUrl => Settings.BaseUrl + "login.php";
public override DownloadProtocol Protocol => DownloadProtocol.Torrent; public override DownloadProtocol Protocol => DownloadProtocol.Torrent;
public override IndexerPrivacy Privacy => IndexerPrivacy.Private; public override IndexerPrivacy Privacy => IndexerPrivacy.Private;
public override IndexerCapabilities Capabilities => SetCapabilities(); public override IndexerCapabilities Capabilities => SetCapabilities();
@@ -38,12 +38,12 @@ namespace NzbDrone.Core.Indexers.Definitions
public override IIndexerRequestGenerator GetRequestGenerator() public override IIndexerRequestGenerator GetRequestGenerator()
{ {
return new AnimeTorrentsRequestGenerator() { Settings = Settings, Capabilities = Capabilities, BaseUrl = BaseUrl }; return new AnimeTorrentsRequestGenerator() { Settings = Settings, Capabilities = Capabilities };
} }
public override IParseIndexerResponse GetParser() public override IParseIndexerResponse GetParser()
{ {
return new AnimeTorrentsParser(Settings, Capabilities.Categories, BaseUrl); return new AnimeTorrentsParser(Settings, Capabilities.Categories);
} }
protected override async Task DoLogin() protected override async Task DoLogin()
@@ -135,7 +135,6 @@ namespace NzbDrone.Core.Indexers.Definitions
{ {
public AnimeTorrentsSettings Settings { get; set; } public AnimeTorrentsSettings Settings { get; set; }
public IndexerCapabilities Capabilities { get; set; } public IndexerCapabilities Capabilities { get; set; }
public string BaseUrl { get; set; }
public AnimeTorrentsRequestGenerator() public AnimeTorrentsRequestGenerator()
{ {
@@ -148,8 +147,8 @@ namespace NzbDrone.Core.Indexers.Definitions
// replace any space, special char, etc. with % (wildcard) // replace any space, special char, etc. with % (wildcard)
var replaceRegex = new Regex("[^a-zA-Z0-9]+"); var replaceRegex = new Regex("[^a-zA-Z0-9]+");
searchString = replaceRegex.Replace(searchString, "%"); searchString = replaceRegex.Replace(searchString, "%");
var searchUrl = BaseUrl + "ajax/torrents_data.php"; var searchUrl = Settings.BaseUrl + "ajax/torrents_data.php";
var searchUrlReferer = BaseUrl + "torrents.php?cat=0&searchin=filename&search="; var searchUrlReferer = Settings.BaseUrl + "torrents.php?cat=0&searchin=filename&search=";
var trackerCats = Capabilities.Categories.MapTorznabCapsToTrackers(categories) ?? new List<string>(); var trackerCats = Capabilities.Categories.MapTorznabCapsToTrackers(categories) ?? new List<string>();
@@ -229,13 +228,11 @@ namespace NzbDrone.Core.Indexers.Definitions
{ {
private readonly AnimeTorrentsSettings _settings; private readonly AnimeTorrentsSettings _settings;
private readonly IndexerCapabilitiesCategories _categories; private readonly IndexerCapabilitiesCategories _categories;
private readonly string _baseUrl;
public AnimeTorrentsParser(AnimeTorrentsSettings settings, IndexerCapabilitiesCategories categories, string baseUrl) public AnimeTorrentsParser(AnimeTorrentsSettings settings, IndexerCapabilitiesCategories categories)
{ {
_settings = settings; _settings = settings;
_categories = categories; _categories = categories;
_baseUrl = baseUrl;
} }
public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse) public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse)
@@ -340,7 +337,7 @@ namespace NzbDrone.Core.Indexers.Definitions
} }
} }
public class AnimeTorrentsSettings : IProviderConfig public class AnimeTorrentsSettings : IIndexerSettings
{ {
private static readonly AnimeTorrentsSettingsValidator Validator = new AnimeTorrentsSettingsValidator(); private static readonly AnimeTorrentsSettingsValidator Validator = new AnimeTorrentsSettingsValidator();
@@ -350,10 +347,13 @@ namespace NzbDrone.Core.Indexers.Definitions
Password = ""; Password = "";
} }
[FieldDefinition(1, Label = "Username", HelpText = "Site Username", Type = FieldType.Textbox, Privacy = PrivacyLevel.UserName)] [FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2, Label = "Username", HelpText = "Site Username", Privacy = PrivacyLevel.UserName)]
public string Username { get; set; } public string Username { get; set; }
[FieldDefinition(2, Label = "Password", HelpText = "Site Password", Type = FieldType.Password, Privacy = PrivacyLevel.Password)] [FieldDefinition(3, Label = "Password", Type = FieldType.Password, HelpText = "Site Password", Privacy = PrivacyLevel.Password)]
public string Password { get; set; } public string Password { get; set; }
public NzbDroneValidationResult Validate() public NzbDroneValidationResult Validate()
@@ -10,7 +10,7 @@ namespace NzbDrone.Core.Indexers.Definitions
public class AnimeWorld : Unit3dBase public class AnimeWorld : Unit3dBase
{ {
public override string Name => "AnimeWorld"; public override string Name => "AnimeWorld";
public override string BaseUrl => "https://animeworld.cx/"; public override string[] IndexerUrls => new string[] { "https://animeworld.cx/" };
public override string Description => "AnimeWorld (AW) is a GERMAN Private site for ANIME / MANGA / HENTAI"; public override string Description => "AnimeWorld (AW) is a GERMAN Private site for ANIME / MANGA / HENTAI";
public override string Language => "de-de"; public override string Language => "de-de";
@@ -24,8 +24,8 @@ namespace NzbDrone.Core.Indexers.Definitions
public class Anthelion : TorrentIndexerBase<AnthelionSettings> public class Anthelion : TorrentIndexerBase<AnthelionSettings>
{ {
public override string Name => "Anthelion"; public override string Name => "Anthelion";
public override string BaseUrl => "https://anthelion.me/"; public override string[] IndexerUrls => new string[] { "https://anthelion.me/" };
private string LoginUrl => BaseUrl + "login.php"; private string LoginUrl => Settings.BaseUrl + "login.php";
public override string Description => "A movies tracker"; public override string Description => "A movies tracker";
public override string Language => "en-us"; public override string Language => "en-us";
public override Encoding Encoding => Encoding.UTF8; public override Encoding Encoding => Encoding.UTF8;
@@ -40,12 +40,12 @@ namespace NzbDrone.Core.Indexers.Definitions
public override IIndexerRequestGenerator GetRequestGenerator() public override IIndexerRequestGenerator GetRequestGenerator()
{ {
return new AnthelionRequestGenerator() { Settings = Settings, Capabilities = Capabilities, BaseUrl = BaseUrl }; return new AnthelionRequestGenerator() { Settings = Settings, Capabilities = Capabilities };
} }
public override IParseIndexerResponse GetParser() public override IParseIndexerResponse GetParser()
{ {
return new AnthelionParser(Settings, Capabilities.Categories, BaseUrl); return new AnthelionParser(Settings, Capabilities.Categories);
} }
protected override async Task DoLogin() protected override async Task DoLogin()
@@ -79,9 +79,13 @@ namespace NzbDrone.Core.Indexers.Definitions
var response = await ExecuteAuth(authLoginRequest); var response = await ExecuteAuth(authLoginRequest);
if (!response.Content.Contains("logout.php")) if (CheckIfLoginNeeded(response))
{ {
throw new IndexerAuthException("Anthelion Auth Failed"); var parser = new HtmlParser();
var dom = parser.ParseDocument(response.Content);
var errorMessage = dom.QuerySelector("form#loginform").TextContent.Trim();
throw new IndexerAuthException(errorMessage);
} }
cookies = response.GetCookies(); cookies = response.GetCookies();
@@ -127,7 +131,6 @@ namespace NzbDrone.Core.Indexers.Definitions
{ {
public AnthelionSettings Settings { get; set; } public AnthelionSettings Settings { get; set; }
public IndexerCapabilities Capabilities { get; set; } public IndexerCapabilities Capabilities { get; set; }
public string BaseUrl { get; set; }
public AnthelionRequestGenerator() public AnthelionRequestGenerator()
{ {
@@ -135,7 +138,7 @@ namespace NzbDrone.Core.Indexers.Definitions
private IEnumerable<IndexerRequest> GetPagedRequests(string term, int[] categories, string imdbId = null) private IEnumerable<IndexerRequest> GetPagedRequests(string term, int[] categories, string imdbId = null)
{ {
var searchUrl = string.Format("{0}/torrents.php", BaseUrl.TrimEnd('/')); var searchUrl = string.Format("{0}/torrents.php", Settings.BaseUrl.TrimEnd('/'));
// TODO: IMDB search is available but it requires to parse the details page // TODO: IMDB search is available but it requires to parse the details page
var qc = new NameValueCollection var qc = new NameValueCollection
@@ -174,8 +177,6 @@ namespace NzbDrone.Core.Indexers.Definitions
{ {
var pageableRequests = new IndexerPageableRequestChain(); var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories));
return pageableRequests; return pageableRequests;
} }
@@ -192,8 +193,6 @@ namespace NzbDrone.Core.Indexers.Definitions
{ {
var pageableRequests = new IndexerPageableRequestChain(); var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories));
return pageableRequests; return pageableRequests;
} }
@@ -214,13 +213,11 @@ namespace NzbDrone.Core.Indexers.Definitions
{ {
private readonly AnthelionSettings _settings; private readonly AnthelionSettings _settings;
private readonly IndexerCapabilitiesCategories _categories; private readonly IndexerCapabilitiesCategories _categories;
private readonly string _baseUrl;
public AnthelionParser(AnthelionSettings settings, IndexerCapabilitiesCategories categories, string baseurl) public AnthelionParser(AnthelionSettings settings, IndexerCapabilitiesCategories categories)
{ {
_settings = settings; _settings = settings;
_categories = categories; _categories = categories;
_baseUrl = baseurl;
} }
public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse) public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse)
@@ -237,9 +234,9 @@ namespace NzbDrone.Core.Indexers.Definitions
var tags = row.QuerySelector("div.torrent_info").FirstChild.TextContent.Replace(" / ", " ").Trim(); var tags = row.QuerySelector("div.torrent_info").FirstChild.TextContent.Replace(" / ", " ").Trim();
var title = $"{qDetailsLink.TextContent} {year} {tags}"; var title = $"{qDetailsLink.TextContent} {year} {tags}";
var description = row.QuerySelector("div.tags").TextContent.Trim(); var description = row.QuerySelector("div.tags").TextContent.Trim();
var details = _baseUrl + qDetailsLink.GetAttribute("href"); var details = _settings.BaseUrl + qDetailsLink.GetAttribute("href");
var torrentId = qDetailsLink.GetAttribute("href").Split('=').Last(); var torrentId = qDetailsLink.GetAttribute("href").Split('=').Last();
var link = _baseUrl + "torrents.php?action=download&id=" + torrentId; var link = _settings.BaseUrl + "torrents.php?action=download&id=" + torrentId;
var posterStr = qDetailsLink.GetAttribute("data-cover"); var posterStr = qDetailsLink.GetAttribute("data-cover");
var poster = !string.IsNullOrWhiteSpace(posterStr) ? new Uri(qDetailsLink.GetAttribute("data-cover")) : null; var poster = !string.IsNullOrWhiteSpace(posterStr) ? new Uri(qDetailsLink.GetAttribute("data-cover")) : null;
@@ -308,7 +305,7 @@ namespace NzbDrone.Core.Indexers.Definitions
} }
} }
public class AnthelionSettings : IProviderConfig public class AnthelionSettings : IIndexerSettings
{ {
private static readonly AnthelionSettingsValidator Validator = new AnthelionSettingsValidator(); private static readonly AnthelionSettingsValidator Validator = new AnthelionSettingsValidator();
@@ -318,10 +315,13 @@ namespace NzbDrone.Core.Indexers.Definitions
Password = ""; Password = "";
} }
[FieldDefinition(1, Label = "Username", HelpText = "Site Username", Type = FieldType.Textbox, Privacy = PrivacyLevel.UserName)] [FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2, Label = "Username", HelpText = "Site Username", Privacy = PrivacyLevel.UserName)]
public string Username { get; set; } public string Username { get; set; }
[FieldDefinition(1, Label = "Password", HelpText = "Site Password", Type = FieldType.Password, Privacy = PrivacyLevel.Password)] [FieldDefinition(3, Label = "Password", HelpText = "Site Password", Type = FieldType.Password, Privacy = PrivacyLevel.Password)]
public string Password { get; set; } public string Password { get; set; }
public NzbDroneValidationResult Validate() public NzbDroneValidationResult Validate()
@@ -10,7 +10,8 @@ namespace NzbDrone.Core.Indexers.Definitions
public class AvistaZ : AvistazBase public class AvistaZ : AvistazBase
{ {
public override string Name => "AvistaZ"; public override string Name => "AvistaZ";
public override string BaseUrl => "https://avistaz.to/"; public override string[] IndexerUrls => new string[] { "https://avistaz.to/" };
public override string Description => "Aka AsiaTorrents";
public override IndexerPrivacy Privacy => IndexerPrivacy.Private; public override IndexerPrivacy Privacy => IndexerPrivacy.Private;
public AvistaZ(IIndexerRepository indexerRepository, IHttpClient httpClient, IEventAggregator eventAggregator, IIndexerStatusService indexerStatusService, IConfigService configService, Logger logger) public AvistaZ(IIndexerRepository indexerRepository, IHttpClient httpClient, IEventAggregator eventAggregator, IIndexerStatusService indexerStatusService, IConfigService configService, Logger logger)
@@ -25,8 +26,7 @@ namespace NzbDrone.Core.Indexers.Definitions
Settings = Settings, Settings = Settings,
HttpClient = _httpClient, HttpClient = _httpClient,
Logger = _logger, Logger = _logger,
Capabilities = Capabilities, Capabilities = Capabilities
BaseUrl = BaseUrl
}; };
} }
@@ -12,8 +12,8 @@ namespace NzbDrone.Core.Indexers.Definitions.Avistaz
public abstract class AvistazBase : TorrentIndexerBase<AvistazSettings> public abstract class AvistazBase : TorrentIndexerBase<AvistazSettings>
{ {
public override DownloadProtocol Protocol => DownloadProtocol.Torrent; public override DownloadProtocol Protocol => DownloadProtocol.Torrent;
public override string BaseUrl => ""; public override string[] IndexerUrls => new string[] { "" };
protected virtual string LoginUrl => BaseUrl + "api/v1/jackett/auth"; protected virtual string LoginUrl => Settings.BaseUrl + "api/v1/jackett/auth";
public override bool SupportsRss => true; public override bool SupportsRss => true;
public override bool SupportsSearch => true; public override bool SupportsSearch => true;
public override int PageSize => 50; public override int PageSize => 50;
@@ -38,8 +38,7 @@ namespace NzbDrone.Core.Indexers.Definitions.Avistaz
Settings = Settings, Settings = Settings,
HttpClient = _httpClient, HttpClient = _httpClient,
Logger = _logger, Logger = _logger,
Capabilities = Capabilities, Capabilities = Capabilities
BaseUrl = BaseUrl
}; };
} }
@@ -12,14 +12,13 @@ namespace NzbDrone.Core.Indexers.Definitions.Avistaz
public class AvistazRequestGenerator : IIndexerRequestGenerator public class AvistazRequestGenerator : IIndexerRequestGenerator
{ {
public AvistazSettings Settings { get; set; } public AvistazSettings Settings { get; set; }
public string BaseUrl { get; set; }
public IDictionary<string, string> AuthCookieCache { get; set; } public IDictionary<string, string> AuthCookieCache { get; set; }
public IHttpClient HttpClient { get; set; } public IHttpClient HttpClient { get; set; }
public IndexerCapabilities Capabilities { get; set; } public IndexerCapabilities Capabilities { get; set; }
public Logger Logger { get; set; } public Logger Logger { get; set; }
protected virtual string SearchUrl => BaseUrl + "api/v1/jackett/torrents"; protected virtual string SearchUrl => Settings.BaseUrl + "api/v1/jackett/torrents";
protected virtual bool ImdbInTags => false; protected virtual bool ImdbInTags => false;
public Func<IDictionary<string, string>> GetCookies { get; set; } public Func<IDictionary<string, string>> GetCookies { get; set; }
@@ -1,6 +1,5 @@
using FluentValidation; using FluentValidation;
using NzbDrone.Core.Annotations; using NzbDrone.Core.Annotations;
using NzbDrone.Core.ThingiProvider;
using NzbDrone.Core.Validation; using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.Definitions.Avistaz namespace NzbDrone.Core.Indexers.Definitions.Avistaz
@@ -15,7 +14,7 @@ namespace NzbDrone.Core.Indexers.Definitions.Avistaz
} }
} }
public class AvistazSettings : IProviderConfig public class AvistazSettings : IIndexerSettings
{ {
private static readonly AvistazSettingsValidator Validator = new AvistazSettingsValidator(); private static readonly AvistazSettingsValidator Validator = new AvistazSettingsValidator();
@@ -26,13 +25,16 @@ namespace NzbDrone.Core.Indexers.Definitions.Avistaz
public string Token { get; set; } public string Token { get; set; }
[FieldDefinition(1, Label = "Username", HelpText = "Site Username", Type = FieldType.Textbox, Privacy = PrivacyLevel.UserName)] [FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2, Label = "Username", HelpText = "Username", Privacy = PrivacyLevel.UserName)]
public string Username { get; set; } public string Username { get; set; }
[FieldDefinition(2, Label = "Password", HelpText = "Site Password", Type = FieldType.Password, Privacy = PrivacyLevel.Password)] [FieldDefinition(3, Label = "Password", Type = FieldType.Password, HelpText = "Password", Privacy = PrivacyLevel.Password)]
public string Password { get; set; } public string Password { get; set; }
[FieldDefinition(3, Label = "PID", HelpText = "PID from My Account or My Profile page")] [FieldDefinition(4, Label = "PID", HelpText = "PID from My Account or My Profile page")]
public string Pid { get; set; } public string Pid { get; set; }
public NzbDroneValidationResult Validate() public NzbDroneValidationResult Validate()
@@ -16,7 +16,6 @@ using NzbDrone.Core.Indexers.Exceptions;
using NzbDrone.Core.IndexerSearch.Definitions; using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Parser.Model; using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.ThingiProvider;
using NzbDrone.Core.Validation; using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.Definitions namespace NzbDrone.Core.Indexers.Definitions
@@ -25,8 +24,9 @@ namespace NzbDrone.Core.Indexers.Definitions
{ {
public override string Name => "BakaBT"; public override string Name => "BakaBT";
public override string BaseUrl => "https://bakabt.me/"; public override string[] IndexerUrls => new string[] { "https://bakabt.me/" };
private string LoginUrl => BaseUrl + "login.php"; public override string Description => "Anime Comunity";
private string LoginUrl => Settings.BaseUrl + "login.php";
public override DownloadProtocol Protocol => DownloadProtocol.Torrent; public override DownloadProtocol Protocol => DownloadProtocol.Torrent;
public override IndexerPrivacy Privacy => IndexerPrivacy.Private; public override IndexerPrivacy Privacy => IndexerPrivacy.Private;
public override IndexerCapabilities Capabilities => SetCapabilities(); public override IndexerCapabilities Capabilities => SetCapabilities();
@@ -38,12 +38,12 @@ namespace NzbDrone.Core.Indexers.Definitions
public override IIndexerRequestGenerator GetRequestGenerator() public override IIndexerRequestGenerator GetRequestGenerator()
{ {
return new BakaBTRequestGenerator() { Settings = Settings, Capabilities = Capabilities, BaseUrl = BaseUrl }; return new BakaBTRequestGenerator() { Settings = Settings, Capabilities = Capabilities };
} }
public override IParseIndexerResponse GetParser() public override IParseIndexerResponse GetParser()
{ {
return new BakaBTParser(Settings, Capabilities.Categories, BaseUrl); return new BakaBTParser(Settings, Capabilities.Categories);
} }
protected override async Task DoLogin() protected override async Task DoLogin()
@@ -138,7 +138,6 @@ namespace NzbDrone.Core.Indexers.Definitions
{ {
public BakaBTSettings Settings { get; set; } public BakaBTSettings Settings { get; set; }
public IndexerCapabilities Capabilities { get; set; } public IndexerCapabilities Capabilities { get; set; }
public string BaseUrl { get; set; }
public BakaBTRequestGenerator() public BakaBTRequestGenerator()
{ {
@@ -147,7 +146,7 @@ namespace NzbDrone.Core.Indexers.Definitions
private IEnumerable<IndexerRequest> GetPagedRequests(string term, int[] categories) private IEnumerable<IndexerRequest> GetPagedRequests(string term, int[] categories)
{ {
var searchString = term; var searchString = term;
var searchUrl = BaseUrl + "browse.php?only=0&hentai=1&incomplete=1&lossless=1&hd=1&multiaudio=1&bonus=1&reorder=1&q="; var searchUrl = Settings.BaseUrl + "browse.php?only=0&hentai=1&incomplete=1&lossless=1&hd=1&multiaudio=1&bonus=1&reorder=1&q=";
var match = Regex.Match(term, @".*(?=\s(?:[Ee]\d+|\d+)$)"); var match = Regex.Match(term, @".*(?=\s(?:[Ee]\d+|\d+)$)");
if (match.Success) if (match.Success)
@@ -213,14 +212,12 @@ namespace NzbDrone.Core.Indexers.Definitions
{ {
private readonly BakaBTSettings _settings; private readonly BakaBTSettings _settings;
private readonly IndexerCapabilitiesCategories _categories; private readonly IndexerCapabilitiesCategories _categories;
private readonly string _baseUrl;
private readonly List<IndexerCategory> _defaultCategories = new List<IndexerCategory> { NewznabStandardCategory.TVAnime }; private readonly List<IndexerCategory> _defaultCategories = new List<IndexerCategory> { NewznabStandardCategory.TVAnime };
public BakaBTParser(BakaBTSettings settings, IndexerCapabilitiesCategories categories, string baseUrl) public BakaBTParser(BakaBTSettings settings, IndexerCapabilitiesCategories categories)
{ {
_settings = settings; _settings = settings;
_categories = categories; _categories = categories;
_baseUrl = baseUrl;
} }
public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse) public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse)
@@ -300,10 +297,10 @@ namespace NzbDrone.Core.Indexers.Definitions
release.Categories = currentCategories; release.Categories = currentCategories;
//release.Description = row.QuerySelector("span.tags")?.TextContent; //release.Description = row.QuerySelector("span.tags")?.TextContent;
release.Guid = _baseUrl + qTitleLink.GetAttribute("href"); release.Guid = _settings.BaseUrl + qTitleLink.GetAttribute("href");
release.InfoUrl = release.Guid; release.InfoUrl = release.Guid;
release.DownloadUrl = _baseUrl + row.QuerySelector(".peers a").GetAttribute("href"); release.DownloadUrl = _settings.BaseUrl + row.QuerySelector(".peers a").GetAttribute("href");
var grabs = row.QuerySelectorAll(".peers")[0].FirstChild.NodeValue.TrimEnd().TrimEnd('/').TrimEnd(); var grabs = row.QuerySelectorAll(".peers")[0].FirstChild.NodeValue.TrimEnd().TrimEnd('/').TrimEnd();
grabs = grabs.Replace("k", "000"); grabs = grabs.Replace("k", "000");
@@ -392,7 +389,7 @@ namespace NzbDrone.Core.Indexers.Definitions
} }
} }
public class BakaBTSettings : IProviderConfig public class BakaBTSettings : IIndexerSettings
{ {
private static readonly BakaBTSettingsValidator Validator = new BakaBTSettingsValidator(); private static readonly BakaBTSettingsValidator Validator = new BakaBTSettingsValidator();
@@ -402,16 +399,19 @@ namespace NzbDrone.Core.Indexers.Definitions
Password = ""; Password = "";
} }
[FieldDefinition(1, Label = "Username", HelpText = "Site Username", Type = FieldType.Textbox, Privacy = PrivacyLevel.UserName)] [FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2, Label = "Username", HelpText = "Site Username", Privacy = PrivacyLevel.UserName)]
public string Username { get; set; } public string Username { get; set; }
[FieldDefinition(2, Label = "Password", HelpText = "Site Password", Type = FieldType.Password, Privacy = PrivacyLevel.Password)] [FieldDefinition(3, Label = "Password", Type = FieldType.Password, HelpText = "Site Password", Privacy = PrivacyLevel.Password)]
public string Password { get; set; } public string Password { get; set; }
[FieldDefinition(3, Label = "Add Romaji Title", Type = FieldType.Checkbox, HelpText = "Add releases for Romaji Title")] [FieldDefinition(4, Label = "Add Romaji Title", Type = FieldType.Checkbox, HelpText = "Add releases for Romaji Title")]
public bool AddRomajiTitle { get; set; } public bool AddRomajiTitle { get; set; }
[FieldDefinition(4, Label = "Append Season", Type = FieldType.Checkbox, HelpText = "Append Season for Sonarr Compatibility")] [FieldDefinition(5, Label = "Append Season", Type = FieldType.Checkbox, HelpText = "Append Season for Sonarr Compatibility")]
public bool AppendSeason { get; set; } public bool AppendSeason { get; set; }
public NzbDroneValidationResult Validate() public NzbDroneValidationResult Validate()
@@ -16,7 +16,6 @@ using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
using NzbDrone.Core.Parser.Model; using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.ThingiProvider;
using NzbDrone.Core.Validation; using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.Definitions namespace NzbDrone.Core.Indexers.Definitions
@@ -25,7 +24,8 @@ namespace NzbDrone.Core.Indexers.Definitions
{ {
public override string Name => "BeyondHD"; public override string Name => "BeyondHD";
public override string BaseUrl => "https://beyond-hd.me/"; public override string[] IndexerUrls => new string[] { "https://beyond-hd.me/" };
public override string Description => "Without BeyondHD, your HDTV is just a TV";
public override DownloadProtocol Protocol => DownloadProtocol.Torrent; public override DownloadProtocol Protocol => DownloadProtocol.Torrent;
public override IndexerPrivacy Privacy => IndexerPrivacy.Private; public override IndexerPrivacy Privacy => IndexerPrivacy.Private;
public override IndexerCapabilities Capabilities => SetCapabilities(); public override IndexerCapabilities Capabilities => SetCapabilities();
@@ -37,12 +37,12 @@ namespace NzbDrone.Core.Indexers.Definitions
public override IIndexerRequestGenerator GetRequestGenerator() public override IIndexerRequestGenerator GetRequestGenerator()
{ {
return new BeyondHDRequestGenerator() { Settings = Settings, Capabilities = Capabilities, BaseUrl = BaseUrl }; return new BeyondHDRequestGenerator() { Settings = Settings, Capabilities = Capabilities };
} }
public override IParseIndexerResponse GetParser() public override IParseIndexerResponse GetParser()
{ {
return new BeyondHDParser(Settings, Capabilities.Categories, BaseUrl); return new BeyondHDParser(Settings, Capabilities.Categories);
} }
private IndexerCapabilities SetCapabilities() private IndexerCapabilities SetCapabilities()
@@ -70,7 +70,6 @@ namespace NzbDrone.Core.Indexers.Definitions
{ {
public BeyondHDSettings Settings { get; set; } public BeyondHDSettings Settings { get; set; }
public IndexerCapabilities Capabilities { get; set; } public IndexerCapabilities Capabilities { get; set; }
public string BaseUrl { get; set; }
public BeyondHDRequestGenerator() public BeyondHDRequestGenerator()
{ {
@@ -106,7 +105,7 @@ namespace NzbDrone.Core.Indexers.Definitions
body.Add("categories", string.Join(",", cats)); body.Add("categories", string.Join(",", cats));
} }
var searchUrl = BaseUrl + "api/torrents/" + Settings.ApiKey; var searchUrl = Settings.BaseUrl + "api/torrents/" + Settings.ApiKey;
var request = new HttpRequest(searchUrl, HttpAccept.Json); var request = new HttpRequest(searchUrl, HttpAccept.Json);
@@ -172,13 +171,11 @@ namespace NzbDrone.Core.Indexers.Definitions
{ {
private readonly BeyondHDSettings _settings; private readonly BeyondHDSettings _settings;
private readonly IndexerCapabilitiesCategories _categories; private readonly IndexerCapabilitiesCategories _categories;
private readonly string _baseUrl;
public BeyondHDParser(BeyondHDSettings settings, IndexerCapabilitiesCategories categories, string baseUrl) public BeyondHDParser(BeyondHDSettings settings, IndexerCapabilitiesCategories categories)
{ {
_settings = settings; _settings = settings;
_categories = categories; _categories = categories;
_baseUrl = baseUrl;
} }
public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse) public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse)
@@ -242,7 +239,7 @@ namespace NzbDrone.Core.Indexers.Definitions
} }
} }
public class BeyondHDSettings : IProviderConfig public class BeyondHDSettings : IIndexerSettings
{ {
private static readonly BeyondHDSettingsValidator Validator = new BeyondHDSettingsValidator(); private static readonly BeyondHDSettingsValidator Validator = new BeyondHDSettingsValidator();
@@ -250,10 +247,13 @@ namespace NzbDrone.Core.Indexers.Definitions
{ {
} }
[FieldDefinition(1, Label = "API Key", HelpText = "API Key from Site", Privacy = PrivacyLevel.ApiKey)] [FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2, Label = "API Key", HelpText = "API Key from Site", Privacy = PrivacyLevel.ApiKey)]
public string ApiKey { get; set; } public string ApiKey { get; set; }
[FieldDefinition(2, Label = "RSS Key", HelpText = "RSS Key from Site", Privacy = PrivacyLevel.ApiKey)] [FieldDefinition(3, Label = "RSS Key", HelpText = "RSS Key from Site", Privacy = PrivacyLevel.ApiKey)]
public string RssKey { get; set; } public string RssKey { get; set; }
public NzbDroneValidationResult Validate() public NzbDroneValidationResult Validate()
@@ -10,7 +10,8 @@ namespace NzbDrone.Core.Indexers.Definitions
public class Blutopia : Unit3dBase public class Blutopia : Unit3dBase
{ {
public override string Name => "Blutopia"; public override string Name => "Blutopia";
public override string BaseUrl => "https://blutopia.xyz/"; public override string[] IndexerUrls => new string[] { "https://blutopia.xyz/" };
public override string Description => "Blutopia (BLU) is a Private Torrent Tracker for HD MOVIES / TV";
public override IndexerPrivacy Privacy => IndexerPrivacy.Private; public override IndexerPrivacy Privacy => IndexerPrivacy.Private;
public Blutopia(IHttpClient httpClient, IEventAggregator eventAggregator, IIndexerStatusService indexerStatusService, IConfigService configService, Logger logger) public Blutopia(IHttpClient httpClient, IEventAggregator eventAggregator, IIndexerStatusService indexerStatusService, IConfigService configService, Logger logger)
@@ -17,7 +17,8 @@ namespace NzbDrone.Core.Indexers.BroadcastheNet
public override int PageSize => 100; public override int PageSize => 100;
public override IndexerCapabilities Capabilities => SetCapabilities(); public override IndexerCapabilities Capabilities => SetCapabilities();
public override string BaseUrl => "http://api.broadcasthe.net/"; public override string[] IndexerUrls => new string[] { "http://api.broadcasthe.net/" };
public override string Description => "BroadcasTheNet (BTN) is an invite-only torrent tracker focused on TV shows";
public BroadcastheNet(IHttpClient httpClient, IEventAggregator eventAggregator, IIndexerStatusService indexerStatusService, IConfigService configService, Logger logger) public BroadcastheNet(IHttpClient httpClient, IEventAggregator eventAggregator, IIndexerStatusService indexerStatusService, IConfigService configService, Logger logger)
: base(httpClient, eventAggregator, indexerStatusService, configService, logger) : base(httpClient, eventAggregator, indexerStatusService, configService, logger)
@@ -26,7 +27,7 @@ namespace NzbDrone.Core.Indexers.BroadcastheNet
public override IIndexerRequestGenerator GetRequestGenerator() public override IIndexerRequestGenerator GetRequestGenerator()
{ {
var requestGenerator = new BroadcastheNetRequestGenerator() { Settings = Settings, PageSize = PageSize, BaseUrl = BaseUrl, Capabilities = Capabilities }; var requestGenerator = new BroadcastheNetRequestGenerator() { Settings = Settings, PageSize = PageSize, Capabilities = Capabilities };
var releaseInfo = _indexerStatusService.GetLastRssSyncReleaseInfo(Definition.Id); var releaseInfo = _indexerStatusService.GetLastRssSyncReleaseInfo(Definition.Id);
if (releaseInfo != null) if (releaseInfo != null)
@@ -16,7 +16,6 @@ namespace NzbDrone.Core.Indexers.BroadcastheNet
public Func<IDictionary<string, string>> GetCookies { get; set; } public Func<IDictionary<string, string>> GetCookies { get; set; }
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; } public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
public string BaseUrl { get; set; }
public BroadcastheNetRequestGenerator() public BroadcastheNetRequestGenerator()
{ {
@@ -26,7 +25,7 @@ namespace NzbDrone.Core.Indexers.BroadcastheNet
private IEnumerable<IndexerRequest> GetPagedRequests(BroadcastheNetTorrentQuery parameters, int results, int offset) private IEnumerable<IndexerRequest> GetPagedRequests(BroadcastheNetTorrentQuery parameters, int results, int offset)
{ {
var builder = new JsonRpcRequestBuilder(BaseUrl) var builder = new JsonRpcRequestBuilder(Settings.BaseUrl)
.Call("getTorrents", Settings.ApiKey, parameters, results, offset); .Call("getTorrents", Settings.ApiKey, parameters, results, offset);
builder.SuppressHttpError = true; builder.SuppressHttpError = true;
@@ -1,6 +1,5 @@
using FluentValidation; using FluentValidation;
using NzbDrone.Core.Annotations; using NzbDrone.Core.Annotations;
using NzbDrone.Core.ThingiProvider;
using NzbDrone.Core.Validation; using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.BroadcastheNet namespace NzbDrone.Core.Indexers.BroadcastheNet
@@ -13,7 +12,7 @@ namespace NzbDrone.Core.Indexers.BroadcastheNet
} }
} }
public class BroadcastheNetSettings : IProviderConfig public class BroadcastheNetSettings : IIndexerSettings
{ {
private static readonly BroadcastheNetSettingsValidator Validator = new BroadcastheNetSettingsValidator(); private static readonly BroadcastheNetSettingsValidator Validator = new BroadcastheNetSettingsValidator();
@@ -21,7 +20,10 @@ namespace NzbDrone.Core.Indexers.BroadcastheNet
{ {
} }
[FieldDefinition(1, Label = "API Key", Privacy = PrivacyLevel.ApiKey)] [FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2, Label = "API Key", Privacy = PrivacyLevel.ApiKey)]
public string ApiKey { get; set; } public string ApiKey { get; set; }
public NzbDroneValidationResult Validate() public NzbDroneValidationResult Validate()
@@ -8,7 +8,8 @@ namespace NzbDrone.Core.Indexers.Definitions
public class BrokenStones : Gazelle.Gazelle public class BrokenStones : Gazelle.Gazelle
{ {
public override string Name => "BrokenStones"; public override string Name => "BrokenStones";
public override string BaseUrl => "https://brokenstones.club/"; public override string[] IndexerUrls => new string[] { "https://brokenstones.club/" };
public override string Description => "Broken Stones is a Private site for MacOS and iOS APPS / GAMES";
public override IndexerPrivacy Privacy => IndexerPrivacy.Private; public override IndexerPrivacy Privacy => IndexerPrivacy.Private;
public BrokenStones(IHttpClient httpClient, IEventAggregator eventAggregator, IIndexerStatusService indexerStatusService, IConfigService configService, Logger logger) public BrokenStones(IHttpClient httpClient, IEventAggregator eventAggregator, IIndexerStatusService indexerStatusService, IConfigService configService, Logger logger)
@@ -8,7 +8,8 @@ namespace NzbDrone.Core.Indexers.Definitions
public class CGPeers : Gazelle.Gazelle public class CGPeers : Gazelle.Gazelle
{ {
public override string Name => "CGPeers"; public override string Name => "CGPeers";
public override string BaseUrl => "https://cgpeers.to/"; public override string[] IndexerUrls => new string[] { "https://cgpeers.to/" };
public override string Description => "CGPeers is a Private Torrent Tracker for GRAPHICS SOFTWARE / TUTORIALS / ETC";
public override IndexerPrivacy Privacy => IndexerPrivacy.Private; public override IndexerPrivacy Privacy => IndexerPrivacy.Private;
public CGPeers(IHttpClient httpClient, IEventAggregator eventAggregator, IIndexerStatusService indexerStatusService, IConfigService configService, Logger logger) public CGPeers(IHttpClient httpClient, IEventAggregator eventAggregator, IIndexerStatusService indexerStatusService, IConfigService configService, Logger logger)
@@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Net; using System.Net;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
@@ -22,7 +23,8 @@ namespace NzbDrone.Core.Indexers.Cardigann
private readonly ICached<CardigannRequestGenerator> _generatorCache; private readonly ICached<CardigannRequestGenerator> _generatorCache;
public override string Name => "Cardigann"; public override string Name => "Cardigann";
public override string BaseUrl => ""; public override string[] IndexerUrls => new string[] { "" };
public override string Description => "";
public override DownloadProtocol Protocol => DownloadProtocol.Torrent; public override DownloadProtocol Protocol => DownloadProtocol.Torrent;
public override IndexerPrivacy Privacy => IndexerPrivacy.Private; public override IndexerPrivacy Privacy => IndexerPrivacy.Private;
@@ -44,6 +46,8 @@ namespace NzbDrone.Core.Indexers.Cardigann
generator = (CardigannRequestGenerator)SetCookieFunctions(generator); generator = (CardigannRequestGenerator)SetCookieFunctions(generator);
generator.Settings = Settings;
_generatorCache.ClearExpired(); _generatorCache.ClearExpired();
return generator; return generator;
@@ -120,6 +124,7 @@ namespace NzbDrone.Core.Indexers.Cardigann
Language = definition.Language, Language = definition.Language,
Description = definition.Description, Description = definition.Description,
Implementation = GetType().Name, Implementation = GetType().Name,
IndexerUrls = definition.Links.ToArray(),
Settings = new CardigannSettings { DefinitionFile = definition.File }, Settings = new CardigannSettings { DefinitionFile = definition.File },
Protocol = DownloadProtocol.Torrent, Protocol = DownloadProtocol.Torrent,
Privacy = definition.Type == "private" ? IndexerPrivacy.Private : IndexerPrivacy.Public, Privacy = definition.Type == "private" ? IndexerPrivacy.Private : IndexerPrivacy.Public,
@@ -133,11 +138,6 @@ namespace NzbDrone.Core.Indexers.Cardigann
protected override bool CheckIfLoginNeeded(HttpResponse httpResponse) protected override bool CheckIfLoginNeeded(HttpResponse httpResponse)
{ {
if (httpResponse.HasHttpError)
{
return true;
}
var generator = (CardigannRequestGenerator)GetRequestGenerator(); var generator = (CardigannRequestGenerator)GetRequestGenerator();
SetCookieFunctions(generator); SetCookieFunctions(generator);
@@ -236,6 +236,16 @@ namespace NzbDrone.Core.Indexers.Cardigann
}; };
} }
if (action == "getUrls")
{
var devices = ((IndexerDefinition)Definition).IndexerUrls;
return new
{
options = devices.Select(d => new { Value = d, Name = d })
};
}
return null; return null;
} }
} }
@@ -23,7 +23,7 @@ namespace NzbDrone.Core.Indexers.Cardigann
protected readonly Encoding _encoding; protected readonly Encoding _encoding;
protected readonly IConfigService _configService; protected readonly IConfigService _configService;
protected string SiteLink { get; private set; } protected virtual string SiteLink { get; private set; }
protected readonly List<CategoryMapping> _categoryMapping = new List<CategoryMapping>(); protected readonly List<CategoryMapping> _categoryMapping = new List<CategoryMapping>();
protected readonly List<string> _defaultCategories = new List<string>(); protected readonly List<string> _defaultCategories = new List<string>();
@@ -18,6 +18,8 @@ namespace NzbDrone.Core.Indexers.Cardigann
{ {
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; } public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
protected override string SiteLink => Settings?.BaseUrl ?? _definition.Links.First();
public CardigannParser(IConfigService configService, public CardigannParser(IConfigService configService,
CardigannDefinition definition, CardigannDefinition definition,
Logger logger) Logger logger)
@@ -22,6 +22,7 @@ namespace NzbDrone.Core.Indexers.Cardigann
public IDictionary<string, string> Cookies { get; set; } public IDictionary<string, string> Cookies { get; set; }
protected HttpResponse landingResult; protected HttpResponse landingResult;
protected IHtmlDocument landingResultDocument; protected IHtmlDocument landingResultDocument;
protected override string SiteLink => Settings?.BaseUrl ?? _definition.Links.First();
public CardigannRequestGenerator(IConfigService configService, public CardigannRequestGenerator(IConfigService configService,
CardigannDefinition definition, CardigannDefinition definition,
@@ -797,6 +798,11 @@ namespace NzbDrone.Core.Indexers.Cardigann
return false; return false;
} }
if (response.HasHttpError)
{
return true;
}
var parser = new HtmlParser(); var parser = new HtmlParser();
var document = parser.ParseDocument(response.Content); var document = parser.ParseDocument(response.Content);
@@ -1,7 +1,6 @@
using System.Collections.Generic; using System.Collections.Generic;
using FluentValidation; using FluentValidation;
using NzbDrone.Core.Annotations; using NzbDrone.Core.Annotations;
using NzbDrone.Core.ThingiProvider;
using NzbDrone.Core.Validation; using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.Cardigann namespace NzbDrone.Core.Indexers.Cardigann
@@ -13,7 +12,7 @@ namespace NzbDrone.Core.Indexers.Cardigann
} }
} }
public class CardigannSettings : IProviderConfig public class CardigannSettings : IIndexerSettings
{ {
private static readonly CardigannSettingsValidator Validator = new CardigannSettingsValidator(); private static readonly CardigannSettingsValidator Validator = new CardigannSettingsValidator();
@@ -25,6 +24,9 @@ namespace NzbDrone.Core.Indexers.Cardigann
[FieldDefinition(0, Hidden = HiddenType.Hidden)] [FieldDefinition(0, Hidden = HiddenType.Hidden)]
public string DefinitionFile { get; set; } public string DefinitionFile { get; set; }
[FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
public Dictionary<string, object> ExtraFieldData { get; set; } public Dictionary<string, object> ExtraFieldData { get; set; }
// Field 8 is used by TorznabSettings MinimumSeeders // Field 8 is used by TorznabSettings MinimumSeeders
@@ -10,7 +10,8 @@ namespace NzbDrone.Core.Indexers.Definitions
public class CinemaZ : AvistazBase public class CinemaZ : AvistazBase
{ {
public override string Name => "CinemaZ"; public override string Name => "CinemaZ";
public override string BaseUrl => "https://cinemaz.to/"; public override string[] IndexerUrls => new string[] { "https://cinemaz.to/" };
public override string Description => "Part of the Avistaz network.";
public override IndexerPrivacy Privacy => IndexerPrivacy.Private; public override IndexerPrivacy Privacy => IndexerPrivacy.Private;
public CinemaZ(IIndexerRepository indexerRepository, IHttpClient httpClient, IEventAggregator eventAggregator, IIndexerStatusService indexerStatusService, IConfigService configService, Logger logger) public CinemaZ(IIndexerRepository indexerRepository, IHttpClient httpClient, IEventAggregator eventAggregator, IIndexerStatusService indexerStatusService, IConfigService configService, Logger logger)
@@ -25,8 +26,7 @@ namespace NzbDrone.Core.Indexers.Definitions
Settings = Settings, Settings = Settings,
HttpClient = _httpClient, HttpClient = _httpClient,
Logger = _logger, Logger = _logger,
Capabilities = Capabilities, Capabilities = Capabilities
BaseUrl = BaseUrl
}; };
} }
@@ -16,7 +16,6 @@ using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
using NzbDrone.Core.Parser.Model; using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.ThingiProvider;
using NzbDrone.Core.Validation; using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.Definitions namespace NzbDrone.Core.Indexers.Definitions
@@ -24,7 +23,8 @@ namespace NzbDrone.Core.Indexers.Definitions
public class DigitalCore : TorrentIndexerBase<DigitalCoreSettings> public class DigitalCore : TorrentIndexerBase<DigitalCoreSettings>
{ {
public override string Name => "DigitalCore"; public override string Name => "DigitalCore";
public override string BaseUrl => "https://digitalcore.club/"; public override string[] IndexerUrls => new string[] { "https://digitalcore.club/" };
public override string Description => "DigitalCore is a Private Torrent Tracker for MOVIES / TV / GENERAL";
public override DownloadProtocol Protocol => DownloadProtocol.Torrent; public override DownloadProtocol Protocol => DownloadProtocol.Torrent;
public override IndexerPrivacy Privacy => IndexerPrivacy.Private; public override IndexerPrivacy Privacy => IndexerPrivacy.Private;
public override IndexerCapabilities Capabilities => SetCapabilities(); public override IndexerCapabilities Capabilities => SetCapabilities();
@@ -36,12 +36,12 @@ namespace NzbDrone.Core.Indexers.Definitions
public override IIndexerRequestGenerator GetRequestGenerator() public override IIndexerRequestGenerator GetRequestGenerator()
{ {
return new DigitalCoreRequestGenerator() { Settings = Settings, PageSize = PageSize, Capabilities = Capabilities, BaseUrl = BaseUrl }; return new DigitalCoreRequestGenerator() { Settings = Settings, PageSize = PageSize, Capabilities = Capabilities };
} }
public override IParseIndexerResponse GetParser() public override IParseIndexerResponse GetParser()
{ {
return new DigitalCoreParser(Settings, Capabilities.Categories, BaseUrl); return new DigitalCoreParser(Settings, Capabilities.Categories);
} }
protected override IDictionary<string, string> GetCookies() protected override IDictionary<string, string> GetCookies()
@@ -123,7 +123,6 @@ namespace NzbDrone.Core.Indexers.Definitions
public class DigitalCoreRequestGenerator : IIndexerRequestGenerator public class DigitalCoreRequestGenerator : IIndexerRequestGenerator
{ {
public string BaseUrl { get; set; }
public DigitalCoreSettings Settings { get; set; } public DigitalCoreSettings Settings { get; set; }
public IndexerCapabilities Capabilities { get; set; } public IndexerCapabilities Capabilities { get; set; }
@@ -138,7 +137,7 @@ namespace NzbDrone.Core.Indexers.Definitions
private IEnumerable<IndexerRequest> GetPagedRequests(string term, int[] categories, string imdbId = null) private IEnumerable<IndexerRequest> GetPagedRequests(string term, int[] categories, string imdbId = null)
{ {
var searchUrl = string.Format("{0}/api/v1/torrents", BaseUrl.TrimEnd('/')); var searchUrl = string.Format("{0}/api/v1/torrents", Settings.BaseUrl.TrimEnd('/'));
var parameters = new NameValueCollection(); var parameters = new NameValueCollection();
@@ -226,15 +225,13 @@ namespace NzbDrone.Core.Indexers.Definitions
public class DigitalCoreParser : IParseIndexerResponse public class DigitalCoreParser : IParseIndexerResponse
{ {
private readonly string _baseUrl;
private readonly DigitalCoreSettings _settings; private readonly DigitalCoreSettings _settings;
private readonly IndexerCapabilitiesCategories _categories; private readonly IndexerCapabilitiesCategories _categories;
public DigitalCoreParser(DigitalCoreSettings settings, IndexerCapabilitiesCategories categories, string baseUrl) public DigitalCoreParser(DigitalCoreSettings settings, IndexerCapabilitiesCategories categories)
{ {
_settings = settings; _settings = settings;
_categories = categories; _categories = categories;
_baseUrl = baseUrl;
} }
public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse) public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse)
@@ -270,8 +267,8 @@ namespace NzbDrone.Core.Indexers.Definitions
release.Files = row.numfiles; release.Files = row.numfiles;
release.Grabs = row.times_completed; release.Grabs = row.times_completed;
release.Guid = new Uri(_baseUrl + "torrent/" + row.id.ToString() + "/").ToString(); release.Guid = new Uri(_settings.BaseUrl + "torrent/" + row.id.ToString() + "/").ToString();
release.DownloadUrl = _baseUrl + "api/v1/torrents/download/" + row.id.ToString(); release.DownloadUrl = _settings.BaseUrl + "api/v1/torrents/download/" + row.id.ToString();
if (row.frileech == 1) if (row.frileech == 1)
{ {
@@ -317,7 +314,7 @@ namespace NzbDrone.Core.Indexers.Definitions
} }
} }
public class DigitalCoreSettings : IProviderConfig public class DigitalCoreSettings : IIndexerSettings
{ {
private static readonly DigitalCoreSettingsValidator Validator = new DigitalCoreSettingsValidator(); private static readonly DigitalCoreSettingsValidator Validator = new DigitalCoreSettingsValidator();
@@ -327,10 +324,13 @@ namespace NzbDrone.Core.Indexers.Definitions
Passphrase = ""; Passphrase = "";
} }
[FieldDefinition(1, Label = "UID", HelpText = "Uid from login cookie")] [FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2, Label = "UID", HelpText = "Uid from login cookie")]
public string UId { get; set; } public string UId { get; set; }
[FieldDefinition(2, Label = "Passphrase", HelpText = "Pass from login cookie")] [FieldDefinition(3, Label = "Passphrase", HelpText = "Pass from login cookie")]
public string Passphrase { get; set; } public string Passphrase { get; set; }
public NzbDroneValidationResult Validate() public NzbDroneValidationResult Validate()
@@ -10,7 +10,8 @@ namespace NzbDrone.Core.Indexers.Definitions
public class ExoticaZ : AvistazBase public class ExoticaZ : AvistazBase
{ {
public override string Name => "ExoticaZ"; public override string Name => "ExoticaZ";
public override string BaseUrl => "https://exoticaz.to/"; public override string[] IndexerUrls => new string[] { "https://exoticaz.to/" };
public override string Description => "ExoticaZ (YourExotic) is a Private Torrent Tracker for 3X";
public override IndexerPrivacy Privacy => IndexerPrivacy.Private; public override IndexerPrivacy Privacy => IndexerPrivacy.Private;
public ExoticaZ(IIndexerRepository indexerRepository, IHttpClient httpClient, IEventAggregator eventAggregator, IIndexerStatusService indexerStatusService, IConfigService configService, Logger logger) public ExoticaZ(IIndexerRepository indexerRepository, IHttpClient httpClient, IEventAggregator eventAggregator, IIndexerStatusService indexerStatusService, IConfigService configService, Logger logger)
@@ -26,7 +27,6 @@ namespace NzbDrone.Core.Indexers.Definitions
HttpClient = _httpClient, HttpClient = _httpClient,
Logger = _logger, Logger = _logger,
Capabilities = Capabilities, Capabilities = Capabilities,
BaseUrl = BaseUrl
}; };
} }
@@ -9,7 +9,8 @@ namespace NzbDrone.Core.Indexers.FileList
public class FileList : TorrentIndexerBase<FileListSettings> public class FileList : TorrentIndexerBase<FileListSettings>
{ {
public override string Name => "FileList.io"; public override string Name => "FileList.io";
public override string BaseUrl => "https://filelist.io"; public override string[] IndexerUrls => new string[] { "https://filelist.io" };
public override string Description => "";
public override DownloadProtocol Protocol => DownloadProtocol.Torrent; public override DownloadProtocol Protocol => DownloadProtocol.Torrent;
public override IndexerPrivacy Privacy => IndexerPrivacy.Private; public override IndexerPrivacy Privacy => IndexerPrivacy.Private;
public override bool SupportsRss => true; public override bool SupportsRss => true;
@@ -24,12 +25,12 @@ namespace NzbDrone.Core.Indexers.FileList
public override IIndexerRequestGenerator GetRequestGenerator() public override IIndexerRequestGenerator GetRequestGenerator()
{ {
return new FileListRequestGenerator() { Settings = Settings, BaseUrl = BaseUrl, Capabilities = Capabilities }; return new FileListRequestGenerator() { Settings = Settings, Capabilities = Capabilities };
} }
public override IParseIndexerResponse GetParser() public override IParseIndexerResponse GetParser()
{ {
return new FileListParser(Settings, BaseUrl, Capabilities.Categories); return new FileListParser(Settings, Capabilities.Categories);
} }
private IndexerCapabilities SetCapabilities() private IndexerCapabilities SetCapabilities()
@@ -10,14 +10,12 @@ namespace NzbDrone.Core.Indexers.FileList
{ {
public class FileListParser : IParseIndexerResponse public class FileListParser : IParseIndexerResponse
{ {
private readonly string _baseUrl;
private readonly FileListSettings _settings; private readonly FileListSettings _settings;
private readonly IndexerCapabilitiesCategories _categories; private readonly IndexerCapabilitiesCategories _categories;
public FileListParser(FileListSettings settings, string baseUrl, IndexerCapabilitiesCategories categories) public FileListParser(FileListSettings settings, IndexerCapabilitiesCategories categories)
{ {
_settings = settings; _settings = settings;
_baseUrl = baseUrl;
_categories = categories; _categories = categories;
} }
@@ -78,7 +76,7 @@ namespace NzbDrone.Core.Indexers.FileList
private string GetDownloadUrl(string torrentId) private string GetDownloadUrl(string torrentId)
{ {
var url = new HttpUri(_baseUrl) var url = new HttpUri(_settings.BaseUrl)
.CombinePath("/download.php") .CombinePath("/download.php")
.AddQueryParam("id", torrentId) .AddQueryParam("id", torrentId)
.AddQueryParam("passkey", _settings.Passkey); .AddQueryParam("passkey", _settings.Passkey);
@@ -88,7 +86,7 @@ namespace NzbDrone.Core.Indexers.FileList
private string GetInfoUrl(string torrentId) private string GetInfoUrl(string torrentId)
{ {
var url = new HttpUri(_baseUrl) var url = new HttpUri(_settings.BaseUrl)
.CombinePath("/details.php") .CombinePath("/details.php")
.AddQueryParam("id", torrentId); .AddQueryParam("id", torrentId);
@@ -1,6 +1,5 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using NzbDrone.Common.Extensions; using NzbDrone.Common.Extensions;
using NzbDrone.Common.Http; using NzbDrone.Common.Http;
using NzbDrone.Core.IndexerSearch.Definitions; using NzbDrone.Core.IndexerSearch.Definitions;
@@ -9,7 +8,6 @@ namespace NzbDrone.Core.Indexers.FileList
{ {
public class FileListRequestGenerator : IIndexerRequestGenerator public class FileListRequestGenerator : IIndexerRequestGenerator
{ {
public string BaseUrl { get; set; }
public FileListSettings Settings { get; set; } public FileListSettings Settings { get; set; }
public IndexerCapabilities Capabilities { get; set; } public IndexerCapabilities Capabilities { get; set; }
public Func<IDictionary<string, string>> GetCookies { get; set; } public Func<IDictionary<string, string>> GetCookies { get; set; }
@@ -109,7 +107,7 @@ namespace NzbDrone.Core.Indexers.FileList
{ {
var categoriesQuery = string.Join(",", Capabilities.Categories.MapTorznabCapsToTrackers(categories)); var categoriesQuery = string.Join(",", Capabilities.Categories.MapTorznabCapsToTrackers(categories));
var baseUrl = string.Format("{0}/api.php?action={1}&category={2}&username={3}&passkey={4}{5}", BaseUrl.TrimEnd('/'), searchType, categoriesQuery, Settings.Username.Trim(), Settings.Passkey.Trim(), parameters); var baseUrl = string.Format("{0}/api.php?action={1}&category={2}&username={3}&passkey={4}{5}", Settings.BaseUrl.TrimEnd('/'), searchType, categoriesQuery, Settings.Username.Trim(), Settings.Passkey.Trim(), parameters);
yield return new IndexerRequest(baseUrl, HttpAccept.Json); yield return new IndexerRequest(baseUrl, HttpAccept.Json);
} }
@@ -1,6 +1,5 @@
using FluentValidation; using FluentValidation;
using NzbDrone.Core.Annotations; using NzbDrone.Core.Annotations;
using NzbDrone.Core.ThingiProvider;
using NzbDrone.Core.Validation; using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.FileList namespace NzbDrone.Core.Indexers.FileList
@@ -14,18 +13,22 @@ namespace NzbDrone.Core.Indexers.FileList
} }
} }
public class FileListSettings : IProviderConfig public class FileListSettings : IIndexerSettings
{ {
private static readonly FileListSettingsValidator Validator = new FileListSettingsValidator(); private static readonly FileListSettingsValidator Validator = new FileListSettingsValidator();
public FileListSettings() public FileListSettings()
{ {
BaseUrl = "https://filelist.io";
} }
[FieldDefinition(0, Label = "Username", HelpText = "Site Username", Type = FieldType.Textbox, Privacy = PrivacyLevel.UserName)] [FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2, Label = "Username", Privacy = PrivacyLevel.UserName)]
public string Username { get; set; } public string Username { get; set; }
[FieldDefinition(1, Label = "Passkey", Privacy = PrivacyLevel.ApiKey)] [FieldDefinition(3, Label = "Passkey", Privacy = PrivacyLevel.ApiKey)]
public string Passkey { get; set; } public string Passkey { get; set; }
public NzbDroneValidationResult Validate() public NzbDroneValidationResult Validate()
@@ -10,8 +10,8 @@ namespace NzbDrone.Core.Indexers.Gazelle
public abstract class Gazelle : TorrentIndexerBase<GazelleSettings> public abstract class Gazelle : TorrentIndexerBase<GazelleSettings>
{ {
public override DownloadProtocol Protocol => DownloadProtocol.Torrent; public override DownloadProtocol Protocol => DownloadProtocol.Torrent;
public override string BaseUrl => ""; public override string[] IndexerUrls => new string[] { "" };
protected virtual string LoginUrl => BaseUrl + "login.php"; protected virtual string LoginUrl => Settings.BaseUrl + "login.php";
public override bool SupportsRss => true; public override bool SupportsRss => true;
public override bool SupportsSearch => true; public override bool SupportsSearch => true;
public override int PageSize => 50; public override int PageSize => 50;
@@ -33,14 +33,13 @@ namespace NzbDrone.Core.Indexers.Gazelle
Settings = Settings, Settings = Settings,
HttpClient = _httpClient, HttpClient = _httpClient,
Logger = _logger, Logger = _logger,
Capabilities = Capabilities, Capabilities = Capabilities
BaseUrl = BaseUrl
}; };
} }
public override IParseIndexerResponse GetParser() public override IParseIndexerResponse GetParser()
{ {
return new GazelleParser(Settings, Capabilities, BaseUrl); return new GazelleParser(Settings, Capabilities);
} }
protected virtual IndexerCapabilities SetCapabilities() protected virtual IndexerCapabilities SetCapabilities()
@@ -13,13 +13,11 @@ namespace NzbDrone.Core.Indexers.Gazelle
{ {
protected readonly GazelleSettings _settings; protected readonly GazelleSettings _settings;
protected readonly IndexerCapabilities _capabilities; protected readonly IndexerCapabilities _capabilities;
protected readonly string _baseUrl;
public GazelleParser(GazelleSettings settings, IndexerCapabilities capabilities, string baseUrl) public GazelleParser(GazelleSettings settings, IndexerCapabilities capabilities)
{ {
_settings = settings; _settings = settings;
_capabilities = capabilities; _capabilities = capabilities;
_baseUrl = baseUrl;
} }
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; } public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
@@ -140,7 +138,7 @@ namespace NzbDrone.Core.Indexers.Gazelle
protected virtual string GetDownloadUrl(int torrentId) protected virtual string GetDownloadUrl(int torrentId)
{ {
var url = new HttpUri(_baseUrl) var url = new HttpUri(_settings.BaseUrl)
.CombinePath("/torrents.php") .CombinePath("/torrents.php")
.AddQueryParam("action", "download") .AddQueryParam("action", "download")
.AddQueryParam("useToken", _settings.UseFreeleechToken ? "1" : "0") .AddQueryParam("useToken", _settings.UseFreeleechToken ? "1" : "0")
@@ -151,7 +149,7 @@ namespace NzbDrone.Core.Indexers.Gazelle
private string GetInfoUrl(string groupId, int torrentId) private string GetInfoUrl(string groupId, int torrentId)
{ {
var url = new HttpUri(_baseUrl) var url = new HttpUri(_settings.BaseUrl)
.CombinePath("/torrents.php") .CombinePath("/torrents.php")
.AddQueryParam("id", groupId) .AddQueryParam("id", groupId)
.AddQueryParam("torrentid", torrentId); .AddQueryParam("torrentid", torrentId);
@@ -9,14 +9,13 @@ namespace NzbDrone.Core.Indexers.Gazelle
public class GazelleRequestGenerator : IIndexerRequestGenerator public class GazelleRequestGenerator : IIndexerRequestGenerator
{ {
public GazelleSettings Settings { get; set; } public GazelleSettings Settings { get; set; }
public string BaseUrl { get; set; }
public IDictionary<string, string> AuthCookieCache { get; set; } public IDictionary<string, string> AuthCookieCache { get; set; }
public IHttpClient HttpClient { get; set; } public IHttpClient HttpClient { get; set; }
public IndexerCapabilities Capabilities { get; set; } public IndexerCapabilities Capabilities { get; set; }
public Logger Logger { get; set; } public Logger Logger { get; set; }
protected virtual string APIUrl => BaseUrl + "ajax.php"; protected virtual string APIUrl => Settings.BaseUrl + "ajax.php";
protected virtual bool ImdbInTags => false; protected virtual bool ImdbInTags => false;
public Func<IDictionary<string, string>> GetCookies { get; set; } public Func<IDictionary<string, string>> GetCookies { get; set; }
@@ -1,6 +1,5 @@
using FluentValidation; using FluentValidation;
using NzbDrone.Core.Annotations; using NzbDrone.Core.Annotations;
using NzbDrone.Core.ThingiProvider;
using NzbDrone.Core.Validation; using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.Gazelle namespace NzbDrone.Core.Indexers.Gazelle
@@ -14,7 +13,7 @@ namespace NzbDrone.Core.Indexers.Gazelle
} }
} }
public class GazelleSettings : IProviderConfig public class GazelleSettings : IIndexerSettings
{ {
private static readonly GazelleSettingsValidator Validator = new GazelleSettingsValidator(); private static readonly GazelleSettingsValidator Validator = new GazelleSettingsValidator();
@@ -25,13 +24,16 @@ namespace NzbDrone.Core.Indexers.Gazelle
public string AuthKey; public string AuthKey;
public string PassKey; public string PassKey;
[FieldDefinition(1, Label = "Username", HelpText = "Site Username", Type = FieldType.Textbox, Privacy = PrivacyLevel.UserName)] [FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2, Label = "Username", HelpText = "Username", Privacy = PrivacyLevel.UserName)]
public string Username { get; set; } public string Username { get; set; }
[FieldDefinition(2, Label = "Password", HelpText = "Site Password", Type = FieldType.Password, Privacy = PrivacyLevel.Password)] [FieldDefinition(3, Label = "Password", Type = FieldType.Password, HelpText = "Password", Privacy = PrivacyLevel.Password)]
public string Password { get; set; } public string Password { get; set; }
[FieldDefinition(3, Type = FieldType.Checkbox, Label = "Use Freeleech Token", HelpText = "Use Freeleech Token")] [FieldDefinition(4, Type = FieldType.Checkbox, Label = "Use Freeleech Token", HelpText = "Use Freeleech Token")]
public bool UseFreeleechToken { get; set; } public bool UseFreeleechToken { get; set; }
public NzbDroneValidationResult Validate() public NzbDroneValidationResult Validate()
@@ -2,6 +2,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Specialized; using System.Collections.Specialized;
using System.Globalization; using System.Globalization;
using System.Linq;
using System.Text; using System.Text;
using AngleSharp.Html.Parser; using AngleSharp.Html.Parser;
using FluentValidation; using FluentValidation;
@@ -21,7 +22,7 @@ namespace NzbDrone.Core.Indexers.Definitions
public class GazelleGames : TorrentIndexerBase<GazelleGamesSettings> public class GazelleGames : TorrentIndexerBase<GazelleGamesSettings>
{ {
public override string Name => "GazelleGames"; public override string Name => "GazelleGames";
public override string BaseUrl => "https://gazellegames.net/"; public override string[] IndexerUrls => new string[] { "https://gazellegames.net/" };
public override string Description => "A gaming tracker."; public override string Description => "A gaming tracker.";
public override string Language => "en-us"; public override string Language => "en-us";
public override Encoding Encoding => Encoding.UTF8; public override Encoding Encoding => Encoding.UTF8;
@@ -36,12 +37,12 @@ namespace NzbDrone.Core.Indexers.Definitions
public override IIndexerRequestGenerator GetRequestGenerator() public override IIndexerRequestGenerator GetRequestGenerator()
{ {
return new GazelleGamesRequestGenerator() { Settings = Settings, Capabilities = Capabilities, BaseUrl = BaseUrl }; return new GazelleGamesRequestGenerator() { Settings = Settings, Capabilities = Capabilities };
} }
public override IParseIndexerResponse GetParser() public override IParseIndexerResponse GetParser()
{ {
return new GazelleGamesParser(Settings, Capabilities.Categories, BaseUrl); return new GazelleGamesParser(Settings, Capabilities.Categories);
} }
protected override IDictionary<string, string> GetCookies() protected override IDictionary<string, string> GetCookies()
@@ -188,7 +189,6 @@ namespace NzbDrone.Core.Indexers.Definitions
{ {
public GazelleGamesSettings Settings { get; set; } public GazelleGamesSettings Settings { get; set; }
public IndexerCapabilities Capabilities { get; set; } public IndexerCapabilities Capabilities { get; set; }
public string BaseUrl { get; set; }
public GazelleGamesRequestGenerator() public GazelleGamesRequestGenerator()
{ {
@@ -196,7 +196,7 @@ namespace NzbDrone.Core.Indexers.Definitions
private IEnumerable<IndexerRequest> GetPagedRequests(string term, int[] categories) private IEnumerable<IndexerRequest> GetPagedRequests(string term, int[] categories)
{ {
var searchUrl = string.Format("{0}/torrents.php", BaseUrl.TrimEnd('/')); var searchUrl = string.Format("{0}/torrents.php", Settings.BaseUrl.TrimEnd('/'));
var searchString = term; var searchString = term;
@@ -278,13 +278,11 @@ namespace NzbDrone.Core.Indexers.Definitions
{ {
private readonly GazelleGamesSettings _settings; private readonly GazelleGamesSettings _settings;
private readonly IndexerCapabilitiesCategories _categories; private readonly IndexerCapabilitiesCategories _categories;
private readonly string _baseUrl;
public GazelleGamesParser(GazelleGamesSettings settings, IndexerCapabilitiesCategories categories, string baseurl) public GazelleGamesParser(GazelleGamesSettings settings, IndexerCapabilitiesCategories categories)
{ {
_settings = settings; _settings = settings;
_categories = categories; _categories = categories;
_baseUrl = baseurl;
} }
public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse) public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse)
@@ -355,12 +353,12 @@ namespace NzbDrone.Core.Indexers.Definitions
var qFreeLeech = row.QuerySelector("strong.freeleech_label"); var qFreeLeech = row.QuerySelector("strong.freeleech_label");
var qNeutralLeech = row.QuerySelector("strong.neutralleech_label"); var qNeutralLeech = row.QuerySelector("strong.neutralleech_label");
var time = qTime.GetAttribute("title"); var time = qTime.GetAttribute("title");
var link = _baseUrl + qDLLink.GetAttribute("href"); var link = _settings.BaseUrl + qDLLink.GetAttribute("href");
var seeders = ParseUtil.CoerceInt(qSeeders.TextContent); var seeders = ParseUtil.CoerceInt(qSeeders.TextContent);
var publishDate = DateTime.SpecifyKind( var publishDate = DateTime.SpecifyKind(
DateTime.ParseExact(time, "MMM dd yyyy, HH:mm", CultureInfo.InvariantCulture), DateTime.ParseExact(time, "MMM dd yyyy, HH:mm", CultureInfo.InvariantCulture),
DateTimeKind.Unspecified).ToLocalTime(); DateTimeKind.Unspecified).ToLocalTime();
var details = _baseUrl + qDetailsLink.GetAttribute("href"); var details = _settings.BaseUrl + qDetailsLink.GetAttribute("href");
var grabs = ParseUtil.CoerceInt(qGrabs.TextContent); var grabs = ParseUtil.CoerceInt(qGrabs.TextContent);
var leechers = ParseUtil.CoerceInt(qLeechers.TextContent); var leechers = ParseUtil.CoerceInt(qLeechers.TextContent);
var size = ReleaseInfo.GetBytes(sizeString); var size = ReleaseInfo.GetBytes(sizeString);
@@ -402,7 +400,7 @@ namespace NzbDrone.Core.Indexers.Definitions
} }
} }
public class GazelleGamesSettings : IProviderConfig public class GazelleGamesSettings : IIndexerSettings
{ {
private static readonly GazelleGamesSettingsValidator Validator = new GazelleGamesSettingsValidator(); private static readonly GazelleGamesSettingsValidator Validator = new GazelleGamesSettingsValidator();
@@ -412,10 +410,13 @@ namespace NzbDrone.Core.Indexers.Definitions
SearchGroupNames = false; SearchGroupNames = false;
} }
[FieldDefinition(1, Label = "Cookie", HelpText = "Login cookie from website")] [FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2, Label = "Cookie", HelpText = "Login cookie from website")]
public string Cookie { get; set; } public string Cookie { get; set; }
[FieldDefinition(2, Label = "Search Group Names", Type = FieldType.Checkbox, HelpText = "Search Group Names Only")] [FieldDefinition(3, Label = "Search Group Names", Type = FieldType.Checkbox, HelpText = "Search Group Names Only")]
public bool SearchGroupNames { get; set; } public bool SearchGroupNames { get; set; }
public NzbDroneValidationResult Validate() public NzbDroneValidationResult Validate()
@@ -9,7 +9,8 @@ namespace NzbDrone.Core.Indexers.HDBits
public class HDBits : TorrentIndexerBase<HDBitsSettings> public class HDBits : TorrentIndexerBase<HDBitsSettings>
{ {
public override string Name => "HDBits"; public override string Name => "HDBits";
public override string BaseUrl => "https://hdbits.org"; public override string[] IndexerUrls => new string[] { "https://hdbits.org" };
public override string Description => "Best HD Tracker";
public override DownloadProtocol Protocol => DownloadProtocol.Torrent; public override DownloadProtocol Protocol => DownloadProtocol.Torrent;
public override IndexerPrivacy Privacy => IndexerPrivacy.Private; public override IndexerPrivacy Privacy => IndexerPrivacy.Private;
public override IndexerCapabilities Capabilities => SetCapabilities(); public override IndexerCapabilities Capabilities => SetCapabilities();
@@ -24,12 +25,12 @@ namespace NzbDrone.Core.Indexers.HDBits
public override IIndexerRequestGenerator GetRequestGenerator() public override IIndexerRequestGenerator GetRequestGenerator()
{ {
return new HDBitsRequestGenerator() { Settings = Settings, BaseUrl = BaseUrl, Capabilities = Capabilities }; return new HDBitsRequestGenerator() { Settings = Settings, Capabilities = Capabilities };
} }
public override IParseIndexerResponse GetParser() public override IParseIndexerResponse GetParser()
{ {
return new HDBitsParser(Settings, BaseUrl); return new HDBitsParser(Settings);
} }
private IndexerCapabilities SetCapabilities() private IndexerCapabilities SetCapabilities()
@@ -11,13 +11,11 @@ namespace NzbDrone.Core.Indexers.HDBits
{ {
public class HDBitsParser : IParseIndexerResponse public class HDBitsParser : IParseIndexerResponse
{ {
private readonly string _baseUrl;
private readonly HDBitsSettings _settings; private readonly HDBitsSettings _settings;
public HDBitsParser(HDBitsSettings settings, string baseUrl) public HDBitsParser(HDBitsSettings settings)
{ {
_settings = settings; _settings = settings;
_baseUrl = baseUrl;
} }
public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse) public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse)
@@ -91,7 +89,7 @@ namespace NzbDrone.Core.Indexers.HDBits
private string GetDownloadUrl(string torrentId) private string GetDownloadUrl(string torrentId)
{ {
var url = new HttpUri(_baseUrl) var url = new HttpUri(_settings.BaseUrl)
.CombinePath("/download.php") .CombinePath("/download.php")
.AddQueryParam("id", torrentId) .AddQueryParam("id", torrentId)
.AddQueryParam("passkey", _settings.ApiKey); .AddQueryParam("passkey", _settings.ApiKey);
@@ -101,7 +99,7 @@ namespace NzbDrone.Core.Indexers.HDBits
private string GetInfoUrl(string torrentId) private string GetInfoUrl(string torrentId)
{ {
var url = new HttpUri(_baseUrl) var url = new HttpUri(_settings.BaseUrl)
.CombinePath("/details.php") .CombinePath("/details.php")
.AddQueryParam("id", torrentId); .AddQueryParam("id", torrentId);
@@ -12,7 +12,6 @@ namespace NzbDrone.Core.Indexers.HDBits
{ {
public IndexerCapabilities Capabilities { get; set; } public IndexerCapabilities Capabilities { get; set; }
public HDBitsSettings Settings { get; set; } public HDBitsSettings Settings { get; set; }
public string BaseUrl { get; set; }
public virtual IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria) public virtual IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
{ {
@@ -50,7 +49,7 @@ namespace NzbDrone.Core.Indexers.HDBits
private IEnumerable<IndexerRequest> GetRequest(TorrentQuery query) private IEnumerable<IndexerRequest> GetRequest(TorrentQuery query)
{ {
var request = new HttpRequestBuilder(BaseUrl) var request = new HttpRequestBuilder(Settings.BaseUrl)
.Resource("/api/torrents") .Resource("/api/torrents")
.Build(); .Build();
@@ -1,7 +1,6 @@
using System.Collections.Generic; using System.Collections.Generic;
using FluentValidation; using FluentValidation;
using NzbDrone.Core.Annotations; using NzbDrone.Core.Annotations;
using NzbDrone.Core.ThingiProvider;
using NzbDrone.Core.Validation; using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.HDBits namespace NzbDrone.Core.Indexers.HDBits
@@ -14,7 +13,7 @@ namespace NzbDrone.Core.Indexers.HDBits
} }
} }
public class HDBitsSettings : IProviderConfig public class HDBitsSettings : IIndexerSettings
{ {
private static readonly HDBitsSettingsValidator Validator = new HDBitsSettingsValidator(); private static readonly HDBitsSettingsValidator Validator = new HDBitsSettingsValidator();
@@ -24,16 +23,19 @@ namespace NzbDrone.Core.Indexers.HDBits
Mediums = System.Array.Empty<int>(); Mediums = System.Array.Empty<int>();
} }
[FieldDefinition(0, Label = "Username", HelpText = "Site Username", Type = FieldType.Textbox, Privacy = PrivacyLevel.UserName)] [FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2, Label = "Username", Privacy = PrivacyLevel.UserName)]
public string Username { get; set; } public string Username { get; set; }
[FieldDefinition(2, Label = "API Key", Privacy = PrivacyLevel.ApiKey)] [FieldDefinition(3, Label = "API Key", Privacy = PrivacyLevel.ApiKey)]
public string ApiKey { get; set; } public string ApiKey { get; set; }
[FieldDefinition(5, Label = "Codecs", Type = FieldType.TagSelect, SelectOptions = typeof(HdBitsCodec), Advanced = true, HelpText = "Options: h264, Mpeg2, VC1, Xvid. If unspecified, all options are used.")] [FieldDefinition(4, Label = "Codecs", Type = FieldType.TagSelect, SelectOptions = typeof(HdBitsCodec), Advanced = true, HelpText = "Options: h264, Mpeg2, VC1, Xvid. If unspecified, all options are used.")]
public IEnumerable<int> Codecs { get; set; } public IEnumerable<int> Codecs { get; set; }
[FieldDefinition(6, Label = "Mediums", Type = FieldType.TagSelect, SelectOptions = typeof(HdBitsMedium), Advanced = true, HelpText = "Options: BluRay, Encode, Capture, Remux, WebDL. If unspecified, all options are used.")] [FieldDefinition(5, Label = "Mediums", Type = FieldType.TagSelect, SelectOptions = typeof(HdBitsMedium), Advanced = true, HelpText = "Options: BluRay, Encode, Capture, Remux, WebDL. If unspecified, all options are used.")]
public IEnumerable<int> Mediums { get; set; } public IEnumerable<int> Mediums { get; set; }
public NzbDroneValidationResult Validate() public NzbDroneValidationResult Validate()
@@ -0,0 +1,349 @@
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using AngleSharp.Html.Parser;
using FluentValidation;
using NLog;
using NzbDrone.Common.Http;
using NzbDrone.Core.Annotations;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.Indexers.Exceptions;
using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Parser;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.Definitions
{
public class HDSpace : TorrentIndexerBase<HDSpaceSettings>
{
public override string Name => "HD-Space";
public override string[] IndexerUrls => new string[] { "https://hd-space.org/" };
private string LoginUrl => Settings.BaseUrl + "index.php?page=login";
public override string Description => "Sharing The Universe";
public override string Language => "en-us";
public override Encoding Encoding => Encoding.UTF8;
public override DownloadProtocol Protocol => DownloadProtocol.Torrent;
public override IndexerPrivacy Privacy => IndexerPrivacy.Private;
public override IndexerCapabilities Capabilities => SetCapabilities();
public HDSpace(IHttpClient httpClient, IEventAggregator eventAggregator, IIndexerStatusService indexerStatusService, IConfigService configService, Logger logger)
: base(httpClient, eventAggregator, indexerStatusService, configService, logger)
{
}
public override IIndexerRequestGenerator GetRequestGenerator()
{
return new HDSpaceRequestGenerator() { Settings = Settings, Capabilities = Capabilities };
}
public override IParseIndexerResponse GetParser()
{
return new HDSpaceParser(Settings, Capabilities.Categories);
}
protected override async Task DoLogin()
{
var loginPage = await _httpClient.ExecuteAsync(new HttpRequest(LoginUrl));
var requestBuilder = new HttpRequestBuilder(LoginUrl)
{
LogResponseContent = true,
AllowAutoRedirect = true
};
requestBuilder.Method = HttpMethod.POST;
requestBuilder.PostProcess += r => r.RequestTimeout = TimeSpan.FromSeconds(15);
var cookies = Cookies;
Cookies = null;
var authLoginRequest = requestBuilder
.AddFormParameter("uid", Settings.Username)
.AddFormParameter("pwd", Settings.Password)
.SetCookies(loginPage.GetCookies())
.SetHeader("Content-Type", "multipart/form-data")
.SetHeader("Referer", LoginUrl)
.Build();
var response = await ExecuteAuth(authLoginRequest);
if (CheckIfLoginNeeded(response))
{
var errorStr = "Login Failed: You have {0} remaining login attempts";
var remainingAttemptSpan = new Regex(string.Format(errorStr, "(.*?)"))
.Match(loginPage.Content).Groups[1].ToString();
var attempts = Regex.Replace(remainingAttemptSpan, "<.*?>", string.Empty);
var errorMessage = string.Format(errorStr, attempts);
throw new IndexerAuthException(errorMessage);
}
cookies = response.GetCookies();
UpdateCookies(cookies, DateTime.Now + TimeSpan.FromDays(30));
_logger.Debug("HDSpace authentication succeeded.");
}
protected override bool CheckIfLoginNeeded(HttpResponse httpResponse)
{
if (!httpResponse.Content.Contains("logout.php"))
{
return true;
}
return false;
}
private IndexerCapabilities SetCapabilities()
{
var caps = new IndexerCapabilities
{
TvSearchParams = new List<TvSearchParam>
{
TvSearchParam.Q, TvSearchParam.Season, TvSearchParam.Ep, TvSearchParam.ImdbId
},
MovieSearchParams = new List<MovieSearchParam>
{
MovieSearchParam.Q, MovieSearchParam.ImdbId
},
MusicSearchParams = new List<MusicSearchParam>
{
MusicSearchParam.Q
}
};
caps.Categories.AddCategoryMapping(15, NewznabStandardCategory.MoviesBluRay, "Movie / Blu-ray");
caps.Categories.AddCategoryMapping(19, NewznabStandardCategory.MoviesHD, "Movie / 1080p");
caps.Categories.AddCategoryMapping(18, NewznabStandardCategory.MoviesHD, "Movie / 720p");
caps.Categories.AddCategoryMapping(40, NewznabStandardCategory.MoviesHD, "Movie / Remux");
caps.Categories.AddCategoryMapping(16, NewznabStandardCategory.MoviesHD, "Movie / HD-DVD");
caps.Categories.AddCategoryMapping(41, NewznabStandardCategory.MoviesUHD, "Movie / 4K UHD");
caps.Categories.AddCategoryMapping(21, NewznabStandardCategory.TVHD, "TV Show / 720p HDTV");
caps.Categories.AddCategoryMapping(22, NewznabStandardCategory.TVHD, "TV Show / 1080p HDTV");
caps.Categories.AddCategoryMapping(24, NewznabStandardCategory.TVDocumentary, "Documentary / 720p");
caps.Categories.AddCategoryMapping(25, NewznabStandardCategory.TVDocumentary, "Documentary / 1080p");
caps.Categories.AddCategoryMapping(27, NewznabStandardCategory.TVAnime, "Animation / 720p");
caps.Categories.AddCategoryMapping(28, NewznabStandardCategory.TVAnime, "Animation / 1080p");
caps.Categories.AddCategoryMapping(30, NewznabStandardCategory.AudioLossless, "Music / HQ Audio");
caps.Categories.AddCategoryMapping(31, NewznabStandardCategory.AudioVideo, "Music / Videos");
caps.Categories.AddCategoryMapping(33, NewznabStandardCategory.XXX, "XXX / 720p");
caps.Categories.AddCategoryMapping(34, NewznabStandardCategory.XXX, "XXX / 1080p");
caps.Categories.AddCategoryMapping(36, NewznabStandardCategory.MoviesOther, "Trailers");
caps.Categories.AddCategoryMapping(37, NewznabStandardCategory.PC, "Software");
caps.Categories.AddCategoryMapping(38, NewznabStandardCategory.Other, "Others");
return caps;
}
}
public class HDSpaceRequestGenerator : IIndexerRequestGenerator
{
public HDSpaceSettings Settings { get; set; }
public IndexerCapabilities Capabilities { get; set; }
public HDSpaceRequestGenerator()
{
}
private IEnumerable<IndexerRequest> GetPagedRequests(string term, int[] categories, string imdb = null)
{
var searchUrl = string.Format("{0}/index.php?page=torrents&", Settings.BaseUrl.TrimEnd('/'));
var queryCollection = new NameValueCollection
{
{ "active", "0" },
{ "category", string.Join(";", Capabilities.Categories.MapTorznabCapsToTrackers(categories)) }
};
if (imdb != null)
{
queryCollection.Add("options", "2");
queryCollection.Add("search", imdb);
}
else
{
queryCollection.Add("options", "0");
queryCollection.Add("search", term);
}
searchUrl += queryCollection.GetQueryString();
var request = new IndexerRequest(searchUrl, HttpAccept.Html);
yield return request;
}
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories, searchCriteria.ImdbId));
return pageableRequests;
}
public IndexerPageableRequestChain GetSearchRequests(MusicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories));
return pageableRequests;
}
public IndexerPageableRequestChain GetSearchRequests(TvSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedTvSearchString), searchCriteria.Categories, searchCriteria.ImdbId));
return pageableRequests;
}
public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
}
public IndexerPageableRequestChain GetSearchRequests(BasicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}", searchCriteria.SanitizedSearchTerm), searchCriteria.Categories));
return pageableRequests;
}
public Func<IDictionary<string, string>> GetCookies { get; set; }
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
}
public class HDSpaceParser : IParseIndexerResponse
{
private readonly HDSpaceSettings _settings;
private readonly IndexerCapabilitiesCategories _categories;
public HDSpaceParser(HDSpaceSettings settings, IndexerCapabilitiesCategories categories)
{
_settings = settings;
_categories = categories;
}
public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse)
{
var torrentInfos = new List<ReleaseInfo>();
var resultParser = new HtmlParser();
var searchResultDocument = resultParser.ParseDocument(indexerResponse.Content);
var rows = searchResultDocument.QuerySelectorAll("table.lista > tbody > tr");
foreach (var row in rows)
{
// this tracker has horrible markup, find the result rows by looking for the style tag before each one
var prev = row.PreviousElementSibling;
if (prev == null || !string.Equals(prev.NodeName, "style", StringComparison.OrdinalIgnoreCase))
{
continue;
}
var release = new TorrentInfo();
release.MinimumRatio = 1;
release.MinimumSeedTime = 86400; // 24 hours
var qLink = row.Children[1].FirstElementChild;
release.Title = qLink.TextContent.Trim();
release.InfoUrl = _settings.BaseUrl + qLink.GetAttribute("href");
release.Guid = release.InfoUrl;
var imdbLink = row.Children[1].QuerySelector("a[href*=imdb]");
if (imdbLink != null)
{
release.ImdbId = ParseUtil.GetImdbID(imdbLink.GetAttribute("href").Split('/').Last()).GetValueOrDefault();
}
var qDownload = row.Children[3].FirstElementChild;
release.DownloadUrl = _settings.BaseUrl + qDownload.GetAttribute("href");
var dateStr = row.Children[4].TextContent.Trim();
//"July 11, 2015, 13:34:09", "Today|Yesterday at 20:04:23"
release.PublishDate = DateTimeUtil.FromUnknown(dateStr);
var sizeStr = row.Children[5].TextContent;
release.Size = ReleaseInfo.GetBytes(sizeStr);
release.Seeders = ParseUtil.CoerceInt(row.Children[7].TextContent);
release.Peers = ParseUtil.CoerceInt(row.Children[8].TextContent) + release.Seeders;
var grabs = row.QuerySelector("td:nth-child(10)").TextContent;
grabs = grabs.Replace("---", "0");
release.Grabs = ParseUtil.CoerceInt(grabs);
if (row.QuerySelector("img[title=\"FreeLeech\"]") != null)
{
release.DownloadVolumeFactor = 0;
}
else if (row.QuerySelector("img[src=\"images/sf.png\"]") != null)
{
release.DownloadVolumeFactor = 0;
}
else if (row.QuerySelector("img[title=\"Half FreeLeech\"]") != null)
{
release.DownloadVolumeFactor = 0.5;
}
else
{
release.DownloadVolumeFactor = 1;
}
release.UploadVolumeFactor = 1;
var qCat = row.QuerySelector("a[href^=\"index.php?page=torrents&category=\"]");
var cat = qCat.GetAttribute("href").Split('=')[2];
release.Categories = _categories.MapTrackerCatToNewznab(cat);
torrentInfos.Add(release);
}
return torrentInfos.ToArray();
}
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
}
public class HDSpaceSettingsValidator : AbstractValidator<HDSpaceSettings>
{
public HDSpaceSettingsValidator()
{
RuleFor(c => c.Username).NotEmpty();
RuleFor(c => c.Password).NotEmpty();
}
}
public class HDSpaceSettings : IIndexerSettings
{
private static readonly HDSpaceSettingsValidator Validator = new HDSpaceSettingsValidator();
public HDSpaceSettings()
{
Username = "";
Password = "";
}
[FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2, Label = "Username", Privacy = PrivacyLevel.UserName, HelpText = "Site Username")]
public string Username { get; set; }
[FieldDefinition(3, Label = "Password", Type = FieldType.Password, Privacy = PrivacyLevel.Password, HelpText = "Site Password")]
public string Password { get; set; }
public NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));
}
}
}
@@ -15,7 +15,6 @@ using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
using NzbDrone.Core.Parser.Model; using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.ThingiProvider;
using NzbDrone.Core.Validation; using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.Definitions namespace NzbDrone.Core.Indexers.Definitions
@@ -24,8 +23,9 @@ namespace NzbDrone.Core.Indexers.Definitions
{ {
public override string Name => "HD-Torrents"; public override string Name => "HD-Torrents";
public override string BaseUrl => "https://hdts.ru/"; public override string[] IndexerUrls => new string[] { "https://hdts.ru/" };
private string LoginUrl => BaseUrl + "login.php"; public override string Description => "HD-Torrents is a private torrent website with HD torrents and strict rules on their content.";
private string LoginUrl => Settings.BaseUrl + "login.php";
public override DownloadProtocol Protocol => DownloadProtocol.Torrent; public override DownloadProtocol Protocol => DownloadProtocol.Torrent;
public override IndexerPrivacy Privacy => IndexerPrivacy.Private; public override IndexerPrivacy Privacy => IndexerPrivacy.Private;
public override IndexerCapabilities Capabilities => SetCapabilities(); public override IndexerCapabilities Capabilities => SetCapabilities();
@@ -37,12 +37,12 @@ namespace NzbDrone.Core.Indexers.Definitions
public override IIndexerRequestGenerator GetRequestGenerator() public override IIndexerRequestGenerator GetRequestGenerator()
{ {
return new HDTorrentsRequestGenerator() { Settings = Settings, Capabilities = Capabilities, BaseUrl = BaseUrl }; return new HDTorrentsRequestGenerator() { Settings = Settings, Capabilities = Capabilities };
} }
public override IParseIndexerResponse GetParser() public override IParseIndexerResponse GetParser()
{ {
return new HDTorrentsParser(Settings, Capabilities.Categories, BaseUrl); return new HDTorrentsParser(Settings, Capabilities.Categories);
} }
protected override async Task DoLogin() protected override async Task DoLogin()
@@ -141,7 +141,6 @@ namespace NzbDrone.Core.Indexers.Definitions
{ {
public HDTorrentsSettings Settings { get; set; } public HDTorrentsSettings Settings { get; set; }
public IndexerCapabilities Capabilities { get; set; } public IndexerCapabilities Capabilities { get; set; }
public string BaseUrl { get; set; }
public HDTorrentsRequestGenerator() public HDTorrentsRequestGenerator()
{ {
@@ -149,7 +148,7 @@ namespace NzbDrone.Core.Indexers.Definitions
private IEnumerable<IndexerRequest> GetPagedRequests(string term, int[] categories, string imdbId = null) private IEnumerable<IndexerRequest> GetPagedRequests(string term, int[] categories, string imdbId = null)
{ {
var searchUrl = BaseUrl + "torrents.php?" + string.Join(string.Empty, Capabilities.Categories.MapTorznabCapsToTrackers(categories).Select(cat => $"category[]={cat}&")); var searchUrl = Settings.BaseUrl + "torrents.php?" + string.Join(string.Empty, Capabilities.Categories.MapTorznabCapsToTrackers(categories).Select(cat => $"category[]={cat}&"));
var queryCollection = new NameValueCollection var queryCollection = new NameValueCollection
{ {
@@ -219,7 +218,6 @@ namespace NzbDrone.Core.Indexers.Definitions
{ {
private readonly HDTorrentsSettings _settings; private readonly HDTorrentsSettings _settings;
private readonly IndexerCapabilitiesCategories _categories; private readonly IndexerCapabilitiesCategories _categories;
private readonly string _baseUrl;
private readonly Regex _posterRegex = new Regex(@"src=\\'./([^']+)\\'", RegexOptions.IgnoreCase); private readonly Regex _posterRegex = new Regex(@"src=\\'./([^']+)\\'", RegexOptions.IgnoreCase);
private readonly HashSet<string> _freeleechRanks = new HashSet<string>(StringComparer.OrdinalIgnoreCase) private readonly HashSet<string> _freeleechRanks = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
@@ -232,11 +230,10 @@ namespace NzbDrone.Core.Indexers.Definitions
"Owner" "Owner"
}; };
public HDTorrentsParser(HDTorrentsSettings settings, IndexerCapabilitiesCategories categories, string baseUrl) public HDTorrentsParser(HDTorrentsSettings settings, IndexerCapabilitiesCategories categories)
{ {
_settings = settings; _settings = settings;
_categories = categories; _categories = categories;
_baseUrl = baseUrl;
} }
public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse) public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse)
@@ -255,12 +252,12 @@ namespace NzbDrone.Core.Indexers.Definitions
{ {
var mainLink = row.Children[2].QuerySelector("a"); var mainLink = row.Children[2].QuerySelector("a");
var title = mainLink.TextContent; var title = mainLink.TextContent;
var details = new Uri(_baseUrl + mainLink.GetAttribute("href")); var details = new Uri(_settings.BaseUrl + mainLink.GetAttribute("href"));
var posterMatch = _posterRegex.Match(mainLink.GetAttribute("onmouseover")); var posterMatch = _posterRegex.Match(mainLink.GetAttribute("onmouseover"));
var poster = posterMatch.Success ? new Uri(_baseUrl + posterMatch.Groups[1].Value.Replace("\\", "/")) : null; var poster = posterMatch.Success ? new Uri(_settings.BaseUrl + posterMatch.Groups[1].Value.Replace("\\", "/")) : null;
var link = new Uri(_baseUrl + row.Children[4].FirstElementChild.GetAttribute("href")); var link = new Uri(_settings.BaseUrl + row.Children[4].FirstElementChild.GetAttribute("href"));
var description = row.Children[2].QuerySelector("span").TextContent; var description = row.Children[2].QuerySelector("span").TextContent;
var size = ReleaseInfo.GetBytes(row.Children[7].TextContent); var size = ReleaseInfo.GetBytes(row.Children[7].TextContent);
@@ -365,7 +362,7 @@ namespace NzbDrone.Core.Indexers.Definitions
} }
} }
public class HDTorrentsSettings : IProviderConfig public class HDTorrentsSettings : IIndexerSettings
{ {
private static readonly HDTorrentsSettingsValidator Validator = new HDTorrentsSettingsValidator(); private static readonly HDTorrentsSettingsValidator Validator = new HDTorrentsSettingsValidator();
@@ -375,10 +372,13 @@ namespace NzbDrone.Core.Indexers.Definitions
Password = ""; Password = "";
} }
[FieldDefinition(1, Label = "Username", HelpText = "Site Username", Type = FieldType.Textbox, Privacy = PrivacyLevel.UserName)] [FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2, Label = "Username", HelpText = "Site Username", Privacy = PrivacyLevel.UserName)]
public string Username { get; set; } public string Username { get; set; }
[FieldDefinition(2, Label = "Password", HelpText = "Site Password", Type = FieldType.Password, Privacy = PrivacyLevel.Password)] [FieldDefinition(3, Label = "Password", Type = FieldType.Password, HelpText = "Site Password", Privacy = PrivacyLevel.Password)]
public string Password { get; set; } public string Password { get; set; }
public NzbDroneValidationResult Validate() public NzbDroneValidationResult Validate()
@@ -17,7 +17,8 @@ namespace NzbDrone.Core.Indexers.Headphones
public override DownloadProtocol Protocol => DownloadProtocol.Usenet; public override DownloadProtocol Protocol => DownloadProtocol.Usenet;
public override IndexerPrivacy Privacy => IndexerPrivacy.Private; public override IndexerPrivacy Privacy => IndexerPrivacy.Private;
public override string BaseUrl => "https://indexer.codeshy.com"; public override string[] IndexerUrls => new string[] { "https://indexer.codeshy.com" };
public override string Description => "";
public override IndexerCapabilities Capabilities => SetCapabilities(); public override IndexerCapabilities Capabilities => SetCapabilities();
public override IIndexerRequestGenerator GetRequestGenerator() public override IIndexerRequestGenerator GetRequestGenerator()
@@ -26,8 +27,7 @@ namespace NzbDrone.Core.Indexers.Headphones
{ {
PageSize = PageSize, PageSize = PageSize,
Settings = Settings, Settings = Settings,
Capabilities = Capabilities, Capabilities = Capabilities
BaseUrl = BaseUrl
}; };
} }
@@ -15,7 +15,7 @@ namespace NzbDrone.Core.Indexers.Headphones
public int PageSize { get; set; } public int PageSize { get; set; }
public HeadphonesSettings Settings { get; set; } public HeadphonesSettings Settings { get; set; }
public IndexerCapabilities Capabilities { get; set; } public IndexerCapabilities Capabilities { get; set; }
public string BaseUrl { get; set; }
public Func<IDictionary<string, string>> GetCookies { get; set; } public Func<IDictionary<string, string>> GetCookies { get; set; }
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; } public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
@@ -106,7 +106,7 @@ namespace NzbDrone.Core.Indexers.Headphones
private IEnumerable<IndexerRequest> GetPagedRequests(SearchCriteriaBase searchCriteria, NameValueCollection parameters) private IEnumerable<IndexerRequest> GetPagedRequests(SearchCriteriaBase searchCriteria, NameValueCollection parameters)
{ {
var baseUrl = string.Format("{0}{1}?t={2}&extended=1", BaseUrl.TrimEnd('/'), Settings.ApiPath.TrimEnd('/'), searchCriteria.SearchType); var baseUrl = string.Format("{0}{1}?t={2}&extended=1", Settings.BaseUrl.TrimEnd('/'), Settings.ApiPath.TrimEnd('/'), searchCriteria.SearchType);
var categories = searchCriteria.Categories; var categories = searchCriteria.Categories;
if (categories != null && categories.Any()) if (categories != null && categories.Any())
@@ -1,6 +1,5 @@
using FluentValidation; using FluentValidation;
using NzbDrone.Core.Annotations; using NzbDrone.Core.Annotations;
using NzbDrone.Core.ThingiProvider;
using NzbDrone.Core.Validation; using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.Headphones namespace NzbDrone.Core.Indexers.Headphones
@@ -14,7 +13,7 @@ namespace NzbDrone.Core.Indexers.Headphones
} }
} }
public class HeadphonesSettings : IProviderConfig public class HeadphonesSettings : IIndexerSettings
{ {
private static readonly HeadphonesSettingsValidator Validator = new HeadphonesSettingsValidator(); private static readonly HeadphonesSettingsValidator Validator = new HeadphonesSettingsValidator();
@@ -28,10 +27,13 @@ namespace NzbDrone.Core.Indexers.Headphones
public string ApiKey { get; set; } public string ApiKey { get; set; }
[FieldDefinition(1, Label = "Username", HelpText = "Site Username", Type = FieldType.Textbox, Privacy = PrivacyLevel.UserName)] [FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2, Label = "Username", Privacy = PrivacyLevel.UserName)]
public string Username { get; set; } public string Username { get; set; }
[FieldDefinition(2, Label = "Password", HelpText = "Site Password", Type = FieldType.Password, Privacy = PrivacyLevel.Password)] [FieldDefinition(3, Label = "Password", Type = FieldType.Password, Privacy = PrivacyLevel.Password)]
public string Password { get; set; } public string Password { get; set; }
public virtual NzbDroneValidationResult Validate() public virtual NzbDroneValidationResult Validate()
@@ -13,7 +13,6 @@ using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
using NzbDrone.Core.Parser.Model; using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.ThingiProvider;
using NzbDrone.Core.Validation; using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.Definitions namespace NzbDrone.Core.Indexers.Definitions
@@ -22,7 +21,21 @@ namespace NzbDrone.Core.Indexers.Definitions
{ {
public override string Name => "IPTorrents"; public override string Name => "IPTorrents";
public override string BaseUrl => "https://iptorrents.com/"; public override string[] IndexerUrls => new string[]
{
"https://iptorrents.com/",
"https://iptorrents.me/",
"https://nemo.iptorrents.com/",
"https://ipt.getcrazy.me/",
"https://ipt.findnemo.net/",
"https://ipt.beelyrics.net/",
"https://ipt.venom.global/",
"https://ipt.workisboring.net/",
"https://ipt.lol/",
"https://ipt.cool/",
"https://ipt.world/"
};
public override string Description => "";
public override DownloadProtocol Protocol => DownloadProtocol.Torrent; public override DownloadProtocol Protocol => DownloadProtocol.Torrent;
public override IndexerPrivacy Privacy => IndexerPrivacy.Private; public override IndexerPrivacy Privacy => IndexerPrivacy.Private;
public override IndexerCapabilities Capabilities => SetCapabilities(); public override IndexerCapabilities Capabilities => SetCapabilities();
@@ -34,12 +47,12 @@ namespace NzbDrone.Core.Indexers.Definitions
public override IIndexerRequestGenerator GetRequestGenerator() public override IIndexerRequestGenerator GetRequestGenerator()
{ {
return new IPTorrentsRequestGenerator() { Settings = Settings, Capabilities = Capabilities, BaseUrl = BaseUrl }; return new IPTorrentsRequestGenerator() { Settings = Settings, Capabilities = Capabilities };
} }
public override IParseIndexerResponse GetParser() public override IParseIndexerResponse GetParser()
{ {
return new IPTorrentsParser(Settings, Capabilities.Categories, BaseUrl); return new IPTorrentsParser(Settings, Capabilities.Categories);
} }
protected override IDictionary<string, string> GetCookies() protected override IDictionary<string, string> GetCookies()
@@ -148,7 +161,6 @@ namespace NzbDrone.Core.Indexers.Definitions
{ {
public IPTorrentsSettings Settings { get; set; } public IPTorrentsSettings Settings { get; set; }
public IndexerCapabilities Capabilities { get; set; } public IndexerCapabilities Capabilities { get; set; }
public string BaseUrl { get; set; }
public IPTorrentsRequestGenerator() public IPTorrentsRequestGenerator()
{ {
@@ -156,7 +168,7 @@ namespace NzbDrone.Core.Indexers.Definitions
private IEnumerable<IndexerRequest> GetPagedRequests(string term, int[] categories, string imdbId = null) private IEnumerable<IndexerRequest> GetPagedRequests(string term, int[] categories, string imdbId = null)
{ {
var searchUrl = BaseUrl + "t"; var searchUrl = Settings.BaseUrl + "t";
var qc = new NameValueCollection(); var qc = new NameValueCollection();
@@ -169,6 +181,11 @@ namespace NzbDrone.Core.Indexers.Definitions
qc.Add("q", term); qc.Add("q", term);
} }
if (Settings.FreeLeechOnly)
{
qc.Add("free", "on");
}
foreach (var cat in Capabilities.Categories.MapTorznabCapsToTrackers(categories)) foreach (var cat in Capabilities.Categories.MapTorznabCapsToTrackers(categories))
{ {
qc.Add(cat, string.Empty); qc.Add(cat, string.Empty);
@@ -234,13 +251,11 @@ namespace NzbDrone.Core.Indexers.Definitions
{ {
private readonly IPTorrentsSettings _settings; private readonly IPTorrentsSettings _settings;
private readonly IndexerCapabilitiesCategories _categories; private readonly IndexerCapabilitiesCategories _categories;
private readonly string _baseUrl;
public IPTorrentsParser(IPTorrentsSettings settings, IndexerCapabilitiesCategories categories, string baseUrl) public IPTorrentsParser(IPTorrentsSettings settings, IndexerCapabilitiesCategories categories)
{ {
_settings = settings; _settings = settings;
_categories = categories; _categories = categories;
_baseUrl = baseUrl;
} }
public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse) public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse)
@@ -263,10 +278,10 @@ namespace NzbDrone.Core.Indexers.Definitions
// drop invalid char that seems to have cropped up in some titles. #6582 // drop invalid char that seems to have cropped up in some titles. #6582
var title = qTitleLink.TextContent.Trim().Replace("\u000f", ""); var title = qTitleLink.TextContent.Trim().Replace("\u000f", "");
var details = new Uri(_baseUrl + qTitleLink.GetAttribute("href").TrimStart('/')); var details = new Uri(_settings.BaseUrl + qTitleLink.GetAttribute("href").TrimStart('/'));
var qLink = row.QuerySelector("a[href^=\"/download.php/\"]"); var qLink = row.QuerySelector("a[href^=\"/download.php/\"]");
var link = new Uri(_baseUrl + qLink.GetAttribute("href").TrimStart('/')); var link = new Uri(_settings.BaseUrl + qLink.GetAttribute("href").TrimStart('/'));
var descrSplit = row.QuerySelector("div.sub").TextContent.Split('|'); var descrSplit = row.QuerySelector("div.sub").TextContent.Split('|');
var dateSplit = descrSplit.Last().Split(new[] { " by " }, StringSplitOptions.None); var dateSplit = descrSplit.Last().Split(new[] { " by " }, StringSplitOptions.None);
@@ -337,7 +352,7 @@ namespace NzbDrone.Core.Indexers.Definitions
} }
} }
public class IPTorrentsSettings : IProviderConfig public class IPTorrentsSettings : IIndexerSettings
{ {
private static readonly IPTorrentsSettingsValidator Validator = new IPTorrentsSettingsValidator(); private static readonly IPTorrentsSettingsValidator Validator = new IPTorrentsSettingsValidator();
@@ -346,11 +361,15 @@ namespace NzbDrone.Core.Indexers.Definitions
Cookie = ""; Cookie = "";
} }
[FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; } public string BaseUrl { get; set; }
[FieldDefinition(1, Label = "Cookie", HelpText = "Site Cookie")] [FieldDefinition(2, Label = "Cookie", HelpText = "Site Cookie")]
public string Cookie { get; set; } public string Cookie { get; set; }
[FieldDefinition(3, Label = "FreeLeech Only", Type = FieldType.Checkbox, Advanced = true, HelpText = "Search Freeleech torrents only")]
public bool FreeLeechOnly { get; set; }
public NzbDroneValidationResult Validate() public NzbDroneValidationResult Validate()
{ {
return new NzbDroneValidationResult(Validator.Validate(this)); return new NzbDroneValidationResult(Validator.Validate(this));
@@ -25,8 +25,9 @@ namespace NzbDrone.Core.Indexers.Definitions
{ {
public override string Name => "ImmortalSeed"; public override string Name => "ImmortalSeed";
public override string BaseUrl => "https://immortalseed.me/"; public override string[] IndexerUrls => new string[] { "https://immortalseed.me/" };
private string LoginUrl => BaseUrl + "takelogin.php"; public override string Description => "ImmortalSeed (iS) is a Private Torrent Tracker for MOVIES / TV / GENERAL";
private string LoginUrl => Settings.BaseUrl + "takelogin.php";
public override DownloadProtocol Protocol => DownloadProtocol.Torrent; public override DownloadProtocol Protocol => DownloadProtocol.Torrent;
public override IndexerPrivacy Privacy => IndexerPrivacy.Private; public override IndexerPrivacy Privacy => IndexerPrivacy.Private;
public override IndexerCapabilities Capabilities => SetCapabilities(); public override IndexerCapabilities Capabilities => SetCapabilities();
@@ -38,12 +39,12 @@ namespace NzbDrone.Core.Indexers.Definitions
public override IIndexerRequestGenerator GetRequestGenerator() public override IIndexerRequestGenerator GetRequestGenerator()
{ {
return new ImmortalSeedRequestGenerator() { Settings = Settings, Capabilities = Capabilities, BaseUrl = BaseUrl }; return new ImmortalSeedRequestGenerator() { Settings = Settings, Capabilities = Capabilities };
} }
public override IParseIndexerResponse GetParser() public override IParseIndexerResponse GetParser()
{ {
return new ImmortalSeedParser(Settings, Capabilities.Categories, BaseUrl); return new ImmortalSeedParser(Settings, Capabilities.Categories);
} }
protected override async Task DoLogin() protected override async Task DoLogin()
@@ -161,7 +162,6 @@ namespace NzbDrone.Core.Indexers.Definitions
{ {
public ImmortalSeedSettings Settings { get; set; } public ImmortalSeedSettings Settings { get; set; }
public IndexerCapabilities Capabilities { get; set; } public IndexerCapabilities Capabilities { get; set; }
public string BaseUrl { get; set; }
public ImmortalSeedRequestGenerator() public ImmortalSeedRequestGenerator()
{ {
@@ -169,7 +169,7 @@ namespace NzbDrone.Core.Indexers.Definitions
private IEnumerable<IndexerRequest> GetPagedRequests(string term, int[] categories, string imdbId = null) private IEnumerable<IndexerRequest> GetPagedRequests(string term, int[] categories, string imdbId = null)
{ {
var searchUrl = BaseUrl + "browse.php"; var searchUrl = Settings.BaseUrl + "browse.php";
//TODO - Actually map some categories here //TODO - Actually map some categories here
if (term.IsNotNullOrWhiteSpace()) if (term.IsNotNullOrWhiteSpace())
@@ -235,13 +235,11 @@ namespace NzbDrone.Core.Indexers.Definitions
{ {
private readonly ImmortalSeedSettings _settings; private readonly ImmortalSeedSettings _settings;
private readonly IndexerCapabilitiesCategories _categories; private readonly IndexerCapabilitiesCategories _categories;
private readonly string _baseUrl;
public ImmortalSeedParser(ImmortalSeedSettings settings, IndexerCapabilitiesCategories categories, string baseUrl) public ImmortalSeedParser(ImmortalSeedSettings settings, IndexerCapabilitiesCategories categories)
{ {
_settings = settings; _settings = settings;
_categories = categories; _categories = categories;
_baseUrl = baseUrl;
} }
public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse) public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse)
@@ -335,7 +333,7 @@ namespace NzbDrone.Core.Indexers.Definitions
} }
} }
public class ImmortalSeedSettings : IProviderConfig public class ImmortalSeedSettings : IIndexerSettings
{ {
private static readonly ImmortalSeedSettingsValidator Validator = new ImmortalSeedSettingsValidator(); private static readonly ImmortalSeedSettingsValidator Validator = new ImmortalSeedSettingsValidator();
@@ -345,10 +343,13 @@ namespace NzbDrone.Core.Indexers.Definitions
Password = ""; Password = "";
} }
[FieldDefinition(1, Label = "Username", HelpText = "Site Username", Type = FieldType.Textbox, Privacy = PrivacyLevel.UserName)] [FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2, Label = "Username", HelpText = "Site Username", Privacy = PrivacyLevel.UserName)]
public string Username { get; set; } public string Username { get; set; }
[FieldDefinition(2, Label = "Password", HelpText = "Site Password", Type = FieldType.Password, Privacy = PrivacyLevel.Password)] [FieldDefinition(3, Label = "Password", Type = FieldType.Password, HelpText = "Site Password", Privacy = PrivacyLevel.Password)]
public string Password { get; set; } public string Password { get; set; }
public NzbDroneValidationResult Validate() public NzbDroneValidationResult Validate()
@@ -11,7 +11,6 @@ using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
using NzbDrone.Core.Parser.Model; using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.ThingiProvider;
using NzbDrone.Core.Validation; using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.Definitions namespace NzbDrone.Core.Indexers.Definitions
@@ -20,7 +19,8 @@ namespace NzbDrone.Core.Indexers.Definitions
{ {
public override string Name => "Milkie"; public override string Name => "Milkie";
public override string BaseUrl => "https://milkie.cc/"; public override string[] IndexerUrls => new string[] { "https://milkie.cc/" };
public override string Description => "";
public override DownloadProtocol Protocol => DownloadProtocol.Torrent; public override DownloadProtocol Protocol => DownloadProtocol.Torrent;
public override IndexerPrivacy Privacy => IndexerPrivacy.Private; public override IndexerPrivacy Privacy => IndexerPrivacy.Private;
public override IndexerCapabilities Capabilities => SetCapabilities(); public override IndexerCapabilities Capabilities => SetCapabilities();
@@ -32,12 +32,12 @@ namespace NzbDrone.Core.Indexers.Definitions
public override IIndexerRequestGenerator GetRequestGenerator() public override IIndexerRequestGenerator GetRequestGenerator()
{ {
return new MilkieRequestGenerator() { Settings = Settings, Capabilities = Capabilities, BaseUrl = BaseUrl }; return new MilkieRequestGenerator() { Settings = Settings, Capabilities = Capabilities };
} }
public override IParseIndexerResponse GetParser() public override IParseIndexerResponse GetParser()
{ {
return new MilkieParser(Settings, Capabilities.Categories, BaseUrl); return new MilkieParser(Settings, Capabilities.Categories);
} }
private IndexerCapabilities SetCapabilities() private IndexerCapabilities SetCapabilities()
@@ -77,7 +77,6 @@ namespace NzbDrone.Core.Indexers.Definitions
{ {
public MilkieSettings Settings { get; set; } public MilkieSettings Settings { get; set; }
public IndexerCapabilities Capabilities { get; set; } public IndexerCapabilities Capabilities { get; set; }
public string BaseUrl { get; set; }
public MilkieRequestGenerator() public MilkieRequestGenerator()
{ {
@@ -85,7 +84,7 @@ namespace NzbDrone.Core.Indexers.Definitions
private IEnumerable<IndexerRequest> GetPagedRequests(string term, int[] categories, string imdbId = null) private IEnumerable<IndexerRequest> GetPagedRequests(string term, int[] categories, string imdbId = null)
{ {
var searchUrl = BaseUrl + "api/v1/torrents"; var searchUrl = Settings.BaseUrl + "api/v1/torrents";
var qc = new NameValueCollection var qc = new NameValueCollection
{ {
@@ -164,13 +163,11 @@ namespace NzbDrone.Core.Indexers.Definitions
{ {
private readonly MilkieSettings _settings; private readonly MilkieSettings _settings;
private readonly IndexerCapabilitiesCategories _categories; private readonly IndexerCapabilitiesCategories _categories;
private readonly string _baseUrl;
public MilkieParser(MilkieSettings settings, IndexerCapabilitiesCategories categories, string baseUrl) public MilkieParser(MilkieSettings settings, IndexerCapabilitiesCategories categories)
{ {
_settings = settings; _settings = settings;
_categories = categories; _categories = categories;
_baseUrl = baseUrl;
} }
public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse) public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse)
@@ -186,9 +183,9 @@ namespace NzbDrone.Core.Indexers.Definitions
foreach (var torrent in response.Torrents) foreach (var torrent in response.Torrents)
{ {
var torrentUrl = _baseUrl + "api/v1/torrents"; var torrentUrl = _settings.BaseUrl + "api/v1/torrents";
var link = $"{torrentUrl}/{torrent.Id}/torrent?{dlQueryParams.GetQueryString()}"; var link = $"{torrentUrl}/{torrent.Id}/torrent?{dlQueryParams.GetQueryString()}";
var details = $"{_baseUrl}browse/{torrent.Id}"; var details = $"{_settings.BaseUrl}browse/{torrent.Id}";
var publishDate = DateTimeUtil.FromUnknown(torrent.CreatedAt); var publishDate = DateTimeUtil.FromUnknown(torrent.CreatedAt);
var release = new TorrentInfo var release = new TorrentInfo
@@ -226,7 +223,7 @@ namespace NzbDrone.Core.Indexers.Definitions
} }
} }
public class MilkieSettings : IProviderConfig public class MilkieSettings : IIndexerSettings
{ {
private static readonly MilkieSettingsValidator Validator = new MilkieSettingsValidator(); private static readonly MilkieSettingsValidator Validator = new MilkieSettingsValidator();
@@ -235,9 +232,10 @@ namespace NzbDrone.Core.Indexers.Definitions
ApiKey = ""; ApiKey = "";
} }
[FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; } public string BaseUrl { get; set; }
[FieldDefinition(1, Label = "Apikey", HelpText = "Site ApiKey", Privacy = PrivacyLevel.ApiKey)] [FieldDefinition(2, Label = "Apikey", HelpText = "Site ApiKey", Privacy = PrivacyLevel.ApiKey)]
public string ApiKey { get; set; } public string ApiKey { get; set; }
public NzbDroneValidationResult Validate() public NzbDroneValidationResult Validate()
@@ -13,7 +13,6 @@ using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
using NzbDrone.Core.Parser.Model; using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.ThingiProvider;
using NzbDrone.Core.Validation; using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.Definitions namespace NzbDrone.Core.Indexers.Definitions
@@ -22,7 +21,8 @@ namespace NzbDrone.Core.Indexers.Definitions
{ {
public override string Name => "MyAnonamouse"; public override string Name => "MyAnonamouse";
public override string BaseUrl => "https://www.myanonamouse.net/"; public override string[] IndexerUrls => new string[] { "https://www.myanonamouse.net/" };
public override string Description => "";
public override DownloadProtocol Protocol => DownloadProtocol.Torrent; public override DownloadProtocol Protocol => DownloadProtocol.Torrent;
public override IndexerPrivacy Privacy => IndexerPrivacy.Private; public override IndexerPrivacy Privacy => IndexerPrivacy.Private;
public override IndexerCapabilities Capabilities => SetCapabilities(); public override IndexerCapabilities Capabilities => SetCapabilities();
@@ -34,12 +34,12 @@ namespace NzbDrone.Core.Indexers.Definitions
public override IIndexerRequestGenerator GetRequestGenerator() public override IIndexerRequestGenerator GetRequestGenerator()
{ {
return new MyAnonamouseRequestGenerator() { Settings = Settings, Capabilities = Capabilities, BaseUrl = BaseUrl }; return new MyAnonamouseRequestGenerator() { Settings = Settings, Capabilities = Capabilities };
} }
public override IParseIndexerResponse GetParser() public override IParseIndexerResponse GetParser()
{ {
return new MyAnonamouseParser(Settings, Capabilities.Categories, BaseUrl); return new MyAnonamouseParser(Settings, Capabilities.Categories);
} }
protected override IDictionary<string, string> GetCookies() protected override IDictionary<string, string> GetCookies()
@@ -160,7 +160,6 @@ namespace NzbDrone.Core.Indexers.Definitions
{ {
public MyAnonamouseSettings Settings { get; set; } public MyAnonamouseSettings Settings { get; set; }
public IndexerCapabilities Capabilities { get; set; } public IndexerCapabilities Capabilities { get; set; }
public string BaseUrl { get; set; }
public MyAnonamouseRequestGenerator() public MyAnonamouseRequestGenerator()
{ {
@@ -202,7 +201,7 @@ namespace NzbDrone.Core.Indexers.Definitions
qParams.Add("tor[cat][]", "0"); qParams.Add("tor[cat][]", "0");
} }
var urlSearch = BaseUrl + "tor/js/loadSearchJSONbasic.php"; var urlSearch = Settings.BaseUrl + "tor/js/loadSearchJSONbasic.php";
if (qParams.Count > 0) if (qParams.Count > 0)
{ {
@@ -261,13 +260,11 @@ namespace NzbDrone.Core.Indexers.Definitions
{ {
private readonly MyAnonamouseSettings _settings; private readonly MyAnonamouseSettings _settings;
private readonly IndexerCapabilitiesCategories _categories; private readonly IndexerCapabilitiesCategories _categories;
private readonly string _baseUrl;
public MyAnonamouseParser(MyAnonamouseSettings settings, IndexerCapabilitiesCategories categories, string baseUrl) public MyAnonamouseParser(MyAnonamouseSettings settings, IndexerCapabilitiesCategories categories)
{ {
_settings = settings; _settings = settings;
_categories = categories; _categories = categories;
_baseUrl = baseUrl;
} }
public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse) public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse)
@@ -331,8 +328,8 @@ namespace NzbDrone.Core.Indexers.Definitions
var category = item.Category; var category = item.Category;
release.Categories = _categories.MapTrackerCatToNewznab(category); release.Categories = _categories.MapTrackerCatToNewznab(category);
release.DownloadUrl = _baseUrl + "/tor/download.php?tid=" + id; release.DownloadUrl = _settings.BaseUrl + "/tor/download.php?tid=" + id;
release.InfoUrl = _baseUrl + "/t/" + id; release.InfoUrl = _settings.BaseUrl + "/t/" + id;
release.Guid = release.InfoUrl; release.Guid = release.InfoUrl;
var dateStr = item.Added; var dateStr = item.Added;
@@ -366,7 +363,7 @@ namespace NzbDrone.Core.Indexers.Definitions
} }
} }
public class MyAnonamouseSettings : IProviderConfig public class MyAnonamouseSettings : IIndexerSettings
{ {
private static readonly MyAnonamouseSettingsValidator Validator = new MyAnonamouseSettingsValidator(); private static readonly MyAnonamouseSettingsValidator Validator = new MyAnonamouseSettingsValidator();
@@ -375,10 +372,13 @@ namespace NzbDrone.Core.Indexers.Definitions
MamId = ""; MamId = "";
} }
[FieldDefinition(1, Label = "Mam Id", HelpText = "Mam Session Id (Created Under Profile -> Security)")] [FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2, Label = "Mam Id", HelpText = "Mam Session Id (Created Under Profile -> Security)")]
public string MamId { get; set; } public string MamId { get; set; }
[FieldDefinition(2, Type = FieldType.Checkbox, Label = "Exclude VIP", HelpText = "Exclude VIP Torrents from search results")] [FieldDefinition(3, Type = FieldType.Checkbox, Label = "Exclude VIP", HelpText = "Exclude VIP Torrents from search results")]
public bool ExcludeVip { get; set; } public bool ExcludeVip { get; set; }
public NzbDroneValidationResult Validate() public NzbDroneValidationResult Validate()
@@ -15,7 +15,6 @@ using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
using NzbDrone.Core.Parser.Model; using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.ThingiProvider;
using NzbDrone.Core.Validation; using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.Definitions namespace NzbDrone.Core.Indexers.Definitions
@@ -23,8 +22,8 @@ namespace NzbDrone.Core.Indexers.Definitions
public class Nebulance : TorrentIndexerBase<NebulanceSettings> public class Nebulance : TorrentIndexerBase<NebulanceSettings>
{ {
public override string Name => "Nebulance"; public override string Name => "Nebulance";
public override string BaseUrl => "https://nebulance.io/"; public override string[] IndexerUrls => new string[] { "https://nebulance.io/" };
private string LoginUrl => BaseUrl + "login.php"; private string LoginUrl => Settings.BaseUrl + "login.php";
public override string Description => "At Nebulance we will change the way you think about TV"; public override string Description => "At Nebulance we will change the way you think about TV";
public override string Language => "en-us"; public override string Language => "en-us";
public override Encoding Encoding => Encoding.UTF8; public override Encoding Encoding => Encoding.UTF8;
@@ -39,12 +38,12 @@ namespace NzbDrone.Core.Indexers.Definitions
public override IIndexerRequestGenerator GetRequestGenerator() public override IIndexerRequestGenerator GetRequestGenerator()
{ {
return new NebulanceRequestGenerator() { Settings = Settings, Capabilities = Capabilities, BaseUrl = BaseUrl }; return new NebulanceRequestGenerator() { Settings = Settings, Capabilities = Capabilities };
} }
public override IParseIndexerResponse GetParser() public override IParseIndexerResponse GetParser()
{ {
return new NebulanceParser(Settings, Capabilities.Categories, BaseUrl); return new NebulanceParser(Settings, Capabilities.Categories);
} }
protected override async Task DoLogin() protected override async Task DoLogin()
@@ -109,7 +108,6 @@ namespace NzbDrone.Core.Indexers.Definitions
{ {
public NebulanceSettings Settings { get; set; } public NebulanceSettings Settings { get; set; }
public IndexerCapabilities Capabilities { get; set; } public IndexerCapabilities Capabilities { get; set; }
public string BaseUrl { get; set; }
public NebulanceRequestGenerator() public NebulanceRequestGenerator()
{ {
@@ -117,7 +115,7 @@ namespace NzbDrone.Core.Indexers.Definitions
private IEnumerable<IndexerRequest> GetPagedRequests(string term, int[] categories) private IEnumerable<IndexerRequest> GetPagedRequests(string term, int[] categories)
{ {
var searchUrl = string.Format("{0}/torrents.php", BaseUrl.TrimEnd('/')); var searchUrl = string.Format("{0}/torrents.php", Settings.BaseUrl.TrimEnd('/'));
var searchTerm = term; var searchTerm = term;
@@ -188,13 +186,11 @@ namespace NzbDrone.Core.Indexers.Definitions
{ {
private readonly NebulanceSettings _settings; private readonly NebulanceSettings _settings;
private readonly IndexerCapabilitiesCategories _categories; private readonly IndexerCapabilitiesCategories _categories;
private readonly string _baseUrl;
public NebulanceParser(NebulanceSettings settings, IndexerCapabilitiesCategories categories, string baseurl) public NebulanceParser(NebulanceSettings settings, IndexerCapabilitiesCategories categories)
{ {
_settings = settings; _settings = settings;
_categories = categories; _categories = categories;
_baseUrl = baseurl;
} }
public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse) public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse)
@@ -224,8 +220,8 @@ namespace NzbDrone.Core.Indexers.Definitions
var posterStr = row.QuerySelector("img")?.GetAttribute("src"); var posterStr = row.QuerySelector("img")?.GetAttribute("src");
Uri.TryCreate(posterStr, UriKind.Absolute, out var poster); Uri.TryCreate(posterStr, UriKind.Absolute, out var poster);
var details = _baseUrl + row.QuerySelector("a[data-src]").GetAttribute("href"); var details = _settings.BaseUrl + row.QuerySelector("a[data-src]").GetAttribute("href");
var link = _baseUrl + row.QuerySelector("a[href*='action=download']").GetAttribute("href"); var link = _settings.BaseUrl + row.QuerySelector("a[href*='action=download']").GetAttribute("href");
var qColSize = row.QuerySelector("td:nth-child(3)"); var qColSize = row.QuerySelector("td:nth-child(3)");
var size = ReleaseInfo.GetBytes(qColSize.Children[0].TextContent); var size = ReleaseInfo.GetBytes(qColSize.Children[0].TextContent);
@@ -278,7 +274,7 @@ namespace NzbDrone.Core.Indexers.Definitions
} }
} }
public class NebulanceSettings : IProviderConfig public class NebulanceSettings : IIndexerSettings
{ {
private static readonly NebulanceSettingsValidator Validator = new NebulanceSettingsValidator(); private static readonly NebulanceSettingsValidator Validator = new NebulanceSettingsValidator();
@@ -289,13 +285,16 @@ namespace NzbDrone.Core.Indexers.Definitions
TwoFactorAuth = ""; TwoFactorAuth = "";
} }
[FieldDefinition(1, Label = "Username", HelpText = "Site Username", Type = FieldType.Textbox, Privacy = PrivacyLevel.UserName)] [FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2, Label = "Username", HelpText = "Site Username", Privacy = PrivacyLevel.UserName)]
public string Username { get; set; } public string Username { get; set; }
[FieldDefinition(2, Label = "Password", HelpText = "Site Password", Type = FieldType.Password, Privacy = PrivacyLevel.Password)] [FieldDefinition(3, Label = "Password", Privacy = PrivacyLevel.Password, Type = FieldType.Password, HelpText = "Site Password")]
public string Password { get; set; } public string Password { get; set; }
[FieldDefinition(3, Label = "Two Factor Auth", HelpText = "Two-Factor Auth")] [FieldDefinition(4, Label = "Two Factor Auth", HelpText = "Two-Factor Auth")]
public string TwoFactorAuth { get; set; } public string TwoFactorAuth { get; set; }
public NzbDroneValidationResult Validate() public NzbDroneValidationResult Validate()
@@ -19,7 +19,8 @@ namespace NzbDrone.Core.Indexers.Newznab
private readonly INewznabCapabilitiesProvider _capabilitiesProvider; private readonly INewznabCapabilitiesProvider _capabilitiesProvider;
public override string Name => "Newznab"; public override string Name => "Newznab";
public override string BaseUrl => GetBaseUrlFromSettings(); public override string[] IndexerUrls => GetBaseUrlFromSettings();
public override string Description => "";
public override bool FollowRedirect => true; public override bool FollowRedirect => true;
public override bool SupportsRedirect => true; public override bool SupportsRedirect => true;
@@ -44,16 +45,16 @@ namespace NzbDrone.Core.Indexers.Newznab
return new NewznabRssParser(Settings); return new NewznabRssParser(Settings);
} }
public string GetBaseUrlFromSettings() public string[] GetBaseUrlFromSettings()
{ {
var baseUrl = ""; var baseUrl = "";
if (Definition == null || Settings == null || Settings.Categories == null) if (Definition == null || Settings == null || Settings.Categories == null)
{ {
return baseUrl; return new string[] { baseUrl };
} }
return Settings.BaseUrl; return new string[] { Settings.BaseUrl };
} }
public IndexerCapabilities GetCapabilitiesFromSettings() public IndexerCapabilities GetCapabilitiesFromSettings()
@@ -4,7 +4,6 @@ using System.Text.RegularExpressions;
using FluentValidation; using FluentValidation;
using NzbDrone.Common.Extensions; using NzbDrone.Common.Extensions;
using NzbDrone.Core.Annotations; using NzbDrone.Core.Annotations;
using NzbDrone.Core.ThingiProvider;
using NzbDrone.Core.Validation; using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.Newznab namespace NzbDrone.Core.Indexers.Newznab
@@ -52,7 +51,7 @@ namespace NzbDrone.Core.Indexers.Newznab
} }
} }
public class NewznabSettings : IProviderConfig public class NewznabSettings : IIndexerSettings
{ {
private static readonly NewznabSettingsValidator Validator = new NewznabSettingsValidator(); private static readonly NewznabSettingsValidator Validator = new NewznabSettingsValidator();
@@ -9,7 +9,8 @@ namespace NzbDrone.Core.Indexers.Definitions
public class NotWhatCD : Gazelle.Gazelle public class NotWhatCD : Gazelle.Gazelle
{ {
public override string Name => "notwhat.cd"; public override string Name => "notwhat.cd";
public override string BaseUrl => "https://notwhat.cd/"; public override string[] IndexerUrls => new string[] { "https://notwhat.cd/" };
public override string Description => "";
public override IndexerPrivacy Privacy => IndexerPrivacy.Private; public override IndexerPrivacy Privacy => IndexerPrivacy.Private;
public NotWhatCD(IHttpClient httpClient, IEventAggregator eventAggregator, IIndexerStatusService indexerStatusService, IConfigService configService, Logger logger) public NotWhatCD(IHttpClient httpClient, IEventAggregator eventAggregator, IIndexerStatusService indexerStatusService, IConfigService configService, Logger logger)
@@ -9,7 +9,8 @@ namespace NzbDrone.Core.Indexers.Definitions
public class Orpheus : Gazelle.Gazelle public class Orpheus : Gazelle.Gazelle
{ {
public override string Name => "Orpheus"; public override string Name => "Orpheus";
public override string BaseUrl => "https://orpheus.network/"; public override string[] IndexerUrls => new string[] { "https://orpheus.network/" };
public override string Description => "";
public override IndexerPrivacy Privacy => IndexerPrivacy.Private; public override IndexerPrivacy Privacy => IndexerPrivacy.Private;
public Orpheus(IHttpClient httpClient, IEventAggregator eventAggregator, IIndexerStatusService indexerStatusService, IConfigService configService, Logger logger) public Orpheus(IHttpClient httpClient, IEventAggregator eventAggregator, IIndexerStatusService indexerStatusService, IConfigService configService, Logger logger)
@@ -10,7 +10,8 @@ namespace NzbDrone.Core.Indexers.PassThePopcorn
public class PassThePopcorn : TorrentIndexerBase<PassThePopcornSettings> public class PassThePopcorn : TorrentIndexerBase<PassThePopcornSettings>
{ {
public override string Name => "PassThePopcorn"; public override string Name => "PassThePopcorn";
public override string BaseUrl => "https://passthepopcorn.me"; public override string[] IndexerUrls => new string[] { "https://passthepopcorn.me" };
public override string Description => "";
public override DownloadProtocol Protocol => DownloadProtocol.Torrent; public override DownloadProtocol Protocol => DownloadProtocol.Torrent;
public override IndexerPrivacy Privacy => IndexerPrivacy.Private; public override IndexerPrivacy Privacy => IndexerPrivacy.Private;
public override bool SupportsRss => true; public override bool SupportsRss => true;
@@ -36,8 +37,7 @@ namespace NzbDrone.Core.Indexers.PassThePopcorn
{ {
Settings = Settings, Settings = Settings,
HttpClient = _httpClient, HttpClient = _httpClient,
Logger = _logger, Logger = _logger
BaseUrl = BaseUrl
}; };
} }
@@ -80,7 +80,7 @@ namespace NzbDrone.Core.Indexers.PassThePopcorn
public override IParseIndexerResponse GetParser() public override IParseIndexerResponse GetParser()
{ {
return new PassThePopcornParser(BaseUrl, Capabilities, _logger); return new PassThePopcornParser(Settings, Capabilities, _logger);
} }
} }
@@ -12,12 +12,12 @@ namespace NzbDrone.Core.Indexers.PassThePopcorn
{ {
public class PassThePopcornParser : IParseIndexerResponse public class PassThePopcornParser : IParseIndexerResponse
{ {
private readonly string _baseUrl;
private readonly IndexerCapabilities _capabilities; private readonly IndexerCapabilities _capabilities;
private readonly PassThePopcornSettings _settings;
private readonly Logger _logger; private readonly Logger _logger;
public PassThePopcornParser(string baseUrl, IndexerCapabilities capabilities, Logger logger) public PassThePopcornParser(PassThePopcornSettings settings, IndexerCapabilities capabilities, Logger logger)
{ {
_baseUrl = baseUrl; _settings = settings;
_capabilities = capabilities; _capabilities = capabilities;
_logger = logger; _logger = logger;
} }
@@ -133,7 +133,7 @@ namespace NzbDrone.Core.Indexers.PassThePopcorn
private string GetDownloadUrl(int torrentId, string authKey, string passKey) private string GetDownloadUrl(int torrentId, string authKey, string passKey)
{ {
var url = new HttpUri(_baseUrl) var url = new HttpUri(_settings.BaseUrl)
.CombinePath("/torrents.php") .CombinePath("/torrents.php")
.AddQueryParam("action", "download") .AddQueryParam("action", "download")
.AddQueryParam("id", torrentId) .AddQueryParam("id", torrentId)
@@ -145,7 +145,7 @@ namespace NzbDrone.Core.Indexers.PassThePopcorn
private string GetInfoUrl(string groupId, int torrentId) private string GetInfoUrl(string groupId, int torrentId)
{ {
var url = new HttpUri(_baseUrl) var url = new HttpUri(_settings.BaseUrl)
.CombinePath("/torrents.php") .CombinePath("/torrents.php")
.AddQueryParam("id", groupId) .AddQueryParam("id", groupId)
.AddQueryParam("torrentid", torrentId); .AddQueryParam("torrentid", torrentId);
@@ -9,7 +9,6 @@ namespace NzbDrone.Core.Indexers.PassThePopcorn
{ {
public class PassThePopcornRequestGenerator : IIndexerRequestGenerator public class PassThePopcornRequestGenerator : IIndexerRequestGenerator
{ {
public string BaseUrl { get; set; }
public PassThePopcornSettings Settings { get; set; } public PassThePopcornSettings Settings { get; set; }
public IDictionary<string, string> Cookies { get; set; } public IDictionary<string, string> Cookies { get; set; }
@@ -40,7 +39,7 @@ namespace NzbDrone.Core.Indexers.PassThePopcorn
{ {
var request = var request =
new IndexerRequest( new IndexerRequest(
$"{BaseUrl.Trim().TrimEnd('/')}/torrents.php?action=advanced&json=noredirect&searchstr={searchParameters}", $"{Settings.BaseUrl.Trim().TrimEnd('/')}/torrents.php?action=advanced&json=noredirect&searchstr={searchParameters}",
HttpAccept.Json); HttpAccept.Json);
request.HttpRequest.Headers["ApiUser"] = Settings.APIUser; request.HttpRequest.Headers["ApiUser"] = Settings.APIUser;
@@ -1,6 +1,5 @@
using FluentValidation; using FluentValidation;
using NzbDrone.Core.Annotations; using NzbDrone.Core.Annotations;
using NzbDrone.Core.ThingiProvider;
using NzbDrone.Core.Validation; using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.PassThePopcorn namespace NzbDrone.Core.Indexers.PassThePopcorn
@@ -14,7 +13,7 @@ namespace NzbDrone.Core.Indexers.PassThePopcorn
} }
} }
public class PassThePopcornSettings : IProviderConfig public class PassThePopcornSettings : IIndexerSettings
{ {
private static readonly PassThePopcornSettingsValidator Validator = new PassThePopcornSettingsValidator(); private static readonly PassThePopcornSettingsValidator Validator = new PassThePopcornSettingsValidator();
@@ -22,10 +21,13 @@ namespace NzbDrone.Core.Indexers.PassThePopcorn
{ {
} }
[FieldDefinition(0, Label = "APIUser", HelpText = "These settings are found in your PassThePopcorn security settings (Edit Profile > Security).", Privacy = PrivacyLevel.UserName)] [FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2, Label = "APIUser", HelpText = "These settings are found in your PassThePopcorn security settings (Edit Profile > Security).", Privacy = PrivacyLevel.UserName)]
public string APIUser { get; set; } public string APIUser { get; set; }
[FieldDefinition(1, Label = "APIKey", Type = FieldType.Password, Privacy = PrivacyLevel.Password)] [FieldDefinition(3, Label = "APIKey", Type = FieldType.Password, Privacy = PrivacyLevel.Password)]
public string APIKey { get; set; } public string APIKey { get; set; }
public NzbDroneValidationResult Validate() public NzbDroneValidationResult Validate()
@@ -16,7 +16,6 @@ using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
using NzbDrone.Core.Parser.Model; using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.ThingiProvider;
using NzbDrone.Core.Validation; using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.Definitions namespace NzbDrone.Core.Indexers.Definitions
@@ -24,9 +23,9 @@ namespace NzbDrone.Core.Indexers.Definitions
public class PreToMe : TorrentIndexerBase<PreToMeSettings> public class PreToMe : TorrentIndexerBase<PreToMeSettings>
{ {
public override string Name => "PreToMe"; public override string Name => "PreToMe";
public override string BaseUrl => "https://pretome.info/"; public override string[] IndexerUrls => new string[] { "https://pretome.info/" };
public override string Description => "BitTorrent site for High Quality, High Definition (HD) movies and TV Shows"; public override string Description => "BitTorrent site for High Quality, High Definition (HD) movies and TV Shows";
private string LoginUrl => BaseUrl + "takelogin.php"; private string LoginUrl => Settings.BaseUrl + "takelogin.php";
public override string Language => "en-us"; public override string Language => "en-us";
public override Encoding Encoding => Encoding.GetEncoding("iso-8859-1"); public override Encoding Encoding => Encoding.GetEncoding("iso-8859-1");
public override DownloadProtocol Protocol => DownloadProtocol.Torrent; public override DownloadProtocol Protocol => DownloadProtocol.Torrent;
@@ -40,12 +39,12 @@ namespace NzbDrone.Core.Indexers.Definitions
public override IIndexerRequestGenerator GetRequestGenerator() public override IIndexerRequestGenerator GetRequestGenerator()
{ {
return new PreToMeRequestGenerator() { Settings = Settings, Capabilities = Capabilities, BaseUrl = BaseUrl }; return new PreToMeRequestGenerator() { Settings = Settings, Capabilities = Capabilities };
} }
public override IParseIndexerResponse GetParser() public override IParseIndexerResponse GetParser()
{ {
return new PreToMeParser(Settings, Capabilities.Categories, BaseUrl); return new PreToMeParser(Settings, Capabilities.Categories);
} }
protected override async Task DoLogin() protected override async Task DoLogin()
@@ -58,7 +57,7 @@ namespace NzbDrone.Core.Indexers.Definitions
AllowAutoRedirect = true AllowAutoRedirect = true
}; };
var loginPage = await _httpClient.ExecuteAsync(new HttpRequest(BaseUrl + "login.php")); var loginPage = await _httpClient.ExecuteAsync(new HttpRequest(Settings.BaseUrl + "login.php"));
requestBuilder.Method = HttpMethod.POST; requestBuilder.Method = HttpMethod.POST;
requestBuilder.PostProcess += r => r.RequestTimeout = TimeSpan.FromSeconds(15); requestBuilder.PostProcess += r => r.RequestTimeout = TimeSpan.FromSeconds(15);
@@ -185,7 +184,6 @@ namespace NzbDrone.Core.Indexers.Definitions
{ {
public PreToMeSettings Settings { get; set; } public PreToMeSettings Settings { get; set; }
public IndexerCapabilities Capabilities { get; set; } public IndexerCapabilities Capabilities { get; set; }
public string BaseUrl { get; set; }
public PreToMeRequestGenerator() public PreToMeRequestGenerator()
{ {
@@ -193,7 +191,7 @@ namespace NzbDrone.Core.Indexers.Definitions
private IEnumerable<IndexerRequest> GetPagedRequests(string term, int[] categories, string imdbId = null) private IEnumerable<IndexerRequest> GetPagedRequests(string term, int[] categories, string imdbId = null)
{ {
var searchUrl = string.Format("{0}/browse.php", BaseUrl.TrimEnd('/')); var searchUrl = string.Format("{0}/browse.php", Settings.BaseUrl.TrimEnd('/'));
var qc = new List<KeyValuePair<string, string>> // NameValueCollection don't support cat[]=19&cat[]=6 var qc = new List<KeyValuePair<string, string>> // NameValueCollection don't support cat[]=19&cat[]=6
{ {
@@ -311,13 +309,11 @@ namespace NzbDrone.Core.Indexers.Definitions
{ {
private readonly PreToMeSettings _settings; private readonly PreToMeSettings _settings;
private readonly IndexerCapabilitiesCategories _categories; private readonly IndexerCapabilitiesCategories _categories;
private readonly string _baseUrl;
public PreToMeParser(PreToMeSettings settings, IndexerCapabilitiesCategories categories, string baseUrl) public PreToMeParser(PreToMeSettings settings, IndexerCapabilitiesCategories categories)
{ {
_settings = settings; _settings = settings;
_categories = categories; _categories = categories;
_baseUrl = baseUrl;
} }
public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse) public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse)
@@ -341,8 +337,8 @@ namespace NzbDrone.Core.Indexers.Definitions
//{ //{
// continue; // we have to skip bad titles due to tags + any word search // continue; // we have to skip bad titles due to tags + any word search
//} //}
var details = _baseUrl + qLink.GetAttribute("href"); var details = _settings.BaseUrl + qLink.GetAttribute("href");
var link = _baseUrl + row.Children[2].QuerySelector("a").GetAttribute("href"); var link = _settings.BaseUrl + row.Children[2].QuerySelector("a").GetAttribute("href");
var dateStr = Regex.Replace(row.Children[5].InnerHtml, @"\<br[\s]{0,1}[\/]{0,1}\>", " "); var dateStr = Regex.Replace(row.Children[5].InnerHtml, @"\<br[\s]{0,1}[\/]{0,1}\>", " ");
var publishDate = DateTimeUtil.FromTimeAgo(dateStr); var publishDate = DateTimeUtil.FromTimeAgo(dateStr);
var files = ParseUtil.CoerceInt(row.Children[3].TextContent); var files = ParseUtil.CoerceInt(row.Children[3].TextContent);
@@ -390,7 +386,7 @@ namespace NzbDrone.Core.Indexers.Definitions
} }
} }
public class PreToMeSettings : IProviderConfig public class PreToMeSettings : IIndexerSettings
{ {
private static readonly PreToMeSettingsValidator Validator = new PreToMeSettingsValidator(); private static readonly PreToMeSettingsValidator Validator = new PreToMeSettingsValidator();
@@ -401,13 +397,16 @@ namespace NzbDrone.Core.Indexers.Definitions
Password = ""; Password = "";
} }
[FieldDefinition(1, Label = "Pin", HelpText = "Site Pin")] [FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2, Label = "Pin", HelpText = "Site Pin")]
public string Pin { get; set; } public string Pin { get; set; }
[FieldDefinition(2, Label = "Username", HelpText = "Site Username", Type = FieldType.Textbox, Privacy = PrivacyLevel.UserName)] [FieldDefinition(3, Label = "Username", HelpText = "Site Username", Privacy = PrivacyLevel.UserName)]
public string Username { get; set; } public string Username { get; set; }
[FieldDefinition(3, Label = "Password", HelpText = "Site Password", Type = FieldType.Password, Privacy = PrivacyLevel.Password)] [FieldDefinition(4, Label = "Password", Privacy = PrivacyLevel.Password, Type = FieldType.Password, HelpText = "Site Password")]
public string Password { get; set; } public string Password { get; set; }
public NzbDroneValidationResult Validate() public NzbDroneValidationResult Validate()
@@ -10,7 +10,8 @@ namespace NzbDrone.Core.Indexers.Definitions
public class PrivateHD : Avistaz.AvistazBase public class PrivateHD : Avistaz.AvistazBase
{ {
public override string Name => "PrivateHD"; public override string Name => "PrivateHD";
public override string BaseUrl => "https://privatehd.to/"; public override string[] IndexerUrls => new string[] { "https://privatehd.to/" };
public override string Description => "";
public override IndexerPrivacy Privacy => IndexerPrivacy.Private; public override IndexerPrivacy Privacy => IndexerPrivacy.Private;
public PrivateHD(IIndexerRepository indexerRepository, IHttpClient httpClient, IEventAggregator eventAggregator, IIndexerStatusService indexerStatusService, IConfigService configService, Logger logger) public PrivateHD(IIndexerRepository indexerRepository, IHttpClient httpClient, IEventAggregator eventAggregator, IIndexerStatusService indexerStatusService, IConfigService configService, Logger logger)
@@ -25,8 +26,7 @@ namespace NzbDrone.Core.Indexers.Definitions
Settings = Settings, Settings = Settings,
HttpClient = _httpClient, HttpClient = _httpClient,
Logger = _logger, Logger = _logger,
Capabilities = Capabilities, Capabilities = Capabilities
BaseUrl = BaseUrl
}; };
} }
@@ -16,7 +16,8 @@ namespace NzbDrone.Core.Indexers.Rarbg
private readonly IRarbgTokenProvider _tokenProvider; private readonly IRarbgTokenProvider _tokenProvider;
public override string Name => "Rarbg"; public override string Name => "Rarbg";
public override string BaseUrl => "https://torrentapi.org"; public override string[] IndexerUrls => new string[] { "https://torrentapi.org" };
public override string Description => "RARBG is a Public torrent site for MOVIES / TV / GENERAL";
public override DownloadProtocol Protocol => DownloadProtocol.Torrent; public override DownloadProtocol Protocol => DownloadProtocol.Torrent;
@@ -34,7 +35,7 @@ namespace NzbDrone.Core.Indexers.Rarbg
public override IIndexerRequestGenerator GetRequestGenerator() public override IIndexerRequestGenerator GetRequestGenerator()
{ {
return new RarbgRequestGenerator(_tokenProvider) { Settings = Settings, Categories = Capabilities.Categories, BaseUrl = BaseUrl }; return new RarbgRequestGenerator(_tokenProvider) { Settings = Settings, Categories = Capabilities.Categories };
} }
public override IParseIndexerResponse GetParser() public override IParseIndexerResponse GetParser()
@@ -105,7 +106,7 @@ namespace NzbDrone.Core.Indexers.Rarbg
try try
{ {
var request = new HttpRequestBuilder(BaseUrl.Trim('/')) var request = new HttpRequestBuilder(Settings.BaseUrl.Trim('/'))
.Resource("/pubapi_v2.php?get_token=get_token") .Resource("/pubapi_v2.php?get_token=get_token")
.Accept(HttpAccept.Json) .Accept(HttpAccept.Json)
.Build(); .Build();
@@ -12,7 +12,6 @@ namespace NzbDrone.Core.Indexers.Rarbg
{ {
private readonly IRarbgTokenProvider _tokenProvider; private readonly IRarbgTokenProvider _tokenProvider;
public string BaseUrl { get; set; }
public RarbgSettings Settings { get; set; } public RarbgSettings Settings { get; set; }
public IndexerCapabilitiesCategories Categories { get; set; } public IndexerCapabilitiesCategories Categories { get; set; }
@@ -23,7 +22,7 @@ namespace NzbDrone.Core.Indexers.Rarbg
private IEnumerable<IndexerRequest> GetRequest(string term, int[] categories, string imdbId = null, int? tmdbId = null) private IEnumerable<IndexerRequest> GetRequest(string term, int[] categories, string imdbId = null, int? tmdbId = null)
{ {
var requestBuilder = new HttpRequestBuilder(BaseUrl) var requestBuilder = new HttpRequestBuilder(Settings.BaseUrl)
.Resource("/pubapi_v2.php") .Resource("/pubapi_v2.php")
.Accept(HttpAccept.Json); .Accept(HttpAccept.Json);
@@ -62,7 +61,7 @@ namespace NzbDrone.Core.Indexers.Rarbg
} }
requestBuilder.AddQueryParam("limit", "100"); requestBuilder.AddQueryParam("limit", "100");
requestBuilder.AddQueryParam("token", _tokenProvider.GetToken(Settings, BaseUrl)); requestBuilder.AddQueryParam("token", _tokenProvider.GetToken(Settings, Settings.BaseUrl));
requestBuilder.AddQueryParam("format", "json_extended"); requestBuilder.AddQueryParam("format", "json_extended");
requestBuilder.AddQueryParam("app_id", BuildInfo.AppName); requestBuilder.AddQueryParam("app_id", BuildInfo.AppName);
@@ -1,6 +1,5 @@
using FluentValidation; using FluentValidation;
using NzbDrone.Core.Annotations; using NzbDrone.Core.Annotations;
using NzbDrone.Core.ThingiProvider;
using NzbDrone.Core.Validation; using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.Rarbg namespace NzbDrone.Core.Indexers.Rarbg
@@ -12,7 +11,7 @@ namespace NzbDrone.Core.Indexers.Rarbg
} }
} }
public class RarbgSettings : IProviderConfig public class RarbgSettings : IIndexerSettings
{ {
private static readonly RarbgSettingsValidator Validator = new RarbgSettingsValidator(); private static readonly RarbgSettingsValidator Validator = new RarbgSettingsValidator();
@@ -21,10 +20,13 @@ namespace NzbDrone.Core.Indexers.Rarbg
RankedOnly = false; RankedOnly = false;
} }
[FieldDefinition(1, Type = FieldType.Checkbox, Label = "Ranked Only", HelpText = "Only include ranked results.")] [FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2, Type = FieldType.Checkbox, Label = "Ranked Only", HelpText = "Only include ranked results.")]
public bool RankedOnly { get; set; } public bool RankedOnly { get; set; }
[FieldDefinition(2, Type = FieldType.Captcha, Label = "CAPTCHA Token", HelpText = "CAPTCHA Clearance token used to handle CloudFlare Anti-DDOS measures on shared-ip VPNs.")] [FieldDefinition(3, Type = FieldType.Captcha, Label = "CAPTCHA Token", HelpText = "CAPTCHA Clearance token used to handle CloudFlare Anti-DDOS measures on shared-ip VPNs.")]
public string CaptchaToken { get; set; } public string CaptchaToken { get; set; }
public NzbDroneValidationResult Validate() public NzbDroneValidationResult Validate()
@@ -9,7 +9,8 @@ namespace NzbDrone.Core.Indexers.Definitions
public class Redacted : Gazelle.Gazelle public class Redacted : Gazelle.Gazelle
{ {
public override string Name => "Redacted"; public override string Name => "Redacted";
public override string BaseUrl => "https://redacted.ch/"; public override string[] IndexerUrls => new string[] { "https://redacted.ch/" };
public override string Description => "";
public override IndexerPrivacy Privacy => IndexerPrivacy.Private; public override IndexerPrivacy Privacy => IndexerPrivacy.Private;
public Redacted(IHttpClient httpClient, IEventAggregator eventAggregator, IIndexerStatusService indexerStatusService, IConfigService configService, Logger logger) public Redacted(IHttpClient httpClient, IEventAggregator eventAggregator, IIndexerStatusService indexerStatusService, IConfigService configService, Logger logger)
@@ -16,7 +16,6 @@ using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
using NzbDrone.Core.Parser.Model; using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.ThingiProvider;
using NzbDrone.Core.Validation; using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.Definitions namespace NzbDrone.Core.Indexers.Definitions
@@ -25,8 +24,9 @@ namespace NzbDrone.Core.Indexers.Definitions
{ {
public override string Name => "RevolutionTT"; public override string Name => "RevolutionTT";
public override string BaseUrl => "https://revolutiontt.me/"; public override string[] IndexerUrls => new string[] { "https://revolutiontt.me/" };
private string LoginUrl => BaseUrl + "takelogin.php"; public override string Description => "The Revolution has begun";
private string LoginUrl => Settings.BaseUrl + "takelogin.php";
public override DownloadProtocol Protocol => DownloadProtocol.Torrent; public override DownloadProtocol Protocol => DownloadProtocol.Torrent;
public override IndexerPrivacy Privacy => IndexerPrivacy.Private; public override IndexerPrivacy Privacy => IndexerPrivacy.Private;
public override IndexerCapabilities Capabilities => SetCapabilities(); public override IndexerCapabilities Capabilities => SetCapabilities();
@@ -38,12 +38,12 @@ namespace NzbDrone.Core.Indexers.Definitions
public override IIndexerRequestGenerator GetRequestGenerator() public override IIndexerRequestGenerator GetRequestGenerator()
{ {
return new RevolutionTTRequestGenerator() { Settings = Settings, Capabilities = Capabilities, BaseUrl = BaseUrl }; return new RevolutionTTRequestGenerator() { Settings = Settings, Capabilities = Capabilities };
} }
public override IParseIndexerResponse GetParser() public override IParseIndexerResponse GetParser()
{ {
return new RevolutionTTParser(Settings, Capabilities.Categories, BaseUrl); return new RevolutionTTParser(Settings, Capabilities.Categories);
} }
protected override async Task DoLogin() protected override async Task DoLogin()
@@ -56,7 +56,7 @@ namespace NzbDrone.Core.Indexers.Definitions
AllowAutoRedirect = true AllowAutoRedirect = true
}; };
var loginPage = await _httpClient.ExecuteAsync(new HttpRequest(BaseUrl + "login.php")); var loginPage = await _httpClient.ExecuteAsync(new HttpRequest(Settings.BaseUrl + "login.php"));
requestBuilder.Method = HttpMethod.POST; requestBuilder.Method = HttpMethod.POST;
requestBuilder.PostProcess += r => r.RequestTimeout = TimeSpan.FromSeconds(15); requestBuilder.PostProcess += r => r.RequestTimeout = TimeSpan.FromSeconds(15);
@@ -155,7 +155,6 @@ namespace NzbDrone.Core.Indexers.Definitions
{ {
public RevolutionTTSettings Settings { get; set; } public RevolutionTTSettings Settings { get; set; }
public IndexerCapabilities Capabilities { get; set; } public IndexerCapabilities Capabilities { get; set; }
public string BaseUrl { get; set; }
public RevolutionTTRequestGenerator() public RevolutionTTRequestGenerator()
{ {
@@ -189,7 +188,7 @@ namespace NzbDrone.Core.Indexers.Definitions
} }
} }
var searchUrl = BaseUrl + "browse.php?" + qc.GetQueryString(); var searchUrl = Settings.BaseUrl + "browse.php?" + qc.GetQueryString();
var request = new IndexerRequest(searchUrl, HttpAccept.Html); var request = new IndexerRequest(searchUrl, HttpAccept.Html);
@@ -249,13 +248,11 @@ namespace NzbDrone.Core.Indexers.Definitions
{ {
private readonly RevolutionTTSettings _settings; private readonly RevolutionTTSettings _settings;
private readonly IndexerCapabilitiesCategories _categories; private readonly IndexerCapabilitiesCategories _categories;
private readonly string _baseUrl;
public RevolutionTTParser(RevolutionTTSettings settings, IndexerCapabilitiesCategories categories, string baseUrl) public RevolutionTTParser(RevolutionTTSettings settings, IndexerCapabilitiesCategories categories)
{ {
_settings = settings; _settings = settings;
_categories = categories; _categories = categories;
_baseUrl = baseUrl;
} }
public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse) public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse)
@@ -269,7 +266,7 @@ namespace NzbDrone.Core.Indexers.Definitions
foreach (var row in rows.Skip(1)) foreach (var row in rows.Skip(1))
{ {
var qDetails = row.QuerySelector(".br_right > a"); var qDetails = row.QuerySelector(".br_right > a");
var details = _baseUrl + qDetails.GetAttribute("href"); var details = _settings.BaseUrl + qDetails.GetAttribute("href");
var title = qDetails.QuerySelector("b").TextContent; var title = qDetails.QuerySelector("b").TextContent;
var qLink = row.QuerySelector("td:nth-child(4) > a"); var qLink = row.QuerySelector("td:nth-child(4) > a");
@@ -278,7 +275,7 @@ namespace NzbDrone.Core.Indexers.Definitions
continue; // support/donation banner continue; // support/donation banner
} }
var link = _baseUrl + qLink.GetAttribute("href"); var link = _settings.BaseUrl + qLink.GetAttribute("href");
// dateString format "yyyy-MMM-dd hh:mm:ss" => eg "2015-04-25 23:38:12" // dateString format "yyyy-MMM-dd hh:mm:ss" => eg "2015-04-25 23:38:12"
var dateString = row.QuerySelector("td:nth-child(6) nobr").TextContent.Trim(); var dateString = row.QuerySelector("td:nth-child(6) nobr").TextContent.Trim();
@@ -333,7 +330,7 @@ namespace NzbDrone.Core.Indexers.Definitions
} }
} }
public class RevolutionTTSettings : IProviderConfig public class RevolutionTTSettings : IIndexerSettings
{ {
private static readonly RevolutionTTSettingsValidator Validator = new RevolutionTTSettingsValidator(); private static readonly RevolutionTTSettingsValidator Validator = new RevolutionTTSettingsValidator();
@@ -343,10 +340,13 @@ namespace NzbDrone.Core.Indexers.Definitions
Password = ""; Password = "";
} }
[FieldDefinition(1, Label = "Username", HelpText = "Site Username", Type = FieldType.Textbox, Privacy = PrivacyLevel.UserName)] [FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2, Label = "Username", HelpText = "Site Username", Privacy = PrivacyLevel.UserName)]
public string Username { get; set; } public string Username { get; set; }
[FieldDefinition(2, Label = "Password", HelpText = "Site Password", Type = FieldType.Password, Privacy = PrivacyLevel.Password)] [FieldDefinition(3, Label = "Password", Type = FieldType.Password, HelpText = "Site Password", Privacy = PrivacyLevel.Password)]
public string Password { get; set; } public string Password { get; set; }
public NzbDroneValidationResult Validate() public NzbDroneValidationResult Validate()
@@ -10,7 +10,7 @@ namespace NzbDrone.Core.Indexers.Definitions
public class ShareIsland : Unit3dBase public class ShareIsland : Unit3dBase
{ {
public override string Name => "ShareIsland"; public override string Name => "ShareIsland";
public override string BaseUrl => "https://shareisland.org/"; public override string[] IndexerUrls => new string[] { "https://shareisland.org/" };
public override string Description => "A general italian tracker"; public override string Description => "A general italian tracker";
public override string Language => "it-it"; public override string Language => "it-it";
public override IndexerPrivacy Privacy => IndexerPrivacy.Private; public override IndexerPrivacy Privacy => IndexerPrivacy.Private;
@@ -6,6 +6,7 @@ using System.Xml;
using FluentValidation; using FluentValidation;
using NLog; using NLog;
using NzbDrone.Common.Http; using NzbDrone.Common.Http;
using NzbDrone.Core.Annotations;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.IndexerSearch.Definitions; using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;
@@ -18,7 +19,7 @@ namespace NzbDrone.Core.Indexers.Definitions
public class ShowRSS : TorrentIndexerBase<ShowRSSSettings> public class ShowRSS : TorrentIndexerBase<ShowRSSSettings>
{ {
public override string Name => "ShowRSS"; public override string Name => "ShowRSS";
public override string BaseUrl => "https://showrss.info/"; public override string[] IndexerUrls => new string[] { "https://showrss.info/" };
public override string Language => "en-us"; public override string Language => "en-us";
public override string Description => "showRSS is a service that allows you to keep track of your favorite TV shows"; public override string Description => "showRSS is a service that allows you to keep track of your favorite TV shows";
public override Encoding Encoding => Encoding.UTF8; public override Encoding Encoding => Encoding.UTF8;
@@ -33,12 +34,12 @@ namespace NzbDrone.Core.Indexers.Definitions
public override IIndexerRequestGenerator GetRequestGenerator() public override IIndexerRequestGenerator GetRequestGenerator()
{ {
return new ShowRSSRequestGenerator() { Settings = Settings, Capabilities = Capabilities, BaseUrl = BaseUrl }; return new ShowRSSRequestGenerator() { Settings = Settings, Capabilities = Capabilities };
} }
public override IParseIndexerResponse GetParser() public override IParseIndexerResponse GetParser()
{ {
return new ShowRSSParser(BaseUrl); return new ShowRSSParser(Settings);
} }
private IndexerCapabilities SetCapabilities() private IndexerCapabilities SetCapabilities()
@@ -63,7 +64,6 @@ namespace NzbDrone.Core.Indexers.Definitions
{ {
public ShowRSSSettings Settings { get; set; } public ShowRSSSettings Settings { get; set; }
public IndexerCapabilities Capabilities { get; set; } public IndexerCapabilities Capabilities { get; set; }
public string BaseUrl { get; set; }
public ShowRSSRequestGenerator() public ShowRSSRequestGenerator()
{ {
@@ -71,7 +71,7 @@ namespace NzbDrone.Core.Indexers.Definitions
private IEnumerable<IndexerRequest> GetPagedRequests(string term, int[] categories) private IEnumerable<IndexerRequest> GetPagedRequests(string term, int[] categories)
{ {
var searchUrl = string.Format("{0}/other/all.rss", BaseUrl.TrimEnd('/')); var searchUrl = string.Format("{0}/other/all.rss", Settings.BaseUrl.TrimEnd('/'));
var request = new IndexerRequest(searchUrl, HttpAccept.Html); var request = new IndexerRequest(searchUrl, HttpAccept.Html);
@@ -123,12 +123,12 @@ namespace NzbDrone.Core.Indexers.Definitions
public class ShowRSSParser : IParseIndexerResponse public class ShowRSSParser : IParseIndexerResponse
{ {
private readonly string _baseUrl; private readonly ShowRSSSettings _settings;
private string BrowseUrl => _baseUrl + "browse/"; private string BrowseUrl => _settings.BaseUrl + "browse/";
public ShowRSSParser(string baseurl) public ShowRSSParser(ShowRSSSettings settings)
{ {
_baseUrl = baseurl; _settings = settings;
} }
public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse) public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse)
@@ -184,10 +184,13 @@ namespace NzbDrone.Core.Indexers.Definitions
{ {
} }
public class ShowRSSSettings : IProviderConfig public class ShowRSSSettings : IIndexerSettings
{ {
private static readonly ShowRSSSettingsValidator Validator = new ShowRSSSettingsValidator(); private static readonly ShowRSSSettingsValidator Validator = new ShowRSSSettingsValidator();
[FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
public NzbDroneValidationResult Validate() public NzbDroneValidationResult Validate()
{ {
return new NzbDroneValidationResult(Validator.Validate(this)); return new NzbDroneValidationResult(Validator.Validate(this));
@@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Specialized; using System.Collections.Specialized;
using System.Linq; using System.Linq;
@@ -28,9 +28,9 @@ namespace NzbDrone.Core.Indexers.Definitions
{ {
public override string Name => "SpeedApp.io"; public override string Name => "SpeedApp.io";
public override string BaseUrl => "https://speedapp.io"; public override string[] IndexerUrls => new string[] { "https://speedapp.io" };
private string ApiUrl => $"{BaseUrl}/api"; private string ApiUrl => $"{Settings.BaseUrl}/api";
private string LoginUrl => $"{ApiUrl}/login"; private string LoginUrl => $"{ApiUrl}/login";
@@ -56,12 +56,12 @@ namespace NzbDrone.Core.Indexers.Definitions
public override IIndexerRequestGenerator GetRequestGenerator() public override IIndexerRequestGenerator GetRequestGenerator()
{ {
return new SpeedAppRequestGenerator(Capabilities, Settings, ApiUrl); return new SpeedAppRequestGenerator(Capabilities, Settings);
} }
public override IParseIndexerResponse GetParser() public override IParseIndexerResponse GetParser()
{ {
return new SpeedAppParser(ApiUrl); return new SpeedAppParser(Settings);
} }
protected override bool CheckIfLoginNeeded(HttpResponse httpResponse) protected override bool CheckIfLoginNeeded(HttpResponse httpResponse)
@@ -262,13 +262,10 @@ namespace NzbDrone.Core.Indexers.Definitions
private SpeedAppSettings Settings { get; } private SpeedAppSettings Settings { get; }
private string BaseUrl { get; } public SpeedAppRequestGenerator(IndexerCapabilities capabilities, SpeedAppSettings settings)
public SpeedAppRequestGenerator(IndexerCapabilities capabilities, SpeedAppSettings settings, string baseUrl)
{ {
Capabilities = capabilities; Capabilities = capabilities;
Settings = settings; Settings = settings;
BaseUrl = baseUrl;
} }
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria) public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
@@ -338,7 +335,7 @@ namespace NzbDrone.Core.Indexers.Definitions
} }
} }
var searchUrl = BaseUrl + "/torrent?" + qc.GetQueryString(); var searchUrl = Settings.BaseUrl + "/api/torrent?" + qc.GetQueryString();
var request = new IndexerRequest(searchUrl, HttpAccept.Json); var request = new IndexerRequest(searchUrl, HttpAccept.Json);
@@ -350,13 +347,13 @@ namespace NzbDrone.Core.Indexers.Definitions
public class SpeedAppParser : IParseIndexerResponse public class SpeedAppParser : IParseIndexerResponse
{ {
public string BaseUrl { get; set; } public SpeedAppSettings Settings { get; set; }
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; } public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
public SpeedAppParser(string baseUrl) public SpeedAppParser(SpeedAppSettings settings)
{ {
BaseUrl = baseUrl; Settings = settings;
} }
public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse) public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse)
@@ -380,7 +377,7 @@ namespace NzbDrone.Core.Indexers.Definitions
Description = torrent.ShortDescription, Description = torrent.ShortDescription,
Size = torrent.Size, Size = torrent.Size,
ImdbId = ParseUtil.GetImdbID(torrent.ImdbId).GetValueOrDefault(), ImdbId = ParseUtil.GetImdbID(torrent.ImdbId).GetValueOrDefault(),
DownloadUrl = $"{BaseUrl}/torrent/{torrent.Id}/download", DownloadUrl = $"{Settings.BaseUrl}/api/torrent/{torrent.Id}/download",
InfoUrl = torrent.Url, InfoUrl = torrent.Url,
Grabs = torrent.TimesCompleted, Grabs = torrent.TimesCompleted,
PublishDate = torrent.CreatedAt, PublishDate = torrent.CreatedAt,
@@ -405,7 +402,7 @@ namespace NzbDrone.Core.Indexers.Definitions
} }
} }
public class SpeedAppSettings : IProviderConfig public class SpeedAppSettings : IIndexerSettings
{ {
private static readonly SpeedAppSettingsValidator Validator = new (); private static readonly SpeedAppSettingsValidator Validator = new ();
@@ -415,13 +412,16 @@ namespace NzbDrone.Core.Indexers.Definitions
Password = ""; Password = "";
} }
[FieldDefinition(1, Label = "Email", HelpText = "Site email")] [FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2, Label = "Email", HelpText = "Site email")]
public string Email { get; set; } public string Email { get; set; }
[FieldDefinition(1, Label = "Password", HelpText = "Site Password", Type = FieldType.Password, Privacy = PrivacyLevel.Password)] [FieldDefinition(3, Label = "Password", HelpText = "Site Password", Privacy = PrivacyLevel.Password, Type = FieldType.Password)]
public string Password { get; set; } public string Password { get; set; }
[FieldDefinition(0, Label = "Api Key", Hidden = HiddenType.Hidden)] [FieldDefinition(4, Label = "Api Key", Hidden = HiddenType.Hidden)]
public string ApiKey { get; set; } public string ApiKey { get; set; }
public NzbDroneValidationResult Validate() public NzbDroneValidationResult Validate()
@@ -7,13 +7,13 @@ using System.Text.RegularExpressions;
using FluentValidation; using FluentValidation;
using NLog; using NLog;
using NzbDrone.Common.Http; using NzbDrone.Common.Http;
using NzbDrone.Core.Annotations;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.Indexers.Exceptions; using NzbDrone.Core.Indexers.Exceptions;
using NzbDrone.Core.IndexerSearch.Definitions; using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
using NzbDrone.Core.Parser.Model; using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.ThingiProvider;
using NzbDrone.Core.Validation; using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.Definitions namespace NzbDrone.Core.Indexers.Definitions
@@ -21,7 +21,11 @@ namespace NzbDrone.Core.Indexers.Definitions
public class SubsPlease : TorrentIndexerBase<SubsPleaseSettings> public class SubsPlease : TorrentIndexerBase<SubsPleaseSettings>
{ {
public override string Name => "SubsPlease"; public override string Name => "SubsPlease";
public override string BaseUrl => "https://subsplease.org/"; public override string[] IndexerUrls => new string[]
{
"https://subsplease.org/",
"https://subsplease.nocensor.space/"
};
public override string Language => "en-us"; public override string Language => "en-us";
public override string Description => "SubsPlease - A better HorribleSubs/Erai replacement"; public override string Description => "SubsPlease - A better HorribleSubs/Erai replacement";
public override Encoding Encoding => Encoding.UTF8; public override Encoding Encoding => Encoding.UTF8;
@@ -36,12 +40,12 @@ namespace NzbDrone.Core.Indexers.Definitions
public override IIndexerRequestGenerator GetRequestGenerator() public override IIndexerRequestGenerator GetRequestGenerator()
{ {
return new SubsPleaseRequestGenerator() { Settings = Settings, Capabilities = Capabilities, BaseUrl = BaseUrl }; return new SubsPleaseRequestGenerator() { Settings = Settings, Capabilities = Capabilities };
} }
public override IParseIndexerResponse GetParser() public override IParseIndexerResponse GetParser()
{ {
return new SubsPleaseParser(Settings, Capabilities.Categories, BaseUrl); return new SubsPleaseParser(Settings, Capabilities.Categories);
} }
private IndexerCapabilities SetCapabilities() private IndexerCapabilities SetCapabilities()
@@ -64,7 +68,6 @@ namespace NzbDrone.Core.Indexers.Definitions
{ {
public SubsPleaseSettings Settings { get; set; } public SubsPleaseSettings Settings { get; set; }
public IndexerCapabilities Capabilities { get; set; } public IndexerCapabilities Capabilities { get; set; }
public string BaseUrl { get; set; }
public SubsPleaseRequestGenerator() public SubsPleaseRequestGenerator()
{ {
@@ -72,7 +75,7 @@ namespace NzbDrone.Core.Indexers.Definitions
private IEnumerable<IndexerRequest> GetSearchRequests(string term) private IEnumerable<IndexerRequest> GetSearchRequests(string term)
{ {
var searchUrl = string.Format("{0}/api/?", BaseUrl.TrimEnd('/')); var searchUrl = string.Format("{0}/api/?", Settings.BaseUrl.TrimEnd('/'));
string searchTerm = Regex.Replace(term, "\\[?SubsPlease\\]?\\s*", string.Empty, RegexOptions.IgnoreCase).Trim(); string searchTerm = Regex.Replace(term, "\\[?SubsPlease\\]?\\s*", string.Empty, RegexOptions.IgnoreCase).Trim();
@@ -97,7 +100,7 @@ namespace NzbDrone.Core.Indexers.Definitions
private IEnumerable<IndexerRequest> GetRssRequest() private IEnumerable<IndexerRequest> GetRssRequest()
{ {
var searchUrl = string.Format("{0}/api/?", BaseUrl.TrimEnd('/')); var searchUrl = string.Format("{0}/api/?", Settings.BaseUrl.TrimEnd('/'));
var queryParameters = new NameValueCollection var queryParameters = new NameValueCollection
{ {
@@ -171,13 +174,11 @@ namespace NzbDrone.Core.Indexers.Definitions
{ {
private readonly SubsPleaseSettings _settings; private readonly SubsPleaseSettings _settings;
private readonly IndexerCapabilitiesCategories _categories; private readonly IndexerCapabilitiesCategories _categories;
private readonly string _baseUrl;
public SubsPleaseParser(SubsPleaseSettings settings, IndexerCapabilitiesCategories categories, string baseurl) public SubsPleaseParser(SubsPleaseSettings settings, IndexerCapabilitiesCategories categories)
{ {
_settings = settings; _settings = settings;
_categories = categories; _categories = categories;
_baseUrl = baseurl;
} }
public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse) public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse)
@@ -205,7 +206,7 @@ namespace NzbDrone.Core.Indexers.Definitions
{ {
var release = new TorrentInfo var release = new TorrentInfo
{ {
InfoUrl = _baseUrl + $"shows/{r.Page}/", InfoUrl = _settings.BaseUrl + $"shows/{r.Page}/",
PublishDate = r.Release_Date.DateTime, PublishDate = r.Release_Date.DateTime,
Files = 1, Files = 1,
Categories = new List<IndexerCategory> { NewznabStandardCategory.TVAnime }, Categories = new List<IndexerCategory> { NewznabStandardCategory.TVAnime },
@@ -255,10 +256,13 @@ namespace NzbDrone.Core.Indexers.Definitions
{ {
} }
public class SubsPleaseSettings : IProviderConfig public class SubsPleaseSettings : IIndexerSettings
{ {
private static readonly SubsPleaseSettingsValidator Validator = new SubsPleaseSettingsValidator(); private static readonly SubsPleaseSettingsValidator Validator = new SubsPleaseSettingsValidator();
[FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
public NzbDroneValidationResult Validate() public NzbDroneValidationResult Validate()
{ {
return new NzbDroneValidationResult(Validator.Validate(this)); return new NzbDroneValidationResult(Validator.Validate(this));
@@ -14,7 +14,6 @@ using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
using NzbDrone.Core.Parser.Model; using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.ThingiProvider;
using NzbDrone.Core.Validation; using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.Definitions namespace NzbDrone.Core.Indexers.Definitions
@@ -23,7 +22,8 @@ namespace NzbDrone.Core.Indexers.Definitions
{ {
public override string Name => "SuperBits"; public override string Name => "SuperBits";
public override string BaseUrl => "https://superbits.org/"; public override string[] IndexerUrls => new string[] { "https://superbits.org/" };
public override string Description => "Superbits is a SWEDISH Private Torrent Tracker for MOVIES / TV / GENERAL";
public override DownloadProtocol Protocol => DownloadProtocol.Torrent; public override DownloadProtocol Protocol => DownloadProtocol.Torrent;
public override IndexerPrivacy Privacy => IndexerPrivacy.Private; public override IndexerPrivacy Privacy => IndexerPrivacy.Private;
public override IndexerCapabilities Capabilities => SetCapabilities(); public override IndexerCapabilities Capabilities => SetCapabilities();
@@ -35,12 +35,12 @@ namespace NzbDrone.Core.Indexers.Definitions
public override IIndexerRequestGenerator GetRequestGenerator() public override IIndexerRequestGenerator GetRequestGenerator()
{ {
return new SuperBitsRequestGenerator() { Settings = Settings, Capabilities = Capabilities, BaseUrl = BaseUrl }; return new SuperBitsRequestGenerator() { Settings = Settings, Capabilities = Capabilities };
} }
public override IParseIndexerResponse GetParser() public override IParseIndexerResponse GetParser()
{ {
return new SuperBitsParser(Settings, Capabilities.Categories, BaseUrl); return new SuperBitsParser(Settings, Capabilities.Categories);
} }
protected override IDictionary<string, string> GetCookies() protected override IDictionary<string, string> GetCookies()
@@ -104,7 +104,6 @@ namespace NzbDrone.Core.Indexers.Definitions
{ {
public SuperBitsSettings Settings { get; set; } public SuperBitsSettings Settings { get; set; }
public IndexerCapabilities Capabilities { get; set; } public IndexerCapabilities Capabilities { get; set; }
public string BaseUrl { get; set; }
public SuperBitsRequestGenerator() public SuperBitsRequestGenerator()
{ {
@@ -112,7 +111,7 @@ namespace NzbDrone.Core.Indexers.Definitions
private IEnumerable<IndexerRequest> GetPagedRequests(string term, int[] categories, string imdbId = null) private IEnumerable<IndexerRequest> GetPagedRequests(string term, int[] categories, string imdbId = null)
{ {
var searchUrl = BaseUrl + "api/v1/torrents"; var searchUrl = Settings.BaseUrl + "api/v1/torrents";
// And this was option one from // And this was option one from
// https://github.com/Jackett/Jackett/pull/7166#discussion_r376817517 // https://github.com/Jackett/Jackett/pull/7166#discussion_r376817517
@@ -151,7 +150,7 @@ namespace NzbDrone.Core.Indexers.Definitions
var request = new IndexerRequest(searchUrl, HttpAccept.Json); var request = new IndexerRequest(searchUrl, HttpAccept.Json);
request.HttpRequest.Headers.Add("Referer", BaseUrl); request.HttpRequest.Headers.Add("Referer", Settings.BaseUrl);
yield return request; yield return request;
} }
@@ -209,13 +208,11 @@ namespace NzbDrone.Core.Indexers.Definitions
{ {
private readonly SuperBitsSettings _settings; private readonly SuperBitsSettings _settings;
private readonly IndexerCapabilitiesCategories _categories; private readonly IndexerCapabilitiesCategories _categories;
private readonly string _baseUrl;
public SuperBitsParser(SuperBitsSettings settings, IndexerCapabilitiesCategories categories, string baseUrl) public SuperBitsParser(SuperBitsSettings settings, IndexerCapabilitiesCategories categories)
{ {
_settings = settings; _settings = settings;
_categories = categories; _categories = categories;
_baseUrl = baseUrl;
} }
public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse) public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse)
@@ -240,9 +237,9 @@ namespace NzbDrone.Core.Indexers.Definitions
release.Files = row.numfiles; release.Files = row.numfiles;
release.Grabs = row.times_completed; release.Grabs = row.times_completed;
release.InfoUrl = _baseUrl + "torrent/" + row.id.ToString() + "/"; release.InfoUrl = _settings.BaseUrl + "torrent/" + row.id.ToString() + "/";
release.Guid = release.InfoUrl; release.Guid = release.InfoUrl;
release.DownloadUrl = _baseUrl + "api/v1/torrents/download/" + row.id.ToString(); release.DownloadUrl = _settings.BaseUrl + "api/v1/torrents/download/" + row.id.ToString();
if (row.frileech == 1) if (row.frileech == 1)
{ {
@@ -329,7 +326,7 @@ namespace NzbDrone.Core.Indexers.Definitions
} }
} }
public class SuperBitsSettings : IProviderConfig public class SuperBitsSettings : IIndexerSettings
{ {
private static readonly SuperBitsSettingsValidator Validator = new SuperBitsSettingsValidator(); private static readonly SuperBitsSettingsValidator Validator = new SuperBitsSettingsValidator();
@@ -338,9 +335,10 @@ namespace NzbDrone.Core.Indexers.Definitions
Cookie = ""; Cookie = "";
} }
[FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; } public string BaseUrl { get; set; }
[FieldDefinition(1, Label = "Cookie", HelpText = "Site Cookie")] [FieldDefinition(2, Label = "Cookie", HelpText = "Site Cookie")]
public string Cookie { get; set; } public string Cookie { get; set; }
public NzbDroneValidationResult Validate() public NzbDroneValidationResult Validate()
@@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Collections.Specialized; using System.Collections.Specialized;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using FluentValidation;
using Newtonsoft.Json; using Newtonsoft.Json;
using NLog; using NLog;
using NzbDrone.Common.Http; using NzbDrone.Common.Http;
@@ -13,7 +12,6 @@ using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
using NzbDrone.Core.Parser.Model; using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.ThingiProvider;
using NzbDrone.Core.Validation; using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.Definitions namespace NzbDrone.Core.Indexers.Definitions
@@ -21,7 +19,8 @@ namespace NzbDrone.Core.Indexers.Definitions
public class ThePirateBay : TorrentIndexerBase<ThePirateBaySettings> public class ThePirateBay : TorrentIndexerBase<ThePirateBaySettings>
{ {
public override string Name => "ThePirateBay"; public override string Name => "ThePirateBay";
public override string BaseUrl => "https://thepiratebay.org/"; public override string[] IndexerUrls => new string[] { "https://thepiratebay.org/" };
public override string Description => "Pirate Bay(TPB) is the galaxys most resilient Public BitTorrent site";
public override string Language => "en-us"; public override string Language => "en-us";
public override Encoding Encoding => Encoding.UTF8; public override Encoding Encoding => Encoding.UTF8;
public override DownloadProtocol Protocol => DownloadProtocol.Torrent; public override DownloadProtocol Protocol => DownloadProtocol.Torrent;
@@ -35,12 +34,12 @@ namespace NzbDrone.Core.Indexers.Definitions
public override IIndexerRequestGenerator GetRequestGenerator() public override IIndexerRequestGenerator GetRequestGenerator()
{ {
return new ThePirateBayRequestGenerator() { Capabilities = Capabilities, BaseUrl = BaseUrl }; return new ThePirateBayRequestGenerator() { Capabilities = Capabilities };
} }
public override IParseIndexerResponse GetParser() public override IParseIndexerResponse GetParser()
{ {
return new ThePirateBayParser(Capabilities.Categories, BaseUrl); return new ThePirateBayParser(Capabilities.Categories, Settings);
} }
private IndexerCapabilities SetCapabilities() private IndexerCapabilities SetCapabilities()
@@ -123,7 +122,7 @@ namespace NzbDrone.Core.Indexers.Definitions
public class ThePirateBayRequestGenerator : IIndexerRequestGenerator public class ThePirateBayRequestGenerator : IIndexerRequestGenerator
{ {
public IndexerCapabilities Capabilities { get; set; } public IndexerCapabilities Capabilities { get; set; }
public string BaseUrl { get; set; }
private static string ApiUrl => "https://apibay.org/"; private static string ApiUrl => "https://apibay.org/";
public ThePirateBayRequestGenerator() public ThePirateBayRequestGenerator()
@@ -211,13 +210,13 @@ namespace NzbDrone.Core.Indexers.Definitions
public class ThePirateBayParser : IParseIndexerResponse public class ThePirateBayParser : IParseIndexerResponse
{ {
private readonly ThePirateBaySettings _settings;
private readonly IndexerCapabilitiesCategories _categories; private readonly IndexerCapabilitiesCategories _categories;
private readonly string _baseUrl;
public ThePirateBayParser(IndexerCapabilitiesCategories categories, string baseUrl) public ThePirateBayParser(IndexerCapabilitiesCategories categories, ThePirateBaySettings settings)
{ {
_settings = settings;
_categories = categories; _categories = categories;
_baseUrl = baseUrl;
} }
public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse) public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse)
@@ -234,7 +233,7 @@ namespace NzbDrone.Core.Indexers.Definitions
foreach (var item in queryResponseItems) foreach (var item in queryResponseItems)
{ {
var details = item.Id == 0 ? null : $"{_baseUrl}description.php?id={item.Id}"; var details = item.Id == 0 ? null : $"{_settings.BaseUrl}description.php?id={item.Id}";
var imdbId = string.IsNullOrEmpty(item.Imdb) ? null : ParseUtil.GetImdbID(item.Imdb); var imdbId = string.IsNullOrEmpty(item.Imdb) ? null : ParseUtil.GetImdbID(item.Imdb);
var torrentItem = new TorrentInfo var torrentItem = new TorrentInfo
{ {
@@ -262,8 +261,11 @@ namespace NzbDrone.Core.Indexers.Definitions
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; } public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
} }
public class ThePirateBaySettings : IProviderConfig public class ThePirateBaySettings : IIndexerSettings
{ {
[FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
public NzbDroneValidationResult Validate() public NzbDroneValidationResult Validate()
{ {
return new NzbDroneValidationResult(); return new NzbDroneValidationResult();
@@ -12,7 +12,6 @@ using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
using NzbDrone.Core.Parser.Model; using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.ThingiProvider;
using NzbDrone.Core.Validation; using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.Definitions namespace NzbDrone.Core.Indexers.Definitions
@@ -21,7 +20,8 @@ namespace NzbDrone.Core.Indexers.Definitions
{ {
public override string Name => "TorrentDay"; public override string Name => "TorrentDay";
public override string BaseUrl => "https://torrentday.cool/"; public override string[] IndexerUrls => new string[] { "https://torrentday.cool/" };
public override string Description => "TorrentDay (TD) is a Private site for TV / MOVIES / GENERAL";
public override DownloadProtocol Protocol => DownloadProtocol.Torrent; public override DownloadProtocol Protocol => DownloadProtocol.Torrent;
public override IndexerPrivacy Privacy => IndexerPrivacy.Private; public override IndexerPrivacy Privacy => IndexerPrivacy.Private;
public override IndexerCapabilities Capabilities => SetCapabilities(); public override IndexerCapabilities Capabilities => SetCapabilities();
@@ -33,12 +33,12 @@ namespace NzbDrone.Core.Indexers.Definitions
public override IIndexerRequestGenerator GetRequestGenerator() public override IIndexerRequestGenerator GetRequestGenerator()
{ {
return new TorrentDayRequestGenerator() { Settings = Settings, Capabilities = Capabilities, BaseUrl = BaseUrl }; return new TorrentDayRequestGenerator() { Settings = Settings, Capabilities = Capabilities };
} }
public override IParseIndexerResponse GetParser() public override IParseIndexerResponse GetParser()
{ {
return new TorrentDayParser(Settings, Capabilities.Categories, BaseUrl); return new TorrentDayParser(Settings, Capabilities.Categories);
} }
protected override IDictionary<string, string> GetCookies() protected override IDictionary<string, string> GetCookies()
@@ -124,7 +124,6 @@ namespace NzbDrone.Core.Indexers.Definitions
{ {
public TorrentDaySettings Settings { get; set; } public TorrentDaySettings Settings { get; set; }
public IndexerCapabilities Capabilities { get; set; } public IndexerCapabilities Capabilities { get; set; }
public string BaseUrl { get; set; }
public TorrentDayRequestGenerator() public TorrentDayRequestGenerator()
{ {
@@ -132,7 +131,7 @@ namespace NzbDrone.Core.Indexers.Definitions
private IEnumerable<IndexerRequest> GetPagedRequests(string term, int[] categories, string imdbId = null) private IEnumerable<IndexerRequest> GetPagedRequests(string term, int[] categories, string imdbId = null)
{ {
var searchUrl = BaseUrl + "t.json"; var searchUrl = Settings.BaseUrl + "t.json";
var cats = Capabilities.Categories.MapTorznabCapsToTrackers(categories); var cats = Capabilities.Categories.MapTorznabCapsToTrackers(categories);
if (cats.Count == 0) if (cats.Count == 0)
@@ -210,13 +209,11 @@ namespace NzbDrone.Core.Indexers.Definitions
{ {
private readonly TorrentDaySettings _settings; private readonly TorrentDaySettings _settings;
private readonly IndexerCapabilitiesCategories _categories; private readonly IndexerCapabilitiesCategories _categories;
private readonly string _baseUrl;
public TorrentDayParser(TorrentDaySettings settings, IndexerCapabilitiesCategories categories, string baseUrl) public TorrentDayParser(TorrentDaySettings settings, IndexerCapabilitiesCategories categories)
{ {
_settings = settings; _settings = settings;
_categories = categories; _categories = categories;
_baseUrl = baseUrl;
} }
public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse) public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse)
@@ -230,11 +227,11 @@ namespace NzbDrone.Core.Indexers.Definitions
var title = (string)row.name; var title = (string)row.name;
var torrentId = (long)row.t; var torrentId = (long)row.t;
var details = new Uri(_baseUrl + "details.php?id=" + torrentId); var details = new Uri(_settings.BaseUrl + "details.php?id=" + torrentId);
var seeders = (int)row.seeders; var seeders = (int)row.seeders;
var imdbId = (string)row["imdb-id"]; var imdbId = (string)row["imdb-id"];
var downloadMultiplier = (double?)row["download-multiplier"] ?? 1; var downloadMultiplier = (double?)row["download-multiplier"] ?? 1;
var link = new Uri(_baseUrl + "download.php/" + torrentId + "/" + torrentId + ".torrent"); var link = new Uri(_settings.BaseUrl + "download.php/" + torrentId + "/" + torrentId + ".torrent");
var publishDate = DateTimeUtil.UnixTimestampToDateTime((long)row.ctime).ToLocalTime(); var publishDate = DateTimeUtil.UnixTimestampToDateTime((long)row.ctime).ToLocalTime();
var imdb = ParseUtil.GetImdbID(imdbId) ?? 0; var imdb = ParseUtil.GetImdbID(imdbId) ?? 0;
@@ -275,7 +272,7 @@ namespace NzbDrone.Core.Indexers.Definitions
} }
} }
public class TorrentDaySettings : IProviderConfig public class TorrentDaySettings : IIndexerSettings
{ {
private static readonly TorrentDaySettingsValidator Validator = new TorrentDaySettingsValidator(); private static readonly TorrentDaySettingsValidator Validator = new TorrentDaySettingsValidator();
@@ -284,7 +281,10 @@ namespace NzbDrone.Core.Indexers.Definitions
Cookie = ""; Cookie = "";
} }
[FieldDefinition(1, Label = "Cookie", HelpText = "Site Cookie")] [FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2, Label = "Cookie", HelpText = "Site Cookie")]
public string Cookie { get; set; } public string Cookie { get; set; }
public NzbDroneValidationResult Validate() public NzbDroneValidationResult Validate()
@@ -16,7 +16,6 @@ using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
using NzbDrone.Core.Parser.Model; using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.ThingiProvider;
using NzbDrone.Core.Validation; using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.Definitions namespace NzbDrone.Core.Indexers.Definitions
@@ -25,8 +24,9 @@ namespace NzbDrone.Core.Indexers.Definitions
{ {
public override string Name => "TorrentLeech"; public override string Name => "TorrentLeech";
public override string BaseUrl => "https://www.torrentleech.org/"; public override string[] IndexerUrls => new string[] { "https://www.torrentleech.org/" };
private string LoginUrl => BaseUrl + "user/account/login/"; public override string Description => "This is what happens when you seed";
private string LoginUrl => Settings.BaseUrl + "user/account/login/";
public override DownloadProtocol Protocol => DownloadProtocol.Torrent; public override DownloadProtocol Protocol => DownloadProtocol.Torrent;
public override IndexerPrivacy Privacy => IndexerPrivacy.Private; public override IndexerPrivacy Privacy => IndexerPrivacy.Private;
public override IndexerCapabilities Capabilities => SetCapabilities(); public override IndexerCapabilities Capabilities => SetCapabilities();
@@ -38,12 +38,12 @@ namespace NzbDrone.Core.Indexers.Definitions
public override IIndexerRequestGenerator GetRequestGenerator() public override IIndexerRequestGenerator GetRequestGenerator()
{ {
return new TorrentLeechRequestGenerator() { Settings = Settings, Capabilities = Capabilities, BaseUrl = BaseUrl }; return new TorrentLeechRequestGenerator() { Settings = Settings, Capabilities = Capabilities };
} }
public override IParseIndexerResponse GetParser() public override IParseIndexerResponse GetParser()
{ {
return new TorrentLeechParser(Settings, Capabilities.Categories, BaseUrl); return new TorrentLeechParser(Settings, Capabilities.Categories);
} }
protected override async Task DoLogin() protected override async Task DoLogin()
@@ -166,7 +166,6 @@ namespace NzbDrone.Core.Indexers.Definitions
{ {
public TorrentLeechSettings Settings { get; set; } public TorrentLeechSettings Settings { get; set; }
public IndexerCapabilities Capabilities { get; set; } public IndexerCapabilities Capabilities { get; set; }
public string BaseUrl { get; set; }
public TorrentLeechRequestGenerator() public TorrentLeechRequestGenerator()
{ {
@@ -176,7 +175,7 @@ namespace NzbDrone.Core.Indexers.Definitions
{ {
var searchString = Regex.Replace(term, @"(^|\s)-", " "); var searchString = Regex.Replace(term, @"(^|\s)-", " ");
var searchUrl = BaseUrl + "torrents/browse/list/"; var searchUrl = Settings.BaseUrl + "torrents/browse/list/";
if (Settings.FreeLeechOnly) if (Settings.FreeLeechOnly)
{ {
@@ -260,13 +259,11 @@ namespace NzbDrone.Core.Indexers.Definitions
{ {
private readonly TorrentLeechSettings _settings; private readonly TorrentLeechSettings _settings;
private readonly IndexerCapabilitiesCategories _categories; private readonly IndexerCapabilitiesCategories _categories;
private readonly string _baseUrl;
public TorrentLeechParser(TorrentLeechSettings settings, IndexerCapabilitiesCategories categories, string baseUrl) public TorrentLeechParser(TorrentLeechSettings settings, IndexerCapabilitiesCategories categories)
{ {
_settings = settings; _settings = settings;
_categories = categories; _categories = categories;
_baseUrl = baseUrl;
} }
public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse) public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse)
@@ -279,8 +276,8 @@ namespace NzbDrone.Core.Indexers.Definitions
var title = row.name.ToString(); var title = row.name.ToString();
var torrentId = row.fid.ToString(); var torrentId = row.fid.ToString();
var details = new Uri(_baseUrl + "torrent/" + torrentId); var details = new Uri(_settings.BaseUrl + "torrent/" + torrentId);
var link = new Uri(_baseUrl + "download/" + torrentId + "/" + row.filename); var link = new Uri(_settings.BaseUrl + "download/" + torrentId + "/" + row.filename);
var publishDate = DateTime.ParseExact(row.addedTimestamp.ToString(), "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture); var publishDate = DateTime.ParseExact(row.addedTimestamp.ToString(), "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture);
var seeders = (int)row.seeders; var seeders = (int)row.seeders;
var leechers = (int)row.leechers; var leechers = (int)row.leechers;
@@ -335,7 +332,7 @@ namespace NzbDrone.Core.Indexers.Definitions
} }
} }
public class TorrentLeechSettings : IProviderConfig public class TorrentLeechSettings : IIndexerSettings
{ {
private static readonly TorrentLeechSettingsValidator Validator = new TorrentLeechSettingsValidator(); private static readonly TorrentLeechSettingsValidator Validator = new TorrentLeechSettingsValidator();
@@ -345,13 +342,16 @@ namespace NzbDrone.Core.Indexers.Definitions
Password = ""; Password = "";
} }
[FieldDefinition(1, Label = "Username", HelpText = "Site Username", Type = FieldType.Textbox, Privacy = PrivacyLevel.UserName)] [FieldDefinition(1, Label = "Base Url", Type = FieldType.Select, SelectOptionsProviderAction = "getUrls", HelpText = "Select which baseurl Prowlarr will use for requests to the site")]
public string BaseUrl { get; set; }
[FieldDefinition(2, Label = "Username", HelpText = "Site Username", Privacy = PrivacyLevel.UserName)]
public string Username { get; set; } public string Username { get; set; }
[FieldDefinition(2, Label = "Password", HelpText = "Site Password", Type = FieldType.Password, Privacy = PrivacyLevel.Password)] [FieldDefinition(3, Label = "Password", Type = FieldType.Password, HelpText = "Site Password", Privacy = PrivacyLevel.Password)]
public string Password { get; set; } public string Password { get; set; }
[FieldDefinition(3, Label = "FreeLeech Only", Type = FieldType.Checkbox, Advanced = true, HelpText = "Search Freeleech torrents only")] [FieldDefinition(4, Label = "FreeLeech Only", Type = FieldType.Checkbox, Advanced = true, HelpText = "Search Freeleech torrents only")]
public bool FreeLeechOnly { get; set; } public bool FreeLeechOnly { get; set; }
public NzbDroneValidationResult Validate() public NzbDroneValidationResult Validate()

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