mirror of
https://github.com/Readarr/Readarr.git
synced 2026-03-17 16:14:04 -04:00
Compare commits
1 Commits
notifiarr-
...
sonarr-pul
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
edce18e2cf |
@@ -3,6 +3,7 @@
|
||||
## Reporting a Vulnerability
|
||||
|
||||
Please report (suspected) security vulnerabilities on Discord (preferred) to
|
||||
any of the Servarr Dev role holders (red names) or via email: development@servarr.com. You will receive a response from
|
||||
either markus101
|
||||
#2148 or Taloth#7357 or via email: security@sonarr.tv. You will receive a response from
|
||||
us within 72 hours. If the issue is confirmed, we will release a patch as soon
|
||||
as possible depending on complexity/severity.
|
||||
|
||||
@@ -39,7 +39,6 @@ module.exports = {
|
||||
plugins: [
|
||||
'filenames',
|
||||
'react',
|
||||
'react-hooks',
|
||||
'simple-import-sort',
|
||||
'import'
|
||||
],
|
||||
@@ -309,9 +308,7 @@ module.exports = {
|
||||
'react/react-in-jsx-scope': 2,
|
||||
'react/self-closing-comp': 2,
|
||||
'react/sort-comp': 2,
|
||||
'react/jsx-wrap-multilines': 2,
|
||||
'react-hooks/rules-of-hooks': 'error',
|
||||
'react-hooks/exhaustive-deps': 'error'
|
||||
'react/jsx-wrap-multilines': 2
|
||||
},
|
||||
overrides: [
|
||||
{
|
||||
|
||||
@@ -12,9 +12,9 @@ import ModalBody from 'Components/Modal/ModalBody';
|
||||
import Portal from 'Components/Portal';
|
||||
import Scroller from 'Components/Scroller/Scroller';
|
||||
import { icons, scrollDirections, sizes } from 'Helpers/Props';
|
||||
import { isMobile as isMobileUtil } from 'Utilities/browser';
|
||||
import * as keyCodes from 'Utilities/Constants/keyCodes';
|
||||
import getUniqueElememtId from 'Utilities/getUniqueElementId';
|
||||
import { isMobile as isMobileUtil } from 'Utilities/mobile';
|
||||
import HintedSelectInputOption from './HintedSelectInputOption';
|
||||
import HintedSelectInputSelectedValue from './HintedSelectInputSelectedValue';
|
||||
import TextInput from './TextInput';
|
||||
|
||||
@@ -33,7 +33,7 @@ function ConfirmModal(props) {
|
||||
|
||||
return () => unbindShortcut('enter', onConfirm);
|
||||
}
|
||||
}, [bindShortcut, unbindShortcut, isOpen, onConfirm]);
|
||||
}, [isOpen, onConfirm]);
|
||||
|
||||
return (
|
||||
<Modal
|
||||
|
||||
@@ -6,9 +6,9 @@ import ReactDOM from 'react-dom';
|
||||
import FocusLock from 'react-focus-lock';
|
||||
import ErrorBoundary from 'Components/Error/ErrorBoundary';
|
||||
import { sizes } from 'Helpers/Props';
|
||||
import { isIOS } from 'Utilities/browser';
|
||||
import * as keyCodes from 'Utilities/Constants/keyCodes';
|
||||
import getUniqueElememtId from 'Utilities/getUniqueElementId';
|
||||
import { isIOS } from 'Utilities/mobile';
|
||||
import { setScrollLock } from 'Utilities/scrollLock';
|
||||
import ModalError from './ModalError';
|
||||
import styles from './Modal.css';
|
||||
|
||||
@@ -1,12 +1,23 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import OverlayScroller from 'Components/Scroller/OverlayScroller';
|
||||
import Scroller from 'Components/Scroller/Scroller';
|
||||
import { scrollDirections } from 'Helpers/Props';
|
||||
import { isMobile as isMobileUtil } from 'Utilities/mobile';
|
||||
import { isLocked } from 'Utilities/scrollLock';
|
||||
import styles from './PageContentBody.css';
|
||||
|
||||
class PageContentBody extends Component {
|
||||
|
||||
//
|
||||
// Lifecycle
|
||||
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
|
||||
this._isMobile = isMobileUtil();
|
||||
}
|
||||
|
||||
//
|
||||
// Listeners
|
||||
|
||||
@@ -30,8 +41,10 @@ class PageContentBody extends Component {
|
||||
...otherProps
|
||||
} = this.props;
|
||||
|
||||
const ScrollerComponent = this._isMobile ? Scroller : OverlayScroller;
|
||||
|
||||
return (
|
||||
<Scroller
|
||||
<ScrollerComponent
|
||||
className={className}
|
||||
scrollDirection={scrollDirections.VERTICAL}
|
||||
{...otherProps}
|
||||
@@ -40,7 +53,7 @@ class PageContentBody extends Component {
|
||||
<div className={innerClassName}>
|
||||
{children}
|
||||
</div>
|
||||
</Scroller>
|
||||
</ScrollerComponent>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import { Scrollbars } from 'react-custom-scrollbars-2';
|
||||
import { Scrollbars } from 'react-custom-scrollbars';
|
||||
import { scrollDirections } from 'Helpers/Props';
|
||||
import styles from './OverlayScroller.css';
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import Measure from 'Components/Measure';
|
||||
import { isMobile as isMobileUtil } from 'Utilities/browser';
|
||||
import { isMobile as isMobileUtil } from 'Utilities/mobile';
|
||||
import styles from './SwipeHeader.css';
|
||||
|
||||
function cursorPosition(event) {
|
||||
|
||||
@@ -5,7 +5,7 @@ import { Manager, Popper, Reference } from 'react-popper';
|
||||
import Portal from 'Components/Portal';
|
||||
import { kinds, tooltipPositions } from 'Helpers/Props';
|
||||
import dimensions from 'Styles/Variables/dimensions';
|
||||
import { isMobile as isMobileUtil } from 'Utilities/browser';
|
||||
import { isMobile as isMobileUtil } from 'Utilities/mobile';
|
||||
import styles from './Tooltip.css';
|
||||
|
||||
let maxWidth = null;
|
||||
|
||||
@@ -58,7 +58,6 @@ function HostSettings(props) {
|
||||
name="port"
|
||||
min={1}
|
||||
max={65535}
|
||||
autocomplete="off"
|
||||
helpTextWarning={translate('PortHelpTextWarning')}
|
||||
onChange={onInputChange}
|
||||
{...port}
|
||||
|
||||
@@ -19,7 +19,7 @@ function PendingChangesModal(props) {
|
||||
|
||||
useEffect(() => {
|
||||
bindShortcut('enter', onConfirm);
|
||||
}, [bindShortcut, onConfirm]);
|
||||
}, [onConfirm]);
|
||||
|
||||
return (
|
||||
<Modal
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
@define-mixin scrollbar {
|
||||
scrollbar-color: var(--scrollbarBackgroundColor) transparent;
|
||||
scrollbar-width: thin;
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
|
||||
@@ -10,7 +10,3 @@ export function isMobile() {
|
||||
export function isIOS() {
|
||||
return mobileDetect.is('iOS');
|
||||
}
|
||||
|
||||
export function isFirefox() {
|
||||
return window.navigator.userAgent.toLowerCase().indexOf('firefox/') >= 0;
|
||||
}
|
||||
@@ -58,7 +58,7 @@
|
||||
"react-addons-shallow-compare": "15.6.3",
|
||||
"react-async-script": "1.2.0",
|
||||
"react-autosuggest": "10.1.0",
|
||||
"react-custom-scrollbars-2": "4.5.0",
|
||||
"react-custom-scrollbars": "4.2.1",
|
||||
"react-dnd": "14.0.2",
|
||||
"react-dnd-html5-backend": "14.0.0",
|
||||
"react-dnd-multi-backend": "6.0.2",
|
||||
@@ -109,7 +109,6 @@
|
||||
"eslint-plugin-filenames": "1.3.2",
|
||||
"eslint-plugin-import": "2.23.4",
|
||||
"eslint-plugin-react": "7.24.0",
|
||||
"eslint-plugin-react-hooks": "4.6.0",
|
||||
"eslint-plugin-simple-import-sort": "7.0.0",
|
||||
"esprint": "3.1.0",
|
||||
"file-loader": "6.2.0",
|
||||
|
||||
@@ -61,7 +61,6 @@ namespace NzbDrone.Common.Test.InstrumentationTests
|
||||
[TestCase("https://notifiarr.com/notifier.php: api=1234530f-422f-4aac-b6b3-01233210aaaa&radarr_health_issue_message=Download")]
|
||||
[TestCase("/readarr/signalr/messages/negotiate?access_token=1234530f422f4aacb6b301233210aaaa&negotiateVersion=1")]
|
||||
[TestCase(@"[Info] MigrationController: *** Migrating Database=readarr-main;Host=postgres14;Username=mySecret;Password=mySecret;Port=5432;Enlist=False ***")]
|
||||
[TestCase(@"[Info] MigrationController: *** Migrating Database=readarr-main;Host=postgres14;Username=mySecret;Password=mySecret;Port=5432;token=mySecret;Enlist=False&username=mySecret;mypassword=mySecret;mypass=shouldkeep1;test_token=mySecret;password=123%@%_@!#^#@;use_password=mySecret;get_token=shouldkeep2;usetoken=shouldkeep3;passwrd=mySecret;")]
|
||||
|
||||
// Announce URLs (passkeys) Magnet & Tracker
|
||||
[TestCase(@"magnet_uri"":""magnet:?xt=urn:btih:9pr04sgkillroyimaveql2tyu8xyui&dn=&tr=https%3a%2f%2fxxx.yyy%2f9pr04sg601233210imaveql2tyu8xyui%2fannounce""}")]
|
||||
@@ -74,36 +73,17 @@ namespace NzbDrone.Common.Test.InstrumentationTests
|
||||
[TestCase(@"tracker"":""https://xxx.yyy/announce.php?passkey=9pr04sg601233210imaveql2tyu8xyui""}")]
|
||||
[TestCase(@"tracker"":""http://xxx.yyy/announce.php?passkey=9pr04sg601233210imaveql2tyu8xyui"",""info"":""http://xxx.yyy/info?a=b""")]
|
||||
|
||||
// Notifiarr
|
||||
// Webhooks - Notifiarr
|
||||
[TestCase(@"https://xxx.yyy/api/v1/notification/readarr/9pr04sg6-0123-3210-imav-eql2tyu8xyui")]
|
||||
|
||||
// Discord
|
||||
[TestCase(@"https://discord.com/api/webhooks/mySecret")]
|
||||
[TestCase(@"https://discord.com/api/webhooks/mySecret/01233210")]
|
||||
|
||||
public void should_clean_message(string message)
|
||||
{
|
||||
var cleansedMessage = CleanseLogMessage.Cleanse(message);
|
||||
|
||||
cleansedMessage.Should().NotContain("mySecret");
|
||||
cleansedMessage.Should().NotContain("123%@%_@!#^#@");
|
||||
cleansedMessage.Should().NotContain("01233210");
|
||||
}
|
||||
|
||||
[TestCase(@"[Info] MigrationController: *** Migrating Database=radarr-main;Host=postgres14;Username=mySecret;Password=mySecret;Port=5432;token=mySecret;Enlist=False&username=mySecret;mypassword=mySecret;mypass=shouldkeep1;test_token=mySecret;password=123%@%_@!#^#@;use_password=mySecret;get_token=shouldkeep2;usetoken=shouldkeep3;passwrd=mySecret;")]
|
||||
public void should_keep_message(string message)
|
||||
{
|
||||
var cleansedMessage = CleanseLogMessage.Cleanse(message);
|
||||
|
||||
cleansedMessage.Should().NotContain("mySecret");
|
||||
cleansedMessage.Should().NotContain("123%@%_@!#^#@");
|
||||
cleansedMessage.Should().NotContain("01233210");
|
||||
|
||||
cleansedMessage.Should().Contain("shouldkeep1");
|
||||
cleansedMessage.Should().Contain("shouldkeep2");
|
||||
cleansedMessage.Should().Contain("shouldkeep3");
|
||||
}
|
||||
|
||||
//GoodReads
|
||||
[TestCase(@"{""signatureMethod"": ""hmacSha1"",""signatureTreatment"": ""escaped"",""type"": ""protectedResource"",""method"": ""GET"",""token"": ""mytoken"",""tokenSecret"": ""mytokensecret"",""requestUrl"": ""https://www.goodreads.com/review/list.xml"",""parameters"": { ""_nc"": ""1"", ""v"": ""2"", ""id"": ""999999999"", ""shelf"": ""currently-reading"", ""per_page"": ""200"", ""page"": ""1""}")]
|
||||
[TestCase(@"https://www.goodreads.com/series/311911?key=1234530f422f4aacb6b301233210aaaa&_nc=1&format=xml")]
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace NzbDrone.Common.Instrumentation
|
||||
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(@"getnzb.*?(?<=\?|&)(r)=(?<secret>[^&=]+?)(?= |&|$)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||
new Regex(@"\b(\w*)?(_?(?<!use|get_)token|username|passwo?rd)=(?<secret>[^&=]+?)(?= |&|$|;)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||
new Regex(@"(?<=[?& ;])[^=]*?(_?(?<!use|get_)token|username|passwo?rd)=(?<secret>[^&=]+?)(?= |&|$|;)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||
|
||||
// Trackers Announce Keys; Designed for Qbit Json; should work for all in theory
|
||||
new Regex(@"announce(\.php)?(/|%2f|%3fpasskey%3d)(?<secret>[a-z0-9]{16,})|(?<secret>[a-z0-9]{16,})(/|%2f)announce"),
|
||||
@@ -51,10 +51,7 @@ namespace NzbDrone.Common.Instrumentation
|
||||
|
||||
// Webhooks
|
||||
// Notifiarr
|
||||
new Regex(@"api/v[0-9]/notification/readarr/(?<secret>[\w-]+)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||
|
||||
// Discord
|
||||
new Regex(@"discord.com/api/webhooks/((?<secret>[\w-]+)/)?(?<secret>[\w-]+)", RegexOptions.Compiled | RegexOptions.IgnoreCase)
|
||||
new Regex(@"api/v[0-9]/notification/readarr/(?<secret>[\w-]+)", RegexOptions.Compiled | RegexOptions.IgnoreCase)
|
||||
};
|
||||
|
||||
private static readonly Regex CleanseRemoteIPRegex = new Regex(@"(?:Auth-\w+(?<!Failure|Unauthorized) ip|from) (\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})", RegexOptions.Compiled);
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace NzbDrone.Core.Test.IndexerSearchTests
|
||||
.Setup(s => s.GetAuthor(It.IsAny<int>()))
|
||||
.Returns(_author);
|
||||
|
||||
Mocker.GetMock<ISearchForReleases>()
|
||||
Mocker.GetMock<ISearchForNzb>()
|
||||
.Setup(s => s.AuthorSearch(_author.Id, false, true, false))
|
||||
.Returns(new List<DownloadDecision>());
|
||||
|
||||
@@ -45,7 +45,7 @@ namespace NzbDrone.Core.Test.IndexerSearchTests
|
||||
|
||||
Subject.Execute(new AuthorSearchCommand { AuthorId = _author.Id, Trigger = CommandTrigger.Manual });
|
||||
|
||||
Mocker.GetMock<ISearchForReleases>()
|
||||
Mocker.GetMock<ISearchForNzb>()
|
||||
.Verify(v => v.AuthorSearch(_author.Id, false, true, false),
|
||||
Times.Exactly(_author.Books.Value.Count(s => s.Monitored)));
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
using NzbDrone.Common.Disk;
|
||||
using NzbDrone.Core.Download.Clients.Sabnzbd.JsonConverters;
|
||||
@@ -7,14 +7,10 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
|
||||
{
|
||||
public class SabnzbdConfig
|
||||
{
|
||||
public SabnzbdConfig()
|
||||
{
|
||||
Categories = new List<SabnzbdCategory>();
|
||||
Servers = new List<object>();
|
||||
}
|
||||
|
||||
public SabnzbdConfigMisc Misc { get; set; }
|
||||
|
||||
public List<SabnzbdCategory> Categories { get; set; }
|
||||
|
||||
public List<object> Servers { get; set; }
|
||||
}
|
||||
|
||||
|
||||
@@ -7,22 +7,22 @@ namespace NzbDrone.Core.IndexerSearch
|
||||
{
|
||||
public class AuthorSearchService : IExecute<AuthorSearchCommand>
|
||||
{
|
||||
private readonly ISearchForReleases _releaseSearchService;
|
||||
private readonly ISearchForNzb _nzbSearchService;
|
||||
private readonly IProcessDownloadDecisions _processDownloadDecisions;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public AuthorSearchService(ISearchForReleases releaseSearchService,
|
||||
public AuthorSearchService(ISearchForNzb nzbSearchService,
|
||||
IProcessDownloadDecisions processDownloadDecisions,
|
||||
Logger logger)
|
||||
{
|
||||
_releaseSearchService = releaseSearchService;
|
||||
_nzbSearchService = nzbSearchService;
|
||||
_processDownloadDecisions = processDownloadDecisions;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public void Execute(AuthorSearchCommand message)
|
||||
{
|
||||
var decisions = _releaseSearchService.AuthorSearch(message.AuthorId, false, message.Trigger == CommandTrigger.Manual, false);
|
||||
var decisions = _nzbSearchService.AuthorSearch(message.AuthorId, false, message.Trigger == CommandTrigger.Manual, false);
|
||||
var processed = _processDownloadDecisions.ProcessDecisions(decisions);
|
||||
|
||||
_logger.ProgressInfo("Author search completed. {0} reports downloaded.", processed.Grabbed.Count);
|
||||
|
||||
@@ -17,21 +17,21 @@ namespace NzbDrone.Core.IndexerSearch
|
||||
IExecute<MissingBookSearchCommand>,
|
||||
IExecute<CutoffUnmetBookSearchCommand>
|
||||
{
|
||||
private readonly ISearchForReleases _releaseSearchService;
|
||||
private readonly ISearchForNzb _nzbSearchService;
|
||||
private readonly IBookService _bookService;
|
||||
private readonly IBookCutoffService _bookCutoffService;
|
||||
private readonly IQueueService _queueService;
|
||||
private readonly IProcessDownloadDecisions _processDownloadDecisions;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public BookSearchService(ISearchForReleases releaseSearchService,
|
||||
public BookSearchService(ISearchForNzb nzbSearchService,
|
||||
IBookService bookService,
|
||||
IBookCutoffService bookCutoffService,
|
||||
IQueueService queueService,
|
||||
IProcessDownloadDecisions processDownloadDecisions,
|
||||
Logger logger)
|
||||
{
|
||||
_releaseSearchService = releaseSearchService;
|
||||
_nzbSearchService = nzbSearchService;
|
||||
_bookService = bookService;
|
||||
_bookCutoffService = bookCutoffService;
|
||||
_queueService = queueService;
|
||||
@@ -47,7 +47,7 @@ namespace NzbDrone.Core.IndexerSearch
|
||||
foreach (var book in books)
|
||||
{
|
||||
List<DownloadDecision> decisions;
|
||||
decisions = _releaseSearchService.BookSearch(book.Id, false, userInvokedSearch, false);
|
||||
decisions = _nzbSearchService.BookSearch(book.Id, false, userInvokedSearch, false);
|
||||
var processed = _processDownloadDecisions.ProcessDecisions(decisions);
|
||||
|
||||
downloadedCount += processed.Grabbed.Count;
|
||||
@@ -61,7 +61,7 @@ namespace NzbDrone.Core.IndexerSearch
|
||||
foreach (var bookId in message.BookIds)
|
||||
{
|
||||
var decisions =
|
||||
_releaseSearchService.BookSearch(bookId, false, message.Trigger == CommandTrigger.Manual, false);
|
||||
_nzbSearchService.BookSearch(bookId, false, message.Trigger == CommandTrigger.Manual, false);
|
||||
var processed = _processDownloadDecisions.ProcessDecisions(decisions);
|
||||
|
||||
_logger.ProgressInfo("Book search completed. {0} reports downloaded.", processed.Grabbed.Count);
|
||||
|
||||
@@ -14,13 +14,13 @@ using NzbDrone.Core.Parser.Model;
|
||||
|
||||
namespace NzbDrone.Core.IndexerSearch
|
||||
{
|
||||
public interface ISearchForReleases
|
||||
public interface ISearchForNzb
|
||||
{
|
||||
List<DownloadDecision> BookSearch(int bookId, bool missingOnly, bool userInvokedSearch, bool interactiveSearch);
|
||||
List<DownloadDecision> AuthorSearch(int authorId, bool missingOnly, bool userInvokedSearch, bool interactiveSearch);
|
||||
}
|
||||
|
||||
public class ReleaseSearchService : ISearchForReleases
|
||||
public class NzbSearchService : ISearchForNzb
|
||||
{
|
||||
private readonly IIndexerFactory _indexerFactory;
|
||||
private readonly IBookService _bookService;
|
||||
@@ -28,7 +28,7 @@ namespace NzbDrone.Core.IndexerSearch
|
||||
private readonly IMakeDownloadDecision _makeDownloadDecision;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public ReleaseSearchService(IIndexerFactory indexerFactory,
|
||||
public NzbSearchService(IIndexerFactory indexerFactory,
|
||||
IBookService bookService,
|
||||
IAuthorService authorService,
|
||||
IMakeDownloadDecision makeDownloadDecision,
|
||||
17
src/NzbDrone.Core/Indexers/IndexerSettingUpdatedEvent.cs
Normal file
17
src/NzbDrone.Core/Indexers/IndexerSettingUpdatedEvent.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using NzbDrone.Common.Messaging;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
|
||||
namespace NzbDrone.Core.Indexers
|
||||
{
|
||||
public class IndexerSettingUpdatedEvent : IEvent
|
||||
{
|
||||
public string IndexerName { get; private set; }
|
||||
public IProviderConfig IndexerSetting { get; private set; }
|
||||
|
||||
public IndexerSettingUpdatedEvent(string indexerName, IProviderConfig indexerSetting)
|
||||
{
|
||||
IndexerName = indexerName;
|
||||
IndexerSetting = indexerSetting;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,6 @@ using NzbDrone.Core.Datastore;
|
||||
using NzbDrone.Core.Download.Clients;
|
||||
using NzbDrone.Core.Messaging.Events;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Core.ThingiProvider.Events;
|
||||
|
||||
namespace NzbDrone.Core.Indexers
|
||||
{
|
||||
@@ -14,7 +13,7 @@ namespace NzbDrone.Core.Indexers
|
||||
TorrentSeedConfiguration GetSeedConfiguration(int indexerId, bool fullSeason);
|
||||
}
|
||||
|
||||
public class SeedConfigProvider : ISeedConfigProvider, IHandle<ProviderUpdatedEvent<IIndexer>>
|
||||
public class SeedConfigProvider : ISeedConfigProvider, IHandle<IndexerSettingUpdatedEvent>
|
||||
{
|
||||
private readonly IIndexerFactory _indexerFactory;
|
||||
private readonly ICached<SeedCriteriaSettings> _cache;
|
||||
@@ -83,7 +82,7 @@ namespace NzbDrone.Core.Indexers
|
||||
}
|
||||
}
|
||||
|
||||
public void Handle(ProviderUpdatedEvent<IIndexer> message)
|
||||
public void Handle(IndexerSettingUpdatedEvent message)
|
||||
{
|
||||
_cache.Clear();
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
"Cancel": "zrušení",
|
||||
"CancelMessageText": "Opravdu chcete zrušit tento nevyřízený úkol?",
|
||||
"CertificateValidation": "Ověření certifikátu",
|
||||
"CertificateValidationHelpText": "Změňte přísnost ověřování certifikátů HTTPS. Neměňte, pokud nerozumíte rizikům.",
|
||||
"CertificateValidationHelpText": "Změňte, jak přísné je ověření certifikace HTTPS",
|
||||
"ChangeFileDate": "Změnit datum souboru",
|
||||
"ChangeHasNotBeenSavedYet": "Změna ještě nebyla uložena",
|
||||
"ChmodFolder": "Složka chmod",
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
"Cancel": "Abbrechen",
|
||||
"CancelMessageText": "Diese laufende Aufgabe wirklich abbrechen?",
|
||||
"CertificateValidation": "Zertifikat Validierung",
|
||||
"CertificateValidationHelpText": "Ändere wie streng die Validierung der HTTPS-Zertifizierung ist. Ändern Sie nicht wenn Ihnen die Risiken nicht bewusst sind.",
|
||||
"CertificateValidationHelpText": "Ändere wie streng die Validierung der HTTPS-Zertifizierung ist. Nicht anpassen, außer du kennst das Risiko.",
|
||||
"ChangeFileDate": "Erstelldatum der Datei anpassen",
|
||||
"ChangeHasNotBeenSavedYet": "Änderung wurde noch nicht gespeichert",
|
||||
"ChmodFolder": "chmod Ordner",
|
||||
@@ -291,7 +291,7 @@
|
||||
"RemoveFromQueue": "Aus der Warteschlage entfernen",
|
||||
"RemoveHelpTextWarning": "Dies wird den Download und alle bereits heruntergeladenen Dateien aus dem Downloader entfernen.",
|
||||
"RemoveSelected": "Auswahl entfernen",
|
||||
"RemoveSelectedMessageText": "Sind sie sicher, dass die ausgewählten Einträge aus der Sperrliste entfernt werden sollen?",
|
||||
"RemoveSelectedMessageText": "Bist du icher, dass du die ausgewählten Einträge aus der Sperrliste entfernen willst?",
|
||||
"RemoveTagExistingTag": "Vorhandener Tag",
|
||||
"RemoveTagRemovingTag": "Tag entfernen",
|
||||
"RemovedFromTaskQueue": "Aus der Aufgabenwarteschlage entfernt",
|
||||
@@ -301,7 +301,7 @@
|
||||
"RequiredHelpText": "Das Release mus mindesten eines der Begriffe beinhalten ( Groß-/Kleinschreibung wird nicht beachtet )",
|
||||
"RequiredPlaceHolder": "Neue Beschränkung hinzufügen",
|
||||
"RescanAfterRefreshHelpTextWarning": "Wenn nicht \"Immer (Always)\" ausgewählt wird, werden Dateiänderungen nicht automatisch erkannt",
|
||||
"RescanAuthorFolderAfterRefresh": "Nach dem Aktualisieren den Autorordner neu scannen",
|
||||
"RescanAuthorFolderAfterRefresh": "Nach dem aktualisieren den Filmordner neu scannen",
|
||||
"Reset": "Zurücksetzen",
|
||||
"ResetAPIKey": "API-Schlüssel zurücksetzen",
|
||||
"ResetAPIKeyMessageText": "Bist du sicher, dass du den API-Schlüssel zurücksetzen willst?",
|
||||
@@ -349,7 +349,7 @@
|
||||
"ShownAboveEachColumnWhenWeekIsTheActiveView": "Wird in der Wochenansicht über jeder Spalte angezeigt",
|
||||
"Size": " Größe",
|
||||
"SkipFreeSpaceCheck": "Pürfung des freien Speichers überspringen",
|
||||
"SkipFreeSpaceCheckWhenImportingHelpText": "Aktiviere diese Option, wenn es Readarr nicht möglich ist, den freien Speicherplatz des Stammverzeichnises für Autoren zu erkennen",
|
||||
"SkipFreeSpaceCheckWhenImportingHelpText": "Aktiviere dies wenn es nicht möglich ist, den freien Speicherplatz vom Stammverzeichnis zu ermitteln",
|
||||
"SorryThatAuthorCannotBeFound": "Schade, dieser Film kann nicht gefunden werden.",
|
||||
"SorryThatBookCannotBeFound": "Schade, dieser Film kann nicht gefunden werden.",
|
||||
"Source": "Quelle",
|
||||
@@ -426,7 +426,7 @@
|
||||
"UnmonitoredHelpText": "Nicht beobachtete Filme im iCal-Feed einschließen",
|
||||
"UpdateAll": "Alle aktualisieren",
|
||||
"UpdateAutomaticallyHelpText": "Updates automatisch herunteraden und installieren. Es kann weiterhin unter \"System -> Updates\" ein manuelles Update angestoßen werden",
|
||||
"UpdateMechanismHelpText": "Benutze Readarr's Built-In Updater oder ein Script",
|
||||
"UpdateMechanismHelpText": "Benutze den Built-In Updater oder ein Script",
|
||||
"UpdateScriptPathHelpText": "Pfad zu einem benutzerdefinierten Skript, das ein extrahiertes Update-Paket übernimmt und den Rest des Update-Prozesses abwickelt",
|
||||
"Updates": "Updates",
|
||||
"UpgradeAllowedHelpText": "Wenn deaktiviert wird die Qualität nicht verbessert",
|
||||
@@ -702,7 +702,7 @@
|
||||
"ImportListStatusCheckSingleClientMessage": "Listen aufgrund von Fehlern nicht verfügbar: {0}",
|
||||
"ImportMechanismHealthCheckMessage": "Aktiviere die Verarbeitung der abgeschlossenen Downloads",
|
||||
"IndexerRssHealthCheckNoIndexers": "Da keine Indexer mit aktivierter RSS-Synchronisierung aktiviert sind, erfasst Readarr neue Erscheinungen nicht automatisch",
|
||||
"IndexerSearchCheckNoInteractiveMessage": "Keine Indexer mit interaktiver Suche verfügbar, Readarr liefert keine interaktiven Suchergebnisse",
|
||||
"IndexerSearchCheckNoInteractiveMessage": "Keine Indexer mit interaktiver Suche aktiviert, Readarr liefert keine interaktiven Suchergebnisse",
|
||||
"IndexerStatusCheckSingleClientMessage": "Indexer aufgrund von Fehlern nicht verfügbar: {0}",
|
||||
"ChownGroup": "chown Gruppe",
|
||||
"AllowFingerprintingHelpText": "Benutze Fingerabdrücke um die Genauigkeit der Buch Übereinstimmungen zu verbessern",
|
||||
@@ -725,7 +725,7 @@
|
||||
"RemotePathMappingCheckDockerFolderMissing": "Docker erkannt; Downloader {0} speichert Downloads in {1}, aber dieser Ordner scheint nicht im Container zu existieren. Überprüfe die Remote-Pfadzuordnungen und die Container Volume Einstellungen.",
|
||||
"RemotePathMappingCheckFilesGenericPermissions": "Downloader {0} meldet Dateien in {1}, aber Radarr kann dieses Verzeichnis nicht sehen.Möglicherweise müssen die Verzeichnisreche angepasst werden.",
|
||||
"RemotePathMappingCheckFolderPermissions": "Radarr kann das Downloadverzeichnis sehen, aber nicht verarbeiten {0}. Möglicherwiese ein Rechteproblem.",
|
||||
"RemotePathMappingCheckGenericPermissions": "Downloader {0} speichert Downloads in {1}, aber Readarr kann dieses Verzeichnis nicht sehen. Möglicherweise müssen die Verzeichnisrechte angepasst werden.",
|
||||
"RemotePathMappingCheckGenericPermissions": "Downloader {0} speichert Downloads in {1}, aber Radarr kann dieses Verzeichnis nicht sehen. Möglicherweise müssen die Verzeichnisrechte angepasst werden.",
|
||||
"RemotePathMappingCheckLocalWrongOSPath": "Downloader {0} speichert Downloads in {1}, aber dies ist kein valider {2} Pfad. Überprüfe die Downloader Einstellungen.",
|
||||
"Monitor": "Beobachten",
|
||||
"MusicBrainzAuthorID": "MusicBranz Künstler Id",
|
||||
@@ -780,12 +780,12 @@
|
||||
"InstanceNameHelpText": "Instanzname im Browser-Tab und für Syslog-Anwendungsname",
|
||||
"RestartRequiredHelpTextWarning": "Erfordert einen Neustart",
|
||||
"UseCalibreContentServer": "Calibre-Content-Server",
|
||||
"DataExistingBooks": "Beobachte Bücher die Dateien haben oder noch nicht veröffentlicht wurden",
|
||||
"DataFirstBook": "Beobachte das erste Buch. Alle anderen Bücher werden ignoriert",
|
||||
"DataFuturebooks": "Überwachung von Büchern die noch nicht veröffentlicht wurden",
|
||||
"DataMissingBooks": "Beobachte Bücher, die noch keine Dateien haben oder noch nicht veröffentlicht wurden",
|
||||
"DataExistingBooks": "Beobachte Alben die Dateien haben oder noch nicht veröffentlicht wurden",
|
||||
"DataFirstBook": "Beobachte die ersten Alben. Alle anderen Alben werden ignoriert",
|
||||
"DataFuturebooks": "Überwachung von Alben die noch nicht veröffentlicht wurden",
|
||||
"DataMissingBooks": "Beobachte Alben, die noch keine Dateien haben oder noch nicht veröffentlicht wurden",
|
||||
"Test": "Testen",
|
||||
"DataNone": "Es werden keine Bücher beobachtet",
|
||||
"DataNone": "Es werden keine Alben beobachtet",
|
||||
"RenameFiles": "Dateien umbenennen",
|
||||
"LoadingEditionsFailed": "Das Laden der Ausgaben ist fehlgeschlagen",
|
||||
"MissingBooksAuthorMonitored": "Fehlende Bücher (Autoren überwacht)",
|
||||
@@ -795,7 +795,7 @@
|
||||
"MediaManagementSettingsSummary": "Namensgebung, Dateimanagement-Einstellungen und Root-Ordner",
|
||||
"MinimumPopularity": "Mindestpolularität",
|
||||
"MinPagesHelpText": "Bücher mit weniger Seiten als dieses ignorieren",
|
||||
"MinPopularityHelpText": "Popularität ist Durchschnittsbewertung * Anzahl der Stimmen",
|
||||
"MinPopularityHelpText": "Popularität ist Durchschnittsbewertung * Stimmen",
|
||||
"MissingBooks": "Fehlende Bücher",
|
||||
"MonitorAuthor": "Autor überwachen",
|
||||
"MissingBooksAuthorNotMonitored": "Fehlende Bücher (Autor nicht überwacht)",
|
||||
@@ -812,70 +812,5 @@
|
||||
"DataNewAllBooks": "Alle neuen Bücher überwachen",
|
||||
"DataNewBooks": "Alle neuen Bücher, welche nach dem neusten existierenden Buch veröffentlicht werden, überwachen",
|
||||
"DataNewNone": "Keine neuen Bücher überwachen",
|
||||
"MassBookSearchWarning": "Sind Sie sicher, dass Sie eine Massensuche für {0} Bücher starten wollen?",
|
||||
"NoTagsHaveBeenAddedYet": "Es wurden bisher noch keine Tags hinzugefügt. Fügen Sie Tags hinzu um Autoren mit Verzögerunsprofilen, Einschränkungen oder Benachrichtigungen zu verknüpfen. Klicken Sie {0} um mehr über Tags in Readarr herauszufinden.",
|
||||
"OutputFormatHelpText": "Optional kann Calibre aufgefordert werden, beim Import in andere Formate zu konvertieren. Kommagetrennte Liste.",
|
||||
"UsernameHelpText": "Calibre Inhaltsserver Benutzername",
|
||||
"MonitorExistingBooks": "Vorhandene Bücher überwachen",
|
||||
"MonitoringOptionsHelpText": "Welche Bücher sollen überwacht werden nachdem der Autor hinzugefügt wurde (einmalige Anpassung)",
|
||||
"MonitorNewBooks": "Neue Bücher überwachen",
|
||||
"MonitorNewItems": "Neue Bücher überwachen",
|
||||
"MonitorNewItemsHelpText": "Welche neuen Bücher sollen überwacht werden",
|
||||
"NewBooks": "Neue Bücher",
|
||||
"NoHistoryBlocklist": "Keine History Blockliste",
|
||||
"NoName": "Namen nicht anzeigen",
|
||||
"OnAuthorDelete": "Beim Löschen eines Autors",
|
||||
"OnAuthorDeleteHelpText": "Beim Löschen eines Autors",
|
||||
"OnBookDelete": "Beim Löschen eines Buches",
|
||||
"OnBookRetagHelpText": "Bei neu markieren eines Buches",
|
||||
"RefreshBook": "Buch aktualisieren",
|
||||
"SearchBoxPlaceHolder": "z.B Krieg und Frieden, goodreads:656, isbn:067003469X, asin:B00JCDK5ME",
|
||||
"SendMetadataToCalibre": "Metadaten an Calibre senden",
|
||||
"SeriesTotal": "Serie ({0})",
|
||||
"SetReadarrTags": "Setze Readarr Tags",
|
||||
"ShouldMonitorExisting": "Existierende Bücher überwachen",
|
||||
"ShouldMonitorHelpText": "Neue Autoren und Bücher aus dieser Liste überwachen",
|
||||
"ShouldSearchHelpText": "Dursuche Indexer nach neu hinzugefügten Einträgen. Vorsichtig benutzen bei großen Listen.",
|
||||
"SkipSecondarySeriesBooks": "Überspringe Bücher von Sekundarserien",
|
||||
"SpecificBook": "Bestimmtes Buch",
|
||||
"TheFollowingFilesWillBeDeleted": "Die folgenden Dateien werden gelöscht:",
|
||||
"TooManyBooks": "Fehlende oder zu viele Bücher? Ändern oder erstellen Sie ein neues",
|
||||
"TrackTitle": "Track Titel",
|
||||
"UseSslHelpText": "Benutze SSL um mit dem Calibre Inhaltsserver zu verbinden",
|
||||
"WriteMetadataTags": "Schreibe Metadaten Tags",
|
||||
"WriteTagsAll": "Alle Dateien; nur erster Import",
|
||||
"WriteTagsNew": "Nur für neue Downloads",
|
||||
"WriteTagsSync": "Alle Dateien; mit Goodreads synchronisiert bleiben",
|
||||
"SearchForAllCutoffUnmetBooks": "Suche nach allen abgeschnittenen unerfüllten Büchern",
|
||||
"OnBookTagUpdate": "Bei Update eines Buch Tags",
|
||||
"ProfilesSettingsSummary": "Qualität, Metadaten, Verzögerung und Release Profile",
|
||||
"RenameBooks": "Bücher umbenennen",
|
||||
"SearchForNewItems": "Suche nach neuen Einträgen",
|
||||
"SeriesNumber": "Seriennummer",
|
||||
"ShouldMonitorExistingHelpText": "Bücher in dieser Liste welche bereits in Readarr sind überwachen",
|
||||
"SkipBooksWithNoISBNOrASIN": "Überspringe Bücher ohne ISBN oder ASIN",
|
||||
"StatusEndedDeceased": "Verstorben",
|
||||
"UpdateCovers": "Covers aktualisieren",
|
||||
"UpdateCoversHelpText": "Buchcovers in Calibre so einstellen, dass sie mit denen aus Readarr übereinstimmen",
|
||||
"UrlBaseHelpText": "Fügt ein Prefix zur Calibre Url hinzu, z.B http://[host]:[port]/[urlBasis]",
|
||||
"UseSSL": "Benutze SSL",
|
||||
"MonitorBookExistingOnlyWarning": "Dies ist eine einmalige Anpassung der Überwachungseinstellung für jedes Buch. Verwenden Sie die Option unter Autor/Bearbeiten, um festzulegen, was bei neu hinzugefügten Büchern geschieht",
|
||||
"MonitoredHelpText": "Readarr wird das Buch suchen und herunterladen",
|
||||
"MonitoredAuthorIsUnmonitored": "Autor wird nicht überwacht",
|
||||
"MonitoredAuthorIsMonitored": "Autor wird überwacht",
|
||||
"NameLastFirst": "Nachname, Vorname",
|
||||
"NameFirstLast": "Vorname Nachname",
|
||||
"NameStyle": "Autor Namensstil",
|
||||
"NETCore": ".NET Core",
|
||||
"ShowLastBook": "Zeige letztes Buch",
|
||||
"SkipBooksWithMissingReleaseDate": "Überspringe Bücher ohne Erscheinungsdatum",
|
||||
"Monitoring": "Überwachung",
|
||||
"OnBookDeleteHelpText": "Beim Löschen eines Buches",
|
||||
"RefreshAuthor": "Autor aktualisieren",
|
||||
"RefreshInformation": "Informationen aktualisieren",
|
||||
"SearchBook": "Buch suchen",
|
||||
"ShowBookCount": "Zeige Anzahl an Büchern",
|
||||
"SkipPartBooksAndSets": "Überspringe Teilbücher und Sets",
|
||||
"TagsHelpText": "Gilt für Autoren mit mindestens einem passenden Tag. Leer lassen, um auf alle Autoren anzuwenden",
|
||||
"TagsSettingsSummary": "Verwalten von Autoren-, Profil-, Beschränkungs- und Benachrichtigungs-Tags"
|
||||
"MassBookSearchWarning": "Sind Sie sicher, dass Sie eine Massensuche für {0} Bücher starten wollen?"
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
"BackupRetentionHelpText": "Säilytysjaksoa vanhemmat, automaattiset varmuuskopiot poistetaan automaattisesti.",
|
||||
"Backups": "Varmuuskopiointi",
|
||||
"BindAddress": "Sidososoite",
|
||||
"BindAddressHelpText": "Toimiva IPv4-osoite tai '*' (tähti) kaikille yhteyksille.",
|
||||
"BindAddressHelpText": "Toimiva IPv4-osoite tai jokerimerkkinä '*' (tähti) kaikille yhteyksille.",
|
||||
"BindAddressHelpTextWarning": "Käyttöönotto vaatii uudelleenkäynnistyksen.",
|
||||
"BookIsDownloading": "Kirjaa ladataan",
|
||||
"BookIsDownloadingInterp": "Kirjaa ladataan - {0} % {1}",
|
||||
@@ -47,7 +47,7 @@
|
||||
"Cancel": "Peruuta",
|
||||
"CancelMessageText": "Haluatko varmasti perua tämän odottavan tehtävän?",
|
||||
"CertificateValidation": "Varmenteen vahvistus",
|
||||
"CertificateValidationHelpText": "Muuta HTTPS-varmennevahvistuksen tarkkuutta. Älä muuta, jollet ymmärrä tähän liittyviä riskejä.",
|
||||
"CertificateValidationHelpText": "Valitse HTTPS-varmenteen vahvistuksen tarkkuus. Älä muuta, jollet ymmärrä tähän liittyviä riskejä.",
|
||||
"ChangeFileDate": "Muuta tiedoston päiväys",
|
||||
"ChangeHasNotBeenSavedYet": "Muutosta ei ole vielä tallennettu",
|
||||
"ChmodFolder": "chmod-kansio",
|
||||
@@ -141,7 +141,7 @@
|
||||
"Fixed": "Korjattu",
|
||||
"Folder": "Kansio",
|
||||
"Folders": "Kansioiden käsittely",
|
||||
"ForMoreInformationOnTheIndividualDownloadClientsClickOnTheInfoButtons": "Lataustyökalukohtaisia tietoja saat painamalla lisätietopainikkeita.",
|
||||
"ForMoreInformationOnTheIndividualDownloadClientsClickOnTheInfoButtons": "Lue lisää yksittäisistä lataustyökaluista painamalla 'Lisätietoja'.",
|
||||
"ForMoreInformationOnTheIndividualIndexersClickOnTheInfoButtons": "Lue lisää tietolähteestä painamalla 'Lisätietoja'.",
|
||||
"ForMoreInformationOnTheIndividualListsClickOnTheInfoButtons": "Lue lisää tuontilistoista painamalla 'Lisätietoja'.",
|
||||
"GeneralSettings": "Yleiset asetukset",
|
||||
@@ -271,7 +271,7 @@
|
||||
"ReadarrTags": "Radarr-tunnisteet",
|
||||
"Real": "Todellinen",
|
||||
"Reason": "Syy",
|
||||
"RecycleBinCleanupDaysHelpText": "Poista automaattinen tyhjennys käytöstä asettamalla arvoksi '0'.",
|
||||
"RecycleBinCleanupDaysHelpText": "Älä tyhjennä automaattisesti asettamalla arvoksi '0'.",
|
||||
"RecycleBinCleanupDaysHelpTextWarning": "Tässä määritettyä aikaa vanhemmat tiedostot poistetaan roskakorista pysyvästi automaattisesti.",
|
||||
"RecycleBinHelpText": "Pysyvän poiston sijaan kirjatiedostot siirretään tähän kansioon.",
|
||||
"RecyclingBin": "Roskakori",
|
||||
@@ -297,7 +297,7 @@
|
||||
"RemoveTagExistingTag": "Olemassa oleva tunniste",
|
||||
"RemoveTagRemovingTag": "Tunniste poistetaan",
|
||||
"RemovedFromTaskQueue": "Poistettu tehtäväjonosta",
|
||||
"RenameBooksHelpText": "Jos uudelleennimeäminen ei ole käytössä, käytetään nykyistä tiedostonimeä.",
|
||||
"RenameBooksHelpText": "Jos uudelleennimeäminen ei ole käytössä, käytetään olemassa olevaa tiedostonimeä.",
|
||||
"Reorder": "Järjestä uudelleen",
|
||||
"ReplaceIllegalCharacters": "Korvaa kielletyt merkit",
|
||||
"RequiredHelpText": "Julkaisun tulee sisältää ainakin yksi näistä termeistä (kirjainkokoa ei huomioida).",
|
||||
@@ -349,7 +349,7 @@
|
||||
"ShownAboveEachColumnWhenWeekIsTheActiveView": "Näkyy jokaisen sarakkeen yläpuolella käytettäessä viikkonäkymää.",
|
||||
"Size": " Koko",
|
||||
"SkipFreeSpaceCheck": "Ohita vapaan levytilan tarkistus",
|
||||
"SkipFreeSpaceCheckWhenImportingHelpText": "Käytä, kun vapaata tallennustilaa ei tunnisteta kirjailijoiden juurikansiosta.",
|
||||
"SkipFreeSpaceCheckWhenImportingHelpText": "Käytä, kun vapaata tilaa ei tunnisteta kirjailijoidesi pääkansiosta.",
|
||||
"SorryThatAuthorCannotBeFound": "Valitettavasti kirjailijaa ei löydy.",
|
||||
"SorryThatBookCannotBeFound": "Valitettavasti elokuvaa ei löydy.",
|
||||
"Source": "Lähdekoodi",
|
||||
@@ -367,7 +367,7 @@
|
||||
"SuccessMyWorkIsDoneNoFilesToRetag": "Menestys! Työni on valmis, ei nimettäviä tiedostoja.",
|
||||
"SupportsRssvalueRSSIsNotSupportedWithThisIndexer": "RSS-syötettä ei ole käytettävissä tälle tietolähteelle",
|
||||
"SupportsSearchvalueSearchIsNotSupportedWithThisIndexer": "Hakemistoa ei tueta tällä hakemistolla",
|
||||
"SupportsSearchvalueWillBeUsedWhenAutomaticSearchesArePerformedViaTheUIOrByReadarr": "Profiilia käytetään automaattihaun yhteydessä, kun haku suoritetaan käyttöliittymästä tai Readarrin toimesta.",
|
||||
"SupportsSearchvalueWillBeUsedWhenAutomaticSearchesArePerformedViaTheUIOrByReadarr": "Käytetään, kun automaattiset haut suoritetaan käyttöliittymän tai Radarrin kautta",
|
||||
"SupportsSearchvalueWillBeUsedWhenInteractiveSearchIsUsed": "Profiilia käytetään vuorovaikutteisen haun yhteydessä.",
|
||||
"TagIsNotUsedAndCanBeDeleted": "Tunnistetta ei ole määritetty millekään kohteelle, joten sen voi poistaa.",
|
||||
"Tags": "Tunnisteet",
|
||||
@@ -588,10 +588,10 @@
|
||||
"MissingBooks": "Puuttuvat kirjat",
|
||||
"MissingBooksAuthorMonitored": "Puuttuvat kirjat (kirjailijaa valvotaan)",
|
||||
"MissingBooksAuthorNotMonitored": "Puuttuvat kirjat (kirjailijaa ei valvota)",
|
||||
"MonitorBookExistingOnlyWarning": "Tämä on kirjakohtaisen valvonnan kertaluontoinen määritys. Määritä Kirjailija/Muokkaa-valinnalla mitä uusille kirjalisäyksille tehdään.",
|
||||
"MonitorBookExistingOnlyWarning": "Tämä on kirjakohtaisen valvonnan kertaluontoinen määritys. Käytä Kirjailija/Muokkaa-valintaa hallinnoidaksesi mitä uusille kirjalisäyksille tehdään.",
|
||||
"MonitorNewItems": "Valvo uusia kirjoja",
|
||||
"MonitorNewItemsHelpText": "Uusien kirjojen valvontatapa.",
|
||||
"MonitoringOptionsHelpText": "Mitkä kirjat asetetaan valvottaviksi kirjailijan lisäyksen yhteydessä (kertaluontoinen määritys).",
|
||||
"MonitoringOptionsHelpText": "Kansiosta löydetyille kirjailijoille oletusarvoisesti asetettava kirjojen valvontataso (kertaluontoinen määritys).",
|
||||
"OutputFormatHelpText": "Voit halutessasi pyytää Calibrea muuntamaan kirjat eri muotoihin tuonnin yhteydessä. Pilkulla eroteltu lista.",
|
||||
"PasswordHelpText": "Calibre-sisältöpalvelimen salasana.",
|
||||
"PortHelpText": "Calibre-sisältöpalvelimen portti.",
|
||||
|
||||
@@ -9,7 +9,6 @@ using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Common.Processes;
|
||||
using NzbDrone.Common.Serializer;
|
||||
using NzbDrone.Core.Books;
|
||||
using NzbDrone.Core.HealthCheck;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
using NzbDrone.Core.Validation;
|
||||
|
||||
@@ -206,7 +205,7 @@ namespace NzbDrone.Core.Notifications.CustomScript
|
||||
var environmentVariables = new StringDictionary();
|
||||
|
||||
environmentVariables.Add("Readarr_EventType", "HealthIssue");
|
||||
environmentVariables.Add("Readarr_Health_Issue_Level", Enum.GetName(typeof(HealthCheckResult), healthCheck.Type));
|
||||
environmentVariables.Add("Readarr_Health_Issue_Level", nameof(healthCheck.Type));
|
||||
environmentVariables.Add("Readarr_Health_Issue_Message", healthCheck.Message);
|
||||
environmentVariables.Add("Readarr_Health_Issue_Type", healthCheck.Source.Name);
|
||||
environmentVariables.Add("Readarr_Health_Issue_Wiki", healthCheck.WikiUrl.ToString() ?? string.Empty);
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Net;
|
||||
using FluentValidation.Results;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Common.EnvironmentInfo;
|
||||
using NzbDrone.Common.Http;
|
||||
using NzbDrone.Core.Configuration;
|
||||
|
||||
namespace NzbDrone.Core.Notifications.Notifiarr
|
||||
{
|
||||
@@ -16,21 +17,27 @@ namespace NzbDrone.Core.Notifications.Notifiarr
|
||||
|
||||
public class NotifiarrProxy : INotifiarrProxy
|
||||
{
|
||||
private const string URL = "https://notifiarr.com";
|
||||
private const string URL = "https://notifiarr.com/notifier.php";
|
||||
private readonly IHttpClient _httpClient;
|
||||
private readonly IConfigFileProvider _configFileProvider;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public NotifiarrProxy(IHttpClient httpClient, IConfigFileProvider configFileProvider, Logger logger)
|
||||
public NotifiarrProxy(IHttpClient httpClient, Logger logger)
|
||||
{
|
||||
_httpClient = httpClient;
|
||||
_configFileProvider = configFileProvider;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public void SendNotification(StringDictionary message, NotifiarrSettings settings)
|
||||
{
|
||||
try
|
||||
{
|
||||
ProcessNotification(message, settings);
|
||||
}
|
||||
catch (NotifiarrException ex)
|
||||
{
|
||||
_logger.Error(ex, "Unable to send notification");
|
||||
throw new NotifiarrException("Unable to send notification");
|
||||
}
|
||||
}
|
||||
|
||||
public ValidationFailure Test(NotifiarrSettings settings)
|
||||
@@ -43,14 +50,21 @@ namespace NzbDrone.Core.Notifications.Notifiarr
|
||||
SendNotification(variables, settings);
|
||||
return null;
|
||||
}
|
||||
catch (NotifiarrException ex)
|
||||
catch (HttpException ex)
|
||||
{
|
||||
return new ValidationFailure("APIKey", ex.Message);
|
||||
if (ex.Response.StatusCode == HttpStatusCode.Unauthorized)
|
||||
{
|
||||
_logger.Error(ex, "API key is invalid: " + ex.Message);
|
||||
return new ValidationFailure("APIKey", "API key is invalid");
|
||||
}
|
||||
|
||||
_logger.Error(ex, "Unable to send test message: " + ex.Message);
|
||||
return new ValidationFailure("APIKey", "Unable to send test notification");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, ex.Message);
|
||||
return new ValidationFailure("", "Unable to send test notification. Check the log for more details.");
|
||||
_logger.Error(ex, "Unable to send test notification: " + ex.Message);
|
||||
return new ValidationFailure("", "Unable to send test notification");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,10 +72,8 @@ namespace NzbDrone.Core.Notifications.Notifiarr
|
||||
{
|
||||
try
|
||||
{
|
||||
var instanceName = _configFileProvider.InstanceName;
|
||||
var requestBuilder = new HttpRequestBuilder(URL + "/api/v1/notification/readarr").Post();
|
||||
requestBuilder.AddFormParameter("instanceName", instanceName).Build();
|
||||
requestBuilder.SetHeader("X-API-Key", settings.APIKey);
|
||||
var requestBuilder = new HttpRequestBuilder(URL).Post();
|
||||
requestBuilder.AddFormParameter("api", settings.APIKey).Build();
|
||||
|
||||
foreach (string key in message.Keys)
|
||||
{
|
||||
@@ -74,31 +86,13 @@ namespace NzbDrone.Core.Notifications.Notifiarr
|
||||
}
|
||||
catch (HttpException ex)
|
||||
{
|
||||
var responseCode = ex.Response.StatusCode;
|
||||
switch ((int)responseCode)
|
||||
if (ex.Response.StatusCode == HttpStatusCode.BadRequest)
|
||||
{
|
||||
case 401:
|
||||
_logger.Error("Unauthorized", "HTTP 401 - API key is invalid");
|
||||
throw new NotifiarrException("API key is invalid");
|
||||
case 400:
|
||||
_logger.Error("Invalid Request", "HTTP 400 - Unable to send notification. Ensure Readarr Integration is enabled & assigned a channel on Notifiarr");
|
||||
throw new NotifiarrException("Unable to send notification. Ensure Readarr Integration is enabled & assigned a channel on Notifiarr");
|
||||
case 502:
|
||||
case 503:
|
||||
case 504:
|
||||
_logger.Error("Service Unavailable", "Unable to send notification. Service Unavailable");
|
||||
throw new NotifiarrException("Unable to send notification. Service Unavailable", ex);
|
||||
case 520:
|
||||
case 521:
|
||||
case 522:
|
||||
case 523:
|
||||
case 524:
|
||||
_logger.Error(ex, "Cloudflare Related HTTP Error - Unable to send notification");
|
||||
throw new NotifiarrException("Cloudflare Related HTTP Error - Unable to send notification", ex);
|
||||
default:
|
||||
_logger.Error(ex, "Unknown HTTP Error - Unable to send notification");
|
||||
throw new NotifiarrException("Unknown HTTP Error - Unable to send notification", ex);
|
||||
_logger.Error(ex, "API key is invalid");
|
||||
throw;
|
||||
}
|
||||
|
||||
throw new NotifiarrException("Unable to send notification", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using FluentValidation.Results;
|
||||
using NzbDrone.Common.Extensions;
|
||||
|
||||
namespace NzbDrone.Core.Notifications.Ntfy
|
||||
{
|
||||
public class Ntfy : NotificationBase<NtfySettings>
|
||||
{
|
||||
private readonly INtfyProxy _proxy;
|
||||
|
||||
public Ntfy(INtfyProxy proxy)
|
||||
{
|
||||
_proxy = proxy;
|
||||
}
|
||||
|
||||
public override string Name => "ntfy.sh";
|
||||
|
||||
public override string Link => "https://ntfy.sh/";
|
||||
|
||||
public override void OnGrab(GrabMessage grabMessage)
|
||||
{
|
||||
_proxy.SendNotification(BOOK_GRABBED_TITLE_BRANDED, grabMessage.Message, Settings);
|
||||
}
|
||||
|
||||
public override void OnReleaseImport(BookDownloadMessage message)
|
||||
{
|
||||
_proxy.SendNotification(BOOK_DOWNLOADED_TITLE_BRANDED, message.Message, Settings);
|
||||
}
|
||||
|
||||
public override void OnAuthorDelete(AuthorDeleteMessage deleteMessage)
|
||||
{
|
||||
_proxy.SendNotification(AUTHOR_DELETED_TITLE, deleteMessage.Message, Settings);
|
||||
}
|
||||
|
||||
public override void OnBookDelete(BookDeleteMessage deleteMessage)
|
||||
{
|
||||
_proxy.SendNotification(BOOK_DELETED_TITLE, deleteMessage.Message, Settings);
|
||||
}
|
||||
|
||||
public override void OnBookFileDelete(BookFileDeleteMessage deleteMessage)
|
||||
{
|
||||
_proxy.SendNotification(BOOK_FILE_DELETED_TITLE, deleteMessage.Message, Settings);
|
||||
}
|
||||
|
||||
public override void OnHealthIssue(HealthCheck.HealthCheck healthCheck)
|
||||
{
|
||||
_proxy.SendNotification(HEALTH_ISSUE_TITLE_BRANDED, healthCheck.Message, Settings);
|
||||
}
|
||||
|
||||
public override ValidationResult Test()
|
||||
{
|
||||
var failures = new List<ValidationFailure>();
|
||||
|
||||
failures.AddIfNotNull(_proxy.Test(Settings));
|
||||
|
||||
return new ValidationResult(failures);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
using System;
|
||||
using NzbDrone.Common.Exceptions;
|
||||
|
||||
namespace NzbDrone.Core.Notifications.Ntfy
|
||||
{
|
||||
public class NtfyException : NzbDroneException
|
||||
{
|
||||
public NtfyException(string message)
|
||||
: base(message)
|
||||
{
|
||||
}
|
||||
|
||||
public NtfyException(string message, Exception innerException, params object[] args)
|
||||
: base(message, innerException, args)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
namespace NzbDrone.Core.Notifications.Ntfy
|
||||
{
|
||||
public enum NtfyPriority
|
||||
{
|
||||
Min = 1,
|
||||
Low = 2,
|
||||
Default = 3,
|
||||
High = 4,
|
||||
Max = 5
|
||||
}
|
||||
}
|
||||
@@ -1,137 +0,0 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using FluentValidation.Results;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Common.Http;
|
||||
|
||||
namespace NzbDrone.Core.Notifications.Ntfy
|
||||
{
|
||||
public interface INtfyProxy
|
||||
{
|
||||
void SendNotification(string title, string message, NtfySettings settings);
|
||||
|
||||
ValidationFailure Test(NtfySettings settings);
|
||||
}
|
||||
|
||||
public class NtfyProxy : INtfyProxy
|
||||
{
|
||||
private const string DEFAULT_PUSH_URL = "https://ntfy.sh";
|
||||
|
||||
private readonly IHttpClient _httpClient;
|
||||
|
||||
private readonly Logger _logger;
|
||||
|
||||
public NtfyProxy(IHttpClient httpClient, Logger logger)
|
||||
{
|
||||
_httpClient = httpClient;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public void SendNotification(string title, string message, NtfySettings settings)
|
||||
{
|
||||
var error = false;
|
||||
|
||||
var serverUrl = settings.ServerUrl.IsNullOrWhiteSpace() ? NtfyProxy.DEFAULT_PUSH_URL : settings.ServerUrl;
|
||||
|
||||
foreach (var topic in settings.Topics)
|
||||
{
|
||||
var request = BuildTopicRequest(serverUrl, topic);
|
||||
|
||||
try
|
||||
{
|
||||
SendNotification(title, message, request, settings);
|
||||
}
|
||||
catch (NtfyException ex)
|
||||
{
|
||||
_logger.Error(ex, "Unable to send test message to {0}", topic);
|
||||
error = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (error)
|
||||
{
|
||||
throw new NtfyException("Unable to send Ntfy notifications to all topics");
|
||||
}
|
||||
}
|
||||
|
||||
private HttpRequestBuilder BuildTopicRequest(string serverUrl, string topic)
|
||||
{
|
||||
var trimServerUrl = serverUrl.TrimEnd('/');
|
||||
|
||||
var requestBuilder = new HttpRequestBuilder($"{trimServerUrl}/{topic}").Post();
|
||||
|
||||
return requestBuilder;
|
||||
}
|
||||
|
||||
public ValidationFailure Test(NtfySettings settings)
|
||||
{
|
||||
try
|
||||
{
|
||||
const string title = "Radarr - Test Notification";
|
||||
|
||||
const string body = "This is a test message from Readarr";
|
||||
|
||||
SendNotification(title, body, settings);
|
||||
}
|
||||
catch (HttpException ex)
|
||||
{
|
||||
if (ex.Response.StatusCode == HttpStatusCode.Unauthorized || ex.Response.StatusCode == HttpStatusCode.Forbidden)
|
||||
{
|
||||
_logger.Error(ex, "Authorization is required");
|
||||
return new ValidationFailure("UserName", "Authorization is required");
|
||||
}
|
||||
|
||||
_logger.Error(ex, "Unable to send test message");
|
||||
return new ValidationFailure("ServerUrl", "Unable to send test message");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, "Unable to send test message");
|
||||
return new ValidationFailure("", "Unable to send test message");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void SendNotification(string title, string message, HttpRequestBuilder requestBuilder, NtfySettings settings)
|
||||
{
|
||||
try
|
||||
{
|
||||
requestBuilder.Headers.Add("X-Title", title);
|
||||
requestBuilder.Headers.Add("X-Message", message);
|
||||
requestBuilder.Headers.Add("X-Priority", settings.Priority.ToString());
|
||||
|
||||
if (settings.Tags.Any())
|
||||
{
|
||||
requestBuilder.Headers.Add("X-Tags", settings.Tags.Join(","));
|
||||
}
|
||||
|
||||
if (!settings.ClickUrl.IsNullOrWhiteSpace())
|
||||
{
|
||||
requestBuilder.Headers.Add("X-Click", settings.ClickUrl);
|
||||
}
|
||||
|
||||
var request = requestBuilder.Build();
|
||||
|
||||
if (!settings.UserName.IsNullOrWhiteSpace() && !settings.Password.IsNullOrWhiteSpace())
|
||||
{
|
||||
request.Credentials = new BasicNetworkCredential(settings.UserName, settings.Password);
|
||||
}
|
||||
|
||||
_httpClient.Execute(request);
|
||||
}
|
||||
catch (HttpException ex)
|
||||
{
|
||||
if (ex.Response.StatusCode == HttpStatusCode.Unauthorized || ex.Response.StatusCode == HttpStatusCode.Forbidden)
|
||||
{
|
||||
_logger.Error(ex, "Authorization is required");
|
||||
throw;
|
||||
}
|
||||
|
||||
throw new NtfyException("Unable to send text message: {0}", ex, ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using FluentValidation;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
using NzbDrone.Core.Validation;
|
||||
|
||||
namespace NzbDrone.Core.Notifications.Ntfy
|
||||
{
|
||||
public class NtfySettingsValidator : AbstractValidator<NtfySettings>
|
||||
{
|
||||
public NtfySettingsValidator()
|
||||
{
|
||||
RuleFor(c => c.Topics).NotEmpty();
|
||||
RuleFor(c => c.Priority).InclusiveBetween(1, 5);
|
||||
RuleFor(c => c.ServerUrl).IsValidUrl().When(c => !c.ServerUrl.IsNullOrWhiteSpace());
|
||||
RuleFor(c => c.ClickUrl).IsValidUrl().When(c => !c.ClickUrl.IsNullOrWhiteSpace());
|
||||
RuleFor(c => c.UserName).NotEmpty().When(c => !c.Password.IsNullOrWhiteSpace());
|
||||
RuleFor(c => c.Password).NotEmpty().When(c => !c.UserName.IsNullOrWhiteSpace());
|
||||
RuleForEach(c => c.Topics).NotEmpty().Matches("[a-zA-Z0-9_-]+").Must(c => !InvalidTopics.Contains(c)).WithMessage("Invalid topic");
|
||||
}
|
||||
|
||||
private static List<string> InvalidTopics => new List<string> { "announcements", "app", "docs", "settings", "stats", "mytopic-rw", "mytopic-ro", "mytopic-wo" };
|
||||
}
|
||||
|
||||
public class NtfySettings : IProviderConfig
|
||||
{
|
||||
private static readonly NtfySettingsValidator Validator = new NtfySettingsValidator();
|
||||
|
||||
public NtfySettings()
|
||||
{
|
||||
Topics = Array.Empty<string>();
|
||||
Priority = 3;
|
||||
}
|
||||
|
||||
[FieldDefinition(0, Label = "Server Url", Type = FieldType.Url, HelpLink = "https://ntfy.sh/docs/install/", HelpText = "Leave blank to use public server (https://ntfy.sh)")]
|
||||
public string ServerUrl { get; set; }
|
||||
|
||||
[FieldDefinition(1, Label = "User Name", HelpText = "Optional Authorization", Privacy = PrivacyLevel.UserName)]
|
||||
public string UserName { get; set; }
|
||||
|
||||
[FieldDefinition(2, Label = "Password", Type = FieldType.Password, HelpText = "Optional Password", Privacy = PrivacyLevel.Password)]
|
||||
public string Password { get; set; }
|
||||
|
||||
[FieldDefinition(3, Label = "Priority", Type = FieldType.Select, SelectOptions = typeof(NtfyPriority))]
|
||||
public int Priority { get; set; }
|
||||
|
||||
[FieldDefinition(4, Label = "Topics", HelpText = "List of Topics to send notifications to", Type = FieldType.Tag)]
|
||||
public IEnumerable<string> Topics { get; set; }
|
||||
|
||||
[FieldDefinition(5, Label = "Ntfy Tags and Emojis", Type = FieldType.Tag, HelpText = "Optional list of tags or emojis to use", HelpLink = "https://ntfy.sh/docs/emojis/")]
|
||||
public IEnumerable<string> Tags { get; set; }
|
||||
|
||||
[FieldDefinition(6, Label = "Click Url", Type = FieldType.Url, HelpText = "Optional link when user clicks notification")]
|
||||
public string ClickUrl { get; set; }
|
||||
|
||||
public NzbDroneValidationResult Validate()
|
||||
{
|
||||
return new NzbDroneValidationResult(Validator.Validate(this));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,8 +17,6 @@ using NzbDrone.Common.Serializer;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.Datastore;
|
||||
using NzbDrone.Core.Instrumentation;
|
||||
using NzbDrone.Core.Lifecycle;
|
||||
using NzbDrone.Core.Messaging.Events;
|
||||
using NzbDrone.Host.AccessControl;
|
||||
using NzbDrone.Http.Authentication;
|
||||
using NzbDrone.SignalR;
|
||||
@@ -134,7 +132,6 @@ namespace NzbDrone.Host
|
||||
IConfigFileProvider configFileProvider,
|
||||
IRuntimeInfo runtimeInfo,
|
||||
IFirewallAdapter firewallAdapter,
|
||||
IEventAggregator eventAggregator,
|
||||
ReadarrErrorPipeline errorHandler)
|
||||
{
|
||||
initializeLogger.Initialize();
|
||||
@@ -157,8 +154,6 @@ namespace NzbDrone.Host
|
||||
Console.CancelKeyPress += (sender, eventArgs) => NLog.LogManager.Configuration = null;
|
||||
}
|
||||
|
||||
eventAggregator.PublishEvent(new ApplicationStartingEvent());
|
||||
|
||||
if (OsInfo.IsWindows && runtimeInfo.IsAdmin)
|
||||
{
|
||||
firewallAdapter.MakeAccessible();
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net6.0</TargetFrameworks>
|
||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="NLog" />
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net6.0</TargetFrameworks>
|
||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="NLog" />
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace Readarr.Api.V1.Indexers
|
||||
public class ReleaseController : ReleaseControllerBase
|
||||
{
|
||||
private readonly IFetchAndParseRss _rssFetcherAndParser;
|
||||
private readonly ISearchForReleases _releaseSearchService;
|
||||
private readonly ISearchForNzb _nzbSearchService;
|
||||
private readonly IMakeDownloadDecision _downloadDecisionMaker;
|
||||
private readonly IPrioritizeDownloadDecision _prioritizeDownloadDecision;
|
||||
private readonly IDownloadService _downloadService;
|
||||
@@ -36,7 +36,7 @@ namespace Readarr.Api.V1.Indexers
|
||||
private readonly ICached<RemoteBook> _remoteBookCache;
|
||||
|
||||
public ReleaseController(IFetchAndParseRss rssFetcherAndParser,
|
||||
ISearchForReleases releaseSearchService,
|
||||
ISearchForNzb nzbSearchService,
|
||||
IMakeDownloadDecision downloadDecisionMaker,
|
||||
IPrioritizeDownloadDecision prioritizeDownloadDecision,
|
||||
IDownloadService downloadService,
|
||||
@@ -47,7 +47,7 @@ namespace Readarr.Api.V1.Indexers
|
||||
Logger logger)
|
||||
{
|
||||
_rssFetcherAndParser = rssFetcherAndParser;
|
||||
_releaseSearchService = releaseSearchService;
|
||||
_nzbSearchService = nzbSearchService;
|
||||
_downloadDecisionMaker = downloadDecisionMaker;
|
||||
_prioritizeDownloadDecision = prioritizeDownloadDecision;
|
||||
_downloadService = downloadService;
|
||||
@@ -155,7 +155,7 @@ namespace Readarr.Api.V1.Indexers
|
||||
{
|
||||
try
|
||||
{
|
||||
var decisions = _releaseSearchService.BookSearch(bookId, true, true, true);
|
||||
var decisions = _nzbSearchService.BookSearch(bookId, true, true, true);
|
||||
var prioritizedDecisions = _prioritizeDownloadDecision.PrioritizeDecisions(decisions);
|
||||
|
||||
return MapDecisions(prioritizedDecisions);
|
||||
@@ -171,7 +171,7 @@ namespace Readarr.Api.V1.Indexers
|
||||
{
|
||||
try
|
||||
{
|
||||
var decisions = _releaseSearchService.AuthorSearch(authorId, false, true, true);
|
||||
var decisions = _nzbSearchService.AuthorSearch(authorId, false, true, true);
|
||||
var prioritizedDecisions = _prioritizeDownloadDecision.PrioritizeDecisions(decisions);
|
||||
|
||||
return MapDecisions(prioritizedDecisions);
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Readarr.Http
|
||||
{
|
||||
public class ApiInfoController : Controller
|
||||
{
|
||||
public ApiInfoController()
|
||||
{
|
||||
}
|
||||
|
||||
[HttpGet("/api")]
|
||||
[Produces("application/json")]
|
||||
public ApiInfoResource GetApiInfo()
|
||||
{
|
||||
return new ApiInfoResource
|
||||
{
|
||||
Current = "v1",
|
||||
Deprecated = new List<string>()
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Readarr.Http
|
||||
{
|
||||
public class ApiInfoResource
|
||||
{
|
||||
public string Current { get; set; }
|
||||
public List<string> Deprecated { get; set; }
|
||||
}
|
||||
}
|
||||
13
yarn.lock
13
yarn.lock
@@ -3277,11 +3277,6 @@ eslint-plugin-import@2.23.4:
|
||||
resolve "^1.20.0"
|
||||
tsconfig-paths "^3.9.0"
|
||||
|
||||
eslint-plugin-react-hooks@4.6.0:
|
||||
version "4.6.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz#4c3e697ad95b77e93f8646aaa1630c1ba607edd3"
|
||||
integrity sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==
|
||||
|
||||
eslint-plugin-react@7.24.0:
|
||||
version "7.24.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.24.0.tgz#eadedfa351a6f36b490aa17f4fa9b14e842b9eb4"
|
||||
@@ -6056,10 +6051,10 @@ react-clientside-effect@^1.2.5:
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.12.13"
|
||||
|
||||
react-custom-scrollbars-2@4.5.0:
|
||||
version "4.5.0"
|
||||
resolved "https://registry.yarnpkg.com/react-custom-scrollbars-2/-/react-custom-scrollbars-2-4.5.0.tgz#cff18e7368bce9d570aea0be780045eda392c745"
|
||||
integrity sha512-/z0nWAeXfMDr4+OXReTpYd1Atq9kkn4oI3qxq3iMXGQx1EEfwETSqB8HTAvg1X7dEqcCachbny1DRNGlqX5bDQ==
|
||||
react-custom-scrollbars@4.2.1:
|
||||
version "4.2.1"
|
||||
resolved "https://registry.yarnpkg.com/react-custom-scrollbars/-/react-custom-scrollbars-4.2.1.tgz#830fd9502927e97e8a78c2086813899b2a8b66db"
|
||||
integrity sha1-gw/ZUCkn6X6KeMIIaBOJmyqLZts=
|
||||
dependencies:
|
||||
dom-css "^2.0.0"
|
||||
prop-types "^15.5.10"
|
||||
|
||||
Reference in New Issue
Block a user