mirror of
https://github.com/Readarr/Readarr.git
synced 2026-03-30 18:24:45 -04:00
Compare commits
56 Commits
v0.1.7.188
...
v0.2.2.194
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c3c9b9afbb | ||
|
|
f225a742cc | ||
|
|
f4fd36061c | ||
|
|
38e39449aa | ||
|
|
484c255fd4 | ||
|
|
f341b5f449 | ||
|
|
eb5654c634 | ||
|
|
e843046d76 | ||
|
|
ef57545221 | ||
|
|
09d44726a4 | ||
|
|
0e2d39f580 | ||
|
|
dbcb0e77a8 | ||
|
|
0186900a54 | ||
|
|
941b30edac | ||
|
|
5c61b6ceb3 | ||
|
|
55959e1112 | ||
|
|
07451cbcde | ||
|
|
1ebdffcd26 | ||
|
|
75119ce9df | ||
|
|
668dc6dfde | ||
|
|
ee989c9c67 | ||
|
|
acac3bd680 | ||
|
|
3b18f3206d | ||
|
|
fcf057a019 | ||
|
|
c7399cdd2b | ||
|
|
08a3682b89 | ||
|
|
3da00f75dc | ||
|
|
60abb298b2 | ||
|
|
c710b117ab | ||
|
|
816f53b36b | ||
|
|
749684e24a | ||
|
|
3a0ca45aa9 | ||
|
|
595efd498e | ||
|
|
dea1060d61 | ||
|
|
f6049b8bf2 | ||
|
|
53ced38221 | ||
|
|
3a3cf8511e | ||
|
|
9ec913337d | ||
|
|
9a2120ae92 | ||
|
|
818d3a94d5 | ||
|
|
4e493b74e6 | ||
|
|
c7eaf1e85c | ||
|
|
31fe15c911 | ||
|
|
2c36a6c25f | ||
|
|
6af56f7a15 | ||
|
|
6e13191c25 | ||
|
|
921ddfc962 | ||
|
|
22f977401a | ||
|
|
113d9a07ef | ||
|
|
0560d65ea1 | ||
|
|
94ff105104 | ||
|
|
9bcf258aa9 | ||
|
|
54985bd4ca | ||
|
|
9e4d551f08 | ||
|
|
8390da1c2a | ||
|
|
44ae043c58 |
4
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
4
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@@ -76,7 +76,7 @@ body:
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Trace Logs have been provided as applicable. Reports may be closed if the required logs are not provided.
|
||||
description: Trace logs are generally required for all bug reports
|
||||
description: Trace logs are generally required for all bug reports and contain `trace`. Info logs are invalid for bug reports and do not contain `debug` nor `trace`
|
||||
options:
|
||||
- label: I have followed the steps in the wiki link above and provided the required trace logs that are relevant and show this issue.
|
||||
- label: I have read and followed the steps in the wiki link above and provided the required trace logs - the logs contain `trace` - that are relevant and show this issue.
|
||||
required: true
|
||||
|
||||
@@ -9,7 +9,7 @@ variables:
|
||||
testsFolder: './_tests'
|
||||
yarnCacheFolder: $(Pipeline.Workspace)/.yarn
|
||||
nugetCacheFolder: $(Pipeline.Workspace)/.nuget/packages
|
||||
majorVersion: '0.1.7'
|
||||
majorVersion: '0.2.2'
|
||||
minorVersion: $[counter('minorVersion', 1)]
|
||||
readarrVersion: '$(majorVersion).$(minorVersion)'
|
||||
buildName: '$(Build.SourceBranchName).$(readarrVersion)'
|
||||
@@ -382,7 +382,7 @@ stages:
|
||||
- bash: |
|
||||
echo "Uploading source maps to sentry"
|
||||
curl -sL https://sentry.io/get-cli/ | bash
|
||||
RELEASENAME="${READARRVERSION}-${BUILD_SOURCEBRANCHNAME}"
|
||||
RELEASENAME="Readarr@${READARRVERSION}-${BUILD_SOURCEBRANCHNAME}"
|
||||
sentry-cli releases new --finalize -p readarr -p readarr-ui -p readarr-update "${RELEASENAME}"
|
||||
sentry-cli releases -p readarr-ui files "${RELEASENAME}" upload-sourcemaps _output/UI/ --rewrite
|
||||
sentry-cli releases set-commits --auto "${RELEASENAME}"
|
||||
@@ -984,7 +984,7 @@ stages:
|
||||
git status
|
||||
if git status | grep modified
|
||||
then
|
||||
git commit -am 'Automated API Docs update'
|
||||
git commit -am 'Automated API Docs update [skip ci]'
|
||||
git push -f --set-upstream origin api-docs
|
||||
curl -X POST -H "Authorization: token ${GITHUBTOKEN}" -H "Accept: application/vnd.github.v3+json" https://api.github.com/repos/readarr/readarr/pulls -d '{"head":"api-docs","base":"develop","title":"Update API docs"}'
|
||||
else
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import Alert from 'Components/Alert';
|
||||
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
||||
import ConfirmModal from 'Components/Modal/ConfirmModal';
|
||||
import PageContent from 'Components/Page/PageContent';
|
||||
@@ -161,16 +162,16 @@ class Blocklist extends Component {
|
||||
|
||||
{
|
||||
!isAnyFetching && !!error &&
|
||||
<div>
|
||||
<Alert kind={kinds.DANGER}>
|
||||
{translate('UnableToLoadBlocklist')}
|
||||
</div>
|
||||
</Alert>
|
||||
}
|
||||
|
||||
{
|
||||
isAllPopulated && !error && !items.length &&
|
||||
<div>
|
||||
<Alert kind={kinds.INFO}>
|
||||
{translate('NoHistoryBlocklist')}
|
||||
</div>
|
||||
</Alert>
|
||||
}
|
||||
|
||||
{
|
||||
@@ -214,7 +215,7 @@ class Blocklist extends Component {
|
||||
isOpen={isConfirmRemoveModalOpen}
|
||||
kind={kinds.DANGER}
|
||||
title={translate('RemoveSelected')}
|
||||
message={translate('RemoveSelectedMessageText')}
|
||||
message={translate('RemoveSelectedItemBlocklistMessageText')}
|
||||
confirmLabel={translate('RemoveSelected')}
|
||||
onConfirm={this.onRemoveSelectedConfirmed}
|
||||
onCancel={this.onConfirmRemoveModalClose}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import Alert from 'Components/Alert';
|
||||
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
||||
import FilterMenu from 'Components/Menu/FilterMenu';
|
||||
import PageContent from 'Components/Page/PageContent';
|
||||
@@ -11,7 +12,7 @@ import Table from 'Components/Table/Table';
|
||||
import TableBody from 'Components/Table/TableBody';
|
||||
import TableOptionsModalWrapper from 'Components/Table/TableOptions/TableOptionsModalWrapper';
|
||||
import TablePager from 'Components/Table/TablePager';
|
||||
import { align, icons } from 'Helpers/Props';
|
||||
import { align, icons, kinds } from 'Helpers/Props';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import HistoryRowConnector from './HistoryRowConnector';
|
||||
|
||||
@@ -85,9 +86,9 @@ class History extends Component {
|
||||
|
||||
{
|
||||
!isFetchingAny && hasError &&
|
||||
<div>
|
||||
<Alert kind={kinds.DANGER}>
|
||||
{translate('UnableToLoadHistory')}
|
||||
</div>
|
||||
</Alert>
|
||||
}
|
||||
|
||||
{
|
||||
@@ -95,9 +96,9 @@ class History extends Component {
|
||||
// wait for the books to populate because they are never coming.
|
||||
|
||||
isPopulated && !hasError && !items.length &&
|
||||
<div>
|
||||
No history found
|
||||
</div>
|
||||
<Alert kind={kinds.INFO}>
|
||||
{translate('NoHistory')}
|
||||
</Alert>
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import _ from 'lodash';
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import Alert from 'Components/Alert';
|
||||
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
||||
import PageContent from 'Components/Page/PageContent';
|
||||
import PageContentBody from 'Components/Page/PageContentBody';
|
||||
@@ -12,7 +13,7 @@ import Table from 'Components/Table/Table';
|
||||
import TableBody from 'Components/Table/TableBody';
|
||||
import TableOptionsModalWrapper from 'Components/Table/TableOptions/TableOptionsModalWrapper';
|
||||
import TablePager from 'Components/Table/TablePager';
|
||||
import { align, icons } from 'Helpers/Props';
|
||||
import { align, icons, kinds } from 'Helpers/Props';
|
||||
import getRemovedItems from 'Utilities/Object/getRemovedItems';
|
||||
import hasDifferentItems from 'Utilities/Object/hasDifferentItems';
|
||||
import translate from 'Utilities/String/translate';
|
||||
@@ -233,17 +234,17 @@ class Queue extends Component {
|
||||
|
||||
{
|
||||
!isRefreshing && hasError ?
|
||||
<div>
|
||||
<Alert kind={kinds.DANGER}>
|
||||
{translate('FailedToLoadQueue')}
|
||||
</div> :
|
||||
</Alert> :
|
||||
null
|
||||
}
|
||||
|
||||
{
|
||||
isAllPopulated && !hasError && !items.length ?
|
||||
<div>
|
||||
<Alert kind={kinds.INFO}>
|
||||
{translate('QueueIsEmpty')}
|
||||
</div> :
|
||||
</Alert> :
|
||||
null
|
||||
}
|
||||
|
||||
|
||||
@@ -124,7 +124,7 @@ class RemoveQueueItemModal extends Component {
|
||||
type={inputTypes.CHECK}
|
||||
name="blocklist"
|
||||
value={blocklist}
|
||||
helpText={translate('BlocklistHelpText')}
|
||||
helpText={translate('BlocklistReleaseHelpText')}
|
||||
onChange={this.onBlocklistChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
@@ -89,12 +89,12 @@ class RemoveQueueItemsModal extends Component {
|
||||
onModalClose={this.onModalClose}
|
||||
>
|
||||
<ModalHeader>
|
||||
Remove Selected Item{selectedCount > 1 ? 's' : ''}
|
||||
{selectedCount > 1 ? translate('RemoveSelectedItems') : translate('RemoveSelectedItem')}
|
||||
</ModalHeader>
|
||||
|
||||
<ModalBody>
|
||||
<div className={styles.message}>
|
||||
Are you sure you want to remove {selectedCount} item{selectedCount > 1 ? 's' : ''} from the queue?
|
||||
{selectedCount > 1 ? translate('RemoveSelectedItemsQueueMessageText', selectedCount) : translate('RemoveSelectedItemQueueMessageText')}
|
||||
</div>
|
||||
|
||||
{
|
||||
@@ -118,14 +118,14 @@ class RemoveQueueItemsModal extends Component {
|
||||
|
||||
<FormGroup>
|
||||
<FormLabel>
|
||||
Add Release{selectedCount > 1 ? 's' : ''} To Blocklist
|
||||
{selectedCount > 1 ? translate('BlocklistReleases') : translate('BlocklistRelease')}
|
||||
</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.CHECK}
|
||||
name="blocklist"
|
||||
value={blocklist}
|
||||
helpText={translate('BlocklistHelpText')}
|
||||
helpText={translate('BlocklistReleaseHelpText')}
|
||||
onChange={this.onBlocklistChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
@@ -150,14 +150,14 @@ class RemoveQueueItemsModal extends Component {
|
||||
|
||||
<ModalFooter>
|
||||
<Button onPress={this.onModalClose}>
|
||||
Close
|
||||
{translate('Close')}
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
kind={kinds.DANGER}
|
||||
onPress={this.onRemoveConfirmed}
|
||||
>
|
||||
Remove
|
||||
{translate('Remove')}
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
</ModalContent>
|
||||
|
||||
@@ -92,6 +92,7 @@ class AuthorDetailsHeader extends Component {
|
||||
titleWidth
|
||||
} = this.state;
|
||||
|
||||
const fanartUrl = getFanartUrl(images);
|
||||
const marqueeWidth = titleWidth - (isSmallScreen ? 85 : 160);
|
||||
|
||||
const continuing = status === 'continuing';
|
||||
@@ -108,9 +109,11 @@ class AuthorDetailsHeader extends Component {
|
||||
<div className={styles.header} style={{ width }} >
|
||||
<div
|
||||
className={styles.backdrop}
|
||||
style={{
|
||||
backgroundImage: `url(${getFanartUrl(images)})`
|
||||
}}
|
||||
style={
|
||||
fanartUrl ?
|
||||
{ backgroundImage: `url(${fanartUrl})` } :
|
||||
null
|
||||
}
|
||||
>
|
||||
<div className={styles.backdropOverlay} />
|
||||
</div>
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import Alert from 'Components/Alert';
|
||||
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
||||
import Table from 'Components/Table/Table';
|
||||
import TableBody from 'Components/Table/TableBody';
|
||||
import { kinds } from 'Helpers/Props';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import AuthorHistoryRowConnector from './AuthorHistoryRowConnector';
|
||||
|
||||
@@ -70,9 +72,9 @@ class AuthorHistoryTableContent extends Component {
|
||||
|
||||
{
|
||||
!isFetching && !!error &&
|
||||
<div>
|
||||
<Alert kind={kinds.DANGER}>
|
||||
{translate('UnableToLoadHistory')}
|
||||
</div>
|
||||
</Alert>
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
@@ -83,15 +83,18 @@ class BookDetailsHeader extends Component {
|
||||
titleWidth
|
||||
} = this.state;
|
||||
|
||||
const fanartUrl = getFanartUrl(author.images);
|
||||
const marqueeWidth = titleWidth - (isSmallScreen ? 85 : 160);
|
||||
|
||||
return (
|
||||
<div className={styles.header} style={{ width }}>
|
||||
<div
|
||||
className={styles.backdrop}
|
||||
style={{
|
||||
backgroundImage: `url(${getFanartUrl(author.images)})`
|
||||
}}
|
||||
style={
|
||||
fanartUrl ?
|
||||
{ backgroundImage: `url(${fanartUrl})` } :
|
||||
null
|
||||
}
|
||||
>
|
||||
<div className={styles.backdropOverlay} />
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import Alert from 'Components/Alert';
|
||||
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
||||
import { kinds } from 'Helpers/Props';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import AgendaConnector from './Agenda/AgendaConnector';
|
||||
import * as calendarViews from './calendarViews';
|
||||
@@ -31,9 +33,9 @@ class Calendar extends Component {
|
||||
|
||||
{
|
||||
!isFetching && !!error &&
|
||||
<div>
|
||||
<Alert kind={kinds.DANGER}>
|
||||
{translate('UnableToLoadTheCalendar')}
|
||||
</div>
|
||||
</Alert>
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
@@ -578,7 +578,7 @@ EnhancedSelectInput.propTypes = {
|
||||
className: PropTypes.string,
|
||||
disabledClassName: PropTypes.string,
|
||||
name: PropTypes.string.isRequired,
|
||||
value: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.arrayOf(PropTypes.number)]).isRequired,
|
||||
value: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.arrayOf(PropTypes.string), PropTypes.arrayOf(PropTypes.number)]).isRequired,
|
||||
values: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
isDisabled: PropTypes.bool.isRequired,
|
||||
isFetching: PropTypes.bool.isRequired,
|
||||
|
||||
@@ -62,6 +62,7 @@ function ProviderFieldFormGroup(props) {
|
||||
name,
|
||||
label,
|
||||
helpText,
|
||||
helpTextWarning,
|
||||
helpLink,
|
||||
placeholder,
|
||||
value,
|
||||
@@ -95,6 +96,7 @@ function ProviderFieldFormGroup(props) {
|
||||
name={name}
|
||||
label={label}
|
||||
helpText={helpText}
|
||||
helpTextWarning={helpTextWarning}
|
||||
helpLink={helpLink}
|
||||
placeholder={placeholder}
|
||||
value={value}
|
||||
@@ -121,6 +123,7 @@ ProviderFieldFormGroup.propTypes = {
|
||||
name: PropTypes.string.isRequired,
|
||||
label: PropTypes.string.isRequired,
|
||||
helpText: PropTypes.string,
|
||||
helpTextWarning: PropTypes.string,
|
||||
helpLink: PropTypes.string,
|
||||
placeholder: PropTypes.string,
|
||||
value: PropTypes.any,
|
||||
|
||||
@@ -26,6 +26,7 @@ function createCleanAuthorSelector() {
|
||||
sortName,
|
||||
titleSlug,
|
||||
images,
|
||||
firstCharacter: authorName.charAt(0).toLowerCase(),
|
||||
tags: tags.reduce((acc, id) => {
|
||||
const matchingTag = allTags.find((tag) => tag.id === id);
|
||||
|
||||
@@ -58,6 +59,7 @@ function createCleanBookSelector() {
|
||||
sortName: title,
|
||||
titleSlug,
|
||||
images,
|
||||
firstCharacter: title.charAt(0).toLowerCase(),
|
||||
tags: []
|
||||
};
|
||||
});
|
||||
|
||||
@@ -15,9 +15,36 @@ const fuseOptions = {
|
||||
|
||||
function getSuggestions(items, value) {
|
||||
const limit = 10;
|
||||
let suggestions = [];
|
||||
|
||||
const fuse = new Fuse(items, fuseOptions);
|
||||
return fuse.search(value, { limit });
|
||||
if (value.length === 1) {
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
const s = items[i];
|
||||
if (s.firstCharacter === value.toLowerCase()) {
|
||||
suggestions.push({
|
||||
item: items[i],
|
||||
indices: [
|
||||
[0, 0]
|
||||
],
|
||||
matches: [
|
||||
{
|
||||
value: s.title,
|
||||
key: 'title'
|
||||
}
|
||||
],
|
||||
arrayIndex: 0
|
||||
});
|
||||
if (suggestions.length > limit) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const fuse = new Fuse(items, fuseOptions);
|
||||
suggestions = fuse.search(value, { limit });
|
||||
}
|
||||
|
||||
return suggestions;
|
||||
}
|
||||
|
||||
onmessage = function(e) {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import Alert from 'Components/Alert';
|
||||
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
||||
import { kinds } from 'Helpers/Props';
|
||||
|
||||
function PageSectionContent(props) {
|
||||
const {
|
||||
@@ -17,7 +19,7 @@ function PageSectionContent(props) {
|
||||
);
|
||||
} else if (!isFetching && !!error) {
|
||||
return (
|
||||
<div>{errorMessage}</div>
|
||||
<Alert kind={kinds.DANGER}>{errorMessage}</Alert>
|
||||
);
|
||||
} else if (isPopulated && !error) {
|
||||
return (
|
||||
|
||||
@@ -16,6 +16,38 @@
|
||||
box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);
|
||||
color: var(--white);
|
||||
transition: width 0.6s ease;
|
||||
|
||||
&.primary {
|
||||
background-color: var(--primaryColor);
|
||||
}
|
||||
|
||||
&.danger {
|
||||
background-color: var(--dangerColor);
|
||||
|
||||
&:global(.colorImpaired) {
|
||||
background: repeating-linear-gradient(90deg, color(#f05050 shade(5%)), color(#f05050 shade(5%)) 5px, color(#f05050 shade(15%)) 5px, color(#f05050 shade(15%)) 10px);
|
||||
}
|
||||
}
|
||||
|
||||
&.success {
|
||||
background-color: var(--successColor);
|
||||
}
|
||||
|
||||
&.purple {
|
||||
background-color: var(--purple);
|
||||
}
|
||||
|
||||
&.warning {
|
||||
background-color: var(--warningColor);
|
||||
|
||||
&:global(.colorImpaired) {
|
||||
background: repeating-linear-gradient(45deg, #ffa500, #ffa500 5px, color(#ffa500 tint(15%)) 5px, color(#ffa500 tint(15%)) 10px);
|
||||
}
|
||||
}
|
||||
|
||||
&.info {
|
||||
background-color: var(--infoColor);
|
||||
}
|
||||
}
|
||||
|
||||
.frontTextContainer {
|
||||
@@ -45,38 +77,6 @@
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.primary {
|
||||
background-color: var(--primaryColor);
|
||||
}
|
||||
|
||||
.danger {
|
||||
background-color: var(--dangerColor);
|
||||
|
||||
&:global(.colorImpaired) {
|
||||
background: repeating-linear-gradient(90deg, color(#f05050 shade(5%)), color(#f05050 shade(5%)) 5px, color(#f05050 shade(15%)) 5px, color(#f05050 shade(15%)) 10px);
|
||||
}
|
||||
}
|
||||
|
||||
.success {
|
||||
background-color: var(--successColor);
|
||||
}
|
||||
|
||||
.purple {
|
||||
background-color: var(--purple);
|
||||
}
|
||||
|
||||
.warning {
|
||||
background-color: var(--warningColor);
|
||||
|
||||
&:global(.colorImpaired) {
|
||||
background: repeating-linear-gradient(45deg, #ffa500, #ffa500 5px, color(#ffa500 tint(15%)) 5px, color(#ffa500 tint(15%)) 10px);
|
||||
}
|
||||
}
|
||||
|
||||
.info {
|
||||
background-color: var(--infoColor);
|
||||
}
|
||||
|
||||
.small {
|
||||
height: $progressBarSmallHeight;
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ function ProgressBar(props) {
|
||||
{
|
||||
showText && width ?
|
||||
<div
|
||||
className={styles.backTextContainer}
|
||||
className={classNames(styles.backTextContainer, styles[kind])}
|
||||
style={{ width: actualWidth }}
|
||||
>
|
||||
<div className={styles.backText}>
|
||||
@@ -67,7 +67,7 @@ function ProgressBar(props) {
|
||||
{
|
||||
showText ?
|
||||
<div
|
||||
className={styles.frontTextContainer}
|
||||
className={classNames(styles.frontTextContainer, styles[kind])}
|
||||
style={{ width: progressPercent }}
|
||||
>
|
||||
<div
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import Alert from 'Components/Alert';
|
||||
import Form from 'Components/Form/Form';
|
||||
import FormGroup from 'Components/Form/FormGroup';
|
||||
import FormInputGroup from 'Components/Form/FormInputGroup';
|
||||
@@ -92,9 +93,9 @@ class SelectQualityModalContent extends Component {
|
||||
|
||||
{
|
||||
!isFetching && !!error &&
|
||||
<div>
|
||||
<Alert kind={kinds.DANGER}>
|
||||
{translate('UnableToLoadQualities')}
|
||||
</div>
|
||||
</Alert>
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
@@ -7,3 +7,9 @@
|
||||
.filteredMessage {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.blankpad {
|
||||
padding-top: 10px;
|
||||
padding-bottom: 10px;
|
||||
padding-left: 2em;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// This file is automatically generated.
|
||||
// Please do not change this file!
|
||||
interface CssExports {
|
||||
'blankpad': string;
|
||||
'filterMenuContainer': string;
|
||||
'filteredMessage': string;
|
||||
}
|
||||
|
||||
@@ -104,7 +104,7 @@ function InteractiveSearch(props) {
|
||||
|
||||
{
|
||||
!isFetching && error ?
|
||||
<div>
|
||||
<div className={styles.blankpad}>
|
||||
Unable to load results for this book search. Try again later
|
||||
</div> :
|
||||
null
|
||||
@@ -112,7 +112,7 @@ function InteractiveSearch(props) {
|
||||
|
||||
{
|
||||
!isFetching && isPopulated && !totalReleasesCount ?
|
||||
<div>
|
||||
<div className={styles.blankpad}>
|
||||
No results found
|
||||
</div> :
|
||||
null
|
||||
@@ -120,7 +120,7 @@ function InteractiveSearch(props) {
|
||||
|
||||
{
|
||||
!!totalReleasesCount && isPopulated && !items.length ?
|
||||
<div>
|
||||
<div className={styles.blankpad}>
|
||||
All results are hidden by the applied filter
|
||||
</div> :
|
||||
null
|
||||
|
||||
@@ -78,7 +78,7 @@ class Specification extends Component {
|
||||
|
||||
<IconButton
|
||||
className={styles.cloneButton}
|
||||
title={translate('Clone')}
|
||||
title={translate('CloneCondition')}
|
||||
name={icons.CLONE}
|
||||
onPress={this.onCloneSpecificationPress}
|
||||
/>
|
||||
@@ -92,14 +92,14 @@ class Specification extends Component {
|
||||
{
|
||||
negate &&
|
||||
<Label kind={kinds.DANGER}>
|
||||
Negated
|
||||
{translate('Negated')}
|
||||
</Label>
|
||||
}
|
||||
|
||||
{
|
||||
required &&
|
||||
<Label kind={kinds.SUCCESS}>
|
||||
Required
|
||||
{translate('Required')}
|
||||
</Label>
|
||||
}
|
||||
</div>
|
||||
@@ -114,8 +114,8 @@ class Specification extends Component {
|
||||
<ConfirmModal
|
||||
isOpen={this.state.isDeleteSpecificationModalOpen}
|
||||
kind={kinds.DANGER}
|
||||
title={translate('DeleteFormat')}
|
||||
message={translate('DeleteFormatMessageText', [name])}
|
||||
title={translate('DeleteCondition')}
|
||||
message={translate('DeleteConditionMessageText', [name])}
|
||||
confirmLabel={translate('Delete')}
|
||||
onConfirm={this.onConfirmDeleteSpecification}
|
||||
onCancel={this.onDeleteSpecificationModalClose}
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import Alert from 'Components/Alert';
|
||||
import FieldSet from 'Components/FieldSet';
|
||||
import Form from 'Components/Form/Form';
|
||||
import FormGroup from 'Components/Form/FormGroup';
|
||||
import FormInputGroup from 'Components/Form/FormInputGroup';
|
||||
import FormLabel from 'Components/Form/FormLabel';
|
||||
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
||||
import { inputTypes, sizes } from 'Helpers/Props';
|
||||
import { inputTypes, kinds, sizes } from 'Helpers/Props';
|
||||
import translate from 'Utilities/String/translate';
|
||||
|
||||
function DownloadClientOptions(props) {
|
||||
@@ -28,9 +29,9 @@ function DownloadClientOptions(props) {
|
||||
|
||||
{
|
||||
!isFetching && error &&
|
||||
<div>
|
||||
<Alert kind={kinds.DANGER}>
|
||||
{translate('UnableToLoadDownloadClientOptions')}
|
||||
</div>
|
||||
</Alert>
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
@@ -88,8 +88,8 @@ class RemotePathMapping extends Component {
|
||||
<ConfirmModal
|
||||
isOpen={this.state.isDeleteRemotePathMappingModalOpen}
|
||||
kind={kinds.DANGER}
|
||||
title={translate('DeleteDelayProfile')}
|
||||
message={translate('DeleteDelayProfileMessageText')}
|
||||
title={translate('DeleteRemotePathMapping')}
|
||||
message={translate('DeleteRemotePathMappingMessageText')}
|
||||
confirmLabel={translate('Delete')}
|
||||
onConfirm={this.onConfirmDeleteRemotePathMapping}
|
||||
onCancel={this.onDeleteRemotePathMappingModalClose}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import _ from 'lodash';
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import Alert from 'Components/Alert';
|
||||
import Form from 'Components/Form/Form';
|
||||
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
||||
import ConfirmModal from 'Components/Modal/ConfirmModal';
|
||||
@@ -124,9 +125,9 @@ class GeneralSettings extends Component {
|
||||
|
||||
{
|
||||
!isFetching && error &&
|
||||
<div>
|
||||
<Alert kind={kinds.DANGER}>
|
||||
{translate('UnableToLoadGeneralSettings')}
|
||||
</div>
|
||||
</Alert>
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import Alert from 'Components/Alert';
|
||||
import FieldSet from 'Components/FieldSet';
|
||||
import Form from 'Components/Form/Form';
|
||||
import FormGroup from 'Components/Form/FormGroup';
|
||||
import FormInputGroup from 'Components/Form/FormInputGroup';
|
||||
import FormLabel from 'Components/Form/FormLabel';
|
||||
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
||||
import { inputTypes } from 'Helpers/Props';
|
||||
import { inputTypes, kinds } from 'Helpers/Props';
|
||||
import translate from 'Utilities/String/translate';
|
||||
|
||||
function IndexerOptions(props) {
|
||||
@@ -28,9 +29,9 @@ function IndexerOptions(props) {
|
||||
|
||||
{
|
||||
!isFetching && error &&
|
||||
<div>
|
||||
<Alert kind={kinds.DANGER}>
|
||||
{translate('UnableToLoadIndexerOptions')}
|
||||
</div>
|
||||
</Alert>
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import Alert from 'Components/Alert';
|
||||
import FieldSet from 'Components/FieldSet';
|
||||
import Form from 'Components/Form/Form';
|
||||
import FormGroup from 'Components/Form/FormGroup';
|
||||
@@ -8,7 +9,7 @@ import FormLabel from 'Components/Form/FormLabel';
|
||||
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
||||
import PageContent from 'Components/Page/PageContent';
|
||||
import PageContentBody from 'Components/Page/PageContentBody';
|
||||
import { inputTypes, sizes } from 'Helpers/Props';
|
||||
import { inputTypes, kinds, sizes } from 'Helpers/Props';
|
||||
import RemotePathMappingsConnector from 'Settings/DownloadClients/RemotePathMappings/RemotePathMappingsConnector';
|
||||
import SettingsToolbarConnector from 'Settings/SettingsToolbarConnector';
|
||||
import translate from 'Utilities/String/translate';
|
||||
@@ -79,9 +80,9 @@ class MediaManagement extends Component {
|
||||
{
|
||||
!isFetching && error &&
|
||||
<FieldSet legend={translate('NamingSettings')}>
|
||||
<div>
|
||||
<Alert kind={kinds.DANGER}>
|
||||
{translate('UnableToLoadMediaManagementSettings')}
|
||||
</div>
|
||||
</Alert>
|
||||
</FieldSet>
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import Alert from 'Components/Alert';
|
||||
import FieldSet from 'Components/FieldSet';
|
||||
import Form from 'Components/Form/Form';
|
||||
import FormGroup from 'Components/Form/FormGroup';
|
||||
@@ -7,7 +8,7 @@ import FormInputButton from 'Components/Form/FormInputButton';
|
||||
import FormInputGroup from 'Components/Form/FormInputGroup';
|
||||
import FormLabel from 'Components/Form/FormLabel';
|
||||
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
||||
import { inputTypes, sizes } from 'Helpers/Props';
|
||||
import { inputTypes, kinds, sizes } from 'Helpers/Props';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import NamingModal from './NamingModal';
|
||||
import styles from './Naming.css';
|
||||
@@ -118,9 +119,9 @@ class Naming extends Component {
|
||||
|
||||
{
|
||||
!isFetching && error &&
|
||||
<div>
|
||||
<Alert kind={kinds.DANGER}>
|
||||
{translate('UnableToLoadNamingSettings')}
|
||||
</div>
|
||||
</Alert>
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import Alert from 'Components/Alert';
|
||||
import FieldSet from 'Components/FieldSet';
|
||||
import Form from 'Components/Form/Form';
|
||||
import FormGroup from 'Components/Form/FormGroup';
|
||||
import FormInputGroup from 'Components/Form/FormInputGroup';
|
||||
import FormLabel from 'Components/Form/FormLabel';
|
||||
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
||||
import { inputTypes } from 'Helpers/Props';
|
||||
import { inputTypes, kinds } from 'Helpers/Props';
|
||||
import translate from 'Utilities/String/translate';
|
||||
|
||||
const writeAudioTagOptions = [
|
||||
@@ -41,9 +42,9 @@ function MetadataProvider(props) {
|
||||
|
||||
{
|
||||
!isFetching && error &&
|
||||
<div>
|
||||
<Alert kind={kinds.DANGER}>
|
||||
{translate('UnableToLoadMetadataProviderSettings')}
|
||||
</div>
|
||||
</Alert>
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
@@ -15,9 +15,6 @@ import { inputTypes, kinds } from 'Helpers/Props';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import styles from './EditMetadataProfileModalContent.css';
|
||||
|
||||
// Tab, enter, and comma
|
||||
const tagInputDelimiters = [9, 13, 188];
|
||||
|
||||
function EditMetadataProfileModalContent(props) {
|
||||
const {
|
||||
isFetching,
|
||||
@@ -189,7 +186,7 @@ function EditMetadataProfileModalContent(props) {
|
||||
helpText={translate('IgnoredMetaHelpText')}
|
||||
kind={kinds.DANGER}
|
||||
placeholder={translate('IgnoredPlaceHolder')}
|
||||
delimiters={tagInputDelimiters}
|
||||
delimiters={['Tab', 'Enter', ',']}
|
||||
{...ignored}
|
||||
onChange={onInputChange}
|
||||
/>
|
||||
|
||||
@@ -23,9 +23,14 @@
|
||||
height: 36px;
|
||||
}
|
||||
|
||||
.bookTypes {
|
||||
.enabled {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
margin-top: 5px;
|
||||
pointer-events: all;
|
||||
}
|
||||
|
||||
.label {
|
||||
composes: label from '~Components/Label.css';
|
||||
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
// This file is automatically generated.
|
||||
// Please do not change this file!
|
||||
interface CssExports {
|
||||
'bookTypes': string;
|
||||
'cloneButton': string;
|
||||
'enabled': string;
|
||||
'label': string;
|
||||
'metadataProfile': string;
|
||||
'name': string;
|
||||
'nameContainer': string;
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import MiddleTruncate from 'react-middle-truncate';
|
||||
import Card from 'Components/Card';
|
||||
import Label from 'Components/Label';
|
||||
import IconButton from 'Components/Link/IconButton';
|
||||
import ConfirmModal from 'Components/Modal/ConfirmModal';
|
||||
import { icons, kinds } from 'Helpers/Props';
|
||||
@@ -64,6 +66,9 @@ class MetadataProfile extends Component {
|
||||
const {
|
||||
id,
|
||||
name,
|
||||
minPopularity,
|
||||
minPages,
|
||||
ignored,
|
||||
isDeleting
|
||||
} = this.props;
|
||||
|
||||
@@ -86,6 +91,48 @@ class MetadataProfile extends Component {
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className={styles.enabled}>
|
||||
{
|
||||
minPopularity ?
|
||||
<Label kind={kinds.DEFAULT}>
|
||||
{translate('MinimumPopularity')}: {minPopularity}
|
||||
</Label> :
|
||||
null
|
||||
}
|
||||
|
||||
{
|
||||
minPages ?
|
||||
<Label kind={kinds.DEFAULT}>
|
||||
{translate('MinimumPages')}: {minPages}
|
||||
</Label> :
|
||||
null
|
||||
}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
{
|
||||
ignored.map((item) => {
|
||||
if (!item) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Label
|
||||
className={styles.label}
|
||||
key={item}
|
||||
kind={kinds.DANGER}
|
||||
>
|
||||
<MiddleTruncate
|
||||
text={item}
|
||||
start={10}
|
||||
end={10}
|
||||
/>
|
||||
</Label>
|
||||
);
|
||||
})
|
||||
}
|
||||
</div>
|
||||
|
||||
<EditMetadataProfileModalConnector
|
||||
id={id}
|
||||
isOpen={this.state.isEditMetadataProfileModalOpen}
|
||||
@@ -111,10 +158,19 @@ class MetadataProfile extends Component {
|
||||
MetadataProfile.propTypes = {
|
||||
id: PropTypes.number.isRequired,
|
||||
name: PropTypes.string.isRequired,
|
||||
minPopularity: PropTypes.number.isRequired,
|
||||
minPages: PropTypes.number.isRequired,
|
||||
ignored: PropTypes.arrayOf(PropTypes.string).isRequired,
|
||||
isDeleting: PropTypes.bool.isRequired,
|
||||
onConfirmDeleteMetadataProfile: PropTypes.func.isRequired,
|
||||
onCloneMetadataProfilePress: PropTypes.func.isRequired
|
||||
|
||||
};
|
||||
|
||||
MetadataProfile.defaultProps = {
|
||||
minPopularity: 0,
|
||||
minPages: 0,
|
||||
ignored: []
|
||||
};
|
||||
|
||||
export default MetadataProfile;
|
||||
|
||||
@@ -55,12 +55,12 @@ class ResetQualityDefinitionsModalContent extends Component {
|
||||
onModalClose={onModalClose}
|
||||
>
|
||||
<ModalHeader>
|
||||
Reset Quality Definitions
|
||||
{translate('ResetQualityDefinitions')}
|
||||
</ModalHeader>
|
||||
|
||||
<ModalBody>
|
||||
<div className={styles.messageContainer}>
|
||||
Are you sure you want to reset quality definitions?
|
||||
{translate('ResetQualityDefinitionsMessageText')}
|
||||
</div>
|
||||
|
||||
<FormGroup>
|
||||
@@ -81,7 +81,7 @@ class ResetQualityDefinitionsModalContent extends Component {
|
||||
|
||||
<ModalFooter>
|
||||
<Button onPress={onModalClose}>
|
||||
Cancel
|
||||
{translate('Cancel')}
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
@@ -89,7 +89,7 @@ class ResetQualityDefinitionsModalContent extends Component {
|
||||
onPress={this.onResetQualityDefinitionsConfirmed}
|
||||
isDisabled={isResettingQualityDefinitions}
|
||||
>
|
||||
Reset
|
||||
{translate('Reset')}
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
</ModalContent>
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import Alert from 'Components/Alert';
|
||||
import FieldSet from 'Components/FieldSet';
|
||||
import Link from 'Components/Link/Link';
|
||||
import PageSectionContent from 'Components/Page/PageSectionContent';
|
||||
import { kinds } from 'Helpers/Props';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import TagConnector from './TagConnector';
|
||||
import styles from './Tags.css';
|
||||
@@ -16,9 +18,9 @@ function Tags(props) {
|
||||
if (!items.length) {
|
||||
const wikiLink = <Link to='https://wiki.servarr.com/readarr/settings#tags'>here</Link>;
|
||||
return (
|
||||
<div>
|
||||
<Alert kind={kinds.INFO}>
|
||||
{translate('NoTagsHaveBeenAddedYet', [wikiLink])}
|
||||
</div>
|
||||
</Alert>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import Alert from 'Components/Alert';
|
||||
import FieldSet from 'Components/FieldSet';
|
||||
import Form from 'Components/Form/Form';
|
||||
import FormGroup from 'Components/Form/FormGroup';
|
||||
@@ -8,7 +9,7 @@ import FormLabel from 'Components/Form/FormLabel';
|
||||
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
||||
import PageContent from 'Components/Page/PageContent';
|
||||
import PageContentBody from 'Components/Page/PageContentBody';
|
||||
import { inputTypes } from 'Helpers/Props';
|
||||
import { inputTypes, kinds } from 'Helpers/Props';
|
||||
import SettingsToolbarConnector from 'Settings/SettingsToolbarConnector';
|
||||
import themes from 'Styles/Themes';
|
||||
import titleCase from 'Utilities/String/titleCase';
|
||||
@@ -81,9 +82,9 @@ class UISettings extends Component {
|
||||
|
||||
{
|
||||
!isFetching && error &&
|
||||
<div>
|
||||
<Alert kind={kinds.DANGER}>
|
||||
{translate('UnableToLoadUISettings')}
|
||||
</div>
|
||||
</Alert>
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import Alert from 'Components/Alert';
|
||||
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
||||
import PageContent from 'Components/Page/PageContent';
|
||||
import PageContentBody from 'Components/Page/PageContentBody';
|
||||
@@ -8,7 +9,7 @@ import PageToolbarButton from 'Components/Page/Toolbar/PageToolbarButton';
|
||||
import PageToolbarSection from 'Components/Page/Toolbar/PageToolbarSection';
|
||||
import Table from 'Components/Table/Table';
|
||||
import TableBody from 'Components/Table/TableBody';
|
||||
import { icons } from 'Helpers/Props';
|
||||
import { icons, kinds } from 'Helpers/Props';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import BackupRow from './BackupRow';
|
||||
import RestoreBackupModalConnector from './RestoreBackupModalConnector';
|
||||
@@ -107,16 +108,16 @@ class Backups extends Component {
|
||||
|
||||
{
|
||||
!isFetching && !!error &&
|
||||
<div>
|
||||
<Alert kind={kinds.DANGER}>
|
||||
{translate('UnableToLoadBackups')}
|
||||
</div>
|
||||
</Alert>
|
||||
}
|
||||
|
||||
{
|
||||
noBackups &&
|
||||
<div>
|
||||
<Alert kind={kinds.INFO}>
|
||||
{translate('NoBackupsAreAvailable')}
|
||||
</div>
|
||||
</Alert>
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import Alert from 'Components/Alert';
|
||||
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
||||
import FilterMenu from 'Components/Menu/FilterMenu';
|
||||
import PageContent from 'Components/Page/PageContent';
|
||||
@@ -11,7 +12,7 @@ import Table from 'Components/Table/Table';
|
||||
import TableBody from 'Components/Table/TableBody';
|
||||
import TableOptionsModalWrapper from 'Components/Table/TableOptions/TableOptionsModalWrapper';
|
||||
import TablePager from 'Components/Table/TablePager';
|
||||
import { align, icons } from 'Helpers/Props';
|
||||
import { align, icons, kinds } from 'Helpers/Props';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import LogsTableRow from './LogsTableRow';
|
||||
|
||||
@@ -82,9 +83,9 @@ function LogsTable(props) {
|
||||
|
||||
{
|
||||
isPopulated && !error && !items.length &&
|
||||
<div>
|
||||
No events found
|
||||
</div>
|
||||
<Alert kind={kinds.INFO}>
|
||||
{translate('NoEventsFound')}
|
||||
</Alert>
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
@@ -11,7 +11,7 @@ import PageToolbarSection from 'Components/Page/Toolbar/PageToolbarSection';
|
||||
import PageToolbarSeparator from 'Components/Page/Toolbar/PageToolbarSeparator';
|
||||
import Table from 'Components/Table/Table';
|
||||
import TableBody from 'Components/Table/TableBody';
|
||||
import { icons } from 'Helpers/Props';
|
||||
import { icons, kinds } from 'Helpers/Props';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import LogsNavMenu from '../LogsNavMenu';
|
||||
import LogFilesTableRow from './LogFilesTableRow';
|
||||
@@ -118,9 +118,9 @@ class LogFiles extends Component {
|
||||
|
||||
{
|
||||
!isFetching && !items.length &&
|
||||
<div>
|
||||
<Alert kind={kinds.INFO}>
|
||||
{translate('NoLogFiles')}
|
||||
</div>
|
||||
</Alert>
|
||||
}
|
||||
</PageContentBody>
|
||||
</PageContent>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import _ from 'lodash';
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component, Fragment } from 'react';
|
||||
import Alert from 'Components/Alert';
|
||||
import Icon from 'Components/Icon';
|
||||
import Label from 'Components/Label';
|
||||
import SpinnerButton from 'Components/Link/SpinnerButton';
|
||||
@@ -61,9 +62,9 @@ class Updates extends Component {
|
||||
|
||||
{
|
||||
noUpdates &&
|
||||
<div>
|
||||
<Alert kind={kinds.INFO}>
|
||||
{translate('NoUpdatesAreAvailable')}
|
||||
</div>
|
||||
</Alert>
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import Alert from 'Components/Alert';
|
||||
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
||||
import FilterMenu from 'Components/Menu/FilterMenu';
|
||||
import ConfirmModal from 'Components/Modal/ConfirmModal';
|
||||
@@ -190,16 +191,16 @@ class CutoffUnmet extends Component {
|
||||
|
||||
{
|
||||
!isAnyFetching && error &&
|
||||
<div>
|
||||
<Alert kind={kinds.DANGER}>
|
||||
Error fetching cutoff unmet
|
||||
</div>
|
||||
</Alert>
|
||||
}
|
||||
|
||||
{
|
||||
isAllPopulated && !error && !items.length &&
|
||||
<div>
|
||||
No cutoff unmet items
|
||||
</div>
|
||||
<Alert kind={kinds.INFO}>
|
||||
{translate('NoCutoffUnmetItems')}
|
||||
</Alert>
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import Alert from 'Components/Alert';
|
||||
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
||||
import FilterMenu from 'Components/Menu/FilterMenu';
|
||||
import ConfirmModal from 'Components/Modal/ConfirmModal';
|
||||
@@ -207,16 +208,16 @@ class Missing extends Component {
|
||||
|
||||
{
|
||||
!isAnyFetching && error &&
|
||||
<div>
|
||||
<Alert kind={kinds.DANGER}>
|
||||
Error fetching missing items
|
||||
</div>
|
||||
</Alert>
|
||||
}
|
||||
|
||||
{
|
||||
isAllPopulated && !error && !items.length &&
|
||||
<div>
|
||||
No missing items
|
||||
</div>
|
||||
<Alert kind={kinds.INFO}>
|
||||
{translate('NoMissingItems')}
|
||||
</Alert>
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
@@ -134,7 +134,7 @@
|
||||
"run-sequence": "2.2.1",
|
||||
"streamqueue": "1.1.2",
|
||||
"style-loader": "3.3.2",
|
||||
"stylelint": "15.6.1",
|
||||
"stylelint": "15.10.1",
|
||||
"stylelint-order": "6.0.3",
|
||||
"terser-webpack-plugin": "5.3.8",
|
||||
"ts-loader": "9.4.3",
|
||||
|
||||
@@ -27,35 +27,36 @@ namespace NzbDrone.Api.Test.ClientSchemaTests
|
||||
|
||||
var schema = SchemaBuilder.ToSchema(model);
|
||||
|
||||
schema.Should().Contain(c =>
|
||||
c.Order == 1 && c.Name == "lastName" && c.Label == "Last Name" && c.HelpText == "Your Last Name" &&
|
||||
(string)c.Value == "Poop");
|
||||
schema.Should().Contain(c =>
|
||||
c.Order == 0 && c.Name == "firstName" && c.Label == "First Name" && c.HelpText == "Your First Name" &&
|
||||
(string)c.Value == "Bob");
|
||||
schema.Should().Contain(c => c.Order == 1 && c.Name == "lastName" && c.Label == "Last Name" && c.HelpText == "Your Last Name" && c.HelpTextWarning == "Mandatory Last Name" && (string)c.Value == "Poop");
|
||||
schema.Should().Contain(c => c.Order == 0 && c.Name == "firstName" && c.Label == "First Name" && c.HelpText == "Your First Name" && c.HelpTextWarning == "Mandatory First Name" && (string)c.Value == "Bob");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void schema_should_have_nested_fields()
|
||||
{
|
||||
var model = new NestedTestModel();
|
||||
model.Name.FirstName = "Bob";
|
||||
model.Name.LastName = "Poop";
|
||||
var model = new NestedTestModel
|
||||
{
|
||||
Name =
|
||||
{
|
||||
FirstName = "Bob",
|
||||
LastName = "Poop"
|
||||
}
|
||||
};
|
||||
|
||||
var schema = SchemaBuilder.ToSchema(model);
|
||||
|
||||
schema.Should().Contain(c => c.Order == 0 && c.Name == "name.firstName" && c.Label == "First Name" && c.HelpText == "Your First Name" && (string)c.Value == "Bob");
|
||||
schema.Should().Contain(c => c.Order == 1 && c.Name == "name.lastName" && c.Label == "Last Name" && c.HelpText == "Your Last Name" && (string)c.Value == "Poop");
|
||||
schema.Should().Contain(c => c.Order == 0 && c.Name == "name.firstName" && c.Label == "First Name" && c.HelpText == "Your First Name" && c.HelpTextWarning == "Mandatory First Name" && (string)c.Value == "Bob");
|
||||
schema.Should().Contain(c => c.Order == 1 && c.Name == "name.lastName" && c.Label == "Last Name" && c.HelpText == "Your Last Name" && c.HelpTextWarning == "Mandatory Last Name" && (string)c.Value == "Poop");
|
||||
schema.Should().Contain(c => c.Order == 2 && c.Name == "quote" && c.Label == "Quote" && c.HelpText == "Your Favorite Quote");
|
||||
}
|
||||
}
|
||||
|
||||
public class TestModel
|
||||
{
|
||||
[FieldDefinition(0, Label = "First Name", HelpText = "Your First Name")]
|
||||
[FieldDefinition(0, Label = "First Name", HelpText = "Your First Name", HelpTextWarning = "Mandatory First Name")]
|
||||
public string FirstName { get; set; }
|
||||
|
||||
[FieldDefinition(1, Label = "Last Name", HelpText = "Your Last Name")]
|
||||
[FieldDefinition(1, Label = "Last Name", HelpText = "Your Last Name", HelpTextWarning = "Mandatory Last Name")]
|
||||
public string LastName { get; set; }
|
||||
|
||||
public string Other { get; set; }
|
||||
|
||||
@@ -10,7 +10,9 @@ namespace NzbDrone.Common.Test.InstrumentationTests
|
||||
// Indexer Urls
|
||||
[TestCase(@"https://iptorrents.com/torrents/rss?u=mySecret;tp=mySecret;l5;download")]
|
||||
[TestCase(@"http://rss.torrentleech.org/mySecret")]
|
||||
[TestCase(@"http://rss.torrentleech.org/rss/download/12345/01233210/filename.torrent")]
|
||||
[TestCase(@"https://rss24h.torrentleech.org/mySecret")]
|
||||
[TestCase(@"http://rss.torrentleech.org/rss/download/12345/01233210/file.name-RLSGRP.torrent")]
|
||||
[TestCase(@"https://www.torrentleech.org/rss/download/12345/01233210/file.name-RLSGRP.torrent")]
|
||||
[TestCase(@"http://www.bitmetv.org/rss.php?uid=mySecret&passkey=mySecret")]
|
||||
[TestCase(@"https://rss.omgwtfnzbs.org/rss-search.php?catid=19,20&user=Readarr&api=mySecret&eng=1")]
|
||||
[TestCase(@"https://dognzb.cr/fetch/2b51db35e1912ffc138825a12b9933d2/2b51db35e1910123321025a12b9933d2")]
|
||||
@@ -44,6 +46,7 @@ namespace NzbDrone.Common.Test.InstrumentationTests
|
||||
// Deluge
|
||||
[TestCase(@",{""download_location"": ""C:\Users\\mySecret mySecret\\Downloads""}")]
|
||||
[TestCase(@",{""download_location"": ""/home/mySecret/Downloads""}")]
|
||||
[TestCase(@",{""download_location"": ""/Users/mySecret/Downloads""}")]
|
||||
[TestCase(@"auth.login(""mySecret"")")]
|
||||
|
||||
// Download Station
|
||||
@@ -56,8 +59,11 @@ namespace NzbDrone.Common.Test.InstrumentationTests
|
||||
|
||||
// Internal
|
||||
[TestCase(@"OutputPath=/home/mySecret/Downloads")]
|
||||
[TestCase(@"OutputPath=/Users/mySecret/Downloads")]
|
||||
[TestCase("Hardlinking episode file: /home/mySecret/Downloads to /media/abc.mkv")]
|
||||
[TestCase("Hardlinking episode file: /Users/mySecret/Downloads to /media/abc.mkv")]
|
||||
[TestCase("Hardlink '/home/mySecret/Downloads/abs.mkv' to '/media/abc.mkv' failed.")]
|
||||
[TestCase("Hardlink '/Users/mySecret/Downloads/abs.mkv' to '/media/abc.mkv' failed.")]
|
||||
[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 ***")]
|
||||
|
||||
@@ -60,8 +60,7 @@ namespace NzbDrone.Common.Http
|
||||
|
||||
if (request.AllowAutoRedirect && response.HasHttpRedirect)
|
||||
{
|
||||
var autoRedirectChain = new List<string>();
|
||||
autoRedirectChain.Add(request.Url.ToString());
|
||||
var autoRedirectChain = new List<string> { request.Url.ToString() };
|
||||
|
||||
do
|
||||
{
|
||||
@@ -75,6 +74,14 @@ namespace NzbDrone.Common.Http
|
||||
throw new WebException($"Too many automatic redirections were attempted for {autoRedirectChain.Join(" -> ")}", WebExceptionStatus.ProtocolError);
|
||||
}
|
||||
|
||||
// 302 or 303 should default to GET on redirect even if POST on original
|
||||
if (RequestRequiresForceGet(response.StatusCode, response.Request.Method))
|
||||
{
|
||||
request.Method = HttpMethod.Get;
|
||||
request.ContentData = null;
|
||||
request.ContentSummary = null;
|
||||
}
|
||||
|
||||
response = ExecuteRequest(request, cookieContainer);
|
||||
}
|
||||
while (response.HasHttpRedirect);
|
||||
@@ -105,6 +112,16 @@ namespace NzbDrone.Common.Http
|
||||
return response;
|
||||
}
|
||||
|
||||
private static bool RequestRequiresForceGet(HttpStatusCode statusCode, HttpMethod requestMethod)
|
||||
{
|
||||
return statusCode switch
|
||||
{
|
||||
HttpStatusCode.Moved or HttpStatusCode.Found or HttpStatusCode.MultipleChoices => requestMethod == HttpMethod.Post,
|
||||
HttpStatusCode.SeeOther => requestMethod != HttpMethod.Get && requestMethod != HttpMethod.Head,
|
||||
_ => false,
|
||||
};
|
||||
}
|
||||
|
||||
private HttpResponse ExecuteRequest(HttpRequest request, CookieContainer cookieContainer)
|
||||
{
|
||||
foreach (var interceptor in _requestInterceptors)
|
||||
|
||||
@@ -50,6 +50,8 @@ namespace NzbDrone.Common.Http
|
||||
|
||||
public bool HasHttpError => (int)StatusCode >= 400;
|
||||
|
||||
public bool HasHttpServerError => (int)StatusCode >= 500;
|
||||
|
||||
public bool HasHttpRedirect => StatusCode == HttpStatusCode.Moved ||
|
||||
StatusCode == HttpStatusCode.MovedPermanently ||
|
||||
StatusCode == HttpStatusCode.Found ||
|
||||
|
||||
@@ -7,56 +7,56 @@ namespace NzbDrone.Common.Instrumentation
|
||||
{
|
||||
public class CleanseLogMessage
|
||||
{
|
||||
private static readonly Regex[] CleansingRules = new[]
|
||||
{
|
||||
// Url
|
||||
new Regex(@"(?<=\?|&|: )((?:api|auth|pass)?key|(?:access[-_]?)?token|auth|user|uid|api|[a-z_]*apikey|account|passwd)=(?<secret>[^&=""]+?)(?=[ ""&=]|$)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||
new Regex(@"(?<=\?|&)[^=]*?(username|password)=(?<secret>[^&=]+?)(?= |&|$)", 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(@"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),
|
||||
private static readonly Regex[] CleansingRules =
|
||||
{
|
||||
// Url
|
||||
new (@"(?<=\?|&|: )((?:api|auth|pass)?key|(?:access[-_]?)?token|auth|user|uid|api|[a-z_]*apikey|account|passwd)=(?<secret>[^&=""]+?)(?=[ ""&=]|$)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||
new (@"(?<=\?|&)[^=]*?(username|password)=(?<secret>[^&=]+?)(?= |&|$)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||
new (@"rss(24h)?\.torrentleech\.org/(?!rss)(?<secret>[0-9a-z]+)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||
new (@"torrentleech\.org/rss/download/[0-9]+/(?<secret>[0-9a-z]+)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||
new (@"iptorrents\.com/[/a-z0-9?&;]*?(?:[?&;](u|tp)=(?<secret>[^&=;]+?))+(?= |;|&|$)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||
new (@"/fetch/[a-z0-9]{32}/(?<secret>[a-z0-9]{32})", RegexOptions.Compiled),
|
||||
new (@"getnzb.*?(?<=\?|&)(r)=(?<secret>[^&=]+?)(?= |&|$)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||
new (@"\b(\w*)?(_?(?<!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"),
|
||||
// Trackers Announce Keys; Designed for Qbit Json; should work for all in theory
|
||||
new (@"announce(\.php)?(/|%2f|%3fpasskey%3d)(?<secret>[a-z0-9]{16,})|(?<secret>[a-z0-9]{16,})(/|%2f)announce"),
|
||||
|
||||
// Path
|
||||
new Regex(@"C:\\Users\\(?<secret>[^\""]+?)(\\|$)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||
new Regex(@"/home/(?<secret>[^/""]+?)(/|$)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||
// Path
|
||||
new (@"C:\\Users\\(?<secret>[^\""]+?)(\\|$)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||
new (@"/(home|Users)/(?<secret>[^/""]+?)(/|$)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||
|
||||
// NzbGet
|
||||
new Regex(@"""Name""\s*:\s*""[^""]*(username|password)""\s*,\s*""Value""\s*:\s*""(?<secret>[^""]+?)""", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||
// NzbGet
|
||||
new (@"""Name""\s*:\s*""[^""]*(username|password)""\s*,\s*""Value""\s*:\s*""(?<secret>[^""]+?)""", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||
|
||||
// Sabnzbd
|
||||
new Regex(@"""[^""]*(username|password|api_?key|nzb_key)""\s*:\s*""(?<secret>[^""]+?)""", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||
new Regex(@"""email_(account|to|from|pwd)""\s*:\s*""(?<secret>[^""]+?)""", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||
// Sabnzbd
|
||||
new (@"""[^""]*(username|password|api_?key|nzb_key)""\s*:\s*""(?<secret>[^""]+?)""", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||
new (@"""email_(account|to|from|pwd)""\s*:\s*""(?<secret>[^""]+?)""", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||
|
||||
// uTorrent
|
||||
new Regex(@"\[""[a-z._]*(username|password)"",\d,""(?<secret>[^""]+?)""", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||
new Regex(@"\[""(boss_key|boss_key_salt|proxy\.proxy)"",\d,""(?<secret>[^""]+?)""", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||
// uTorrent
|
||||
new (@"\[""[a-z._]*(username|password)"",\d,""(?<secret>[^""]+?)""", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||
new (@"\[""(boss_key|boss_key_salt|proxy\.proxy)"",\d,""(?<secret>[^""]+?)""", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||
|
||||
// Deluge
|
||||
new Regex(@"auth.login\(""(?<secret>[^""]+?)""", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||
// Deluge
|
||||
new (@"auth.login\(""(?<secret>[^""]+?)""", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||
|
||||
// BroadcastheNet
|
||||
new Regex(@"""?method""?\s*:\s*""(getTorrents)"",\s*""?params""?\s*:\s*\[\s*""(?<secret>[^""]+?)""", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||
new Regex(@"getTorrents\(""(?<secret>[^""]+?)""", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||
new Regex(@"(?<=\?|&)(authkey|torrent_pass)=(?<secret>[^&=]+?)(?=""|&|$)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||
// BroadcastheNet
|
||||
new (@"""?method""?\s*:\s*""(getTorrents)"",\s*""?params""?\s*:\s*\[\s*""(?<secret>[^""]+?)""", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||
new (@"getTorrents\(""(?<secret>[^""]+?)""", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||
new (@"(?<=\?|&)(authkey|torrent_pass)=(?<secret>[^&=]+?)(?=""|&|$)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||
|
||||
// Good Reads
|
||||
new Regex(@"(?<=""(token|tokensecret)"":\s)""(?<secret>[^""]+?)""", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||
// Good Reads
|
||||
new (@"(?<=""(token|tokensecret)"":\s)""(?<secret>[^""]+?)""", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||
|
||||
// Webhooks
|
||||
// Notifiarr
|
||||
new Regex(@"api/v[0-9]/notification/readarr/(?<secret>[\w-]+)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||
// Webhooks
|
||||
// Notifiarr
|
||||
new (@"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)
|
||||
};
|
||||
// Discord
|
||||
new (@"discord.com/api/webhooks/((?<secret>[\w-]+)/)?(?<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);
|
||||
private static readonly Regex CleanseRemoteIPRegex = new (@"(?:Auth-\w+(?<!Failure|Unauthorized) ip|from) (\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})", RegexOptions.Compiled);
|
||||
|
||||
public static string Cleanse(string message)
|
||||
{
|
||||
@@ -68,15 +68,15 @@ namespace NzbDrone.Common.Instrumentation
|
||||
foreach (var regex in CleansingRules)
|
||||
{
|
||||
message = regex.Replace(message, m =>
|
||||
{
|
||||
var value = m.Value;
|
||||
foreach (var capture in m.Groups["secret"].Captures.OfType<Capture>().Reverse())
|
||||
{
|
||||
var value = m.Value;
|
||||
foreach (var capture in m.Groups["secret"].Captures.OfType<Capture>().Reverse())
|
||||
{
|
||||
value = value.Replace(capture.Index - m.Index, capture.Length, "(removed)");
|
||||
}
|
||||
value = value.Replace(capture.Index - m.Index, capture.Length, "(removed)");
|
||||
}
|
||||
|
||||
return value;
|
||||
});
|
||||
return value;
|
||||
});
|
||||
}
|
||||
|
||||
message = CleanseRemoteIPRegex.Replace(message, CleanseRemoteIP);
|
||||
@@ -87,7 +87,6 @@ namespace NzbDrone.Common.Instrumentation
|
||||
private static string CleanseRemoteIP(Match match)
|
||||
{
|
||||
var group = match.Groups[1];
|
||||
var valueAll = match.Value;
|
||||
var valueIP = group.Value;
|
||||
|
||||
if (IPAddress.TryParse(valueIP, out var address) && !address.IsLocalAddress())
|
||||
|
||||
@@ -100,7 +100,7 @@ namespace NzbDrone.Common.Instrumentation.Sentry
|
||||
o.Dsn = dsn;
|
||||
o.AttachStacktrace = true;
|
||||
o.MaxBreadcrumbs = 200;
|
||||
o.Release = BuildInfo.Release;
|
||||
o.Release = $"{BuildInfo.AppName}@{BuildInfo.Release}";
|
||||
o.BeforeSend = x => SentryCleanser.CleanseEvent(x);
|
||||
o.BeforeBreadcrumb = x => SentryCleanser.CleanseBreadcrumb(x);
|
||||
o.Environment = BuildInfo.Branch;
|
||||
|
||||
@@ -71,6 +71,11 @@ namespace NzbDrone.Common.Serializer
|
||||
return JsonConvert.SerializeObject(obj, SerializerSettings);
|
||||
}
|
||||
|
||||
public static string ToJson(this object obj, Formatting formatting)
|
||||
{
|
||||
return JsonConvert.SerializeObject(obj, formatting, SerializerSettings);
|
||||
}
|
||||
|
||||
public static void Serialize<TModel>(TModel model, TextWriter outputStream)
|
||||
{
|
||||
var jsonTextWriter = new JsonTextWriter(outputStream);
|
||||
|
||||
@@ -225,6 +225,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.QBittorrentTests
|
||||
[TestCase("checkingDL")]
|
||||
[TestCase("checkingUP")]
|
||||
[TestCase("metaDL")]
|
||||
[TestCase("checkingResumeData")]
|
||||
public void queued_item_should_have_required_properties(string state)
|
||||
{
|
||||
var torrent = new QBittorrentTorrent
|
||||
|
||||
@@ -15,6 +15,7 @@ namespace NzbDrone.Core.Annotations
|
||||
public string Label { get; set; }
|
||||
public string Unit { get; set; }
|
||||
public string HelpText { get; set; }
|
||||
public string HelpTextWarning { get; set; }
|
||||
public string HelpLink { get; set; }
|
||||
public FieldType Type { get; set; }
|
||||
public bool Advanced { get; set; }
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
using Dapper;
|
||||
using FluentMigrator;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using NzbDrone.Common.Serializer;
|
||||
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||
|
||||
namespace NzbDrone.Core.Datastore.Migration
|
||||
{
|
||||
[Migration(033)]
|
||||
public class metadata_profile_ignored_to_list : NzbDroneMigrationBase
|
||||
{
|
||||
protected override void MainDbUpgrade()
|
||||
{
|
||||
Execute.WithConnection(MigrateMetadataProfileIgnored);
|
||||
}
|
||||
|
||||
private void MigrateMetadataProfileIgnored(IDbConnection conn, IDbTransaction tran)
|
||||
{
|
||||
var updatedMetadataProfiles = new List<object>();
|
||||
|
||||
using (var selectCommand = conn.CreateCommand())
|
||||
{
|
||||
selectCommand.Transaction = tran;
|
||||
selectCommand.CommandText = "SELECT \"Id\", \"Ignored\" FROM \"MetadataProfiles\"";
|
||||
|
||||
using var reader = selectCommand.ExecuteReader();
|
||||
|
||||
while (reader.Read())
|
||||
{
|
||||
var id = reader.GetInt32(0);
|
||||
var ignored = reader.GetValue(1).ToString() ?? string.Empty;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(ignored))
|
||||
{
|
||||
try
|
||||
{
|
||||
JsonConvert.DeserializeObject<JArray>(ignored);
|
||||
|
||||
continue;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
|
||||
ignored = ignored
|
||||
.Split(',', StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries)
|
||||
.Distinct()
|
||||
.ToJson();
|
||||
|
||||
updatedMetadataProfiles.Add(new
|
||||
{
|
||||
Id = id,
|
||||
Ignored = ignored
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
var updatedMetadataProfilesSql = "UPDATE \"MetadataProfiles\" SET \"Ignored\" = @Ignored WHERE \"Id\" = @Id";
|
||||
conn.Execute(updatedMetadataProfilesSql, updatedMetadataProfiles, transaction: tran);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -253,6 +253,7 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
|
||||
case "queuedDL": // queuing is enabled and torrent is queued for download
|
||||
case "checkingDL": // same as checkingUP, but torrent has NOT finished downloading
|
||||
case "checkingUP": // torrent has finished downloading and is being checked. Set when `recheck torrent on completion` is enabled. In the event the check fails we shouldn't treat it as completed.
|
||||
case "checkingResumeData": // torrent is checking resume data on load
|
||||
item.Status = DownloadItemStatus.Queued;
|
||||
break;
|
||||
|
||||
|
||||
@@ -14,34 +14,32 @@ namespace NzbDrone.Core.Housekeeping.Housekeepers
|
||||
|
||||
public void Clean()
|
||||
{
|
||||
using (var mapper = _database.OpenConnection())
|
||||
using var mapper = _database.OpenConnection();
|
||||
if (_database.DatabaseType == DatabaseType.PostgreSQL)
|
||||
{
|
||||
if (_database.DatabaseType == DatabaseType.PostgreSQL)
|
||||
{
|
||||
mapper.Execute(@"DELETE FROM ""MetadataFiles""
|
||||
WHERE ""Id"" = ANY (
|
||||
SELECT ""Id"" FROM ""MetadataFiles""
|
||||
WHERE ""RelativePath""
|
||||
LIKE '_:\\%'
|
||||
OR ""RelativePath""
|
||||
LIKE '\\%'
|
||||
OR ""RelativePath""
|
||||
LIKE '/%'
|
||||
)");
|
||||
}
|
||||
else
|
||||
{
|
||||
mapper.Execute(@"DELETE FROM ""MetadataFiles""
|
||||
WHERE ""Id"" IN (
|
||||
SELECT ""Id"" FROM ""MetadataFiles""
|
||||
WHERE ""RelativePath""
|
||||
LIKE '_:\%'
|
||||
OR ""RelativePath""
|
||||
LIKE '\%'
|
||||
OR ""RelativePath""
|
||||
LIKE '/%'
|
||||
)");
|
||||
}
|
||||
mapper.Execute(@"DELETE FROM ""MetadataFiles""
|
||||
WHERE ""Id"" = ANY (
|
||||
SELECT ""Id"" FROM ""MetadataFiles""
|
||||
WHERE ""RelativePath""
|
||||
LIKE '_:\\%'
|
||||
OR ""RelativePath""
|
||||
LIKE '\\%'
|
||||
OR ""RelativePath""
|
||||
LIKE '/%'
|
||||
)");
|
||||
}
|
||||
else
|
||||
{
|
||||
mapper.Execute(@"DELETE FROM ""MetadataFiles""
|
||||
WHERE ""Id"" IN (
|
||||
SELECT ""Id"" FROM ""MetadataFiles""
|
||||
WHERE ""RelativePath""
|
||||
LIKE '_:\%'
|
||||
OR ""RelativePath""
|
||||
LIKE '\%'
|
||||
OR ""RelativePath""
|
||||
LIKE '/%'
|
||||
)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,13 +14,11 @@ namespace NzbDrone.Core.Housekeeping.Housekeepers
|
||||
|
||||
public void Clean()
|
||||
{
|
||||
using (var mapper = _database.OpenConnection())
|
||||
{
|
||||
mapper.Execute(@"DELETE FROM ""NamingConfig""
|
||||
WHERE ""Id"" NOT IN (
|
||||
SELECT ""Id"" FROM ""NamingConfig""
|
||||
LIMIT 1)");
|
||||
}
|
||||
using var mapper = _database.OpenConnection();
|
||||
mapper.Execute(@"DELETE FROM ""NamingConfig""
|
||||
WHERE ""Id"" NOT IN (
|
||||
SELECT ""Id"" FROM ""NamingConfig""
|
||||
LIMIT 1)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,13 +14,11 @@ namespace NzbDrone.Core.Housekeeping.Housekeepers
|
||||
|
||||
public void Clean()
|
||||
{
|
||||
using (var mapper = _database.OpenConnection())
|
||||
{
|
||||
mapper.Execute(@"DELETE FROM ""Users""
|
||||
WHERE ""Id"" NOT IN (
|
||||
SELECT ""Id"" FROM ""Users""
|
||||
LIMIT 1)");
|
||||
}
|
||||
using var mapper = _database.OpenConnection();
|
||||
mapper.Execute(@"DELETE FROM ""Users""
|
||||
WHERE ""Id"" NOT IN (
|
||||
SELECT ""Id"" FROM ""Users""
|
||||
LIMIT 1)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,29 +16,29 @@ namespace NzbDrone.Core.Housekeeping.Housekeepers
|
||||
|
||||
public void Clean()
|
||||
{
|
||||
var mapper = _database.OpenConnection();
|
||||
using var mapper = _database.OpenConnection();
|
||||
|
||||
if (_database.DatabaseType == DatabaseType.PostgreSQL)
|
||||
{
|
||||
mapper.Execute(@"DELETE FROM ""PendingReleases""
|
||||
WHERE ""Added"" < @TwoWeeksAgo
|
||||
AND ""Reason"" = ANY (@Reasons)",
|
||||
new
|
||||
{
|
||||
TwoWeeksAgo = DateTime.UtcNow.AddDays(-14),
|
||||
Reasons = new[] { (int)PendingReleaseReason.DownloadClientUnavailable, (int)PendingReleaseReason.Fallback }
|
||||
});
|
||||
WHERE ""Added"" < @TwoWeeksAgo
|
||||
AND ""Reason"" = ANY (@Reasons)",
|
||||
new
|
||||
{
|
||||
TwoWeeksAgo = DateTime.UtcNow.AddDays(-14),
|
||||
Reasons = new[] { (int)PendingReleaseReason.DownloadClientUnavailable, (int)PendingReleaseReason.Fallback }
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
mapper.Execute(@"DELETE FROM ""PendingReleases""
|
||||
WHERE ""Added"" < @TwoWeeksAgo
|
||||
AND ""REASON"" IN @Reasons",
|
||||
new
|
||||
{
|
||||
TwoWeeksAgo = DateTime.UtcNow.AddDays(-14),
|
||||
Reasons = new[] { (int)PendingReleaseReason.DownloadClientUnavailable, (int)PendingReleaseReason.Fallback }
|
||||
});
|
||||
mapper.Execute(@"DELETE FROM ""PendingReleases""
|
||||
WHERE ""Added"" < @TwoWeeksAgo
|
||||
AND ""REASON"" IN @Reasons",
|
||||
new
|
||||
{
|
||||
TwoWeeksAgo = DateTime.UtcNow.AddDays(-14),
|
||||
Reasons = new[] { (int)PendingReleaseReason.DownloadClientUnavailable, (int)PendingReleaseReason.Fallback }
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,44 +21,38 @@ namespace NzbDrone.Core.Housekeeping.Housekeepers
|
||||
|
||||
private void DeleteDuplicateAuthorMetadata()
|
||||
{
|
||||
using (var mapper = _database.OpenConnection())
|
||||
{
|
||||
mapper.Execute(@"DELETE FROM ""MetadataFiles""
|
||||
WHERE ""Id"" IN (
|
||||
SELECT MIN(""Id"") FROM ""MetadataFiles""
|
||||
WHERE ""Type"" = 1
|
||||
GROUP BY ""AuthorId"", ""Consumer""
|
||||
HAVING COUNT(""AuthorId"") > 1
|
||||
)");
|
||||
}
|
||||
using var mapper = _database.OpenConnection();
|
||||
mapper.Execute(@"DELETE FROM ""MetadataFiles""
|
||||
WHERE ""Id"" IN (
|
||||
SELECT MIN(""Id"") FROM ""MetadataFiles""
|
||||
WHERE ""Type"" = 1
|
||||
GROUP BY ""AuthorId"", ""Consumer""
|
||||
HAVING COUNT(""AuthorId"") > 1
|
||||
)");
|
||||
}
|
||||
|
||||
private void DeleteDuplicateBookMetadata()
|
||||
{
|
||||
using (var mapper = _database.OpenConnection())
|
||||
{
|
||||
mapper.Execute(@"DELETE FROM ""MetadataFiles""
|
||||
WHERE ""Id"" IN (
|
||||
SELECT MIN(""Id"") FROM ""MetadataFiles""
|
||||
WHERE ""Type"" IN (2, 4)
|
||||
GROUP BY ""BookId"", ""Consumer""
|
||||
HAVING COUNT(""BookId"") > 1
|
||||
)");
|
||||
}
|
||||
using var mapper = _database.OpenConnection();
|
||||
mapper.Execute(@"DELETE FROM ""MetadataFiles""
|
||||
WHERE ""Id"" IN (
|
||||
SELECT MIN(""Id"") FROM ""MetadataFiles""
|
||||
WHERE ""Type"" IN (2, 4)
|
||||
GROUP BY ""BookId"", ""Consumer""
|
||||
HAVING COUNT(""BookId"") > 1
|
||||
)");
|
||||
}
|
||||
|
||||
private void DeleteDuplicateBookFileMetadata()
|
||||
{
|
||||
using (var mapper = _database.OpenConnection())
|
||||
{
|
||||
mapper.Execute(@"DELETE FROM ""MetadataFiles""
|
||||
WHERE ""Id"" IN (
|
||||
SELECT MIN(""Id"") FROM ""MetadataFiles""
|
||||
WHERE ""Type"" IN (2, 4)
|
||||
GROUP BY ""BookFileId"", ""Consumer""
|
||||
HAVING COUNT(""BookFileId"") > 1
|
||||
)");
|
||||
}
|
||||
using var mapper = _database.OpenConnection();
|
||||
mapper.Execute(@"DELETE FROM ""MetadataFiles""
|
||||
WHERE ""Id"" IN (
|
||||
SELECT MIN(""Id"") FROM ""MetadataFiles""
|
||||
WHERE ""Type"" IN (2, 4)
|
||||
GROUP BY ""BookFileId"", ""Consumer""
|
||||
HAVING COUNT(""BookFileId"") > 1
|
||||
)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,15 +14,13 @@ namespace NzbDrone.Core.Housekeeping.Housekeepers
|
||||
|
||||
public void Clean()
|
||||
{
|
||||
using (var mapper = _database.OpenConnection())
|
||||
{
|
||||
mapper.Execute(@"DELETE FROM ""AuthorMetadata""
|
||||
WHERE ""Id"" IN (
|
||||
SELECT ""AuthorMetadata"".""Id"" FROM ""AuthorMetadata""
|
||||
LEFT OUTER JOIN ""Books"" ON ""Books"".""AuthorMetadataId"" = ""AuthorMetadata"".""Id""
|
||||
LEFT OUTER JOIN ""Authors"" ON ""Authors"".""AuthorMetadataId"" = ""AuthorMetadata"".""Id""
|
||||
WHERE ""Books"".""Id"" IS NULL AND ""Authors"".""Id"" IS NULL)");
|
||||
}
|
||||
using var mapper = _database.OpenConnection();
|
||||
mapper.Execute(@"DELETE FROM ""AuthorMetadata""
|
||||
WHERE ""Id"" IN (
|
||||
SELECT ""AuthorMetadata"".""Id"" FROM ""AuthorMetadata""
|
||||
LEFT OUTER JOIN ""Books"" ON ""Books"".""AuthorMetadataId"" = ""AuthorMetadata"".""Id""
|
||||
LEFT OUTER JOIN ""Authors"" ON ""Authors"".""AuthorMetadataId"" = ""AuthorMetadata"".""Id""
|
||||
WHERE ""Books"".""Id"" IS NULL AND ""Authors"".""Id"" IS NULL)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,15 +14,13 @@ namespace NzbDrone.Core.Housekeeping.Housekeepers
|
||||
|
||||
public void Clean()
|
||||
{
|
||||
using (var mapper = _database.OpenConnection())
|
||||
{
|
||||
mapper.Execute(@"DELETE FROM ""Blocklist""
|
||||
WHERE ""Id"" IN (
|
||||
SELECT ""Blocklist"".""Id"" FROM ""Blocklist""
|
||||
LEFT OUTER JOIN ""Authors""
|
||||
ON ""Blocklist"".""AuthorId"" = ""Authors"".""Id""
|
||||
WHERE ""Authors"".""Id"" IS NULL)");
|
||||
}
|
||||
using var mapper = _database.OpenConnection();
|
||||
mapper.Execute(@"DELETE FROM ""Blocklist""
|
||||
WHERE ""Id"" IN (
|
||||
SELECT ""Blocklist"".""Id"" FROM ""Blocklist""
|
||||
LEFT OUTER JOIN ""Authors""
|
||||
ON ""Blocklist"".""AuthorId"" = ""Authors"".""Id""
|
||||
WHERE ""Authors"".""Id"" IS NULL)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,17 +14,16 @@ namespace NzbDrone.Core.Housekeeping.Housekeepers
|
||||
|
||||
public void Clean()
|
||||
{
|
||||
using (var mapper = _database.OpenConnection())
|
||||
{
|
||||
// Unlink where track no longer exists
|
||||
mapper.Execute(@"UPDATE ""BookFiles""
|
||||
SET ""EditionId"" = 0
|
||||
WHERE ""Id"" IN (
|
||||
SELECT ""BookFiles"".""Id"" FROM ""BookFiles""
|
||||
LEFT OUTER JOIN ""Editions""
|
||||
ON ""BookFiles"".""EditionId"" = ""Editions"".""Id""
|
||||
WHERE ""Editions"".""Id"" IS NULL)");
|
||||
}
|
||||
using var mapper = _database.OpenConnection();
|
||||
|
||||
// Unlink where books no longer exists
|
||||
mapper.Execute(@"UPDATE ""BookFiles""
|
||||
SET ""EditionId"" = 0
|
||||
WHERE ""Id"" IN (
|
||||
SELECT ""BookFiles"".""Id"" FROM ""BookFiles""
|
||||
LEFT OUTER JOIN ""Editions""
|
||||
ON ""BookFiles"".""EditionId"" = ""Editions"".""Id""
|
||||
WHERE ""Editions"".""Id"" IS NULL)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,15 +14,13 @@ namespace NzbDrone.Core.Housekeeping.Housekeepers
|
||||
|
||||
public void Clean()
|
||||
{
|
||||
using (var mapper = _database.OpenConnection())
|
||||
{
|
||||
mapper.Execute(@"DELETE FROM ""Books""
|
||||
WHERE ""Id"" IN (
|
||||
SELECT ""Books"".""Id"" FROM ""Books""
|
||||
LEFT OUTER JOIN ""Authors""
|
||||
ON ""Books"".""AuthorMetadataId"" = ""Authors"".""AuthorMetadataId""
|
||||
WHERE ""Authors"".""Id"" IS NULL)");
|
||||
}
|
||||
using var mapper = _database.OpenConnection();
|
||||
mapper.Execute(@"DELETE FROM ""Books""
|
||||
WHERE ""Id"" IN (
|
||||
SELECT ""Books"".""Id"" FROM ""Books""
|
||||
LEFT OUTER JOIN ""Authors""
|
||||
ON ""Books"".""AuthorMetadataId"" = ""Authors"".""AuthorMetadataId""
|
||||
WHERE ""Authors"".""Id"" IS NULL)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,14 +14,14 @@ namespace NzbDrone.Core.Housekeeping.Housekeepers
|
||||
|
||||
public void Clean()
|
||||
{
|
||||
var mapper = _database.OpenConnection();
|
||||
using var mapper = _database.OpenConnection();
|
||||
|
||||
mapper.Execute(@"DELETE FROM ""DownloadClientStatus""
|
||||
WHERE ""Id"" IN (
|
||||
SELECT ""DownloadClientStatus"".""Id"" FROM ""DownloadClientStatus""
|
||||
LEFT OUTER JOIN ""DownloadClients""
|
||||
ON ""DownloadClientStatus"".""ProviderId"" = ""DownloadClients"".""Id""
|
||||
WHERE ""DownloadClients"".""Id"" IS NULL)");
|
||||
WHERE ""Id"" IN (
|
||||
SELECT ""DownloadClientStatus"".""Id"" FROM ""DownloadClientStatus""
|
||||
LEFT OUTER JOIN ""DownloadClients""
|
||||
ON ""DownloadClientStatus"".""ProviderId"" = ""DownloadClients"".""Id""
|
||||
WHERE ""DownloadClients"".""Id"" IS NULL)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,15 +14,13 @@ namespace NzbDrone.Core.Housekeeping.Housekeepers
|
||||
|
||||
public void Clean()
|
||||
{
|
||||
using (var mapper = _database.OpenConnection())
|
||||
{
|
||||
mapper.Execute(@"DELETE FROM ""Editions""
|
||||
WHERE ""Id"" IN (
|
||||
SELECT ""Editions"".""Id"" FROM ""Editions""
|
||||
LEFT OUTER JOIN ""Books""
|
||||
ON ""Editions"".""BookId"" = ""Books"".""Id""
|
||||
WHERE ""Books"".""Id"" IS NULL)");
|
||||
}
|
||||
using var mapper = _database.OpenConnection();
|
||||
mapper.Execute(@"DELETE FROM ""Editions""
|
||||
WHERE ""Id"" IN (
|
||||
SELECT ""Editions"".""Id"" FROM ""Editions""
|
||||
LEFT OUTER JOIN ""Books""
|
||||
ON ""Editions"".""BookId"" = ""Books"".""Id""
|
||||
WHERE ""Books"".""Id"" IS NULL)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,28 +20,24 @@ namespace NzbDrone.Core.Housekeeping.Housekeepers
|
||||
|
||||
private void CleanupOrphanedByAuthor()
|
||||
{
|
||||
using (var mapper = _database.OpenConnection())
|
||||
{
|
||||
mapper.Execute(@"DELETE FROM ""History""
|
||||
WHERE ""Id"" IN (
|
||||
SELECT ""History"".""Id"" FROM ""History""
|
||||
LEFT OUTER JOIN ""Authors""
|
||||
ON ""History"".""AuthorId"" = ""Authors"".""Id""
|
||||
WHERE ""Authors"".""Id"" IS NULL)");
|
||||
}
|
||||
using var mapper = _database.OpenConnection();
|
||||
mapper.Execute(@"DELETE FROM ""History""
|
||||
WHERE ""Id"" IN (
|
||||
SELECT ""History"".""Id"" FROM ""History""
|
||||
LEFT OUTER JOIN ""Authors""
|
||||
ON ""History"".""AuthorId"" = ""Authors"".""Id""
|
||||
WHERE ""Authors"".""Id"" IS NULL)");
|
||||
}
|
||||
|
||||
private void CleanupOrphanedByBook()
|
||||
{
|
||||
using (var mapper = _database.OpenConnection())
|
||||
{
|
||||
mapper.Execute(@"DELETE FROM ""History""
|
||||
WHERE ""Id"" IN (
|
||||
SELECT ""History"".""Id"" FROM ""History""
|
||||
LEFT OUTER JOIN ""Books""
|
||||
ON ""History"".""BookId"" = ""Books"".""Id""
|
||||
WHERE ""Books"".""Id"" IS NULL)");
|
||||
}
|
||||
using var mapper = _database.OpenConnection();
|
||||
mapper.Execute(@"DELETE FROM ""History""
|
||||
WHERE ""Id"" IN (
|
||||
SELECT ""History"".""Id"" FROM ""History""
|
||||
LEFT OUTER JOIN ""Books""
|
||||
ON ""History"".""BookId"" = ""Books"".""Id""
|
||||
WHERE ""Books"".""Id"" IS NULL)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,15 +14,13 @@ namespace NzbDrone.Core.Housekeeping.Housekeepers
|
||||
|
||||
public void Clean()
|
||||
{
|
||||
using (var mapper = _database.OpenConnection())
|
||||
{
|
||||
mapper.Execute(@"DELETE FROM ""ImportListStatus""
|
||||
WHERE ""Id"" IN (
|
||||
SELECT ""ImportListStatus"".""Id"" FROM ""ImportListStatus""
|
||||
LEFT OUTER JOIN ""ImportLists""
|
||||
ON ""ImportListStatus"".""ProviderId"" = ""ImportLists"".""Id""
|
||||
WHERE ""ImportLists"".""Id"" IS NULL)");
|
||||
}
|
||||
using var mapper = _database.OpenConnection();
|
||||
mapper.Execute(@"DELETE FROM ""ImportListStatus""
|
||||
WHERE ""Id"" IN (
|
||||
SELECT ""ImportListStatus"".""Id"" FROM ""ImportListStatus""
|
||||
LEFT OUTER JOIN ""ImportLists""
|
||||
ON ""ImportListStatus"".""ProviderId"" = ""ImportLists"".""Id""
|
||||
WHERE ""ImportLists"".""Id"" IS NULL)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,15 +14,13 @@ namespace NzbDrone.Core.Housekeeping.Housekeepers
|
||||
|
||||
public void Clean()
|
||||
{
|
||||
using (var mapper = _database.OpenConnection())
|
||||
{
|
||||
mapper.Execute(@"DELETE FROM ""IndexerStatus""
|
||||
WHERE ""Id"" IN (
|
||||
SELECT ""IndexerStatus"".""Id"" FROM ""IndexerStatus""
|
||||
LEFT OUTER JOIN ""Indexers""
|
||||
ON ""IndexerStatus"".""ProviderId"" = ""Indexers"".""Id""
|
||||
WHERE ""Indexers"".""Id"" IS NULL)");
|
||||
}
|
||||
using var mapper = _database.OpenConnection();
|
||||
mapper.Execute(@"DELETE FROM ""IndexerStatus""
|
||||
WHERE ""Id"" IN (
|
||||
SELECT ""IndexerStatus"".""Id"" FROM ""IndexerStatus""
|
||||
LEFT OUTER JOIN ""Indexers""
|
||||
ON ""IndexerStatus"".""ProviderId"" = ""Indexers"".""Id""
|
||||
WHERE ""Indexers"".""Id"" IS NULL)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,67 +23,57 @@ namespace NzbDrone.Core.Housekeeping.Housekeepers
|
||||
|
||||
private void DeleteOrphanedByAuthor()
|
||||
{
|
||||
using (var mapper = _database.OpenConnection())
|
||||
{
|
||||
mapper.Execute(@"DELETE FROM ""MetadataFiles""
|
||||
WHERE ""Id"" IN (
|
||||
SELECT ""MetadataFiles"".""Id"" FROM ""MetadataFiles""
|
||||
LEFT OUTER JOIN ""Authors""
|
||||
ON ""MetadataFiles"".""AuthorId"" = ""Authors"".""Id""
|
||||
WHERE ""Authors"".""Id"" IS NULL)");
|
||||
}
|
||||
using var mapper = _database.OpenConnection();
|
||||
mapper.Execute(@"DELETE FROM ""MetadataFiles""
|
||||
WHERE ""Id"" IN (
|
||||
SELECT ""MetadataFiles"".""Id"" FROM ""MetadataFiles""
|
||||
LEFT OUTER JOIN ""Authors""
|
||||
ON ""MetadataFiles"".""AuthorId"" = ""Authors"".""Id""
|
||||
WHERE ""Authors"".""Id"" IS NULL)");
|
||||
}
|
||||
|
||||
private void DeleteOrphanedByBook()
|
||||
{
|
||||
using (var mapper = _database.OpenConnection())
|
||||
{
|
||||
mapper.Execute(@"DELETE FROM ""MetadataFiles""
|
||||
WHERE ""Id"" IN (
|
||||
SELECT ""MetadataFiles"".""Id"" FROM ""MetadataFiles""
|
||||
LEFT OUTER JOIN ""Books""
|
||||
ON ""MetadataFiles"".""BookId"" = ""Books"".""Id""
|
||||
WHERE ""MetadataFiles"".""BookId"" > 0
|
||||
AND ""Books"".""Id"" IS NULL)");
|
||||
}
|
||||
using var mapper = _database.OpenConnection();
|
||||
mapper.Execute(@"DELETE FROM ""MetadataFiles""
|
||||
WHERE ""Id"" IN (
|
||||
SELECT ""MetadataFiles"".""Id"" FROM ""MetadataFiles""
|
||||
LEFT OUTER JOIN ""Books""
|
||||
ON ""MetadataFiles"".""BookId"" = ""Books"".""Id""
|
||||
WHERE ""MetadataFiles"".""BookId"" > 0
|
||||
AND ""Books"".""Id"" IS NULL)");
|
||||
}
|
||||
|
||||
private void DeleteOrphanedByTrackFile()
|
||||
{
|
||||
using (var mapper = _database.OpenConnection())
|
||||
{
|
||||
mapper.Execute(@"DELETE FROM ""MetadataFiles""
|
||||
WHERE ""Id"" IN (
|
||||
SELECT ""MetadataFiles"".""Id"" FROM ""MetadataFiles""
|
||||
LEFT OUTER JOIN ""BookFiles""
|
||||
ON ""MetadataFiles"".""BookFileId"" = ""BookFiles"".""Id""
|
||||
WHERE ""MetadataFiles"".""BookFileId"" > 0
|
||||
AND ""BookFiles"".""Id"" IS NULL)");
|
||||
}
|
||||
using var mapper = _database.OpenConnection();
|
||||
mapper.Execute(@"DELETE FROM ""MetadataFiles""
|
||||
WHERE ""Id"" IN (
|
||||
SELECT ""MetadataFiles"".""Id"" FROM ""MetadataFiles""
|
||||
LEFT OUTER JOIN ""BookFiles""
|
||||
ON ""MetadataFiles"".""BookFileId"" = ""BookFiles"".""Id""
|
||||
WHERE ""MetadataFiles"".""BookFileId"" > 0
|
||||
AND ""BookFiles"".""Id"" IS NULL)");
|
||||
}
|
||||
|
||||
private void DeleteWhereBookIdIsZero()
|
||||
{
|
||||
using (var mapper = _database.OpenConnection())
|
||||
{
|
||||
mapper.Execute(@"DELETE FROM ""MetadataFiles""
|
||||
WHERE ""Id"" IN (
|
||||
SELECT ""Id"" FROM ""MetadataFiles""
|
||||
WHERE ""Type"" IN (2, 4)
|
||||
AND ""BookId"" = 0)");
|
||||
}
|
||||
using var mapper = _database.OpenConnection();
|
||||
mapper.Execute(@"DELETE FROM ""MetadataFiles""
|
||||
WHERE ""Id"" IN (
|
||||
SELECT ""Id"" FROM ""MetadataFiles""
|
||||
WHERE ""Type"" IN (2, 4)
|
||||
AND ""BookId"" = 0)");
|
||||
}
|
||||
|
||||
private void DeleteWhereTrackFileIsZero()
|
||||
{
|
||||
using (var mapper = _database.OpenConnection())
|
||||
{
|
||||
mapper.Execute(@"DELETE FROM ""MetadataFiles""
|
||||
WHERE ""Id"" IN (
|
||||
SELECT ""Id"" FROM ""MetadataFiles""
|
||||
WHERE ""Type"" IN (2, 4)
|
||||
AND ""BookFileId"" = 0)");
|
||||
}
|
||||
using var mapper = _database.OpenConnection();
|
||||
mapper.Execute(@"DELETE FROM ""MetadataFiles""
|
||||
WHERE ""Id"" IN (
|
||||
SELECT ""Id"" FROM ""MetadataFiles""
|
||||
WHERE ""Type"" IN (2, 4)
|
||||
AND ""BookFileId"" = 0)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,15 +14,13 @@ namespace NzbDrone.Core.Housekeeping.Housekeepers
|
||||
|
||||
public void Clean()
|
||||
{
|
||||
using (var mapper = _database.OpenConnection())
|
||||
{
|
||||
mapper.Execute(@"DELETE FROM ""PendingReleases""
|
||||
WHERE ""Id"" IN (
|
||||
SELECT ""PendingReleases"".""Id"" FROM ""PendingReleases""
|
||||
LEFT OUTER JOIN ""Authors""
|
||||
ON ""PendingReleases"".""AuthorId"" = ""Authors"".""Id""
|
||||
WHERE ""Authors"".""Id"" IS NULL)");
|
||||
}
|
||||
using var mapper = _database.OpenConnection();
|
||||
mapper.Execute(@"DELETE FROM ""PendingReleases""
|
||||
WHERE ""Id"" IN (
|
||||
SELECT ""PendingReleases"".""Id"" FROM ""PendingReleases""
|
||||
LEFT OUTER JOIN ""Authors""
|
||||
ON ""PendingReleases"".""AuthorId"" = ""Authors"".""Id""
|
||||
WHERE ""Authors"".""Id"" IS NULL)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,22 +14,20 @@ namespace NzbDrone.Core.Housekeeping.Housekeepers
|
||||
|
||||
public void Clean()
|
||||
{
|
||||
using (var mapper = _database.OpenConnection())
|
||||
{
|
||||
mapper.Execute(@"DELETE FROM ""SeriesBookLink""
|
||||
WHERE ""Id"" IN (
|
||||
SELECT ""SeriesBookLink"".""Id"" FROM ""SeriesBookLink""
|
||||
LEFT OUTER JOIN ""Books""
|
||||
ON ""SeriesBookLink"".""BookId"" = ""Books"".""Id""
|
||||
WHERE ""Books"".""Id"" IS NULL)");
|
||||
using var mapper = _database.OpenConnection();
|
||||
mapper.Execute(@"DELETE FROM ""SeriesBookLink""
|
||||
WHERE ""Id"" IN (
|
||||
SELECT ""SeriesBookLink"".""Id"" FROM ""SeriesBookLink""
|
||||
LEFT OUTER JOIN ""Books""
|
||||
ON ""SeriesBookLink"".""BookId"" = ""Books"".""Id""
|
||||
WHERE ""Books"".""Id"" IS NULL)");
|
||||
|
||||
mapper.Execute(@"DELETE FROM ""SeriesBookLink""
|
||||
WHERE ""Id"" IN (
|
||||
SELECT ""SeriesBookLink"".""Id"" FROM ""SeriesBookLink""
|
||||
LEFT OUTER JOIN ""Series""
|
||||
ON ""SeriesBookLink"".""SeriesId"" = ""Series"".""Id""
|
||||
WHERE ""Series"".""Id"" IS NULL)");
|
||||
}
|
||||
mapper.Execute(@"DELETE FROM ""SeriesBookLink""
|
||||
WHERE ""Id"" IN (
|
||||
SELECT ""SeriesBookLink"".""Id"" FROM ""SeriesBookLink""
|
||||
LEFT OUTER JOIN ""Series""
|
||||
ON ""SeriesBookLink"".""SeriesId"" = ""Series"".""Id""
|
||||
WHERE ""Series"".""Id"" IS NULL)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,31 +18,29 @@ namespace NzbDrone.Core.Housekeeping.Housekeepers
|
||||
|
||||
public void Clean()
|
||||
{
|
||||
using (var mapper = _database.OpenConnection())
|
||||
using var mapper = _database.OpenConnection();
|
||||
var usedTags = new[] { "Authors", "Notifications", "DelayProfiles", "ReleaseProfiles", "ImportLists", "Indexers" }
|
||||
.SelectMany(v => GetUsedTags(v, mapper))
|
||||
.Distinct()
|
||||
.ToArray();
|
||||
|
||||
if (usedTags.Any())
|
||||
{
|
||||
var usedTags = new[] { "Authors", "Notifications", "DelayProfiles", "ReleaseProfiles", "ImportLists", "Indexers" }
|
||||
.SelectMany(v => GetUsedTags(v, mapper))
|
||||
.Distinct()
|
||||
.ToArray();
|
||||
var usedTagsList = usedTags.Select(d => d.ToString()).Join(",");
|
||||
|
||||
if (usedTags.Any())
|
||||
if (_database.DatabaseType == DatabaseType.PostgreSQL)
|
||||
{
|
||||
var usedTagsList = usedTags.Select(d => d.ToString()).Join(",");
|
||||
|
||||
if (_database.DatabaseType == DatabaseType.PostgreSQL)
|
||||
{
|
||||
mapper.Execute($"DELETE FROM \"Tags\" WHERE NOT \"Id\" = ANY (\'{{{usedTagsList}}}\'::int[])");
|
||||
}
|
||||
else
|
||||
{
|
||||
mapper.Execute($"DELETE FROM \"Tags\" WHERE NOT \"Id\" IN ({usedTagsList})");
|
||||
}
|
||||
mapper.Execute($"DELETE FROM \"Tags\" WHERE NOT \"Id\" = ANY (\'{{{usedTagsList}}}\'::int[])");
|
||||
}
|
||||
else
|
||||
{
|
||||
mapper.Execute("DELETE FROM \"Tags\"");
|
||||
mapper.Execute($"DELETE FROM \"Tags\" WHERE NOT \"Id\" IN ({usedTagsList})");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mapper.Execute("DELETE FROM \"Tags\"");
|
||||
}
|
||||
}
|
||||
|
||||
private int[] GetUsedTags(string table, IDbConnection mapper)
|
||||
|
||||
@@ -24,13 +24,11 @@ namespace NzbDrone.Core.Housekeeping.Housekeepers
|
||||
_logger.Debug("Not running scheduled task last execution cleanup during debug");
|
||||
}
|
||||
|
||||
using (var mapper = _database.OpenConnection())
|
||||
{
|
||||
mapper.Execute(@"UPDATE ""ScheduledTasks""
|
||||
SET ""LastExecution"" = @time
|
||||
WHERE ""LastExecution"" > @time",
|
||||
new { time = DateTime.UtcNow });
|
||||
}
|
||||
using var mapper = _database.OpenConnection();
|
||||
mapper.Execute(@"UPDATE ""ScheduledTasks""
|
||||
SET ""LastExecution"" = @time
|
||||
WHERE ""LastExecution"" > @time",
|
||||
new { time = DateTime.UtcNow });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,11 +108,11 @@ namespace NzbDrone.Core.ImportLists.Readarr
|
||||
return new
|
||||
{
|
||||
options = devices.OrderBy(d => d.Name, StringComparer.InvariantCultureIgnoreCase)
|
||||
.Select(d => new
|
||||
{
|
||||
Value = d.Id,
|
||||
Name = d.Name
|
||||
})
|
||||
.Select(d => new
|
||||
{
|
||||
Value = d.Id,
|
||||
Name = d.Name
|
||||
})
|
||||
};
|
||||
}
|
||||
|
||||
@@ -123,28 +123,26 @@ namespace NzbDrone.Core.ImportLists.Readarr
|
||||
return new
|
||||
{
|
||||
options = devices.OrderBy(d => d.Label, StringComparer.InvariantCultureIgnoreCase)
|
||||
.Select(d => new
|
||||
{
|
||||
Value = d.Id,
|
||||
Name = d.Label
|
||||
})
|
||||
.Select(d => new
|
||||
{
|
||||
Value = d.Id,
|
||||
Name = d.Label
|
||||
})
|
||||
};
|
||||
}
|
||||
|
||||
if (action == "getRootFolders")
|
||||
{
|
||||
Settings.Validate().Filter("ApiKey").ThrowOnError();
|
||||
|
||||
var remoteRootfolders = _readarrV1Proxy.GetRootFolders(Settings);
|
||||
var remoteRootFolders = _readarrV1Proxy.GetRootFolders(Settings);
|
||||
|
||||
return new
|
||||
{
|
||||
options = remoteRootfolders.OrderBy(d => d.Path, StringComparer.InvariantCultureIgnoreCase)
|
||||
.Select(d => new
|
||||
{
|
||||
value = d.Path,
|
||||
name = d.Path
|
||||
})
|
||||
options = remoteRootFolders.OrderBy(d => d.Path, StringComparer.InvariantCultureIgnoreCase)
|
||||
.Select(d => new
|
||||
{
|
||||
value = d.Path,
|
||||
name = d.Path
|
||||
})
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -69,13 +69,19 @@ namespace NzbDrone.Core.ImportLists.Readarr
|
||||
return new ValidationFailure("ApiKey", "API Key is invalid");
|
||||
}
|
||||
|
||||
_logger.Error(ex, "Unable to send test message");
|
||||
return new ValidationFailure("ApiKey", "Unable to send test message");
|
||||
if (ex.Response.HasHttpRedirect)
|
||||
{
|
||||
_logger.Error(ex, "Readarr returned redirect and is invalid");
|
||||
return new ValidationFailure("BaseUrl", "Readarr URL is invalid, are you missing a URL base?");
|
||||
}
|
||||
|
||||
_logger.Error(ex, "Unable to connect to import list.");
|
||||
return new ValidationFailure(string.Empty, $"Unable to connect to import list: {ex.Message}. Check the log surrounding this error for details.");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, "Unable to send test message");
|
||||
return new ValidationFailure("", "Unable to send test message");
|
||||
_logger.Error(ex, "Unable to connect to import list.");
|
||||
return new ValidationFailure(string.Empty, $"Unable to connect to import list: {ex.Message}. Check the log surrounding this error for details.");
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -90,11 +96,18 @@ namespace NzbDrone.Core.ImportLists.Readarr
|
||||
|
||||
var baseUrl = settings.BaseUrl.TrimEnd('/');
|
||||
|
||||
var request = new HttpRequestBuilder(baseUrl).Resource(resource).Accept(HttpAccept.Json)
|
||||
.SetHeader("X-Api-Key", settings.ApiKey).Build();
|
||||
var request = new HttpRequestBuilder(baseUrl).Resource(resource)
|
||||
.Accept(HttpAccept.Json)
|
||||
.SetHeader("X-Api-Key", settings.ApiKey)
|
||||
.Build();
|
||||
|
||||
var response = _httpClient.Get(request);
|
||||
|
||||
if ((int)response.StatusCode >= 300)
|
||||
{
|
||||
throw new HttpException(response);
|
||||
}
|
||||
|
||||
var results = JsonConvert.DeserializeObject<List<TResource>>(response.Content);
|
||||
|
||||
return results;
|
||||
|
||||
@@ -2,6 +2,8 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using FluentValidation.Results;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Extensions;
|
||||
@@ -77,6 +79,7 @@ namespace NzbDrone.Core.Indexers
|
||||
{
|
||||
var releases = new List<ReleaseInfo>();
|
||||
var url = string.Empty;
|
||||
var minimumBackoff = TimeSpan.FromHours(1);
|
||||
|
||||
try
|
||||
{
|
||||
@@ -169,8 +172,7 @@ namespace NzbDrone.Core.Indexers
|
||||
}
|
||||
catch (WebException webException)
|
||||
{
|
||||
if (webException.Status == WebExceptionStatus.NameResolutionFailure ||
|
||||
webException.Status == WebExceptionStatus.ConnectFailure)
|
||||
if (webException.Status is WebExceptionStatus.NameResolutionFailure or WebExceptionStatus.ConnectFailure)
|
||||
{
|
||||
_indexerStatusService.RecordConnectionFailure(Definition.Id);
|
||||
}
|
||||
@@ -180,7 +182,7 @@ namespace NzbDrone.Core.Indexers
|
||||
}
|
||||
|
||||
if (webException.Message.Contains("502") || webException.Message.Contains("503") ||
|
||||
webException.Message.Contains("timed out"))
|
||||
webException.Message.Contains("504") || webException.Message.Contains("timed out"))
|
||||
{
|
||||
_logger.Warn("{0} server is currently unavailable. {1} {2}", this, url, webException.Message);
|
||||
}
|
||||
@@ -191,34 +193,29 @@ namespace NzbDrone.Core.Indexers
|
||||
}
|
||||
catch (TooManyRequestsException ex)
|
||||
{
|
||||
if (ex.RetryAfter != TimeSpan.Zero)
|
||||
{
|
||||
_indexerStatusService.RecordFailure(Definition.Id, ex.RetryAfter);
|
||||
}
|
||||
else
|
||||
{
|
||||
_indexerStatusService.RecordFailure(Definition.Id, TimeSpan.FromHours(1));
|
||||
}
|
||||
var retryTime = ex.RetryAfter != TimeSpan.Zero ? ex.RetryAfter : minimumBackoff;
|
||||
_indexerStatusService.RecordFailure(Definition.Id, retryTime);
|
||||
|
||||
_logger.Warn("API Request Limit reached for {0}", this);
|
||||
_logger.Warn("API Request Limit reached for {0}. Disabled for {1}", this, retryTime);
|
||||
}
|
||||
catch (HttpException ex)
|
||||
{
|
||||
_indexerStatusService.RecordFailure(Definition.Id);
|
||||
_logger.Warn("{0} {1}", this, ex.Message);
|
||||
}
|
||||
catch (RequestLimitReachedException ex)
|
||||
{
|
||||
if (ex.RetryAfter != TimeSpan.Zero)
|
||||
if (ex.Response.HasHttpServerError)
|
||||
{
|
||||
_indexerStatusService.RecordFailure(Definition.Id, ex.RetryAfter);
|
||||
_logger.Warn("Unable to connect to {0} at [{1}]. Indexer's server is unavailable. Try again later. {2}", this, url, ex.Message);
|
||||
}
|
||||
else
|
||||
{
|
||||
_indexerStatusService.RecordFailure(Definition.Id, TimeSpan.FromHours(1));
|
||||
_logger.Warn("{0} {1}", this, ex.Message);
|
||||
}
|
||||
}
|
||||
catch (RequestLimitReachedException ex)
|
||||
{
|
||||
var retryTime = ex.RetryAfter != TimeSpan.Zero ? ex.RetryAfter : minimumBackoff;
|
||||
_indexerStatusService.RecordFailure(Definition.Id, retryTime);
|
||||
|
||||
_logger.Warn("API Request Limit reached for {0}", this);
|
||||
_logger.Warn("API Request Limit reached for {0}. Disabled for {1}", this, retryTime);
|
||||
}
|
||||
catch (ApiKeyException)
|
||||
{
|
||||
@@ -238,6 +235,11 @@ namespace NzbDrone.Core.Indexers
|
||||
_logger.Error(ex, "CAPTCHA token required for {0}, check indexer settings.", this);
|
||||
}
|
||||
}
|
||||
catch (TaskCanceledException ex)
|
||||
{
|
||||
_indexerStatusService.RecordFailure(Definition.Id);
|
||||
_logger.Warn(ex, "Unable to connect to indexer, possibly due to a timeout. {0}", url);
|
||||
}
|
||||
catch (IndexerException ex)
|
||||
{
|
||||
_indexerStatusService.RecordFailure(Definition.Id);
|
||||
@@ -333,6 +335,8 @@ namespace NzbDrone.Core.Indexers
|
||||
catch (RequestLimitReachedException ex)
|
||||
{
|
||||
_logger.Warn("Request limit reached: " + ex.Message);
|
||||
|
||||
return new ValidationFailure(string.Empty, "Request limit reached: " + ex.Message);
|
||||
}
|
||||
catch (CloudFlareCaptchaException ex)
|
||||
{
|
||||
@@ -357,6 +361,55 @@ namespace NzbDrone.Core.Indexers
|
||||
|
||||
return new ValidationFailure(string.Empty, "Unable to connect to indexer. " + ex.Message);
|
||||
}
|
||||
catch (HttpException ex)
|
||||
{
|
||||
if (ex.Response.StatusCode == HttpStatusCode.BadRequest &&
|
||||
ex.Response.Content.Contains("not support the requested query"))
|
||||
{
|
||||
_logger.Warn(ex, "Indexer does not support the query");
|
||||
return new ValidationFailure(string.Empty, "Indexer does not support the current query. Check if the categories and or searching for seasons/episodes are supported. Check the log for more details.");
|
||||
}
|
||||
|
||||
_logger.Warn(ex, "Unable to connect to indexer");
|
||||
if (ex.Response.HasHttpServerError)
|
||||
{
|
||||
return new ValidationFailure(string.Empty, "Unable to connect to indexer, indexer's server is unavailable. Try again later. " + ex.Message);
|
||||
}
|
||||
|
||||
if (ex.Response.StatusCode is HttpStatusCode.Forbidden or HttpStatusCode.Unauthorized)
|
||||
{
|
||||
return new ValidationFailure(string.Empty, "Unable to connect to indexer, invalid credentials. " + ex.Message);
|
||||
}
|
||||
|
||||
return new ValidationFailure(string.Empty, "Unable to connect to indexer, check the log above the ValidationFailure for more details. " + ex.Message);
|
||||
}
|
||||
catch (HttpRequestException ex)
|
||||
{
|
||||
_logger.Warn(ex, "Unable to connect to indexer");
|
||||
|
||||
return new ValidationFailure(string.Empty, "Unable to connect to indexer, please check your DNS settings and ensure IPv6 is working or disabled. " + ex.Message);
|
||||
}
|
||||
catch (TaskCanceledException ex)
|
||||
{
|
||||
_logger.Warn(ex, "Unable to connect to indexer");
|
||||
|
||||
return new ValidationFailure(string.Empty, "Unable to connect to indexer, possibly due to a timeout. Try again or check your network settings. " + ex.Message);
|
||||
}
|
||||
catch (WebException webException)
|
||||
{
|
||||
_logger.Warn("Unable to connect to indexer.");
|
||||
|
||||
if (webException.Status is WebExceptionStatus.NameResolutionFailure or WebExceptionStatus.ConnectFailure)
|
||||
{
|
||||
return new ValidationFailure(string.Empty, "Unable to connect to indexer connection failure. Check your connection to the indexer's server and DNS." + webException.Message);
|
||||
}
|
||||
|
||||
if (webException.Message.Contains("502") || webException.Message.Contains("503") ||
|
||||
webException.Message.Contains("504") || webException.Message.Contains("timed out"))
|
||||
{
|
||||
return new ValidationFailure(string.Empty, "Unable to connect to indexer, indexer's server is unavailable. Try again later. " + webException.Message);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Warn(ex, "Unable to connect to indexer");
|
||||
|
||||
@@ -121,7 +121,8 @@ namespace NzbDrone.Core.Indexers
|
||||
|
||||
protected virtual bool PreProcess(IndexerResponse indexerResponse)
|
||||
{
|
||||
if (indexerResponse.HttpResponse.StatusCode != HttpStatusCode.OK)
|
||||
// Server Down HTTP Errors are handled in HTTPIndexerBase so ignore them here
|
||||
if (indexerResponse.HttpResponse.StatusCode != HttpStatusCode.OK && !indexerResponse.HttpResponse.HasHttpServerError)
|
||||
{
|
||||
throw new IndexerException(indexerResponse, "Indexer API call resulted in an unexpected StatusCode [{0}]", indexerResponse.HttpResponse.StatusCode);
|
||||
}
|
||||
|
||||
@@ -149,7 +149,6 @@
|
||||
"RemovedFromTaskQueue": "تمت إزالته من قائمة انتظار المهام",
|
||||
"RemoveTagRemovingTag": "إزالة العلامة",
|
||||
"RemoveTagExistingTag": "علامة موجودة",
|
||||
"RemoveSelectedMessageText": "هل أنت متأكد أنك تريد إزالة العناصر المحددة من القائمة السوداء؟",
|
||||
"RemoveSelected": "ازل المحدد",
|
||||
"RemoveHelpTextWarning": "ستؤدي الإزالة إلى إزالة التنزيل والملف (الملفات) من عميل التنزيل.",
|
||||
"RemoveFromQueue": "إزالة من قائمة الانتظار",
|
||||
@@ -466,7 +465,6 @@
|
||||
"Time": "زمن",
|
||||
"Component": "مكون",
|
||||
"Blocklist": "القائمة السوداء",
|
||||
"BlocklistHelpText": "يمنع Radarr من الاستيلاء على هذا الإصدار تلقائيًا مرة أخرى",
|
||||
"BlocklistRelease": "إصدار القائمة السوداء",
|
||||
"ThisCannotBeCancelled": "لا يمكن إلغاء هذا بمجرد البدء دون إعادة تشغيل Radarr.",
|
||||
"UnselectAll": "إلغاء تحديد الكل",
|
||||
@@ -579,5 +577,20 @@
|
||||
"HiddenClickToShow": "مخفي ، انقر للعرض",
|
||||
"HideAdvanced": "إخفاء الإعدادات المتقدمة",
|
||||
"ShowAdvanced": "عرض متقدمة",
|
||||
"ShownClickToHide": "يظهر ، انقر للإخفاء"
|
||||
"ShownClickToHide": "يظهر ، انقر للإخفاء",
|
||||
"ColonReplacement": "استبدال القولون",
|
||||
"ReplaceWithDash": "استبدل بـ داش",
|
||||
"ReplaceWithSpaceDash": "استبدل بـ Space Dash",
|
||||
"ReplaceWithSpaceDashSpace": "استبدل بـ Space Dash Space",
|
||||
"DeleteRemotePathMapping": "تحرير تعيين المسار البعيد",
|
||||
"BlocklistReleases": "إصدار القائمة السوداء",
|
||||
"DeleteRemotePathMappingMessageText": "هل أنت متأكد أنك تريد حذف تعيين المسار البعيد هذا؟",
|
||||
"Negated": "نفي",
|
||||
"RemoveSelectedItemBlocklistMessageText": "هل أنت متأكد أنك تريد إزالة العناصر المحددة من القائمة السوداء؟",
|
||||
"RemoveSelectedItemQueueMessageText": "هل تريد بالتأكيد إزالة {0} عنصر {1} من قائمة الانتظار؟",
|
||||
"Required": "مطلوب",
|
||||
"DeleteConditionMessageText": "هل أنت متأكد أنك تريد حذف العلامة \"{0}\"؟",
|
||||
"RemoveSelectedItemsQueueMessageText": "هل تريد بالتأكيد إزالة {0} عنصر {1} من قائمة الانتظار؟",
|
||||
"NoEventsFound": "لم يتم العثور على أحداث",
|
||||
"BlocklistReleaseHelpText": "يمنع Radarr من الاستيلاء على هذا الإصدار تلقائيًا مرة أخرى"
|
||||
}
|
||||
|
||||
@@ -288,7 +288,6 @@
|
||||
"RemoveFromQueue": "Премахване от опашката",
|
||||
"RemoveHelpTextWarning": "Премахването ще премахне изтеглянето и файловете от клиента за изтегляне.",
|
||||
"RemoveSelected": "Премахнете избраното",
|
||||
"RemoveSelectedMessageText": "Наистина ли искате да премахнете избраните елементи от черния списък?",
|
||||
"RemoveTagExistingTag": "Съществуващ маркер",
|
||||
"RemoveTagRemovingTag": "Премахване на етикет",
|
||||
"RemovedFromTaskQueue": "Премахнато от опашката на задачите",
|
||||
@@ -578,5 +577,19 @@
|
||||
"HiddenClickToShow": "Скрито, кликнете за показване",
|
||||
"HideAdvanced": "Скрий Разширено",
|
||||
"ShowAdvanced": "Показване на напреднали",
|
||||
"ShownClickToHide": "Показано, щракнете, за да се скриете"
|
||||
"ShownClickToHide": "Показано, щракнете, за да се скриете",
|
||||
"ColonReplacement": "Подмяна на дебелото черво",
|
||||
"ReplaceWithDash": "Заменете с Dash",
|
||||
"ReplaceWithSpaceDash": "Заменете с Space Dash",
|
||||
"ReplaceWithSpaceDashSpace": "Заменете с Space Dash Space",
|
||||
"DeleteRemotePathMapping": "Редактиране на отдалечено картографиране на пътя",
|
||||
"DeleteRemotePathMappingMessageText": "Наистина ли искате да изтриете това отдалечено картографиране на пътя?",
|
||||
"BlocklistReleases": "Освобождаване на черния списък",
|
||||
"DeleteConditionMessageText": "Наистина ли искате да изтриете маркера '{0}'?",
|
||||
"RemoveSelectedItemQueueMessageText": "Наистина ли искате да премахнете {0} елемент {1} от опашката?",
|
||||
"Required": "Задължително",
|
||||
"Negated": "Отрицателно",
|
||||
"RemoveSelectedItemBlocklistMessageText": "Наистина ли искате да премахнете избраните елементи от черния списък?",
|
||||
"RemoveSelectedItemsQueueMessageText": "Наистина ли искате да премахнете {0} елемент {1} от опашката?",
|
||||
"NoEventsFound": "Няма намерени събития"
|
||||
}
|
||||
|
||||
@@ -513,7 +513,6 @@
|
||||
"APIKey": "Clau API",
|
||||
"ApiKeyHelpTextWarning": "Cal reiniciar perquè tingui efecte",
|
||||
"ApplyTagsHelpTexts1": "Com aplicar etiquetes a les pel·lícules seleccionades",
|
||||
"RemoveSelectedMessageText": "Esteu segur que voleu suprimir els elements seleccionats de la llista de blocs?",
|
||||
"RescanAfterRefreshHelpTextWarning": "Radarr no detectarà automàticament els canvis als fitxers quan no estigui configurat com a \"Sempre\"",
|
||||
"ShowUnknownAuthorItems": "Mostra elements de pel·lícula desconeguda",
|
||||
"Size": " Mida",
|
||||
@@ -584,7 +583,6 @@
|
||||
"BookIsDownloading": "La pel·lícula s'està baixant",
|
||||
"BookIsDownloadingInterp": "La pel·lícula s'està baixant - {0}% {1}",
|
||||
"Label": "Etiqueta",
|
||||
"BlocklistHelpText": "Impedeix que Lidarr torni a capturar aquesta versió automàticament",
|
||||
"ChooseImportMethod": "Trieu el mode d'importació",
|
||||
"ClickToChangeReleaseGroup": "Feu clic per canviar el grup de llançaments",
|
||||
"HardlinkCopyFiles": "Enllaç dur/Copia fitxers",
|
||||
@@ -621,5 +619,13 @@
|
||||
"CutoffFormatScoreHelpText": "Un cop s'arribi a aquesta puntuació de format personalitzat, Radarr ja no baixarà pel·lícules",
|
||||
"DeleteCustomFormatMessageText": "Esteu segur que voleu suprimir l'indexador '{0}'?",
|
||||
"ImportListMissingRoot": "Falta la carpeta arrel per a les llistes d'importació: {0}",
|
||||
"IndexerTagsHelpText": "Utilitzeu aquest indexador només per a pel·lícules amb almenys una etiqueta coincident. Deixeu-ho en blanc per utilitzar-ho amb totes les pel·lícules."
|
||||
"IndexerTagsHelpText": "Utilitzeu aquest indexador només per a pel·lícules amb almenys una etiqueta coincident. Deixeu-ho en blanc per utilitzar-ho amb totes les pel·lícules.",
|
||||
"ColonReplacement": "Substitució de dos punts",
|
||||
"HiddenClickToShow": "Amagat, feu clic per mostrar",
|
||||
"HideAdvanced": "Amaga avançat",
|
||||
"ReplaceWithDash": "Substitueix per guió",
|
||||
"ReplaceWithSpaceDash": "Substitueix per espai i guió",
|
||||
"ReplaceWithSpaceDashSpace": "Substitueix per espai, guió i espai",
|
||||
"ShowAdvanced": "Mostra característiques avançades",
|
||||
"ShownClickToHide": "Es mostra, feu clic per amagar"
|
||||
}
|
||||
|
||||
@@ -293,7 +293,6 @@
|
||||
"RemoveFromQueue": "Odebrat z fronty",
|
||||
"RemoveHelpTextWarning": "Odebráním odstraníte stažené soubory a soubory z klienta pro stahování.",
|
||||
"RemoveSelected": "Odstranit vybrané",
|
||||
"RemoveSelectedMessageText": "Opravdu chcete odebrat vybrané položky z černé listiny?",
|
||||
"RemoveTagExistingTag": "Stávající značka",
|
||||
"RemoveTagRemovingTag": "Odebírání značky",
|
||||
"RemovedFromTaskQueue": "Odebráno z fronty úkolů",
|
||||
@@ -578,5 +577,19 @@
|
||||
"HiddenClickToShow": "Skryté, kliknutím zobrazíte",
|
||||
"HideAdvanced": "Skrýt pokročilé",
|
||||
"ShowAdvanced": "Zobrazit pokročilé",
|
||||
"ShownClickToHide": "Zobrazeno, kliknutím se skryjete"
|
||||
"ShownClickToHide": "Zobrazeno, kliknutím se skryjete",
|
||||
"ColonReplacement": "Výměna tlustého střeva",
|
||||
"ReplaceWithDash": "Nahraďte Dash",
|
||||
"ReplaceWithSpaceDashSpace": "Nahraďte Space Dash Space",
|
||||
"ReplaceWithSpaceDash": "Nahraďte Space Dash",
|
||||
"DeleteRemotePathMapping": "Upravit vzdálené mapování cesty",
|
||||
"DeleteRemotePathMappingMessageText": "Opravdu chcete toto vzdálené mapování cesty odstranit?",
|
||||
"Negated": "Negovaný",
|
||||
"BlocklistReleases": "Vydání černé listiny",
|
||||
"DeleteConditionMessageText": "Opravdu chcete smazat značku „{0}“?",
|
||||
"RemoveSelectedItemBlocklistMessageText": "Opravdu chcete odebrat vybrané položky z černé listiny?",
|
||||
"RemoveSelectedItemQueueMessageText": "Opravdu chcete odebrat {0} položku {1} z fronty?",
|
||||
"RemoveSelectedItemsQueueMessageText": "Opravdu chcete odebrat {0} položku {1} z fronty?",
|
||||
"Required": "Požadované",
|
||||
"NoEventsFound": "Nebyly nalezeny žádné události"
|
||||
}
|
||||
|
||||
@@ -290,7 +290,6 @@
|
||||
"RemoveFromQueue": "Fjern fra køen",
|
||||
"RemoveHelpTextWarning": "Fjernelse fjerner download og fil (er) fra download-klienten.",
|
||||
"RemoveSelected": "Fjern valgte",
|
||||
"RemoveSelectedMessageText": "Er du sikker på, at du vil fjerne de valgte emner fra sortlisten?",
|
||||
"RemoveTagExistingTag": "Eksisterende mærke",
|
||||
"RemoveTagRemovingTag": "Fjerner tag",
|
||||
"RemovedFromTaskQueue": "Fjernet fra opgavekøen",
|
||||
@@ -581,5 +580,19 @@
|
||||
"HiddenClickToShow": "Skjult, klik for at vise",
|
||||
"ShownClickToHide": "Vist, klik for at skjule",
|
||||
"HideAdvanced": "Gemt Avancerede",
|
||||
"ShowAdvanced": "Vis avanceret"
|
||||
"ShowAdvanced": "Vis avanceret",
|
||||
"ColonReplacement": "Udskiftning af tyktarm",
|
||||
"ReplaceWithDash": "Udskift med Dash",
|
||||
"ReplaceWithSpaceDash": "Udskift med Space Dash",
|
||||
"ReplaceWithSpaceDashSpace": "Udskift med Space Dash Space",
|
||||
"DeleteRemotePathMapping": "Rediger kortlægning af fjernsti",
|
||||
"DeleteRemotePathMappingMessageText": "Er du sikker på, at du vil slette denne kortlægning af fjernstien?",
|
||||
"DeleteConditionMessageText": "Er du sikker på, at du vil slette listen '{0}'?",
|
||||
"Negated": "Negeret",
|
||||
"RemoveSelectedItemBlocklistMessageText": "Er du sikker på, at du vil fjerne de valgte emner fra sortlisten?",
|
||||
"BlocklistReleases": "Udgivelse af sortliste",
|
||||
"RemoveSelectedItemQueueMessageText": "Er du sikker på, at du vil fjerne {0} element {1} fra køen?",
|
||||
"RemoveSelectedItemsQueueMessageText": "Er du sikker på, at du vil fjerne {0} element {1} fra køen?",
|
||||
"Required": "Påkrævet",
|
||||
"NoEventsFound": "Ingen begivenheder fundet"
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@
|
||||
"DeleteBackup": "Backup löschen",
|
||||
"DeleteBackupMessageText": "Backup '{0}' wirkich löschen?",
|
||||
"DeleteDelayProfile": "Verzögerungsprofil löschen",
|
||||
"DeleteDelayProfileMessageText": "Bist du sicher, dass du dieses Verzögerungs-Profil löschen willst?",
|
||||
"DeleteDelayProfileMessageText": "Bist du sicher, dass du dieses Verzögerung-Profil löschen willst?",
|
||||
"DeleteDownloadClient": "Downloader löschen",
|
||||
"DeleteDownloadClientMessageText": "Downloader '{0}' wirklich löschen?",
|
||||
"DeleteEmptyFolders": "Leere Ordner löschen",
|
||||
@@ -113,12 +113,12 @@
|
||||
"Edition": "Auflage",
|
||||
"Enable": "Aktivieren",
|
||||
"EnableAutomaticAdd": "Automatisch hinzufügen",
|
||||
"EnableAutomaticSearch": "Automatisch suchen",
|
||||
"EnableAutomaticSearch": "Automatische Suche einschalten",
|
||||
"EnableColorImpairedMode": "Farbbeeinträchtigter Modus aktivieren",
|
||||
"EnableColorImpairedModeHelpText": "Alternativer Stil, um farbbeeinträchtigten Benutzern eine bessere Unterscheidung farbcodierter Informationen zu ermöglichen",
|
||||
"EnableCompletedDownloadHandlingHelpText": "Importiere fertige Downloads vom Downloader automatisch",
|
||||
"EnableHelpText": "Metadaten Dateien erstellen für diesen Metadata Typ",
|
||||
"EnableInteractiveSearch": "Interaktive Suche",
|
||||
"EnableInteractiveSearch": "Interaktive Suche einschalten",
|
||||
"EnableRSS": "RSS aktivieren",
|
||||
"EnableSSL": "SSL",
|
||||
"EnableSslHelpText": " Erfordert einen Neustart als Administrator",
|
||||
@@ -287,7 +287,6 @@
|
||||
"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?",
|
||||
"RemoveTagExistingTag": "Vorhandener Tag",
|
||||
"RemoveTagRemovingTag": "Tag entfernen",
|
||||
"RemovedFromTaskQueue": "Aus der Aufgabenwarteschlage entfernt",
|
||||
@@ -516,7 +515,6 @@
|
||||
"UnableToLoadBlocklist": "Sperrliste konnte nicht geladen werden",
|
||||
"ReleaseBranchCheckOfficialBranchMessage": "Zweig {0} ist kein gültiger Radarr-Release-Zweig. Sie erhalten keine Updates",
|
||||
"Blocklist": "Sperrliste",
|
||||
"BlocklistHelpText": "Dieses Release nicht automatisch erneut erfassen",
|
||||
"BlocklistRelease": "Release sperren",
|
||||
"RescanAfterRefreshHelpText": "Nach dem aktualisieren des Films, den Filmordner neu scannen",
|
||||
"ShowUnknownAuthorItems": "Unzugeordente Filmeinträge anzeigen",
|
||||
@@ -809,7 +807,7 @@
|
||||
"MonitorNewItems": "Neue Bücher überwachen",
|
||||
"MonitorNewItemsHelpText": "Welche neuen Bücher sollen überwacht werden",
|
||||
"NewBooks": "Neue Bücher",
|
||||
"NoHistoryBlocklist": "Keine History Blockliste",
|
||||
"NoHistoryBlocklist": "Keine Verlauf-Sperrliste",
|
||||
"NoName": "Namen nicht anzeigen",
|
||||
"OnAuthorDelete": "Beim Löschen eines Autors",
|
||||
"OnAuthorDeleteHelpText": "Beim Löschen eines Autors",
|
||||
@@ -885,7 +883,7 @@
|
||||
"CustomFormat": "Eigenes Format",
|
||||
"CustomFormats": "Eigene Formate",
|
||||
"CutoffFormatScoreHelpText": "Sobald diese eigener Format Bewertung erreicht wird, werden keine neuen Releases erfasst",
|
||||
"DeleteFormatMessageText": "Bist du sicher, dass du das Formatierungstag {0} löschen willst ?",
|
||||
"DeleteFormatMessageText": "Bist du sicher, dass du das Formatierungstag {0} löschen willst?",
|
||||
"ExportCustomFormat": "Eigenes Format exportieren",
|
||||
"Formats": "Formate",
|
||||
"MinFormatScoreHelpText": "Mindester eigener Format Score bis zum Download",
|
||||
@@ -896,7 +894,7 @@
|
||||
"CustomFormatSettings": "Einstellungen für eigene Formate",
|
||||
"DataFutureBooks": "Überwachung von Alben die noch nicht veröffentlicht wurden",
|
||||
"DeleteCustomFormat": "Eigenes Format löschen",
|
||||
"DeleteCustomFormatMessageText": "Indexer '{0}' wirklich löschen?",
|
||||
"DeleteCustomFormatMessageText": "Bist du sicher, dass du das eigene Format '{0}' löschen willst?",
|
||||
"IncludeCustomFormatWhenRenamingHelpText": "In {Custom Formats} umbennenungs Format",
|
||||
"ResetTitles": "Titel zurücksetzen",
|
||||
"UnableToLoadCustomFormats": "Eigene Formate konnten nicht geladen werden",
|
||||
@@ -908,5 +906,22 @@
|
||||
"HiddenClickToShow": "Versteckt, klicken zum anzeigen",
|
||||
"HideAdvanced": "Erweiterte Ansicht",
|
||||
"ShowAdvanced": "Einfache Ansicht",
|
||||
"ShownClickToHide": "Angezeigt, zum verstecken klicken"
|
||||
"ShownClickToHide": "Angezeigt, zum verstecken klicken",
|
||||
"ColonReplacement": "Doppelpunkt-Ersatz",
|
||||
"ReplaceWithDash": "Mit Bindestrich ersetzen",
|
||||
"ReplaceWithSpaceDash": "Mit Leerzeichen Bindestrich ersetzen",
|
||||
"ReplaceWithSpaceDashSpace": "Mit Leerzeichen Bindestrich Leerzeichen ersetzen",
|
||||
"ApiKeyValidationHealthCheckMessage": "Bitte den API Schlüssel korrigieren, dieser muss mindestens {0} Zeichen lang sein. Die Änderung kann über die Einstellungen oder die Konfigurationsdatei erfolgen",
|
||||
"ThereWasAnErrorLoadingThisItem": "Beim Laden des Eintrags ist ein Fehler aufgetreten",
|
||||
"ThereWasAnErrorLoadingThisPage": "Beim Laden der Seite ist ein Fehler aufgetreten",
|
||||
"DeleteRemotePathMapping": "Entfernte Pfadzuordnung löschen",
|
||||
"DeleteRemotePathMappingMessageText": "Bist du sicher, dass du das diese entfernte Pfadzuordnung löschen willst?",
|
||||
"CloneCondition": "Bedingung klonen",
|
||||
"DeleteCondition": "Bedingung löschen",
|
||||
"RemoveSelectedItemBlocklistMessageText": "Bist du sicher, dass du die ausgewählten Einträge aus der Sperrliste entfernen willst?",
|
||||
"ResetQualityDefinitionsMessageText": "Bist du sicher, dass du die Qualitätsdefinitionen zurücksetzen willst?",
|
||||
"RemoveSelectedItemQueueMessageText": "Bist du sicher, dass du ein Eintrag aus der Warteschlange entfernen willst?",
|
||||
"RemoveSelectedItemsQueueMessageText": "Bist du sicher, dass du {0} Einträge aus der Warteschlange entfernen willst?",
|
||||
"ListRefreshInterval": "Listen Aktualisierungsintervall",
|
||||
"ListWillRefreshEveryInterp": "Liste wird alle [0] aktualisiert"
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@
|
||||
"CompletedDownloadHandling": "Διαχείριση Ολοκληρωμένων Λήψεων",
|
||||
"ConnectSettings": "Σύνδεση ρυθμίσεων",
|
||||
"Connections": "Συνδέσεις",
|
||||
"CopyUsingHardlinksHelpText": "Χρησιμοποιήστε σκληρούς συνδέσμους όταν προσπαθείτε να αντιγράψετε αρχεία από torrents που εξακολουθούν να σπέρνονται",
|
||||
"CopyUsingHardlinksHelpText": "Οι σκληροί σύνδεσμοι επιτρέπουν στο Readarr να εισαγάγει τα torrents που έχουν κατέβει, στον φάκελο της ταινίας χωρίς να καταλαμβάνει περισσότερο χώρο στον δίσκο ή να αντιγράφει ολόκληρο το περιεχόμενο του αρχείου. Οι σκληροί σύνδεσμοι θα λειτουργήσουν μόνο αν η πηγή και ο προορισμός βρίσκονται στον ίδιο τόμο δίσκου",
|
||||
"CopyUsingHardlinksHelpTextWarning": "Περιστασιακά, τα κλειδώματα αρχείων ενδέχεται να αποτρέψουν τη μετονομασία αρχείων που έχουν σπαρθεί. Μπορείτε προσωρινά να απενεργοποιήσετε τη σπορά και να χρησιμοποιήσετε τη λειτουργία μετονομασίας Radarr ως εργασία.",
|
||||
"CreateEmptyAuthorFoldersHelpText": "Δημιουργήστε φακέλους ταινιών που λείπουν κατά τη σάρωση δίσκου",
|
||||
"CreateGroup": "Δημιουργησε ΟΜΑΔΑ",
|
||||
@@ -78,7 +78,7 @@
|
||||
"DeleteBackup": "Διαγραφή αντιγράφων ασφαλείας",
|
||||
"DeleteBackupMessageText": "Είστε βέβαιοι ότι θέλετε να διαγράψετε το αντίγραφο ασφαλείας \"{0}\";",
|
||||
"DeleteDelayProfile": "Διαγραφή προφίλ καθυστέρησης",
|
||||
"DeleteDelayProfileMessageText": "Είστε βέβαιοι ότι θέλετε να διαγράψετε αυτό το προφίλ καθυστέρησης;",
|
||||
"DeleteDelayProfileMessageText": "Είστε σίγουροι πως θέλετε να διαγράψετε αυτό το Προφίλ χρονοκαθυστέρησης;",
|
||||
"DeleteDownloadClient": "Διαγραφή προγράμματος-πελάτη λήψης",
|
||||
"DeleteDownloadClientMessageText": "Είστε βέβαιοι ότι θέλετε να διαγράψετε τον πελάτη λήψης \"{0}\";",
|
||||
"DeleteEmptyFolders": "Διαγραφή κενών φακέλων",
|
||||
@@ -290,14 +290,13 @@
|
||||
"RemoveFromQueue": "Κατάργηση από την ουρά",
|
||||
"RemoveHelpTextWarning": "Η κατάργηση θα καταργήσει τη λήψη και τα αρχεία από τον πελάτη λήψης.",
|
||||
"RemoveSelected": "Αφαιρέστε τα επιλεγμένα",
|
||||
"RemoveSelectedMessageText": "Είστε βέβαιοι ότι θέλετε να αφαιρέσετε τα επιλεγμένα στοιχεία από τη λίστα αποκλεισμού;",
|
||||
"RemoveTagExistingTag": "Υφιστάμενη ετικέτα",
|
||||
"RemoveTagRemovingTag": "Κατάργηση ετικέτας",
|
||||
"RemovedFromTaskQueue": "Καταργήθηκε από την ουρά εργασιών",
|
||||
"RenameBooksHelpText": "Το Radarr θα χρησιμοποιήσει το υπάρχον όνομα αρχείου εάν η μετονομασία είναι απενεργοποιημένη",
|
||||
"Reorder": "Παραγγέλλω πάλι",
|
||||
"ReplaceIllegalCharacters": "Αντικαταστήστε τους παράνομους χαρακτήρες",
|
||||
"RequiredHelpText": "Η κυκλοφορία πρέπει να περιέχει τουλάχιστον έναν από αυτούς τους όρους (μη ευαίσθητη υπόθεση)",
|
||||
"RequiredHelpText": "Αυτή η {0} συνθήκη πρέπει να ταιριάζει για να εφαρμοστεί το προσαρμοσμένο μορφότυπο. Διαφορετικά, αρκεί μία μόνο {0} αντιστοιχία.",
|
||||
"RequiredPlaceHolder": "Προσθέστε νέο περιορισμό",
|
||||
"RescanAfterRefreshHelpTextWarning": "Το Radarr δεν θα εντοπίσει αυτόματα αλλαγές στα αρχεία όταν δεν έχει οριστεί σε \"Πάντα\"",
|
||||
"RescanAuthorFolderAfterRefresh": "Επανεκκίνηση φακέλου ταινίας μετά την ανανέωση",
|
||||
@@ -346,7 +345,7 @@
|
||||
"ShowSizeOnDisk": "Εμφάνιση μεγέθους στο δίσκο",
|
||||
"ShownAboveEachColumnWhenWeekIsTheActiveView": "Εμφανίζεται πάνω από κάθε στήλη όταν η εβδομάδα είναι η ενεργή προβολή",
|
||||
"SkipFreeSpaceCheck": "Παράλειψη ελέγχου ελεύθερου χώρου",
|
||||
"SkipFreeSpaceCheckWhenImportingHelpText": "Χρησιμοποιήστε το όταν το Radarr δεν μπορεί να εντοπίσει ελεύθερο χώρο από τον ριζικό φάκελο της ταινίας σας",
|
||||
"SkipFreeSpaceCheckWhenImportingHelpText": "Χρησιμοποιήστε το όταν το Readarr δεν μπορεί να εντοπίσει ελεύθερο χώρο από τον ριζικό φάκελο του συγγραφέα",
|
||||
"SorryThatAuthorCannotBeFound": "Δυστυχώς, δεν είναι δυνατή η εύρεση αυτής της ταινίας.",
|
||||
"SorryThatBookCannotBeFound": "Δυστυχώς, δεν είναι δυνατή η εύρεση αυτής της ταινίας.",
|
||||
"SourcePath": "Διαδρομή πηγής",
|
||||
@@ -421,7 +420,7 @@
|
||||
"UnmonitoredHelpText": "Συμπεριλάβετε ταινίες χωρίς παρακολούθηση στη ροή iCal",
|
||||
"UpdateAll": "Ενημέρωση όλων",
|
||||
"UpdateAutomaticallyHelpText": "Αυτόματη λήψη και εγκατάσταση ενημερώσεων. Θα εξακολουθείτε να μπορείτε να κάνετε εγκατάσταση από το System: Updates",
|
||||
"UpdateMechanismHelpText": "Χρησιμοποιήστε το ενσωματωμένο πρόγραμμα ενημέρωσης του Radarr ή ένα σενάριο",
|
||||
"UpdateMechanismHelpText": "Χρησιμοποιήστε το ενσωματωμένο πρόγραμμα ενημέρωσης του Readarr ή ένα script",
|
||||
"UpdateScriptPathHelpText": "Διαδρομή σε ένα προσαρμοσμένο σενάριο που λαμβάνει ένα εξαγόμενο πακέτο ενημέρωσης και χειρίζεται το υπόλοιπο της διαδικασίας ενημέρωσης",
|
||||
"Updates": "Ενημερώσεις",
|
||||
"UpgradeAllowedHelpText": "Εάν οι ιδιότητες με ειδικές ανάγκες δεν θα αναβαθμιστούν",
|
||||
@@ -498,7 +497,7 @@
|
||||
"IndexerRssHealthCheckNoIndexers": "Δεν υπάρχουν διαθέσιμα ευρετήρια με ενεργοποιημένο τον συγχρονισμό RSS, το Radarr δεν θα τραβήξει αυτόματα νέες κυκλοφορίες",
|
||||
"IndexerSearchCheckNoAutomaticMessage": "Δεν υπάρχουν διαθέσιμα ευρετήρια με ενεργοποιημένη την αυτόματη αναζήτηση, το Radarr δεν θα παρέχει αποτελέσματα αυτόματης αναζήτησης",
|
||||
"CreateEmptyAuthorFolders": "Δημιουργήστε άδειους φακέλους ταινιών",
|
||||
"AppDataLocationHealthCheckMessage": "Η αναβάθμιση δεν είναι πιθανό να αποτρέψει την διαγραφή των AppData κατά την αναβάθμιση",
|
||||
"AppDataLocationHealthCheckMessage": "Η ενημέρωση δεν θα είναι δυνατή για να αποτραπεί η διαγραφή των δεδομένων εφαρμογής κατά την ενημέρωση",
|
||||
"DownloadClientStatusCheckAllClientMessage": "Όλα τα προγράμματα λήψης είναι μη διαθέσιμα λόγων αποτυχιών",
|
||||
"Monitor": "Οθόνη",
|
||||
"OnBookFileDeleteForUpgrade": "Διαγραφή αρχείου ταινίας για αναβάθμιση",
|
||||
@@ -590,7 +589,6 @@
|
||||
"MoveFiles": "Μετακίνηση αρχείων",
|
||||
"OnApplicationUpdate": "Στην ενημέρωση της εφαρμογής",
|
||||
"OnApplicationUpdateHelpText": "Στην ενημέρωση της εφαρμογής",
|
||||
"BlocklistHelpText": "Αποτρέπει το Radarr από το να πάρει ξανά αυτόματα αυτήν την έκδοση",
|
||||
"LoadingEditionsFailed": "Η φόρτωση των εκδόσεων απέτυχε",
|
||||
"ManualDownload": "Χειροκίνητη λήψη",
|
||||
"MetadataConsumers": "Καταναλωτές μεταδεδομένων",
|
||||
@@ -890,7 +888,7 @@
|
||||
"Formats": "Φορμάτ",
|
||||
"IncludeCustomFormatWhenRenamingHelpText": "Συμπεριλάβετε στη μορφή μετονομασίας {Custom Formats}",
|
||||
"MinFormatScoreHelpText": "Επιτρέπεται η λήψη της ελάχιστης βαθμολογίας προσαρμοσμένης μορφής",
|
||||
"ResetDefinitionTitlesHelpText": "Επαναφέρετε τίτλους ορισμού καθώς και τιμές",
|
||||
"ResetDefinitionTitlesHelpText": "Επαναφορά τίτλων ορισμού και των τιμών τους",
|
||||
"UpgradesAllowed": "Επιτρέπονται αναβαθμίσεις",
|
||||
"CustomFormats": "Προσαρμοσμένες Μορφές",
|
||||
"ResetTitles": "Επαναφορά τίτλων",
|
||||
@@ -901,7 +899,7 @@
|
||||
"CutoffFormatScoreHelpText": "Μόλις επιτευχθεί αυτό το σκορ προσαρμοσμένης μορφής, το Radarr δεν θα κατεβάζει πλέον ταινίες",
|
||||
"DataFutureBooks": "Παρακολουθήστε άλμπουμ που δεν έχουν κυκλοφορήσει ακόμα",
|
||||
"DeleteCustomFormat": "Διαγραφή προσαρμοσμένης μορφής",
|
||||
"DeleteCustomFormatMessageText": "Είστε βέβαιοι ότι θέλετε να διαγράψετε το ευρετήριο \"{0}\";",
|
||||
"DeleteCustomFormatMessageText": "Είστε σίγουροι πως θέλετε να διαγράψετε τη προσαρμοσμένη μορφή '{0}';",
|
||||
"DeleteFormatMessageText": "Είστε βέβαιοι ότι θέλετε να διαγράψετε την ετικέτα μορφής {0};",
|
||||
"NegateHelpText": "Εάν επιλεγεί, η προσαρμοσμένη μορφή δεν θα εφαρμοστεί εάν αντιστοιχεί σε αυτήν την {0} συνθήκη.",
|
||||
"ImportListMissingRoot": "Λείπει ο ριζικός φάκελος για λίστες εισαγωγής: {0}",
|
||||
@@ -911,5 +909,25 @@
|
||||
"HiddenClickToShow": "Κρυφό, κάντε κλικ για εμφάνιση",
|
||||
"HideAdvanced": "Απόκρυψη Προχωρημένων",
|
||||
"ShowAdvanced": "Εμφάνιση για προχωρημένους",
|
||||
"ShownClickToHide": "Εμφανίζεται, κάντε κλικ για απόκρυψη"
|
||||
"ShownClickToHide": "Εμφανίζεται, κάντε κλικ για απόκρυψη",
|
||||
"ColonReplacement": "Αντικατάσταση παχέος εντέρου",
|
||||
"ReplaceWithDash": "Αντικαταστήστε με Dash",
|
||||
"ReplaceWithSpaceDash": "Αντικαταστήστε με το Space Dash",
|
||||
"ReplaceWithSpaceDashSpace": "Αντικαταστήστε με Space Dash Space",
|
||||
"DashOrSpaceDashDependingOnName": "Παύλα ή Κενό-Παύλα ανάλογα με το όνομα",
|
||||
"ListRefreshInterval": "Διάστημα Ανανέωσης Λίστας",
|
||||
"ListWillRefreshEveryInterp": "Η λίστα θα ανανεώνεται κάθε {0}",
|
||||
"Loading": "φόρτωση",
|
||||
"RecycleBinUnableToWriteHealthCheck": "Δεν είναι δυνατή η εγγραφή στον επιλεγμένο φάκελο ανακύκλωσης: {0}. Ελέγξτε ότι αυτό το μονοπάτι υπάρχει και ότι είναι εγγράψιμο από τον χρήστη που τρέχει το Readarr",
|
||||
"SmartReplace": "Έξυπνη Αντικατάσταση",
|
||||
"ThereWasAnErrorLoadingThisItem": "Υπήρξε ένα σφάλμα κατά τη φόρτωση του αρχείου",
|
||||
"ThereWasAnErrorLoadingThisPage": "Υπήρξε ένα σφάλμα κατά τη φόρτωση της σελίδας",
|
||||
"Clone": "Κλωνοποίηση",
|
||||
"ApiKeyValidationHealthCheckMessage": "Παρακαλούμε ενημερώστε το κλείδι API ώστε να έχει τουλάχιστον {0} χαρακτήρες. Μπορείτε να το κάνετε αυτό μέσα από τις ρυθμίσεις ή το αρχείο ρυθμίσεων",
|
||||
"RemoveSelectedItemBlocklistMessageText": "Είστε σίγουροι πως θέλετε να διαγράψετε τα επιλεγμένα αντικείμενα από τη λίστα αποκλεισμού;",
|
||||
"RemoveSelectedItemQueueMessageText": "Είστε σίγουροι πως θέλετε να διαγράψετε 1 αντικείμενο από την ουρά;",
|
||||
"ResetQualityDefinitionsMessageText": "Είστε σίγουροι πως θέλετε να επαναφέρετε τους ορισμούς ποιότητας;",
|
||||
"CloneCondition": "Κλωνοποίηση συνθήκης",
|
||||
"DeleteCondition": "Διαγραφή συνθήκης",
|
||||
"RemoveSelectedItemsQueueMessageText": "Είστε σίγουροι πως θέλετε να διαγράψετε {0} αντικείμενα από την ουρά;"
|
||||
}
|
||||
|
||||
@@ -64,8 +64,9 @@
|
||||
"BindAddressHelpText": "Valid IP address, localhost or '*' for all interfaces",
|
||||
"BindAddressHelpTextWarning": "Requires restart to take effect",
|
||||
"Blocklist": "Blocklist",
|
||||
"BlocklistHelpText": "Prevents Readarr from automatically grabbing these files again",
|
||||
"BlocklistRelease": "Blocklist Release",
|
||||
"BlocklistReleaseHelpText": "Prevents Readarr from automatically grabbing these files again",
|
||||
"BlocklistReleases": "Blocklist Releases",
|
||||
"Book": "Book",
|
||||
"BookAvailableButMissing": "Book Available, but Missing",
|
||||
"BookEditor": "Book Editor",
|
||||
@@ -122,6 +123,7 @@
|
||||
"ClickToChangeReleaseGroup": "Click to change release group",
|
||||
"ClientPriority": "Client Priority",
|
||||
"Clone": "Clone",
|
||||
"CloneCondition": "Clone Condition",
|
||||
"CloneCustomFormat": "Clone Custom Format",
|
||||
"CloneIndexer": "Clone Indexer",
|
||||
"CloneProfile": "Clone Profile",
|
||||
@@ -188,6 +190,8 @@
|
||||
"DeleteBackupMessageText": "Are you sure you want to delete the backup '{0}'?",
|
||||
"DeleteBookFile": "Delete Book File",
|
||||
"DeleteBookFileMessageText": "Are you sure you want to delete {0}?",
|
||||
"DeleteCondition": "Delete Condition",
|
||||
"DeleteConditionMessageText": "Are you sure you want to delete condition '{0}'?",
|
||||
"DeleteCustomFormat": "Delete Custom Format",
|
||||
"DeleteCustomFormatMessageText": "Are you sure you want to delete the custom format '{0}'?",
|
||||
"DeleteDelayProfile": "Delete Delay Profile",
|
||||
@@ -213,6 +217,8 @@
|
||||
"DeleteQualityProfileMessageText": "Are you sure you want to delete the quality profile '{0}'?",
|
||||
"DeleteReleaseProfile": "Delete Release Profile",
|
||||
"DeleteReleaseProfileMessageText": "Are you sure you want to delete this Release Profile?",
|
||||
"DeleteRemotePathMapping": "Delete Remote Path Mapping",
|
||||
"DeleteRemotePathMappingMessageText": "Are you sure you want to delete this remote path mapping?",
|
||||
"DeleteRootFolder": "Delete Root Folder",
|
||||
"DeleteRootFolderMessageText": "Are you sure you want to delete the root folder '{0}'?",
|
||||
"DeleteSelectedBookFiles": "Delete Selected Book Files",
|
||||
@@ -505,15 +511,19 @@
|
||||
"NameStyle": "Author Name Style",
|
||||
"NamingSettings": "Naming Settings",
|
||||
"NegateHelpText": "If checked, the custom format will not apply if this {0} condition matches.",
|
||||
"Negated": "Negated",
|
||||
"New": "New",
|
||||
"NewBooks": "New Books",
|
||||
"NoBackupsAreAvailable": "No backups are available",
|
||||
"NoCutoffUnmetItems": "No cutoff unmet items",
|
||||
"NoEventsFound": "No events found",
|
||||
"NoHistory": "No history.",
|
||||
"NoHistoryBlocklist": "No history blocklist",
|
||||
"NoLeaveIt": "No, Leave It",
|
||||
"NoLimitForAnyRuntime": "No limit for any runtime",
|
||||
"NoLogFiles": "No log files",
|
||||
"NoMinimumForAnyRuntime": "No minimum for any runtime",
|
||||
"NoMissingItems": "No missing items",
|
||||
"NoName": "Do not show name",
|
||||
"NoTagsHaveBeenAddedYet": "No tags have been added yet. Add tags to link authors with delay profiles, restrictions, or notifications. Click {0} to find out more about tags in Readarr.",
|
||||
"NoUpdatesAreAvailable": "No updates are available",
|
||||
@@ -654,7 +664,11 @@
|
||||
"RemoveFromQueue": "Remove from queue",
|
||||
"RemoveHelpTextWarning": "Removing will remove the download and the file(s) from the download client.",
|
||||
"RemoveSelected": "Remove Selected",
|
||||
"RemoveSelectedMessageText": "Are you sure you want to remove the selected items from the blocklist?",
|
||||
"RemoveSelectedItem": "Remove Selected Item",
|
||||
"RemoveSelectedItemBlocklistMessageText": "Are you sure you want to remove the selected items from the blocklist?",
|
||||
"RemoveSelectedItemQueueMessageText": "Are you sure you want to remove 1 item from the queue?",
|
||||
"RemoveSelectedItems": "Remove Selected Items",
|
||||
"RemoveSelectedItemsQueueMessageText": "Are you sure you want to remove {0} items from the queue?",
|
||||
"RemoveTagExistingTag": "Existing tag",
|
||||
"RemoveTagRemovingTag": "Removing tag",
|
||||
"RemovedFromTaskQueue": "Removed from task queue",
|
||||
@@ -667,6 +681,7 @@
|
||||
"ReplaceWithDash": "Replace with Dash",
|
||||
"ReplaceWithSpaceDash": "Replace with Space Dash",
|
||||
"ReplaceWithSpaceDashSpace": "Replace with Space Dash Space",
|
||||
"Required": "Required",
|
||||
"RequiredHelpText": "This {0} condition must match for the custom format to apply. Otherwise a single {0} match is sufficient.",
|
||||
"RequiredPlaceHolder": "Add new restriction",
|
||||
"RescanAfterRefreshHelpText": "Rescan the author folder after refreshing the author",
|
||||
@@ -677,6 +692,8 @@
|
||||
"ResetAPIKeyMessageText": "Are you sure you want to reset your API Key?",
|
||||
"ResetDefinitionTitlesHelpText": "Reset definition titles as well as values",
|
||||
"ResetDefinitions": "Reset Definitions",
|
||||
"ResetQualityDefinitions": "Reset Quality Definitions",
|
||||
"ResetQualityDefinitionsMessageText": "Are you sure you want to reset quality definitions?",
|
||||
"ResetTitles": "Reset Titles",
|
||||
"Restart": "Restart",
|
||||
"RestartNow": "Restart Now",
|
||||
|
||||
@@ -294,7 +294,6 @@
|
||||
"RemoveFromQueue": "Eliminar de la cola",
|
||||
"RemoveHelpTextWarning": "Eliminar borrará la descarga y el/los fichero(s) del gestor de descargas.",
|
||||
"RemoveSelected": "Borrar Seleccionados",
|
||||
"RemoveSelectedMessageText": "¿Está seguro de que desea eliminar los elementos seleccionados de la lista negra?",
|
||||
"RemoveTagExistingTag": "Etiqueta existente",
|
||||
"RemoveTagRemovingTag": "Eliminando etiqueta",
|
||||
"RemovedFromTaskQueue": "Eliminar de la cola de tareas",
|
||||
@@ -468,7 +467,6 @@
|
||||
"Level": "Nivel",
|
||||
"ReleaseBranchCheckOfficialBranchMessage": "Las versión {0} no es una versión válida de Radarr, no recibirás actualizaciones",
|
||||
"Blocklist": "Bloqueadas",
|
||||
"BlocklistHelpText": "Evita que Radarr vuelva a capturar esta película automáticamente",
|
||||
"BlocklistRelease": "Bloquear este Estreno",
|
||||
"CreateEmptyAuthorFolders": "Crear carpetas de películas vacías",
|
||||
"SelectAll": "Seleccionar Todas",
|
||||
@@ -638,5 +636,23 @@
|
||||
"HiddenClickToShow": "Oculto, clic para mostrar",
|
||||
"HideAdvanced": "Ocultar Avanzado",
|
||||
"ShowAdvanced": "Mostrar Avanzado",
|
||||
"ShownClickToHide": "Mostrado, clic para ocultar"
|
||||
"ShownClickToHide": "Mostrado, clic para ocultar",
|
||||
"ColonReplacement": "Reemplazo dos puntos",
|
||||
"ReplaceWithDash": "Reemplazar con Dash",
|
||||
"ReplaceWithSpaceDash": "Reemplazar con Space Dash",
|
||||
"ReplaceWithSpaceDashSpace": "Reemplazar con Space Dash Space",
|
||||
"DeleteRemotePathMapping": "Editar Mapeo de Ruta Remota",
|
||||
"BlocklistReleases": "Bloquear este Estreno",
|
||||
"DeleteConditionMessageText": "Seguro que quieres eliminar la etiqueta '{0}'?",
|
||||
"Negated": "Negado",
|
||||
"RemoveSelectedItem": "Eliminar el elemento seleccionado",
|
||||
"RemoveSelectedItemBlocklistMessageText": "¿Está seguro de que desea eliminar los elementos seleccionados de la lista negra?",
|
||||
"RemoveSelectedItemQueueMessageText": "¿Está seguro de que desea eliminar el {0} elemento {1} de la cola?",
|
||||
"RemoveSelectedItems": "Eliminar los elementos seleccionados",
|
||||
"RemoveSelectedItemsQueueMessageText": "¿Estás seguro de que quieres eliminar {0} elementos de la cola?",
|
||||
"Required": "Necesario",
|
||||
"ResetQualityDefinitions": "Restablecer definiciones de calidad",
|
||||
"ResetQualityDefinitionsMessageText": "¿Está seguro de que desea restablecer las definiciones de calidad?",
|
||||
"BlocklistReleaseHelpText": "Evita que Radarr vuelva a capturar esta película automáticamente",
|
||||
"NoEventsFound": "No se encontraron eventos"
|
||||
}
|
||||
|
||||
@@ -289,7 +289,6 @@
|
||||
"RemoveFromQueue": "Poista jonosta",
|
||||
"RemoveHelpTextWarning": "Poistaminen poistaa latauksen ja tiedostot latausohjelmasta.",
|
||||
"RemoveSelected": "Poista valitut",
|
||||
"RemoveSelectedMessageText": "Haluatko varmasti poistaa valitut kohteet estolistalta?",
|
||||
"RemoveTagExistingTag": "Olemassa oleva tunniste",
|
||||
"RemoveTagRemovingTag": "Tunniste poistetaan",
|
||||
"RemovedFromTaskQueue": "Poistettu tehtäväjonosta",
|
||||
@@ -478,7 +477,6 @@
|
||||
"UrlBaseHelpText": "Lisää Calibren URL-osoitteeseen etuliitteen, (esim. 'http://[host]:[port]/[urlBase]').",
|
||||
"Author": "Kirjailija",
|
||||
"BackupIntervalHelpText": "Readarrin tietokannan ja asetusten automaattisen varmuuskopioinnin suoritusaikaväli.",
|
||||
"BlocklistHelpText": "Estää julkaisun automaattisen uudelleensieppauksen.",
|
||||
"TagsHelpText": "Käytetään vähintään yhdellä täsmäävällä tunnisteella merkityille kirjailijoille. Käytä kaikille jättämällä tyhjäksi.",
|
||||
"WriteAudioTagsScrubHelp": "Poista olemassa olevat tagit tiedostoista säilyttäen vain Readarrin lisäämät tagit.",
|
||||
"DefaultTagsHelpText": "Kansiosta löydetyille kirjailijoille oletusarvoisesti määritettävät tunnisteet.",
|
||||
@@ -816,5 +814,23 @@
|
||||
"HiddenClickToShow": "Piilotettu, näytä painalla",
|
||||
"HideAdvanced": "Piilota edistyneet",
|
||||
"ShowAdvanced": "Näytä lisäasetukset",
|
||||
"ShownClickToHide": "Näkyvissä, piilota painamalla"
|
||||
"ShownClickToHide": "Näkyvissä, piilota painamalla",
|
||||
"ColonReplacement": "Kaksoispisteen käsittely",
|
||||
"ReplaceWithDash": "Korvaus: väliviiva",
|
||||
"ReplaceWithSpaceDash": "Korvaus: välilyönti-väliviiva",
|
||||
"ReplaceWithSpaceDashSpace": "Korvus: välilyönti-väliviiva-välilyönti",
|
||||
"DeleteRemotePathMapping": "Muokkaa etäreittien kartoitusta",
|
||||
"BlocklistReleases": "Lisää julkaisut estolistalle",
|
||||
"DeleteConditionMessageText": "Haluatko varmasti poistaa tunnisteen '{0}'?",
|
||||
"Negated": "Mitätöity",
|
||||
"RemoveSelectedItem": "Poista valittu kohde",
|
||||
"RemoveSelectedItemBlocklistMessageText": "Haluatko varmasti poistaa valitut kohteet estolistalta?",
|
||||
"RemoveSelectedItemQueueMessageText": "Haluatko varmasti poistaa jonosta 1 kohteen?",
|
||||
"RemoveSelectedItems": "Poista valitut kohteet",
|
||||
"RemoveSelectedItemsQueueMessageText": "Haluatko varmasti poistaa jonosta {0} kohdetta?",
|
||||
"Required": "Vaaditaan",
|
||||
"ResetQualityDefinitions": "Palauta laatumääritykset",
|
||||
"ResetQualityDefinitionsMessageText": "Haluatko varmasti palauttaa laatumääritykset?",
|
||||
"NoEventsFound": "Tapahtumia ei löytynyt",
|
||||
"BlocklistReleaseHelpText": "Estää julkaisun automaattisen uudelleensieppauksen."
|
||||
}
|
||||
|
||||
@@ -294,7 +294,6 @@
|
||||
"RemoveFromQueue": "Supprimer de la file d'attente",
|
||||
"RemoveHelpTextWarning": "La suppression supprimera le téléchargement et le(s) fichier(s) du client de téléchargement.",
|
||||
"RemoveSelected": "Supprimer la sélection",
|
||||
"RemoveSelectedMessageText": "Êtes-vous sûr de vouloir supprimer les éléments sélectionnés de la liste noire ?",
|
||||
"RemoveTagExistingTag": "Tag existant",
|
||||
"RemoveTagRemovingTag": "Suppression du tag",
|
||||
"RemovedFromTaskQueue": "Supprimé de la file d'attente des tâches",
|
||||
@@ -478,7 +477,6 @@
|
||||
"ReleaseBranchCheckOfficialBranchMessage": "La branche {0} n'est pas une branche de version Readarr valide, vous ne recevrez pas de mises à jour",
|
||||
"Time": "Heure",
|
||||
"Blocklist": "Liste noire",
|
||||
"BlocklistHelpText": "Empêche Readarr de récupérer automatiquement ces fichiers de nouveau",
|
||||
"BlocklistRelease": "Mettre cette release sur la liste noire",
|
||||
"RescanAfterRefreshHelpText": "Réanalyser le dossier de l'auteur après avoir actualisé l'auteur",
|
||||
"ShowUnknownAuthorItems": "Afficher les éléments avec auteur inconnu",
|
||||
@@ -490,7 +488,7 @@
|
||||
"All": "Tout",
|
||||
"Wanted": "Recherché",
|
||||
"CreateEmptyAuthorFolders": "Créer des dossiers auteurs vides",
|
||||
"AppDataLocationHealthCheckMessage": "Mettre à jour ne sera pas possible afin d'éviter de supprimer le dossier AppData lors de la mise à jour",
|
||||
"AppDataLocationHealthCheckMessage": "La mise à jour ne sera pas possible pour empêcher la suppression de AppData lors de la mise à jour",
|
||||
"IndexerPriorityHelpText": "Priorité de l'indexeur de 1 (la plus élevée) à 50 (la plus basse). Par défaut : 25. Utilisé pour départager les versions lors des téléchargements. Readarr continuera d'utiliser tous les indexeurs activés pour les synchro RSS et les recherches.",
|
||||
"Duration": "Durée",
|
||||
"RemotePathMappingCheckBadDockerPath": "Vous utilisez docker ; le client de téléchargement {0} enregistre les téléchargements dans {1} mais ce n'est pas un chemin valide. Vérifiez vos paramètres de dossier distant et les paramètres de votre client de téléchargement.",
|
||||
@@ -692,7 +690,7 @@
|
||||
"CopyToClipboard": "Copier dans le presse-papier",
|
||||
"CustomFormat": "Format Personnalisé",
|
||||
"CustomFormatSettings": "Réglages Formats Personnalisés",
|
||||
"CustomFormats": "Formats personnalisés",
|
||||
"CustomFormats": "Formats perso.",
|
||||
"DeleteCustomFormat": "Supprimer le format personnalisé",
|
||||
"DeleteCustomFormatMessageText": "Voulez-vous vraiment supprimer l'indexeur '{0}' ?",
|
||||
"DeleteFormatMessageText": "Êtes-vous sûr de vouloir supprimer le tag {0} ?",
|
||||
@@ -717,10 +715,27 @@
|
||||
"Loading": "Chargement",
|
||||
"ThereWasAnErrorLoadingThisItem": "Une erreur s'est produite lors du chargement de cet élément",
|
||||
"ThereWasAnErrorLoadingThisPage": "Une erreur s'est produite lors du chargement de cette page",
|
||||
"ApiKeyValidationHealthCheckMessage": "Merci de mettre à jour votre clé API afin qu'elle fasse plus de 20 caractères. Rendez vous dans les paramètres ou dans le fichier de configuration",
|
||||
"ApiKeyValidationHealthCheckMessage": "Veuillez mettre à jour votre clé API pour qu'elle contienne au moins {0} caractères. Vous pouvez le faire via les paramètres ou le fichier de configuration",
|
||||
"DeleteBookFile": "Effacer le fichier du livre",
|
||||
"HiddenClickToShow": "Caché, cliquez pour afficher",
|
||||
"HideAdvanced": "Masquer avancé",
|
||||
"ShowAdvanced": "Afficher avancés",
|
||||
"ShownClickToHide": "Montré, cliquez pour masquer"
|
||||
"ShownClickToHide": "Montré, cliquez pour masquer",
|
||||
"ColonReplacement": "Remplacement pour le 'deux-points'",
|
||||
"ReplaceWithDash": "Remplacer par Dash",
|
||||
"ReplaceWithSpaceDash": "Remplacer par Space Dash",
|
||||
"ReplaceWithSpaceDashSpace": "Remplacer par Space Dash Space",
|
||||
"DeleteRemotePathMapping": "Éditer le chemin distant",
|
||||
"DeleteRemotePathMappingMessageText": "Êtes-vous sûr de vouloir effacer ce chemin ?",
|
||||
"BlocklistReleases": "Mettre cette release sur la liste noire",
|
||||
"DeleteConditionMessageText": "Voulez-vous vraiment supprimer la liste '{0}' ?",
|
||||
"Negated": "Inversé",
|
||||
"RemoveSelectedItem": "Supprimer l'élément sélectionné",
|
||||
"RemoveSelectedItemBlocklistMessageText": "Êtes-vous sûr de vouloir supprimer les films sélectionnés de la liste noire ?",
|
||||
"RemoveSelectedItemQueueMessageText": "Êtes-vous sûr de vouloir désinstaller {0} objet{1} de la file d'attente ?",
|
||||
"RemoveSelectedItems": "Supprimer les éléments sélectionnés",
|
||||
"RemoveSelectedItemsQueueMessageText": "Êtes-vous sûr de vouloir supprimer {0} objet(s) de la file d'attente ?",
|
||||
"Required": "Obligatoire",
|
||||
"ResetQualityDefinitions": "Réinitialiser les définitions de qualité",
|
||||
"ResetQualityDefinitionsMessageText": "Êtes-vous sûr de vouloir réinitialiser les définitions de qualité ?"
|
||||
}
|
||||
|
||||
@@ -274,7 +274,6 @@
|
||||
"RemoveFromQueue": "הסר מהתור",
|
||||
"RemoveHelpTextWarning": "הסרה תסיר את ההורדה ואת הקבצים מלקוח ההורדה.",
|
||||
"RemoveSelected": "הסר פריטים שנבחרו",
|
||||
"RemoveSelectedMessageText": "האם אתה בטוח שברצונך להסיר את הפריטים שנבחרו מהרשימה השחורה?",
|
||||
"RemoveTagExistingTag": "תג קיים",
|
||||
"RemoveTagRemovingTag": "הסרת התג",
|
||||
"RemovedFromTaskQueue": "הוסר מתור המשימות",
|
||||
@@ -554,7 +553,6 @@
|
||||
"InstanceNameHelpText": "שם מופע בטאב ובשביל שם אפליקציית סיסלוג",
|
||||
"RemotePathMappingCheckBadDockerPath": "אתה משתמש בדוקר; קליינט ההורדות {0} שם הורדות ב-{1} אבל הנתיב לא תקין {2}. בחן מחדש את ניתוב התיקיות והגדרות קליינט ההורדות.",
|
||||
"AddList": "הוסף רשימה",
|
||||
"BlocklistHelpText": "מנע מראדרר להוסיף את ההוצאה הזאת שוב",
|
||||
"RemotePathMappingCheckDownloadPermissions": "ראדארר יכול לראות אבל לא לגשת לסרטים שירדו {0}. ככל הנראה בעיית הרשאות.",
|
||||
"RemotePathMappingCheckFileRemoved": "הקובץ {0} הוסר תוך כדי התהליך.",
|
||||
"RemotePathMappingCheckFilesBadDockerPath": "אתה משתמש בדוקר; קליינט ההורדות {0} שם הורדות ב-{1} אבל הנתיב לא תקין {2}. בחן מחדש את ניתוב התיקיות והגדרות קליינט ההורדות.",
|
||||
@@ -600,5 +598,21 @@
|
||||
"HiddenClickToShow": "מוסתר, לחץ להצגה",
|
||||
"HideAdvanced": "הסתר מתקדם",
|
||||
"ShowAdvanced": "הצג מתקדם",
|
||||
"ShownClickToHide": "מוצג, לחץ כדי להסתיר"
|
||||
"ShownClickToHide": "מוצג, לחץ כדי להסתיר",
|
||||
"ColonReplacement": "החלפת המעי הגס",
|
||||
"ReplaceWithDash": "החלף ב- Dash",
|
||||
"ReplaceWithSpaceDash": "החלף במקף החלל",
|
||||
"ReplaceWithSpaceDashSpace": "החלף במרחב מקף החלל",
|
||||
"DeleteRemotePathMapping": "ערוך מיפוי נתיבים מרחוק",
|
||||
"DeleteRemotePathMappingMessageText": "האם אתה בטוח שברצונך למחוק את מיפוי הנתיבים המרוחק הזה?",
|
||||
"BlocklistReleases": "שחרור הרשימה השחורה",
|
||||
"DeleteConditionMessageText": "האם אתה בטוח שברצונך למחוק את התג '{0}'?",
|
||||
"Negated": "שלילי",
|
||||
"Required": "נדרש",
|
||||
"RemoveSelectedItemBlocklistMessageText": "האם אתה בטוח שברצונך להסיר את הפריטים שנבחרו מהרשימה השחורה?",
|
||||
"RemoveSelectedItemQueueMessageText": "האם אתה בטוח שברצונך להסיר את {0} פריט {1} מהתור?",
|
||||
"RemoveSelectedItemsQueueMessageText": "האם אתה בטוח שברצונך להסיר את {0} פריט {1} מהתור?",
|
||||
"BlocklistReleaseHelpText": "מנע מראדרר להוסיף את ההוצאה הזאת שוב",
|
||||
"NoEventsFound": "לא נמצאו אירועים",
|
||||
"ApiKeyValidationHealthCheckMessage": "עדכן בבקשה את מפתח ה API שלך שיהיה עם לפחות {0} תווים. ניתן לעשות זאת דרך ההגדות או קובץ הקונפיגורציה"
|
||||
}
|
||||
|
||||
@@ -281,7 +281,6 @@
|
||||
"RemoveFromQueue": "कतार से निकालें",
|
||||
"RemoveHelpTextWarning": "हटाने से डाउनलोड और फ़ाइल को डाउनलोड क्लाइंट से निकाल दिया जाएगा।",
|
||||
"RemoveSelected": "चुना हुआ हटाओ",
|
||||
"RemoveSelectedMessageText": "क्या आप वाकई चयनित आइटम को ब्लैकलिस्ट से हटाना चाहते हैं?",
|
||||
"RemoveTagExistingTag": "मौजूदा टैग",
|
||||
"RemoveTagRemovingTag": "टैग हटाना",
|
||||
"RemovedFromTaskQueue": "कार्य कतार से हटा दिया गया",
|
||||
@@ -578,5 +577,18 @@
|
||||
"HiddenClickToShow": "छिपा हुआ, दिखाने के लिए क्लिक करें",
|
||||
"HideAdvanced": "उन्नत छिपाएँ",
|
||||
"ShowAdvanced": "शो पहले होगा",
|
||||
"ShownClickToHide": "दिखाया, छिपाने के लिए क्लिक करें"
|
||||
"ShownClickToHide": "दिखाया, छिपाने के लिए क्लिक करें",
|
||||
"ColonReplacement": "कोलन रिप्लेसमेंट",
|
||||
"ReplaceWithDash": "डैश के साथ बदलें",
|
||||
"ReplaceWithSpaceDash": "स्पेस डैश के साथ बदलें",
|
||||
"ReplaceWithSpaceDashSpace": "स्पेस डैश स्पेस के साथ बदलें",
|
||||
"DeleteRemotePathMapping": "दूरस्थ पथ मानचित्रण संपादित करें",
|
||||
"BlocklistReleases": "ब्लैकलिस्ट रिलीज़",
|
||||
"Negated": "नकार दिया गया",
|
||||
"Required": "अपेक्षित",
|
||||
"DeleteConditionMessageText": "क्या आप वाकई '{0}' सूची को हटाना चाहते हैं?",
|
||||
"RemoveSelectedItemBlocklistMessageText": "क्या आप वाकई चयनित आइटम को ब्लैकलिस्ट से हटाना चाहते हैं?",
|
||||
"RemoveSelectedItemQueueMessageText": "क्या आप वाकई {0} आइटम {1} को कतार से हटाना चाहते हैं?",
|
||||
"RemoveSelectedItemsQueueMessageText": "क्या आप वाकई {0} आइटम {1} को कतार से हटाना चाहते हैं?",
|
||||
"NoEventsFound": "कोई घटना नहीं मिली"
|
||||
}
|
||||
|
||||
@@ -130,7 +130,6 @@
|
||||
"AuthorClickToChangeBook": "Klikni za promjenu filma",
|
||||
"AutoUnmonitorPreviouslyDownloadedBooksHelpText": "U Radarru se automatski isključuje nadzor za filmove koji su izbrisani sa diska",
|
||||
"BackupFolderHelpText": "Relativne putanje će biti unutar Radarrovog AppData direktorija",
|
||||
"BlocklistHelpText": "Spriječi Radarr da automatski dohvaća ovu verziju ponovno",
|
||||
"BypassIfHighestQuality": "Zaobiđi ako je Najviši Kvalitet",
|
||||
"CancelMessageText": "Jeste li sigurni da želite otkazati ovaj zadatak na čekanju?",
|
||||
"ChmodFolderHelpTextWarning": "Ovo jedino radi ako je korisnik koji je pokrenuo Radarr vlasnik datoteke. Bolje je osigurati da klijent za preuzimanje postavi dozvolu ispravno.",
|
||||
@@ -141,7 +140,7 @@
|
||||
"DeleteNotificationMessageText": "Jeste li sigurni da želite obrisati oznaku formata {0}?",
|
||||
"DeleteQualityProfileMessageText": "Jeste li sigurni da želite obrisati ovaj profil odgode?",
|
||||
"DeleteRootFolderMessageText": "Jeste li sigurni da želite obrisati oznaku formata {0}?",
|
||||
"RemoveSelectedMessageText": "Jeste li sigurni da želite izbrisati odabrane stavke iz blok liste?",
|
||||
"UsingExternalUpdateMechanismBranchToUseToUpdateReadarr": "Grana korištena za ažuriranje Radarra",
|
||||
"UsingExternalUpdateMechanismBranchUsedByExternalUpdateMechanism": "Grana korištena od strane vanjskog mehanizma za ažuriranje"
|
||||
"UsingExternalUpdateMechanismBranchUsedByExternalUpdateMechanism": "Grana korištena od strane vanjskog mehanizma za ažuriranje",
|
||||
"ColonReplacement": "Zamjena Zareza"
|
||||
}
|
||||
|
||||
@@ -100,16 +100,16 @@
|
||||
"Edition": "Kiadás",
|
||||
"Enable": "Aktiválás",
|
||||
"EnableAutomaticAdd": "Engedélyezd az automatikus hozzáadást",
|
||||
"EnableAutomaticSearch": "Engedélyezd az Automatikus Keresést",
|
||||
"EnableAutomaticSearch": "Automatikus keresés engedélyezése",
|
||||
"EnableColorImpairedMode": "Engedélyezze a színtévesztő módot",
|
||||
"EnableColorImpairedModeHelpText": "Megváltoztatott színek, hogy a színvak felhasználók jobban meg tudják különböztetni a színkódolt információkat",
|
||||
"EnableCompletedDownloadHandlingHelpText": "A befejezett letöltések automatikus importálása a letöltési kliensből",
|
||||
"EnableHelpText": "Engedélyezze a metaadatfájlok létrehozását ehhez a metaadat típushoz",
|
||||
"EnableInteractiveSearch": "Interaktív Keresés Engedélyezése",
|
||||
"EnableInteractiveSearch": "Interaktív keresés engedélyezése",
|
||||
"EnableRSS": "RSS Engedélyezése",
|
||||
"EnableSSL": "SSL Engedélyezése",
|
||||
"EnableSslHelpText": " A hatálybalépéshez újra kell indítani rendszergazdaként",
|
||||
"Ended": "Vége lett",
|
||||
"Ended": "Vége",
|
||||
"ErrorLoadingContents": "Hiba történt a tartalom betöltésekor",
|
||||
"ErrorLoadingPreviews": "Hiba történt az előnézetek betöltése közben",
|
||||
"Exception": "Kivétel",
|
||||
@@ -196,7 +196,7 @@
|
||||
"MinimumLimits": "Minimális Határ",
|
||||
"Missing": "Hiányzó",
|
||||
"Mode": "Mód",
|
||||
"Monitored": "Monitorozva",
|
||||
"Monitored": "Felügyelt",
|
||||
"MoreInfo": "Több Információ",
|
||||
"MustContain": "Tartalmaznia kell",
|
||||
"MustNotContain": "Nem tartalmazhatja",
|
||||
@@ -242,7 +242,7 @@
|
||||
"PublishedDate": "Közzététel dátuma",
|
||||
"Quality": "Minőség",
|
||||
"QualityDefinitions": "Minőségi meghatározások",
|
||||
"QualityProfile": "Minőségi Profil",
|
||||
"QualityProfile": "Minőségi profil",
|
||||
"QualityProfiles": "Minőségi profilok",
|
||||
"QualitySettings": "Minőségi beállítások",
|
||||
"Queue": "Várakozási sor",
|
||||
@@ -271,11 +271,10 @@
|
||||
"RemoveCompletedDownloadsHelpText": "Távolítsa el az importált letöltéseket a letöltési kliens előzményeiből",
|
||||
"RemoveFailedDownloadsHelpText": "Távolítsa el a sikertelen letöltéseket a letöltési kliens előzményeiből",
|
||||
"RemoveFilter": "Szűrő törlése",
|
||||
"RemoveFromDownloadClient": "Eltávolítás a letöltőkliensből",
|
||||
"RemoveFromDownloadClient": "Eltávolítás a letöltési kliensből",
|
||||
"RemoveFromQueue": "Eltávolítás a sorból",
|
||||
"RemoveHelpTextWarning": "Az eltávolítás eltávolítja a letöltést és a fájl(oka)t a letöltési kliensből.",
|
||||
"RemoveSelected": "Kiválaszottak törlése",
|
||||
"RemoveSelectedMessageText": "Biztosan eltávolítja a kijelölt elemeket a feketelistáról?",
|
||||
"RemoveTagExistingTag": "Meglévő Címke",
|
||||
"RemoveTagRemovingTag": "Címke eltávolítása",
|
||||
"RemovedFromTaskQueue": "Eltávolítva a feladatsorról",
|
||||
@@ -696,7 +695,6 @@
|
||||
"BlocklistRelease": "Feketelistás Kiadás",
|
||||
"NoHistoryBlocklist": "Nincs blokkolási előzménylista",
|
||||
"Blocklist": "Feketelista",
|
||||
"BlocklistHelpText": "Megakadályozza, hogy a Readarr automatikusan letöltse újra",
|
||||
"RemoveFromBlocklist": "Eltávolítás a feketelistáról",
|
||||
"UnableToLoadBlocklist": "Nem sikerült betölteni a feketelistát",
|
||||
"Component": "Komponens",
|
||||
@@ -780,7 +778,7 @@
|
||||
"RemotePathMappingCheckDockerFolderMissing": "Dockert használsz; a letöltő kliens {0} letölti a letöltéseket a(z) {1} fájlban, de úgy tűnik, hogy ez a könyvtár nem létezik a tárolóban. Tekintse át a távoli elérési utak hozzárendelését és a tároló kötetbeállításait.",
|
||||
"RemotePathMappingCheckGenericPermissions": "A letöltőkliens {0} a letöltéseket a(z) {1} helyre helyezi, de a Readarr nem látja ezt a könyvtárat. Lehet, hogy módosítania kell a mappa engedélyeit.",
|
||||
"RemotePathMappingCheckLocalWrongOSPath": "A helyi letöltőkliens {0} letölti a letöltéseket a(z) {1} könyvtárba, de ez nem érvényes {2} útvonal. Ellenőrizze a letöltőkliens beállításait.",
|
||||
"AppDataLocationHealthCheckMessage": "A frissítés nem lehetséges anélkül hogy az AppData ne törlődjön",
|
||||
"AppDataLocationHealthCheckMessage": "A frissítés nem lehetséges az alkalmazás adatok törlése nélkül",
|
||||
"IndexerSearchCheckNoAutomaticMessage": "Nincs elérhető indexelő Automatikus kereséssel engedélyezve. A Readarr nem nyújt automatikus keresési eredményt",
|
||||
"ProxyCheckResolveIpMessage": "Nem sikerült megoldani a konfigurált proxykiszolgáló IP-címét {0}",
|
||||
"RootFolderCheckSingleMessage": "Hiányzó gyökérmappa: {0}",
|
||||
@@ -879,17 +877,17 @@
|
||||
"MinimumCustomFormatScore": "Minimum Egyéni Formátum száma",
|
||||
"BypassIfHighestQuality": "Kihagyás ha a legjobb minőség elérhető",
|
||||
"CustomFormatScore": "Egyéni formátum pontszám",
|
||||
"CloneCustomFormat": "Egyéni Formátum Klónozása",
|
||||
"CloneCustomFormat": "Egyéni formátum klónozása",
|
||||
"Conditions": "Állapot",
|
||||
"CopyToClipboard": "Másold a Vágólapra",
|
||||
"CustomFormat": "Egyéni formátum",
|
||||
"CustomFormatSettings": "Egyéni Formátum Beállításai",
|
||||
"CustomFormats": "Egyéni Formátumok",
|
||||
"DataFutureBooks": "Figyelje meg azokat az albumokat, amelyek még nem jelentek meg",
|
||||
"DeleteCustomFormat": "Egyéni Formátum Törlése",
|
||||
"DeleteCustomFormatMessageText": "Biztosan törlöd a(z) „{0}” gyökérmappát?",
|
||||
"DeleteCustomFormat": "Egyéni formátum törlése",
|
||||
"DeleteCustomFormatMessageText": "Biztosan törölni akarod a/az '{0}' egyéni formátumot?",
|
||||
"DeleteFormatMessageText": "Biztosan törlöd a(z) {0} formátumú címkét?",
|
||||
"ExportCustomFormat": "Egyéni Formátum Exportálása",
|
||||
"ExportCustomFormat": "Egyéni formátum exportálása",
|
||||
"Formats": "Formátumok",
|
||||
"IncludeCustomFormatWhenRenamingHelpText": "Tartalmazza a(z) {Custom Formats} átnevezési formátumot",
|
||||
"MinFormatScoreHelpText": "A letöltéshez engedélyezett minimális egyéni formátum pontszám",
|
||||
@@ -904,8 +902,20 @@
|
||||
"ImportListMultipleMissingRoots": "Több gyökérmappa hiányzik az importálási listákhoz: {0}",
|
||||
"IndexerDownloadClientHelpText": "Adja meg, hogy melyik letöltési kliens használja az indexelőből történő megfogásokat",
|
||||
"IndexerTagsHelpText": "Csak olyan filmekhez használja ezt az indexelőt, amelyek legalább egy megfelelő címkével rendelkeznek. Hagyja üresen az összes filmhez való használathoz.",
|
||||
"HiddenClickToShow": "Rejtett, kattints a megjelenítéshez",
|
||||
"HideAdvanced": "Haladó Elrejtése",
|
||||
"HiddenClickToShow": "Rejtett, kattints a felfedéshez",
|
||||
"HideAdvanced": "Haladó elrejtése",
|
||||
"ShowAdvanced": "Haladó nézet",
|
||||
"ShownClickToHide": "Kattints, hogy elrejtsd"
|
||||
"ShownClickToHide": "Kattints, hogy elrejtsd",
|
||||
"ColonReplacement": "Kettőspont Helyettesítés",
|
||||
"ReplaceWithDash": "Cserélés kötőjelre",
|
||||
"ReplaceWithSpaceDash": "Cserélje szóközre",
|
||||
"ReplaceWithSpaceDashSpace": "Cserélje Szóköz kötőjel szóközre",
|
||||
"CloneCondition": "Feltétel klónozása",
|
||||
"DeleteCondition": "Feltétel törlése",
|
||||
"RemoveSelectedItem": "Kijelölt elem eltávolítása",
|
||||
"RemoveSelectedItemQueueMessageText": "Biztosan el akar távolítani 1 elemet a várólistáról?",
|
||||
"RemoveSelectedItems": "Kijelölt elemek eltávolítása",
|
||||
"RemoveSelectedItemsQueueMessageText": "Biztosan el akar távolítani {0} elemet a várólistáról?",
|
||||
"Required": "Kötelező",
|
||||
"ApiKeyValidationHealthCheckMessage": "Kérlek frissítsd az API kulcsot, ami legalább {0} karakter hosszú. Ezt megteheted a Beállításokban, vagy a config file-ban"
|
||||
}
|
||||
|
||||
@@ -23,5 +23,15 @@
|
||||
"Calendar": "Kalender",
|
||||
"Cancel": "Batal",
|
||||
"Grab": "Peroleh",
|
||||
"Hostname": "Hostname"
|
||||
"Hostname": "Hostname",
|
||||
"ChangeHasNotBeenSavedYet": "Perubahan belum disimpan",
|
||||
"ClickToChangeQuality": "Klik untuk mengubah kualitas",
|
||||
"AlternateTitles": "Judul Lain",
|
||||
"AppDataDirectory": "Direktori AppData",
|
||||
"Connections": "Koleksi",
|
||||
"ExportCustomFormat": "Tambahkan Format Khusus",
|
||||
"AuthorClickToChangeBook": "Klik untuk mengubah film",
|
||||
"Automatic": "Otomatis",
|
||||
"Close": "Tutup",
|
||||
"Delete": "Hapus"
|
||||
}
|
||||
|
||||
@@ -295,7 +295,6 @@
|
||||
"RemoveFromQueue": "Fjarlægðu úr biðröð",
|
||||
"RemoveHelpTextWarning": "Fjarlæging fjarlægir niðurhalið og skrána / skrána úr niðurhalsviðskiptavininum.",
|
||||
"RemoveSelected": "Fjarlægja valið",
|
||||
"RemoveSelectedMessageText": "Ertu viss um að þú viljir fjarlægja valda hluti af svörtum lista?",
|
||||
"RemoveTagExistingTag": "Núverandi merki",
|
||||
"RemoveTagRemovingTag": "Fjarlægir merkið",
|
||||
"RemovedFromTaskQueue": "Fjarlægð úr verkröð",
|
||||
@@ -578,5 +577,19 @@
|
||||
"HiddenClickToShow": "Falinn, smelltu til að sýna",
|
||||
"HideAdvanced": "Fela lengra komna",
|
||||
"ShowAdvanced": "Sýna lengra komna",
|
||||
"ShownClickToHide": "Sýnt, smelltu til að fela"
|
||||
"ShownClickToHide": "Sýnt, smelltu til að fela",
|
||||
"ColonReplacement": "Skipt um ristil",
|
||||
"ReplaceWithDash": "Skiptu um með Dash",
|
||||
"ReplaceWithSpaceDash": "Skiptu um með Space Dash",
|
||||
"ReplaceWithSpaceDashSpace": "Skiptu um með Space Dash Space",
|
||||
"DeleteRemotePathMapping": "Breyta kortlagningu fjarstígs",
|
||||
"DeleteRemotePathMappingMessageText": "Ertu viss um að þú viljir eyða þessari ytri slóðakortun?",
|
||||
"BlocklistReleases": "Útgáfa svartalista",
|
||||
"DeleteConditionMessageText": "Ertu viss um að þú viljir eyða merkinu '{0}'?",
|
||||
"Negated": "Negated",
|
||||
"RemoveSelectedItemBlocklistMessageText": "Ertu viss um að þú viljir fjarlægja valda hluti af svörtum lista?",
|
||||
"RemoveSelectedItemQueueMessageText": "Ertu viss um að þú viljir fjarlægja {0} hlut {1} úr biðröðinni?",
|
||||
"RemoveSelectedItemsQueueMessageText": "Ertu viss um að þú viljir fjarlægja {0} hlut {1} úr biðröðinni?",
|
||||
"Required": "Nauðsynlegt",
|
||||
"NoEventsFound": "Engir viðburðir fundust"
|
||||
}
|
||||
|
||||
@@ -298,7 +298,6 @@
|
||||
"RemoveFromQueue": "Rimuovi dalla coda",
|
||||
"RemoveHelpTextWarning": "La rimozione eliminerà il download e i file dal client di download.",
|
||||
"RemoveSelected": "Rimuovi Selezionato",
|
||||
"RemoveSelectedMessageText": "Sei sicuro di voler rimuovere gli elementi selezionati della blacklist?",
|
||||
"RemoveTagExistingTag": "Tag esistente",
|
||||
"RemoveTagRemovingTag": "Sto eliminando il tag",
|
||||
"RemovedFromTaskQueue": "Rimosso dalla coda lavori",
|
||||
@@ -471,7 +470,6 @@
|
||||
"AddMissing": "Aggiungi mancanti",
|
||||
"AddNewItem": "Aggiungi Nuovo Elemento",
|
||||
"Blocklist": "Lista dei Blocchi",
|
||||
"BlocklistHelpText": "Impedisci a Readarr di re-acquisire automaticamente questi file",
|
||||
"BlocklistRelease": "Release in Lista dei Blocchi",
|
||||
"AllowFingerprinting": "Consenti il \"Fingerprinting\"",
|
||||
"AllExpandedCollapseAll": "Collassa tutto",
|
||||
@@ -684,5 +682,9 @@
|
||||
"HiddenClickToShow": "Nascosto, premi per mostrare",
|
||||
"HideAdvanced": "Nascondi Avanzate",
|
||||
"ShowAdvanced": "Mostra Avanzate",
|
||||
"ShownClickToHide": "Visibile, clicca per nascondere"
|
||||
"ShownClickToHide": "Visibile, clicca per nascondere",
|
||||
"ColonReplacement": "Sostituzione Due Punti",
|
||||
"ReplaceWithDash": "Sostituisci con Dash",
|
||||
"ReplaceWithSpaceDash": "Sostituisci con Space Dash",
|
||||
"ReplaceWithSpaceDashSpace": "Sostituisci con Space Dash Space"
|
||||
}
|
||||
|
||||
@@ -288,7 +288,6 @@
|
||||
"RemoveHelpTextWarning": "削除すると、ダウンロードとファイルがダウンロードクライアントから削除されます。",
|
||||
"RemoveSelected": "削除選択",
|
||||
"UpdateMechanismHelpText": "Radarrの組み込みアップデーターまたはスクリプトを使用する",
|
||||
"RemoveSelectedMessageText": "選択したアイテムをブラックリストから削除してもよろしいですか?",
|
||||
"RemoveTagExistingTag": "既存のタグ",
|
||||
"RemoveTagRemovingTag": "タグの削除",
|
||||
"RemovedFromTaskQueue": "タスクキューから削除されました",
|
||||
@@ -578,5 +577,17 @@
|
||||
"HiddenClickToShow": "非表示、クリックして表示",
|
||||
"HideAdvanced": "高度な非表示",
|
||||
"ShowAdvanced": "高度な表示",
|
||||
"ShownClickToHide": "表示、クリックして非表示"
|
||||
"ShownClickToHide": "表示、クリックして非表示",
|
||||
"ColonReplacement": "結腸の置換",
|
||||
"ReplaceWithDash": "ダッシュに置き換えます",
|
||||
"ReplaceWithSpaceDash": "スペースダッシュに置き換えます",
|
||||
"ReplaceWithSpaceDashSpace": "スペースダッシュスペースに置き換えます",
|
||||
"DeleteRemotePathMapping": "リモートパスマッピングの編集",
|
||||
"Negated": "否定",
|
||||
"RemoveSelectedItemBlocklistMessageText": "選択したアイテムをブラックリストから削除してもよろしいですか?",
|
||||
"RemoveSelectedItemQueueMessageText": "キューから{0}アイテム{1}を削除してもよろしいですか?",
|
||||
"RemoveSelectedItemsQueueMessageText": "キューから{0}アイテム{1}を削除してもよろしいですか?",
|
||||
"Required": "必須",
|
||||
"BlocklistReleases": "ブラックリストリリース",
|
||||
"DeleteConditionMessageText": "リスト「{0}」を削除してもよろしいですか?"
|
||||
}
|
||||
|
||||
@@ -310,7 +310,6 @@
|
||||
"RemoveFromQueue": "대기열에서 제거",
|
||||
"RemoveHelpTextWarning": "제거하면 다운로드 클라이언트에서 다운로드 및 파일이 제거됩니다.",
|
||||
"RemoveSelected": "선택된 것을 지워 라",
|
||||
"RemoveSelectedMessageText": "블랙리스트에서 선택한 항목을 제거 하시겠습니까?",
|
||||
"RemoveTagExistingTag": "기존 태그",
|
||||
"RemoveTagRemovingTag": "태그 제거",
|
||||
"RemovedFromTaskQueue": "작업 대기열에서 제거됨",
|
||||
@@ -577,5 +576,11 @@
|
||||
"UpgradesAllowed": "허용되는 업그레이드",
|
||||
"HideAdvanced": "고급 숨기기",
|
||||
"HiddenClickToShow": "숨김, 클릭하여 표시",
|
||||
"ShowAdvanced": "고급보기"
|
||||
"ShowAdvanced": "고급보기",
|
||||
"DeleteRemotePathMapping": "원격 경로 매핑 편집",
|
||||
"BlocklistReleases": "블랙리스트 릴리스",
|
||||
"DeleteConditionMessageText": "'{0}' 태그를 삭제하시겠습니까?",
|
||||
"RemoveSelectedItemQueueMessageText": "대기열에서 {0} 항목 {1}을 제거하시겠습니까?",
|
||||
"RemoveSelectedItemBlocklistMessageText": "블랙리스트에서 선택한 항목을 제거 하시겠습니까?",
|
||||
"RemoveSelectedItemsQueueMessageText": "대기열에서 {0} 항목 {1}을 제거하시겠습니까?"
|
||||
}
|
||||
|
||||
@@ -46,7 +46,6 @@
|
||||
"DeleteImportListExclusionMessageText": "Er du sikker på at du vil slette denne ekskluderingen av importlister?",
|
||||
"DeleteReleaseProfileMessageText": "Er du sikker på at du vil slette denne forsinkelsesprofilen?",
|
||||
"DeleteTagMessageText": "Er du sikker på at du vil slette formattaggen {0}?",
|
||||
"RemoveSelectedMessageText": "Er du sikker på at du vil fjerne de valgte elementene fra svartelisten?",
|
||||
"ResetAPIKeyMessageText": "Er du sikker på at du vil tilbakestille API -nøkkelen din?",
|
||||
"ShowQualityProfile": "Legg til kvalitetsprofil",
|
||||
"UsingExternalUpdateMechanismBranchToUseToUpdateReadarr": "Gren som skal brukes til å oppdatere Radarr",
|
||||
@@ -61,7 +60,6 @@
|
||||
"All": "Alle",
|
||||
"DeleteBackupMessageText": "Er du sikker på at du vil slette formattaggen {0}?",
|
||||
"Blocklist": "Svarteliste",
|
||||
"BlocklistHelpText": "Hindrer Radarr i å automatisk gripe denne utgivelsen igjen",
|
||||
"BlocklistRelease": "Blacklist -utgivelse",
|
||||
"AppDataLocationHealthCheckMessage": "Oppdatering vil ikke være mulig for å forhindre sletting av AppData på oppdateringen",
|
||||
"CopyUsingHardlinksHelpText": "Bruk harde lenker ved forsøk på å kopiere filer fra torrents som fortsatt blir delt",
|
||||
@@ -147,5 +145,11 @@
|
||||
"CustomFormat": "Egendefinert format",
|
||||
"CustomFormats": "Egendefinert format",
|
||||
"BypassIfHighestQuality": "Omgå hvis høyeste kvalitet",
|
||||
"Formats": "Format"
|
||||
"Formats": "Format",
|
||||
"ColonReplacement": "Kolon erstatntning",
|
||||
"20MinutesTwenty": "20 Minutter: {0}",
|
||||
"AddMissing": "Legg til manglende",
|
||||
"AddNewItem": "Legg til nytt item",
|
||||
"45MinutesFourtyFive": "45 Minutter: {0}",
|
||||
"60MinutesSixty": "60 Minutter: {0}"
|
||||
}
|
||||
|
||||
@@ -297,7 +297,6 @@
|
||||
"RemoveFromQueue": "Verwijder uit wachtrij",
|
||||
"RemoveHelpTextWarning": "Het verwijderen zal zowel de download als de bestanden verwijderen bij de downloader.",
|
||||
"RemoveSelected": "Selectie Verwijderen",
|
||||
"RemoveSelectedMessageText": "Ben je zeker dat je de geselecteerde items wil verwijderen van de uitzonderingslijst?",
|
||||
"RemoveTagExistingTag": "Bestaande tag",
|
||||
"RemoveTagRemovingTag": "Tag verwijderen",
|
||||
"RemovedFromTaskQueue": "Verwijderd uit taken wachtrij",
|
||||
@@ -479,14 +478,13 @@
|
||||
"SelectAll": "Alles Selecteren",
|
||||
"SelectedCountBooksSelectedInterp": "{0} Film(s) Geselecteerd",
|
||||
"Series": "Series",
|
||||
"ThisCannotBeCancelled": "Eenmaal gestart kan dit niet worden geannuleerd zonder Radarr opnieuw te starten.",
|
||||
"ThisCannotBeCancelled": "Eenmaal gestart kan dit niet worden geannuleerd zonder al je indexeerders uit te schakelen.",
|
||||
"UnableToLoadBlocklist": "Kon zwarte lijst niet laden",
|
||||
"UnselectAll": "Alles Deselecteren",
|
||||
"UpdateSelected": "Selectie Bijwerken",
|
||||
"Time": "Tijd",
|
||||
"Label": "Label",
|
||||
"Wanted": "Gezocht",
|
||||
"BlocklistHelpText": "Voorkom dat Radarr deze release nogmaals automatisch ophaalt",
|
||||
"AppDataLocationHealthCheckMessage": "Updaten zal niet mogelijk zijn om het verwijderen van AppData te voorkomen",
|
||||
"AddedAuthorSettings": "Auteur instellingen toegevoegd",
|
||||
"AddMissing": "Voeg ontbrekende toe",
|
||||
@@ -632,5 +630,16 @@
|
||||
"HiddenClickToShow": "Verborgen, klik om te tonen",
|
||||
"HideAdvanced": "Verberg Gevorderd",
|
||||
"ShowAdvanced": "Toon Geavanceerd",
|
||||
"ShownClickToHide": "Getoond, klik om te verbergen"
|
||||
"ShownClickToHide": "Getoond, klik om te verbergen",
|
||||
"ColonReplacement": "Dubbelepunt Vervanging",
|
||||
"IndexerJackettAll": "Indexeerders die het niet ondersteunde 'all' endpoint van Jacket gebruiken: {0}",
|
||||
"ReplaceWithDash": "Vervang met Streepje",
|
||||
"ReplaceWithSpaceDash": "Vervang met Spatie Streepje",
|
||||
"ReplaceWithSpaceDashSpace": "Vervang met Spatie Streepje Spatie",
|
||||
"InstanceName": "Naam van de instantie",
|
||||
"ThereWasAnErrorLoadingThisItem": "Er ging iets fout bij het laden van dit item",
|
||||
"ThereWasAnErrorLoadingThisPage": "Er ging iets fout bij het laden van deze pagina",
|
||||
"ApiKeyValidationHealthCheckMessage": "Maak je API sleutel alsjeblieft minimaal {0} karakters lang. Dit kan gedaan worden via de instellingen of het configuratiebestand",
|
||||
"ResetDefinitions": "Reset definities",
|
||||
"ResetTitles": "Reset titels"
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user