mirror of
https://github.com/Readarr/Readarr.git
synced 2026-03-17 16:14:04 -04:00
Compare commits
39 Commits
v0.2.0.190
...
v0.2.3.195
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
690e0b5d96 | ||
|
|
212eedd345 | ||
|
|
0b38743292 | ||
|
|
1def54f246 | ||
|
|
0eeaa1e443 | ||
|
|
7beee07a2c | ||
|
|
924f739d1f | ||
|
|
b187fb23e3 | ||
|
|
ca043b3820 | ||
|
|
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 |
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.2.0'
|
||||
majorVersion: '0.2.3'
|
||||
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}"
|
||||
|
||||
@@ -16,6 +16,12 @@
|
||||
width: 150px;
|
||||
}
|
||||
|
||||
.customFormatScore {
|
||||
composes: cell from '~Components/Table/Cells/TableRowCell.css';
|
||||
|
||||
width: 55px;
|
||||
}
|
||||
|
||||
.actions {
|
||||
composes: cell from '~Components/Table/Cells/TableRowCell.css';
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// Please do not change this file!
|
||||
interface CssExports {
|
||||
'actions': string;
|
||||
'customFormatScore': string;
|
||||
'progress': string;
|
||||
'protocol': string;
|
||||
'quality': string;
|
||||
|
||||
@@ -17,6 +17,7 @@ import Popover from 'Components/Tooltip/Popover';
|
||||
import { icons, kinds, tooltipPositions } from 'Helpers/Props';
|
||||
import InteractiveImportModal from 'InteractiveImport/InteractiveImportModal';
|
||||
import formatBytes from 'Utilities/Number/formatBytes';
|
||||
import formatPreferredWordScore from 'Utilities/Number/formatPreferredWordScore';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import QueueStatusCell from './QueueStatusCell';
|
||||
import RemoveQueueItemModal from './RemoveQueueItemModal';
|
||||
@@ -91,6 +92,7 @@ class QueueRow extends Component {
|
||||
book,
|
||||
quality,
|
||||
customFormats,
|
||||
customFormatScore,
|
||||
protocol,
|
||||
indexer,
|
||||
outputPath,
|
||||
@@ -222,6 +224,17 @@ class QueueRow extends Component {
|
||||
);
|
||||
}
|
||||
|
||||
if (name === 'customFormatScore') {
|
||||
return (
|
||||
<TableRowCell
|
||||
key={name}
|
||||
className={styles.customFormatScore}
|
||||
>
|
||||
{formatPreferredWordScore(customFormatScore)}
|
||||
</TableRowCell>
|
||||
);
|
||||
}
|
||||
|
||||
if (name === 'protocol') {
|
||||
return (
|
||||
<TableRowCell key={name}>
|
||||
@@ -392,6 +405,7 @@ QueueRow.propTypes = {
|
||||
book: PropTypes.object,
|
||||
quality: PropTypes.object.isRequired,
|
||||
customFormats: PropTypes.arrayOf(PropTypes.object),
|
||||
customFormatScore: PropTypes.number.isRequired,
|
||||
protocol: PropTypes.string.isRequired,
|
||||
indexer: PropTypes.string,
|
||||
outputPath: PropTypes.string,
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -258,7 +258,9 @@ class InteractiveImportRow extends Component {
|
||||
>
|
||||
{
|
||||
showReleaseGroupPlaceholder ?
|
||||
<InteractiveImportRowCellPlaceholder /> :
|
||||
<InteractiveImportRowCellPlaceholder
|
||||
isOptional={true}
|
||||
/> :
|
||||
releaseGroup
|
||||
}
|
||||
</TableRowCellButton>
|
||||
|
||||
@@ -5,3 +5,7 @@
|
||||
height: 25px;
|
||||
border: 2px dashed var(--dangerColor);
|
||||
}
|
||||
|
||||
.optional {
|
||||
border: 2px dashed var(--gray);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// This file is automatically generated.
|
||||
// Please do not change this file!
|
||||
interface CssExports {
|
||||
'optional': string;
|
||||
'placeholder': string;
|
||||
}
|
||||
export const cssExports: CssExports;
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
import React from 'react';
|
||||
import styles from './InteractiveImportRowCellPlaceholder.css';
|
||||
|
||||
function InteractiveImportRowCellPlaceholder() {
|
||||
return (
|
||||
<span className={styles.placeholder} />
|
||||
);
|
||||
}
|
||||
|
||||
export default InteractiveImportRowCellPlaceholder;
|
||||
@@ -0,0 +1,22 @@
|
||||
import classNames from 'classnames';
|
||||
import React from 'react';
|
||||
import styles from './InteractiveImportRowCellPlaceholder.css';
|
||||
|
||||
interface InteractiveImportRowCellPlaceholderProps {
|
||||
isOptional?: boolean;
|
||||
}
|
||||
|
||||
function InteractiveImportRowCellPlaceholder(
|
||||
props: InteractiveImportRowCellPlaceholderProps
|
||||
) {
|
||||
return (
|
||||
<span
|
||||
className={classNames(
|
||||
styles.placeholder,
|
||||
props.isOptional && styles.optional
|
||||
)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export default InteractiveImportRowCellPlaceholder;
|
||||
@@ -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;
|
||||
|
||||
@@ -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,7 +1,9 @@
|
||||
import _ from 'lodash';
|
||||
import React from 'react';
|
||||
import { createAction } from 'redux-actions';
|
||||
import { batchActions } from 'redux-batched-actions';
|
||||
import { sortDirections } from 'Helpers/Props';
|
||||
import Icon from 'Components/Icon';
|
||||
import { icons, sortDirections } from 'Helpers/Props';
|
||||
import { createThunk, handleThunks } from 'Store/thunks';
|
||||
import createAjaxRequest from 'Utilities/createAjaxRequest';
|
||||
import serverSideCollectionHandlers from 'Utilities/serverSideCollectionHandlers';
|
||||
@@ -93,6 +95,15 @@ export const defaultState = {
|
||||
isSortable: false,
|
||||
isVisible: true
|
||||
},
|
||||
{
|
||||
name: 'customFormatScore',
|
||||
columnLabel: translate('CustomFormatScore'),
|
||||
label: React.createElement(Icon, {
|
||||
name: icons.SCORE,
|
||||
title: translate('CustomFormatScore')
|
||||
}),
|
||||
isVisible: false
|
||||
},
|
||||
{
|
||||
name: 'protocol',
|
||||
label: translate('Protocol'),
|
||||
|
||||
@@ -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>
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
30
package.json
30
package.json
@@ -86,27 +86,27 @@
|
||||
"typescript": "4.9.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "7.21.8",
|
||||
"@babel/eslint-parser": "7.21.8",
|
||||
"@babel/core": "7.22.9",
|
||||
"@babel/eslint-parser": "7.22.9",
|
||||
"@babel/plugin-proposal-class-properties": "7.18.6",
|
||||
"@babel/plugin-proposal-export-default-from": "7.18.10",
|
||||
"@babel/plugin-proposal-export-default-from": "7.22.5",
|
||||
"@babel/plugin-proposal-export-namespace-from": "7.18.9",
|
||||
"@babel/plugin-proposal-nullish-coalescing-operator": "7.18.6",
|
||||
"@babel/plugin-proposal-optional-chaining": "7.21.0",
|
||||
"@babel/plugin-syntax-dynamic-import": "7.8.3",
|
||||
"@babel/preset-env": "7.21.5",
|
||||
"@babel/preset-react": "7.18.6",
|
||||
"@babel/preset-typescript": "7.21.5",
|
||||
"@typescript-eslint/eslint-plugin": "5.59.7",
|
||||
"@typescript-eslint/parser": "5.59.7",
|
||||
"@babel/preset-env": "7.22.9",
|
||||
"@babel/preset-react": "7.22.5",
|
||||
"@babel/preset-typescript": "7.22.5",
|
||||
"@typescript-eslint/eslint-plugin": "6.0.0",
|
||||
"@typescript-eslint/parser": "6.0.0",
|
||||
"autoprefixer": "10.4.14",
|
||||
"babel-loader": "9.1.2",
|
||||
"babel-loader": "9.1.3",
|
||||
"babel-plugin-inline-classnames": "2.0.1",
|
||||
"babel-plugin-transform-react-remove-prop-types": "0.4.24",
|
||||
"core-js": "3.30.2",
|
||||
"core-js": "3.31.1",
|
||||
"css-loader": "6.7.3",
|
||||
"css-modules-typescript-loader": "4.0.1",
|
||||
"eslint": "8.40.0",
|
||||
"eslint": "8.44.0",
|
||||
"eslint-config-prettier": "8.8.0",
|
||||
"eslint-plugin-filenames": "1.3.2",
|
||||
"eslint-plugin-import": "2.27.5",
|
||||
@@ -134,14 +134,14 @@
|
||||
"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",
|
||||
"terser-webpack-plugin": "5.3.9",
|
||||
"ts-loader": "9.4.3",
|
||||
"typescript-plugin-css-modules": "5.0.1",
|
||||
"url-loader": "4.1.1",
|
||||
"webpack": "5.82.1",
|
||||
"webpack-cli": "5.1.1",
|
||||
"webpack": "5.88.1",
|
||||
"webpack-cli": "5.1.4",
|
||||
"webpack-livereload-plugin": "3.0.2",
|
||||
"worker-loader": "3.0.8"
|
||||
},
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,24 +21,24 @@ namespace NzbDrone.Core.Housekeeping.Housekeepers
|
||||
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 }
|
||||
});
|
||||
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)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,11 +17,11 @@ namespace NzbDrone.Core.Housekeeping.Housekeepers
|
||||
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 });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,10 +49,15 @@ namespace NzbDrone.Core.ImportLists
|
||||
var importListLocal = importList;
|
||||
var importListStatus = _importListStatusService.GetLastSyncListInfo(importListLocal.Definition.Id);
|
||||
|
||||
if (importListStatus.HasValue && DateTime.UtcNow < importListStatus + importListLocal.MinRefreshInterval)
|
||||
if (importListStatus.HasValue)
|
||||
{
|
||||
_logger.Trace("Skipping refresh of Import List {0} due to minimum refresh inverval", importListLocal.Definition.Name);
|
||||
continue;
|
||||
var importListNextSync = importListStatus.Value + importListLocal.MinRefreshInterval;
|
||||
|
||||
if (DateTime.UtcNow < importListNextSync)
|
||||
{
|
||||
_logger.Trace("Skipping refresh of Import List {0} ({1}) due to minimum refresh interval. Next sync after {2}", importList.Name, importListLocal.Definition.Name, importListNextSync);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
var task = taskFactory.StartNew(() =>
|
||||
@@ -63,7 +68,7 @@ namespace NzbDrone.Core.ImportLists
|
||||
|
||||
lock (result)
|
||||
{
|
||||
_logger.Debug("Found {0} from {1}", importListReports.Count, importList.Name);
|
||||
_logger.Debug("Found {0} reports from {1} ({2})", importListReports.Count, importList.Name, importListLocal.Definition.Name);
|
||||
|
||||
result.AddRange(importListReports);
|
||||
}
|
||||
@@ -72,7 +77,7 @@ namespace NzbDrone.Core.ImportLists
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.Error(e, "Error during Import List Sync");
|
||||
_logger.Error(e, "Error during Import List Sync of {0} ({1})", importList.Name, importListLocal.Definition.Name);
|
||||
}
|
||||
}).LogExceptions();
|
||||
|
||||
@@ -83,7 +88,7 @@ namespace NzbDrone.Core.ImportLists
|
||||
|
||||
result = result.DistinctBy(r => new { r.Author, r.Book }).ToList();
|
||||
|
||||
_logger.Debug("Found {0} reports", result.Count);
|
||||
_logger.Debug("Found {0} total reports from {1} lists", result.Count, importLists.Count);
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -96,7 +101,7 @@ namespace NzbDrone.Core.ImportLists
|
||||
|
||||
if (importList == null || !definition.EnableAutomaticAdd)
|
||||
{
|
||||
_logger.Debug("Import list not enabled, skipping.");
|
||||
_logger.Debug("Import List {0} ({1}) is not enabled, skipping.", importList.Name, importList.Definition.Name);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -121,7 +126,7 @@ namespace NzbDrone.Core.ImportLists
|
||||
|
||||
lock (result)
|
||||
{
|
||||
_logger.Debug("Found {0} from {1}", importListReports.Count, importList.Name);
|
||||
_logger.Debug("Found {0} reports from {1} ({2})", importListReports.Count, importList.Name, importListLocal.Definition.Name);
|
||||
|
||||
result.AddRange(importListReports);
|
||||
}
|
||||
@@ -130,7 +135,7 @@ namespace NzbDrone.Core.ImportLists
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.Error(e, "Error during Import List Sync");
|
||||
_logger.Error(e, "Error during Import List Sync of {0} ({1})", importList.Name, importListLocal.Definition.Name);
|
||||
}
|
||||
}).LogExceptions();
|
||||
|
||||
|
||||
@@ -590,5 +590,7 @@
|
||||
"RemoveSelectedItemQueueMessageText": "هل تريد بالتأكيد إزالة {0} عنصر {1} من قائمة الانتظار؟",
|
||||
"Required": "مطلوب",
|
||||
"DeleteConditionMessageText": "هل أنت متأكد أنك تريد حذف العلامة \"{0}\"؟",
|
||||
"RemoveSelectedItemsQueueMessageText": "هل تريد بالتأكيد إزالة {0} عنصر {1} من قائمة الانتظار؟"
|
||||
"RemoveSelectedItemsQueueMessageText": "هل تريد بالتأكيد إزالة {0} عنصر {1} من قائمة الانتظار؟",
|
||||
"NoEventsFound": "لم يتم العثور على أحداث",
|
||||
"BlocklistReleaseHelpText": "يمنع Radarr من الاستيلاء على هذا الإصدار تلقائيًا مرة أخرى"
|
||||
}
|
||||
|
||||
@@ -590,5 +590,6 @@
|
||||
"Required": "Задължително",
|
||||
"Negated": "Отрицателно",
|
||||
"RemoveSelectedItemBlocklistMessageText": "Наистина ли искате да премахнете избраните елементи от черния списък?",
|
||||
"RemoveSelectedItemsQueueMessageText": "Наистина ли искате да премахнете {0} елемент {1} от опашката?"
|
||||
"RemoveSelectedItemsQueueMessageText": "Наистина ли искате да премахнете {0} елемент {1} от опашката?",
|
||||
"NoEventsFound": "Няма намерени събития"
|
||||
}
|
||||
|
||||
@@ -590,5 +590,6 @@
|
||||
"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é"
|
||||
"Required": "Požadované",
|
||||
"NoEventsFound": "Nebyly nalezeny žádné události"
|
||||
}
|
||||
|
||||
@@ -593,5 +593,6 @@
|
||||
"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"
|
||||
"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",
|
||||
@@ -807,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",
|
||||
@@ -883,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",
|
||||
@@ -894,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",
|
||||
@@ -913,5 +913,15 @@
|
||||
"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"
|
||||
"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"
|
||||
}
|
||||
|
||||
@@ -78,7 +78,7 @@
|
||||
"DeleteBackup": "Διαγραφή αντιγράφων ασφαλείας",
|
||||
"DeleteBackupMessageText": "Είστε βέβαιοι ότι θέλετε να διαγράψετε το αντίγραφο ασφαλείας \"{0}\";",
|
||||
"DeleteDelayProfile": "Διαγραφή προφίλ καθυστέρησης",
|
||||
"DeleteDelayProfileMessageText": "Είστε βέβαιοι ότι θέλετε να διαγράψετε αυτό το προφίλ καθυστέρησης;",
|
||||
"DeleteDelayProfileMessageText": "Είστε σίγουροι πως θέλετε να διαγράψετε αυτό το Προφίλ χρονοκαθυστέρησης;",
|
||||
"DeleteDownloadClient": "Διαγραφή προγράμματος-πελάτη λήψης",
|
||||
"DeleteDownloadClientMessageText": "Είστε βέβαιοι ότι θέλετε να διαγράψετε τον πελάτη λήψης \"{0}\";",
|
||||
"DeleteEmptyFolders": "Διαγραφή κενών φακέλων",
|
||||
@@ -888,7 +888,7 @@
|
||||
"Formats": "Φορμάτ",
|
||||
"IncludeCustomFormatWhenRenamingHelpText": "Συμπεριλάβετε στη μορφή μετονομασίας {Custom Formats}",
|
||||
"MinFormatScoreHelpText": "Επιτρέπεται η λήψη της ελάχιστης βαθμολογίας προσαρμοσμένης μορφής",
|
||||
"ResetDefinitionTitlesHelpText": "Επαναφέρετε τίτλους ορισμού καθώς και τιμές",
|
||||
"ResetDefinitionTitlesHelpText": "Επαναφορά τίτλων ορισμού και των τιμών τους",
|
||||
"UpgradesAllowed": "Επιτρέπονται αναβαθμίσεις",
|
||||
"CustomFormats": "Προσαρμοσμένες Μορφές",
|
||||
"ResetTitles": "Επαναφορά τίτλων",
|
||||
@@ -899,7 +899,7 @@
|
||||
"CutoffFormatScoreHelpText": "Μόλις επιτευχθεί αυτό το σκορ προσαρμοσμένης μορφής, το Radarr δεν θα κατεβάζει πλέον ταινίες",
|
||||
"DataFutureBooks": "Παρακολουθήστε άλμπουμ που δεν έχουν κυκλοφορήσει ακόμα",
|
||||
"DeleteCustomFormat": "Διαγραφή προσαρμοσμένης μορφής",
|
||||
"DeleteCustomFormatMessageText": "Είστε βέβαιοι ότι θέλετε να διαγράψετε το ευρετήριο \"{0}\";",
|
||||
"DeleteCustomFormatMessageText": "Είστε σίγουροι πως θέλετε να διαγράψετε τη προσαρμοσμένη μορφή '{0}';",
|
||||
"DeleteFormatMessageText": "Είστε βέβαιοι ότι θέλετε να διαγράψετε την ετικέτα μορφής {0};",
|
||||
"NegateHelpText": "Εάν επιλεγεί, η προσαρμοσμένη μορφή δεν θα εφαρμοστεί εάν αντιστοιχεί σε αυτήν την {0} συνθήκη.",
|
||||
"ImportListMissingRoot": "Λείπει ο ριζικός φάκελος για λίστες εισαγωγής: {0}",
|
||||
@@ -923,5 +923,11 @@
|
||||
"ThereWasAnErrorLoadingThisItem": "Υπήρξε ένα σφάλμα κατά τη φόρτωση του αρχείου",
|
||||
"ThereWasAnErrorLoadingThisPage": "Υπήρξε ένα σφάλμα κατά τη φόρτωση της σελίδας",
|
||||
"Clone": "Κλωνοποίηση",
|
||||
"ApiKeyValidationHealthCheckMessage": "Παρακαλούμε ενημερώστε το κλείδι API ώστε να έχει τουλάχιστον {0} χαρακτήρες. Μπορείτε να το κάνετε αυτό μέσα από τις ρυθμίσεις ή το αρχείο ρυθμίσεων"
|
||||
"ApiKeyValidationHealthCheckMessage": "Παρακαλούμε ενημερώστε το κλείδι API ώστε να έχει τουλάχιστον {0} χαρακτήρες. Μπορείτε να το κάνετε αυτό μέσα από τις ρυθμίσεις ή το αρχείο ρυθμίσεων",
|
||||
"RemoveSelectedItemBlocklistMessageText": "Είστε σίγουροι πως θέλετε να διαγράψετε τα επιλεγμένα αντικείμενα από τη λίστα αποκλεισμού;",
|
||||
"RemoveSelectedItemQueueMessageText": "Είστε σίγουροι πως θέλετε να διαγράψετε 1 αντικείμενο από την ουρά;",
|
||||
"ResetQualityDefinitionsMessageText": "Είστε σίγουροι πως θέλετε να επαναφέρετε τους ορισμούς ποιότητας;",
|
||||
"CloneCondition": "Κλωνοποίηση συνθήκης",
|
||||
"DeleteCondition": "Διαγραφή συνθήκης",
|
||||
"RemoveSelectedItemsQueueMessageText": "Είστε σίγουροι πως θέλετε να διαγράψετε {0} αντικείμενα από την ουρά;"
|
||||
}
|
||||
|
||||
@@ -515,12 +515,15 @@
|
||||
"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",
|
||||
|
||||
@@ -652,5 +652,7 @@
|
||||
"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?"
|
||||
"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"
|
||||
}
|
||||
|
||||
@@ -19,15 +19,15 @@
|
||||
"AnalyticsEnabledHelpText": "Lähetä nimettömiä käyttö- ja virhetietoja sovelluksen palvelimille. Tämä sisältää tietoja selaimestasi, verkkokäyttöliittymän sivujen käytöstä, virheraportoinnista sekä käyttöjärjestelmästäsi ja versiosta. Käytämme näitä tietoja ominaisuuksien ja virhekorjauksien painotukseen.",
|
||||
"AppDataDirectory": "AppData-kansio",
|
||||
"ApplyTags": "Tunnistetoimenpide",
|
||||
"ApplyTagsHelpTexts1": "Miten tunnisteita sovelletaan valittuun kirjailijaan",
|
||||
"ApplyTagsHelpTexts2": "– 'Lisää' syötetyt tunnisteet aiempiin tunnisteisiin",
|
||||
"ApplyTagsHelpTexts3": "- \"Poista\" tyhjentää syötetyt tunnisteet.",
|
||||
"ApplyTagsHelpTexts4": "- \"Korvaa\" nykyiset tunnisteet syötetyillä tai tyhjennä kaikki tunnisteet jättämällä tyhjäksi.",
|
||||
"ApplyTagsHelpTexts1": "Tunnistetoimenpiteiden selitykset:",
|
||||
"ApplyTagsHelpTexts2": "– \"Lisää\" syötetyt tunnisteet aiempiin tunnisteisiin",
|
||||
"ApplyTagsHelpTexts3": "– \"Poista\" tyhjentää syötetyt tunnisteet",
|
||||
"ApplyTagsHelpTexts4": "– \"Korvaa\" nykyiset tunnisteet syötetyillä tai tyhjennä kaikki jättämällä tyhjäksi",
|
||||
"Authentication": "Todennus",
|
||||
"AuthenticationMethodHelpText": "Vaadi käyttäjätunnus ja salasana.",
|
||||
"AuthorClickToChangeBook": "Vaihda kirjaa painamalla",
|
||||
"AutoRedownloadFailedHelpText": "Etsi ja yritä ladata toinen julkaisu automaattisesti",
|
||||
"AutoUnmonitorPreviouslyDownloadedBooksHelpText": "Levyltä poistettuja kirjoja ei poisteta Radarrin seurannasta automaattisesti",
|
||||
"AutoUnmonitorPreviouslyDownloadedBooksHelpText": "Levyltä poistettavien kirjojen valvonta lopetetaan automaattisesti.",
|
||||
"Automatic": "Automaattinen",
|
||||
"BackupFolderHelpText": "Suhteelliset polut kohdistuvat sovelluksen AppData-kansioon.",
|
||||
"BackupNow": "Varmuuskopioi nyt",
|
||||
@@ -264,7 +264,7 @@
|
||||
"RSSSyncInterval": "RSS-synkronointiväli",
|
||||
"ReadTheWikiForMoreInformation": "Lue lisätietoja Wikistä",
|
||||
"ReadarrSupportsAnyIndexerThatUsesTheNewznabStandardAsWellAsOtherIndexersListedBelow": "Readarr tukee Newznab- ja Torznab-yhteensopivien tietolähteiden ohella myös monia muita alla lueteltuja tietolähteitä.",
|
||||
"ReadarrTags": "Radarr-tunnisteet",
|
||||
"ReadarrTags": "Tunnisteet",
|
||||
"Real": "Todellinen",
|
||||
"Reason": "Syy",
|
||||
"RecycleBinCleanupDaysHelpText": "Poista automaattinen tyhjennys käytöstä asettamalla arvoksi '0'.",
|
||||
@@ -476,13 +476,13 @@
|
||||
"SkipBooksWithMissingReleaseDate": "Ohita kirjat, joilta puuttuu julkaisupäivä",
|
||||
"UrlBaseHelpText": "Lisää Calibren URL-osoitteeseen etuliitteen, (esim. 'http://[host]:[port]/[urlBase]').",
|
||||
"Author": "Kirjailija",
|
||||
"BackupIntervalHelpText": "Readarrin tietokannan ja asetusten automaattisen varmuuskopioinnin suoritusaikaväli.",
|
||||
"BackupIntervalHelpText": "Tietokannan ja asetusten automaattisen varmuuskopioinnin ajoitus.",
|
||||
"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.",
|
||||
"DefaultReadarrTags": "Oletustunnisteet",
|
||||
"ExistingTagsScrubbed": "Olemassa olevat tunnisteet on poistettu",
|
||||
"WriteAudioTagsScrub": "Tyhjennä tagit",
|
||||
"WriteAudioTagsScrub": "Tyhjennä olemassa olevat tunnisteet",
|
||||
"WriteBookTagsHelpTextWarning": "'Kaikki tiedostot' -valinnat käsittelevät myös olemassa olevien tiedostojen tagit tuonnin yhteydessä.",
|
||||
"WriteAudioTags": "Tallenna metatiedot äänitiedostoihin",
|
||||
"WriteTagsNew": "Vain uudet lataukset",
|
||||
@@ -525,7 +525,7 @@
|
||||
"Label": "Tunniste",
|
||||
"LogRotateHelpText": "Lokien tallennuskansiossa säilytettävien lokitiedostojen enimmäismäärä",
|
||||
"LogRotation": "Lokitiedostojen kierrätys",
|
||||
"LogSqlHelpText": "Kirjaa kaikki Prowlarrin SQL-kyselyt",
|
||||
"LogSqlHelpText": "Kirjaa kaikki SQL-kyselyt",
|
||||
"Publisher": "Julkasija",
|
||||
"SelectAll": "Valitse kaikki",
|
||||
"SelectedCountBooksSelectedInterp": "{0} elokuva(a) valittu",
|
||||
@@ -568,7 +568,7 @@
|
||||
"IndexerPriorityHelpText": "Tietolähteen painotus: 1 (korkein) - 50 (matalin). Oletusarvo on 25. Käytetään muutoin tasaveroisten julkaisujen sieppauspäätökseen. Kaikkia käytössä olevia tietolähteitä käytetään edelleen RSS-synkronointiin ja hakuun.",
|
||||
"IndexerLongTermStatusCheckSingleClientMessage": "Tietolähteet eivät ole käytettävissä yli 6 tuntia kestäneiden virheiden vuoksi: {0}",
|
||||
"IndexerLongTermStatusCheckAllClientMessage": "Mikään tietolähde ei ole käytettävissä yli 6 tuntia kestäneiden virheiden vuoksi.",
|
||||
"IndexerSearchCheckNoInteractiveMessage": "Tietolähteitä ei ole määritetty vuorovaikutteiselle haulle, eikä sillä tämän vuoksi löydy tuloksia.",
|
||||
"IndexerSearchCheckNoInteractiveMessage": "Manuaalista hakua varten ei ole määritetty tietolähteitä, jonka vuoksi haku ei löydä tuloksia.",
|
||||
"IsCalibreLibraryHelpText": "Hallinnoi kirjastoa Calibren sisältöpalvelimen avulla.",
|
||||
"IsInUseCantDeleteAMetadataProfileThatIsAttachedToAnAuthorOrImportList": "Kirjailijaan tai tuontilistaan liitettyä metatietoprofiilia ei voi poistaa.",
|
||||
"IsInUseCantDeleteAQualityProfileThatIsAttachedToAnAuthorOrImportList": "Kirjailijaan tai tuontilistaan liitettyä laatuprofiilia ei voi poistaa.",
|
||||
@@ -626,23 +626,23 @@
|
||||
"ProxyCheckFailedToTestMessage": "Välityspalvelintesti epäonnistui: {0}",
|
||||
"Queued": "Jonossa",
|
||||
"SearchFiltered": "Etsi suodatettuja",
|
||||
"RemotePathMappingCheckFilesGenericPermissions": "Lataustyökalu '{0}' ilmoitti tiedostosijainniksi '{1}', mutta Radarr ei näe sitä. Saata joutua muokkaamaan kansion käyttöoikeuksia.",
|
||||
"RemotePathMappingCheckImportFailed": "Radarr ei voinut tuoda elokuvaa. Tarkista loki saadaksesi lisätietoja.",
|
||||
"RemotePathMappingCheckFilesGenericPermissions": "Lataustyökalu \"{0}\" ilmoitti tiedostosijainniksi \"{1}\", mutta kansiota ei nähdä. Saatat joutua muokkaamaan kansion käyttöoikeuksia.",
|
||||
"RemotePathMappingCheckImportFailed": "Kirjan tuonti epäonnistui. Katso tarkemmat tiedot lokista.",
|
||||
"CouldntFindAnyResultsForTerm": "Haku '{0}' ei tuottanut tuloksia.",
|
||||
"IndexerSearchCheckNoAutomaticMessage": "Automaattihaussa käytettäviä tietolähteitä ei ole käytettävissä, eikä automaattisia hakutuloksia ole tämän vuoksi saatavilla.",
|
||||
"IndexerSearchCheckNoAutomaticMessage": "Automaattista hakua varten ei ole määritetty tietolähteitä, jonka vuoksi haku ei löydä tuloksia.",
|
||||
"IndexerSearchCheckNoAvailableIndexersMessage": "Kaikki hakukelpoiset tietolähteet ovat tilapaisesti tavoittamattomissa viimeaikaisten tietolähdevirheiden vuoksi.",
|
||||
"RemotePathMappingCheckDockerFolderMissing": "Käytät Dockeria ja lataustyökalu '{0}' sijoittaa lataukset kohteeseen '{1}', mutta kansiota ei näytä olevan olemassa containerissa. Tarkista etäsijaintiesi kartoitukset ja containerin tallennusmedia-asetukset.",
|
||||
"RemotePathMappingCheckDownloadPermissions": "Radarr näkee, muttei voi käyttää ladattua elokuvaa '{0}'. Todennäköinen syy on sijainnin käyttöoikeusvirhe.",
|
||||
"RemotePathMappingCheckDownloadPermissions": "Ladattu kirja \"{0}\" näkyy, mutta sitä ei voida käyttää. Todennäköinen syy on sijainnin käyttöoikeusvirhe.",
|
||||
"RemotePathMappingCheckFilesBadDockerPath": "Käytät Dockeria ja lataustyökalu '{0}' ilmoitti latauskohteeksi '{1}', mutta se ei ole kelvollinen '{2}' -sijainti. Tarkista etäsijaintiesi kartoitukset ja lataustyökalun asetukset.",
|
||||
"RemotePathMappingCheckFolderPermissions": "Radarr näkee, muttei voi käyttää latauskansiota '{0}'. Todennäköinen syy on sijainnin käyttöoikeusvirhe.",
|
||||
"RemotePathMappingCheckFolderPermissions": "Ladatauskansio \"{1}\" näkyy, mutta sitä ei voida käyttää. Todennäköinen syy on sijainnin käyttöoikeusvirhe.",
|
||||
"RemotePathMappingCheckFilesLocalWrongOSPath": "Paikallinen lataustyökalu '{0}' ilmoitti tiedostosijainniksi '{1}', mutta se ei ole kelvollinen '{2}' -sijainti. Tarkista lataustyökalusi asetukset.",
|
||||
"RemotePathMappingCheckFilesWrongOSPath": "Etälataustyökalu '{0}' ilmoitti tiedostosijainniksi '{1}', mutta se ei ole kelvollinen '{2}' -sijainti. Tarkista etsijaintiesi kartoitukset lataustyökalusi asetukset.",
|
||||
"RemotePathMappingCheckGenericPermissions": "Lataustyökalu '{0}' sijoittaa lataukset kansioon '{1}', mutta Readarr ei näe sitä. Saatat joutua muokkaamaan kansion käyttöoikeuksia.",
|
||||
"RemotePathMappingCheckGenericPermissions": "Lataustyökalu \"{0}\" tallentaa lataukset sijaintiin \"{1}\", mutta kansiota ei nähdä. Saatat joutua muokkaamaan kansion käyttöoikeuksia.",
|
||||
"RemotePathMappingCheckLocalFolderMissing": "Etälataustyökalu '{0}' sijoittaa lataukset kohteeseen '{1}', mutta kansiota ei näytä olevan olemassa. Todennäköinen syy on puuttuva tai virheellinen etäsijainnin kartoitus.",
|
||||
"RemotePathMappingCheckLocalWrongOSPath": "Paikallinen lataustyökalu '{0}' sijoittaa lataukset kohteeseen '{1}', mutta se ei ole kelvollinen '{2}' -sijainti. Tarkista lataustyökalun asetukset.",
|
||||
"RemotePathMappingCheckRemoteDownloadClient": "Etälataustyökalu '{0}' ilmoitti tiedostosijainniksi '{1}', mutta kansiota ei näytä olevan olemassa. Todennäköinen syy on puuttuva tai virheellinen etäsijainnin kartoitus.",
|
||||
"RemotePathMappingCheckWrongOSPath": "Etälataustyökalu '{0}' sijoittaa lataukset kohteeseen '{1}', mutta se ei ole kelvollinen '{2}' -sijainti. Tarkista etäsijaintiesi kartoitukset ja lataustyökalun asetukset.",
|
||||
"RestartReloadNote": "Huomautus: Radarr käynnistää ja lataa käyttöliittymän automaattisesti palautusprosessin aikana.",
|
||||
"RestartReloadNote": "Huomioi: Sovellus käynnistyy palautusprosessin aikana automaattisesti uudelleen.",
|
||||
"DownloadClientStatusCheckAllClientMessage": "Yhtään lataustyökalua ei ole virheiden vuoksi käytettävissä",
|
||||
"DownloadClientsSettingsSummary": "Lataustyökalut, latausten käsittely ja etäsijaintien kartoitukset.",
|
||||
"Connect": "Kytkennät",
|
||||
@@ -655,9 +655,9 @@
|
||||
"FileWasDeletedByUpgrade": "Tiedosto poistettiin päivityksen tuontia varten.",
|
||||
"HealthNoIssues": "Kokoonpanossasi ei ole ongelmia.",
|
||||
"IndexerRssHealthCheckNoAvailableIndexers": "Kaikki RSS-tietolähteet ovat tilapaisesti tavoittamattomissa viimeaikaisten tietolähdevirheiden vuoksi.",
|
||||
"IndexerRssHealthCheckNoIndexers": "Yhtään RSS-synkronointia käyttävää tietolähdettä ei ole käytettävissä, eikä uusia julkaisuja sen vuoksi siepata automaattisesti.",
|
||||
"IndexerRssHealthCheckNoIndexers": "RSS-synkronointia käyttäviä tietolähteitä määritetty, jonka vuoksi uusia julkaisuja ei siepata automaattisesti.",
|
||||
"IndexerStatusCheckSingleClientMessage": "Tietolähteet eivät ole käytettävissä virheiden vuoksi: {0}",
|
||||
"MissingFromDisk": "Radarr ei löytänyt tiedostoa levyltä, joten sen kytkös kirjaston elokuvaan poistettiin",
|
||||
"MissingFromDisk": "Koska tiedostoa ei löytynyt levyltä, sen kytkös kirjastossa olevaan kirjaan poistettiin.",
|
||||
"Monitor": "Valvo",
|
||||
"MountCheckMessage": "Elokuvareitin sisältävä kiinnike on asennettu vain luku -tilaan: ",
|
||||
"OnBookFileDelete": "Kun elokuvatiedosto poistetaan",
|
||||
@@ -670,12 +670,12 @@
|
||||
"ProxyCheckResolveIpMessage": "Määritetyn välityspalvelimen '{0}' IP-osoitteen selvitys epäonnistui.",
|
||||
"QualitySettingsSummary": "Laatumääritykset erilaisia sisältömuotoja ja tiedostokokoja varten.",
|
||||
"QueueIsEmpty": "Jono on tyhjä",
|
||||
"ReadarrSupportsAnyDownloadClient": "Radarr tukee kaikkien Newznab-yhteensopivien lataustyökalujen ohella myös monia muita alla listattuja torrent- ja Usenet-lataustyökaluja.",
|
||||
"ReadarrSupportsAnyDownloadClient": "Monet torrent- ja Usenet-lataustyökalut ovat tuettuja.",
|
||||
"RefreshAndScan": "Päivitä ja tarkista",
|
||||
"RemotePathMappingCheckBadDockerPath": "Käytät Dockeria ja lataustyökalu '{0}' sijoittaa lataukset kohteeseen '{1}', mutta se ei ole kelvollinen '{2}' -sijainti. Tarkista etäsijaintiesi kartoitukset ja lataustyökalun asetukset.",
|
||||
"RootFolderCheckMultipleMessage": "Useita juurikansioita puuttuu: {0}",
|
||||
"SettingsRemotePathMappingLocalPath": "Paikallinen sijainti",
|
||||
"SettingsRemotePathMappingLocalPathHelpText": "Polku, jota Radarrin tulisi käyttää päästäksesi etäpolulle paikallisesti",
|
||||
"SettingsRemotePathMappingLocalPathHelpText": "Polku, jonka kautta etäsijaintia tulee käyttää paikallisesti.",
|
||||
"SettingsRemotePathMappingRemotePath": "Etäsijainti",
|
||||
"SettingsRemotePathMappingRemotePathHelpText": "Lataustyökalun käyttämän hakemiston juurisijainti",
|
||||
"SizeLimit": "Kokorajoitus",
|
||||
@@ -830,5 +830,8 @@
|
||||
"RemoveSelectedItemsQueueMessageText": "Haluatko varmasti poistaa jonosta {0} kohdetta?",
|
||||
"Required": "Vaaditaan",
|
||||
"ResetQualityDefinitions": "Palauta laatumääritykset",
|
||||
"ResetQualityDefinitionsMessageText": "Haluatko varmasti palauttaa laatumääritykset?"
|
||||
"ResetQualityDefinitionsMessageText": "Haluatko varmasti palauttaa laatumääritykset?",
|
||||
"NoEventsFound": "Tapahtumia ei löytynyt",
|
||||
"BlocklistReleaseHelpText": "Estää julkaisun automaattisen uudelleensieppauksen.",
|
||||
"RecycleBinUnableToWriteHealthCheck": "Määritettyyn roskakorikansioon ei voi tallentaa: {0}. Varmista, että sijainti on olemassa ja että käyttäjällä on kirjoitusoikeus kansioon."
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
"SslPortHelpTextWarning": "Nécessite un redémarrage pour prendre effet",
|
||||
"SslCertPathHelpTextWarning": "Nécessite un redémarrage pour prendre effet",
|
||||
"UnableToLoadMetadataProfiles": "Impossible de charger les profils de délai",
|
||||
"AddingTag": "Ajouter un tag",
|
||||
"AddingTag": "Ajout d'un tag",
|
||||
"AgeWhenGrabbed": "Age (au moment du téléchargement)",
|
||||
"AlreadyInYourLibrary": "Déjà présent dans votre collection",
|
||||
"AlternateTitles": "Titre alternatif",
|
||||
@@ -31,7 +31,7 @@
|
||||
"AnalyticsEnabledHelpText": "Envoyer des informations anonymes sur l'utilisation et les erreurs vers les serveurs de Readarr. Cela inclut des informations sur votre navigateur, quelle page de l'interface web Readarr vous utilisez, les rapports d'erreur ainsi que le SE et sa version. Nous utiliserons ces informations pour prioriser les nouvelles fonctionnalités et les corrections de bugs.",
|
||||
"AnalyticsEnabledHelpTextWarning": "Nécessite un redémarrage pour prendre effet",
|
||||
"AppDataDirectory": "Dossier AppData",
|
||||
"ApplyTags": "Appliquer les Étiquettes",
|
||||
"ApplyTags": "Appliquer les tags",
|
||||
"ApplyTagsHelpTexts1": "Comment appliquer des tags à l'auteur sélectionné",
|
||||
"ApplyTagsHelpTexts2": "Ajouter : Ajouter les étiquettes à la liste des étiquettes existantes",
|
||||
"ApplyTagsHelpTexts3": "Retirer : Retire les étiquettes renseignées",
|
||||
|
||||
@@ -611,5 +611,8 @@
|
||||
"Required": "נדרש",
|
||||
"RemoveSelectedItemBlocklistMessageText": "האם אתה בטוח שברצונך להסיר את הפריטים שנבחרו מהרשימה השחורה?",
|
||||
"RemoveSelectedItemQueueMessageText": "האם אתה בטוח שברצונך להסיר את {0} פריט {1} מהתור?",
|
||||
"RemoveSelectedItemsQueueMessageText": "האם אתה בטוח שברצונך להסיר את {0} פריט {1} מהתור?"
|
||||
"RemoveSelectedItemsQueueMessageText": "האם אתה בטוח שברצונך להסיר את {0} פריט {1} מהתור?",
|
||||
"BlocklistReleaseHelpText": "מנע מראדרר להוסיף את ההוצאה הזאת שוב",
|
||||
"NoEventsFound": "לא נמצאו אירועים",
|
||||
"ApiKeyValidationHealthCheckMessage": "עדכן בבקשה את מפתח ה API שלך שיהיה עם לפחות {0} תווים. ניתן לעשות זאת דרך ההגדות או קובץ הקונפיגורציה"
|
||||
}
|
||||
|
||||
@@ -589,5 +589,6 @@
|
||||
"DeleteConditionMessageText": "क्या आप वाकई '{0}' सूची को हटाना चाहते हैं?",
|
||||
"RemoveSelectedItemBlocklistMessageText": "क्या आप वाकई चयनित आइटम को ब्लैकलिस्ट से हटाना चाहते हैं?",
|
||||
"RemoveSelectedItemQueueMessageText": "क्या आप वाकई {0} आइटम {1} को कतार से हटाना चाहते हैं?",
|
||||
"RemoveSelectedItemsQueueMessageText": "क्या आप वाकई {0} आइटम {1} को कतार से हटाना चाहते हैं?"
|
||||
"RemoveSelectedItemsQueueMessageText": "क्या आप वाकई {0} आइटम {1} को कतार से हटाना चाहते हैं?",
|
||||
"NoEventsFound": "कोई घटना नहीं मिली"
|
||||
}
|
||||
|
||||
@@ -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,7 +271,7 @@
|
||||
"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",
|
||||
@@ -778,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}",
|
||||
@@ -877,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",
|
||||
@@ -902,12 +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",
|
||||
"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"
|
||||
"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"
|
||||
}
|
||||
|
||||
@@ -590,5 +590,6 @@
|
||||
"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"
|
||||
"Required": "Nauðsynlegt",
|
||||
"NoEventsFound": "Engir viðburðir fundust"
|
||||
}
|
||||
|
||||
@@ -29,11 +29,11 @@
|
||||
"Analytics": "Análises",
|
||||
"AnalyticsEnabledHelpText": "Envie informações anônimas de uso e erro para os servidores do Readarr. Isso inclui informações sobre seu navegador, quais páginas da interface Web do Readarr você usa, relatórios de erros, e a versão do sistema operacional e do tempo de execução. Usaremos essas informações para priorizar recursos e correções de bugs.",
|
||||
"AppDataDirectory": "Diretório AppData",
|
||||
"ApplyTags": "Aplicar tags",
|
||||
"ApplyTags": "Aplicar Tags",
|
||||
"ApplyTagsHelpTexts1": "Como aplicar tags ao autor selecionado",
|
||||
"ApplyTagsHelpTexts2": "Adicionar: adiciona as etiquetas à lista existente de etiquetas",
|
||||
"ApplyTagsHelpTexts3": "Remover: excluir as tags inseridas",
|
||||
"ApplyTagsHelpTexts4": "Substituir: sobrepor as tags existentes pelas inseridas (deixe em branco para limpar todas as tags)",
|
||||
"ApplyTagsHelpTexts2": "Adicionar: adicione as tags à lista existente de tags",
|
||||
"ApplyTagsHelpTexts3": "Remover: remove as tags inseridas",
|
||||
"ApplyTagsHelpTexts4": "Substituir: Substitua as tags pelas tags inseridas (não digite nenhuma tag para limpar todas as tags)",
|
||||
"Authentication": "Autenticação",
|
||||
"AuthenticationMethodHelpText": "Exigir nome de usuário e senha para acessar o Readarr",
|
||||
"AuthorClickToChangeBook": "Clique para alterar o livro",
|
||||
@@ -692,7 +692,7 @@
|
||||
"Monitoring": "Monitorando",
|
||||
"SeriesTotal": "Séries ({0})",
|
||||
"TooManyBooks": "Livros ausentes ou muitos? Modifique ou crie um novo",
|
||||
"BlocklistRelease": "Lista de Bloqueio de Lançamentos",
|
||||
"BlocklistRelease": "Lançamento na lista de bloqueio",
|
||||
"NoHistoryBlocklist": "Nenhum histórico na lista de bloqueio",
|
||||
"Blocklist": "Lista de bloqueio",
|
||||
"RemoveFromBlocklist": "Remover da lista de bloqueio",
|
||||
@@ -762,7 +762,7 @@
|
||||
"UpdateAvailable": "Nova atualização está disponível",
|
||||
"UserAgentProvidedByTheAppThatCalledTheAPI": "User-Agent fornecido pelo aplicativo que chamou a API",
|
||||
"UpdateCheckUINotWritableMessage": "Não é possível instalar a atualização porque a pasta de IU '{0}' não pode ser gravada pelo usuário '{1}'.",
|
||||
"FailedToLoadQueue": "Falha ao carregar fila",
|
||||
"FailedToLoadQueue": "Falha ao carregar a fila",
|
||||
"DownloadClientStatusCheckSingleClientMessage": "Clientes de download indisponíveis devido a falhas: {0}",
|
||||
"EditBook": "Editar Livro",
|
||||
"FileWasDeletedByUpgrade": "Arquivo foi excluído para importar uma atualização",
|
||||
@@ -890,14 +890,14 @@
|
||||
"MinFormatScoreHelpText": "Pontuação mínima de formato personalizado permitida para download",
|
||||
"RecycleBinUnableToWriteHealthCheck": "Não é possível gravar na pasta da lixeira configurada: {0}. Certifique-se de que este caminho exista e seja gravável pelo usuário executando o Readarr",
|
||||
"Clone": "Clonar",
|
||||
"CloneCustomFormat": "Clonar Formato Personalizado",
|
||||
"CloneCustomFormat": "Clonar formato personalizado",
|
||||
"Conditions": "'Condições'",
|
||||
"CopyToClipboard": "Copiar para área de transferência",
|
||||
"CustomFormat": "Formato Personalizado",
|
||||
"CustomFormatSettings": "Configurações do Formato Personalizado",
|
||||
"CustomFormats": "Formatos Personalizados",
|
||||
"CutoffFormatScoreHelpText": "Depois que essa pontuação de formato personalizado for alcançada, Readarr não obterá mais lançamentos de livros",
|
||||
"DeleteCustomFormat": "Excluir Formato Personalizado",
|
||||
"DeleteCustomFormat": "Excluir formato personalizado",
|
||||
"ExportCustomFormat": "Exportar Formato Personalizado",
|
||||
"Formats": "Formatos",
|
||||
"Loading": "carregando",
|
||||
@@ -926,11 +926,11 @@
|
||||
"SmartReplace": "Substituição Inteligente",
|
||||
"ReplaceWithSpaceDashSpace": "Substituir com Espaço e Traço e Espaço",
|
||||
"DeleteRemotePathMapping": "Excluir Mapeamento de Caminho Remoto",
|
||||
"BlocklistReleases": "Lista de Bloqueio de Lançamentos",
|
||||
"CloneCondition": "Condição de Clone",
|
||||
"BlocklistReleases": "Lançamentos na lista de bloqueio",
|
||||
"CloneCondition": "Condição de clone",
|
||||
"DeleteConditionMessageText": "Tem certeza de que deseja excluir a condição '{0}'?",
|
||||
"DeleteRemotePathMappingMessageText": "Tem certeza de que deseja excluir este mapeamento de caminho remoto?",
|
||||
"DeleteCondition": "Excluir Condição",
|
||||
"DeleteCondition": "Excluir condição",
|
||||
"Negated": "Negado",
|
||||
"RemoveSelectedItem": "Remover Item Selecionado",
|
||||
"RemoveSelectedItemBlocklistMessageText": "Tem certeza de que deseja remover os itens selecionados da lista de bloqueio?",
|
||||
@@ -940,5 +940,8 @@
|
||||
"Required": "Requerido",
|
||||
"ResetQualityDefinitions": "Redefinir Configurações de Qualidade",
|
||||
"ResetQualityDefinitionsMessageText": "Tem certeza de que deseja redefinir as configurações de qualidade?",
|
||||
"BlocklistReleaseHelpText": "Evita que o Readarr pegue automaticamente esses arquivos novamente"
|
||||
"BlocklistReleaseHelpText": "Evita que o Readarr pegue automaticamente esses arquivos novamente",
|
||||
"NoCutoffUnmetItems": "Nenhum item de corte não atendido",
|
||||
"NoEventsFound": "Nenhum evento encontrado",
|
||||
"NoMissingItems": "Nenhum item faltando"
|
||||
}
|
||||
|
||||
@@ -581,5 +581,13 @@
|
||||
"ColonReplacement": "การเปลี่ยนลำไส้ใหญ่",
|
||||
"ReplaceWithDash": "แทนที่ด้วย Dash",
|
||||
"ReplaceWithSpaceDash": "แทนที่ด้วย Space Dash",
|
||||
"ReplaceWithSpaceDashSpace": "แทนที่ด้วย Space Dash Space"
|
||||
"ReplaceWithSpaceDashSpace": "แทนที่ด้วย Space Dash Space",
|
||||
"NoEventsFound": "ไม่พบกิจกรรม",
|
||||
"BlocklistReleases": "Blacklist Release",
|
||||
"DeleteConditionMessageText": "แน่ใจไหมว่าต้องการลบรายการ \"{0}\"",
|
||||
"DeleteRemotePathMapping": "แก้ไขการแมปเส้นทางระยะไกล",
|
||||
"Negated": "เมื่อตะกี้",
|
||||
"RemoveSelectedItemQueueMessageText": "แน่ใจไหมว่าต้องการนำ {0} ออกจากคิว",
|
||||
"RemoveSelectedItemsQueueMessageText": "แน่ใจไหมว่าต้องการนำ {0} ออกจากคิว",
|
||||
"Required": "จำเป็น"
|
||||
}
|
||||
|
||||
@@ -46,9 +46,9 @@
|
||||
"BackupFolderHelpText": "Các đường dẫn tương đối sẽ nằm trong thư mục AppData của Radarr",
|
||||
"BackupNow": "Sao lưu ngay",
|
||||
"BackupRetentionHelpText": "Các bản sao lưu tự động cũ hơn khoảng thời gian lưu giữ sẽ tự động được dọn dẹp",
|
||||
"Backups": "Sao lưu",
|
||||
"Backups": "Những bản sao lưu",
|
||||
"BindAddress": "Địa chỉ ràng buộc",
|
||||
"BindAddressHelpText": "Địa chỉ IP4 hợp lệ hoặc '*' cho tất cả các giao diện",
|
||||
"BindAddressHelpText": "Địa chỉ IP hợp lệ, localhost hoặc '*' cho tất cả các giao diện",
|
||||
"BindAddressHelpTextWarning": "Yêu cầu khởi động lại để có hiệu lực",
|
||||
"BookIsDownloading": "Đang tải phim",
|
||||
"BookIsDownloadingInterp": "Đang tải phim xuống - {0}% {1}",
|
||||
@@ -59,7 +59,7 @@
|
||||
"Cancel": "Huỷ bỏ",
|
||||
"CancelMessageText": "Bạn có chắc chắn muốn hủy nhiệm vụ đang chờ xử lý này không?",
|
||||
"CertificateValidation": "Xác thực chứng chỉ",
|
||||
"CertificateValidationHelpText": "Thay đổi cách xác thực chứng chỉ HTTPS nghiêm ngặt",
|
||||
"CertificateValidationHelpText": "Thay đổi cách xác thực chứng chỉ HTTPS nghiêm ngặt. Không được đổi nếu bạn biết rõ về",
|
||||
"ChangeFileDate": "Thay đổi ngày tệp",
|
||||
"ChangeHasNotBeenSavedYet": "Thay đổi vẫn chưa được lưu",
|
||||
"ChmodFolder": "Thư mục chmod",
|
||||
@@ -471,11 +471,11 @@
|
||||
"Level": "Cấp độ",
|
||||
"SelectedCountBooksSelectedInterp": "{0} Phim đã chọn",
|
||||
"ThisCannotBeCancelled": "Điều này không thể bị hủy sau khi bắt đầu mà không khởi động lại Radarr.",
|
||||
"Blocklist": "Danh sách đen",
|
||||
"BlocklistRelease": "Phát hành danh sách đen",
|
||||
"Blocklist": "Danh sách chặn",
|
||||
"BlocklistRelease": "Chặn bản phát hành",
|
||||
"IndexerLongTermStatusCheckAllClientMessage": "Tất cả các trình lập chỉ mục không khả dụng do lỗi trong hơn 6 giờ",
|
||||
"Disabled": "Tàn tật",
|
||||
"AppDataLocationHealthCheckMessage": "Việc cập nhật sẽ không thể ngăn việc xóa AppData khi cập nhật",
|
||||
"AppDataLocationHealthCheckMessage": "Việc cập nhật sẽ không xảy ra để tránh xóa AppData khi cập nhật",
|
||||
"ConnectSettingsSummary": "Thông báo, kết nối với máy chủ / trình phát đa phương tiện và tập lệnh tùy chỉnh",
|
||||
"CouldntFindAnyResultsForTerm": "Không thể tìm thấy bất kỳ kết quả nào cho '{0}'",
|
||||
"DownloadClientStatusCheckSingleClientMessage": "Ứng dụng khách tải xuống không khả dụng do lỗi: {0}",
|
||||
@@ -581,5 +581,8 @@
|
||||
"ColonReplacement": "Thay thế ruột kết",
|
||||
"ReplaceWithDash": "Thay thế bằng Dấu gạch ngang",
|
||||
"ReplaceWithSpaceDash": "Thay thế bằng Dấu gạch ngang",
|
||||
"ReplaceWithSpaceDashSpace": "Thay thế bằng Space Dash Space"
|
||||
"ReplaceWithSpaceDashSpace": "Thay thế bằng Space Dash Space",
|
||||
"BlocklistReleases": "Phát hành danh sách đen",
|
||||
"ApplicationURL": "URL của ứng dụng",
|
||||
"ApiKeyValidationHealthCheckMessage": "Hãy cập nhật mã API để dài ít nhất {0} kí tự. Bạn có thể làm điều này trong cài đặt hoặc trong tập config"
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
"ApplyTags": "应用标签",
|
||||
"ApplyTagsHelpTexts1": "如何给选中的电影添加标签",
|
||||
"ApplyTagsHelpTexts2": "添加:将标签添加到现有标签列表",
|
||||
"ApplyTagsHelpTexts3": "删除:移除输入的标签",
|
||||
"ApplyTagsHelpTexts3": "删除:删除输入的标签",
|
||||
"ApplyTagsHelpTexts4": "替换:用输入的标签替换标签(不输入标签将清除所有标签)",
|
||||
"Authentication": "认证",
|
||||
"AuthenticationMethodHelpText": "您需要用户名和密码来访问Radarr",
|
||||
@@ -70,13 +70,13 @@
|
||||
"DeleteBackup": "删除备份",
|
||||
"DeleteBackupMessageText": "您确定要删除备份 '{0}' 吗?",
|
||||
"DeleteDelayProfile": "删除延迟配置",
|
||||
"DeleteDelayProfileMessageText": "您确定要删除这个延迟配置?",
|
||||
"DeleteDelayProfileMessageText": "是否确实要删除此延迟配置文件?",
|
||||
"DeleteDownloadClient": "删除下载客户端",
|
||||
"DeleteDownloadClientMessageText": "您确定要删除下载客户端 '{0}' 吗?",
|
||||
"DeleteEmptyFolders": "删除空目录",
|
||||
"DeleteEmptyFoldersHelpText": "磁盘扫描过程中删除被移除的电影空目录",
|
||||
"DeleteImportListExclusion": "删除导入排除列表",
|
||||
"DeleteImportListExclusionMessageText": "确定删除导入排除列表?",
|
||||
"DeleteImportListExclusionMessageText": "你确定要删除这个导入排除列表吗?",
|
||||
"DeleteImportListMessageText": "您确定要删除列表 '{0}'?",
|
||||
"DeleteIndexer": "删除索引",
|
||||
"DeleteIndexerMessageText": "您确定要删除索引 '{0}'吗?",
|
||||
@@ -290,7 +290,7 @@
|
||||
"RescanAuthorFolderAfterRefresh": "刷新后重新扫描作者文件夹",
|
||||
"Reset": "重置",
|
||||
"ResetAPIKey": "重置API Key",
|
||||
"ResetAPIKeyMessageText": "您确定要重置您的API密钥吗?",
|
||||
"ResetAPIKeyMessageText": "您确定要重置您的 API 密钥吗?",
|
||||
"Restart": "重启",
|
||||
"RestartNow": "马上重启",
|
||||
"RestartReadarr": "重启Radarr",
|
||||
@@ -796,7 +796,7 @@
|
||||
"MinPopularityHelpText": "人气是平均评分*票",
|
||||
"MonitorBookExistingOnlyWarning": "这是对每本书籍的监控设置的一次性调整 使用作者/编辑下的选项来控制新添加的书籍将如何",
|
||||
"NameFirstLast": "姓名",
|
||||
"NoHistoryBlocklist": "没有历史黑名单列表",
|
||||
"NoHistoryBlocklist": "没有历史黑名单",
|
||||
"OnAuthorDelete": "在作者删除时",
|
||||
"OnBookRetagHelpText": "在书籍重加标签时",
|
||||
"OnImportFailure": "在导入失败时",
|
||||
@@ -884,8 +884,8 @@
|
||||
"CustomFormats": "自定义命名格式",
|
||||
"CutoffFormatScoreHelpText": "一旦自定义格式分数满足则Radarr不会再下载影片",
|
||||
"DeleteCustomFormat": "删除自定义命名格式",
|
||||
"DeleteCustomFormatMessageText": "您确定要删除索引 '{0}'吗?",
|
||||
"DeleteFormatMessageText": "您确定要删除格式标签 {0}?",
|
||||
"DeleteCustomFormatMessageText": "是否确实要删除条件“{0}”?",
|
||||
"DeleteFormatMessageText": "你确定要删除格式标签 “{0}” 吗?",
|
||||
"Formats": "格式",
|
||||
"ImportListMissingRoot": "在导入列表中缺少根目录文件夹",
|
||||
"ImportListMultipleMissingRoots": "导入列表中缺失多个根目录文件夹",
|
||||
@@ -906,5 +906,19 @@
|
||||
"CustomFormatScore": "自定义格式分数",
|
||||
"DataFutureBooks": "监控尚未发布的书籍",
|
||||
"ExportCustomFormat": "已有自定义格式",
|
||||
"ResetDefinitionTitlesHelpText": "重置定义标题与参数值"
|
||||
"ResetDefinitionTitlesHelpText": "重置定义标题和值",
|
||||
"DeleteRemotePathMappingMessageText": "是否确实要删除此远程路径映射?",
|
||||
"ListRefreshInterval": "列表刷新间隔",
|
||||
"CloneCondition": "克隆条件",
|
||||
"DeleteCondition": "删除条件",
|
||||
"ApiKeyValidationHealthCheckMessage": "请将API密钥更新为至少{0}个字符长。您可以通过设置或配置文件执行此操作",
|
||||
"HiddenClickToShow": "隐藏,点击显示",
|
||||
"HideAdvanced": "隐藏高级",
|
||||
"ListWillRefreshEveryInterp": "列表将每 {0} 刷新一次",
|
||||
"ShowAdvanced": "显示高级",
|
||||
"ShownClickToHide": "显示,点击隐藏",
|
||||
"RemoveSelectedItemQueueMessageText": "您确定要从队列中删除 1 项吗?",
|
||||
"RemoveSelectedItemBlocklistMessageText": "您确定要从阻止列表中删除所选项目吗?",
|
||||
"RemoveSelectedItemsQueueMessageText": "您确定要从队列中删除 {0} 个项目吗?",
|
||||
"ResetQualityDefinitionsMessageText": "您确定要重置质量定义吗?"
|
||||
}
|
||||
|
||||
@@ -5,5 +5,31 @@
|
||||
"AddingTag": "新增標籤",
|
||||
"Analytics": "分析",
|
||||
"AddList": "新增列表",
|
||||
"ExportCustomFormat": "新增自定義格式"
|
||||
"ExportCustomFormat": "新增自定義格式",
|
||||
"Blocklist": "封鎖清單",
|
||||
"Branch": "分支",
|
||||
"AppDataLocationHealthCheckMessage": "為了避免在更新過程中刪除AppData,將無法進行更新。",
|
||||
"AppDataDirectory": "AppData 路徑",
|
||||
"ApiKeyValidationHealthCheckMessage": "請將您的API金鑰更新為至少{0}個字元長。您可以通過設定或配置文件進行此操作。",
|
||||
"ApplyTags": "套用標籤",
|
||||
"Authentication": "認證",
|
||||
"AutoRedownloadFailedHelpText": "自動搜尋並嘗試下載不同的版本",
|
||||
"Automatic": "自動",
|
||||
"BackupRetentionHelpText": "超過保留期的自動備份將被自動清理",
|
||||
"Backups": "備份",
|
||||
"BindAddress": "綁定地址(Bind Address)",
|
||||
"BindAddressHelpText": "有效的IP地址,本地主機(localhost)或者「*」以表示所有介面。",
|
||||
"Quality": "品質",
|
||||
"QualityDefinitions": "品質定義",
|
||||
"BlocklistReleases": "封鎖清單版本",
|
||||
"ClickToChangeQuality": "點擊以更改品質",
|
||||
"ApplicationUrlHelpText": "這個應用程式的外部網址,包括http(s)://、端口和URL Base。",
|
||||
"ApplicationURL": "應用程式 URL",
|
||||
"AlreadyInYourLibrary": "已經在您的資源庫中",
|
||||
"DeleteQualityProfile": "刪除品質設定檔",
|
||||
"ApplyTagsHelpTexts3": "移除:刪除輸入的標籤",
|
||||
"ApplyTagsHelpTexts4": "取代:用輸入的標籤替換現有的標籤(如果不輸入任何標籤,則清除所有標籤)",
|
||||
"AddListExclusion": "新增排除清單",
|
||||
"BackupNow": "馬上備份",
|
||||
"BlocklistRelease": "封鎖清單版本"
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using NzbDrone.Core.Datastore;
|
||||
|
||||
namespace NzbDrone.Core.Profiles.Metadata
|
||||
@@ -12,6 +13,11 @@ namespace NzbDrone.Core.Profiles.Metadata
|
||||
public bool SkipSeriesSecondary { get; set; }
|
||||
public string AllowedLanguages { get; set; }
|
||||
public int MinPages { get; set; }
|
||||
public string Ignored { get; set; }
|
||||
public List<string> Ignored { get; set; }
|
||||
|
||||
public MetadataProfile()
|
||||
{
|
||||
Ignored = new List<string>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,7 +158,7 @@ namespace NzbDrone.Core.Profiles.Metadata
|
||||
FilterByPredicate(hash, x => x.ForeignBookId, localHash, profile, (x, p) => !p.SkipMissingDate || x.ReleaseDate.HasValue, "release date is missing");
|
||||
FilterByPredicate(hash, x => x.ForeignBookId, localHash, profile, (x, p) => !p.SkipPartsAndSets || !IsPartOrSet(x, seriesLinks.GetValueOrDefault(x), titles), "book is part of set");
|
||||
FilterByPredicate(hash, x => x.ForeignBookId, localHash, profile, (x, p) => !p.SkipSeriesSecondary || !seriesLinks.ContainsKey(x) || seriesLinks[x].Any(y => y.IsPrimary), "book is a secondary series item");
|
||||
FilterByPredicate(hash, x => x.ForeignBookId, localHash, profile, (x, p) => !MatchesTerms(x.Title, p.Ignored), "contains ignored terms");
|
||||
FilterByPredicate(hash, x => x.ForeignBookId, localHash, profile, (x, p) => !p.Ignored.Any(i => MatchesTerms(x.Title, i)), "contains ignored terms");
|
||||
|
||||
foreach (var book in hash)
|
||||
{
|
||||
@@ -184,7 +184,7 @@ namespace NzbDrone.Core.Profiles.Metadata
|
||||
|
||||
FilterByPredicate(hash, x => x.ForeignEditionId, localHash, profile, (x, p) => !allowedLanguages.Any() || allowedLanguages.Contains(x.Language?.CanonicalizeLanguage()), "edition language not allowed");
|
||||
FilterByPredicate(hash, x => x.ForeignEditionId, localHash, profile, (x, p) => !p.SkipMissingIsbn || x.Isbn13.IsNotNullOrWhiteSpace() || x.Asin.IsNotNullOrWhiteSpace(), "isbn and asin is missing");
|
||||
FilterByPredicate(hash, x => x.ForeignEditionId, localHash, profile, (x, p) => !MatchesTerms(x.Title, p.Ignored), "contains ignored terms");
|
||||
FilterByPredicate(hash, x => x.ForeignEditionId, localHash, profile, (x, p) => !p.Ignored.Any(i => MatchesTerms(x.Title, i)), "contains ignored terms");
|
||||
|
||||
return hash.ToList();
|
||||
}
|
||||
|
||||
@@ -21,7 +21,9 @@ namespace NzbDrone.Core.Validation.Paths
|
||||
return true;
|
||||
}
|
||||
|
||||
return !_authorService.GetAllAuthors().Exists(s => s.Metadata.Value.ForeignAuthorId == context.PropertyValue.ToString());
|
||||
var foreignAuthorId = context.PropertyValue.ToString();
|
||||
|
||||
return _authorService.FindById(foreignAuthorId) == null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,12 @@ namespace Readarr.Api.V1.Health
|
||||
_healthCheckService = healthCheckService;
|
||||
}
|
||||
|
||||
[NonAction]
|
||||
public override ActionResult<HealthResource> GetResourceByIdWithErrorHandler(int id)
|
||||
{
|
||||
return base.GetResourceByIdWithErrorHandler(id);
|
||||
}
|
||||
|
||||
protected override HealthResource GetResourceById(int id)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using NzbDrone.Core.DecisionEngine;
|
||||
using Readarr.Http.REST;
|
||||
|
||||
@@ -7,6 +8,12 @@ namespace Readarr.Api.V1.Indexers
|
||||
{
|
||||
public abstract class ReleaseControllerBase : RestController<ReleaseResource>
|
||||
{
|
||||
[NonAction]
|
||||
public override ActionResult<ReleaseResource> GetResourceByIdWithErrorHandler(int id)
|
||||
{
|
||||
return base.GetResourceByIdWithErrorHandler(id);
|
||||
}
|
||||
|
||||
protected override ReleaseResource GetResourceById(int id)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
|
||||
@@ -18,7 +18,12 @@ namespace Readarr.Api.V1.Profiles.Metadata
|
||||
public MetadataProfileController(IMetadataProfileService profileService)
|
||||
{
|
||||
_profileService = profileService;
|
||||
SharedValidator.RuleFor(c => c.Name).NotEqual("None").WithMessage("'None' is a reserved profile name").NotEmpty();
|
||||
|
||||
SharedValidator.RuleFor(c => c.Name)
|
||||
.NotEqual("None").WithMessage("'None' is a reserved profile name")
|
||||
.NotEmpty();
|
||||
SharedValidator.RuleFor(c => c.MinPopularity).GreaterThanOrEqualTo(0);
|
||||
SharedValidator.RuleFor(c => c.MinPages).GreaterThanOrEqualTo(0);
|
||||
SharedValidator.RuleFor(c => c.AllowedLanguages)
|
||||
.Must(x => x
|
||||
.Trim(',')
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace Readarr.Api.V1.Profiles.Metadata
|
||||
public bool SkipSeriesSecondary { get; set; }
|
||||
public string AllowedLanguages { get; set; }
|
||||
public int MinPages { get; set; }
|
||||
public string Ignored { get; set; }
|
||||
public List<string> Ignored { get; set; }
|
||||
}
|
||||
|
||||
public static class MetadataProfileResourceMapper
|
||||
|
||||
@@ -41,6 +41,7 @@ namespace Readarr.Api.V1
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[Produces("application/json")]
|
||||
public List<TProviderResource> GetAll()
|
||||
{
|
||||
var providerDefinitions = _providerFactory.All().OrderBy(p => p.ImplementationName);
|
||||
@@ -58,6 +59,8 @@ namespace Readarr.Api.V1
|
||||
}
|
||||
|
||||
[RestPostById]
|
||||
[Consumes("application/json")]
|
||||
[Produces("application/json")]
|
||||
public ActionResult<TProviderResource> CreateProvider([FromBody] TProviderResource providerResource, [FromQuery] bool forceSave = false)
|
||||
{
|
||||
var providerDefinition = GetDefinition(providerResource, true, !forceSave, false);
|
||||
@@ -73,6 +76,8 @@ namespace Readarr.Api.V1
|
||||
}
|
||||
|
||||
[RestPutById]
|
||||
[Consumes("application/json")]
|
||||
[Produces("application/json")]
|
||||
public ActionResult<TProviderResource> UpdateProvider([FromBody] TProviderResource providerResource, [FromQuery] bool forceSave = false)
|
||||
{
|
||||
var providerDefinition = GetDefinition(providerResource, true, !forceSave, false);
|
||||
@@ -108,6 +113,7 @@ namespace Readarr.Api.V1
|
||||
}
|
||||
|
||||
[HttpGet("schema")]
|
||||
[Produces("application/json")]
|
||||
public List<TProviderResource> GetTemplates()
|
||||
{
|
||||
var defaultDefinitions = _providerFactory.GetDefaultDefinitions().OrderBy(p => p.ImplementationName).ToList();
|
||||
@@ -131,6 +137,7 @@ namespace Readarr.Api.V1
|
||||
|
||||
[SkipValidation(true, false)]
|
||||
[HttpPost("test")]
|
||||
[Consumes("application/json")]
|
||||
public object Test([FromBody] TProviderResource providerResource)
|
||||
{
|
||||
var providerDefinition = GetDefinition(providerResource, true, true, true);
|
||||
@@ -141,6 +148,7 @@ namespace Readarr.Api.V1
|
||||
}
|
||||
|
||||
[HttpPost("testall")]
|
||||
[Produces("application/json")]
|
||||
public IActionResult TestAll()
|
||||
{
|
||||
var providerDefinitions = _providerFactory.All()
|
||||
@@ -164,6 +172,8 @@ namespace Readarr.Api.V1
|
||||
|
||||
[SkipValidation]
|
||||
[HttpPost("action/{name}")]
|
||||
[Consumes("application/json")]
|
||||
[Produces("application/json")]
|
||||
public IActionResult RequestAction(string name, [FromBody] TProviderResource resource)
|
||||
{
|
||||
var providerDefinition = GetDefinition(resource, false, false, false);
|
||||
|
||||
@@ -57,6 +57,12 @@ namespace Readarr.Api.V1.Queue
|
||||
_qualityComparer = new QualityModelComparer(qualityProfileService.GetDefaultProfile(string.Empty));
|
||||
}
|
||||
|
||||
[NonAction]
|
||||
public override ActionResult<QueueResource> GetResourceByIdWithErrorHandler(int id)
|
||||
{
|
||||
return base.GetResourceByIdWithErrorHandler(id);
|
||||
}
|
||||
|
||||
protected override QueueResource GetResourceById(int id)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
|
||||
@@ -26,6 +26,12 @@ namespace Readarr.Api.V1.Queue
|
||||
_pendingReleaseService = pendingReleaseService;
|
||||
}
|
||||
|
||||
[NonAction]
|
||||
public override ActionResult<QueueResource> GetResourceByIdWithErrorHandler(int id)
|
||||
{
|
||||
return base.GetResourceByIdWithErrorHandler(id);
|
||||
}
|
||||
|
||||
protected override QueueResource GetResourceById(int id)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
|
||||
@@ -20,6 +20,7 @@ namespace Readarr.Api.V1.Queue
|
||||
public BookResource Book { get; set; }
|
||||
public QualityModel Quality { get; set; }
|
||||
public List<CustomFormatResource> CustomFormats { get; set; }
|
||||
public int CustomFormatScore { get; set; }
|
||||
public decimal Size { get; set; }
|
||||
public string Title { get; set; }
|
||||
public decimal Sizeleft { get; set; }
|
||||
@@ -47,6 +48,9 @@ namespace Readarr.Api.V1.Queue
|
||||
return null;
|
||||
}
|
||||
|
||||
var customFormats = model.RemoteBook?.CustomFormats;
|
||||
var customFormatScore = model.RemoteBook?.Author?.QualityProfile?.Value?.CalculateCustomFormatScore(customFormats) ?? 0;
|
||||
|
||||
return new QueueResource
|
||||
{
|
||||
Id = model.Id,
|
||||
@@ -55,7 +59,8 @@ namespace Readarr.Api.V1.Queue
|
||||
Author = includeAuthor && model.Author != null ? model.Author.ToResource() : null,
|
||||
Book = includeBook && model.Book != null ? model.Book.ToResource() : null,
|
||||
Quality = model.Quality,
|
||||
CustomFormats = model.RemoteBook?.CustomFormats?.ToResource(false),
|
||||
CustomFormats = customFormats?.ToResource(false),
|
||||
CustomFormatScore = customFormatScore,
|
||||
Size = model.Size,
|
||||
Title = model.Title,
|
||||
Sizeleft = model.Sizeleft,
|
||||
|
||||
@@ -30,6 +30,12 @@ namespace Readarr.Api.V1.Queue
|
||||
_broadcastDebounce = new Debouncer(BroadcastChange, TimeSpan.FromSeconds(5));
|
||||
}
|
||||
|
||||
[NonAction]
|
||||
public override ActionResult<QueueStatusResource> GetResourceByIdWithErrorHandler(int id)
|
||||
{
|
||||
return base.GetResourceByIdWithErrorHandler(id);
|
||||
}
|
||||
|
||||
protected override QueueStatusResource GetResourceById(int id)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace Readarr.Api.V1.System.Backup
|
||||
private readonly IAppFolderInfo _appFolderInfo;
|
||||
private readonly IDiskProvider _diskProvider;
|
||||
|
||||
private static readonly List<string> ValidExtensions = new List<string> { ".zip", ".db", ".xml" };
|
||||
private static readonly List<string> ValidExtensions = new () { ".zip", ".db", ".xml" };
|
||||
|
||||
public BackupController(IBackupService backupService,
|
||||
IAppFolderInfo appFolderInfo,
|
||||
@@ -37,22 +37,28 @@ namespace Readarr.Api.V1.System.Backup
|
||||
var backups = _backupService.GetBackups();
|
||||
|
||||
return backups.Select(b => new BackupResource
|
||||
{
|
||||
Id = GetBackupId(b),
|
||||
Name = b.Name,
|
||||
Path = $"/backup/{b.Type.ToString().ToLower()}/{b.Name}",
|
||||
Type = b.Type,
|
||||
Size = b.Size,
|
||||
Time = b.Time
|
||||
})
|
||||
.OrderByDescending(b => b.Time)
|
||||
.ToList();
|
||||
{
|
||||
Id = GetBackupId(b),
|
||||
Name = b.Name,
|
||||
Path = $"/backup/{b.Type.ToString().ToLower()}/{b.Name}",
|
||||
Type = b.Type,
|
||||
Size = b.Size,
|
||||
Time = b.Time
|
||||
})
|
||||
.OrderByDescending(b => b.Time)
|
||||
.ToList();
|
||||
}
|
||||
|
||||
[RestDeleteById]
|
||||
public void DeleteBackup(int id)
|
||||
{
|
||||
var backup = GetBackup(id);
|
||||
|
||||
if (backup == null)
|
||||
{
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
var path = GetBackupPath(backup);
|
||||
|
||||
if (!_diskProvider.FileExists(path))
|
||||
@@ -84,6 +90,7 @@ namespace Readarr.Api.V1.System.Backup
|
||||
}
|
||||
|
||||
[HttpPost("restore/upload")]
|
||||
[RequestFormLimits(MultipartBodyLengthLimit = 500000000)]
|
||||
public object UploadAndRestore()
|
||||
{
|
||||
var files = Request.Form.Files;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -39,7 +39,8 @@ namespace Readarr.Http.REST
|
||||
}
|
||||
|
||||
[RestGetById]
|
||||
public ActionResult<TResource> GetResourceByIdWithErrorHandler(int id)
|
||||
[Produces("application/json")]
|
||||
public virtual ActionResult<TResource> GetResourceByIdWithErrorHandler(int id)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user