mirror of
https://github.com/Readarr/Readarr.git
synced 2026-03-24 17:24:30 -04:00
Compare commits
30 Commits
v0.3.10.22
...
v0.3.12.23
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fd201912a9 | ||
|
|
c412701a3d | ||
|
|
7451a66365 | ||
|
|
a6431fdb0b | ||
|
|
060b133f6d | ||
|
|
5ed13b942b | ||
|
|
89f3d8167b | ||
|
|
77b027374f | ||
|
|
650490abb2 | ||
|
|
7d2e215d61 | ||
|
|
65ff890c74 | ||
|
|
50c0b0dbaa | ||
|
|
d5f36d0144 | ||
|
|
fab7558bd4 | ||
|
|
3dc86b3a01 | ||
|
|
24ad6134e3 | ||
|
|
033f8c40af | ||
|
|
4c73a619eb | ||
|
|
3ca798e983 | ||
|
|
d9827fd6a6 | ||
|
|
f4f03a853f | ||
|
|
4f4e4bf2ca | ||
|
|
413a70a312 | ||
|
|
a8f2b91010 | ||
|
|
68a4ee6000 | ||
|
|
5196ce311b | ||
|
|
ae92b22727 | ||
|
|
0bccffef01 | ||
|
|
bca899b9c0 | ||
|
|
2bb576a94b |
@@ -9,13 +9,13 @@ variables:
|
||||
testsFolder: './_tests'
|
||||
yarnCacheFolder: $(Pipeline.Workspace)/.yarn
|
||||
nugetCacheFolder: $(Pipeline.Workspace)/.nuget/packages
|
||||
majorVersion: '0.3.10'
|
||||
majorVersion: '0.3.12'
|
||||
minorVersion: $[counter('minorVersion', 1)]
|
||||
readarrVersion: '$(majorVersion).$(minorVersion)'
|
||||
buildName: '$(Build.SourceBranchName).$(readarrVersion)'
|
||||
sentryOrg: 'servarr'
|
||||
sentryUrl: 'https://sentry.servarr.com'
|
||||
dotnetVersion: '6.0.413'
|
||||
dotnetVersion: '6.0.417'
|
||||
nodeVersion: '16.X'
|
||||
innoVersion: '6.2.0'
|
||||
windowsImage: 'windows-2022'
|
||||
|
||||
@@ -47,7 +47,7 @@ class CalendarConnector extends Component {
|
||||
gotoCalendarToday
|
||||
} = this.props;
|
||||
|
||||
registerPagePopulator(this.repopulate);
|
||||
registerPagePopulator(this.repopulate, ['bookFileUpdated', 'bookFileDeleted']);
|
||||
|
||||
if (useCurrentPage) {
|
||||
fetchCalendar();
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
.description {
|
||||
line-height: $lineHeight;
|
||||
}
|
||||
|
||||
.description {
|
||||
margin-left: 0;
|
||||
line-height: $lineHeight;
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
|
||||
@@ -202,6 +202,8 @@ class SignalRConnector extends Component {
|
||||
this.props.dispatchUpdateItem({ section, ...body.resource });
|
||||
} else if (body.action === 'deleted') {
|
||||
this.props.dispatchRemoveItem({ section, id: body.resource.id });
|
||||
|
||||
repopulatePage('bookFileDeleted');
|
||||
}
|
||||
|
||||
// Repopulate the page to handle recently imported file
|
||||
|
||||
@@ -15,5 +15,5 @@
|
||||
"start_url": "../../../../",
|
||||
"theme_color": "#3a3f51",
|
||||
"background_color": "#3a3f51",
|
||||
"display": "standalone"
|
||||
"display": "minimal-ui"
|
||||
}
|
||||
|
||||
120
frontend/src/Diag/ConsoleApi.js
Normal file
120
frontend/src/Diag/ConsoleApi.js
Normal file
@@ -0,0 +1,120 @@
|
||||
import createAjaxRequest from 'Utilities/createAjaxRequest';
|
||||
|
||||
// This file contains some helpers for power users in a browser console
|
||||
|
||||
let hasWarned = false;
|
||||
|
||||
function checkActivationWarning() {
|
||||
if (!hasWarned) {
|
||||
console.log('Activated ReadarrApi console helpers.');
|
||||
console.warn('Be warned: There will be no further confirmation checks.');
|
||||
hasWarned = true;
|
||||
}
|
||||
}
|
||||
|
||||
function attachAsyncActions(promise) {
|
||||
promise.filter = function() {
|
||||
const args = arguments;
|
||||
const res = this.then((d) => d.filter(...args));
|
||||
attachAsyncActions(res);
|
||||
return res;
|
||||
};
|
||||
|
||||
promise.map = function() {
|
||||
const args = arguments;
|
||||
const res = this.then((d) => d.map(...args));
|
||||
attachAsyncActions(res);
|
||||
return res;
|
||||
};
|
||||
|
||||
promise.all = function() {
|
||||
const res = this.then((d) => Promise.all(d));
|
||||
attachAsyncActions(res);
|
||||
return res;
|
||||
};
|
||||
|
||||
promise.forEach = function(action) {
|
||||
const res = this.then((d) => Promise.all(d.map(action)));
|
||||
attachAsyncActions(res);
|
||||
return res;
|
||||
};
|
||||
}
|
||||
|
||||
class ResourceApi {
|
||||
constructor(api, url) {
|
||||
this.api = api;
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
single(id) {
|
||||
return this.api.fetch(`${this.url}/${id}`);
|
||||
}
|
||||
|
||||
all() {
|
||||
return this.api.fetch(this.url);
|
||||
}
|
||||
|
||||
filter(pred) {
|
||||
return this.all().filter(pred);
|
||||
}
|
||||
|
||||
update(resource) {
|
||||
return this.api.fetch(`${this.url}/${resource.id}`, { method: 'PUT', data: resource });
|
||||
}
|
||||
|
||||
delete(resource) {
|
||||
if (typeof resource === 'object' && resource !== null && resource.id) {
|
||||
resource = resource.id;
|
||||
}
|
||||
|
||||
if (!resource || !Number.isInteger(resource)) {
|
||||
throw Error('Invalid resource', resource);
|
||||
}
|
||||
|
||||
return this.api.fetch(`${this.url}/${resource}`, { method: 'DELETE' });
|
||||
}
|
||||
|
||||
fetch(url, options) {
|
||||
return this.api.fetch(`${this.url}${url}`, options);
|
||||
}
|
||||
}
|
||||
|
||||
class ConsoleApi {
|
||||
constructor() {
|
||||
this.author = new ResourceApi(this, '/author');
|
||||
}
|
||||
|
||||
resource(url) {
|
||||
return new ResourceApi(this, url);
|
||||
}
|
||||
|
||||
fetch(url, options) {
|
||||
checkActivationWarning();
|
||||
|
||||
options = options || {};
|
||||
|
||||
const req = {
|
||||
url,
|
||||
method: options.method || 'GET'
|
||||
};
|
||||
|
||||
if (options.data) {
|
||||
req.dataType = 'json';
|
||||
req.data = JSON.stringify(options.data);
|
||||
}
|
||||
|
||||
const promise = createAjaxRequest(req).request;
|
||||
|
||||
promise.fail((xhr) => {
|
||||
console.error(`Failed to fetch ${url}`, xhr);
|
||||
});
|
||||
|
||||
attachAsyncActions(promise);
|
||||
|
||||
return promise;
|
||||
}
|
||||
}
|
||||
|
||||
window.ReadarrApi = new ConsoleApi();
|
||||
|
||||
export default ConsoleApi;
|
||||
@@ -212,26 +212,24 @@ class MediaManagement extends Component {
|
||||
</FormGroup>
|
||||
|
||||
{
|
||||
settings.importExtraFiles.value &&
|
||||
settings.importExtraFiles.value ?
|
||||
<FormGroup
|
||||
advancedSettings={advancedSettings}
|
||||
isAdvanced={true}
|
||||
>
|
||||
<FormLabel>
|
||||
{translate('ImportExtraFiles')}
|
||||
</FormLabel>
|
||||
<FormLabel>{translate('ImportExtraFiles')}</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.TEXT}
|
||||
name="extraFileExtensions"
|
||||
helpTexts={[
|
||||
translate('ExtraFileExtensionsHelpTexts1'),
|
||||
translate('ExtraFileExtensionsHelpTexts2')
|
||||
translate('ExtraFileExtensionsHelpText'),
|
||||
translate('ExtraFileExtensionsHelpTextsExamples')
|
||||
]}
|
||||
onChange={onInputChange}
|
||||
{...settings.extraFileExtensions}
|
||||
/>
|
||||
</FormGroup>
|
||||
</FormGroup> : null
|
||||
}
|
||||
</FieldSet>
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ class CutoffUnmetConnector extends Component {
|
||||
gotoCutoffUnmetFirstPage
|
||||
} = this.props;
|
||||
|
||||
registerPagePopulator(this.repopulate, ['bookFileUpdated']);
|
||||
registerPagePopulator(this.repopulate, ['bookFileUpdated', 'bookFileDeleted']);
|
||||
|
||||
if (useCurrentPage) {
|
||||
fetchCutoffUnmet();
|
||||
|
||||
@@ -50,7 +50,7 @@ class MissingConnector extends Component {
|
||||
gotoMissingFirstPage
|
||||
} = this.props;
|
||||
|
||||
registerPagePopulator(this.repopulate, ['bookFileUpdated']);
|
||||
registerPagePopulator(this.repopulate, ['bookFileUpdated', 'bookFileDeleted']);
|
||||
|
||||
if (useCurrentPage) {
|
||||
fetchMissing();
|
||||
|
||||
@@ -4,6 +4,8 @@ import { render } from 'react-dom';
|
||||
import createAppStore from 'Store/createAppStore';
|
||||
import App from './App/App';
|
||||
|
||||
import 'Diag/ConsoleApi';
|
||||
|
||||
export async function bootstrap() {
|
||||
const history = createBrowserHistory();
|
||||
const store = createAppStore(history);
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
"@fortawesome/free-regular-svg-icons": "6.4.0",
|
||||
"@fortawesome/free-solid-svg-icons": "6.4.0",
|
||||
"@fortawesome/react-fontawesome": "0.2.0",
|
||||
"@microsoft/signalr": "6.0.21",
|
||||
"@microsoft/signalr": "6.0.25",
|
||||
"@sentry/browser": "7.51.2",
|
||||
"@sentry/integrations": "7.51.2",
|
||||
"@types/node": "18.16.16",
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<PackageVersion Include="AutoFixture" Version="4.17.0" />
|
||||
<PackageVersion Include="coverlet.collector" Version="3.0.4-preview.27.ge7cb7c3b40" PrivateAssets="all" />
|
||||
<PackageVersion Include="Dapper" Version="2.0.123" />
|
||||
<PackageVersion Include="DryIoc.dll" Version="5.4.1" />
|
||||
<PackageVersion Include="DryIoc.dll" Version="5.4.3" />
|
||||
<PackageVersion Include="DryIoc.Microsoft.DependencyInjection" Version="6.2.0" />
|
||||
<PackageVersion Include="Equ" Version="2.3.0" />
|
||||
<PackageVersion Include="FluentAssertions" Version="5.10.3" />
|
||||
@@ -16,11 +16,11 @@
|
||||
<PackageVersion Include="ImpromptuInterface" Version="7.0.1" />
|
||||
<PackageVersion Include="LazyCache" Version="2.4.0" />
|
||||
<PackageVersion Include="Mailkit" Version="3.6.0" />
|
||||
<PackageVersion Include="Microsoft.AspNetCore.SignalR.Client" Version="6.0.21" />
|
||||
<PackageVersion Include="Microsoft.AspNetCore.SignalR.Client" Version="6.0.25" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="6.0.1" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Configuration" Version="6.0.1" />
|
||||
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="6.0.1" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Hosting.WindowsServices" Version="6.0.1" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Hosting.WindowsServices" Version="6.0.2" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging" Version="6.0.0" />
|
||||
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.4.1" />
|
||||
<PackageVersion Include="Microsoft.Win32.Registry" Version="5.0.0" />
|
||||
@@ -32,7 +32,7 @@
|
||||
<PackageVersion Include="NLog.Extensions.Logging" Version="5.2.3" />
|
||||
<PackageVersion Include="NLog" Version="5.1.4" />
|
||||
<PackageVersion Include="NLog.Targets.Syslog" Version="7.0.0" />
|
||||
<PackageVersion Include="Npgsql" Version="7.0.4" />
|
||||
<PackageVersion Include="Npgsql" Version="7.0.6" />
|
||||
<PackageVersion Include="NUnit3TestAdapter" Version="4.2.1" />
|
||||
<PackageVersion Include="NUnit" Version="3.13.3" />
|
||||
<PackageVersion Include="NunitXml.TestLogger" Version="3.0.117" />
|
||||
@@ -59,7 +59,7 @@
|
||||
<PackageVersion Include="System.Security.Principal.Windows" Version="5.0.0" />
|
||||
<PackageVersion Include="System.ServiceProcess.ServiceController" Version="6.0.1" />
|
||||
<PackageVersion Include="System.Text.Encoding.CodePages" Version="6.0.0" />
|
||||
<PackageVersion Include="System.Text.Json" Version="6.0.8" />
|
||||
<PackageVersion Include="System.Text.Json" Version="6.0.9" />
|
||||
<PackageVersion Include="System.ValueTuple" Version="4.5.0" />
|
||||
<PackageVersion Include="TagLibSharp-Lidarr" Version="2.2.0.19" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -5,12 +5,15 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using FizzWare.NBuilder;
|
||||
using FluentAssertions;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Common.Disk;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Books;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.MediaFiles;
|
||||
using NzbDrone.Core.MediaFiles.Events;
|
||||
using NzbDrone.Core.Messaging.Events;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using NzbDrone.Test.Common;
|
||||
using NzbDrone.Test.Common.AutoMoq;
|
||||
@@ -166,7 +169,7 @@ namespace NzbDrone.Core.Test.MediaFiles.AudioTagServiceFixture
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCaseSource(typeof(TestCaseFactory), "TestCases")]
|
||||
[TestCaseSource(typeof(TestCaseFactory), nameof(TestCaseFactory.TestCases))]
|
||||
public void should_read_duration(string filename, string[] ignored)
|
||||
{
|
||||
var path = Path.Combine(_testdir, filename);
|
||||
@@ -177,7 +180,7 @@ namespace NzbDrone.Core.Test.MediaFiles.AudioTagServiceFixture
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCaseSource(typeof(TestCaseFactory), "TestCases")]
|
||||
[TestCaseSource(typeof(TestCaseFactory), nameof(TestCaseFactory.TestCases))]
|
||||
public void should_read_write_tags(string filename, string[] skipProperties)
|
||||
{
|
||||
GivenFileCopy(filename);
|
||||
@@ -198,7 +201,7 @@ namespace NzbDrone.Core.Test.MediaFiles.AudioTagServiceFixture
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCaseSource(typeof(TestCaseFactory), "TestCases")]
|
||||
[TestCaseSource(typeof(TestCaseFactory), nameof(TestCaseFactory.TestCases))]
|
||||
public void should_read_audiotag_from_file_with_no_tags(string filename, string[] skipProperties)
|
||||
{
|
||||
GivenFileCopy(filename);
|
||||
@@ -220,7 +223,7 @@ namespace NzbDrone.Core.Test.MediaFiles.AudioTagServiceFixture
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCaseSource(typeof(TestCaseFactory), "TestCases")]
|
||||
[TestCaseSource(typeof(TestCaseFactory), nameof(TestCaseFactory.TestCases))]
|
||||
public void should_read_parsedtrackinfo_from_file_with_no_tags(string filename, string[] skipProperties)
|
||||
{
|
||||
GivenFileCopy(filename);
|
||||
@@ -235,7 +238,7 @@ namespace NzbDrone.Core.Test.MediaFiles.AudioTagServiceFixture
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCaseSource(typeof(TestCaseFactory), "TestCases")]
|
||||
[TestCaseSource(typeof(TestCaseFactory), nameof(TestCaseFactory.TestCases))]
|
||||
public void should_set_quality_and_mediainfo_for_corrupt_file(string filename, string[] skipProperties)
|
||||
{
|
||||
// use missing to simulate corrupt
|
||||
@@ -250,7 +253,7 @@ namespace NzbDrone.Core.Test.MediaFiles.AudioTagServiceFixture
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCaseSource(typeof(TestCaseFactory), "TestCases")]
|
||||
[TestCaseSource(typeof(TestCaseFactory), nameof(TestCaseFactory.TestCases))]
|
||||
public void should_read_file_with_only_title_tag(string filename, string[] ignored)
|
||||
{
|
||||
GivenFileCopy(filename);
|
||||
@@ -270,7 +273,7 @@ namespace NzbDrone.Core.Test.MediaFiles.AudioTagServiceFixture
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCaseSource(typeof(TestCaseFactory), "TestCases")]
|
||||
[TestCaseSource(typeof(TestCaseFactory), nameof(TestCaseFactory.TestCases))]
|
||||
public void should_remove_date_from_tags_when_not_in_metadata(string filename, string[] ignored)
|
||||
{
|
||||
GivenFileCopy(filename);
|
||||
@@ -365,6 +368,29 @@ namespace NzbDrone.Core.Test.MediaFiles.AudioTagServiceFixture
|
||||
var fileInfo = _diskProvider.GetFileInfo(file.Path);
|
||||
file.Modified.Should().Be(fileInfo.LastWriteTimeUtc);
|
||||
file.Size.Should().Be(fileInfo.Length);
|
||||
|
||||
Mocker.GetMock<IEventAggregator>()
|
||||
.Verify(v => v.PublishEvent(It.IsAny<BookFileRetaggedEvent>()), Times.Once());
|
||||
}
|
||||
|
||||
[TestCase("nin.mp3")]
|
||||
public void write_tags_should_not_update_tags_if_already_updated(string filename)
|
||||
{
|
||||
Mocker.GetMock<IConfigService>()
|
||||
.Setup(x => x.ScrubAudioTags)
|
||||
.Returns(true);
|
||||
|
||||
GivenFileCopy(filename);
|
||||
|
||||
var file = GivenPopulatedTrackfile(0);
|
||||
|
||||
file.Path = _copiedFile;
|
||||
Subject.WriteTags(file, false, true);
|
||||
Subject.WriteTags(file, false, true);
|
||||
Subject.WriteTags(file, false, true);
|
||||
|
||||
Mocker.GetMock<IEventAggregator>()
|
||||
.Verify(v => v.PublishEvent(It.IsAny<BookFileRetaggedEvent>()), Times.Once());
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
||||
@@ -13,6 +13,7 @@ using NzbDrone.Core.Test.Framework;
|
||||
namespace NzbDrone.Core.Test.MetadataSource.Goodreads
|
||||
{
|
||||
[TestFixture]
|
||||
[Ignore("Waiting for metadata to be back again", Until = "2023-12-31 00:00:00Z")]
|
||||
public class BookInfoProxyFixture : CoreTest<BookInfoProxy>
|
||||
{
|
||||
private MetadataProfile _metadataProfile;
|
||||
|
||||
@@ -15,6 +15,7 @@ using NzbDrone.Test.Common;
|
||||
namespace NzbDrone.Core.Test.MetadataSource.Goodreads
|
||||
{
|
||||
[TestFixture]
|
||||
[Ignore("Waiting for metadata to be back again", Until = "2023-12-31 00:00:00Z")]
|
||||
public class BookInfoProxySearchFixture : CoreTest<BookInfoProxy>
|
||||
{
|
||||
[SetUp]
|
||||
|
||||
@@ -322,6 +322,20 @@ namespace NzbDrone.Core.Configuration
|
||||
}
|
||||
}
|
||||
|
||||
public void MigrateConfigFile()
|
||||
{
|
||||
if (!File.Exists(_configFile))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// If SSL is enabled and a cert hash is still in the config file disable SSL
|
||||
if (EnableSsl && GetValue("SslCertHash", null).IsNotNullOrWhiteSpace())
|
||||
{
|
||||
SetValue("EnableSsl", false);
|
||||
}
|
||||
}
|
||||
|
||||
private void DeleteOldValues()
|
||||
{
|
||||
var xDoc = LoadConfigFile();
|
||||
@@ -404,6 +418,7 @@ namespace NzbDrone.Core.Configuration
|
||||
|
||||
public void HandleAsync(ApplicationStartedEvent message)
|
||||
{
|
||||
MigrateConfigFile();
|
||||
EnsureDefaultConfigFile();
|
||||
DeleteOldValues();
|
||||
}
|
||||
|
||||
@@ -9,9 +9,9 @@ namespace NzbDrone.Core.Datastore
|
||||
{
|
||||
public interface IConnectionStringFactory
|
||||
{
|
||||
string MainDbConnectionString { get; }
|
||||
string LogDbConnectionString { get; }
|
||||
string CacheDbConnectionString { get; }
|
||||
DatabaseConnectionInfo MainDbConnection { get; }
|
||||
DatabaseConnectionInfo LogDbConnection { get; }
|
||||
DatabaseConnectionInfo CacheDbConnection { get; }
|
||||
string GetDatabasePath(string connectionString);
|
||||
}
|
||||
|
||||
@@ -23,19 +23,19 @@ namespace NzbDrone.Core.Datastore
|
||||
{
|
||||
_configFileProvider = configFileProvider;
|
||||
|
||||
MainDbConnectionString = _configFileProvider.PostgresHost.IsNotNullOrWhiteSpace() ? GetPostgresConnectionString(_configFileProvider.PostgresMainDb) :
|
||||
MainDbConnection = _configFileProvider.PostgresHost.IsNotNullOrWhiteSpace() ? GetPostgresConnectionString(_configFileProvider.PostgresMainDb) :
|
||||
GetConnectionString(appFolderInfo.GetDatabase());
|
||||
|
||||
LogDbConnectionString = _configFileProvider.PostgresHost.IsNotNullOrWhiteSpace() ? GetPostgresConnectionString(_configFileProvider.PostgresLogDb) :
|
||||
LogDbConnection = _configFileProvider.PostgresHost.IsNotNullOrWhiteSpace() ? GetPostgresConnectionString(_configFileProvider.PostgresLogDb) :
|
||||
GetConnectionString(appFolderInfo.GetLogDatabase());
|
||||
|
||||
CacheDbConnectionString = _configFileProvider.PostgresHost.IsNotNullOrWhiteSpace() ? GetPostgresConnectionString(_configFileProvider.PostgresCacheDb) :
|
||||
CacheDbConnection = _configFileProvider.PostgresHost.IsNotNullOrWhiteSpace() ? GetPostgresConnectionString(_configFileProvider.PostgresCacheDb) :
|
||||
GetConnectionString(appFolderInfo.GetCacheDatabase());
|
||||
}
|
||||
|
||||
public string MainDbConnectionString { get; private set; }
|
||||
public string LogDbConnectionString { get; private set; }
|
||||
public string CacheDbConnectionString { get; private set; }
|
||||
public DatabaseConnectionInfo MainDbConnection { get; private set; }
|
||||
public DatabaseConnectionInfo LogDbConnection { get; private set; }
|
||||
public DatabaseConnectionInfo CacheDbConnection { get; private set; }
|
||||
|
||||
public string GetDatabasePath(string connectionString)
|
||||
{
|
||||
@@ -44,7 +44,7 @@ namespace NzbDrone.Core.Datastore
|
||||
return connectionBuilder.DataSource;
|
||||
}
|
||||
|
||||
private static string GetConnectionString(string dbPath)
|
||||
private static DatabaseConnectionInfo GetConnectionString(string dbPath)
|
||||
{
|
||||
var connectionBuilder = new SQLiteConnectionStringBuilder
|
||||
{
|
||||
@@ -62,21 +62,22 @@ namespace NzbDrone.Core.Datastore
|
||||
connectionBuilder.Add("Full FSync", true);
|
||||
}
|
||||
|
||||
return connectionBuilder.ConnectionString;
|
||||
return new DatabaseConnectionInfo(DatabaseType.SQLite, connectionBuilder.ConnectionString);
|
||||
}
|
||||
|
||||
private string GetPostgresConnectionString(string dbName)
|
||||
private DatabaseConnectionInfo GetPostgresConnectionString(string dbName)
|
||||
{
|
||||
var connectionBuilder = new NpgsqlConnectionStringBuilder();
|
||||
var connectionBuilder = new NpgsqlConnectionStringBuilder
|
||||
{
|
||||
Database = dbName,
|
||||
Host = _configFileProvider.PostgresHost,
|
||||
Username = _configFileProvider.PostgresUser,
|
||||
Password = _configFileProvider.PostgresPassword,
|
||||
Port = _configFileProvider.PostgresPort,
|
||||
Enlist = false
|
||||
};
|
||||
|
||||
connectionBuilder.Database = dbName;
|
||||
connectionBuilder.Host = _configFileProvider.PostgresHost;
|
||||
connectionBuilder.Username = _configFileProvider.PostgresUser;
|
||||
connectionBuilder.Password = _configFileProvider.PostgresPassword;
|
||||
connectionBuilder.Port = _configFileProvider.PostgresPort;
|
||||
connectionBuilder.Enlist = false;
|
||||
|
||||
return connectionBuilder.ConnectionString;
|
||||
return new DatabaseConnectionInfo(DatabaseType.PostgreSQL, connectionBuilder.ConnectionString);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
14
src/NzbDrone.Core/Datastore/DatabaseConnectionInfo.cs
Normal file
14
src/NzbDrone.Core/Datastore/DatabaseConnectionInfo.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
namespace NzbDrone.Core.Datastore
|
||||
{
|
||||
public class DatabaseConnectionInfo
|
||||
{
|
||||
public DatabaseConnectionInfo(DatabaseType databaseType, string connectionString)
|
||||
{
|
||||
DatabaseType = databaseType;
|
||||
ConnectionString = connectionString;
|
||||
}
|
||||
|
||||
public DatabaseType DatabaseType { get; internal set; }
|
||||
public string ConnectionString { get; internal set; }
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ using System;
|
||||
using System.Data.Common;
|
||||
using System.Data.SQLite;
|
||||
using System.Net.Sockets;
|
||||
using System.Threading;
|
||||
using NLog;
|
||||
using Npgsql;
|
||||
using NzbDrone.Common.Disk;
|
||||
@@ -59,30 +60,30 @@ namespace NzbDrone.Core.Datastore
|
||||
|
||||
public IDatabase Create(MigrationContext migrationContext)
|
||||
{
|
||||
string connectionString;
|
||||
DatabaseConnectionInfo connectionInfo;
|
||||
|
||||
switch (migrationContext.MigrationType)
|
||||
{
|
||||
case MigrationType.Main:
|
||||
{
|
||||
connectionString = _connectionStringFactory.MainDbConnectionString;
|
||||
CreateMain(connectionString, migrationContext);
|
||||
connectionInfo = _connectionStringFactory.MainDbConnection;
|
||||
CreateMain(connectionInfo.ConnectionString, migrationContext, connectionInfo.DatabaseType);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case MigrationType.Log:
|
||||
{
|
||||
connectionString = _connectionStringFactory.LogDbConnectionString;
|
||||
CreateLog(connectionString, migrationContext);
|
||||
connectionInfo = _connectionStringFactory.LogDbConnection;
|
||||
CreateLog(connectionInfo.ConnectionString, migrationContext, connectionInfo.DatabaseType);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case MigrationType.Cache:
|
||||
{
|
||||
connectionString = _connectionStringFactory.CacheDbConnectionString;
|
||||
CreateLog(connectionString, migrationContext);
|
||||
connectionInfo = _connectionStringFactory.CacheDbConnection;
|
||||
CreateLog(connectionInfo.ConnectionString, migrationContext, connectionInfo.DatabaseType);
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -97,14 +98,14 @@ namespace NzbDrone.Core.Datastore
|
||||
{
|
||||
DbConnection conn;
|
||||
|
||||
if (connectionString.Contains(".db"))
|
||||
if (connectionInfo.DatabaseType == DatabaseType.SQLite)
|
||||
{
|
||||
conn = SQLiteFactory.Instance.CreateConnection();
|
||||
conn.ConnectionString = connectionString;
|
||||
conn.ConnectionString = connectionInfo.ConnectionString;
|
||||
}
|
||||
else
|
||||
{
|
||||
conn = new NpgsqlConnection(connectionString);
|
||||
conn = new NpgsqlConnection(connectionInfo.ConnectionString);
|
||||
}
|
||||
|
||||
conn.Open();
|
||||
@@ -114,12 +115,12 @@ namespace NzbDrone.Core.Datastore
|
||||
return db;
|
||||
}
|
||||
|
||||
private void CreateMain(string connectionString, MigrationContext migrationContext)
|
||||
private void CreateMain(string connectionString, MigrationContext migrationContext, DatabaseType databaseType)
|
||||
{
|
||||
try
|
||||
{
|
||||
_restoreDatabaseService.Restore();
|
||||
_migrationController.Migrate(connectionString, migrationContext);
|
||||
_migrationController.Migrate(connectionString, migrationContext, databaseType);
|
||||
}
|
||||
catch (SQLiteException e)
|
||||
{
|
||||
@@ -142,15 +143,17 @@ namespace NzbDrone.Core.Datastore
|
||||
{
|
||||
Logger.Error(e, "Failure to connect to Postgres DB, {0} retries remaining", retryCount);
|
||||
|
||||
Thread.Sleep(5000);
|
||||
|
||||
try
|
||||
{
|
||||
_migrationController.Migrate(connectionString, migrationContext);
|
||||
_migrationController.Migrate(connectionString, migrationContext, databaseType);
|
||||
return;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (--retryCount > 0)
|
||||
{
|
||||
System.Threading.Thread.Sleep(5000);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -169,11 +172,11 @@ namespace NzbDrone.Core.Datastore
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateLog(string connectionString, MigrationContext migrationContext)
|
||||
private void CreateLog(string connectionString, MigrationContext migrationContext, DatabaseType databaseType)
|
||||
{
|
||||
try
|
||||
{
|
||||
_migrationController.Migrate(connectionString, migrationContext);
|
||||
_migrationController.Migrate(connectionString, migrationContext, databaseType);
|
||||
}
|
||||
catch (SQLiteException e)
|
||||
{
|
||||
@@ -193,7 +196,7 @@ namespace NzbDrone.Core.Datastore
|
||||
Logger.Error("Unable to recreate logging database automatically. It will need to be removed manually.");
|
||||
}
|
||||
|
||||
_migrationController.Migrate(connectionString, migrationContext);
|
||||
_migrationController.Migrate(connectionString, migrationContext, databaseType);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace NzbDrone.Core.Datastore.Migration.Framework
|
||||
{
|
||||
public interface IMigrationController
|
||||
{
|
||||
void Migrate(string connectionString, MigrationContext migrationContext);
|
||||
void Migrate(string connectionString, MigrationContext migrationContext, DatabaseType databaseType);
|
||||
}
|
||||
|
||||
public class MigrationController : IMigrationController
|
||||
@@ -29,7 +29,7 @@ namespace NzbDrone.Core.Datastore.Migration.Framework
|
||||
_migrationLoggerProvider = migrationLoggerProvider;
|
||||
}
|
||||
|
||||
public void Migrate(string connectionString, MigrationContext migrationContext)
|
||||
public void Migrate(string connectionString, MigrationContext migrationContext, DatabaseType databaseType)
|
||||
{
|
||||
var sw = Stopwatch.StartNew();
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace NzbDrone.Core.Datastore.Migration.Framework
|
||||
|
||||
ServiceProvider serviceProvider;
|
||||
|
||||
var db = connectionString.Contains(".db") ? "sqlite" : "postgres";
|
||||
var db = databaseType == DatabaseType.SQLite ? "sqlite" : "postgres";
|
||||
|
||||
serviceProvider = new ServiceCollection()
|
||||
.AddLogging(b => b.AddNLog())
|
||||
|
||||
@@ -53,7 +53,6 @@ namespace NzbDrone.Core.Indexers.Newznab
|
||||
yield return GetDefinition("NZBFinder.ws", GetSettings("https://nzbfinder.ws"));
|
||||
yield return GetDefinition("NZBgeek", GetSettings("https://api.nzbgeek.info"));
|
||||
yield return GetDefinition("nzbplanet.net", GetSettings("https://api.nzbplanet.net"));
|
||||
yield return GetDefinition("OZnzb.com", GetSettings("https://api.oznzb.com"));
|
||||
yield return GetDefinition("SimplyNZBs", GetSettings("https://simplynzbs.com"));
|
||||
yield return GetDefinition("Tabula Rasa", GetSettings("https://www.tabula-rasa.pw", apiPath: @"/api/v1/api"));
|
||||
yield return GetDefinition("Usenet Crawler", GetSettings("https://www.usenet-crawler.com"));
|
||||
|
||||
@@ -85,16 +85,15 @@ namespace NzbDrone.Core.Instrumentation
|
||||
|
||||
log.Level = logEvent.Level.Name;
|
||||
|
||||
var connectionString = _connectionStringFactory.LogDbConnectionString;
|
||||
var connectionInfo = _connectionStringFactory.LogDbConnection;
|
||||
|
||||
//TODO: Probably need more robust way to differentiate what's being used
|
||||
if (connectionString.Contains(".db"))
|
||||
if (connectionInfo.DatabaseType == DatabaseType.SQLite)
|
||||
{
|
||||
WriteSqliteLog(log, connectionString);
|
||||
WriteSqliteLog(log, connectionInfo.ConnectionString);
|
||||
}
|
||||
else
|
||||
{
|
||||
WritePostgresLog(log, connectionString);
|
||||
WritePostgresLog(log, connectionInfo.ConnectionString);
|
||||
}
|
||||
}
|
||||
catch (SQLiteException ex)
|
||||
|
||||
@@ -80,19 +80,19 @@
|
||||
"DeleteDelayProfile": "Odstranění profilu zpoždění",
|
||||
"DeleteDelayProfileMessageText": "Opravdu chcete smazat tento profil zpoždění?",
|
||||
"DeleteDownloadClient": "Odstranění klienta pro stahování",
|
||||
"DeleteDownloadClientMessageText": "Opravdu chcete odstranit klienta pro stahování „{0}“?",
|
||||
"DeleteDownloadClientMessageText": "Opravdu chcete odstranit klienta pro stahování '{name}'?",
|
||||
"DeleteEmptyFolders": "Odstraňte prázdné složky",
|
||||
"DeleteEmptyFoldersHelpText": "Během skenování disku a při mazání filmových souborů odstraňte prázdné složky s filmy",
|
||||
"DeleteImportListExclusion": "Odstranit vyloučení seznamu importů",
|
||||
"DeleteImportListExclusionMessageText": "Opravdu chcete toto vyloučení importního seznamu smazat?",
|
||||
"DeleteImportListMessageText": "Opravdu chcete smazat seznam „{0}“?",
|
||||
"DeleteImportListMessageText": "Opravdu chcete smazat seznam '{name}'?",
|
||||
"DeleteIndexer": "Odstranit indexer",
|
||||
"DeleteIndexerMessageText": "Opravdu chcete odstranit indexer „{0}“?",
|
||||
"DeleteMetadataProfileMessageText": "Opravdu chcete smazat kvalitní profil {0}",
|
||||
"DeleteIndexerMessageText": "Opravdu chcete odstranit indexer '{name}'?",
|
||||
"DeleteMetadataProfileMessageText": "Opravdu chcete smazat profil metadat '{name}'?",
|
||||
"DeleteNotification": "Smazat oznámení",
|
||||
"DeleteNotificationMessageText": "Opravdu chcete smazat oznámení „{0}“?",
|
||||
"DeleteNotificationMessageText": "Opravdu chcete smazat oznámení '{name}'?",
|
||||
"DeleteQualityProfile": "Smažte profil kvality",
|
||||
"DeleteQualityProfileMessageText": "Opravdu chcete smazat kvalitní profil {0}",
|
||||
"DeleteQualityProfileMessageText": "Opravdu chcete smazat profil kvality '{name}'?",
|
||||
"DeleteReleaseProfile": "Smazat profil zpoždění",
|
||||
"DeleteReleaseProfileMessageText": "Opravdu chcete smazat tento profil zpoždění?",
|
||||
"DeleteSelectedBookFiles": "Odstranit vybrané filmové soubory",
|
||||
@@ -588,23 +588,23 @@
|
||||
"Required": "Požadované",
|
||||
"NoEventsFound": "Nebyly nalezeny žádné události",
|
||||
"RedownloadFailed": "Stažení se nezdařilo",
|
||||
"DeleteSelectedImportListsMessageText": "Opravdu chcete odstranit indexer „{0}“?",
|
||||
"DeleteSelectedImportListsMessageText": "Opravdu chcete smazat {count} vybraných seznamů k importu?",
|
||||
"DeleteSelectedIndexers": "Odstranit indexer",
|
||||
"ExistingTag": "Stávající značka",
|
||||
"ApplyTagsHelpTextHowToApplyAuthors": "Jak použít značky na vybrané filmy",
|
||||
"DeleteSelectedDownloadClientsMessageText": "Opravdu chcete odstranit indexer „{0}“?",
|
||||
"DeleteSelectedDownloadClientsMessageText": "Opravdu chcete smazat {count} vybraných klientů pro stahování?",
|
||||
"No": "Ne",
|
||||
"NoChange": "Žádná změna",
|
||||
"RemovingTag": "Odebírání značky",
|
||||
"SetTags": "Nastavit značky",
|
||||
"ApplyTagsHelpTextAdd": "Přidat: Přidá značky k již existujícímu seznamu",
|
||||
"ApplyTagsHelpTextHowToApplyDownloadClients": "Jak použít značky na vybrané klienty pro stahování",
|
||||
"ApplyTagsHelpTextHowToApplyImportLists": "Jak použít značky na vybrané importní seznamy",
|
||||
"ApplyTagsHelpTextHowToApplyIndexers": "Jak použít značky na vybrané indexátory",
|
||||
"ApplyTagsHelpTextHowToApplyImportLists": "Jak použít značky na vybrané seznamy k importu",
|
||||
"ApplyTagsHelpTextHowToApplyIndexers": "Jak použít značky na vybrané indexery",
|
||||
"ApplyTagsHelpTextRemove": "Odebrat: Odebrat zadané značky",
|
||||
"ApplyTagsHelpTextReplace": "Nahradit: Nahradit značky zadanými značkami (zadáním žádné značky vymažete všechny značky)",
|
||||
"DeleteSelectedDownloadClients": "Odstranit staženého klienta",
|
||||
"DeleteSelectedIndexersMessageText": "Opravdu chcete odstranit indexer „{0}“?",
|
||||
"ApplyTagsHelpTextReplace": "Nahradit: Nahradit značky zadanými značkami (prázdné pole vymaže všechny značky)",
|
||||
"DeleteSelectedDownloadClients": "Odstranit klienta pro stahování",
|
||||
"DeleteSelectedIndexersMessageText": "Opravdu chcete smazat {count} vybraný(ch) indexer(ů)?",
|
||||
"Yes": "Ano",
|
||||
"NotificationStatusAllClientHealthCheckMessage": "Všechny seznamy nejsou k dispozici z důvodu selhání",
|
||||
"Small": "Malý",
|
||||
@@ -624,7 +624,7 @@
|
||||
"TotalSpace": "Celkový prostor",
|
||||
"ConnectionLost": "Spojení ztraceno",
|
||||
"ConnectionLostReconnect": "{appName} se pokusí připojit automaticky, nebo můžete kliknout na tlačítko znovunačtení níže.",
|
||||
"ConnectionLostToBackend": "{appName} ztratila spojení s backendem a pro obnovení funkčnosti bude třeba ji znovu načíst.",
|
||||
"ConnectionLostToBackend": "{appName} ztratil spojení s backendem a pro obnovení funkčnosti bude třebaho znovu načíst.",
|
||||
"Large": "Velký",
|
||||
"LastDuration": "lastDuration",
|
||||
"Ui": "UI",
|
||||
@@ -645,8 +645,8 @@
|
||||
"CloneCondition": "Klonovat podmínku",
|
||||
"Clone": "Klonovat",
|
||||
"ApiKeyValidationHealthCheckMessage": "Aktualizujte svůj klíč API tak, aby měl alespoň {0} znaků. Můžete to provést prostřednictvím nastavení nebo konfiguračního souboru",
|
||||
"ChooseImportMethod": "Vyberte mód importu",
|
||||
"CatalogNumber": "katalogové číslo",
|
||||
"ChooseImportMethod": "Vyberte způsob importu",
|
||||
"CatalogNumber": "Katalogové číslo",
|
||||
"Publisher": "Vydavatel",
|
||||
"StatusEndedContinuing": "Pokračující",
|
||||
"MetadataProfiles": "profil metadat",
|
||||
@@ -655,7 +655,7 @@
|
||||
"Label": "Etiketa",
|
||||
"Library": "Knihovna",
|
||||
"BypassIfAboveCustomFormatScore": "Obejít, pokud je vyšší než skóre vlastního formátu",
|
||||
"AppUpdatedVersion": "{appName} byla aktualizována na verzi `{version}`, abyste získali nejnovější změny, musíte znovu načíst {appName}.",
|
||||
"AppUpdatedVersion": "{appName} byl aktualizován na verzi `{version}`, abyste získali nejnovější změny, musíte znovu načíst {appName}",
|
||||
"BypassIfAboveCustomFormatScoreHelpText": "Povolit obcházení, pokud má vydání vyšší skóre, než je nakonfigurované minimální skóre vlastního formátu",
|
||||
"BypassIfHighestQuality": "Obejít v případě nejvyšší kvality",
|
||||
"Theme": "Motiv",
|
||||
@@ -666,5 +666,19 @@
|
||||
"CountDownloadClientsSelected": "{count} vybraných klientů ke stahování",
|
||||
"ImportListMissingRoot": "Chybí kořenový adresář pro import seznamu: {0}",
|
||||
"IndexerDownloadClientHelpText": "Zvolte, který klient pro stahování bude použit pro zachytávání z toho indexeru",
|
||||
"ImportListMultipleMissingRoots": "Několik kořenových adresářů chybí pro seznamy importu: {0}"
|
||||
"ImportListMultipleMissingRoots": "Několik kořenových adresářů chybí pro seznamy importu: {0}",
|
||||
"EditSelectedDownloadClients": "Upravit vybrané klienty pro stahování",
|
||||
"EditSelectedIndexers": "Upravit vybrané indexery",
|
||||
"EnableProfile": "Povolit profil",
|
||||
"DeleteImportList": "Smazat seznam importovaných položek",
|
||||
"AddNewItem": "Přidat novou položku",
|
||||
"AddMissing": "Přidat chybějící",
|
||||
"EditSelectedImportLists": "Upravit vybrané seznamy k importu",
|
||||
"DeleteSelectedImportLists": "Smazat seznam k importu",
|
||||
"Duration": "Trvání",
|
||||
"DeleteRootFolder": "Smazat kořenový adresář",
|
||||
"DownloadClientTagHelpText": "Tohoto klienta pro stahování používat pouze pro filmy s alespoň jednou odpovídající značkou. Pro použití se všemi filmy ponechte prázdné pole.",
|
||||
"AddedAuthorSettings": "Nastavení umělce přidáno",
|
||||
"DownloadClientRemovesCompletedDownloadsHealthCheckMessage": "Klient stahování {downloadClientName} je nastaven na odstranění dokončených stahování. To může vést k tomu, že stahování budou z klienta odstraněna dříve, než je bude moci importovat {1}.",
|
||||
"IndexerTagsHelpText": "Tohoto klienta pro stahování používat pouze pro filmy s alespoň jednou odpovídající značkou. Pro použití se všemi filmy ponechte prázdné pole."
|
||||
}
|
||||
|
||||
@@ -240,32 +240,32 @@
|
||||
"PortNumber": "Port Nummer",
|
||||
"PosterSize": "Plakatgröße",
|
||||
"Profiles": "Profile",
|
||||
"Proper": "Proper",
|
||||
"Proper": "Korrekt",
|
||||
"PropersAndRepacks": "Propers und Repacks",
|
||||
"Protocol": "Protokoll",
|
||||
"ProtocolHelpText": "Wählen Sie, welche(s) Protokoll(e) verwendet werden soll(en) und welches Protokoll bei der Wahl zwischen ansonsten gleichwertigen Releases bevorzugt wird",
|
||||
"ProtocolHelpText": "Wählen Sie aus, welche(s) Protokoll(e) Sie verwenden möchten und welches Protokoll Sie bevorzugen, wenn Sie zwischen ansonsten gleichen Versionen wählen",
|
||||
"Proxy": "Proxy",
|
||||
"ProxyBypassFilterHelpText": "Verwende ',' als Trennzeichen und '*.' als Platzhalter für Subdomains",
|
||||
"ProxyPasswordHelpText": "Nur wenn ein Benutzername und Passwort erforderlich ist, muss es eingegeben werden. Ansonsten leer lassen.",
|
||||
"ProxyType": "Proxy Typ",
|
||||
"PublishedDate": "Veröffentlichungs Datum",
|
||||
"ProxyBypassFilterHelpText": "Verwenden Sie ',' als Trennzeichen und '*.' als Wildcard für Subdomains",
|
||||
"ProxyPasswordHelpText": "Sie müssen nur einen Benutzernamen und ein Passwort eingeben, wenn dies erforderlich ist. Andernfalls lassen Sie sie leer.",
|
||||
"ProxyType": "Proxy-Typ",
|
||||
"PublishedDate": "Veröffentlichungsdatum",
|
||||
"Quality": "Qualität",
|
||||
"QualityDefinitions": "Qualitätsdefinitionen",
|
||||
"QualityProfile": "Qualitätsprofil",
|
||||
"QualityProfiles": "Qualitätsprofile",
|
||||
"QualitySettings": "Qualitäts Einstellungen",
|
||||
"QualitySettings": "Qualitätseinstellungen",
|
||||
"Queue": "Warteschlange",
|
||||
"RSSSync": "RSS-Sync",
|
||||
"RSSSyncInterval": "RSS Synchronisierungs Intervall",
|
||||
"ReadTheWikiForMoreInformation": "Lese das Wiki für mehr Informationen",
|
||||
"ReadTheWikiForMoreInformation": "Lesen Sie das Wiki für weitere Informationen",
|
||||
"ReadarrSupportsAnyIndexerThatUsesTheNewznabStandardAsWellAsOtherIndexersListedBelow": "Jeder Indexer der den Newznab-Standard verwendet oder unten aufgelistet ist wird untertützt.",
|
||||
"ReadarrTags": "Radarr Tags",
|
||||
"Real": "Echt",
|
||||
"Reason": "Grund",
|
||||
"Real": "Real",
|
||||
"Reason": "Begründung",
|
||||
"RecycleBinCleanupDaysHelpText": "Auf 0 setzen um das automatische leeren des Papierkorbs zu deaktivieren",
|
||||
"RecycleBinCleanupDaysHelpTextWarning": "Datien im Papierkorb die älter sind als der gewählte Wert, werden endgültig gelöscht",
|
||||
"RecycleBinHelpText": "Gelöschte Filmdateien werden hierher verschoben anstatt sie direkt endgültig zu löschen",
|
||||
"RecyclingBinCleanup": "Papierkorb aufräumen",
|
||||
"RecyclingBinCleanup": "Papierkorb leeren",
|
||||
"Redownload": "Nochmal herunterladen",
|
||||
"Refresh": "Aktualisieren",
|
||||
"RefreshInformationAndScanDisk": "Metadaten aktualisieren und Festplatte scannen",
|
||||
@@ -435,7 +435,7 @@
|
||||
"YesCancel": "Ja, abbrechen",
|
||||
"BindAddressHelpTextWarning": "Erfordert einen Neustart",
|
||||
"LoadingBooksFailed": "Laden der Film-Dateien fehlgeschlagen",
|
||||
"ProxyUsernameHelpText": "Nur wenn ein Benutzername und Passwort erforderlich ist, muss es eingegeben werden. Ansonsten leer lassen.",
|
||||
"ProxyUsernameHelpText": "Sie müssen nur einen Benutzernamen und ein Passwort eingeben, wenn dies erforderlich ist. Andernfalls lassen Sie sie leer.",
|
||||
"SslPortHelpTextWarning": "Erfordert einen Neustart",
|
||||
"UnableToLoadMetadataProfiles": "Verzögerungsprofile konnten nicht geladen werden",
|
||||
"ApiKeyHelpTextWarning": "Erfordert einen Neustart",
|
||||
@@ -694,8 +694,8 @@
|
||||
"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",
|
||||
"RefreshAndScan": "Aktualisieren",
|
||||
"Queued": "In Warteschlange",
|
||||
"RefreshAndScan": "Aktualisieren und scannen",
|
||||
"SettingsRemotePathMappingRemotePathHelpText": "Root-Pfad zum Verzeichnis, auf das der Download-Client zugreift",
|
||||
"Yesterday": "Gestern",
|
||||
"UpdateAvailable": "Neue Version verfügbar",
|
||||
@@ -750,8 +750,8 @@
|
||||
"IfYouDontAddAnImportListExclusionAndTheAuthorHasAMetadataProfileOtherThanNoneThenThisBookMayBeReaddedDuringTheNextAuthorRefresh": "Wenn kein Ausschluss der Import Liste hinzugefügt wird und der Künstler ein anderes Metadaten Profil als 'Keine' hat, kann es passieren, dass dieses Album bei der nächsten Aktualisierung des Künstlers erneut hinzugefügt wird.",
|
||||
"MissingFromDisk": "Radarr konnte die Datei nicht auf der Festplatte finden, daher wurde die Verknüpfung auf die Datei aus der Datenbank entfernt",
|
||||
"ProxyCheckResolveIpMessage": "Fehler beim Auflösen der IP-Adresse für den konfigurierten Proxy-Host {0}",
|
||||
"QualitySettingsSummary": "Qualitätgrößen und Bennenung",
|
||||
"QueueIsEmpty": "Warteschlange ist leer",
|
||||
"QualitySettingsSummary": "Qualitätsgrößen und Namensgebung",
|
||||
"QueueIsEmpty": "Die Warteschlange ist leer",
|
||||
"ReadarrSupportsMultipleListsForImportingBooksAndAuthorsIntoTheDatabase": "Lidarr unterstützt mehrere Listen für den Import von Alben und Künstlern in die Datenbank.",
|
||||
"TotalBookCountBooksTotalBookFileCountBooksWithFilesInterp": "{0} Titel insgesamt. {1} Titel mit Dateien.",
|
||||
"SearchFiltered": "Suche gefilterte",
|
||||
@@ -985,7 +985,7 @@
|
||||
"ConnectionLost": "Verbindung unterbrochen",
|
||||
"Events": "Events",
|
||||
"LastDuration": "Letzte Dauer",
|
||||
"RecentChanges": "Neuste Änderungen",
|
||||
"RecentChanges": "Kürzliche Änderungen",
|
||||
"System": "System",
|
||||
"WhatsNew": "Was gibt's Neues?",
|
||||
"NextExecution": "Nächste Ausführung",
|
||||
@@ -993,7 +993,9 @@
|
||||
"SomeResultsAreHiddenByTheAppliedFilter": "Einige Ergebnisse werden wegen der aktiven Filter nicht angezeigt",
|
||||
"Medium": "Medium",
|
||||
"Activity": "Aktivität",
|
||||
"AddNew": "Hinzufügen",
|
||||
"AddNew": "Neue hinzufügen",
|
||||
"Backup": "Backups",
|
||||
"AllResultsAreHiddenByTheAppliedFilter": "Keine Ergebnisse mit den ausgewählten Filtern"
|
||||
"AllResultsAreHiddenByTheAppliedFilter": "Keine Ergebnisse mit den ausgewählten Filtern",
|
||||
"AppUpdated": "{appName} aktualisiert",
|
||||
"AppUpdatedVersion": "{appName} wurde auf die Version `{version}` aktualisiert. Um die neusten Funktionen zu bekommen lade {appName} neu"
|
||||
}
|
||||
|
||||
@@ -317,8 +317,8 @@
|
||||
"ExistingTag": "Existing tag",
|
||||
"ExistingTagsScrubbed": "Existing tags scrubbed",
|
||||
"ExportCustomFormat": "Export Custom Format",
|
||||
"ExtraFileExtensionsHelpTexts1": "Comma separated list of extra files to import (.nfo will be imported as .nfo-orig)",
|
||||
"ExtraFileExtensionsHelpTexts2": "Examples: \".sub, .nfo\" or \"sub,nfo\"",
|
||||
"ExtraFileExtensionsHelpText": "Comma separated list of extra files to import (.nfo will be imported as .nfo-orig)",
|
||||
"ExtraFileExtensionsHelpTextsExamples": "Examples: '.sub, .nfo' or 'sub,nfo'",
|
||||
"FailedDownloadHandling": "Failed Download Handling",
|
||||
"FailedToLoadQueue": "Failed to load Queue",
|
||||
"FileDateHelpText": "Change file date on import/rescan",
|
||||
|
||||
@@ -14,11 +14,11 @@
|
||||
"60MinutesSixty": "60 Minutos: {0}",
|
||||
"APIKey": "Clave API",
|
||||
"About": "Acerca de",
|
||||
"AddListExclusion": "Añadir Exclusión De Lista",
|
||||
"AddListExclusion": "Agregar Lista de Exclusión",
|
||||
"AddingTag": "Añadir etiqueta",
|
||||
"AgeWhenGrabbed": "Antigüedad (cuando se añadió)",
|
||||
"AlreadyInYourLibrary": "Ya en tu biblioteca",
|
||||
"AlternateTitles": "Título alternativo",
|
||||
"AlternateTitles": "Titulos alternativos",
|
||||
"Analytics": "Analíticas",
|
||||
"AnalyticsEnabledHelpText": "Envíe información anónima de uso y error a los servidores de Radarr. Esto incluye información sobre su navegador, qué páginas de Radarr WebUI utiliza, informes de errores, así como el sistema operativo y la versión en tiempo de ejecución. Usaremos esta información para priorizar funciones y correcciones de errores.",
|
||||
"AnalyticsEnabledHelpTextWarning": "Requiere reiniciar para que surta efecto",
|
||||
@@ -45,9 +45,9 @@
|
||||
"CalendarWeekColumnHeaderHelpText": "Mostrado sobre cada columna cuando la vista activa es semana",
|
||||
"Cancel": "Cancelar",
|
||||
"CancelMessageText": "Seguro que quieres cancelar esta tarea pendiente?",
|
||||
"CertificateValidation": "Validación del certificado",
|
||||
"CertificateValidationHelpText": "Cambiar la rigidez de la validación de la certificación HTTPS",
|
||||
"ChangeFileDate": "Cambiar Fecha de Archivo",
|
||||
"CertificateValidation": "Validacion de certificado",
|
||||
"CertificateValidationHelpText": "Cambiar como es la validacion de la certificacion estricta de HTTPS. No cambiar a menos que entiendas las consecuencias.",
|
||||
"ChangeFileDate": "Cambiar fecha de archivo",
|
||||
"ChangeHasNotBeenSavedYet": "El cambio aún no se ha guardado",
|
||||
"ChmodFolder": "Carpeta chmod",
|
||||
"ChmodFolderHelpText": "Octal, aplicado durante la importación / cambio de nombre a carpetas y archivos multimedia (sin bits de ejecución)",
|
||||
@@ -56,12 +56,7 @@
|
||||
"ChownGroupHelpTextWarning": "Esto solo funciona si el usuario que ejecuta Radarr es el propietario del archivo. Es mejor asegurarse de que el cliente de descarga use el mismo grupo que Radarr.",
|
||||
"Clear": "Borrar",
|
||||
"ClickToChangeQuality": "Clic para cambiar la calidad",
|
||||
"ClientPriority": "Prioridad de Cliente",
|
||||
"CloneIndexer": "Clonar Indexer",
|
||||
"CloneProfile": "Clonar Perfil",
|
||||
"Close": "Cerrar",
|
||||
"Columns": "Columnas",
|
||||
"CompletedDownloadHandling": "Manipulación de descargas completas",
|
||||
"ConnectSettings": "Conectar Ajustes",
|
||||
"Connections": "Conexiones",
|
||||
"CopyUsingHardlinksHelpText": "Usar Hardlinks al intentar copiar ficheros de los torrents que siguen seedeando",
|
||||
@@ -89,7 +84,7 @@
|
||||
"DeleteImportListMessageText": "Seguro que quieres eliminar la lista '{name}'?",
|
||||
"DeleteIndexer": "Borrar Indexer",
|
||||
"DeleteIndexerMessageText": "Seguro que quieres eliminar el indexer '{name}'?",
|
||||
"DeleteMetadataProfileMessageText": "Seguro que quieres eliminar el perfil de calidad {0}",
|
||||
"DeleteMetadataProfileMessageText": "¿Seguro que quieres eliminar el perfil de metadatos '{name}'?",
|
||||
"DeleteNotification": "Borrar Notificación",
|
||||
"DeleteNotificationMessageText": "¿Seguro que quieres eliminiar la notificación '{name}'?",
|
||||
"DeleteQualityProfile": "Borrar Perfil de Calidad",
|
||||
@@ -154,7 +149,7 @@
|
||||
"GrabSelected": "Capturar Seleccionados",
|
||||
"HasPendingChangesNoChanges": "Sin Cambios",
|
||||
"HasPendingChangesSaveChanges": "Guardar Cambios",
|
||||
"History": "Historia",
|
||||
"History": "Historial",
|
||||
"Host": "Host",
|
||||
"Hostname": "Nombre del Host",
|
||||
"ICalFeed": "iCal Feed",
|
||||
@@ -210,7 +205,7 @@
|
||||
"MinimumLimits": "Límites Mínimos",
|
||||
"Missing": "Falta",
|
||||
"Mode": "Modo",
|
||||
"Monitored": "Monitoreada",
|
||||
"Monitored": "Monitorizado",
|
||||
"MoreInfo": "Más Información",
|
||||
"MustContain": "Debe Contener",
|
||||
"MustNotContain": "No Debe Contener",
|
||||
@@ -462,7 +457,7 @@
|
||||
"Level": "Nivel",
|
||||
"ReleaseBranchCheckOfficialBranchMessage": "Las versión {0} no es una versión válida de Radarr, no recibirás actualizaciones",
|
||||
"Blocklist": "Bloqueadas",
|
||||
"BlocklistRelease": "Bloquear este Estreno",
|
||||
"BlocklistRelease": "Lista de lanzamientos bloqueados",
|
||||
"CreateEmptyAuthorFolders": "Crear carpetas de películas vacías",
|
||||
"SelectAll": "Seleccionar Todas",
|
||||
"SelectedCountBooksSelectedInterp": "{0} Película(s) Seleccionada(s)",
|
||||
@@ -599,7 +594,6 @@
|
||||
"BypassIfHighestQuality": "Pasar sí es la calidad más alta",
|
||||
"CustomFormatScore": "Puntuación de Formato personalizado",
|
||||
"MinimumCustomFormatScore": "Puntuación mínima de formato personalizado",
|
||||
"CloneCustomFormat": "Clonar Formato Personalizado",
|
||||
"Conditions": "Condiciones",
|
||||
"CopyToClipboard": "Copiar al portapapeles",
|
||||
"CustomFormat": "Formatos Personalizados",
|
||||
@@ -630,12 +624,11 @@
|
||||
"HideAdvanced": "Ocultar Avanzado",
|
||||
"ShowAdvanced": "Mostrar Avanzado",
|
||||
"ShownClickToHide": "Mostrado, clic para ocultar",
|
||||
"ColonReplacement": "Reemplazo dos puntos",
|
||||
"ReplaceWithDash": "Reemplazar con Dash",
|
||||
"ReplaceWithSpaceDash": "Reemplazar con Space Dash",
|
||||
"ReplaceWithSpaceDashSpace": "Reemplazar con Space Dash Space",
|
||||
"DeleteRemotePathMapping": "Editar Mapeo de Ruta Remota",
|
||||
"BlocklistReleases": "Bloquear este Estreno",
|
||||
"BlocklistReleases": "Lista de lanzamientos bloqueados",
|
||||
"DeleteConditionMessageText": "Seguro que quieres eliminar la etiqueta '{0}'?",
|
||||
"Negated": "Negado",
|
||||
"RemoveSelectedItem": "Eliminar el elemento seleccionado",
|
||||
@@ -649,7 +642,7 @@
|
||||
"BlocklistReleaseHelpText": "Evita que Radarr vuelva a capturar esta película automáticamente",
|
||||
"NoEventsFound": "No se encontraron eventos",
|
||||
"ApplyTagsHelpTextHowToApplyAuthors": "Cómo añadir etiquetas a las películas seleccionadas",
|
||||
"DeleteSelectedIndexersMessageText": "Seguro que quieres eliminar el indexer '{0}'?",
|
||||
"DeleteSelectedIndexersMessageText": "Seguro que quieres eliminar {count} indexer seleccionado(s)?",
|
||||
"Yes": "Sí",
|
||||
"RedownloadFailed": "La descarga ha fallado",
|
||||
"RemoveCompleted": "Eliminación completada",
|
||||
@@ -663,7 +656,7 @@
|
||||
"ApplyTagsHelpTextReplace": "Reemplazar: Reemplazar las etiquetas con las etiquetas introducidas (no introducir etiquetas para eliminar todas las etiquetas)",
|
||||
"DeleteSelectedDownloadClients": "Borrar Gestor de Descargas",
|
||||
"DeleteSelectedDownloadClientsMessageText": "¿Estas seguro que quieres eliminar {count} cliente(s) de descarga seleccionado(s)?",
|
||||
"DeleteSelectedImportListsMessageText": "Seguro que quieres eliminar el indexer '{0}'?",
|
||||
"DeleteSelectedImportListsMessageText": "Seguro que quieres eliminar {count} lista(s) de importación seleccionada(s)?",
|
||||
"DeleteSelectedIndexers": "Borrar Indexer",
|
||||
"DownloadClientTagHelpText": "Solo utilizar este indexador para películas que coincidan con al menos una etiqueta. Déjelo en blanco para utilizarlo con todas las películas.",
|
||||
"ExistingTag": "Etiqueta existente",
|
||||
@@ -723,7 +716,7 @@
|
||||
"NextExecution": "Siguiente ejecución",
|
||||
"NoResultsFound": "No se han encontrado resultados",
|
||||
"RecentChanges": "Cambios recientes",
|
||||
"WhatsNew": "¿Qué hay de nuevo?",
|
||||
"WhatsNew": "Que es lo nuevo?",
|
||||
"Loading": "Cargando",
|
||||
"Events": "Eventos",
|
||||
"Medium": "Medio",
|
||||
@@ -746,7 +739,7 @@
|
||||
"ASIN": "ASIN",
|
||||
"AnyEditionOkHelpText": "Readarr cambiará automáticamente a la edición que mejor coincida con los archivos descargados",
|
||||
"AppUpdated": "{appName} Actualizada",
|
||||
"AppUpdatedVersion": "{appName} ha sido actualizado a la versión `{version}`, para obtener los cambios más recientes, necesitaras recargar {appName}",
|
||||
"AppUpdatedVersion": "{appName} ha sido actualizado a la versión `{version}`, para obtener los cambios más recientes necesitará recargar {appName}",
|
||||
"AuthorFolderFormat": "Formato de Carpeta de Autor",
|
||||
"AuthorNameHelpText": "El nombre del autor/libro a excluir (puede ser cualquier cosa significativa)",
|
||||
"BookMonitoring": "Monitoreo de libros",
|
||||
@@ -755,5 +748,19 @@
|
||||
"Book": "Libro",
|
||||
"AutomaticallySwitchEdition": "Cambiar edición automáticamente",
|
||||
"BookNaming": "Nombrado de libros",
|
||||
"Books": "Libro"
|
||||
"Books": "Libro",
|
||||
"NoHistoryBlocklist": "Sin lista de bloqueo de historial",
|
||||
"WouldYouLikeToRestoreBackup": "Te gustaria restaurar la copia de seguridad '{name}'?",
|
||||
"IsShowingMonitoredUnmonitorSelected": "Monitorizar Seleccionados",
|
||||
"CloneCustomFormat": "Clonar formato personalizado",
|
||||
"MinimumCustomFormatScoreHelpText": "Puntuación mínima de formato personalizado necesaria para evitar el retraso del protocolo preferido",
|
||||
"BypassIfAboveCustomFormatScore": "Omitir si está por encima de la puntuación del formato personalizado",
|
||||
"BypassIfAboveCustomFormatScoreHelpText": "Habilitar ignorar cuando la versión tenga una puntuación superior a la puntuación mínima configurada para el formato personalizado",
|
||||
"IsShowingMonitoredMonitorSelected": "Monitorizar Seleccionados",
|
||||
"ClientPriority": "Prioridad del Cliente",
|
||||
"ColonReplacement": "Reemplazar dos puntos",
|
||||
"CloneProfile": "Clonar Perfil",
|
||||
"Close": "Cerrar",
|
||||
"CloneIndexer": "Clonar Indexer",
|
||||
"CompletedDownloadHandling": "Manipulación de descargas completas"
|
||||
}
|
||||
|
||||
@@ -112,7 +112,7 @@
|
||||
"DiskSpace": "Espace disque",
|
||||
"DownloadClient": "Client de téléchargement",
|
||||
"DownloadClientSettings": "Télécharger les paramètres client",
|
||||
"DownloadClients": "Clients de téléchargements",
|
||||
"DownloadClients": "Clients de téléchargement",
|
||||
"DownloadFailedCheckDownloadClientForMoreDetails": "Téléchargement échoué : voir le client de téléchargement pour plus de détails",
|
||||
"DownloadFailedInterp": "Échec du téléchargement : {0}",
|
||||
"DownloadPropersAndRepacksHelpTexts1": "S'il faut ou non mettre à niveau automatiquement vers Propres/Repacks",
|
||||
@@ -140,7 +140,7 @@
|
||||
"Filename": "Nom de fichier",
|
||||
"Files": "Fichiers",
|
||||
"FirstDayOfWeek": "Premier jour de la semaine",
|
||||
"Fixed": "Fixé",
|
||||
"Fixed": "Corrigés",
|
||||
"Folder": "Dossier",
|
||||
"Folders": "Dossiers",
|
||||
"ForMoreInformationOnTheIndividualDownloadClientsClickOnTheInfoButtons": "Pour plus d'informations sur les clients de téléchargement individuels, cliquez sur les boutons d'information.",
|
||||
@@ -158,7 +158,7 @@
|
||||
"HasPendingChangesNoChanges": "Aucune modification",
|
||||
"HasPendingChangesSaveChanges": "Sauvegarder les modifications",
|
||||
"History": "Historique",
|
||||
"Hostname": "Hostname",
|
||||
"Hostname": "Nom d'hôte",
|
||||
"ICalFeed": "Flux iCal",
|
||||
"ICalHttpUrlHelpText": "Copiez cette URL dans votre/vos client(s) ou cliquez pour abonner si votre navigateur est compatible avec webcal",
|
||||
"ICalLink": "Lien iCal",
|
||||
@@ -246,7 +246,7 @@
|
||||
"PortNumber": "Numéro de port",
|
||||
"PosterSize": "Poster taille",
|
||||
"PreviewRename": "Aperçu Renommer",
|
||||
"Profiles": "Profiles",
|
||||
"Profiles": "Profils",
|
||||
"Proper": "Approprié",
|
||||
"PropersAndRepacks": "Propres et Repacks",
|
||||
"Protocol": "Protocole",
|
||||
@@ -398,7 +398,7 @@
|
||||
"UnableToLoadDownloadClientOptions": "Impossible de charger les options du client de téléchargement",
|
||||
"UnableToLoadDownloadClients": "Impossible de charger les clients de téléchargement",
|
||||
"UnableToLoadGeneralSettings": "Impossible de charger les paramètres généraux",
|
||||
"UnableToLoadHistory": "Impossible de charger l'historique",
|
||||
"UnableToLoadHistory": "Impossible de charger l'historique.",
|
||||
"UnableToLoadImportListExclusions": "Impossible de charger les exclusions de liste",
|
||||
"UnableToLoadIndexerOptions": "Impossible de charger les options de l'indexeur",
|
||||
"UnableToLoadIndexers": "Impossible de charger les indexeurs",
|
||||
@@ -502,7 +502,7 @@
|
||||
"Save": "Sauvegarder",
|
||||
"BackupIntervalHelpText": "Intervalle entre les sauvegardes automatiques",
|
||||
"CatalogNumber": "Numéro de catalogue",
|
||||
"Metadata": "Metadonnées",
|
||||
"Metadata": "Métadonnées",
|
||||
"Disabled": "Désactivé",
|
||||
"IndexersSettingsSummary": "Indexeurs et restrictions de version",
|
||||
"OnUpgrade": "Lors de la mise à niveau",
|
||||
@@ -525,7 +525,7 @@
|
||||
"ImportListStatusCheckAllClientMessage": "Toutes les listes ne sont pas disponibles en raison d'échecs",
|
||||
"ImportMechanismHealthCheckMessage": "Activer la gestion des téléchargements terminés",
|
||||
"IndexerRssHealthCheckNoIndexers": "Aucun indexeur disponible avec la synchronisation RSS activée, Readarr ne récupérera pas automatiquement les nouvelles versions",
|
||||
"CouldntFindAnyResultsForTerm": "Pas de résultats pour '{0}'",
|
||||
"CouldntFindAnyResultsForTerm": "Aucun résultat pour de résultats pour '{0}'",
|
||||
"ReadarrSupportsAnyDownloadClient": "Readarr prend en charge de nombreux clients de téléchargement torrent et usenet.",
|
||||
"RefreshAndScan": "Actualiser et analyser",
|
||||
"RemotePathMappingCheckFileRemoved": "Le fichier {0} a été supprimé pendant le processus.",
|
||||
@@ -685,10 +685,10 @@
|
||||
"CopyToClipboard": "Copier dans le presse-papier",
|
||||
"CustomFormat": "Format personnalisé",
|
||||
"CustomFormatSettings": "Réglages Formats Personnalisés",
|
||||
"CustomFormats": "Formats perso.",
|
||||
"CustomFormats": "Formats personnalisés",
|
||||
"DeleteCustomFormat": "Supprimer le format personnalisé",
|
||||
"DeleteCustomFormatMessageText": "Voulez-vous vraiment supprimer le format personnalisé « {name} » ?",
|
||||
"DeleteFormatMessageText": "Êtes-vous sûr de vouloir supprimer le tag {0} ?",
|
||||
"DeleteFormatMessageText": "Êtes-vous sûr de vouloir supprimer le tag « {0} » ?",
|
||||
"ExportCustomFormat": "Exporter un format personnalisé",
|
||||
"Formats": "Formats",
|
||||
"IncludeCustomFormatWhenRenamingHelpText": "Inclus dans {Custom Formats} renommer le format",
|
||||
@@ -885,7 +885,7 @@
|
||||
"IndexerIdHelpText": "Spécifiez à quel indexeur le profil s'applique",
|
||||
"Monitoring": "Surveillance",
|
||||
"UnmappedFiles": "Fichiers non mappés",
|
||||
"Bookshelf": "Étagère à livres",
|
||||
"Bookshelf": "Bibliothèque",
|
||||
"ErrorLoadingContent": "Une erreur s'est produite lors du chargement de ce contenu",
|
||||
"OnReleaseImportHelpText": "Lors de l'importation de la version",
|
||||
"UnableToLoadMetadataProviderSettings": "Impossible de charger les paramètres du fournisseur de métadonnées",
|
||||
@@ -921,5 +921,9 @@
|
||||
"ReadarrSupportsMultipleListsForImportingBooksAndAuthorsIntoTheDatabase": "Lidarr prend en charge plusieurs listes pour importer des albums et des artistes dans la base de données.",
|
||||
"TotalBookCountBooksTotalBookFileCountBooksWithFilesInterp": "{0} pistes au total. {1} pistes avec fichiers.",
|
||||
"SearchForAllMissingBooks": "Rechercher tous les albums manquants",
|
||||
"ForeignIdHelpText": "L'identifiant Musicbrainz de l'artiste/album à exclure"
|
||||
"ForeignIdHelpText": "L'identifiant Musicbrainz de l'artiste/album à exclure",
|
||||
"EnableProfile": "Activer profil",
|
||||
"Development": "Développement",
|
||||
"FilesTotal": "Fichiers ({0})",
|
||||
"SearchBoxPlaceHolder": "Par ex. Guerre et Paix, goodreads:656, isbn:067003469X, asin:B00JCDK5ME"
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"Actions": "Tindakan",
|
||||
"AgeWhenGrabbed": "Usia (saat diperoleh)",
|
||||
"All": "Semua",
|
||||
"AlreadyInYourLibrary": "Sudah ada di pustaka kamu",
|
||||
"AlreadyInYourLibrary": "Sudah di pustakamu",
|
||||
"Analytics": "Analitik",
|
||||
"AnalyticsEnabledHelpText": "Kirimkan informasi penggunaan secara anonim ke server Radarr. Informasi tersebut mengandung browser kamu, halaman WebUI Radarr yang kamu gunakan, pelaporan masalah serta OS dan versi runtime. Kami akan memanfaatkan informasi ini untuk memprioritaskan fitur dan perbaikan bug.",
|
||||
"ApplicationURL": "URL Aplikasi",
|
||||
@@ -28,7 +28,7 @@
|
||||
"ClickToChangeQuality": "Klik untuk mengubah kualitas",
|
||||
"AlternateTitles": "Judul Lain",
|
||||
"AppDataDirectory": "Direktori AppData",
|
||||
"Connections": "Koleksi",
|
||||
"Connections": "Koneksi",
|
||||
"ExportCustomFormat": "Tambahkan Format Khusus",
|
||||
"AuthorClickToChangeBook": "Klik untuk mengubah film",
|
||||
"Automatic": "Otomatis",
|
||||
@@ -38,7 +38,7 @@
|
||||
"EnableRSS": "Aktifkan RSS",
|
||||
"MetadataSource": "Sumber Metadata",
|
||||
"Language": "Bahasa",
|
||||
"LogFiles": "Berkas Log",
|
||||
"LogFiles": "File Log",
|
||||
"MediaManagement": "Pengelolaan Media",
|
||||
"Metadata": "Metadata",
|
||||
"Queue": "Antrean",
|
||||
@@ -67,7 +67,23 @@
|
||||
"Activity": "Aktivitas",
|
||||
"Backup": "Cadangan",
|
||||
"ConnectionLost": "Koneksi Terputus",
|
||||
"ConnectionLostReconnect": "Radarr akan mencoba untuk menghubungi secara otomatis, atau klik muat ulang di bawah.",
|
||||
"ConnectionLostReconnect": "{appName} akan mencoba untuk menghubungkan secara otomatis, atau silakan klik muat ulang di bawah.",
|
||||
"SomeResultsAreHiddenByTheAppliedFilter": "Seluruh hasil disembunyikan karena penyaringan yang diterapkan",
|
||||
"AllResultsAreHiddenByTheAppliedFilter": "Seluruh hasil disembunyikan karena penyaringan yang diterapkan"
|
||||
"AllResultsAreHiddenByTheAppliedFilter": "Seluruh hasil disembunyikan karena penyaringan yang diterapkan",
|
||||
"Today": "Hari Ini",
|
||||
"TotalFileSize": "Jumlah Ukuran File",
|
||||
"Unmonitored": "Tidak Dimonitor",
|
||||
"ConnectSettings": "Pengaturan Koneksi",
|
||||
"Yesterday": "Kemarin",
|
||||
"ClickToChangeReleaseGroup": "Klik untuk mengubah rilis grup",
|
||||
"Connect": "Koneksi",
|
||||
"Continuing": "Berlanjut",
|
||||
"Edit": "Edit",
|
||||
"Files": "File",
|
||||
"AddNew": "Tambah",
|
||||
"Search": "Cari",
|
||||
"Refresh": "Muat Ulang",
|
||||
"ConnectionLostToBackend": "Koneksi {appName} telah terputus dari backend dan perlu dimuat ulang untuk dipulihkan.",
|
||||
"ApplyChanges": "Terapkan Perubahan",
|
||||
"History": "Riwayat"
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
"60MinutesSixty": "60 Minuten: {0}",
|
||||
"APIKey": "API-sleutel",
|
||||
"About": "Over",
|
||||
"AddListExclusion": "Toevoegen aan Uitzonderingenlijst",
|
||||
"AddListExclusion": "Lijst uitzondering toevoegen",
|
||||
"AddingTag": "Tag wordt toegevoegd",
|
||||
"AgeWhenGrabbed": "Leeftijd (op moment van ophalen)",
|
||||
"AlreadyInYourLibrary": "Reeds in uw bibliotheek",
|
||||
|
||||
@@ -245,7 +245,7 @@
|
||||
"Ended": "Terminado",
|
||||
"ErrorLoadingContents": "Erro ao carregar conteúdo",
|
||||
"ErrorLoadingPreviews": "Erro ao carregar pré-visualizações",
|
||||
"Exception": "Excepção",
|
||||
"Exception": "Exceção",
|
||||
"ExtraFileExtensionsHelpTexts1": "Lista separada por vírgulas de ficheiros adicionais a importar (.nfo será importado como .nfo-orig)",
|
||||
"ExtraFileExtensionsHelpTexts2": "Exemplos: \".sub, .nfo\" ou \"sub,nfo\"",
|
||||
"FailedDownloadHandling": "Falha no processamento de transferências",
|
||||
@@ -857,5 +857,6 @@
|
||||
"DeleteCondition": "Eliminar Condição",
|
||||
"AppUpdatedVersion": "{appName} foi atualizado para a versão `{version}`, para obter as alterações mais recentes, você precisará recarregar {appName}",
|
||||
"AutomaticUpdatesDisabledDocker": "As actualizações automáticas não são diretamente suportadas quando se utiliza o mecanismo de atualização do Docker. Terá de atualizar a imagem do contentor fora de {appName} ou utilizar um script",
|
||||
"EditSelectedDownloadClients": "Editar Clientes de Transferência Selecionados"
|
||||
"EditSelectedDownloadClients": "Editar Clientes de Transferência Selecionados",
|
||||
"ApplyChanges": "Aplicar alterações"
|
||||
}
|
||||
|
||||
@@ -964,7 +964,7 @@
|
||||
"AutoAdd": "Adicionar automaticamente",
|
||||
"AutomaticAdd": "Adição Automática",
|
||||
"ApplyChanges": "Aplicar Mudanças",
|
||||
"ApplyTagsHelpTextAdd": "Adicionar: adicione as tags à lista existente de tags",
|
||||
"ApplyTagsHelpTextAdd": "Adicionar: Adicione as tags à lista existente de tags",
|
||||
"ApplyTagsHelpTextRemove": "Remover: Remove as tags inseridas",
|
||||
"ApplyTagsHelpTextReplace": "Substituir: Substitua as tags pelas tags inseridas (não digite nenhuma tag para limpar todas as tags)",
|
||||
"ApplyTagsHelpTextHowToApplyDownloadClients": "Como aplicar tags aos clientes de download selecionados",
|
||||
@@ -981,7 +981,7 @@
|
||||
"ExistingTag": "Tag existente",
|
||||
"No": "Não",
|
||||
"RemoveCompletedDownloads": "Remover downloads concluídos",
|
||||
"RemovingTag": "Removendo tag",
|
||||
"RemovingTag": "Removendo a tag",
|
||||
"SkipRedownloadHelpText": "Impede Readarr de tentar baixar versões alternativas para os itens removidos",
|
||||
"IndexerDownloadClientHealthCheckMessage": "Indexadores com clientes de download inválidos: {0}.",
|
||||
"Activity": "Atividade",
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
"AddingTag": "添加标签",
|
||||
"AgeWhenGrabbed": "年龄(在被抓取后)",
|
||||
"AlreadyInYourLibrary": "已经在你的库中",
|
||||
"AlternateTitles": "备选标题",
|
||||
"AlternateTitles": "别名",
|
||||
"Analytics": "分析",
|
||||
"AnalyticsEnabledHelpText": "发送匿名使用和错误信息到Readarr的服务器。这包括有关浏览器的信息、您使用的Readarr web页面、错误报告以及操作系统和运行时版本。我们将使用这些信息来确定功能和bug修复的优先级。",
|
||||
"AnalyticsEnabledHelpTextWarning": "需要重启生效",
|
||||
@@ -86,8 +86,8 @@
|
||||
"DeleteSelectedBookFiles": "删除选择的电影文件",
|
||||
"DeleteSelectedBookFilesMessageText": "您确定要删除选择的电影文件吗?",
|
||||
"DeleteTagMessageText": "您确定要删除标签 '{0}' 吗?",
|
||||
"DestinationPath": "目的路径",
|
||||
"DetailedProgressBar": "详细的进度条",
|
||||
"DestinationPath": "目标路径",
|
||||
"DetailedProgressBar": "详细进度条",
|
||||
"DetailedProgressBarHelpText": "在进度条上显示文本",
|
||||
"DiskSpace": "硬盘空间",
|
||||
"Docker": "Docker",
|
||||
@@ -326,7 +326,7 @@
|
||||
"ShowRelativeDatesHelpText": "显示相对日期(今天昨天等)或绝对日期",
|
||||
"ShowSearch": "显示搜索",
|
||||
"ShowSearchActionHelpText": "在选项中显示搜索框",
|
||||
"ShowSizeOnDisk": "显示已用空间",
|
||||
"ShowSizeOnDisk": "显示占用空间",
|
||||
"ShownAboveEachColumnWhenWeekIsTheActiveView": "当使用周视图时显示上面的每一列",
|
||||
"Size": " 文件大小",
|
||||
"SkipFreeSpaceCheck": "跳过剩余空间检查",
|
||||
@@ -779,7 +779,6 @@
|
||||
"CalibreUsername": "Calibre用户名",
|
||||
"ChownGroup": "修改组权限",
|
||||
"ContinuingAllBooksDownloaded": "仍在继续(所有书籍已下载)",
|
||||
"EnableProfile": "启用配置文件",
|
||||
"IfYouDontAddAnImportListExclusionAndTheAuthorHasAMetadataProfileOtherThanNoneThenThisBookMayBeReaddedDuringTheNextAuthorRefresh": "如果您不添加导入列表排除,并且作者有除“无”之外的元数据配置文件,那么这本书可能会在下一次作者刷新期间重新添加。",
|
||||
"IndexerIdHelpTextWarning": "使用带有首字母的特定索引器可能会导致复制版本被抓取",
|
||||
"MassBookSearchWarning": "您确定要对{0}本书进行批量书籍搜索吗?",
|
||||
|
||||
@@ -174,6 +174,12 @@ namespace NzbDrone.Core.MediaFiles
|
||||
|
||||
var diff = ReadAudioTag(path).Diff(newTags);
|
||||
|
||||
if (!diff.Any())
|
||||
{
|
||||
_logger.Debug("No tags update for {0} due to no difference", trackfile);
|
||||
return;
|
||||
}
|
||||
|
||||
_rootFolderWatchingService.ReportFileSystemChangeBeginning(path);
|
||||
|
||||
if (_configService.ScrubAudioTags)
|
||||
|
||||
@@ -129,7 +129,7 @@ namespace NzbDrone.Core.MediaFiles
|
||||
{
|
||||
unwanted = combined
|
||||
.Where(x => x.DiskFile.Length == x.DbFile.Size &&
|
||||
Math.Abs((x.DiskFile.LastWriteTimeUtc - x.DbFile.Modified).TotalSeconds) <= 1)
|
||||
Math.Abs((x.DiskFile.LastWriteTimeUtc - x.DbFile.Modified.ToUniversalTime()).TotalSeconds) <= 1)
|
||||
.Select(x => x.DiskFile)
|
||||
.ToList();
|
||||
_logger.Trace($"{unwanted.Count} unchanged existing files");
|
||||
@@ -138,7 +138,7 @@ namespace NzbDrone.Core.MediaFiles
|
||||
{
|
||||
unwanted = combined
|
||||
.Where(x => x.DiskFile.Length == x.DbFile.Size &&
|
||||
Math.Abs((x.DiskFile.LastWriteTimeUtc - x.DbFile.Modified).TotalSeconds) <= 1 &&
|
||||
Math.Abs((x.DiskFile.LastWriteTimeUtc - x.DbFile.Modified.ToUniversalTime()).TotalSeconds) <= 1 &&
|
||||
(x.DbFile.Edition == null || (x.DbFile.Edition.IsLoaded && x.DbFile.Edition.Value != null)))
|
||||
.Select(x => x.DiskFile)
|
||||
.ToList();
|
||||
|
||||
@@ -183,7 +183,7 @@ namespace NzbDrone.Core.MediaFiles
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Error(ex, "Error in Directory watcher for: {0}" + dw.Path);
|
||||
_logger.Error(ex, "Error in Directory watcher for: {0}", dw.Path);
|
||||
|
||||
DisposeWatcher(dw, true);
|
||||
}
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using FluentValidation.Results;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Books;
|
||||
|
||||
namespace NzbDrone.Core.Notifications.Boxcar
|
||||
{
|
||||
public class Boxcar : NotificationBase<BoxcarSettings>
|
||||
{
|
||||
private readonly IBoxcarProxy _proxy;
|
||||
|
||||
public Boxcar(IBoxcarProxy proxy)
|
||||
{
|
||||
_proxy = proxy;
|
||||
}
|
||||
|
||||
public override string Link => "https://boxcar.io/client";
|
||||
public override string Name => "Boxcar";
|
||||
|
||||
public override void OnGrab(GrabMessage grabMessage)
|
||||
{
|
||||
_proxy.SendNotification(BOOK_GRABBED_TITLE, grabMessage.Message, Settings);
|
||||
}
|
||||
|
||||
public override void OnReleaseImport(BookDownloadMessage message)
|
||||
{
|
||||
_proxy.SendNotification(BOOK_DOWNLOADED_TITLE, message.Message, Settings);
|
||||
}
|
||||
|
||||
public override void OnAuthorAdded(Author author)
|
||||
{
|
||||
_proxy.SendNotification(AUTHOR_ADDED_TITLE, author.Name, Settings);
|
||||
}
|
||||
|
||||
public override void OnAuthorDelete(AuthorDeleteMessage deleteMessage)
|
||||
{
|
||||
_proxy.SendNotification(AUTHOR_DELETED_TITLE, deleteMessage.Message, Settings);
|
||||
}
|
||||
|
||||
public override void OnBookDelete(BookDeleteMessage deleteMessage)
|
||||
{
|
||||
_proxy.SendNotification(BOOK_DELETED_TITLE, deleteMessage.Message, Settings);
|
||||
}
|
||||
|
||||
public override void OnBookFileDelete(BookFileDeleteMessage deleteMessage)
|
||||
{
|
||||
_proxy.SendNotification(BOOK_FILE_DELETED_TITLE, deleteMessage.Message, Settings);
|
||||
}
|
||||
|
||||
public override void OnHealthIssue(HealthCheck.HealthCheck message)
|
||||
{
|
||||
_proxy.SendNotification(HEALTH_ISSUE_TITLE, message.Message, Settings);
|
||||
}
|
||||
|
||||
public override void OnDownloadFailure(DownloadFailedMessage message)
|
||||
{
|
||||
_proxy.SendNotification(DOWNLOAD_FAILURE_TITLE, message.Message, Settings);
|
||||
}
|
||||
|
||||
public override void OnImportFailure(BookDownloadMessage message)
|
||||
{
|
||||
_proxy.SendNotification(IMPORT_FAILURE_TITLE, message.Message, Settings);
|
||||
}
|
||||
|
||||
public override void OnApplicationUpdate(ApplicationUpdateMessage message)
|
||||
{
|
||||
_proxy.SendNotification(APPLICATION_UPDATE_TITLE, message.Message, Settings);
|
||||
}
|
||||
|
||||
public override ValidationResult Test()
|
||||
{
|
||||
var failures = new List<ValidationFailure>();
|
||||
|
||||
failures.AddIfNotNull(_proxy.Test(Settings));
|
||||
|
||||
return new ValidationResult(failures);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
using System;
|
||||
using NzbDrone.Common.Exceptions;
|
||||
|
||||
namespace NzbDrone.Core.Notifications.Boxcar
|
||||
{
|
||||
public class BoxcarException : NzbDroneException
|
||||
{
|
||||
public BoxcarException(string message)
|
||||
: base(message)
|
||||
{
|
||||
}
|
||||
|
||||
public BoxcarException(string message, Exception innerException, params object[] args)
|
||||
: base(message, innerException, args)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,96 +0,0 @@
|
||||
using System;
|
||||
using System.Net;
|
||||
using FluentValidation.Results;
|
||||
using NLog;
|
||||
using NzbDrone.Common.EnvironmentInfo;
|
||||
using NzbDrone.Common.Http;
|
||||
|
||||
namespace NzbDrone.Core.Notifications.Boxcar
|
||||
{
|
||||
public interface IBoxcarProxy
|
||||
{
|
||||
void SendNotification(string title, string message, BoxcarSettings settings);
|
||||
ValidationFailure Test(BoxcarSettings settings);
|
||||
}
|
||||
|
||||
public class BoxcarProxy : IBoxcarProxy
|
||||
{
|
||||
private const string URL = "https://new.boxcar.io/api/notifications";
|
||||
private readonly IHttpClient _httpClient;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public BoxcarProxy(IHttpClient httpClient, Logger logger)
|
||||
{
|
||||
_httpClient = httpClient;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public void SendNotification(string title, string message, BoxcarSettings settings)
|
||||
{
|
||||
try
|
||||
{
|
||||
ProcessNotification(title, message, settings);
|
||||
}
|
||||
catch (BoxcarException ex)
|
||||
{
|
||||
_logger.Error(ex, "Unable to send message");
|
||||
throw new BoxcarException("Unable to send Boxcar notifications");
|
||||
}
|
||||
}
|
||||
|
||||
public ValidationFailure Test(BoxcarSettings settings)
|
||||
{
|
||||
try
|
||||
{
|
||||
const string title = "Test Notification";
|
||||
const string body = "This is a test message from Readarr";
|
||||
|
||||
SendNotification(title, body, settings);
|
||||
return null;
|
||||
}
|
||||
catch (HttpException ex)
|
||||
{
|
||||
if (ex.Response.StatusCode == HttpStatusCode.Unauthorized)
|
||||
{
|
||||
_logger.Error(ex, "Access Token is invalid");
|
||||
return new ValidationFailure("Token", "Access Token is invalid");
|
||||
}
|
||||
|
||||
_logger.Error(ex, "Unable to send test message");
|
||||
return new ValidationFailure("Token", "Unable to send test message");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, "Unable to send test message");
|
||||
return new ValidationFailure("", "Unable to send test message");
|
||||
}
|
||||
}
|
||||
|
||||
private void ProcessNotification(string title, string message, BoxcarSettings settings)
|
||||
{
|
||||
try
|
||||
{
|
||||
var requestBuilder = new HttpRequestBuilder(URL).Post();
|
||||
|
||||
var request = requestBuilder.AddFormParameter("user_credentials", settings.Token)
|
||||
.AddFormParameter("notification[title]", title)
|
||||
.AddFormParameter("notification[long_message]", message)
|
||||
.AddFormParameter("notification[source_name]", BuildInfo.AppName)
|
||||
.AddFormParameter("notification[icon_url]", "https://github.com/readarr/Readarr/raw/develop/Logo/64.png")
|
||||
.Build();
|
||||
|
||||
_httpClient.Post(request);
|
||||
}
|
||||
catch (HttpException ex)
|
||||
{
|
||||
if (ex.Response.StatusCode == HttpStatusCode.Unauthorized)
|
||||
{
|
||||
_logger.Error(ex, "Access Token is invalid");
|
||||
throw;
|
||||
}
|
||||
|
||||
throw new BoxcarException("Unable to send text message: " + ex.Message, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
using FluentValidation;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
using NzbDrone.Core.Validation;
|
||||
|
||||
namespace NzbDrone.Core.Notifications.Boxcar
|
||||
{
|
||||
public class BoxcarSettingsValidator : AbstractValidator<BoxcarSettings>
|
||||
{
|
||||
public BoxcarSettingsValidator()
|
||||
{
|
||||
RuleFor(c => c.Token).NotEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
public class BoxcarSettings : IProviderConfig
|
||||
{
|
||||
private static readonly BoxcarSettingsValidator Validator = new BoxcarSettingsValidator();
|
||||
|
||||
[FieldDefinition(0, Label = "Access Token", Privacy = PrivacyLevel.ApiKey, HelpText = "Your Access Token, from your Boxcar account settings: https://new.boxcar.io/account/edit", HelpLink = "https://new.boxcar.io/account/edit")]
|
||||
public string Token { get; set; }
|
||||
|
||||
public NzbDroneValidationResult Validate()
|
||||
{
|
||||
return new NzbDroneValidationResult(Validator.Validate(this));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -252,14 +252,6 @@ namespace NzbDrone.Core.Notifications.CustomScript
|
||||
failures.Add(new NzbDroneValidationFailure("Path", "File does not exist"));
|
||||
}
|
||||
|
||||
foreach (var systemFolder in SystemFolders.GetSystemFolders())
|
||||
{
|
||||
if (systemFolder.IsParentPath(Settings.Path))
|
||||
{
|
||||
failures.Add(new NzbDroneValidationFailure("Path", $"Must not be a descendant of '{systemFolder}'"));
|
||||
}
|
||||
}
|
||||
|
||||
if (failures.Empty())
|
||||
{
|
||||
try
|
||||
|
||||
@@ -11,6 +11,7 @@ namespace NzbDrone.Core.Notifications.CustomScript
|
||||
public CustomScriptSettingsValidator()
|
||||
{
|
||||
RuleFor(c => c.Path).IsValidPath();
|
||||
RuleFor(c => c.Path).SetValidator(new SystemFolderValidator()).WithMessage("Must not be a descendant of '{systemFolder}'");
|
||||
RuleFor(c => c.Arguments).Empty().WithMessage("Arguments are no longer supported for custom scripts");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using FluentValidation.Results;
|
||||
using NLog;
|
||||
using NzbDrone.Core.Messaging.Events;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
@@ -217,5 +218,26 @@ namespace NzbDrone.Core.Notifications
|
||||
definition.SupportsOnBookRetag = provider.SupportsOnBookRetag;
|
||||
definition.SupportsOnApplicationUpdate = provider.SupportsOnApplicationUpdate;
|
||||
}
|
||||
|
||||
public override ValidationResult Test(NotificationDefinition definition)
|
||||
{
|
||||
var result = base.Test(definition);
|
||||
|
||||
if (definition.Id == 0)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
if (result == null || result.IsValid)
|
||||
{
|
||||
_notificationStatusService.RecordSuccess(definition.Id);
|
||||
}
|
||||
else
|
||||
{
|
||||
_notificationStatusService.RecordFailure(definition.Id);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,6 +59,11 @@ namespace NzbDrone.Core.ThingiProvider.Status
|
||||
|
||||
public virtual void RecordSuccess(int providerId)
|
||||
{
|
||||
if (providerId <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
lock (_syncRoot)
|
||||
{
|
||||
var status = GetProviderStatus(providerId);
|
||||
|
||||
@@ -7,6 +7,7 @@ using Readarr.Api.V1.Author;
|
||||
namespace NzbDrone.Integration.Test.ApiTests
|
||||
{
|
||||
[TestFixture]
|
||||
[Ignore("Waiting for metadata to be back again", Until = "2023-12-31 00:00:00Z")]
|
||||
public class AuthorEditorFixture : IntegrationTest
|
||||
{
|
||||
private void GivenExistingAuthor()
|
||||
|
||||
@@ -7,6 +7,7 @@ using NUnit.Framework;
|
||||
namespace NzbDrone.Integration.Test.ApiTests
|
||||
{
|
||||
[TestFixture]
|
||||
[Ignore("Waiting for metadata to be back again", Until = "2023-12-31 00:00:00Z")]
|
||||
public class AuthorFixture : IntegrationTest
|
||||
{
|
||||
[Test]
|
||||
|
||||
@@ -4,6 +4,7 @@ using NUnit.Framework;
|
||||
namespace NzbDrone.Integration.Test.ApiTests
|
||||
{
|
||||
[TestFixture]
|
||||
[Ignore("Waiting for metadata to be back again", Until = "2023-12-31 00:00:00Z")]
|
||||
public class AuthorLookupFixture : IntegrationTest
|
||||
{
|
||||
[TestCase("Robert Harris", "Robert Harris")]
|
||||
|
||||
@@ -6,6 +6,7 @@ using Readarr.Api.V1.Blocklist;
|
||||
namespace NzbDrone.Integration.Test.ApiTests
|
||||
{
|
||||
[TestFixture]
|
||||
[Ignore("Waiting for metadata to be back again", Until = "2023-12-31 00:00:00Z")]
|
||||
public class BlocklistFixture : IntegrationTest
|
||||
{
|
||||
private AuthorResource _author;
|
||||
|
||||
@@ -9,6 +9,7 @@ using Readarr.Api.V1.Books;
|
||||
namespace NzbDrone.Integration.Test.ApiTests
|
||||
{
|
||||
[TestFixture]
|
||||
[Ignore("Waiting for metadata to be back again", Until = "2023-12-31 00:00:00Z")]
|
||||
public class CalendarFixture : IntegrationTest
|
||||
{
|
||||
public ClientBase<BookResource> Calendar;
|
||||
|
||||
@@ -8,6 +8,7 @@ using Readarr.Api.V1.RootFolders;
|
||||
namespace NzbDrone.Integration.Test.ApiTests.WantedTests
|
||||
{
|
||||
[TestFixture]
|
||||
[Ignore("Waiting for metadata to be back again", Until = "2023-12-31 00:00:00Z")]
|
||||
public class CutoffUnmetFixture : IntegrationTest
|
||||
{
|
||||
[SetUp]
|
||||
|
||||
@@ -7,6 +7,7 @@ using Readarr.Api.V1.RootFolders;
|
||||
namespace NzbDrone.Integration.Test.ApiTests.WantedTests
|
||||
{
|
||||
[TestFixture]
|
||||
[Ignore("Waiting for metadata to be back again", Until = "2023-12-31 00:00:00Z")]
|
||||
public class MissingFixture : IntegrationTest
|
||||
{
|
||||
[SetUp]
|
||||
|
||||
@@ -72,7 +72,7 @@ namespace NzbDrone.Integration.Test.Client
|
||||
{
|
||||
// cache control header gets reordered on net core
|
||||
var headers = response.Headers;
|
||||
((string)headers.Single(c => c.Name == "Cache-Control").Value).Split(',').Select(x => x.Trim())
|
||||
((string)headers.SingleOrDefault(c => c.Name == "Cache-Control")?.Value ?? string.Empty).Split(',').Select(x => x.Trim())
|
||||
.Should().BeEquivalentTo("no-store, no-cache".Split(',').Select(x => x.Trim()));
|
||||
headers.Single(c => c.Name == "Pragma").Value.Should().Be("no-cache");
|
||||
headers.Single(c => c.Name == "Expires").Value.Should().Be("-1");
|
||||
|
||||
@@ -48,7 +48,7 @@ namespace NzbDrone.Integration.Test
|
||||
protected override void InitializeTestTarget()
|
||||
{
|
||||
// Make sure tasks have been initialized so the config put below doesn't cause errors
|
||||
WaitForCompletion(() => Tasks.All().SelectList(x => x.TaskName).Contains("RssSync"));
|
||||
WaitForCompletion(() => Tasks.All().SelectList(x => x.TaskName).Contains("RssSync"), 30000);
|
||||
|
||||
Indexers.Post(new Readarr.Api.V1.Indexers.IndexerResource
|
||||
{
|
||||
|
||||
@@ -74,7 +74,7 @@ namespace Readarr.Api.V1
|
||||
|
||||
if (providerDefinition.Enable)
|
||||
{
|
||||
Test(providerDefinition, false);
|
||||
Test(providerDefinition, !forceSave);
|
||||
}
|
||||
|
||||
providerDefinition = _providerFactory.Create(providerDefinition);
|
||||
@@ -92,7 +92,7 @@ namespace Readarr.Api.V1
|
||||
// Only test existing definitions if it is enabled and forceSave isn't set.
|
||||
if (providerDefinition.Enable && !forceSave)
|
||||
{
|
||||
Test(providerDefinition, false);
|
||||
Test(providerDefinition, true);
|
||||
}
|
||||
|
||||
_providerFactory.Update(providerDefinition);
|
||||
|
||||
@@ -34,6 +34,7 @@ namespace Readarr.Http.Authentication
|
||||
options.LoginPath = "/login";
|
||||
options.ExpireTimeSpan = TimeSpan.FromDays(7);
|
||||
options.SlidingExpiration = true;
|
||||
options.ReturnUrlParameter = "returnUrl";
|
||||
})
|
||||
.AddApiKey("API", options =>
|
||||
{
|
||||
|
||||
14
yarn.lock
14
yarn.lock
@@ -8,9 +8,9 @@
|
||||
integrity sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==
|
||||
|
||||
"@adobe/css-tools@^4.0.1":
|
||||
version "4.3.1"
|
||||
resolved "https://registry.yarnpkg.com/@adobe/css-tools/-/css-tools-4.3.1.tgz#abfccb8ca78075a2b6187345c26243c1a0842f28"
|
||||
integrity sha512-/62yikz7NLScCGAAST5SHdnjaDJQBDq0M2muyRTpf2VQhw6StBg2ALiu73zSJQ4fMVLA+0uBhBHAle7Wg+2kSg==
|
||||
version "4.3.2"
|
||||
resolved "https://registry.yarnpkg.com/@adobe/css-tools/-/css-tools-4.3.2.tgz#a6abc715fb6884851fca9dad37fc34739a04fd11"
|
||||
integrity sha512-DA5a1C0gD/pLOvhv33YMrbf2FK3oUzwNl9oOJqE4XVjuEtt6XIakRcsd7eLiOSPkp1kTRQGICTA8cKra/vFbjw==
|
||||
|
||||
"@ampproject/remapping@^2.2.0":
|
||||
version "2.2.1"
|
||||
@@ -1259,10 +1259,10 @@
|
||||
"@jridgewell/resolve-uri" "^3.1.0"
|
||||
"@jridgewell/sourcemap-codec" "^1.4.14"
|
||||
|
||||
"@microsoft/signalr@6.0.21":
|
||||
version "6.0.21"
|
||||
resolved "https://registry.yarnpkg.com/@microsoft/signalr/-/signalr-6.0.21.tgz#b45f335df7011abba831cb3d7974b58da7e725c7"
|
||||
integrity sha512-3MWhSUE7AxkQs3QBuJ/spJJpg1mAHo0/6yRGhs5+Hew3Z+iqYrHVfo0yTElC7W2bVA9t3fW3jliQ9rBN0OvJLA==
|
||||
"@microsoft/signalr@6.0.25":
|
||||
version "6.0.25"
|
||||
resolved "https://registry.yarnpkg.com/@microsoft/signalr/-/signalr-6.0.25.tgz#009f043066d383e2de41a483bd7e02bfd74d3cf8"
|
||||
integrity sha512-8AzrpxS+E0yn1tXSlv7+UlURLmSxTQDgbvOT0pGKXjZT7MkhnDP+/GLuk7veRtUjczou/x32d9PHhYlr2NBy6Q==
|
||||
dependencies:
|
||||
abort-controller "^3.0.0"
|
||||
eventsource "^1.0.7"
|
||||
|
||||
Reference in New Issue
Block a user