Compare commits

..

1 Commits

Author SHA1 Message Date
Mark McDowall
bd8f1823bb Sliding expiration for auth cookie and a little clean up
(cherry picked from commit 05ee4e644907b7f1e84589465ac9ab1848f5a766)
2022-08-19 06:29:50 +00:00
144 changed files with 670 additions and 1806 deletions

View File

@@ -5,9 +5,9 @@ body:
- type: checkboxes
attributes:
label: Is there an existing issue for this?
description: Please search to see if an open or closed issue already exists for the bug you encountered. If a bug exists and is closed note that it may only be fixed in an unstable branch.
description: Please search to see if an issue already exists for the bug you encountered.
options:
- label: I have searched the existing open and closed issues
- label: I have searched the existing issues
required: true
- type: textarea
attributes:
@@ -42,14 +42,12 @@ body:
- **Docker Install**: Yes
- **Using Reverse Proxy**: No
- **Browser**: Firefox 90 (If UI related)
- **Database**: Sqlite 3.36.0
value: |
- OS:
- Readarr:
- Docker Install:
- Using Reverse Proxy:
- Browser:
- Database:
render: markdown
validations:
required: true

View File

@@ -5,9 +5,9 @@ body:
- type: checkboxes
attributes:
label: Is there an existing issue for this?
description: Please search to see if an open or closed issue already exists for the feature you are requesting. If a request exists and is closed note that it may only be fixed in an unstable branch.
description: Please search to see if an issue already exists for the feature you are requesting.
options:
- label: I have searched the existing open and closed issues
- label: I have searched the existing issues
required: true
- type: textarea
attributes:

View File

@@ -1,132 +0,0 @@
# Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, caste, color, religion, or sexual
identity and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
* Focusing on what is best not just for us as individuals, but for the overall
community
Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or advances of
any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email address,
without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
<development@readarr.com>.
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series of
actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or permanent
ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within the
community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.1, available at
[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
Community Impact Guidelines were inspired by
[Mozilla's code of conduct enforcement ladder][Mozilla CoC].
For answers to common questions about this code of conduct, see the FAQ at
[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at
[https://www.contributor-covenant.org/translations][translations].
[homepage]: https://www.contributor-covenant.org
[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
[Mozilla CoC]: https://github.com/mozilla/diversity
[FAQ]: https://www.contributor-covenant.org/faq
[translations]: https://www.contributor-covenant.org/translations

View File

@@ -1,8 +0,0 @@
# Security Policy
## Reporting a Vulnerability
Please report (suspected) security vulnerabilities on Discord (preferred) to
any of the Servarr Dev role holders (red names) or via email: development@servarr.com. You will receive a response from
us within 72 hours. If the issue is confirmed, we will release a patch as soon
as possible depending on complexity/severity.

View File

@@ -730,7 +730,7 @@ stages:
inputs:
buildType: 'current'
artifactName: Packages
itemPattern: '**/$(pattern)'
itemPattern: '/$(pattern)'
targetPath: $(Build.ArtifactStagingDirectory)
- bash: |
mkdir -p ${BUILD_ARTIFACTSTAGINGDIRECTORY}/bin
@@ -1050,4 +1050,3 @@ stages:
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
DISCORDCHANNELID: $(discordChannelId)
DISCORDWEBHOOKKEY: $(discordWebhookKey)
DISCORDTHREADID: $(discordThreadId)

View File

@@ -39,7 +39,6 @@ module.exports = {
plugins: [
'filenames',
'react',
'react-hooks',
'simple-import-sort',
'import'
],
@@ -309,9 +308,7 @@ module.exports = {
'react/react-in-jsx-scope': 2,
'react/self-closing-comp': 2,
'react/sort-comp': 2,
'react/jsx-wrap-multilines': 2,
'react-hooks/rules-of-hooks': 'error',
'react-hooks/exhaustive-deps': 'error'
'react/jsx-wrap-multilines': 2
},
overrides: [
{

View File

@@ -169,16 +169,6 @@ class HistoryRow extends Component {
);
}
if (name === 'sourceTitle') {
return (
<TableRowCell
key={name}
>
{sourceTitle}
</TableRowCell>
);
}
if (name === 'details') {
return (
<TableRowCell

View File

@@ -12,9 +12,9 @@ import ModalBody from 'Components/Modal/ModalBody';
import Portal from 'Components/Portal';
import Scroller from 'Components/Scroller/Scroller';
import { icons, scrollDirections, sizes } from 'Helpers/Props';
import { isMobile as isMobileUtil } from 'Utilities/browser';
import * as keyCodes from 'Utilities/Constants/keyCodes';
import getUniqueElememtId from 'Utilities/getUniqueElementId';
import { isMobile as isMobileUtil } from 'Utilities/mobile';
import HintedSelectInputOption from './HintedSelectInputOption';
import HintedSelectInputSelectedValue from './HintedSelectInputSelectedValue';
import TextInput from './TextInput';

View File

@@ -33,7 +33,7 @@ function ConfirmModal(props) {
return () => unbindShortcut('enter', onConfirm);
}
}, [bindShortcut, unbindShortcut, isOpen, onConfirm]);
}, [isOpen, onConfirm]);
return (
<Modal

View File

@@ -6,9 +6,9 @@ import ReactDOM from 'react-dom';
import FocusLock from 'react-focus-lock';
import ErrorBoundary from 'Components/Error/ErrorBoundary';
import { sizes } from 'Helpers/Props';
import { isIOS } from 'Utilities/browser';
import * as keyCodes from 'Utilities/Constants/keyCodes';
import getUniqueElememtId from 'Utilities/getUniqueElementId';
import { isIOS } from 'Utilities/mobile';
import { setScrollLock } from 'Utilities/scrollLock';
import ModalError from './ModalError';
import styles from './Modal.css';

View File

@@ -1,12 +1,23 @@
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import OverlayScroller from 'Components/Scroller/OverlayScroller';
import Scroller from 'Components/Scroller/Scroller';
import { scrollDirections } from 'Helpers/Props';
import { isMobile as isMobileUtil } from 'Utilities/mobile';
import { isLocked } from 'Utilities/scrollLock';
import styles from './PageContentBody.css';
class PageContentBody extends Component {
//
// Lifecycle
constructor(props, context) {
super(props, context);
this._isMobile = isMobileUtil();
}
//
// Listeners
@@ -30,8 +41,10 @@ class PageContentBody extends Component {
...otherProps
} = this.props;
const ScrollerComponent = this._isMobile ? Scroller : OverlayScroller;
return (
<Scroller
<ScrollerComponent
className={className}
scrollDirection={scrollDirections.VERTICAL}
{...otherProps}
@@ -40,7 +53,7 @@ class PageContentBody extends Component {
<div className={innerClassName}>
{children}
</div>
</Scroller>
</ScrollerComponent>
);
}
}

View File

@@ -1,5 +1,4 @@
.jumpBar {
z-index: $pageJumpBarZIndex;
display: flex;
align-content: stretch;
align-items: stretch;

View File

@@ -1,6 +1,6 @@
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import { Scrollbars } from 'react-custom-scrollbars-2';
import { Scrollbars } from 'react-custom-scrollbars';
import { scrollDirections } from 'Helpers/Props';
import styles from './OverlayScroller.css';

View File

@@ -1,7 +1,7 @@
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import Measure from 'Components/Measure';
import { isMobile as isMobileUtil } from 'Utilities/browser';
import { isMobile as isMobileUtil } from 'Utilities/mobile';
import styles from './SwipeHeader.css';
function cursorPosition(event) {

View File

@@ -5,7 +5,7 @@ import { Manager, Popper, Reference } from 'react-popper';
import Portal from 'Components/Portal';
import { kinds, tooltipPositions } from 'Helpers/Props';
import dimensions from 'Styles/Variables/dimensions';
import { isMobile as isMobileUtil } from 'Utilities/browser';
import { isMobile as isMobileUtil } from 'Utilities/mobile';
import styles from './Tooltip.css';
let maxWidth = null;

View File

@@ -148,10 +148,11 @@ class AddNewItem extends Component {
);
} else if (item.book) {
const book = item.book;
const edition = book.editions.find((x) => x.monitored);
return (
<AddNewBookSearchResultConnector
key={item.id}
isExistingBook={'id' in book && book.id !== 0}
isExistingBook={'id' in edition && edition.id !== 0}
isExistingAuthor={'id' in book.author && book.author.id !== 0}
{...book}
/>

View File

@@ -138,20 +138,17 @@ class AddNewBookSearchResult extends Component {
null
}
{
editions && editions.length > 1 ?
<Link
className={styles.mbLink}
to={`https://goodreads.com/book/show/${editions[0].foreignEditionId}`}
onPress={this.onTVDBLinkPress}
>
<Icon
className={styles.mbLinkIcon}
name={icons.EXTERNAL_LINK}
size={28}
/>
</Link> : null
}
<Link
className={styles.mbLink}
to={`https://goodreads.com/book/show/${editions[0].foreignEditionId}`}
onPress={this.onTVDBLinkPress}
>
<Icon
className={styles.mbLinkIcon}
name={icons.EXTERNAL_LINK}
size={28}
/>
</Link>
</div>
</div>
@@ -221,7 +218,7 @@ AddNewBookSearchResult.propTypes = {
overview: PropTypes.string,
ratings: PropTypes.object.isRequired,
author: PropTypes.object,
editions: PropTypes.arrayOf(PropTypes.object),
editions: PropTypes.arrayOf(PropTypes.object).isRequired,
images: PropTypes.arrayOf(PropTypes.object).isRequired,
isExistingBook: PropTypes.bool.isRequired,
isExistingAuthor: PropTypes.bool.isRequired,

View File

@@ -173,7 +173,7 @@ class AddAuthorOptionsForm extends Component {
AddAuthorOptionsForm.propTypes = {
rootFolderPath: PropTypes.object,
monitor: PropTypes.object.isRequired,
monitorNewItems: PropTypes.object.isRequired,
monitorNewItems: PropTypes.string.isRequired,
qualityProfileId: PropTypes.object,
metadataProfileId: PropTypes.object,
showMetadataProfile: PropTypes.bool.isRequired,

View File

@@ -21,7 +21,6 @@ function HostSettings(props) {
port,
urlBase,
instanceName,
applicationUrl,
enableSsl,
sslPort,
sslCertPath,
@@ -59,7 +58,6 @@ function HostSettings(props) {
name="port"
min={1}
max={65535}
autocomplete="off"
helpTextWarning={translate('PortHelpTextWarning')}
onChange={onInputChange}
{...port}
@@ -97,21 +95,6 @@ function HostSettings(props) {
/>
</FormGroup>
<FormGroup
advancedSettings={advancedSettings}
isAdvanced={true}
>
<FormLabel>{translate('ApplicationURL')}</FormLabel>
<FormInputGroup
type={inputTypes.TEXT}
name="applicationUrl"
helpText={translate('ApplicationUrlHelpText')}
onChange={onInputChange}
{...applicationUrl}
/>
</FormGroup>
<FormGroup
advancedSettings={advancedSettings}
isAdvanced={true}

View File

@@ -19,7 +19,7 @@ function PendingChangesModal(props) {
useEffect(() => {
bindShortcut('enter', onConfirm);
}, [bindShortcut, onConfirm]);
}, [onConfirm]);
return (
<Modal

View File

@@ -6,7 +6,6 @@ import getProviderState from 'Utilities/State/getProviderState';
import { removeItem, set, updateItem } from '../baseActions';
const abortCurrentRequests = {};
let lastSaveData = null;
export function createCancelSaveProviderHandler(section) {
return function(getState, payload, dispatch) {
@@ -28,33 +27,27 @@ function createSaveProviderHandler(section, url, options = {}, removeStale = fal
} = payload;
const saveData = Array.isArray(id) ? id.map((x) => getProviderState({ id: x, ...otherPayload }, getState, section)) : getProviderState({ id, ...otherPayload }, getState, section);
const requestUrl = id ? `${url}/${id}` : url;
const params = { ...queryParams };
// If the user is re-saving the same provider without changes
// force it to be saved. Only applies to editing existing providers.
if (id && _.isEqual(saveData, lastSaveData)) {
params.forceSave = true;
}
lastSaveData = saveData;
const ajaxOptions = {
url: `${requestUrl}?${$.param(params, true)}`,
method: id ? 'PUT' : 'POST',
url: `${url}?${$.param(queryParams, true)}`,
method: 'POST',
contentType: 'application/json',
dataType: 'json',
data: JSON.stringify(saveData)
};
if (id) {
ajaxOptions.method = 'PUT';
if (!Array.isArray(id)) {
ajaxOptions.url = `${url}/${id}?${$.param(queryParams, true)}`;
}
}
const { request, abortRequest } = createAjaxRequest(ajaxOptions);
abortCurrentRequests[section] = abortRequest;
request.done((data) => {
lastSaveData = null;
if (!Array.isArray(data)) {
data = [data];
}

View File

@@ -71,11 +71,6 @@ export const defaultState = {
label: 'Release Group',
isVisible: false
},
{
name: 'sourceTitle',
label: 'Source Title',
isVisible: false
},
{
name: 'details',
columnLabel: 'Details',

View File

@@ -1,7 +1,4 @@
@define-mixin scrollbar {
scrollbar-color: var(--scrollbarBackgroundColor) transparent;
scrollbar-width: thin;
&::-webkit-scrollbar {
width: 10px;
height: 10px;

View File

@@ -1,5 +1,4 @@
module.exports = {
pageJumpBarZIndex: 10,
modalZIndex: 1000,
popperZIndex: 2000
};

View File

@@ -20,6 +20,7 @@ class About extends Component {
packageVersion,
packageAuthor,
isNetCore,
isMono,
isDocker,
runtimeVersion,
migrationVersion,
@@ -49,6 +50,14 @@ class About extends Component {
/>
}
{
isMono &&
<DescriptionListItem
title={translate('MonoVersion')}
data={runtimeVersion}
/>
}
{
isNetCore &&
<DescriptionListItem
@@ -112,6 +121,7 @@ About.propTypes = {
packageVersion: PropTypes.string,
packageAuthor: PropTypes.string,
isNetCore: PropTypes.bool.isRequired,
isMono: PropTypes.bool.isRequired,
runtimeVersion: PropTypes.string.isRequired,
isDocker: PropTypes.bool.isRequired,
migrationVersion: PropTypes.number.isRequired,

View File

@@ -10,7 +10,3 @@ export function isMobile() {
export function isIOS() {
return mobileDetect.is('iOS');
}
export function isFirefox() {
return window.navigator.userAgent.toLowerCase().indexOf('firefox/') >= 0;
}

View File

@@ -58,7 +58,7 @@
"react-addons-shallow-compare": "15.6.3",
"react-async-script": "1.2.0",
"react-autosuggest": "10.1.0",
"react-custom-scrollbars-2": "4.5.0",
"react-custom-scrollbars": "4.2.1",
"react-dnd": "14.0.2",
"react-dnd-html5-backend": "14.0.0",
"react-dnd-multi-backend": "6.0.2",
@@ -109,7 +109,6 @@
"eslint-plugin-filenames": "1.3.2",
"eslint-plugin-import": "2.23.4",
"eslint-plugin-react": "7.24.0",
"eslint-plugin-react-hooks": "4.6.0",
"eslint-plugin-simple-import-sort": "7.0.0",
"esprint": "3.1.0",
"file-loader": "6.2.0",

View File

@@ -29,9 +29,9 @@
<PackageVersion Include="MonoTorrent" Version="2.0.6" />
<PackageVersion Include="NBuilder" Version="6.1.0" />
<PackageVersion Include="Newtonsoft.Json" Version="13.0.1" />
<PackageVersion Include="NLog.Extensions.Logging" Version="5.1.0" />
<PackageVersion Include="NLog" Version="5.0.5" />
<PackageVersion Include="NLog.Targets.Syslog" Version="7.0.0" />
<PackageVersion Include="NLog.Extensions.Logging" Version="1.7.4" />
<PackageVersion Include="NLog" Version="4.7.14" />
<PackageVersion Include="NLog.Targets.Syslog" Version="6.0.2" />
<PackageVersion Include="Npgsql" Version="6.0.3" />
<PackageVersion Include="NUnit3TestAdapter" Version="4.2.1" />
<PackageVersion Include="NUnit" Version="3.13.3" />

View File

@@ -437,6 +437,24 @@ namespace NzbDrone.Common.Test.DiskTests
Assert.Throws<IOException>(() => Subject.TransferFolder(source.FullName, destination.FullName, TransferMode.Copy));
}
[Test]
public void CopyFolder_should_not_copy_casesensitive_folder()
{
MonoOnly();
WithRealDiskProvider();
var original = GetFilledTempFolder();
var root = new DirectoryInfo(GetTempFilePath());
var source = new DirectoryInfo(root.FullName + "A/series");
var destination = new DirectoryInfo(root.FullName + "A/Series");
Subject.TransferFolder(original.FullName, source.FullName, TransferMode.Copy);
// Note: Although technically possible top copy to different case, we're not allowing it
Assert.Throws<IOException>(() => Subject.TransferFolder(source.FullName, destination.FullName, TransferMode.Copy));
}
[Test]
public void CopyFolder_should_ignore_nfs_temp_file()
{
@@ -522,6 +540,26 @@ namespace NzbDrone.Common.Test.DiskTests
source.FullName.GetActualCasing().Should().Be(destination.FullName);
}
[Test]
public void MoveFolder_should_rename_casesensitive_folder()
{
MonoOnly();
WithRealDiskProvider();
var original = GetFilledTempFolder();
var root = new DirectoryInfo(GetTempFilePath());
var source = new DirectoryInfo(root.FullName + "A/series");
var destination = new DirectoryInfo(root.FullName + "A/Series");
Subject.TransferFolder(original.FullName, source.FullName, TransferMode.Copy);
Subject.TransferFolder(source.FullName, destination.FullName, TransferMode.Move);
Directory.Exists(source.FullName).Should().Be(false);
Directory.Exists(destination.FullName).Should().Be(true);
}
[Test]
public void should_throw_if_destination_is_readonly()
{

View File

@@ -207,7 +207,6 @@ namespace NzbDrone.Common.Test.Http
}
[Test]
[Platform(Exclude = "MacOsX", Reason = "Azure agent update prevents brotli on OSX")]
public void should_execute_get_using_brotli()
{
var request = new HttpRequest($"https://{_httpBinHost}/brotli");
@@ -308,6 +307,11 @@ namespace NzbDrone.Common.Test.Http
[Test]
public void should_follow_redirects_to_https()
{
if (typeof(TDispatcher) == typeof(ManagedHttpDispatcher) && PlatformInfo.IsMono)
{
Assert.Ignore("Will fail on tls1.2 via managed dispatcher, ignore.");
}
var request = new HttpRequestBuilder($"https://{_httpBinHost}/redirect-to")
.AddQueryParam("url", $"https://readarr.com/")
.Build();

View File

@@ -61,7 +61,6 @@ namespace NzbDrone.Common.Test.InstrumentationTests
[TestCase("https://notifiarr.com/notifier.php: api=1234530f-422f-4aac-b6b3-01233210aaaa&radarr_health_issue_message=Download")]
[TestCase("/readarr/signalr/messages/negotiate?access_token=1234530f422f4aacb6b301233210aaaa&negotiateVersion=1")]
[TestCase(@"[Info] MigrationController: *** Migrating Database=readarr-main;Host=postgres14;Username=mySecret;Password=mySecret;Port=5432;Enlist=False ***")]
[TestCase(@"[Info] MigrationController: *** Migrating Database=readarr-main;Host=postgres14;Username=mySecret;Password=mySecret;Port=5432;token=mySecret;Enlist=False&username=mySecret;mypassword=mySecret;mypass=shouldkeep1;test_token=mySecret;password=123%@%_@!#^#@;use_password=mySecret;get_token=shouldkeep2;usetoken=shouldkeep3;passwrd=mySecret;")]
// Announce URLs (passkeys) Magnet & Tracker
[TestCase(@"magnet_uri"":""magnet:?xt=urn:btih:9pr04sgkillroyimaveql2tyu8xyui&dn=&tr=https%3a%2f%2fxxx.yyy%2f9pr04sg601233210imaveql2tyu8xyui%2fannounce""}")]
@@ -74,36 +73,17 @@ namespace NzbDrone.Common.Test.InstrumentationTests
[TestCase(@"tracker"":""https://xxx.yyy/announce.php?passkey=9pr04sg601233210imaveql2tyu8xyui""}")]
[TestCase(@"tracker"":""http://xxx.yyy/announce.php?passkey=9pr04sg601233210imaveql2tyu8xyui"",""info"":""http://xxx.yyy/info?a=b""")]
// Notifiarr
// Webhooks - Notifiarr
[TestCase(@"https://xxx.yyy/api/v1/notification/readarr/9pr04sg6-0123-3210-imav-eql2tyu8xyui")]
// Discord
[TestCase(@"https://discord.com/api/webhooks/mySecret")]
[TestCase(@"https://discord.com/api/webhooks/mySecret/01233210")]
public void should_clean_message(string message)
{
var cleansedMessage = CleanseLogMessage.Cleanse(message);
cleansedMessage.Should().NotContain("mySecret");
cleansedMessage.Should().NotContain("123%@%_@!#^#@");
cleansedMessage.Should().NotContain("01233210");
}
[TestCase(@"[Info] MigrationController: *** Migrating Database=radarr-main;Host=postgres14;Username=mySecret;Password=mySecret;Port=5432;token=mySecret;Enlist=False&username=mySecret;mypassword=mySecret;mypass=shouldkeep1;test_token=mySecret;password=123%@%_@!#^#@;use_password=mySecret;get_token=shouldkeep2;usetoken=shouldkeep3;passwrd=mySecret;")]
public void should_keep_message(string message)
{
var cleansedMessage = CleanseLogMessage.Cleanse(message);
cleansedMessage.Should().NotContain("mySecret");
cleansedMessage.Should().NotContain("123%@%_@!#^#@");
cleansedMessage.Should().NotContain("01233210");
cleansedMessage.Should().Contain("shouldkeep1");
cleansedMessage.Should().Contain("shouldkeep2");
cleansedMessage.Should().Contain("shouldkeep3");
}
//GoodReads
[TestCase(@"{""signatureMethod"": ""hmacSha1"",""signatureTreatment"": ""escaped"",""type"": ""protectedResource"",""method"": ""GET"",""token"": ""mytoken"",""tokenSecret"": ""mytokensecret"",""requestUrl"": ""https://www.goodreads.com/review/list.xml"",""parameters"": { ""_nc"": ""1"", ""v"": ""2"", ""id"": ""999999999"", ""shelf"": ""currently-reading"", ""per_page"": ""200"", ""page"": ""1""}")]
[TestCase(@"https://www.goodreads.com/series/311911?key=1234530f422f4aacb6b301233210aaaa&_nc=1&format=xml")]

View File

@@ -279,7 +279,7 @@ namespace NzbDrone.Common.Test
[Test]
public void GetUpdateClientExePath()
{
GetIAppDirectoryInfo().GetUpdateClientExePath().Should().BeEquivalentTo(@"C:\Temp\readarr_update\Readarr.Update".AsOsAgnostic().ProcessNameToExe());
GetIAppDirectoryInfo().GetUpdateClientExePath(PlatformType.DotNet).Should().BeEquivalentTo(@"C:\Temp\readarr_update\Readarr.Update.exe".AsOsAgnostic());
}
[Test]

View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
@@ -171,7 +171,7 @@ namespace NzbDrone.Common.Test
var processStarted = new ManualResetEventSlim();
string suffix;
if (OsInfo.IsWindows)
if (OsInfo.IsWindows || PlatformInfo.IsMono)
{
suffix = ".exe";
}

View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using NzbDrone.Common.EnvironmentInfo;
@@ -24,8 +24,7 @@ namespace NzbDrone.Common.Disk
"/boot",
"/lib",
"/sbin",
"/proc",
"/usr/bin"
"/proc"
};
}
}

View File

@@ -1,7 +1,17 @@
using System;
using System;
using System.Reflection;
using System.Text.RegularExpressions;
using Microsoft.Win32;
namespace NzbDrone.Common.EnvironmentInfo
{
public enum PlatformType
{
DotNet = 0,
Mono = 1,
NetCore = 2
}
public interface IPlatformInfo
{
Version Version { get; }
@@ -9,18 +19,38 @@ namespace NzbDrone.Common.EnvironmentInfo
public class PlatformInfo : IPlatformInfo
{
private static readonly Regex MonoVersionRegex = new Regex(@"(?<=\W|^)(?<version>\d+\.\d+(\.\d+)?(\.\d+)?)(?=\W)", RegexOptions.Compiled | RegexOptions.IgnoreCase);
private static PlatformType _platform;
private static Version _version;
static PlatformInfo()
{
_platform = PlatformType.NetCore;
_version = Environment.Version;
}
public static PlatformType Platform => _platform;
public static bool IsMono => Platform == PlatformType.Mono;
public static bool IsDotNet => Platform == PlatformType.DotNet;
public static bool IsNetCore => Platform == PlatformType.NetCore;
public static string PlatformName
{
get
{
return ".NET";
if (IsDotNet)
{
return ".NET";
}
else if (IsMono)
{
return "Mono";
}
else
{
return ".NET Core";
}
}
}
@@ -30,5 +60,107 @@ namespace NzbDrone.Common.EnvironmentInfo
{
return _version;
}
private static Version GetMonoVersion()
{
try
{
var type = Type.GetType("Mono.Runtime");
if (type != null)
{
var displayNameMethod = type.GetMethod("GetDisplayName", BindingFlags.NonPublic | BindingFlags.Static);
if (displayNameMethod != null)
{
var displayName = displayNameMethod.Invoke(null, null).ToString();
var versionMatch = MonoVersionRegex.Match(displayName);
if (versionMatch.Success)
{
return new Version(versionMatch.Groups["version"].Value);
}
}
}
}
catch (Exception ex)
{
Console.WriteLine("Couldnt get Mono version: " + ex.ToString());
}
return new Version();
}
private static Version GetDotNetVersion()
{
try
{
const string subkey = @"SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full\";
using (var ndpKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32).OpenSubKey(subkey))
{
if (ndpKey == null)
{
return new Version(4, 0);
}
var releaseKey = (int)ndpKey.GetValue("Release");
if (releaseKey >= 528040)
{
return new Version(4, 8, 0);
}
if (releaseKey >= 461808)
{
return new Version(4, 7, 2);
}
if (releaseKey >= 461308)
{
return new Version(4, 7, 1);
}
if (releaseKey >= 460798)
{
return new Version(4, 7);
}
if (releaseKey >= 394802)
{
return new Version(4, 6, 2);
}
if (releaseKey >= 394254)
{
return new Version(4, 6, 1);
}
if (releaseKey >= 393295)
{
return new Version(4, 6);
}
if (releaseKey >= 379893)
{
return new Version(4, 5, 2);
}
if (releaseKey >= 378675)
{
return new Version(4, 5, 1);
}
if (releaseKey >= 378389)
{
return new Version(4, 5);
}
}
}
catch (Exception ex)
{
Console.WriteLine("Couldnt get .NET framework version: " + ex.ToString());
}
return new Version(4, 0);
}
}
}

View File

@@ -240,9 +240,9 @@ namespace NzbDrone.Common.Extensions
return null;
}
public static string ProcessNameToExe(this string processName)
public static string ProcessNameToExe(this string processName, PlatformType runtime)
{
if (OsInfo.IsWindows)
if (OsInfo.IsWindows || runtime != PlatformType.NetCore)
{
processName += ".exe";
}
@@ -250,6 +250,11 @@ namespace NzbDrone.Common.Extensions
return processName;
}
public static string ProcessNameToExe(this string processName)
{
return processName.ProcessNameToExe(PlatformInfo.Platform);
}
public static string GetLongestCommonPath(this List<string> paths)
{
var firstPath = paths.First();
@@ -342,9 +347,9 @@ namespace NzbDrone.Common.Extensions
return Path.Combine(GetUpdatePackageFolder(appFolderInfo), UPDATE_CLIENT_FOLDER_NAME);
}
public static string GetUpdateClientExePath(this IAppFolderInfo appFolderInfo)
public static string GetUpdateClientExePath(this IAppFolderInfo appFolderInfo, PlatformType runtime)
{
return Path.Combine(GetUpdateSandboxFolder(appFolderInfo), UPDATE_CLIENT_EXE_NAME).ProcessNameToExe();
return Path.Combine(GetUpdateSandboxFolder(appFolderInfo), UPDATE_CLIENT_EXE_NAME).ProcessNameToExe(runtime);
}
public static string GetDatabase(this IAppFolderInfo appFolderInfo)

View File

@@ -55,8 +55,7 @@ namespace NzbDrone.Common.Http
StatusCode == HttpStatusCode.Found ||
StatusCode == HttpStatusCode.TemporaryRedirect ||
StatusCode == HttpStatusCode.RedirectMethod ||
StatusCode == HttpStatusCode.SeeOther ||
StatusCode == HttpStatusCode.PermanentRedirect;
StatusCode == HttpStatusCode.SeeOther;
public string[] GetCookieHeaders()
{

View File

@@ -18,7 +18,7 @@ namespace NzbDrone.Common.Instrumentation
new Regex(@"iptorrents\.com/[/a-z0-9?&;]*?(?:[?&;](u|tp)=(?<secret>[^&=;]+?))+(?= |;|&|$)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
new Regex(@"/fetch/[a-z0-9]{32}/(?<secret>[a-z0-9]{32})", RegexOptions.Compiled),
new Regex(@"getnzb.*?(?<=\?|&)(r)=(?<secret>[^&=]+?)(?= |&|$)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
new Regex(@"\b(\w*)?(_?(?<!use|get_)token|username|passwo?rd)=(?<secret>[^&=]+?)(?= |&|$|;)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
new Regex(@"(?<=[?& ;])[^=]*?(_?(?<!use|get_)token|username|passwo?rd)=(?<secret>[^&=]+?)(?= |&|$|;)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
// Trackers Announce Keys; Designed for Qbit Json; should work for all in theory
new Regex(@"announce(\.php)?(/|%2f|%3fpasskey%3d)(?<secret>[a-z0-9]{16,})|(?<secret>[a-z0-9]{16,})(/|%2f)announce"),
@@ -51,10 +51,7 @@ namespace NzbDrone.Common.Instrumentation
// Webhooks
// Notifiarr
new Regex(@"api/v[0-9]/notification/readarr/(?<secret>[\w-]+)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
// Discord
new Regex(@"discord.com/api/webhooks/((?<secret>[\w-]+)/)?(?<secret>[\w-]+)", RegexOptions.Compiled | RegexOptions.IgnoreCase)
new Regex(@"api/v[0-9]/notification/readarr/(?<secret>[\w-]+)", RegexOptions.Compiled | RegexOptions.IgnoreCase)
};
private static readonly Regex CleanseRemoteIPRegex = new Regex(@"(?:Auth-\w+(?<!Failure|Unauthorized) ip|from) (\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})", RegexOptions.Compiled);

View File

@@ -1,6 +1,6 @@
using System.Collections.Generic;
using System.Linq;
using System.Linq;
using NLog;
using NLog.Fluent;
namespace NzbDrone.Common.Instrumentation.Extensions
{
@@ -8,46 +8,47 @@ namespace NzbDrone.Common.Instrumentation.Extensions
{
public static readonly Logger SentryLogger = LogManager.GetLogger("Sentry");
public static LogEventBuilder SentryFingerprint(this LogEventBuilder logBuilder, params string[] fingerprint)
public static LogBuilder SentryFingerprint(this LogBuilder logBuilder, params string[] fingerprint)
{
return logBuilder.Property("Sentry", fingerprint);
}
public static LogEventBuilder WriteSentryDebug(this LogEventBuilder logBuilder, params string[] fingerprint)
public static LogBuilder WriteSentryDebug(this LogBuilder logBuilder, params string[] fingerprint)
{
return LogSentryMessage(logBuilder, LogLevel.Debug, fingerprint);
}
public static LogEventBuilder WriteSentryInfo(this LogEventBuilder logBuilder, params string[] fingerprint)
public static LogBuilder WriteSentryInfo(this LogBuilder logBuilder, params string[] fingerprint)
{
return LogSentryMessage(logBuilder, LogLevel.Info, fingerprint);
}
public static LogEventBuilder WriteSentryWarn(this LogEventBuilder logBuilder, params string[] fingerprint)
public static LogBuilder WriteSentryWarn(this LogBuilder logBuilder, params string[] fingerprint)
{
return LogSentryMessage(logBuilder, LogLevel.Warn, fingerprint);
}
public static LogEventBuilder WriteSentryError(this LogEventBuilder logBuilder, params string[] fingerprint)
public static LogBuilder WriteSentryError(this LogBuilder logBuilder, params string[] fingerprint)
{
return LogSentryMessage(logBuilder, LogLevel.Error, fingerprint);
}
private static LogEventBuilder LogSentryMessage(LogEventBuilder logBuilder, LogLevel level, string[] fingerprint)
private static LogBuilder LogSentryMessage(LogBuilder logBuilder, LogLevel level, string[] fingerprint)
{
SentryLogger.ForLogEvent(level)
.CopyLogEvent(logBuilder.LogEvent)
SentryLogger.Log(level)
.CopyLogEvent(logBuilder.LogEventInfo)
.SentryFingerprint(fingerprint)
.Log();
.Write();
return logBuilder.Property<string>("Sentry", null);
return logBuilder.Property("Sentry", null);
}
private static LogEventBuilder CopyLogEvent(this LogEventBuilder logBuilder, LogEventInfo logEvent)
private static LogBuilder CopyLogEvent(this LogBuilder logBuilder, LogEventInfo logEvent)
{
return logBuilder.TimeStamp(logEvent.TimeStamp)
return logBuilder.LoggerName(logEvent.LoggerName)
.TimeStamp(logEvent.TimeStamp)
.Message(logEvent.Message, logEvent.Parameters)
.Properties(logEvent.Properties.Select(p => new KeyValuePair<string, object>(p.Key.ToString(), p.Value)))
.Properties(logEvent.Properties.ToDictionary(v => v.Key, v => v.Value))
.Exception(logEvent.Exception);
}
}

View File

@@ -38,6 +38,16 @@ namespace NzbDrone.Common.Instrumentation
return;
}
if (PlatformInfo.IsMono)
{
if ((exception is TypeInitializationException && exception.InnerException is DllNotFoundException) ||
exception is DllNotFoundException)
{
Logger.Debug(exception, "Minor Fail: " + exception.Message);
return;
}
}
Console.WriteLine("EPIC FAIL: {0}", exception);
Logger.Fatal(exception, "EPIC FAIL.");
}

View File

@@ -1,15 +1,13 @@
using System.Text;
using NLog;
using NLog;
using NLog.Targets;
namespace NzbDrone.Common.Instrumentation
{
public class NzbDroneFileTarget : FileTarget
{
protected override void RenderFormattedMessage(LogEventInfo logEvent, StringBuilder target)
protected override string GetFormattedMessage(LogEventInfo logEvent)
{
var result = CleanseLogMessage.Cleanse(Layout.Render(logEvent));
target.Append(result);
return CleanseLogMessage.Cleanse(Layout.Render(logEvent));
}
}
}

View File

@@ -34,8 +34,6 @@ namespace NzbDrone.Common.Instrumentation
var appFolderInfo = new AppFolderInfo(startupContext);
RegisterGlobalFilters();
if (Debugger.IsAttached)
{
RegisterDebugger();
@@ -103,16 +101,6 @@ namespace NzbDrone.Common.Instrumentation
LogManager.Configuration.LoggingRules.Add(loggingRule);
}
private static void RegisterGlobalFilters()
{
LogManager.Setup().LoadConfiguration(c =>
{
c.ForLogger("Microsoft.Hosting.Lifetime*").WriteToNil(LogLevel.Info);
c.ForLogger("System*").WriteToNil(LogLevel.Warn);
c.ForLogger("Microsoft*").WriteToNil(LogLevel.Warn);
});
}
private static void RegisterConsole()
{
var level = LogLevel.Trace;

View File

@@ -109,6 +109,13 @@ namespace NzbDrone.Common.Instrumentation.Sentry
o.Debug = false;
o.DiagnosticLevel = SentryLevel.Debug;
o.Release = BuildInfo.Release;
if (PlatformInfo.IsMono)
{
// Mono 6.0 broke GzipStream.WriteAsync
// TODO: Check specific version
o.RequestBodyCompressionLevel = System.IO.Compression.CompressionLevel.NoCompression;
}
o.BeforeSend = x => SentryCleanser.CleanseEvent(x);
o.BeforeBreadcrumb = x => SentryCleanser.CleanseBreadcrumb(x);
o.Environment = BuildInfo.Branch;
@@ -151,6 +158,14 @@ namespace NzbDrone.Common.Instrumentation.Sentry
SentrySdk.ConfigureScope(scope =>
{
scope.SetTag("is_docker", $"{osInfo.IsDocker}");
if (osInfo.Name != null && PlatformInfo.IsMono)
{
// Sentry auto-detection of non-Windows platforms isn't that accurate on certain devices.
scope.Contexts.OperatingSystem.Name = osInfo.Name.FirstCharToUpper();
scope.Contexts.OperatingSystem.RawDescription = osInfo.FullName;
scope.Contexts.OperatingSystem.Version = osInfo.Version.ToString();
}
});
}
@@ -206,11 +221,7 @@ namespace NzbDrone.Common.Instrumentation.Sentry
if (ex != null)
{
fingerPrint.Add(ex.GetType().FullName);
if (ex.TargetSite != null)
{
fingerPrint.Add(ex.TargetSite.ToString());
}
fingerPrint.Add(ex.TargetSite.ToString());
if (ex.InnerException != null)
{
fingerPrint.Add(ex.InnerException.GetType().FullName);

View File

@@ -377,6 +377,11 @@ namespace NzbDrone.Common.Processes
private (string Path, string Args) GetPathAndArgs(string path, string args)
{
if (PlatformInfo.IsMono && path.EndsWith(".exe", StringComparison.InvariantCultureIgnoreCase))
{
return ("mono", $"--debug {path} {args}");
}
if (OsInfo.IsWindows && path.EndsWith(".bat", StringComparison.InvariantCultureIgnoreCase))
{
return ("cmd.exe", $"/c {path} {args}");

View File

@@ -1,4 +1,3 @@
using System;
using System.Collections.Generic;
using System.Linq;
using FizzWare.NBuilder;
@@ -6,7 +5,6 @@ using FluentAssertions;
using Moq;
using NUnit.Framework;
using NzbDrone.Core.Books;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.DecisionEngine.Specifications;
using NzbDrone.Core.MediaFiles;
using NzbDrone.Core.Parser.Model;
@@ -246,89 +244,5 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
.Should()
.BeFalse();
}
[Test]
public void should_return_true_when_repacks_are_not_preferred()
{
Mocker.GetMock<IConfigService>()
.Setup(s => s.DownloadPropersAndRepacks)
.Returns(ProperDownloadTypes.DoNotPrefer);
_trackFiles.Select(c =>
{
c.ReleaseGroup = "";
return c;
}).ToList();
_trackFiles.Select(c =>
{
c.Quality = new QualityModel(Quality.FLAC);
return c;
}).ToList();
var remoteAlbum = Builder<RemoteBook>.CreateNew()
.With(e => e.ParsedBookInfo = _parsedBookInfo)
.With(e => e.Books = _books)
.Build();
Subject.IsSatisfiedBy(remoteAlbum, null).Accepted.Should().BeTrue();
}
[Test]
public void should_return_true_when_repack_but_auto_download_repacks_is_true()
{
Mocker.GetMock<IConfigService>()
.Setup(s => s.DownloadPropersAndRepacks)
.Returns(ProperDownloadTypes.PreferAndUpgrade);
_parsedBookInfo.Quality.Revision.IsRepack = true;
_trackFiles.Select(c =>
{
c.ReleaseGroup = "Readarr";
return c;
}).ToList();
_trackFiles.Select(c =>
{
c.Quality = new QualityModel(Quality.FLAC);
return c;
}).ToList();
var remoteAlbum = Builder<RemoteBook>.CreateNew()
.With(e => e.ParsedBookInfo = _parsedBookInfo)
.With(e => e.Books = _books)
.Build();
Subject.IsSatisfiedBy(remoteAlbum, null).Accepted.Should().BeTrue();
}
[Test]
public void should_return_false_when_repack_but_auto_download_repacks_is_false()
{
Mocker.GetMock<IConfigService>()
.Setup(s => s.DownloadPropersAndRepacks)
.Returns(ProperDownloadTypes.DoNotUpgrade);
_parsedBookInfo.Quality.Revision.IsRepack = true;
_trackFiles.Select(c =>
{
c.ReleaseGroup = "Readarr";
return c;
}).ToList();
_trackFiles.Select(c =>
{
c.Quality = new QualityModel(Quality.FLAC);
return c;
}).ToList();
var remoteAlbum = Builder<RemoteBook>.CreateNew()
.With(e => e.ParsedBookInfo = _parsedBookInfo)
.With(e => e.Books = _books)
.Build();
Subject.IsSatisfiedBy(remoteAlbum, null).Accepted.Should().BeFalse();
}
}
}

View File

@@ -25,7 +25,7 @@ namespace NzbDrone.Core.Test.IndexerSearchTests
.Setup(s => s.GetAuthor(It.IsAny<int>()))
.Returns(_author);
Mocker.GetMock<ISearchForReleases>()
Mocker.GetMock<ISearchForNzb>()
.Setup(s => s.AuthorSearch(_author.Id, false, true, false))
.Returns(new List<DownloadDecision>());
@@ -45,7 +45,7 @@ namespace NzbDrone.Core.Test.IndexerSearchTests
Subject.Execute(new AuthorSearchCommand { AuthorId = _author.Id, Trigger = CommandTrigger.Manual });
Mocker.GetMock<ISearchForReleases>()
Mocker.GetMock<ISearchForNzb>()
.Verify(v => v.AuthorSearch(_author.Id, false, true, false),
Times.Exactly(_author.Books.Value.Count(s => s.Monitored)));
}

View File

@@ -16,6 +16,11 @@ namespace NzbDrone.Core.Test.MediaCoverTests
[SetUp]
public void SetUp()
{
if (PlatformInfo.IsMono && PlatformInfo.GetVersion() < new Version(5, 8))
{
Assert.Inconclusive("Not supported on Mono < 5.8");
}
Mocker.GetMock<IDiskProvider>()
.Setup(v => v.FileExists(It.IsAny<string>()))
.Returns<string>(s => File.Exists(s));

View File

@@ -7,6 +7,7 @@ using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.ParserTests
{
[TestFixture]
public class QualityParserFixture : CoreTest
{
public static object[] SelfQualityParserCases =

View File

@@ -69,7 +69,7 @@ namespace NzbDrone.Core.Test.UpdateTests
.Returns(true);
Mocker.GetMock<IDiskProvider>()
.Setup(v => v.FileExists(It.Is<string>(s => s.EndsWith("Readarr.Update".ProcessNameToExe()))))
.Setup(v => v.FileExists(It.Is<string>(s => s.EndsWith("Readarr.Update.exe"))))
.Returns(true);
_sandboxFolder = Mocker.GetMock<IAppFolderInfo>().Object.GetUpdateSandboxFolder();
@@ -165,7 +165,7 @@ namespace NzbDrone.Core.Test.UpdateTests
public void should_return_with_warning_if_updater_doesnt_exists()
{
Mocker.GetMock<IDiskProvider>()
.Setup(v => v.FileExists(It.Is<string>(s => s.EndsWith("Readarr.Update".ProcessNameToExe()))))
.Setup(v => v.FileExists(It.Is<string>(s => s.EndsWith("Readarr.Update.exe"))))
.Returns(false);
Subject.Execute(new ApplicationUpdateCommand());

View File

@@ -410,8 +410,6 @@ namespace NzbDrone.Core.Configuration
public CertificateValidationType CertificateValidation =>
GetValueEnum("CertificateValidation", CertificateValidationType.Enabled);
public string ApplicationUrl => GetValue("ApplicationUrl", string.Empty);
private string GetValue(string key)
{
return GetValue(key, string.Empty);

View File

@@ -97,6 +97,5 @@ namespace NzbDrone.Core.Configuration
int BackupRetention { get; }
CertificateValidationType CertificateValidation { get; }
string ApplicationUrl { get; }
}
}

View File

@@ -1,7 +1,6 @@
using System;
using System.Data.Common;
using System.Data.SQLite;
using System.Net.Sockets;
using NLog;
using Npgsql;
using NzbDrone.Common.Disk;
@@ -132,37 +131,6 @@ namespace NzbDrone.Core.Datastore
throw new CorruptDatabaseException("Database file: {0} is corrupt, restore from backup if available. See: https://wiki.servarr.com/readarr/faq#i-am-getting-an-error-database-disk-image-is-malformed", e, fileName);
}
catch (NpgsqlException e)
{
if (e.InnerException is SocketException)
{
var retryCount = 3;
while (true)
{
Logger.Error(e, "Failure to connect to Postgres DB, {0} retries remaining", retryCount);
try
{
_migrationController.Migrate(connectionString, migrationContext);
}
catch (Exception ex)
{
if (--retryCount > 0)
{
System.Threading.Thread.Sleep(5000);
continue;
}
throw new ReadarrStartupException(ex, "Error creating main database");
}
}
}
else
{
throw new ReadarrStartupException(e, "Error creating main database");
}
}
catch (Exception e)
{
throw new ReadarrStartupException(e, "Error creating main database");

View File

@@ -1,11 +1,9 @@
using System;
using NLog;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.MediaFiles;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Qualities;
namespace NzbDrone.Core.DecisionEngine.Specifications
{
@@ -13,14 +11,12 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
{
private readonly IMediaFileService _mediaFileService;
private readonly UpgradableSpecification _upgradableSpecification;
private readonly IConfigService _configService;
private readonly Logger _logger;
public RepackSpecification(IMediaFileService mediaFileService, UpgradableSpecification upgradableSpecification, IConfigService configService, Logger logger)
public RepackSpecification(IMediaFileService mediaFileService, UpgradableSpecification upgradableSpecification, Logger logger)
{
_mediaFileService = mediaFileService;
_upgradableSpecification = upgradableSpecification;
_configService = configService;
_logger = logger;
}
@@ -34,14 +30,6 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
return Decision.Accept();
}
var downloadPropersAndRepacks = _configService.DownloadPropersAndRepacks;
if (downloadPropersAndRepacks == ProperDownloadTypes.DoNotPrefer)
{
_logger.Debug("Repacks are not preferred, skipping check");
return Decision.Accept();
}
foreach (var book in subject.Books)
{
var releaseGroup = subject.ParsedBookInfo.ReleaseGroup;
@@ -51,12 +39,6 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
{
if (_upgradableSpecification.IsRevisionUpgrade(file.Quality, subject.ParsedBookInfo.Quality))
{
if (downloadPropersAndRepacks == ProperDownloadTypes.DoNotUpgrade)
{
_logger.Debug("Auto downloading of repacks is disabled");
return Decision.Reject("Repack downloading is disabled");
}
var fileReleaseGroup = file.ReleaseGroup;
if (fileReleaseGroup.IsNullOrWhiteSpace())

View File

@@ -125,22 +125,22 @@ namespace NzbDrone.Core.Download.Clients.Flood
item.RemainingTime = TimeSpan.FromSeconds(properties.Eta);
}
if (properties.Status.Contains("seeding") || properties.Status.Contains("complete"))
{
item.Status = DownloadItemStatus.Completed;
}
else if (properties.Status.Contains("stopped"))
{
item.Status = DownloadItemStatus.Paused;
}
else if (properties.Status.Contains("error"))
if (properties.Status.Contains("error"))
{
item.Status = DownloadItemStatus.Warning;
}
else if (properties.Status.Contains("seeding") || properties.Status.Contains("complete"))
{
item.Status = DownloadItemStatus.Completed;
}
else if (properties.Status.Contains("downloading"))
{
item.Status = DownloadItemStatus.Downloading;
}
else if (properties.Status.Contains("stopped"))
{
item.Status = DownloadItemStatus.Paused;
}
if (item.Status == DownloadItemStatus.Completed)
{

View File

@@ -88,8 +88,6 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
if (!addHasSetShareLimits && setShareLimits)
{
Proxy.SetTorrentSeedingConfiguration(hash.ToLower(), remoteBook.SeedConfiguration, Settings);
try
{
Proxy.SetTorrentSeedingConfiguration(hash.ToLower(), remoteBook.SeedConfiguration, Settings);
@@ -288,8 +286,7 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
break;
case "forcedDL": // torrent is being downloaded, and was forced started
case "forcedMetaDL": // torrent metadata is being forcibly downloaded
case "forcedDL": //torrent is being downloaded, and was forced started
case "moving": // torrent is being moved from a folder
case "downloading": // torrent is being downloaded and data is being transferred
item.Status = DownloadItemStatus.Downloading;

View File

@@ -142,8 +142,20 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
var request = BuildRequest(settings).Resource("/api/v2/torrents/add")
.Post()
.AddFormParameter("urls", torrentUrl);
if (settings.MusicCategory.IsNotNullOrWhiteSpace())
{
request.AddFormParameter("category", settings.MusicCategory);
}
AddTorrentDownloadFormParameters(request, settings);
// Note: ForceStart is handled by separate api call
if ((QBittorrentState)settings.InitialState == QBittorrentState.Start)
{
request.AddFormParameter("paused", false);
}
else if ((QBittorrentState)settings.InitialState == QBittorrentState.Pause)
{
request.AddFormParameter("paused", true);
}
if (seedConfiguration != null)
{
@@ -165,7 +177,20 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
.Post()
.AddFormUpload("torrents", fileName, fileContent);
AddTorrentDownloadFormParameters(request, settings);
if (settings.MusicCategory.IsNotNullOrWhiteSpace())
{
request.AddFormParameter("category", settings.MusicCategory);
}
// Note: ForceStart is handled by separate api call
if ((QBittorrentState)settings.InitialState == QBittorrentState.Start)
{
request.AddFormParameter("paused", false);
}
else if ((QBittorrentState)settings.InitialState == QBittorrentState.Pause)
{
request.AddFormParameter("paused", true);
}
if (seedConfiguration != null)
{
@@ -234,34 +259,6 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
}
}
private void AddTorrentDownloadFormParameters(HttpRequestBuilder request, QBittorrentSettings settings)
{
if (settings.MusicCategory.IsNotNullOrWhiteSpace())
{
request.AddFormParameter("category", settings.MusicCategory);
}
// Note: ForceStart is handled by separate api call
if ((QBittorrentState)settings.InitialState == QBittorrentState.Start)
{
request.AddFormParameter("paused", false);
}
else if ((QBittorrentState)settings.InitialState == QBittorrentState.Pause)
{
request.AddFormParameter("paused", true);
}
if (settings.SequentialOrder)
{
request.AddFormParameter("sequentialDownload", true);
}
if (settings.FirstAndLast)
{
request.AddFormParameter("firstLastPiecePrio", true);
}
}
public void SetTorrentSeedingConfiguration(string hash, TorrentSeedConfiguration seedConfiguration, QBittorrentSettings settings)
{
var request = BuildRequest(settings).Resource("/api/v2/torrents/setShareLimits")

View File

@@ -63,12 +63,6 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
[FieldDefinition(10, Label = "Initial State", Type = FieldType.Select, SelectOptions = typeof(QBittorrentState), HelpText = "Initial state for torrents added to qBittorrent. Note that Forced Torrents do not abide by seed restrictions")]
public int InitialState { get; set; }
[FieldDefinition(11, Label = "Sequential Order", Type = FieldType.Checkbox, HelpText = "Download in sequential order (qBittorrent 4.1.0+)")]
public bool SequentialOrder { get; set; }
[FieldDefinition(12, Label = "First and Last First", Type = FieldType.Checkbox, HelpText = "Download first and last pieces first (qBittorrent 4.1.0+)")]
public bool FirstAndLast { get; set; }
public NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));

View File

@@ -14,7 +14,7 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
public double Progress { get; set; } // Torrent progress (%/100)
public BigInteger Eta { get; set; } // Torrent ETA (seconds) (QBit contains a bug exceeding ulong limits)
public BigInteger Eta { get; set; } // Torrent ETA (seconds)
public string State { get; set; } // Torrent state. See possible values here below

View File

@@ -1,4 +1,4 @@
using System.Collections.Generic;
using System.Collections.Generic;
using Newtonsoft.Json;
using NzbDrone.Common.Disk;
using NzbDrone.Core.Download.Clients.Sabnzbd.JsonConverters;
@@ -7,14 +7,10 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
{
public class SabnzbdConfig
{
public SabnzbdConfig()
{
Categories = new List<SabnzbdCategory>();
Servers = new List<object>();
}
public SabnzbdConfigMisc Misc { get; set; }
public List<SabnzbdCategory> Categories { get; set; }
public List<object> Servers { get; set; }
}

View File

@@ -115,7 +115,7 @@ namespace NzbDrone.Core.Download.Clients.RTorrent
public override string Name => "rTorrent";
public override ProviderMessage Message => new ProviderMessage($"rTorrent will not pause torrents when they meet the seed criteria. Readarr will handle automatic removal of torrents based on the current seed criteria in Settings->Indexers only when Remove Completed is enabled. After importing it will also set \"{_imported_view}\" as an rTorrent view, which can be used in rTorrent scripts to customize behavior.", ProviderMessageType.Info);
public override ProviderMessage Message => new ProviderMessage($"Readarr will handle automatic removal of torrents based on the current seed criteria in Settings->Indexers. After importing it will also set \"{_imported_view}\" as an rTorrent view, which can be used in rTorrent scripts to customize behavior.", ProviderMessageType.Info);
public override IEnumerable<DownloadClientItem> GetItems()
{

View File

@@ -37,10 +37,10 @@ namespace NzbDrone.Core.Download.Clients.RTorrent
[FieldDefinition(1, Label = "Port", Type = FieldType.Textbox)]
public int Port { get; set; }
[FieldDefinition(2, Label = "Use SSL", Type = FieldType.Checkbox, HelpText = "Use secure connection when connecting to rTorrent")]
[FieldDefinition(2, Label = "Use SSL", Type = FieldType.Checkbox, HelpText = "Use secure connection when connecting to ruTorrent")]
public bool UseSsl { get; set; }
[FieldDefinition(3, Label = "Url Path", Type = FieldType.Textbox, HelpText = "Path to the XMLRPC endpoint, see http(s)://[host]:[port]/[urlPath]. This is usually RPC2 or [path to ruTorrent]/plugins/rpc/rpc.php when using ruTorrent.")]
[FieldDefinition(3, Label = "Url Path", Type = FieldType.Textbox, HelpText = "Path to the XMLRPC endpoint, see http(s)://[host]:[port]/[urlPath]. When using ruTorrent this usually is RPC2 or (path to ruTorrent)/plugins/rpc/rpc.php")]
public string UrlBase { get; set; }
[FieldDefinition(4, Label = "Username", Type = FieldType.Textbox, Privacy = PrivacyLevel.UserName)]
@@ -64,7 +64,7 @@ namespace NzbDrone.Core.Download.Clients.RTorrent
[FieldDefinition(10, Label = "Older Priority", Type = FieldType.Select, SelectOptions = typeof(RTorrentPriority), HelpText = "Priority to use when grabbing books released over 14 days ago")]
public int OlderTvPriority { get; set; }
[FieldDefinition(11, Label = "Add Stopped", Type = FieldType.Checkbox, HelpText = "Enabling will add torrents and magnets to rTorrent in a stopped state. This may break magnet files.")]
[FieldDefinition(11, Label = "Add Stopped", Type = FieldType.Checkbox, HelpText = "Enabling will add torrents and magnets to ruTorrent in a stopped state")]
public bool AddStopped { get; set; }
public NzbDroneValidationResult Validate()

View File

@@ -164,14 +164,14 @@ namespace NzbDrone.Core.Download
}
else
{
_logger.ForDebugEvent()
_logger.Debug()
.Message("No books were just imported, but all books were previously imported, possible issue with download history.")
.Property("AuthorId", trackedDownload.RemoteBook.Author.Id)
.Property("DownloadId", trackedDownload.DownloadItem.DownloadId)
.Property("Title", trackedDownload.DownloadItem.Title)
.Property("Path", trackedDownload.DownloadItem.OutputPath.ToString())
.WriteSentryWarn("DownloadHistoryIncomplete")
.Log();
.Write();
}
trackedDownload.State = TrackedDownloadState.Imported;

View File

@@ -1,6 +1,5 @@
using System.Collections.Generic;
using NzbDrone.Common.Messaging;
using NzbDrone.Core.Download.TrackedDownloads;
using NzbDrone.Core.Qualities;
namespace NzbDrone.Core.Download
@@ -14,6 +13,5 @@ namespace NzbDrone.Core.Download
public DownloadClientItemClientInfo DownloadClientInfo { get; set; }
public string DownloadId { get; set; }
public string Message { get; set; }
public TrackedDownload TrackedDownload { get; set; }
}
}

View File

@@ -110,7 +110,7 @@ namespace NzbDrone.Core.Download
bookGrabbedEvent.DownloadId = downloadClientId;
}
_logger.ProgressInfo("Report sent to {0} from indexer {1}. {2}", downloadClient.Definition.Name, remoteBook.Release.Indexer, downloadTitle);
_logger.ProgressInfo("Report sent to {0}. {1}", downloadClient.Definition.Name, downloadTitle);
_eventAggregator.PublishEvent(bookGrabbedEvent);
}
}

View File

@@ -42,7 +42,6 @@ namespace NzbDrone.Core.Download
SourceTitle = trackedDownload.DownloadItem.Title,
DownloadClientInfo = trackedDownload.DownloadItem.DownloadClientInfo,
DownloadId = trackedDownload.DownloadItem.DownloadId,
TrackedDownload = trackedDownload,
Message = "Manually ignored"
};

View File

@@ -52,7 +52,7 @@ namespace NzbDrone.Core.HealthCheck
.AddQueryParam("version", BuildInfo.Version)
.AddQueryParam("os", OsInfo.Os.ToString().ToLowerInvariant())
.AddQueryParam("arch", RuntimeInformation.OSArchitecture)
.AddQueryParam("runtime", "netcore")
.AddQueryParam("runtime", PlatformInfo.Platform.ToString().ToLowerInvariant())
.AddQueryParam("branch", _configFileProvider.Branch)
.Build();
try

View File

@@ -200,7 +200,6 @@ namespace NzbDrone.Core.History
};
history.Data.Add("StatusMessages", message.TrackedDownload.StatusMessages.ToJson());
history.Data.Add("ReleaseGroup", message.TrackedDownload?.RemoteBook?.ParsedBookInfo?.ReleaseGroup);
_historyRepository.Insert(history);
}
}
@@ -236,7 +235,6 @@ namespace NzbDrone.Core.History
history.Data.Add("ImportedPath", message.ImportedBook.Path);
history.Data.Add("DownloadClient", message.DownloadClientInfo?.Type);
history.Data.Add("DownloadClientName", message.DownloadClientInfo?.Name);
history.Data.Add("ReleaseGroup", message.BookInfo.ReleaseGroup);
_historyRepository.Insert(history);
}
@@ -288,7 +286,6 @@ namespace NzbDrone.Core.History
};
history.Data.Add("Reason", message.Reason.ToString());
history.Data.Add("ReleaseGroup", message.BookFile.ReleaseGroup);
_historyRepository.Insert(history);
}
@@ -310,7 +307,6 @@ namespace NzbDrone.Core.History
history.Data.Add("SourcePath", sourcePath);
history.Data.Add("Path", path);
history.Data.Add("ReleaseGroup", message.BookFile.ReleaseGroup);
_historyRepository.Insert(history);
}
@@ -362,7 +358,6 @@ namespace NzbDrone.Core.History
};
history.Data.Add("DownloadClient", message.DownloadClientInfo.Name);
history.Data.Add("ReleaseGroup", message.TrackedDownload?.RemoteBook?.ParsedBookInfo?.ReleaseGroup);
history.Data.Add("Message", message.Message);
historyToAdd.Add(history);

View File

@@ -7,22 +7,22 @@ namespace NzbDrone.Core.IndexerSearch
{
public class AuthorSearchService : IExecute<AuthorSearchCommand>
{
private readonly ISearchForReleases _releaseSearchService;
private readonly ISearchForNzb _nzbSearchService;
private readonly IProcessDownloadDecisions _processDownloadDecisions;
private readonly Logger _logger;
public AuthorSearchService(ISearchForReleases releaseSearchService,
public AuthorSearchService(ISearchForNzb nzbSearchService,
IProcessDownloadDecisions processDownloadDecisions,
Logger logger)
{
_releaseSearchService = releaseSearchService;
_nzbSearchService = nzbSearchService;
_processDownloadDecisions = processDownloadDecisions;
_logger = logger;
}
public void Execute(AuthorSearchCommand message)
{
var decisions = _releaseSearchService.AuthorSearch(message.AuthorId, false, message.Trigger == CommandTrigger.Manual, false);
var decisions = _nzbSearchService.AuthorSearch(message.AuthorId, false, message.Trigger == CommandTrigger.Manual, false);
var processed = _processDownloadDecisions.ProcessDecisions(decisions);
_logger.ProgressInfo("Author search completed. {0} reports downloaded.", processed.Grabbed.Count);

View File

@@ -17,21 +17,21 @@ namespace NzbDrone.Core.IndexerSearch
IExecute<MissingBookSearchCommand>,
IExecute<CutoffUnmetBookSearchCommand>
{
private readonly ISearchForReleases _releaseSearchService;
private readonly ISearchForNzb _nzbSearchService;
private readonly IBookService _bookService;
private readonly IBookCutoffService _bookCutoffService;
private readonly IQueueService _queueService;
private readonly IProcessDownloadDecisions _processDownloadDecisions;
private readonly Logger _logger;
public BookSearchService(ISearchForReleases releaseSearchService,
public BookSearchService(ISearchForNzb nzbSearchService,
IBookService bookService,
IBookCutoffService bookCutoffService,
IQueueService queueService,
IProcessDownloadDecisions processDownloadDecisions,
Logger logger)
{
_releaseSearchService = releaseSearchService;
_nzbSearchService = nzbSearchService;
_bookService = bookService;
_bookCutoffService = bookCutoffService;
_queueService = queueService;
@@ -47,7 +47,7 @@ namespace NzbDrone.Core.IndexerSearch
foreach (var book in books)
{
List<DownloadDecision> decisions;
decisions = _releaseSearchService.BookSearch(book.Id, false, userInvokedSearch, false);
decisions = _nzbSearchService.BookSearch(book.Id, false, userInvokedSearch, false);
var processed = _processDownloadDecisions.ProcessDecisions(decisions);
downloadedCount += processed.Grabbed.Count;
@@ -61,7 +61,7 @@ namespace NzbDrone.Core.IndexerSearch
foreach (var bookId in message.BookIds)
{
var decisions =
_releaseSearchService.BookSearch(bookId, false, message.Trigger == CommandTrigger.Manual, false);
_nzbSearchService.BookSearch(bookId, false, message.Trigger == CommandTrigger.Manual, false);
var processed = _processDownloadDecisions.ProcessDecisions(decisions);
_logger.ProgressInfo("Book search completed. {0} reports downloaded.", processed.Grabbed.Count);

View File

@@ -14,13 +14,13 @@ using NzbDrone.Core.Parser.Model;
namespace NzbDrone.Core.IndexerSearch
{
public interface ISearchForReleases
public interface ISearchForNzb
{
List<DownloadDecision> BookSearch(int bookId, bool missingOnly, bool userInvokedSearch, bool interactiveSearch);
List<DownloadDecision> AuthorSearch(int authorId, bool missingOnly, bool userInvokedSearch, bool interactiveSearch);
}
public class ReleaseSearchService : ISearchForReleases
public class NzbSearchService : ISearchForNzb
{
private readonly IIndexerFactory _indexerFactory;
private readonly IBookService _bookService;
@@ -28,7 +28,7 @@ namespace NzbDrone.Core.IndexerSearch
private readonly IMakeDownloadDecision _makeDownloadDecision;
private readonly Logger _logger;
public ReleaseSearchService(IIndexerFactory indexerFactory,
public NzbSearchService(IIndexerFactory indexerFactory,
IBookService bookService,
IAuthorService authorService,
IMakeDownloadDecision makeDownloadDecision,

View File

@@ -0,0 +1,17 @@
using NzbDrone.Common.Messaging;
using NzbDrone.Core.ThingiProvider;
namespace NzbDrone.Core.Indexers
{
public class IndexerSettingUpdatedEvent : IEvent
{
public string IndexerName { get; private set; }
public IProviderConfig IndexerSetting { get; private set; }
public IndexerSettingUpdatedEvent(string indexerName, IProviderConfig indexerSetting)
{
IndexerName = indexerName;
IndexerSetting = indexerSetting;
}
}
}

View File

@@ -4,7 +4,6 @@ using NzbDrone.Core.Datastore;
using NzbDrone.Core.Download.Clients;
using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.ThingiProvider.Events;
namespace NzbDrone.Core.Indexers
{
@@ -14,7 +13,7 @@ namespace NzbDrone.Core.Indexers
TorrentSeedConfiguration GetSeedConfiguration(int indexerId, bool fullSeason);
}
public class SeedConfigProvider : ISeedConfigProvider, IHandle<ProviderUpdatedEvent<IIndexer>>
public class SeedConfigProvider : ISeedConfigProvider, IHandle<IndexerSettingUpdatedEvent>
{
private readonly IIndexerFactory _indexerFactory;
private readonly ICached<SeedCriteriaSettings> _cache;
@@ -83,7 +82,7 @@ namespace NzbDrone.Core.Indexers
}
}
public void Handle(ProviderUpdatedEvent<IIndexer> message)
public void Handle(IndexerSettingUpdatedEvent message)
{
_cache.Clear();
}

View File

@@ -50,7 +50,7 @@ namespace NzbDrone.Core.Indexers
{
private static readonly SeedCriteriaSettingsValidator Validator = new SeedCriteriaSettingsValidator();
[FieldDefinition(0, Type = FieldType.Textbox, Label = "Seed Ratio", HelpText = "The ratio a torrent should reach before stopping, empty is download client's default. Ratio should be at least 1.0 and follow the indexers rules")]
[FieldDefinition(0, Type = FieldType.Textbox, Label = "Seed Ratio", HelpText = "The ratio a torrent should reach before stopping, empty is download client's default", Advanced = true)]
public double? SeedRatio { get; set; }
[FieldDefinition(1, Type = FieldType.Textbox, Label = "Seed Time", Unit = "minutes", HelpText = "The time a torrent should be seeded before stopping, empty is download client's default", Advanced = true)]

View File

@@ -117,6 +117,7 @@ namespace NzbDrone.Core.Instrumentation
syslogTarget.MessageSend.Protocol = ProtocolType.Udp;
syslogTarget.MessageSend.Udp.Port = syslogPort;
syslogTarget.MessageSend.Udp.Server = syslogServer;
syslogTarget.MessageSend.Udp.ReconnectInterval = 500;
syslogTarget.MessageCreation.Rfc = RfcNumber.Rfc5424;
syslogTarget.MessageCreation.Rfc5424.AppName = _configFileProvider.InstanceName;

View File

@@ -557,6 +557,5 @@
"RestartRequiredHelpTextWarning": "يتطلب إعادة التشغيل ليصبح ساري المفعول",
"AddList": "اضف قائمة",
"RenameFiles": "إعادة تسمية الملفات",
"Test": "اختبار",
"ManualImportSelectEdition": "استيراد يدوي - حدد فيلم"
"Test": "اختبار"
}

View File

@@ -556,6 +556,5 @@
"RestartRequiredHelpTextWarning": "Изисква рестартиране, за да влезе в сила",
"Test": "Тест",
"AddList": "Добавяне на списък",
"RenameFiles": "Преименувайте файловете",
"ManualImportSelectEdition": "Ръчно импортиране - Изберете филм"
"RenameFiles": "Преименувайте файловете"
}

View File

@@ -51,7 +51,7 @@
"Cancel": "zrušení",
"CancelMessageText": "Opravdu chcete zrušit tento nevyřízený úkol?",
"CertificateValidation": "Ověření certifikátu",
"CertificateValidationHelpText": "Změňte přísnost ověřování certifikátů HTTPS. Neměňte, pokud nerozumíte rizikům.",
"CertificateValidationHelpText": "Změňte, jak přísné je ověření certifikace HTTPS",
"ChangeFileDate": "Změnit datum souboru",
"ChangeHasNotBeenSavedYet": "Změna ještě nebyla uložena",
"ChmodFolder": "Složka chmod",
@@ -556,6 +556,5 @@
"RestartRequiredHelpTextWarning": "Vyžaduje restart, aby se projevilo",
"RenameFiles": "Přejmenovat soubory",
"Test": "Test",
"AddList": "Přidat seznam",
"ManualImportSelectEdition": "Ruční import - vyberte Film"
"AddList": "Přidat seznam"
}

View File

@@ -556,6 +556,5 @@
"RestartRequiredHelpTextWarning": "Kræver genstart for at træde i kraft",
"AddList": "Tilføj Liste",
"Test": "Prøve",
"RenameFiles": "Omdøb filer",
"ManualImportSelectEdition": "Manuel import - Vælg film"
"RenameFiles": "Omdøb filer"
}

View File

@@ -44,7 +44,7 @@
"Cancel": "Abbrechen",
"CancelMessageText": "Diese laufende Aufgabe wirklich abbrechen?",
"CertificateValidation": "Zertifikat Validierung",
"CertificateValidationHelpText": "Ändere wie streng die Validierung der HTTPS-Zertifizierung ist. Ändern Sie nicht wenn Ihnen die Risiken nicht bewusst sind.",
"CertificateValidationHelpText": "Ändere wie streng die Validierung der HTTPS-Zertifizierung ist. Nicht anpassen, außer du kennst das Risiko.",
"ChangeFileDate": "Erstelldatum der Datei anpassen",
"ChangeHasNotBeenSavedYet": "Änderung wurde noch nicht gespeichert",
"ChmodFolder": "chmod Ordner",
@@ -92,8 +92,8 @@
"DeleteNotificationMessageText": "Benachrichtigung '{0}' wirklich löschen?",
"DeleteQualityProfile": "Qualitätsdefinition löschen",
"DeleteQualityProfileMessageText": "Qualitätsprofil '{0}' wirklich löschen?",
"DeleteReleaseProfile": "Release-Profil löschen",
"DeleteReleaseProfileMessageText": "Bist du sicher, dass du dieses Release-Profil löschen willst?",
"DeleteReleaseProfile": "Verzögerungsprofil löschen",
"DeleteReleaseProfileMessageText": "Bist du sicher, dass du dieses Verzögerungs-Profil löschen willst?",
"DeleteRootFolderMessageText": "Indexer '{0}' wirklich löschen?",
"DeleteSelectedBookFiles": "Ausgewählte Filmdateien löschen",
"DeleteSelectedBookFilesMessageText": "Ausgewählte Filme wirklich löschen?",
@@ -172,7 +172,7 @@
"ImportedTo": "Importiert nach",
"Importing": "Importiere",
"IncludeHealthWarningsHelpText": "Zustandswarnung",
"IncludeUnknownAuthorItemsHelpText": "Einträge ohne eine Zuordnung in der Warteschlange anzeigen. Dies könnten gelöschte Autoren, Bücher oder alles andere mit Readarrs Downloadkategorie sein",
"IncludeUnknownAuthorItemsHelpText": "Einträge ohne eine Zuordnung in der Warteschlange anzeigen. Dies könnten gelöschte Filme oder alles andere mit Radarrs Downloadkategorie sein",
"IncludeUnmonitored": "Nicht beobachtete einbeziehen",
"Indexer": "Indexer",
"IndexerPriority": "Priorität",
@@ -291,7 +291,7 @@
"RemoveFromQueue": "Aus der Warteschlage entfernen",
"RemoveHelpTextWarning": "Dies wird den Download und alle bereits heruntergeladenen Dateien aus dem Downloader entfernen.",
"RemoveSelected": "Auswahl entfernen",
"RemoveSelectedMessageText": "Sind sie sicher, dass die ausgewählten Einträge aus der Sperrliste entfernt werden sollen?",
"RemoveSelectedMessageText": "Bist du icher, dass du die ausgewählten Einträge aus der Sperrliste entfernen willst?",
"RemoveTagExistingTag": "Vorhandener Tag",
"RemoveTagRemovingTag": "Tag entfernen",
"RemovedFromTaskQueue": "Aus der Aufgabenwarteschlage entfernt",
@@ -301,7 +301,7 @@
"RequiredHelpText": "Das Release mus mindesten eines der Begriffe beinhalten ( Groß-/Kleinschreibung wird nicht beachtet )",
"RequiredPlaceHolder": "Neue Beschränkung hinzufügen",
"RescanAfterRefreshHelpTextWarning": "Wenn nicht \"Immer (Always)\" ausgewählt wird, werden Dateiänderungen nicht automatisch erkannt",
"RescanAuthorFolderAfterRefresh": "Nach dem Aktualisieren den Autorordner neu scannen",
"RescanAuthorFolderAfterRefresh": "Nach dem aktualisieren den Filmordner neu scannen",
"Reset": "Zurücksetzen",
"ResetAPIKey": "API-Schlüssel zurücksetzen",
"ResetAPIKeyMessageText": "Bist du sicher, dass du den API-Schlüssel zurücksetzen willst?",
@@ -349,7 +349,7 @@
"ShownAboveEachColumnWhenWeekIsTheActiveView": "Wird in der Wochenansicht über jeder Spalte angezeigt",
"Size": " Größe",
"SkipFreeSpaceCheck": "Pürfung des freien Speichers überspringen",
"SkipFreeSpaceCheckWhenImportingHelpText": "Aktiviere diese Option, wenn es Readarr nicht möglich ist, den freien Speicherplatz des Stammverzeichnises für Autoren zu erkennen",
"SkipFreeSpaceCheckWhenImportingHelpText": "Aktiviere dies wenn es nicht möglich ist, den freien Speicherplatz vom Stammverzeichnis zu ermitteln",
"SorryThatAuthorCannotBeFound": "Schade, dieser Film kann nicht gefunden werden.",
"SorryThatBookCannotBeFound": "Schade, dieser Film kann nicht gefunden werden.",
"Source": "Quelle",
@@ -426,7 +426,7 @@
"UnmonitoredHelpText": "Nicht beobachtete Filme im iCal-Feed einschließen",
"UpdateAll": "Alle aktualisieren",
"UpdateAutomaticallyHelpText": "Updates automatisch herunteraden und installieren. Es kann weiterhin unter \"System -> Updates\" ein manuelles Update angestoßen werden",
"UpdateMechanismHelpText": "Benutze Readarr's Built-In Updater oder ein Script",
"UpdateMechanismHelpText": "Benutze den Built-In Updater oder ein Script",
"UpdateScriptPathHelpText": "Pfad zu einem benutzerdefinierten Skript, das ein extrahiertes Update-Paket übernimmt und den Rest des Update-Prozesses abwickelt",
"Updates": "Updates",
"UpgradeAllowedHelpText": "Wenn deaktiviert wird die Qualität nicht verbessert",
@@ -546,7 +546,7 @@
"ImportListSettings": "Allgemeine Einstellungen der Importliste",
"ImportListSpecificSettings": "Listenspezifische Einstellungen importieren",
"IndexerLongTermStatusCheckSingleClientMessage": "Indexer wegen über 6 Stunden langen bestehenden Fehlern nicht verfügbar: {0}",
"IndexerPriorityHelpText": "Indexer Priorität von 1 (höchste) bis 50 (niedrigste). Standard: 25. Wird beim Holen von Veröffentlichungen als Tiebreaker für ansonsten gleiche Veröffentlichungen verwendet, Readarr benützt weiterhin alle aktivierten Indexer für RSS-Synchronisierung und -Suche.",
"IndexerPriorityHelpText": "Indexer Priorität von 1 (höchste) bis 50 (niedrigste). Standard: 25.",
"IndexerRssHealthCheckNoAvailableIndexers": "Alle RSS-fähigen Indexer sind aufgrund der kürzlichen Indexerfehler vorübergehend nicht verfügbar",
"DiscNumber": "Plattennummer",
"Lists": "Listen",
@@ -702,7 +702,7 @@
"ImportListStatusCheckSingleClientMessage": "Listen aufgrund von Fehlern nicht verfügbar: {0}",
"ImportMechanismHealthCheckMessage": "Aktiviere die Verarbeitung der abgeschlossenen Downloads",
"IndexerRssHealthCheckNoIndexers": "Da keine Indexer mit aktivierter RSS-Synchronisierung aktiviert sind, erfasst Readarr neue Erscheinungen nicht automatisch",
"IndexerSearchCheckNoInteractiveMessage": "Keine Indexer mit interaktiver Suche verfügbar, Readarr liefert keine interaktiven Suchergebnisse",
"IndexerSearchCheckNoInteractiveMessage": "Keine Indexer mit interaktiver Suche aktiviert, Readarr liefert keine interaktiven Suchergebnisse",
"IndexerStatusCheckSingleClientMessage": "Indexer aufgrund von Fehlern nicht verfügbar: {0}",
"ChownGroup": "chown Gruppe",
"AllowFingerprintingHelpText": "Benutze Fingerabdrücke um die Genauigkeit der Buch Übereinstimmungen zu verbessern",
@@ -713,7 +713,7 @@
"PathHelpText": "Stammordner für die Musikbibliothek",
"ProxyCheckBadRequestMessage": "Proxy konnte nicht getestet werden. StatusCode: {0}",
"ProxyCheckFailedToTestMessage": "Proxy konnte nicht getestet werden: {0}",
"Queued": "In der Warteschlange",
"Queued": "Eingereiht",
"RefreshAndScan": "Aktualisieren",
"SettingsRemotePathMappingRemotePathHelpText": "Root-Pfad zum Verzeichnis, auf das der Download-Client zugreift",
"Yesterday": "Gestern",
@@ -725,7 +725,7 @@
"RemotePathMappingCheckDockerFolderMissing": "Docker erkannt; Downloader {0} speichert Downloads in {1}, aber dieser Ordner scheint nicht im Container zu existieren. Überprüfe die Remote-Pfadzuordnungen und die Container Volume Einstellungen.",
"RemotePathMappingCheckFilesGenericPermissions": "Downloader {0} meldet Dateien in {1}, aber Radarr kann dieses Verzeichnis nicht sehen.Möglicherweise müssen die Verzeichnisreche angepasst werden.",
"RemotePathMappingCheckFolderPermissions": "Radarr kann das Downloadverzeichnis sehen, aber nicht verarbeiten {0}. Möglicherwiese ein Rechteproblem.",
"RemotePathMappingCheckGenericPermissions": "Downloader {0} speichert Downloads in {1}, aber Readarr kann dieses Verzeichnis nicht sehen. Möglicherweise müssen die Verzeichnisrechte angepasst werden.",
"RemotePathMappingCheckGenericPermissions": "Downloader {0} speichert Downloads in {1}, aber Radarr kann dieses Verzeichnis nicht sehen. Möchlicherweise müssen die Verzeichnisrechte angepasst werden.",
"RemotePathMappingCheckLocalWrongOSPath": "Downloader {0} speichert Downloads in {1}, aber dies ist kein valider {2} Pfad. Überprüfe die Downloader Einstellungen.",
"Monitor": "Beobachten",
"MusicBrainzAuthorID": "MusicBranz Künstler Id",
@@ -780,102 +780,11 @@
"InstanceNameHelpText": "Instanzname im Browser-Tab und für Syslog-Anwendungsname",
"RestartRequiredHelpTextWarning": "Erfordert einen Neustart",
"UseCalibreContentServer": "Calibre-Content-Server",
"DataExistingBooks": "Beobachte Bücher die Dateien haben oder noch nicht veröffentlicht wurden",
"DataFirstBook": "Beobachte das erste Buch. Alle anderen Bücher werden ignoriert",
"DataFuturebooks": "Überwachung von Büchern die noch nicht veröffentlicht wurden",
"DataMissingBooks": "Beobachte Bücher, die noch keine Dateien haben oder noch nicht veröffentlicht wurden",
"DataExistingBooks": "Beobachte Alben die Dateien haben oder noch nicht veröffentlicht wurden",
"DataFirstBook": "Beobachte die ersten Alben. Alle anderen Alben werden ignoriert",
"DataFuturebooks": "Überwachung von Alben die noch nicht veröffentlicht wurden",
"DataMissingBooks": "Beobachte Alben, die noch keine Dateien haben oder noch nicht veröffentlicht wurden",
"Test": "Testen",
"DataNone": "Es werden keine Bücher beobachtet",
"RenameFiles": "Dateien umbenennen",
"LoadingEditionsFailed": "Das Laden der Ausgaben ist fehlgeschlagen",
"MissingBooksAuthorMonitored": "Fehlende Bücher (Autoren überwacht)",
"MonitorBook": "Buch überwachen",
"MinimumPages": "Mindestseiten",
"MassBookSearch": "Massensuche nach Büchern",
"MediaManagementSettingsSummary": "Namensgebung, Dateimanagement-Einstellungen und Root-Ordner",
"MinimumPopularity": "Mindestpolularität",
"MinPagesHelpText": "Bücher mit weniger Seiten als dieses ignorieren",
"MinPopularityHelpText": "Popularität ist Durchschnittsbewertung * Anzahl der Stimmen",
"MissingBooks": "Fehlende Bücher",
"MonitorAuthor": "Autor überwachen",
"MissingBooksAuthorNotMonitored": "Fehlende Bücher (Autor nicht überwacht)",
"ConvertToFormat": "In Format umwandeln",
"EditList": "Liste bearbeiten",
"ManualImportSelectEdition": "Manueller Import - Ausgabe auswählen",
"MetadataSettingsSummary": "Metadaten-Dateien erstellen, wenn Bücher importiert oder Autoren aktualisiert werden",
"DataAllBooks": "Alle Bücher überwachen",
"DataLatestBook": "Die neusten und zukünftigen Bücher überwachen",
"Database": "Datenbank",
"DataListMonitorAll": "Autoren und alle Bücher für jeden Autor werden auf der Import-Liste miteinbezogen",
"DataListMonitorNone": "Autoren oder Bücher nicht überwachen",
"DataListMonitorSpecificBook": "Autoren überwachen aber nur Bücher überwachen, welche explizit in der Liste miteinbezogen wurden",
"DataNewAllBooks": "Alle neuen Bücher überwachen",
"DataNewBooks": "Alle neuen Bücher, welche nach dem neusten existierenden Buch veröffentlicht werden, überwachen",
"DataNewNone": "Keine neuen Bücher überwachen",
"MassBookSearchWarning": "Sind Sie sicher, dass Sie eine Massensuche für {0} Bücher starten wollen?",
"NoTagsHaveBeenAddedYet": "Es wurden bisher noch keine Tags hinzugefügt. Fügen Sie Tags hinzu um Autoren mit Verzögerunsprofilen, Einschränkungen oder Benachrichtigungen zu verknüpfen. Klicken Sie {0} um mehr über Tags in Readarr herauszufinden.",
"OutputFormatHelpText": "Optional kann Calibre aufgefordert werden, beim Import in andere Formate zu konvertieren. Kommagetrennte Liste.",
"UsernameHelpText": "Calibre Inhaltsserver Benutzername",
"MonitorExistingBooks": "Vorhandene Bücher überwachen",
"MonitoringOptionsHelpText": "Welche Bücher sollen überwacht werden nachdem der Autor hinzugefügt wurde (einmalige Anpassung)",
"MonitorNewBooks": "Neue Bücher überwachen",
"MonitorNewItems": "Neue Bücher überwachen",
"MonitorNewItemsHelpText": "Welche neuen Bücher sollen überwacht werden",
"NewBooks": "Neue Bücher",
"NoHistoryBlocklist": "Keine History Blockliste",
"NoName": "Namen nicht anzeigen",
"OnAuthorDelete": "Beim Löschen eines Autors",
"OnAuthorDeleteHelpText": "Beim Löschen eines Autors",
"OnBookDelete": "Beim Löschen eines Buches",
"OnBookRetagHelpText": "Bei neu markieren eines Buches",
"RefreshBook": "Buch aktualisieren",
"SearchBoxPlaceHolder": "z.B Krieg und Frieden, goodreads:656, isbn:067003469X, asin:B00JCDK5ME",
"SendMetadataToCalibre": "Metadaten an Calibre senden",
"SeriesTotal": "Serie ({0})",
"SetReadarrTags": "Setze Readarr Tags",
"ShouldMonitorExisting": "Existierende Bücher überwachen",
"ShouldMonitorHelpText": "Neue Autoren und Bücher aus dieser Liste überwachen",
"ShouldSearchHelpText": "Dursuche Indexer nach neu hinzugefügten Einträgen. Vorsichtig benutzen bei großen Listen.",
"SkipSecondarySeriesBooks": "Überspringe Bücher von Sekundarserien",
"SpecificBook": "Bestimmtes Buch",
"TheFollowingFilesWillBeDeleted": "Die folgenden Dateien werden gelöscht:",
"TooManyBooks": "Fehlende oder zu viele Bücher? Ändern oder erstellen Sie ein neues",
"TrackTitle": "Track Titel",
"UseSslHelpText": "Benutze SSL um mit dem Calibre Inhaltsserver zu verbinden",
"WriteMetadataTags": "Schreibe Metadaten Tags",
"WriteTagsAll": "Alle Dateien; nur erster Import",
"WriteTagsNew": "Nur für neue Downloads",
"WriteTagsSync": "Alle Dateien; mit Goodreads synchronisiert bleiben",
"SearchForAllCutoffUnmetBooks": "Suche nach allen abgeschnittenen unerfüllten Büchern",
"OnBookTagUpdate": "Bei Update eines Buch Tags",
"ProfilesSettingsSummary": "Qualität, Metadaten, Verzögerung und Release Profile",
"RenameBooks": "Bücher umbenennen",
"SearchForNewItems": "Suche nach neuen Einträgen",
"SeriesNumber": "Seriennummer",
"ShouldMonitorExistingHelpText": "Bücher in dieser Liste welche bereits in Readarr sind überwachen",
"SkipBooksWithNoISBNOrASIN": "Überspringe Bücher ohne ISBN oder ASIN",
"StatusEndedDeceased": "Verstorben",
"UpdateCovers": "Covers aktualisieren",
"UpdateCoversHelpText": "Buchcovers in Calibre so einstellen, dass sie mit denen aus Readarr übereinstimmen",
"UrlBaseHelpText": "Fügt ein Prefix zur Calibre Url hinzu, z.B http://[host]:[port]/[urlBasis]",
"UseSSL": "Benutze SSL",
"MonitorBookExistingOnlyWarning": "Dies ist eine einmalige Anpassung der Überwachungseinstellung für jedes Buch. Verwenden Sie die Option unter Autor/Bearbeiten, um festzulegen, was bei neu hinzugefügten Büchern geschieht",
"MonitoredHelpText": "Readarr wird das Buch suchen und herunterladen",
"MonitoredAuthorIsUnmonitored": "Autor wird nicht überwacht",
"MonitoredAuthorIsMonitored": "Autor wird überwacht",
"NameLastFirst": "Nachname, Vorname",
"NameFirstLast": "Vorname Nachname",
"NameStyle": "Autor Namensstil",
"NETCore": ".NET Core",
"ShowLastBook": "Zeige letztes Buch",
"SkipBooksWithMissingReleaseDate": "Überspringe Bücher ohne Erscheinungsdatum",
"Monitoring": "Überwachung",
"OnBookDeleteHelpText": "Beim Löschen eines Buches",
"RefreshAuthor": "Autor aktualisieren",
"RefreshInformation": "Informationen aktualisieren",
"SearchBook": "Buch suchen",
"ShowBookCount": "Zeige Anzahl an Büchern",
"SkipPartBooksAndSets": "Überspringe Teilbücher und Sets",
"TagsHelpText": "Gilt für Autoren mit mindestens einem passenden Tag. Leer lassen, um auf alle Autoren anzuwenden",
"TagsSettingsSummary": "Verwalten von Autoren-, Profil-, Beschränkungs- und Benachrichtigungs-Tags"
"DataNone": "Es werden keine Alben beobachtet",
"RenameFiles": "Dateien umbenennen"
}

View File

@@ -556,6 +556,5 @@
"RestartRequiredHelpTextWarning": "Απαιτείται επανεκκίνηση για να τεθεί σε ισχύ",
"Test": "Δοκιμή",
"AddList": "Προσθήκη Λίστας",
"RenameFiles": "Μετονομασία αρχείων",
"ManualImportSelectEdition": "Μη αυτόματη εισαγωγή - Επιλέξτε ταινία"
"RenameFiles": "Μετονομασία αρχείων"
}

View File

@@ -34,8 +34,6 @@
"ApiKeyHelpTextWarning": "Requires restart to take effect",
"AppDataDirectory": "AppData directory",
"AppDataLocationHealthCheckMessage": "Updating will not be possible to prevent deleting AppData on Update",
"ApplicationURL": "Application URL",
"ApplicationUrlHelpText": "This application's external URL including http(s)://, port and URL base",
"ApplyTags": "Apply Tags",
"ApplyTagsHelpTexts1": "How to apply tags to the selected author",
"ApplyTagsHelpTexts2": "Add: Add the tags the existing list of tags",

View File

@@ -216,7 +216,7 @@
"MinimumLimits": "Límites Mínimos",
"Missing": "Falta",
"Mode": "Modo",
"Monitored": "Monitoreada",
"Monitored": "Monitoreadas",
"MonoVersion": "Version de Mono",
"MoreInfo": "Más Información",
"MustContain": "Debe Contener",
@@ -235,8 +235,8 @@
"NotificationTriggers": "Desencadenantes de Notificaciones",
"OnGrabHelpText": "Al Capturar",
"OnHealthIssueHelpText": "En Problema de Salud",
"OnRenameHelpText": "Al Renombrar",
"OnUpgradeHelpText": "Al Mejorar La Calidad",
"OnRenameHelpText": "En Renombrado",
"OnUpgradeHelpText": "Al Actualizar",
"OpenBrowserOnStart": "Abrir navegador al arrancar",
"Options": "Opciones",
"Original": "Original",
@@ -269,7 +269,7 @@
"QualityProfiles": "Perfiles de Calidad",
"QualitySettings": "Ajustes de Calidad",
"Queue": "Cola",
"RSSSync": "Sincronizar RSS",
"RSSSync": "Sincronización RSS",
"RSSSyncInterval": "Intervalo de Sincronización de RSS",
"ReadTheWikiForMoreInformation": "Lee la Wiki para más información",
"ReadarrSupportsAnyIndexerThatUsesTheNewznabStandardAsWellAsOtherIndexersListedBelow": "Radarr soporta cualquier indexer que utilice el estandar Newznab, como también cualquiera de los indexers listados debajo.",
@@ -557,8 +557,8 @@
"OnBookFileDeleteForUpgradeHelpText": "En archivo de película Eliminar para actualizar",
"OnBookFileDeleteHelpText": "Al eliminar archivo de película",
"OnGrab": "Al Capturar",
"OnRename": "Al Renombrar",
"OnUpgrade": "Al Mejorar La Calidad",
"OnRename": "En Renombrado",
"OnUpgrade": "Al Actualizar",
"ProxyCheckBadRequestMessage": "Fallo al comprobar el proxy. StatusCode: {0}",
"ProxyCheckFailedToTestMessage": "Fallo al comprobar el proxy: {0}",
"QualitySettingsSummary": "Tamaños de calidad y nombrado",
@@ -597,9 +597,5 @@
"RestartRequiredHelpTextWarning": "Requiere reiniciar para que surta efecto",
"AddList": "Añadir lista",
"RenameFiles": "Renombrar Archivos",
"Test": "Test",
"InstanceName": "Nombre de Instancia",
"InstanceNameHelpText": "Nombre de instancia en pestaña y para nombre de aplicación en Syslog",
"Database": "Base de Datos",
"ManualImportSelectEdition": "Importar Manualmente - Seleccionar Película"
"Test": "Test"
}

View File

@@ -20,11 +20,11 @@
"Analytics": "Analytiikka",
"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",
"ApplyTags": "Toimenpide tunnisteille",
"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.",
"ApplyTagsHelpTexts3": " 'Poista' ainoastaan syötetyt tunnisteet",
"ApplyTagsHelpTexts4": " 'Korvaa' kaikki aiemmat tunnisteet tai poista kaikki tunnisteet jättämällä tyhjäksi",
"Authentication": "Todennus",
"AuthenticationMethodHelpText": "Vaadi käyttäjätunnus ja salasana.",
"AuthorClickToChangeBook": "Vaihda kirjaa painamalla",
@@ -36,7 +36,7 @@
"BackupRetentionHelpText": "Säilytysjaksoa vanhemmat, automaattiset varmuuskopiot poistetaan automaattisesti.",
"Backups": "Varmuuskopiointi",
"BindAddress": "Sidososoite",
"BindAddressHelpText": "Toimiva IPv4-osoite tai '*' (tähti) kaikille yhteyksille.",
"BindAddressHelpText": "Toimiva IPv4-osoite tai jokerimerkkinä '*' (tähti) kaikille yhteyksille.",
"BindAddressHelpTextWarning": "Käyttöönotto vaatii uudelleenkäynnistyksen.",
"BookIsDownloading": "Kirjaa ladataan",
"BookIsDownloadingInterp": "Kirjaa ladataan - {0} % {1}",
@@ -47,7 +47,7 @@
"Cancel": "Peruuta",
"CancelMessageText": "Haluatko varmasti perua tämän odottavan tehtävän?",
"CertificateValidation": "Varmenteen vahvistus",
"CertificateValidationHelpText": "Muuta HTTPS-varmennevahvistuksen tarkkuutta. Älä muuta, jollet ymmärrä tähän liittyviä riskejä.",
"CertificateValidationHelpText": "Valitse HTTPS-varmenteen vahvistuksen tarkkuus. Älä muuta, jollet ymmärrä tähän liittyviä riskejä.",
"ChangeFileDate": "Muuta tiedoston päiväys",
"ChangeHasNotBeenSavedYet": "Muutosta ei ole vielä tallennettu",
"ChmodFolder": "chmod-kansio",
@@ -141,7 +141,7 @@
"Fixed": "Korjattu",
"Folder": "Kansio",
"Folders": "Kansioiden käsittely",
"ForMoreInformationOnTheIndividualDownloadClientsClickOnTheInfoButtons": "Lataustyökalukohtaisia tietoja saat painamalla lisätietopainikkeita.",
"ForMoreInformationOnTheIndividualDownloadClientsClickOnTheInfoButtons": "Lue lisää yksittäisistä lataustyökaluista painamalla 'Lisätietoja'.",
"ForMoreInformationOnTheIndividualIndexersClickOnTheInfoButtons": "Lue lisää tietolähteestä painamalla 'Lisätietoja'.",
"ForMoreInformationOnTheIndividualListsClickOnTheInfoButtons": "Lue lisää tuontilistoista painamalla 'Lisätietoja'.",
"GeneralSettings": "Yleiset asetukset",
@@ -271,7 +271,7 @@
"ReadarrTags": "Radarr-tunnisteet",
"Real": "Todellinen",
"Reason": "Syy",
"RecycleBinCleanupDaysHelpText": "Poista automaattinen tyhjennys käytöstä asettamalla arvoksi '0'.",
"RecycleBinCleanupDaysHelpText": "Älä tyhjennä automaattisesti asettamalla arvoksi '0'.",
"RecycleBinCleanupDaysHelpTextWarning": "Tässä määritettyä aikaa vanhemmat tiedostot poistetaan roskakorista pysyvästi automaattisesti.",
"RecycleBinHelpText": "Pysyvän poiston sijaan kirjatiedostot siirretään tähän kansioon.",
"RecyclingBin": "Roskakori",
@@ -297,7 +297,7 @@
"RemoveTagExistingTag": "Olemassa oleva tunniste",
"RemoveTagRemovingTag": "Tunniste poistetaan",
"RemovedFromTaskQueue": "Poistettu tehtäväjonosta",
"RenameBooksHelpText": "Jos uudelleennimeäminen ei ole käytössä, käytetään nykyistä tiedostonimeä.",
"RenameBooksHelpText": "Jos uudelleennimeäminen ei ole käytössä, käytetään olemassa olevaa tiedostonimeä.",
"Reorder": "Järjestä uudelleen",
"ReplaceIllegalCharacters": "Korvaa kielletyt merkit",
"RequiredHelpText": "Julkaisun tulee sisältää ainakin yksi näistä termeistä (kirjainkokoa ei huomioida).",
@@ -349,7 +349,7 @@
"ShownAboveEachColumnWhenWeekIsTheActiveView": "Näkyy jokaisen sarakkeen yläpuolella käytettäessä viikkonäkymää.",
"Size": " Koko",
"SkipFreeSpaceCheck": "Ohita vapaan levytilan tarkistus",
"SkipFreeSpaceCheckWhenImportingHelpText": "Käytä, kun vapaata tallennustilaa ei tunnisteta kirjailijoiden juurikansiosta.",
"SkipFreeSpaceCheckWhenImportingHelpText": "Käytä, kun vapaata tilaa ei tunnisteta kirjailijoidesi pääkansiosta.",
"SorryThatAuthorCannotBeFound": "Valitettavasti kirjailijaa ei löydy.",
"SorryThatBookCannotBeFound": "Valitettavasti elokuvaa ei löydy.",
"Source": "Lähdekoodi",
@@ -367,7 +367,7 @@
"SuccessMyWorkIsDoneNoFilesToRetag": "Menestys! Työni on valmis, ei nimettäviä tiedostoja.",
"SupportsRssvalueRSSIsNotSupportedWithThisIndexer": "RSS-syötettä ei ole käytettävissä tälle tietolähteelle",
"SupportsSearchvalueSearchIsNotSupportedWithThisIndexer": "Hakemistoa ei tueta tällä hakemistolla",
"SupportsSearchvalueWillBeUsedWhenAutomaticSearchesArePerformedViaTheUIOrByReadarr": "Profiilia käytetään automaattihaun yhteydessä, kun haku suoritetaan käyttöliittymästä tai Readarrin toimesta.",
"SupportsSearchvalueWillBeUsedWhenAutomaticSearchesArePerformedViaTheUIOrByReadarr": "Käytetään, kun automaattiset haut suoritetaan käyttöliittymän tai Radarrin kautta",
"SupportsSearchvalueWillBeUsedWhenInteractiveSearchIsUsed": "Profiilia käytetään vuorovaikutteisen haun yhteydessä.",
"TagIsNotUsedAndCanBeDeleted": "Tunnistetta ei ole määritetty millekään kohteelle, joten sen voi poistaa.",
"Tags": "Tunnisteet",
@@ -588,10 +588,10 @@
"MissingBooks": "Puuttuvat kirjat",
"MissingBooksAuthorMonitored": "Puuttuvat kirjat (kirjailijaa valvotaan)",
"MissingBooksAuthorNotMonitored": "Puuttuvat kirjat (kirjailijaa ei valvota)",
"MonitorBookExistingOnlyWarning": "Tämä on kirjakohtaisen valvonnan kertaluontoinen määritys. Määritä Kirjailija/Muokkaa-valinnalla mitä uusille kirjalisäyksille tehdään.",
"MonitorBookExistingOnlyWarning": "Tämä on kirjakohtaisen valvonnan kertaluontoinen määritys. Käytä Kirjailija/Muokkaa-valintaa hallinnoidaksesi mitä uusille kirjalisäyksille tehdään.",
"MonitorNewItems": "Valvo uusia kirjoja",
"MonitorNewItemsHelpText": "Uusien kirjojen valvontatapa.",
"MonitoringOptionsHelpText": "Mitkä kirjat asetetaan valvottaviksi kirjailijan lisäyksen yhteydessä (kertaluontoinen määritys).",
"MonitoringOptionsHelpText": "Kansiosta löydetyille kirjailijoille oletusarvoisesti asetettava kirjojen valvontataso (kertaluontoinen määritys).",
"OutputFormatHelpText": "Voit halutessasi pyytää Calibrea muuntamaan kirjat eri muotoihin tuonnin yhteydessä. Pilkulla eroteltu lista.",
"PasswordHelpText": "Calibre-sisältöpalvelimen salasana.",
"PortHelpText": "Calibre-sisältöpalvelimen portti.",
@@ -700,7 +700,5 @@
"RenameFiles": "Uudelleennimeä tiedostot",
"Test": "Kokeile",
"AllowFingerprintingHelpText": "Käytä piiloleimausta kirjojen täsmäyksen tarkennukseen",
"AllowFingerprinting": "Salli piiloleimaus",
"Database": "Tietokanta",
"ManualImportSelectEdition": "Manuaalinen tuonti - Valitse versio"
"AllowFingerprinting": "Salli piiloleimaus"
}

View File

@@ -666,15 +666,5 @@
"DefaultMonitorOptionHelpText": "Quels livres doivent être surveillés lors de l'ajout initial pour les auteurs détectés dans ce dossier",
"DefaultQualityProfileIdHelpText": "Profil de qualité par défaut pour les auteurs détectés dans ce dossier",
"AddMissing": "Ajouter les manquants",
"BookFileCountBookCountTotalTotalBookCountInterp": "{0} / {1} (Total : {2})",
"InstanceName": "Nom de l'instance",
"InstanceNameHelpText": "Nom de l'instance dans l'onglet du navigateur et pour le nom d'application dans Syslog",
"UseCalibreContentServer": "Serveur de contenu Calibre",
"DefaultTagsHelpText": "Profil de métadonnées par défaut pour les auteurs détectés dans ce dossier",
"MetadataProfiles": "profil de métadonnées",
"ManualImportSelectEdition": "Importation manuelle - Sélectionnez un film",
"Term": "Terme",
"MetadataProfile": "profil de métadonnées",
"StatusEndedContinuing": "Continuant",
"Database": "Base de données"
"BookFileCountBookCountTotalTotalBookCountInterp": "{0} / {1} (Total : {2})"
}

View File

@@ -568,7 +568,5 @@
"RenameFiles": "שנה את שם הקבצים",
"Test": "מִבְחָן",
"InstanceName": "שם מופע",
"RemotePathMappingCheckWrongOSPath": "אתה משתמש בדוקר; קליינט ההורדות {0} שם הורדות ב-{1} אבל הנתיב לא תקין {2}. בחן מחדש את ניתוב התיקיות והגדרות קליינט ההורדות.",
"ManualImportSelectEdition": "ייבוא ידני - בחר סרט",
"Database": "מסד נתונים"
"RemotePathMappingCheckWrongOSPath": "אתה משתמש בדוקר; קליינט ההורדות {0} שם הורדות ב-{1} אבל הנתיב לא תקין {2}. בחן מחדש את ניתוב התיקיות והגדרות קליינט ההורדות."
}

View File

@@ -556,6 +556,5 @@
"RenameFiles": "फ़ाइलों का नाम बदलें",
"RestartRequiredHelpTextWarning": "प्रभावी करने के लिए पुनरारंभ की आवश्यकता है",
"AddList": "सूची में जोड़ने",
"Test": "परीक्षा",
"ManualImportSelectEdition": "मैनुअल आयात - मूवी का चयन करें"
"Test": "परीक्षा"
}

View File

@@ -556,6 +556,5 @@
"RestartRequiredHelpTextWarning": "Krefst endurræsingar til að taka gildi",
"AddList": "Bæta við lista",
"RenameFiles": "Endurnefna skrár",
"Test": "Próf",
"ManualImportSelectEdition": "Handvirkur innflutningur - Veldu kvikmynd"
"Test": "Próf"
}

View File

@@ -619,7 +619,5 @@
"InstanceName": "Nome Istanza",
"InstanceNameHelpText": "Nome dell'istanza nella scheda e per il nome dell'applicazione Syslog",
"LogRotateHelpText": "Numero massimo di file di log da tenere salvati nella cartella log",
"LogRotation": "Rotazione Log",
"ManualImportSelectEdition": "Importazione manuale: seleziona Film",
"Database": "Database"
"LogRotation": "Rotazione Log"
}

View File

@@ -556,6 +556,5 @@
"RestartRequiredHelpTextWarning": "有効にするには再起動が必要です",
"RenameFiles": "ファイルの名前を変更する",
"Test": "テスト",
"AddList": "リストを追加",
"ManualImportSelectEdition": "手動インポート-ムービーを選択"
"AddList": "リストを追加"
}

View File

@@ -1 +0,0 @@
{}

View File

@@ -589,7 +589,5 @@
"RestartRequiredHelpTextWarning": "Herstarten vereist om in werking te treden",
"AddList": "Lijst Toevoegen",
"RenameFiles": "Hernoem Bestanden",
"Test": "Test",
"ManualImportSelectEdition": "Manuele import - Selecteer Film",
"Database": "Databasis"
"Test": "Test"
}

View File

@@ -131,11 +131,11 @@
"DeleteImportListMessageText": "Czy na pewno chcesz usunąć listę „{0}”?",
"DeleteIndexer": "Usuń indeksator",
"DeleteIndexerMessageText": "Czy na pewno chcesz usunąć indeksator „{0}”?",
"DeleteMetadataProfileMessageText": "Czy na pewno chcesz usunąć profil metadanych '{0}'?",
"DeleteMetadataProfileMessageText": "Czy na pewno chcesz usunąć profil jakości {0}",
"DeleteNotification": "Usuń powiadomienie",
"DeleteNotificationMessageText": "Czy na pewno chcesz usunąć powiadomienie „{0}”?",
"DeleteQualityProfile": "Usuń profil jakości",
"DeleteQualityProfileMessageText": "Czy na pewno chcesz usunąć profil jakości '{0}'?",
"DeleteQualityProfileMessageText": "Czy na pewno chcesz usunąć profil jakości {0}",
"DownloadPropersAndRepacksHelpTexts1": "Czy automatycznie uaktualnić do Propers / Repacks",
"DownloadWarningCheckDownloadClientForMoreDetails": "Ostrzeżenie dotyczące pobierania: sprawdź klienta pobierania, aby uzyskać więcej informacji",
"Edit": "Edytować",
@@ -217,7 +217,7 @@
"MarkAsFailedMessageText": "Czy na pewno chcesz oznaczyć „{0}” jako nieudany?",
"MaximumLimits": "Maksymalne limity",
"MaximumSize": "Największy rozmiar",
"MaximumSizeHelpText": "Maksymalny rozmiar pobrania wydania w MB. Ustaw na zero, aby ustawić na nieograniczony.",
"MaximumSizeHelpText": "Maksymalny rozmiar pobrania wydania w MB. Ustaw na zero, aby ustawić na nieograniczony",
"Mechanism": "Mechanizm",
"MinimumAgeHelpText": "Tylko Usenet: minimalny wiek NZB w minutach przed ich przechwyceniem. Wykorzystaj to, aby dać czas na rozpowszechnienie nowych wersji do Twojego dostawcy usenetu.",
"MinimumFreeSpace": "Minimalna wolna przestrzeń",
@@ -232,7 +232,7 @@
"NamingSettings": "Ustawienia nazewnictwa",
"New": "Nowy",
"NoBackupsAreAvailable": "Brak dostępnych kopii zapasowych",
"NoHistory": "Brak historii.",
"NoHistory": "Żadnej historii",
"NoLeaveIt": "Nie, zostaw to",
"NoLimitForAnyRuntime": "Brak ograniczeń dla dowolnego czasu wykonywania",
"NoLogFiles": "Brak plików dziennika",
@@ -409,7 +409,7 @@
"UnableToLoadDownloadClientOptions": "Nie można załadować opcji klienta pobierania",
"UnableToLoadDownloadClients": "Nie można załadować klientów pobierania",
"UnableToLoadGeneralSettings": "Nie można załadować ustawień ogólnych",
"UnableToLoadHistory": "Nie można załadować historii.",
"UnableToLoadHistory": "Nie można załadować historii",
"UnableToLoadImportListExclusions": "Nie można załadować wykluczeń list",
"UnableToLoadIndexerOptions": "Nie można załadować opcji indeksatora",
"UnableToLoadIndexers": "Nie można załadować indeksatorów",
@@ -577,7 +577,7 @@
"RemotePathMappingCheckDownloadPermissions": "Radarr widzi film {0}, lecz nie ma do niego dostępu. Najprawdopodobniej to wynik błędu w uprawnieniach dostępu.",
"RemotePathMappingCheckFilesGenericPermissions": "Klient pobierania {0} zgłosił pliki w {1}, lecz Radarr nie widzi tego folderu. Być może musisz zmienić uprawnienia dostępu do tego folderu.",
"RemotePathMappingCheckFolderPermissions": "Radarr widzi folder {0}, lecz nie ma do niego dostępu. Prawdopodobnie to wynik błędu uprawnień dostępu.",
"RemotePathMappingCheckGenericPermissions": "Klient pobierania {0} umieszcza pobrane pliki w {1}, lecz Radarr nie widzi tego folderu. Prawdopodobnie należy zmienić uprawnienia dostępu do folderu.",
"RemotePathMappingCheckGenericPermissions": "Klient pobierania {0} umieszcza pobrane pliki w {1}, lecz Radarr nie widzi tego folderu. Być może należy zmienić uprawnienia dostępu do folderu.",
"RemotePathMappingCheckImportFailed": "Radarr nie mógł zaimportować filmu. Szczegóły znajdziesz w dzienniku.",
"RenameFiles": "Zmień nazwy plików",
"Test": "Test",

View File

@@ -306,7 +306,7 @@
"LogLevel": "Nível de log",
"LogLevelvalueTraceTraceLoggingShouldOnlyBeEnabledTemporarily": "O registo de rastreio somente deve ser ativado temporariamente",
"Logging": "guardar nos registos",
"Logs": "Registos",
"Logs": "Logs",
"LongDateFormat": "Formato longo de data",
"MIA": "Desaparecidos",
"ManualImport": "Importação manual",
@@ -355,7 +355,7 @@
"Preferred": "Preferido",
"PreviewRename": "Pré-visualizar renomeação",
"Profiles": "Perfis",
"Proper": "Correta",
"Proper": "Proper",
"PropersAndRepacks": "Propers e Repacks",
"Protocol": "Protocolo",
"ProtocolHelpText": "Escolha que protocolo(s) utilizar e qual o preferido ao escolher entre versões iguais",
@@ -494,7 +494,7 @@
"MetadataConsumers": "Consumidores de metadados",
"MetadataProfile": "Perfil de metadados",
"ReleaseProfiles": "Perfis de versão",
"AddImportListExclusionHelpText": "Impedir que o livro seja adicionado ao Readarr por Listas de Importação ou Atualização do Autor",
"AddImportListExclusionHelpText": "Impedir que o livro seja adicionado ao Readarr por listas de importação ou atualização do autor",
"AddMissing": "Adicionar ausentes",
"AddNewItem": "Adicionar novo item",
"AllAuthorBooks": "Todos os livros do autor",
@@ -803,8 +803,5 @@
"RestartRequiredHelpTextWarning": "Requer reinício para aplicar alterações",
"AddList": "Adicionar lista",
"RenameFiles": "Renomear ficheiros",
"Test": "Testar",
"InstanceNameHelpText": "Nome da instância na aba e nome da aplicação para Syslog",
"Database": "Base de dados",
"AddedAuthorSettings": "Definições de Autor adicionadas"
"Test": "Testar"
}

View File

@@ -239,7 +239,7 @@
"NoUpdatesAreAvailable": "Não há atualizações disponíveis",
"None": "Nenhum",
"NotificationTriggers": "Acionadores da notificação",
"OnGrabHelpText": "Em Espera",
"OnGrabHelpText": "Ao obter",
"OnHealthIssueHelpText": "Ao ter problema de integridade",
"OnRenameHelpText": "Ao renomear",
"OnUpgradeHelpText": "Ao atualizar",
@@ -754,14 +754,14 @@
"OnBookFileDeleteHelpText": "Ao Excluir um Arquivo de Livro",
"OnBookTagUpdate": "Ao Atualizar Etiqueta de um Livro",
"OnDownloadFailure": "Na Falha do Download",
"OnGrab": "Em Espera",
"OnGrab": "Ao Baixar",
"OnHealthIssue": "Em Problema de Saúde",
"OnImportFailure": "Em uma Falha de Importação",
"OnReleaseImport": "Ao Importar Lançamento",
"OnRename": "Ao Renomear",
"OnUpgrade": "Ao Atualizar",
"AppDataLocationHealthCheckMessage": "A atualização não será possível para evitar a exclusão de AppData na atualização",
"IndexerSearchCheckNoInteractiveMessage": "Nenhum indexador disponível com a Pesquisa Interativa habilitada, Readarr não irá prover quaisquer resultados para pesquisa interativa",
"IndexerSearchCheckNoInteractiveMessage": "Nenhum indexador disponível com a Pesquisa interativa ativada, o Readarr não fornecerá nenhum resultado de pesquisa interativo",
"ConnectSettingsSummary": "Notificações, conexões com servidores/tocadores de mídia e scripts personalizados",
"DownloadClientStatusCheckAllClientMessage": "Todos os clientes download não estão disponíveis devido a falhas",
"DownloadClientsSettingsSummary": "Clientes de download, gerenciamento do download e mapeamento remoto de caminhos",
@@ -874,8 +874,5 @@
"DataNewNone": "Não monitorar nenhum novo livro",
"DataNone": "Nenhum livro irá ser monitorado",
"MonitorNewBooks": "Monitorar Novos Livros",
"SetReadarrTags": "Configurar Etiquetas do Readarr",
"Database": "Banco de dados",
"LoadingEditionsFailed": "Falha ao carregar edições",
"ManualImportSelectEdition": "Importação Manual - Selecionar Edição"
"SetReadarrTags": "Configurar Etiquetas do Readarr"
}

View File

@@ -47,23 +47,5 @@
"AgeWhenGrabbed": "Vek (po uchopení)",
"Analytics": "Analytika",
"BindAddressHelpText": "Platná adresa IP4 alebo '*' pre všetky rozhrania",
"AppDataLocationHealthCheckMessage": "Aktualizácia nebude možná, aby sa predišlo zmazaniu AppData v priebehu aktualizácie",
"ChmodFolder": "chmod Priečinok",
"ClickToChangeQuality": "Kliknutím zmeníte kvalitu",
"ChangeFileDate": "Zmeniť dátum súboru",
"ChangeHasNotBeenSavedYet": "Zmena ešte nebola uložená",
"ClientPriority": "Priorita klienta",
"Component": "Komponent",
"CertificateValidation": "Overenie certifikátu",
"CertificateValidationHelpText": "Zmeňte, aké prísne je overenie certifikácie HTTPS. Nemeňte, pokiaľ nerozumiete rizikám.",
"Close": "Zatvoriť",
"CloneIndexer": "Klonovať indexer",
"CloneProfile": "Klonovať profil",
"Connect": "Pripojiť",
"BindAddress": "Viazať adresu",
"Clear": "Vymazať",
"Blocklist": "Blocklist",
"BlocklistRelease": "Blocklistnúť vydanie",
"Columns": "Stĺpce",
"CompletedDownloadHandling": "Zaobchádzanie s dokončenými sťahovaniami"
"AppDataLocationHealthCheckMessage": "Aktualizácia nebude možná, aby sa predišlo zmazaniu AppData v priebehu aktualizácie"
}

View File

@@ -32,6 +32,7 @@
"BackupRetentionHelpText": "早于保留周期的自动备份将被自动清除",
"Backups": "备份",
"BindAddress": "绑定地址",
"BindAddressHelpText": "有效的 IP4 地址或以'*'代表所有地址",
"BindAddressHelpTextWarning": "需重启以生效",
"BookIsDownloading": "影片正在下载中",
"BookIsDownloadingInterp": "影片正在下载中 - {0}% {1}",
@@ -89,7 +90,7 @@
"DeleteQualityProfile": "删除电影质量配置",
"DeleteQualityProfileMessageText": "确定要删除影片质量配置“{0}”",
"DeleteReleaseProfile": "删除延迟配置",
"DeleteReleaseProfileMessageText": "您确定要删除这个发行配置?",
"DeleteReleaseProfileMessageText": "您确定要删除这个延迟配置?",
"DeleteSelectedBookFiles": "删除选择的电影文件",
"DeleteSelectedBookFilesMessageText": "您确定要删除选择的电影文件吗?",
"DeleteTagMessageText": "您确定要删除标签 '{0}' 吗?",
@@ -134,7 +135,7 @@
"Fixed": "已修复",
"Folder": "文件夹",
"Folders": "文件夹",
"ForMoreInformationOnTheIndividualDownloadClientsClickOnTheInfoButtons": "有关个下载客户端的详细信息请单击info按钮。",
"ForMoreInformationOnTheIndividualDownloadClientsClickOnTheInfoButtons": "有关个下载客户端的详细信息请单击info按钮。",
"ForMoreInformationOnTheIndividualIndexersClickOnTheInfoButtons": "有关更多搜刮器的详细信息,请单击信息按钮。",
"ForMoreInformationOnTheIndividualListsClickOnTheInfoButtons": "有关更多导入列表的详细信息请单击info按钮。",
"GeneralSettings": "通用设置",
@@ -164,7 +165,7 @@
"ImportedTo": "导入到",
"Importing": "导入中",
"IncludeHealthWarningsHelpText": "包含健康度警告",
"IncludeUnknownAuthorItemsHelpText": "显示队列中没有作者的项,这可能包括已移除的作者、书籍或Readarr类别中的任何其他内容",
"IncludeUnknownAuthorItemsHelpText": "显示队列中没有电影的项,这可能包括被删除的电影或Radarr类别中的任何其他内容",
"IncludeUnmonitored": "包含未监控的",
"Indexer": "索引器",
"IndexerPriority": "索引器优先级",
@@ -292,7 +293,7 @@
"RequiredHelpText": "发布的影片必须至少包含一个这些项目(不区分大小写)",
"RequiredPlaceHolder": "添加新限制",
"RescanAfterRefreshHelpTextWarning": "当没有设置为“总是”时Radarr将不会自动检测文件的更改",
"RescanAuthorFolderAfterRefresh": "刷新后重新扫描作者文件夹",
"RescanAuthorFolderAfterRefresh": "刷新后重新扫描影片文件夹",
"Reset": "重置",
"ResetAPIKey": "重置API Key",
"ResetAPIKeyMessageText": "您确定要重置您的API密钥吗",
@@ -433,8 +434,8 @@
"WeekColumnHeader": "日期格式",
"Year": "年",
"YesCancel": "是,取消",
"20MinutesTwenty": "20分钟: {0}",
"45MinutesFourtyFive": "45分钟: {0}",
"20MinutesTwenty": "60分钟: {0}",
"45MinutesFourtyFive": "60分钟: {0}",
"60MinutesSixty": "60分钟: {0}",
"APIKey": "API Key",
"About": "关于",
@@ -595,7 +596,7 @@
"ShowUnknownAuthorItems": "显示未知影片条目",
"AllowFingerprintingHelpText": "利用指纹技术提高航迹匹配的准确性",
"AllowFingerprintingHelpTextWarning": "这需要读取部分文件,这将减慢扫描速度,并可能导致磁盘或网络活动频繁。",
"AuthorFolderFormat": "作者文件夹格式",
"AuthorFolderFormat": "艺术家文件夹格式",
"Authors": "作者",
"BackupIntervalHelpText": "备份 Lidarr 数据库和设置的时间间隔",
"Term": "项",
@@ -603,279 +604,5 @@
"MetadataProfiles": "元数据配置",
"InstanceName": "中文",
"InstanceNameHelpText": "选项卡及日志应用名称",
"AddList": "添加列表",
"BookList": "书籍清单",
"Books": "书籍",
"BookFileCountBookCountTotalTotalBookCountInterp": "{0} / {1} (全部: {2})",
"BookFileCounttotalBookCountBooksDownloadedInterp": "{0}/{1} 书籍已下载",
"BookFilesCountMessage": "无书籍文件",
"AutomaticallySwitchEdition": "自动切换版本",
"AllAuthorBooks": "该作者所有书籍",
"AllBooks": "所有书籍",
"AllowedLanguages": "允许的语言",
"Book": "书籍",
"BookIndex": "书籍索引",
"CalibreContentServerText": "使用Calibre内容服务器非 Calibre Web允许Readarr将书籍添加到您的Calibre库并触发格式之间的转换",
"CalibreNotCalibreWeb": "Readarr可以与Calibre内容服务器相接。无法使用Calibre-Web两者不同。",
"CatalogNumber": "目录编号",
"ConvertToFormat": "转换为格式",
"DataAllBooks": "监控所有书籍",
"DataExistingBooks": "监控书籍有文件或尚未发布",
"DataFirstBook": "监控第一本书。其他所有书籍都将被忽略",
"DataFuturebooks": "监控尚未发布的书籍",
"DataLatestBook": "监控最新书籍及未来的书籍",
"DataListMonitorAll": "监控作者们及导入列表中每个作者的所有书籍",
"DataListMonitorNone": "不要监控作者或书籍",
"DataListMonitorSpecificBook": "监控作者,但只监控明确包含在列表中的书籍",
"DataMissingBooks": "监控没有文件或尚未发布的书籍",
"DataNewAllBooks": "监控所有新书籍",
"DataNewNone": "不要监控任何新书籍",
"DataNone": "不会监控任何书籍",
"DataNewBooks": "监控现有最新书籍之后发布的新书",
"DefaultQualityProfileIdHelpText": "此文件夹中检测到的作者的默认质量配置",
"DefaultMetadataProfileIdHelpText": "此文件夹中检测到的作者的默认元数据配置文件",
"DefaultMonitorOptionHelpText": "对于在此文件夹中检测到的作者,应在初始添加时监控哪些书籍",
"DefaultReadarrTags": "默认Readarr标签",
"DefaultTagsHelpText": "对于在此文件夹中检测到的作者使用默认Readarr标签",
"DeleteBookFile": "删除书籍文件",
"DeleteFilesHelpText": "删除书籍文件及作者文件夹",
"DeleteImportList": "删除导入的列表",
"DeleteMetadataProfile": "删除元数据配置",
"DeleteRootFolder": "删除根目录",
"DiscNumber": "磁盘编号",
"Development": "开发",
"DiscCount": "磁盘数量",
"DownloadPropersAndRepacksHelpTexts2": "使用“不要偏好”按首字母而不是专有/重新打包进行排序",
"EditionsHelpText": "修改这本书的版本",
"EmbedMetadataHelpText": "告知Calibre将元数据写入实际的图书文件中",
"EmbedMetadataInBookFiles": "将元数据写入书籍文件",
"EditBook": "编辑书籍",
"EditList": "编辑列表",
"EnableAutomaticAddHelpText": "当通过UI或Readarr执行同步时将作者/书籍添加到Readarr",
"EnabledHelpText": "检查以启用发布配置文件",
"FileDetails": "文件详情",
"FilterPlaceHolder": "过滤书籍",
"FilterAuthor": "过滤作者",
"FirstBook": "第一本书籍",
"ForeignId": "国外 ID",
"ForeignIdHelpText": "作者/书籍的Musicbrainz ID排除",
"FutureBooks": "未来书籍",
"FutureDays": "未来天数",
"FutureDaysHelpText": "iCal订阅地址等待天数",
"GoToAuthorListing": "转到作者列表",
"HasMonitoredBooksNoMonitoredBooksForThisAuthor": "此作者没有受监控的书籍",
"ImportListSettings": "常规导入列表设置",
"ImportListSpecificSettings": "导入列表特定设置",
"IndexerIdHelpText": "指定配置文件应用于哪个索引器",
"MusicbrainzId": "Musicbrainz ID",
"MusicBrainzRecordingID": "MusicBrainz 唱片ID",
"MusicBrainzReleaseID": "MusicBrainz发行ID",
"MusicBrainzAuthorID": "MusicBrainz作者ID",
"OnBookDelete": "在书籍删除时",
"OnBookTagUpdate": "在书籍标签更新时",
"OnDownloadFailure": "在下载失败时",
"PastDays": "过去天数",
"SearchBook": "搜索书籍",
"SearchBoxPlaceHolder": "例: War and Peace, goodreads:656, isbn:067003469X, asin:B00JCDK5ME",
"TrackNumber": "跟踪编号",
"RootFolderPathHelpText": "根目录文件夹列表项需添加",
"SelectedCountAuthorsSelectedInterp": "{0} 作者选中",
"SearchForNewItems": "搜索新项目",
"SearchMonitored": "搜索已监控",
"ShowBookCount": "显示书籍序号",
"ShowBannersHelpText": "显示横幅而不是名称",
"ShowLastBook": "显示最后书籍",
"SkipPartBooksAndSets": "跳过节选和系列",
"StatusEndedContinuing": "仍在继续",
"UpdatingIsDisabledInsideADockerContainerUpdateTheContainerImageInstead": "更新在docker容器内被禁用. 改为更新容器映像。",
"WatchLibraryForChangesHelpText": "当根目录文件夹中的文件发生变化时,会自动重新扫描",
"WatchRootFoldersForFileChanges": "监测根目录文件夹的文件更改",
"EditAuthor": "编辑作者",
"EndedAllBooksDownloaded": "完成(所以书籍已下载)",
"EntityName": "实体名称",
"ShowBanners": "显示横幅",
"LogSQL": "Log SQL",
"CalibreSettings": "Calibre设置",
"Country": "国家",
"Iso639-3": "ISO 639-3语言代码或“null”逗点分离",
"ExistingItems": "现有项目",
"ExistingBooks": "现有书籍",
"ExistingTagsScrubbed": "已删除现有标签",
"ImportFailures": "导入失败",
"IgnoreDeletedBooks": "忽略已删除的书籍",
"WriteTagsAll": "所有文件;仅限初始导入",
"WriteTagsNew": "仅适用于新下载",
"LoadingEditionsFailed": "加载版本失败",
"ManualImportSelectEdition": "手动导入 - 选择版本",
"MassBookSearch": "批量书籍搜索",
"MetadataProviderSource": "元数据提供源",
"MetadataSource": "元数据源",
"MetadataSourceHelpText": "备选元数据源(默认为空)",
"MinimumPopularity": "最低人气",
"MinPagesHelpText": "忽略页数比这少的书",
"MissingBooksAuthorMonitored": "书籍丢失(已监控作者)",
"MissingBooks": "书籍丢失",
"MissingBooksAuthorNotMonitored": "丢失书籍(未监控作者)",
"MonitorAuthor": "监控作者",
"MonitorBook": "监控书籍",
"MonitoredAuthorIsMonitored": "作者已监控",
"MonitoredAuthorIsUnmonitored": "作者未监控",
"MonitoredHelpText": "Readarr将搜索及下载书籍",
"MonitorExistingBooks": "监控现有书籍",
"Monitoring": "监控中",
"MonitoringOptions": "监控选项",
"MonitoringOptionsHelpText": "添加作者后应该监控哪些书籍(一次性调整)",
"MonitorNewBooks": "监控新书",
"MonitorNewItems": "监控新书",
"MonitorNewItemsHelpText": "哪些新书应被监控",
"MusicBrainzBookID": "MusicBrainz书籍ID",
"MusicBrainzTrackID": "MusicBrainz曲目ID",
"NameLastFirst": "名姓",
"NameStyle": "作者姓名样式",
"NETCore": ".NET Core",
"NewBooks": "新书",
"NoName": "不显示名称",
"OnAuthorDeleteHelpText": "在作者删除时",
"OnBookDeleteHelpText": "在书籍删除时",
"OnDownloadFailureHelpText": "在下载失败时",
"OnImportFailureHelpText": "在导入失败时",
"OnReleaseImportHelpText": "在发行导入时",
"Other": "其他",
"PastDaysHelpText": "iCal订阅地址 过去天数",
"PathHelpText": "根目录文件夹包含您的书籍库",
"PortHelpText": "Calibre内容服务器端口",
"PreferredHelpTexts1": "发行将优先根据每个期间评分(不区分大小写)",
"PreferredHelpTexts2": "高得分将更优先",
"PreferredHelpTexts3": "低分将不优先",
"PreviewRetag": "预览重新标记",
"QualityProfileIdHelpText": "质量配置列表项应该被添加",
"ReadarrSupportsMultipleListsForImportingBooksAndAuthorsIntoTheDatabase": "Readarr支持将书籍和作者导入数据库的多个列表。",
"RefreshAuthor": "刷新作者",
"RefreshBook": "刷新书籍",
"RefreshInformation": "刷新信息",
"ReleaseProfiles": "刷新配置文件",
"RenameBooks": "重命名书籍",
"RenameFiles": "重命名文件",
"RestartRequiredHelpTextWarning": "需要重新启动才能生效",
"SearchForAllMissingBooks": "搜索所有丢失的书籍",
"SendMetadataToCalibre": "发送元数据至Calibre",
"SeriesNumber": "系列编号",
"SeriesTotal": "系列 ({0})",
"SetReadarrTags": "设置Readarr标签",
"ShouldMonitorExistingHelpText": "自动监控此列表中已经在Readarr中的书籍",
"ShouldMonitorHelpText": "监控从此列表中添加的新作者和书籍",
"SkipBooksWithMissingReleaseDate": "跳过缺少发行日期的书籍",
"SkipBooksWithNoISBNOrASIN": "跳过没有ISBN或ASIN的书籍",
"SkipRedownload": "跳过重新下载",
"SkipSecondarySeriesBooks": "跳过重版系列书籍",
"StatusEndedDeceased": "已故",
"TagsHelpText": "适用于至少一个匹配标签的作者,留空以适用于所有作者",
"TagsSettingsSummary": "管理作者、配置文件、限制和通知标签",
"Test": "测试",
"TheFollowingFilesWillBeDeleted": "以下文件将被删除:",
"TrackTitle": "跟踪标题",
"UnableToLoadMetadataProviderSettings": "无法加载元数据源设置",
"UnmappedFiles": "未映射文件",
"UpdateCovers": "更新封面",
"UpdateCoversHelpText": "在Calibre里设置书籍封面以匹配Readarr中的封面",
"UrlBaseHelpText": "添加Calibre url例 http://[主机/ip]:[端口]/[urlBase]",
"UseCalibreContentServer": "使用Calibre内容服务器",
"UsernameHelpText": "Calibre内容服务器用户名",
"WriteAudioTagsScrub": "覆盖现有标签",
"WriteBookTagsHelpTextWarning": "选择“所有文件”将在导入时更改现有文件。",
"WriteMetadataTags": "编写元数据标签",
"WriteTagsSync": "所有文件与Goodreads保持同步",
"ShowName": "显示名称",
"AddedAuthorSettings": "已添加作者设置",
"Continuing": "仍在继续",
"ContinuingMoreBooksAreExpected": "预计会有更多书籍",
"ContinuingNoAdditionalBooksAreExpected": "预计不会有其他书籍",
"ProfilesSettingsSummary": "质量、元数据、延迟、发行配置",
"AuthorIndex": "作者索引",
"BookEditor": "书籍编辑",
"CalibreUsername": "Calibre用户名",
"ChownGroup": "修改组权限",
"ContinuingAllBooksDownloaded": "仍在继续(所有书籍已下载)",
"EnableProfile": "启用配置文件",
"IfYouDontAddAnImportListExclusionAndTheAuthorHasAMetadataProfileOtherThanNoneThenThisBookMayBeReaddedDuringTheNextAuthorRefresh": "如果您不添加导入列表例外,并且作者元数据配置不是“无”,那这本书可能会在下次作者刷新是重新添加",
"IncludePreferredWhenRenaming": "重命名时包括首选",
"IndexerIdHelpTextWarning": "使用带有首字母的特定索引器可能会导致复制版本被抓取",
"MassBookSearchWarning": "您确定要对{0}本书进行批量书籍搜索吗?",
"MediaManagementSettingsSummary": "命名、文件管理设置、根目录文件夹",
"MetadataConsumers": "用户元数据",
"MetadataProfileIdHelpText": "元数据配置文件列表项应添加",
"MetadataSettingsSummary": "在导入书籍或刷新作者时创建元数据文件",
"MinimumPages": "最小页面",
"MinPopularityHelpText": "人气是平均评分*票",
"MonitorBookExistingOnlyWarning": "这是对每本书籍的监控设置的一次性调整 使用作者/编辑下的选项来控制新添加的书籍将如何",
"NameFirstLast": "姓名",
"NoHistoryBlocklist": "没有历史黑名单列表",
"OnAuthorDelete": "在作者删除时",
"OnBookRetagHelpText": "在书籍重加标签时",
"OnImportFailure": "在导入失败时",
"OnReleaseImport": "在发行导入时",
"OutputFormatHelpText": "可选择让Calibre在导入时转换为其他格式 逗点分隔列表。",
"PasswordHelpText": "Calibre内容服务器密码",
"PathHelpTextWarning": "这必须与下载客户端放置文件的目录不同",
"SearchForAllCutoffUnmetBooks": "搜索所有Cutoff Unmet书籍",
"SearchForMonitoredBooks": "搜索监控中的书籍",
"ShouldMonitorExisting": "监控现有书籍",
"ShouldSearchHelpText": "在索引器中搜索新添加的项目, 小心使用长列表。",
"ShowTitleHelpText": "在海报下显示作者姓名",
"SkipredownloadHelpText": "阻止Readarr尝试为删除的项目下载替代版本",
"SpecificBook": "特定书籍",
"TheBooksFilesWillBeDeleted": "此书籍文件将删除。",
"TooManyBooks": "丢失还是过多书籍?修改或创建新的",
"TotalBookCountBooksTotalBookFileCountBooksWithFilesInterp": "共{0}本书籍 . {1} 有文件.",
"UseSSL": "使用SSL",
"UseSslHelpText": "使用SSL连接到Calibre内容服务器",
"WriteAudioTags": "使用元数据标记音频文件",
"WriteAudioTagsScrubHelp": "从文件中删除现有标签只留下Readarr添加的标签。",
"Database": "数据库",
"FilesTotal": "文件 ({0})",
"HideBooks": "隐藏书籍",
"HostHelpText": "Calibre内容服务器主机",
"IgnoredMetaHelpText": "如果书籍包含一个/多个术语(不区分大小写)将被忽略",
"ImportListExclusions": "导入列表例外",
"ImportLists": "导入列表",
"IndexerIdvalue0IncludeInPreferredWordsRenamingFormat": "以 {Preferred Words} 重命名格式包含",
"IndexerIdvalue0OnlySupportedWhenIndexerIsSetToAll": "仅当索引器设置为 (全部)时才支持",
"ISBN": "ISBN",
"IsCalibreLibraryHelpText": "使用Calibre内容服务器操作库",
"IsExpandedHideBooks": "隐藏书籍",
"IsExpandedHideFileInfo": "隐藏文件信息",
"IsExpandedShowBooks": "显示书籍",
"IsExpandedShowFileInfo": "显示文件信息",
"IsInUseCantDeleteAMetadataProfileThatIsAttachedToAnAuthorOrImportList": "无法删除元数据配置文件,其已经附加到作者或为导入列表",
"IsInUseCantDeleteAQualityProfileThatIsAttachedToAnAuthorOrImportList": "无法删除质量配置文件,其已附加到作者或为导入列表",
"IsShowingMonitoredMonitorSelected": "监控选中的",
"IsShowingMonitoredUnmonitorSelected": "未监控选中的",
"ItsEasyToAddANewAuthorOrBookJustStartTypingTheNameOfTheItemYouWantToAdd": "添加新作者或书籍很容易,只需开始输入要添加的条目的名称",
"LatestBook": "最新书籍",
"LibraryHelpText": "Calibre内容服务器库名 默认留空",
"ListsSettingsSummary": "导入列表",
"AddImportListExclusionHelpText": "通过导入列表或作者刷新 防止书籍添加到Readarr",
"ManualDownload": "手动下载",
"BookMonitoring": "书籍监控",
"BookNaming": "书籍命名",
"BooksTotal": "书籍 ({0})",
"BookTitle": "书籍名称",
"CalibreContentServer": "Calibre内容服务器",
"CalibreHost": "Calibre主机",
"CalibreLibrary": "Calibre库",
"CalibreMetadata": "Calibre元数据",
"CalibreOutputFormat": "Calibre输出格式",
"CalibreOutputProfile": "Calibre输出配置文件",
"CalibrePassword": "Calibre密码",
"CalibrePort": "Calibre端口",
"CalibreUrlBase": "Calibre基本URL",
"BookStudio": "书籍出版商",
"AudioFileMetadata": "将元数据写入音频文件",
"AuthorEditor": "作者编辑",
"AuthorNameHelpText": "要排除的作者/书籍的名称(任何有涵义的均可)",
"CollapseMultipleBooks": "折叠多本书籍",
"CollapseMultipleBooksHelpText": "折叠在同日发行的多本书籍",
"ASIN": "亚马逊标准识别码",
"NoTagsHaveBeenAddedYet": "尚未添加标签,添加标签以链接具有延迟配置文件、限制或通知的作者。单击{0}以了解有关Readarr中标签的更多信息。",
"BindAddressHelpText": "有效的 IPv4 地址或以'*'代表所有接口"
"AddList": "添加列表"
}

View File

@@ -3,6 +3,5 @@
"Actions": "執行",
"All": "全部",
"AddingTag": "新增標籤",
"Analytics": "分析",
"AddList": "新增列表"
"Analytics": "分析"
}

View File

@@ -1,4 +1,4 @@
using NzbDrone.Common.Disk;
using NzbDrone.Common.Disk;
using NzbDrone.Common.EnvironmentInfo;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Formats.Jpeg;
@@ -21,6 +21,12 @@ namespace NzbDrone.Core.MediaCover
{
_diskProvider = diskProvider;
// Random segfaults on mono 5.0 and 5.4
if (PlatformInfo.IsMono && platformInfo.Version < new System.Version(5, 8))
{
return;
}
_enabled = true;
// More conservative memory allocation

View File

@@ -400,11 +400,11 @@ namespace NzbDrone.Core.MediaFiles
}
catch (Exception ex)
{
Logger.ForWarnEvent()
Logger.Warn()
.Exception(ex)
.Message($"Tag writing failed for {path}")
.WriteSentryWarn("Tag writing failed")
.Log();
.Write();
}
finally
{

View File

@@ -147,11 +147,11 @@ namespace NzbDrone.Core.MediaFiles
}
catch (Exception ex)
{
_logger.ForWarnEvent()
_logger.Warn()
.Exception(ex)
.Message($"Tag removal failed for {path}")
.WriteSentryWarn("Tag removal failed")
.Log();
.Write();
}
finally
{

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