1
0
mirror of https://github.com/Radarr/Radarr.git synced 2026-03-13 15:34:56 -04:00

Compare commits

...

41 Commits

Author SHA1 Message Date
Bogdan
204a8bab79 Fixed: (Notifications) Consistency in notification titles 2023-04-23 07:36:08 -07:00
Bogdan
0158c84a98 Fixed: (FileList) Use labels for category options 2023-04-22 22:12:02 -07:00
Bogdan
ac51a943fb New: (Notifications) Add Apprise 2023-04-22 21:23:13 -07:00
Servarr
78edc9aa43 Automated API Docs update 2023-04-22 18:48:01 -07:00
Qstick
f2bf494cef New: Rescan movie if destination file already exists during import
Closes #8230

Co-Authored-By: Mark McDowall <markus101@users.noreply.github.com>
2023-04-22 20:27:26 -05:00
Qstick
5727e7c43b New: Improve accepted and rejected release logging
Closes #8236

Co-Authored-By: Mark McDowall <markus101@users.noreply.github.com>
2023-04-22 20:23:55 -05:00
Qstick
a7ba1a6454 Update SixLabors.ImageSharp, MailKit, DryIoc libraries
Closes #8282

Co-Authored-By: Stepan Goremykin <25577658+goremykin@users.noreply.github.com>
2023-04-22 20:18:22 -05:00
Qstick
cc285fab45 Use MinBy and MaxBy instead of OrderBy + First
Co-Authored-By: Stepan Goremykin <25577658+goremykin@users.noreply.github.com>
2023-04-22 20:10:04 -05:00
Bogdan
e0ad573e7f New: Add version and timestamp to backup archive
(cherry picked from commit ed3d880974ae6a1430866eebaf72533f35258f6f)
2023-04-22 20:00:45 -05:00
Qstick
9a23b7f0fc New: Improve video stream formatting
(cherry picked from commit 39350ed0de4aca769ef7661f1dce08f9f462e7c3)
2023-04-22 19:59:11 -05:00
Qstick
85aecbe67e New: Improve primary video stream selection
(cherry picked from commit b0834015e7b4bcc37a72cd7d6d47879a6ef2a494)
2023-04-22 19:59:11 -05:00
Qstick
bbb20e95af Fixed: DrunkenSlug Default URL
Fixes #8333

Co-Authored-By: bakerboy448 <55419169+bakerboy448@users.noreply.github.com>
2023-04-22 19:59:11 -05:00
Qstick
3fb337e20b Fixed: Tag filtering on iCal feed
Fixes #8359
2023-04-22 19:59:11 -05:00
Weblate
5e63da418e Translated using Weblate (Chinese (Simplified) (zh_CN)) [skip ci]
Currently translated at 100.0% (1159 of 1159 strings)

Translated using Weblate (German) [skip ci]

Currently translated at 99.9% (1158 of 1159 strings)

Translated using Weblate (German) [skip ci]

Currently translated at 100.0% (1159 of 1159 strings)

Translated using Weblate (Portuguese (Brazil)) [skip ci]

Currently translated at 100.0% (1159 of 1159 strings)

Co-authored-by: Deflector8249 <lh2jwko5@gomail.me>
Co-authored-by: Havok Dan <havokdan@yahoo.com.br>
Co-authored-by: SHUAI.W <x@ousui.org>
Co-authored-by: Sascha Brockel <gsydaydreamer@gmail.com>
Co-authored-by: Weblate <noreply@weblate.org>
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/de/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/pt_BR/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/zh_CN/
Translation: Servarr/Radarr
2023-04-22 17:39:35 -07:00
Qstick
890f9d6fe4 Fixed: Prevent error on manual import processing with multi languages
Closes #7713
2023-04-22 19:36:04 -05:00
Mark McDowall
8a496cbdae New: Don't try to analyze disk image files (iso, img, etc)
(cherry picked from commit 764c08498783865834e607bd41feaaedf69a254a)
2023-04-22 16:41:57 -07:00
Stevie Robinson
f54a5388a0 Fixed: Border hover colors in dark theme
(cherry picked from commit bead56893f080a1ac1df230908314f3ba8e0c6ce)
2023-04-22 10:18:21 -07:00
Bogdan
6961633cc9 Serve plain text files (eg. logs) as UTF-8 2023-04-22 10:03:17 -07:00
Qstick
1be450a9d0 Remove mono process detection
(cherry picked from commit 5a046026725084bc880a7b63d7105dcf4d882128)
2023-04-16 19:51:07 -05:00
Bogdan
2b4d6464e2 Rename CC to Cc 2023-04-16 19:50:55 -05:00
Lars
ee4c34bd6c New: Option to use Telegram topics for notifications
(cherry picked from commit c8933d812490ba375c6f7e07cd4355921dc513ac)
2023-04-16 17:46:45 -05:00
Qstick
07d41f7902 Bump version to 4.5.0 2023-04-15 10:29:39 -05:00
Qstick
bb573594d9 Fix Blocklist Tests 2023-04-13 22:35:22 -05:00
Qstick
12e360ab4f Fixed: Some posters not showing for new movies search results
Fixes #8175

Co-Authored-By: Mark McDowall <markus101@users.noreply.github.com>
2023-04-13 22:09:55 -05:00
Qstick
bae555f63e Fixed: Custom Format calculation error on Blocklist by Movie
Fixes #8136
2023-04-13 21:55:01 -05:00
Qstick
31abb93d8c Bump dotnet to 6.0.16 2023-04-13 19:15:09 -05:00
LarsHelo
75035035e1 Fixed: Remote path mapping UI being partially hidden on smaller screens 2023-04-13 19:08:19 -05:00
bakerboy448
c1e5990a58 Update library clean helptext 2023-04-13 19:07:39 -05:00
Weblate
4a42ebe44c Translated using Weblate (German) [skip ci]
Currently translated at 100.0% (1159 of 1159 strings)

Translated using Weblate (Czech) [skip ci]

Currently translated at 90.7% (1052 of 1159 strings)

Translated using Weblate (French) [skip ci]

Currently translated at 100.0% (1159 of 1159 strings)

Translated using Weblate (Portuguese) [skip ci]

Currently translated at 100.0% (1159 of 1159 strings)

Translated using Weblate (Hebrew) [skip ci]

Currently translated at 92.9% (1077 of 1159 strings)

Translated using Weblate (Italian) [skip ci]

Currently translated at 95.4% (1106 of 1159 strings)

Translated using Weblate (Arabic) [skip ci]

Currently translated at 90.4% (1048 of 1159 strings)

Translated using Weblate (Italian) [skip ci]

Currently translated at 94.6% (1097 of 1159 strings)

Translated using Weblate (German) [skip ci]

Currently translated at 100.0% (1159 of 1159 strings)

Translated using Weblate (German) [skip ci]

Currently translated at 100.0% (1159 of 1159 strings)

Translated using Weblate (Norwegian Bokmål) [skip ci]

Currently translated at 22.5% (261 of 1159 strings)

Translated using Weblate (Greek) [skip ci]

Currently translated at 100.0% (1159 of 1159 strings)

Translated using Weblate (Italian) [skip ci]

Currently translated at 94.3% (1094 of 1159 strings)

Translated using Weblate (French) [skip ci]

Currently translated at 100.0% (1159 of 1159 strings)

Translated using Weblate (Portuguese (Brazil)) [skip ci]

Currently translated at 100.0% (1159 of 1159 strings)

Translated using Weblate (French) [skip ci]

Currently translated at 99.5% (1154 of 1159 strings)

Translated using Weblate (Portuguese (Brazil)) [skip ci]

Currently translated at 100.0% (1159 of 1159 strings)

Translated using Weblate (Croatian) [skip ci]

Currently translated at 21.4% (249 of 1159 strings)

Co-authored-by: Bendik Remoy <Bendikremoy@hotmail.com>
Co-authored-by: Cassio Rizzi <clrizzi@gmail.com>
Co-authored-by: Deflector8249 <lh2jwko5@gomail.me>
Co-authored-by: Elias Benbourenane <eliasbenbourenane@gmail.com>
Co-authored-by: Florian <sephrat.flo@gmail.com>
Co-authored-by: Havok Dan <havokdan@yahoo.com.br>
Co-authored-by: Ivan Mazzoli <dreadtank27@gmail.com>
Co-authored-by: Lizandra Candido da Silva <lizandra.c.s@gmail.com>
Co-authored-by: Michele Caputo <michele@caputoweb.xyz>
Co-authored-by: Nir Israel Hen <nirisraelh@gmail.com>
Co-authored-by: Remy <remy@mrbk.fr>
Co-authored-by: TheHrle <Hpranjkovic@gmail.com>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: federicofortini <federico.fortini@yahoo.it>
Co-authored-by: libsu <libsu@qq.com>
Co-authored-by: reloxx <reloxx@interia.pl>
Co-authored-by: tomas15420 <tomas15420@gmail.com>
Co-authored-by: zobe123 <manuel.zobl@gmx.at>
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/ar/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/cs/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/de/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/el/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/fr/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/he/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/hr/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/it/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/nb_NO/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/pt/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/pt_BR/
Translation: Servarr/Radarr
2023-04-13 19:06:57 -05:00
Qstick
c82aa5c2c7 Fixed: Validation for CleanOriginalTitle
Fixes #8331
Closes #8332

Co-Authored-By: bakerboy448 <55419169+bakerboy448@users.noreply.github.com>
2023-04-13 19:03:13 -05:00
Qstick
d1bae32e1c Fixed: Correct TitleThe naming token parsing 2023-04-13 18:59:15 -05:00
Qstick
c514c7cac0 Fixed: Default value in new Delay Profile 2023-04-13 18:52:13 -05:00
Qstick
3d244057b5 Fixed: Don't grab propers/repacks when item in queue meets cutoff and propers/repacks are not downloaded automatically
Fixes #8134
2023-04-13 18:47:21 -05:00
Bakerboy448
323510300c Fixed: Cleanup erroneous QBittorrent Seeding calls 2023-04-13 18:14:36 -05:00
Bakerboy448
669d87b7ef Fixed: Include Digital Only Releases for Recent Movie determination
Use most recent of physical or digital release date
2023-04-13 18:14:08 -05:00
Bakerboy448
ec7f7b085a New: More information on on why hardlinks should be used over copying
Closes #8327

(cherry picked from commit 83a9d15ff8721c8effdc2c8055e37bfb757022d4)
2023-04-13 18:13:43 -05:00
Bogdan
ecc906a754 Fixed: Config file settings do not need to be case-sensitive
(cherry picked from commit 2107635b7e7e5392624f2957af7d7b88ba6be283)
2023-04-11 20:00:35 -05:00
Bogdan
d0fcac389c Fixed: Ensure default config file on starting app
(cherry picked from commit 5326a102e23eacfc1132eb544a92af737a531df5)
2023-04-11 20:00:35 -05:00
Qstick
621acbef9a Bump version to 4.4.4 2023-04-09 12:23:51 -05:00
Mark McDowall
7fb1163b23 Fixed: Number input changing while scrolling
(cherry picked from commit cc46ed56b4b70fe1f1443c0a927383f19c989c47)
2023-04-09 12:12:29 -05:00
Sergey M
b48eda95dd Fixed: Mapping by MovieTitles collection instead of PrimaryMovieTitle (#8157)
Co-authored-by: Sergey M <msergein>
2023-04-02 16:53:24 -05:00
75 changed files with 753 additions and 294 deletions

View File

@@ -9,13 +9,13 @@ variables:
testsFolder: './_tests'
yarnCacheFolder: $(Pipeline.Workspace)/.yarn
nugetCacheFolder: $(Pipeline.Workspace)/.nuget/packages
majorVersion: '4.4.3'
majorVersion: '4.5.0'
minorVersion: $[counter('minorVersion', 2000)]
radarrVersion: '$(majorVersion).$(minorVersion)'
buildName: '$(Build.SourceBranchName).$(radarrVersion)'
sentryOrg: 'servarr'
sentryUrl: 'https://sentry.servarr.com'
dotnetVersion: '6.0.400'
dotnetVersion: '6.0.408'
nodeVersion: '16.X'
innoVersion: '6.2.0'
windowsImage: 'windows-2022'

View File

@@ -113,6 +113,7 @@ class AddNewMovieSearchResult extends Component {
images={images}
size={250}
overflow={true}
lazy={false}
/>
</div>

View File

@@ -112,6 +112,12 @@ class TextInput extends Component {
this._isMouseTarget = false;
};
onWheel = () => {
if (this.props.type === 'number') {
this._input.blur();
}
};
//
// Render
@@ -161,6 +167,7 @@ class TextInput extends Component {
onKeyUp={this.onKeyUp}
onMouseDown={this.onMouseDown}
onMouseUp={this.onMouseUp}
onWheel={this.onWheel}
/>
);
}

View File

@@ -8,11 +8,15 @@
}
.host {
flex: 0 0 300px;
@add-mixin truncate;
flex: 0 1 300px;
}
.path {
flex: 0 0 400px;
@add-mixin truncate;
flex: 0 1 400px;
}
.actions {

View File

@@ -1,15 +1,20 @@
.remotePathMappingsHeader {
display: flex;
margin-bottom: 10px;
padding-right: 24px;
font-weight: bold;
}
.host {
flex: 0 0 300px;
@add-mixin truncate;
flex: 0 1 300px;
}
.path {
flex: 0 0 400px;
@add-mixin truncate;
flex: 0 1 400px;
}
.addRemotePathMapping {

View File

@@ -191,6 +191,7 @@ const delayProfileShape = {
enableTorrent: PropTypes.shape(boolSettingShape).isRequired,
usenetDelay: PropTypes.shape(numberSettingShape).isRequired,
torrentDelay: PropTypes.shape(numberSettingShape).isRequired,
bypassIfHighestQuality: PropTypes.shape(boolSettingShape).isRequired,
order: PropTypes.shape(numberSettingShape),
tags: PropTypes.shape(tagSettingShape).isRequired
};

View File

@@ -13,6 +13,7 @@ const newDelayProfile = {
preferredProtocol: 'usenet',
usenetDelay: 0,
torrentDelay: 0,
bypassIfHighestQuality: false,
tags: []
};

View File

@@ -94,27 +94,27 @@ module.exports = {
defaultBackgroundColor: '#333',
defaultBorderColor: '#eaeaea',
defaultHoverBackgroundColor: '#444',
defaultHoverBorderColor: '#d6d6d6;',
defaultHoverBorderColor: '#d6d6d6',
primaryBackgroundColor: '#5d9cec',
primaryBorderColor: '#5899eb',
primaryHoverBackgroundColor: '#4b91ea',
primaryHoverBorderColor: '#3483e7;',
primaryHoverBorderColor: '#3483e7',
successBackgroundColor: '#27c24c',
successBorderColor: '#26be4a',
successHoverBackgroundColor: '#24b145',
successHoverBorderColor: '#1f9c3d;',
successHoverBorderColor: '#1f9c3d',
warningBackgroundColor: '#ff902b',
warningBorderColor: '#ff8d26',
warningHoverBackgroundColor: '#ff8517',
warningHoverBorderColor: '#fc7800;',
warningHoverBorderColor: '#fc7800',
dangerBackgroundColor: '#f05050',
dangerBorderColor: '#f04b4b',
dangerHoverBackgroundColor: '#ee3d3d',
dangerHoverBorderColor: '#ec2626;',
dangerHoverBorderColor: '#ec2626',
iconButtonDisabledColor: '#7a7a7a',
iconButtonHoverColor: '#666',

View File

@@ -30,7 +30,7 @@
"@fortawesome/free-regular-svg-icons": "6.1.0",
"@fortawesome/free-solid-svg-icons": "6.1.0",
"@fortawesome/react-fontawesome": "0.1.18",
"@microsoft/signalr": "6.0.8",
"@microsoft/signalr": "6.0.16",
"@sentry/browser": "6.18.2",
"@sentry/integrations": "6.18.2",
"classnames": "2.3.1",

View File

@@ -92,7 +92,7 @@
<!-- Standard testing packages -->
<ItemGroup Condition="'$(TestProject)'=='true'">
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.4.1" />
<PackageReference Include="NUnit" Version="3.13.2" />
<PackageReference Include="NUnit3TestAdapter" Version="4.1.0" />
<PackageReference Include="NunitXml.TestLogger" Version="3.0.117" />

View File

@@ -483,12 +483,11 @@ namespace NzbDrone.Common.Disk
return mounts.Where(drive => drive.RootDirectory.PathEquals(path) ||
drive.RootDirectory.IsParentPath(path))
.OrderByDescending(drive => drive.RootDirectory.Length)
.FirstOrDefault();
.MaxBy(drive => drive.RootDirectory.Length);
}
catch (Exception ex)
{
Logger.Debug(ex, string.Format("Failed to get mount for path {0}", path));
Logger.Debug(ex, $"Failed to get mount for path {path}");
return null;
}
}

View File

@@ -320,7 +320,7 @@ namespace NzbDrone.Common.Processes
processInfo = new ProcessInfo();
processInfo.Id = process.Id;
processInfo.Name = process.ProcessName;
processInfo.StartPath = GetExeFileName(process);
processInfo.StartPath = process.MainModule.FileName;
if (process.Id != GetCurrentProcessId() && process.HasExited)
{
@@ -335,16 +335,6 @@ namespace NzbDrone.Common.Processes
return processInfo;
}
private static string GetExeFileName(Process process)
{
if (process.MainModule.FileName != "mono.exe")
{
return process.MainModule.FileName;
}
return process.Modules.Cast<ProcessModule>().FirstOrDefault(module => module.ModuleName.ToLower().EndsWith(".exe")).FileName;
}
private List<Process> GetProcessesByName(string name)
{
var processes = Process.GetProcessesByName(name).ToList();

View File

@@ -4,9 +4,9 @@
<DefineConstants Condition="'$(RuntimeIdentifier)' == 'linux-musl-x64' or '$(RuntimeIdentifier)' == 'linux-musl-arm64'">ISMUSL</DefineConstants>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="DryIoc.dll" Version="5.3.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="6.0.0" />
<PackageReference Include="DryIoc.dll" Version="5.3.4" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="6.0.1" />
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="6.0.1" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
<PackageReference Include="NLog" Version="5.0.1" />
<PackageReference Include="NLog.Extensions.Logging" Version="5.0.0" />
@@ -14,10 +14,10 @@
<PackageReference Include="Sentry" Version="3.23.1" />
<PackageReference Include="NLog.Targets.Syslog" Version="7.0.0" />
<PackageReference Include="SharpZipLib" Version="1.3.3" />
<PackageReference Include="System.Text.Json" Version="6.0.5" />
<PackageReference Include="System.Text.Json" Version="6.0.7" />
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
<PackageReference Include="System.Data.SQLite.Core.Servarr" Version="1.0.115.5-18" />
<PackageReference Include="System.Configuration.ConfigurationManager" Version="6.0.0" />
<PackageReference Include="System.Configuration.ConfigurationManager" Version="6.0.1" />
<PackageReference Include="System.IO.FileSystem.AccessControl" Version="5.0.0" />
<PackageReference Include="System.Runtime.Loader" Version="4.3.0" />
<PackageReference Include="System.ServiceProcess.ServiceController" Version="6.0.0" />

View File

@@ -81,8 +81,9 @@ namespace NzbDrone.Core.Test.Blocklisting
Subject.DeleteForMovies(new List<int> { _movie1.Id });
var removedMovieBlocklists = Subject.BlocklistedByMovie(_movie1.Id);
var nonRemovedMovieBlocklists = Subject.BlocklistedByMovie(_movie2.Id);
var blocklist = Subject.All();
var removedMovieBlocklists = blocklist.Where(b => b.MovieId == _movie1.Id);
var nonRemovedMovieBlocklists = blocklist.Where(b => b.MovieId == _movie2.Id);
removedMovieBlocklists.Should().HaveCount(0);
nonRemovedMovieBlocklists.Should().HaveCount(1);

View File

@@ -4,9 +4,11 @@ using FizzWare.NBuilder;
using FluentAssertions;
using Moq;
using NUnit.Framework;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.CustomFormats;
using NzbDrone.Core.DecisionEngine.Specifications;
using NzbDrone.Core.Download.TrackedDownloads;
using NzbDrone.Core.Languages;
using NzbDrone.Core.Movies;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Profiles;
@@ -204,5 +206,31 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
Subject.IsSatisfiedBy(_remoteMovie, null).Accepted.Should().BeTrue();
}
[Test]
public void should_return_false_if_same_quality_non_proper_in_queue_and_download_propers_is_do_not_upgrade()
{
_remoteMovie.ParsedMovieInfo.Quality = new QualityModel(Quality.HDTV720p, new Revision(2));
_movie.Profile.Cutoff = _remoteMovie.ParsedMovieInfo.Quality.Quality.Id;
Mocker.GetMock<IConfigService>()
.Setup(s => s.DownloadPropersAndRepacks)
.Returns(ProperDownloadTypes.DoNotUpgrade);
var remoteMovie = Builder<RemoteMovie>.CreateNew()
.With(r => r.Movie = _movie)
.With(r => r.ParsedMovieInfo = new ParsedMovieInfo
{
Quality = new QualityModel(Quality.HDTV720p),
Languages = new List<Language> { Language.English }
})
.With(r => r.Release = _releaseInfo)
.With(r => r.CustomFormats = new List<CustomFormat>())
.Build();
GivenQueue(new List<RemoteMovie> { remoteMovie });
Subject.IsSatisfiedBy(_remoteMovie, null).Accepted.Should().BeFalse();
}
}
}

View File

@@ -25,6 +25,7 @@ namespace NzbDrone.Core.Test.MediaFiles.MediaInfo.MediaInfoFormatterTests
[TestCase("msmpeg4, DIV3", "Movie the Title (1976) 360p MPEG Audio.avi", "DivX")]
[TestCase("msmpeg4v2, DIV3", "Movie the Title (1976) 360p MPEG Audio.avi", "DivX")]
[TestCase("msmpeg4v3, DIV3", "Movie the Title (1976) 360p MPEG Audio.avi", "DivX")]
[TestCase("vp6f, 4", "Movie the Title (1976) 360p MPEG Audio.flv", "VP6")]
[TestCase("vp6, 4", "Top Gear - S12E01 - Lorries - SD TV.flv", "VP6")]
[TestCase("vp7, VP70", "Movie the Title.avi", "VP7")]
[TestCase("vp8, V_VP8", "Movie the Title.mkv", "VP8")]

View File

@@ -75,7 +75,7 @@ namespace NzbDrone.Core.Test.NotificationTests.EmailTests
[TestCase("radarr.video")]
public void should_not_be_valid_if_cc_is_invalid(string email)
{
_emailSettings.CC = new string[] { email };
_emailSettings.Cc = new string[] { email };
_validator.Validate(_emailSettings).IsValid.Should().BeFalse();
}
@@ -94,7 +94,7 @@ namespace NzbDrone.Core.Test.NotificationTests.EmailTests
public void should_not_be_valid_if_to_bcc_cc_are_all_empty()
{
_emailSettings.To = Array.Empty<string>();
_emailSettings.CC = Array.Empty<string>();
_emailSettings.Cc = Array.Empty<string>();
_emailSettings.Bcc = Array.Empty<string>();
_validator.Validate(_emailSettings).IsValid.Should().BeFalse();

View File

@@ -69,7 +69,8 @@ namespace NzbDrone.Core.Backup
_diskProvider.EnsureFolder(_backupTempFolder);
_diskProvider.EnsureFolder(GetBackupFolder(backupType));
var backupFilename = string.Format("radarr_backup_v{0}_{1:yyyy.MM.dd_HH.mm.ss}.zip", BuildInfo.Version, DateTime.Now);
var dateNow = DateTime.Now;
var backupFilename = $"radarr_backup_v{BuildInfo.Version}_{dateNow:yyyy.MM.dd_HH.mm.ss}.zip";
var backupPath = Path.Combine(GetBackupFolder(backupType), backupFilename);
Cleanup();
@@ -81,7 +82,7 @@ namespace NzbDrone.Core.Backup
BackupConfigFile();
BackupDatabase();
CreateVersionInfo();
CreateVersionInfo(dateNow);
_logger.ProgressDebug("Creating backup zip");
@@ -208,11 +209,15 @@ namespace NzbDrone.Core.Backup
_diskTransferService.TransferFile(configFile, tempConfigFile, TransferMode.Copy);
}
private void CreateVersionInfo()
private void CreateVersionInfo(DateTime dateNow)
{
var builder = new StringBuilder();
var tempFile = Path.Combine(_backupTempFolder, "INFO");
builder.AppendLine(BuildInfo.Version.ToString());
var builder = new StringBuilder();
builder.AppendLine($"v{BuildInfo.Version}");
builder.AppendLine($"{dateNow:yyyy-MM-dd HH:mm:ss}");
_diskProvider.WriteAllText(tempFile, builder.ToString());
}
private void CleanupOldBackups(BackupType backupType)

View File

@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System.Linq;
using NzbDrone.Core.Datastore;
using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Movies;
@@ -32,7 +33,14 @@ namespace NzbDrone.Core.Blocklisting
public List<Blocklist> BlocklistedByMovie(int movieId)
{
return Query(x => x.MovieId == movieId);
var builder = Builder().Join<Blocklist, Movie>((h, a) => h.MovieId == a.Id)
.Where<Blocklist>(h => h.MovieId == movieId);
return _database.QueryJoined<Blocklist, Movie>(builder, (blocklist, movie) =>
{
blocklist.Movie = movie;
return blocklist;
}).OrderByDescending(h => h.Date).ToList();
}
public void DeleteForMovies(List<int> movieIds)

View File

@@ -26,6 +26,7 @@ namespace NzbDrone.Core.Configuration
XDocument LoadConfigFile();
Dictionary<string, object> GetConfigDictionary();
void SaveConfigDictionary(Dictionary<string, object> configValues);
void EnsureDefaultConfigFile();
string BindAddress { get; }
int Port { get; }
@@ -253,7 +254,7 @@ namespace NzbDrone.Core.Configuration
public T GetValueEnum<T>(string key, T defaultValue, bool persist = true)
{
return (T)Enum.Parse(typeof(T), GetValue(key, defaultValue), persist);
return (T)Enum.Parse(typeof(T), GetValue(key, defaultValue, persist), true);
}
public string GetValue(string key, object defaultValue, bool persist = true)
@@ -312,7 +313,7 @@ namespace NzbDrone.Core.Configuration
SetValue(key, value.ToString().ToLower());
}
private void EnsureDefaultConfigFile()
public void EnsureDefaultConfigFile()
{
if (!File.Exists(_configFile))
{

View File

@@ -141,11 +141,11 @@ namespace NzbDrone.Core.DecisionEngine
{
if (decision.Rejections.Any())
{
_logger.Debug("Release rejected for the following reasons: {0}", string.Join(", ", decision.Rejections));
_logger.Debug("Release '{0}' from '{1}' rejected for the following reasons: {2}", report.Title, report.Indexer, string.Join(", ", decision.Rejections));
}
else
{
_logger.Debug("Release accepted");
_logger.Debug("Release '{0}' from '{1}' accepted", report.Title, report.Indexer);
}
yield return decision;

View File

@@ -1,10 +1,12 @@
using System.Linq;
using NLog;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.CustomFormats;
using NzbDrone.Core.Download.TrackedDownloads;
using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Qualities;
using NzbDrone.Core.Queue;
namespace NzbDrone.Core.DecisionEngine.Specifications
@@ -14,16 +16,19 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
private readonly IQueueService _queueService;
private readonly UpgradableSpecification _upgradableSpecification;
private readonly ICustomFormatCalculationService _formatService;
private readonly IConfigService _configService;
private readonly Logger _logger;
public QueueSpecification(IQueueService queueService,
UpgradableSpecification upgradableSpecification,
ICustomFormatCalculationService formatService,
IConfigService configService,
Logger logger)
{
_queueService = queueService;
_upgradableSpecification = upgradableSpecification;
_formatService = formatService;
_configService = configService;
_logger = logger;
}
@@ -85,6 +90,15 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
{
return Decision.Reject("Another release is queued and the Quality profile does not allow upgrades");
}
if (_upgradableSpecification.IsRevisionUpgrade(remoteMovie.ParsedMovieInfo.Quality, subject.ParsedMovieInfo.Quality))
{
if (_configService.DownloadPropersAndRepacks == ProperDownloadTypes.DoNotUpgrade)
{
_logger.Debug("Auto downloading of propers is disabled");
return Decision.Reject("Proper downloading is disabled");
}
}
}
return Decision.Accept();

View File

@@ -36,13 +36,13 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
if (qualityCompare > 0)
{
_logger.Debug("New item has a better quality");
_logger.Debug("New item has a better quality. Existing: {0}. New: {1}", currentQuality, newQuality);
return true;
}
if (qualityCompare < 0)
{
_logger.Debug("Existing item has better quality, skipping");
_logger.Debug("Existing item has better quality, skipping. Existing: {0}. New: {1}", currentQuality, newQuality);
return false;
}
@@ -53,6 +53,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
if (downloadPropersAndRepacks != ProperDownloadTypes.DoNotPrefer &&
qualityRevisionCompare > 0)
{
_logger.Debug("New item has a better quality revision, skipping. Existing: {0}. New: {1}", currentQuality, newQuality);
return true;
}
@@ -63,19 +64,21 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
if (downloadPropersAndRepacks != ProperDownloadTypes.DoNotPrefer &&
qualityRevisionCompare < 0)
{
_logger.Debug("Existing item has a better quality revision, skipping");
_logger.Debug("Existing item has a better quality revision, skipping. Existing: {0}. New: {1}", currentQuality, newQuality);
return false;
}
if (newFormatScore <= currentFormatScore)
{
_logger.Debug("New item's custom formats [{0}] do not improve on [{1}], skipping",
_logger.Debug("New item's custom formats [{0}] ({1}) do not improve on [{2}] ({3}), skipping",
newCustomFormats.ConcatToString(),
currentCustomFormats.ConcatToString());
newFormatScore,
currentCustomFormats.ConcatToString(),
currentFormatScore);
return false;
}
_logger.Debug("New item has a custom format upgrade");
_logger.Debug("New item has a better custom format score");
return true;
}
@@ -115,7 +118,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
return true;
}
_logger.Debug("Existing item meets cut-off. skipping.");
_logger.Debug("Existing item meets cut-off. skipping. Existing: {0}", currentQuality);
return false;
}
@@ -124,9 +127,10 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
{
var compare = newQuality.Revision.CompareTo(currentQuality.Revision);
// Comparing the quality directly because we don't want to upgrade to a proper for a webrip from a webdl or vice versa
if (currentQuality.Quality == newQuality.Quality && compare > 0)
{
_logger.Debug("New quality is a better revision for existing quality");
_logger.Debug("New quality is a better revision for existing quality. Existing: {0}. New: {1}", currentQuality, newQuality);
return true;
}

View File

@@ -88,8 +88,6 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
if (!addHasSetShareLimits && setShareLimits)
{
Proxy.SetTorrentSeedingConfiguration(hash.ToLower(), remoteMovie.SeedConfiguration, Settings);
try
{
Proxy.SetTorrentSeedingConfiguration(hash.ToLower(), remoteMovie.SeedConfiguration, Settings);

View File

@@ -239,8 +239,7 @@ namespace NzbDrone.Core.Download.Pending
var movieReleases = GetPendingReleases(movieId);
return movieReleases.Select(r => r.RemoteMovie)
.OrderByDescending(p => p.Release.AgeHours)
.FirstOrDefault();
.MaxBy(p => p.Release.AgeHours);
}
private List<PendingRelease> GetPendingReleases()

View File

@@ -37,9 +37,7 @@ namespace NzbDrone.Core.History
public MovieHistory MostRecentForDownloadId(string downloadId)
{
return FindByDownloadId(downloadId)
.OrderByDescending(h => h.Date)
.FirstOrDefault();
return FindByDownloadId(downloadId).MaxBy(h => h.Date);
}
public List<MovieHistory> FindByDownloadId(string downloadId)
@@ -90,9 +88,7 @@ namespace NzbDrone.Core.History
public MovieHistory MostRecentForMovie(int movieId)
{
return Query(x => x.MovieId == movieId)
.OrderByDescending(h => h.Date)
.FirstOrDefault();
return Query(x => x.MovieId == movieId).MaxBy(h => h.Date);
}
public List<MovieHistory> Since(DateTime date, MovieHistoryEventType? eventType)

View File

@@ -71,25 +71,25 @@ namespace NzbDrone.Core.Indexers.FileList
public enum FileListCategories
{
[FieldOption]
[FieldOption("Movies SD")]
Movie_SD = 1,
[FieldOption]
[FieldOption("Movies DVD")]
Movie_DVD = 2,
[FieldOption]
[FieldOption("Movies DVD-RO")]
Movie_DVDRO = 3,
[FieldOption]
[FieldOption("Movies HD")]
Movie_HD = 4,
[FieldOption]
[FieldOption("Movies HD-RO")]
Movie_HDRO = 19,
[FieldOption]
Movie_BluRay = 20,
[FieldOption]
Movie_BluRay4K = 26,
[FieldOption]
Movie_3D = 25,
[FieldOption]
[FieldOption("Movies 4K")]
Movie_4K = 6,
[FieldOption]
[FieldOption("Movies Blu-Ray")]
Movie_BluRay = 20,
[FieldOption("Movies 4K Blu-Ray")]
Movie_BluRay4K = 26,
[FieldOption("Movies 3D")]
Movie_3D = 25,
[FieldOption("XXX")]
Xxx = 7
}
}

View File

@@ -41,7 +41,7 @@ namespace NzbDrone.Core.Indexers.Newznab
get
{
yield return GetDefinition("DOGnzb", GetSettings("https://api.dognzb.cr"));
yield return GetDefinition("DrunkenSlug", GetSettings("https://api.drunkenslug.com"));
yield return GetDefinition("DrunkenSlug", GetSettings("https://drunkenslug.com"));
yield return GetDefinition("Nzb-Tortuga", GetSettings("https://www.nzb-tortuga.com"));
yield return GetDefinition("Nzb.su", GetSettings("https://api.nzb.su"));
yield return GetDefinition("NZBCat", GetSettings("https://nzb.cat"));

View File

@@ -1064,5 +1064,6 @@
"RssSyncHelpText": "الفاصل بالدقائق. اضبط على صفر للتعطيل (سيؤدي هذا إلى إيقاف كل عمليات الاستيلاء على التحرير التلقائي)",
"AllCollectionsHiddenDueToFilter": "جميع الأفلام مخفية بسبب الفلتر المطبق.",
"Collections": "مجموعة",
"File": "الملفات"
"File": "الملفات",
"AnnouncedMsg": "تم اعلان الفيلم"
}

View File

@@ -238,7 +238,7 @@
"ImportHeader": "Chcete-li přidat filmy do Radarru, importujte existující organizovanou knihovnu",
"ImportListStatusCheckSingleClientMessage": "Seznamy nejsou k dispozici z důvodu selhání: {0}",
"ChmodFolderHelpText": "Octal, aplikováno během importu / přejmenování na mediální složky a soubory (bez provádění bitů)",
"AgeWhenGrabbed": "Věk (po uchopení)",
"AgeWhenGrabbed": "Stáří (při zachycení)",
"AreYouSureYouWantToDeleteThisImportListExclusion": "Opravdu chcete toto vyloučení importního seznamu smazat?",
"ChmodFolderHelpTextWarning": "Funguje to pouze v případě, že je uživatel souboru Radarr vlastníkem souboru. Je lepší zajistit, aby stahovací klient správně nastavil oprávnění.",
"ChmodGroup": "chmod Group",
@@ -441,7 +441,7 @@
"AnalyseVideoFiles": "Analyzujte video soubory",
"Age": "Stáří",
"Agenda": "Denní program",
"All": "Všechno",
"All": "Vše",
"Analytics": "Analytics",
"PackageVersion": "Verze balíčku",
"AddMovie": "Přidat film",

View File

@@ -59,7 +59,7 @@
"IndexerRssHealthCheckNoIndexers": "Da keine Indexer mit aktivierter RSS-Synchronisierung verfügbar sind, erfasst Radarr nicht automatisch neue Releases auf",
"IndexerSearchCheckNoAutomaticMessage": "Keine Indexer mit aktivierter automatischer Suche verfügbar. Radarr liefert keine automatischen Suchergebnisse",
"IndexerSearchCheckNoAvailableIndexersMessage": "Alle suchfähigen Indexer sind aufgrund der kürzlichen Indexerfehler vorübergehend nicht verfügbar",
"IndexerSearchCheckNoInteractiveMessage": "Keine Indexer mit aktivierter interaktiver Suche verfügbar, Radarr liefert keine interaktiven Suchergebnisse",
"IndexerSearchCheckNoInteractiveMessage": "Keine Indexer mit aktivierter interaktiver Suche verfügbar, Radarr wird keine interaktiven Suchergebnisse liefern",
"IndexerStatusCheckAllClientMessage": "Alle Indexer sind aufgrund von Fehlern nicht verfügbar",
"IndexerStatusCheckSingleClientMessage": "Indexer aufgrund von Fehlern nicht verfügbar: {0}",
"Indexers": "Indexer",
@@ -101,7 +101,7 @@
"QualityProfile": "Qualitätsprofil",
"QualityProfiles": "Qualitätsprofile",
"Queue": "Warteschlange",
"RSSSync": "RSS Sync",
"RSSSync": "RSS-Sync",
"Refresh": "Aktualisieren",
"RefreshAndScan": "Aktualisieren",
"ReleaseBranchCheckOfficialBranchMessage": "Zweig {0} ist kein gültiger Radarr-Release-Zweig. Sie erhalten keine Updates",
@@ -223,9 +223,9 @@
"RejectionCount": "Anzahl der Ablehnungen",
"Peers": "Peers",
"PageSize": "Einträge pro Seite",
"OrganizeModalSuccess": "Fertig! Keine weiteren Dateien zum umbennenen.",
"OrganizeModalSuccess": "Fertig! Keine weiteren Dateien zum Umbenennen.",
"OrganizeModalNamingPattern": "Benennungsmuster:",
"OrganizeModalDisabled": "Umbenennen ist deaktiviert, nichts zum umbennenen",
"OrganizeModalDisabled": "Umbenennen ist deaktiviert, nichts zum Umbenennen",
"OrganizeModalAllPathsRelative": "Alle Pfade sind relativ zu:",
"OrganizeAndRename": "Organisieren & Umbenennen",
"Organize": "Organisieren",
@@ -327,14 +327,14 @@
"AvailabilityDelayHelpText": "Zeit vor( - ) oder nach( + ) dem Verfügbarkeitsdatum für die Suche nach einem Film",
"BackupIntervalHelpText": "Intervall zum sichern der Datenbank und Einstellungen",
"BackupRetentionHelpText": "Automatische Backups, die älter als die Aufbewahrungsfrist sind, werden automatisch gelöscht",
"Backups": "Backups",
"Backups": "Sicherungen",
"BindAddress": "Adresse binden",
"BindAddressHelpText": "Gültige IP Adresse oder \"*\" für alle Netzwerke",
"Branch": "Git-Branch",
"BypassProxyForLocalAddresses": "Proxy für lokale Adressen umgehen",
"CertificateValidation": "Zertifikat Validierung",
"CertificateValidationHelpText": "Ändere wie streng die Validierung der HTTPS-Zertifizierung ist. Ändern Sie nicht wenn Ihnen die Risiken nicht bewusst sind.",
"CertificationCountry": "Zertifizierungs Land",
"CertificationCountry": "Zertifizierungsland",
"ChangeFileDate": "Erstelldatum der Datei anpassen",
"ChangeHasNotBeenSavedYet": "Änderung wurde noch nicht gespeichert",
"CheckForFinishedDownloadsInterval": "Intervall zum prüfen von fertigen Downloads",
@@ -415,7 +415,7 @@
"LanguageHelpText": "Sprache für Releases",
"Links": "Links",
"ListSettings": "Listen Einstellungen",
"ListSyncLevelHelpText": "Filme in deiner Mediathek werden gelöscht oder nicht weiter beobachtet wenn sie nicht in der Liste sind",
"ListSyncLevelHelpText": "Die Filme in der Bibliothek werden auf der Grundlage Ihrer Auswahl behandelt, wenn sie nicht auf Ihrer Liste auftauchen",
"ListUpdateInterval": "Aktualisierungs Intervall der Listen",
"Local": "Lokal",
"LogLevel": "Log Level",
@@ -531,7 +531,7 @@
"TestAllIndexers": "Alle testen",
"TestAllLists": "Alle testen",
"TimeFormat": "Zeitformat",
"UpdateMechanismHelpText": "Benutze Radarr's Build-In Updater oder ein Script",
"UpdateMechanismHelpText": "Benutze den in Radarr eingebauten Updater oder ein Script",
"UpdateScriptPathHelpText": "Pfad zu einem benutzerdefinierten Skript, das ein extrahiertes Update-Paket übernimmt und den Rest des Update-Prozesses abwickelt",
"UpgradeAllowedHelpText": "Wenn deaktiviert wird die Qualität nicht verbessert",
"Uptime": "Laufzeit",
@@ -587,7 +587,7 @@
"ImportExtraFilesHelpText": "Importiere zutreffende Extra Dateien (Untertitel, nfo, etc.) nach dem Importieren einer Filmdatei",
"PreferIndexerFlags": "Bevorzugte Indexer Flags",
"AreYouSureYouWantToResetYourAPIKey": "Bist du sicher, dass du den API-Schlüssel zurücksetzen willst?",
"CopyUsingHardlinksHelpText": "Hardlinks erstellen wenn Torrents die noch geseeded werden kopiert werden sollen",
"CopyUsingHardlinksHelpText": "Hardlinks erlauben es Radarr, Torrents zu importieren die derzeit geseeded werden, ohne dabei weiteren Speicherplatz zu belegen oder die Datei vollständig zu kopieren. Hardlinks funktionieren nur, wenn sich die Quelle und das Ziel auf dem selben Volume befinden",
"IncludeUnknownMovieItemsHelpText": "Einträge ohne eine Zuordnung in der Warteschlange anzeigen. Dies könnten gelöschte Filme oder alles andere mit Radarrs Downloadkategorie sein",
"PriorityHelpText": "Priorisiere mehrere Downloader. Rundlauf-Verfahren wird für Downloader mit der gleichen Priorität verwendet.",
"SearchForMovie": "Film suchen",
@@ -830,7 +830,7 @@
"ChmodFolderHelpText": "Oktal, wird beim Importieren/Umbenennen von Medienordnern und Dateien angewendet (ohne Ausführungsbits)",
"ChmodFolder": "chmod Ordner",
"FileNameTokens": "Dateinamen Teile",
"YesMoveFiles": "Ja, Dateien verchieben",
"YesMoveFiles": "Ja, Dateien verschieben",
"WouldYouLikeToRestoreBackup": "Willst du das Backup {0} wiederherstellen?",
"Wiki": "Wiki",
"WhatsNew": "Was gibt's Neues?",
@@ -904,7 +904,7 @@
"PhysicalReleaseDate": "Disc Veröffentlichungsdatum",
"OrganizeSelectedMovies": "Ausgewählte Filme organisieren",
"OrganizeConfirm": "Bist du sicher, dass du alle Datien der {0} ausgewählten Filme organisieren willst?",
"OnRename": "Bei Umbennenung",
"OnRename": "Bei Umbenennen",
"OnlyUsenet": "Nur Usenet",
"OnlyTorrent": "Nur Torrents",
"OnLatestVersion": "Die aktuellste Version ist bereits installiert",
@@ -1024,7 +1024,7 @@
"Add": "Hinzufügen",
"RequiredRestrictionHelpText": "Das Release mus mindesten eines der Begriffe beinhalten ( Groß-/Kleinschreibung wird nicht beachtet )",
"MoveFolders2": "Bist du sicher, dass du die Filmdateien von '{0}' nach '{1}' verschieben willst ?",
"ImportLibrary": "Mediathek Import",
"ImportLibrary": "Importieren",
"ImportNotForDownloads": "Benutze dies NICHT um abgeschlossene Downloads deines Download Clients hinzuzufügen. Dies ist NUR für vorhandene organisierte Mediatheken und nicht für unsortierte Dateien.",
"SqliteVersionCheckUpgradeRequiredMessage": "Die derzeit installierte SQLite-Version {0} wird nicht mehr unterstützt. Bitte aktualisieren Sie SQLite auf mindestens Version {1}.",
"ShowCinemaRelease": "Erscheinungsdatum des Kinos anzeigen",
@@ -1156,5 +1156,6 @@
"SettingsTheme": "Design",
"RSSHelpText": "Wird benutzt, wenn Radarr mittels RSS-Sync regelmäßig nach Releases schaut",
"DownloadClientSortingCheckMessage": "Downloader {0} hat die {1} Sortierung für Radarrs Kategorie aktiviert. Dies sollte deaktiviert werden, um Import-Probleme zu vermeiden.",
"File": "Datei"
"File": "Datei",
"UMask": "UMask"
}

View File

@@ -1156,5 +1156,6 @@
"Waiting": "Αναμονή",
"UpdateAvailable": "Νέα ενημέρωση είναι διαθέσιμη",
"SizeLimit": "Όριο μεγέθους",
"File": "Αρχεία"
"File": "Αρχεία",
"UMask": "UMask"
}

View File

@@ -163,7 +163,7 @@
"ConnectSettingsSummary": "Notifications, connections to media servers/players, and custom scripts",
"ConsideredAvailable": "Considered Available",
"CopyToClipboard": "Copy to Clipboard",
"CopyUsingHardlinksHelpText": "Use Hardlinks when trying to copy files from torrents that are still being seeded",
"CopyUsingHardlinksHelpText": "Hardlinks allow Radarr to import seeding torrents to the movie folder without taking extra disk space or copying the entire contents of the file. Hardlinks will only work if the source and destination are on the same volume",
"CopyUsingHardlinksHelpTextWarning": "Occasionally, file locks may prevent renaming files that are being seeded. You may temporarily disable seeding and use Radarr's rename function as a work around.",
"CouldNotConnectSignalR": "Could not connect to SignalR, UI won't update",
"CouldNotFindResults": "Couldn't find any results for '{0}'",
@@ -483,7 +483,7 @@
"Lists": "Lists",
"ListSettings": "List Settings",
"ListsSettingsSummary": "Import Lists, list exclusions",
"ListSyncLevelHelpText": "Movies in library will be removed or unmonitored if not in your list",
"ListSyncLevelHelpText": "Movies in library will handled based on your selection if they fall off or do not appear on your list(s)",
"ListSyncLevelHelpTextWarning": "Movie files will be permanently deleted, this can result in wiping your library if your lists are empty",
"ListTagsHelpText": "Tags list items will be added with",
"ListUpdateInterval": "List Update Interval",

View File

@@ -144,7 +144,7 @@
"ListsSettingsSummary": "Importer listes, listes d'exclusions",
"ListExclusions": "Liste des exclusions",
"IndexersSettingsSummary": "Indexeurs et restrictions de version",
"Grabbed": "Attrapé",
"Grabbed": "Récupéré",
"Genres": "Genres",
"Forecast": "Prévision",
"DownloadClientsSettingsSummary": "Clients de Téléchargement, la gestion des téléchargements et les mappages de chemins d'accès à distance",
@@ -582,7 +582,7 @@
"UsenetDelayHelpText": "Délai en minutes avant de récupérer une version Usenet",
"Uptime": "Durée de fonctionnent",
"UpgradeUntilThisQualityIsMetOrExceeded": "Mettre à niveau jusqu'à ce que cette qualité soit atteinte ou dépassée",
"UpgradeAllowedHelpText": "Ne sera pas mis à jour si la qualité est désactivée",
"UpgradeAllowedHelpText": "Si désactivé, la qualité ne sera pas améliorée",
"UpdateScriptPathHelpText": "Chemin vers un script personnalisé qui prend un package de mise à jour extraite et gère le reste du processus de mise à jour",
"UpdateMechanismHelpText": "Utiliser le programme de mise à jour intégré de Radarr ou un script",
"UpdateAutomaticallyHelpText": "Télécharger et installer automatiquement les mises à jour. Vous pourrez toujours installer à partir de System : Updates",
@@ -671,7 +671,7 @@
"ShowCutoffUnmetIconHelpText": "Afficher l'icône des fichiers lorsque la limite n'a pas été atteinte",
"ShowCertification": "Afficher la certification",
"ShowAsAllDayEvents": "Afficher comme événements d'une journée entière",
"ShouldMonitorHelpText": "Les films ou les collections ajoutés par cette liste doivent-ils être ajoutés en tant que surveillés",
"ShouldMonitorHelpText": "Les films ou les collections ajoutés par cette liste devraient-ils être ajoutés en tant que surveillés",
"SettingsRuntimeFormat": "Format de durée",
"SetPermissionsLinuxHelpTextWarning": "Si vous ne savez pas ce que font ces paramètres, ne les modifiez pas.",
"SetPermissionsLinuxHelpText": "Chmod doit-il être exécuté lorsque les fichiers sont importés/renommés ?",
@@ -1117,7 +1117,7 @@
"Collections": "Collections",
"MonitorMovies": "Surveiller les films",
"NoCollections": "Aucune collection n'a été trouvée. Pour commencer, vous devez ajouter un nouveau film ou importer des films existants",
"RssSyncHelpText": "Intervalle en minutes. Mettez la valeur zéro pour désactiver (cela arrêtera tous les téléchargements automatiques de version)",
"RssSyncHelpText": "Intervalle en minutes. Régler à zéro pour désactiver (cela arrêtera tous les déclenchements automatiques).",
"CollectionsSelectedInterp": "{0} Collections(s) Sélectionnée(s)",
"ChooseImportMode": "Mode d'importation",
"CollectionOptions": "Options de collection",
@@ -1156,5 +1156,6 @@
"ResetTitlesHelpText": "Réinitialiser les titres des définitions ainsi que les valeurs",
"SettingsThemeHelpText": "Changez le thème de l'interface de l'application. Le thème \"Auto\" utilisera celui de votre système d'exploitation pour définir le mode clair ou foncé. Inspiré par Theme.Park",
"ShowPosters": "Montre les affiches",
"File": "Fichier"
"File": "Fichier",
"UMask": "UMask"
}

View File

@@ -146,7 +146,7 @@
"BackupIntervalHelpText": "מרווח בין גיבויים אוטומטיים",
"BackupRetentionHelpText": "גיבויים אוטומטיים ישנים יותר מתקופת השמירה ינוקו אוטומטית",
"BindAddress": "כתובת איגוד",
"BindAddressHelpText": "כתובת IP4 תקפה או '*' לכל הממשקים",
"BindAddressHelpText": "יש להזין localhost, כתובת IP או '*' כדי לאפשר הכל",
"Branch": "ענף",
"BuiltIn": "נִבנָה בְּ",
"CalendarOptions": "אפשרויות לוח שנה",
@@ -530,7 +530,7 @@
"DestinationRelativePath": "מסלול יחסי יעד",
"DetailedProgressBar": "סרגל התקדמות מפורט",
"Details": "פרטים",
"Discord": "מַחֲלוֹקֶת",
"Discord": "דיסקורד",
"Discover": "לְגַלוֹת",
"DiskSpace": "שטח דיסק",
"Docker": "דוקר",

View File

@@ -227,5 +227,26 @@
"ChmodGroup": "chmod Grupa",
"ChmodGroupHelpText": "Naziv grupe ili gid. Koristite gid za udaljene sustave datoteka.",
"ChooseAnotherFolder": "Odaberite Drugu Mapu",
"ChooseImportMode": "Odaberite Način Uvoza"
"ChooseImportMode": "Odaberite Način Uvoza",
"AppDataLocationHealthCheckMessage": "Ažuriranje ne može spriječiti brisanje AppData pri ažuriranju",
"CleanLibraryLevel": "Očisti Razinu Biblioteke",
"ClickToChangeLanguage": "Klikni za promjenu jezika",
"ClickToChangeMovie": "Klikni za promjenu filma",
"ClickToChangeQuality": "Klikni za promjenu kvalitete",
"ClickToChangeReleaseGroup": "Klikni za promjenu grupe verzije",
"ClientPriority": "Prioritet Klijenata",
"CloneCustomFormat": "Kloniraj Prilagođeni Format",
"CloneFormatTag": "Kloniraj Oznaku Formata",
"CloneIndexer": "Kloniraj Indekser",
"CloneProfile": "Kloniraj Profil",
"Close": "Zatvori",
"CloseCurrentModal": "Zatvori Trenutni Modal",
"CollectionOptions": "Opcije Kolekcije",
"CollectionShowDetailsHelpText": "Prikaži status i svojstva kolekcije",
"CollectionShowOverviewsHelpText": "Prikaži pregled kolekcije",
"CollectionShowPostersHelpText": "Prikaži Kolekciju postera",
"CollectionsSelectedInterp": "{0} Kolekcija odabrano",
"ColonReplacement": "Zamjena Zareza",
"ColonReplacementFormatHelpText": "izmijeni kako Radar upravlja zamjenama zareza",
"Columns": "Stupci"
}

View File

@@ -225,7 +225,7 @@
"Cancel": "Annulla",
"BypassProxyForLocalAddresses": "Evita il Proxy per gli Indirizzi Locali",
"Branch": "Ramo",
"BindAddressHelpText": "Indirizzo IPV4 valido o '*' per tutte le interfacce di rete",
"BindAddressHelpText": "Indirizzo IP valido, localhost o '*' per tutte le interfacce di rete",
"BindAddress": "Indirizzo di Bind",
"Backups": "I Backup",
"BackupRetentionHelpText": "I backup automatici più vecchi del periodo di conservazione verranno eliminati automaticamente",
@@ -845,7 +845,7 @@
"AddDownloadClient": "Aggiungi Downloader",
"AddCustomFormat": "Aggiungi Formato Personalizzato",
"Add": "Aggiungi",
"ImportLibrary": "Importazione della libreria",
"ImportLibrary": "Importazione libreria",
"CustomFormatHelpText": "Radarr valuta ogni release usando la somma dei punteggi dei corrispondenti formati personalizzati. Se una nuova versione migliorasse il punteggio, con una qualità uguale o migliore, Radarr lo prenderà.",
"DefaultDelayProfile": "Questo è il profilo predefinito. Si applica a tutti i film che non hanno un profilo esplicito.",
"EditCustomFormat": "Modifica Formato Personalizzato",
@@ -948,9 +948,9 @@
"LookingForReleaseProfiles1": "Cerchi profili di rilascio? Prova",
"LookingForReleaseProfiles2": "piuttosto.",
"LowerCase": "Minuscolo",
"ManualImportSelectLanguage": "Importazione manuale: seleziona Lingua",
"ManualImportSelectLanguage": "Importazione Manuale: Seleziona Lingua",
"ManualImportSelectMovie": "Importazione manuale: seleziona Film",
"ManualImportSelectQuality": " Importazione manuale: seleziona Qualità",
"ManualImportSelectQuality": " Importazione Manuale: Seleziona Qualità",
"MegabytesPerMinute": "Megabyte al minuto",
"Min": "Min",
"MinimumCustomFormatScore": "Punteggio formato personalizzato minimo",
@@ -1108,5 +1108,13 @@
"EditCollection": "Modifica Connessione",
"SettingsThemeHelpText": "Cambia il Tema dell'interfaccia dellapplicazione, il Tema 'Auto' userà il suo Tema di Sistema per impostare la modalità Chiara o Scura. Ispirato da {0}",
"PreferredProtocol": "Protocollo Preferito",
"File": "File"
"File": "File",
"SettingsTheme": "Tema",
"ShowCollectionDetails": "Mostra stato collezione",
"Waiting": "In attesa",
"CollectionsSelectedInterp": "{0} Collezione(i) Selezionate",
"CollectionShowOverviewsHelpText": "Mostra panoramica della collezione",
"ImdbVotes": "Voti IMDb",
"ImdbRating": "Valutazione IMDb",
"DownloadClientSortingCheckMessage": "Il client di download {0} ha l'ordinamento {1} abilitato per la categoria di Radarr. Dovresti disabilitare l'ordinamento nel tuo client di download per evitare problemi di importazione."
}

View File

@@ -108,7 +108,7 @@
"AreYouSureYouWantToDeleteThisRemotePathMapping": "Er du sikker på at du vil slette denne eksterne banetilordningen?",
"AutoRedownloadFailedHelpText": "Søk etter eller prøv å laste ned en annen versjon automatisk",
"BackupFolderHelpText": "Relative stier vil være under Radarr's AppData -katalog",
"BindAddressHelpText": "Gyldig IPv4 -adresse eller \"*\" for alle grensesnitt",
"BindAddressHelpText": "Gyldig IPv4 -adresse, localhost eller \"*\" for alle grensesnitt",
"BypassDelayIfHighestQuality": "Omgå hvis høyeste kvalitet",
"BypassDelayIfHighestQualityHelpText": "Omgåelsesforsinkelse når utgivelsen har den høyeste aktiverte kvaliteten i kvalitetsprofilen med den foretrukne protokollen",
"ChangeHasNotBeenSavedYet": "Endringen er ikke lagret ennå",
@@ -256,5 +256,9 @@
"New": "Ny",
"RemotePathMappings": "Ekstern portmapping",
"Languages": "språk",
"File": "Fil"
"File": "Fil",
"ApplicationURL": "Applikasjon URL",
"ApplicationUrlHelpText": "Denne applikasjonens eksterne URL inkludert http(s)://, port og URL base",
"CollectionOptions": "Innstillinger for Samling",
"AreYouSureYouWantToResetQualityDefinitions": "Er du sikker på at du vil nullstille kvalitetsdefinisjonene?"
}

View File

@@ -194,7 +194,7 @@
"IndexerStatusCheckSingleClientMessage": "Indexadores indisponíveis devido a falhas: {0}",
"IndexerStatusCheckAllClientMessage": "Todos os indexadores estão indisponíveis devido a falhas",
"IndexersSettingsSummary": "Restrições de versões e de indexadores",
"IndexerSearchCheckNoInteractiveMessage": "Nenhum indexador disponível com a Pesquisa Interativa ativada, o Radarr não fornecerá nenhum resultado nas Pesquisas Interativas",
"IndexerSearchCheckNoInteractiveMessage": "Nenhum indexador disponível com a Pesquisa Interativa ativada. O Radarr não fornecerá nenhum resultado nas Pesquisas Interativas",
"IndexerSearchCheckNoAutomaticMessage": "Não há indexadores disponíveis com Pesquisa automática ativada, o Radarr não fornecerá nenhum resultado de pesquisa automática",
"IndexerSearchCheckNoAvailableIndexersMessage": "Todos os indexadores com funcionalidade de pesquisa estão indisponíveis devido a erros recentes do indexador",
"Indexers": "Indexadores",
@@ -486,7 +486,7 @@
"CertificateValidation": "Validação de certificado",
"BypassProxyForLocalAddresses": "Ignorar proxy para endereços locais",
"Branch": "Ramificação",
"BindAddressHelpText": "Endereço IPv4 válido ou \"*\" para todas as interfaces",
"BindAddressHelpText": "Endereço de IP válido, localhost ou \"*\" para todas as interfaces",
"BindAddress": "Endereço de vínculo",
"Backups": "Cópias de segurança",
"BackupFolderHelpText": "Caminhos relativos estarão na pasta AppData do Radarr",
@@ -635,7 +635,7 @@
"Disabled": "Desativado",
"DeleteTagMessageText": "Tem a certeza que quer eliminar a etiqueta \"{0}\"?",
"DeleteSelectedMovieFilesMessage": "Tem a certeza que quer eliminar os ficheiros do filme selecionado?",
"DeleteRestrictionHelpText": "Tem a certeza que quer eliminar esta restrição?",
"DeleteRestrictionHelpText": "Tem certeza de que quer eliminar esta restrição?",
"DeleteNotificationMessageText": "Tem a certeza que quer eliminar a notificação \"{0}\"?",
"DeleteListMessageText": "Tem a certeza que quer eliminar a lista \"{0}\"?",
"DeleteDownloadClientMessageText": "Tem a certeza que quer eliminar o cliente de transferências \"{0}\"?",
@@ -897,7 +897,7 @@
"OnRename": "Ao renomear",
"PreferTorrent": "Preferir torrent",
"PreferUsenet": "Preferir Usenet",
"QualitiesHelpText": "Qualidades mais acima na lista têm maior prioridade, as que estão no mesmo grupo têm prioridade igual. Apenas qualidades verificadas são desejadas",
"QualitiesHelpText": "Qualidades mais acima na lista têm maior prioridade, mesmo que não sejam verificadas. As que estão no mesmo grupo têm prioridade igual. Apenas qualidades verificadas são desejadas",
"QualityProfileInUse": "Não é possível eliminar um perfil de qualidade quando associado a um filme, lista ou coleção",
"QueueIsEmpty": "A fila está vazia",
"RadarrCalendarFeed": "Feed de calendário do Radarr",
@@ -1146,5 +1146,16 @@
"MovieCollectionMultipleMissingRoots": "Faltam várias pastas base para as coleções de filmes: {0}",
"MovieOnly": "Apenas filme",
"ShowCollectionDetails": "Mostrar estado da coleção",
"File": "Ficheiro"
"File": "Ficheiro",
"ResetDefinitions": "Redefinir Definições",
"ResetQualityDefinitions": "Redefinir Qualidade de Definições",
"ResetTitles": "Redefinir Títulos",
"ResetTitlesHelpText": "Redefinir títulos de definição, bem como valores",
"SettingsThemeHelpText": "Alterar o tema da interface do usuário. O tema 'Auto' usará o tema do sistema operacional para definir o modo Claro ou Escuro. Inspirado por Theme.Park",
"UMask": "UMask",
"RSSHelpText": "Será usado quando o Radarr procurar periodicamente releases via RSS Sync",
"SettingsTheme": "Tema",
"AreYouSureYouWantToResetQualityDefinitions": "Tem certeza de que deseja redefinir as definições de qualidade?",
"DownloadClientSortingCheckMessage": "O cliente de download {0} tem {1} classificação habilitada para a categoria do Radarr. Você deve desativar a classificação em seu cliente de download para evitar problemas de importação.",
"PreferredProtocol": "Protocolo Preferido"
}

View File

@@ -19,7 +19,7 @@
"IndexerStatusCheckAllClientMessage": "Todos os indexadores estão indisponíveis devido a falhas",
"IndexersSettingsSummary": "Indexadores e restrições de lançamento",
"IndexerSettings": "Configurações do indexador",
"IndexerSearchCheckNoInteractiveMessage": "Nenhum indexador disponível com a Pesquisa Interativa habilitada, o Radarr não fornecerá nenhum resultado para a pesquisa interativa",
"IndexerSearchCheckNoInteractiveMessage": "Nenhum indexador disponível com a Pesquisa interativa habilitada, o Radarr não fornecerá nenhum resultado de pesquisa interativa",
"IndexerSearchCheckNoAvailableIndexersMessage": "Todos os indexadores com capacidade de pesquisa estão temporariamente indisponíveis devido a erros recentes do indexador",
"IndexerSearchCheckNoAutomaticMessage": "Nenhum indexador disponível com a Pesquisa automática habilitada, o Radarr não fornecerá nenhum resultado de pesquisa automática",
"Indexers": "Indexadores",
@@ -84,7 +84,7 @@
"HealthNoIssues": "Nenhum problema com sua configuração",
"Health": "Integridade",
"HaveNotAddedMovies": "Você ainda não adicionou nenhum filme, deseja importar alguns ou todos os seus filmes primeiro?",
"HardlinkCopyFiles": "Hardlink/Copiar arquivos",
"HardlinkCopyFiles": "Vínculo real/Copiar arquivos",
"Group": "Grupo",
"GrabSelected": "Obter selecionado",
"GrabReleaseMessageText": "O Radarr não conseguiu determinar a qual filme este lançamento está relacionado. O Radarr pode não conseguir importar automaticamente este lançamento. Quer obter \"{0}\"?",
@@ -282,7 +282,7 @@
"CouldNotFindResults": "Não foi possível encontrar resultados para \"{0}\"",
"CouldNotConnectSignalR": "Não é possível conectar ao SignalR, a interface não atualizará",
"CopyUsingHardlinksHelpTextWarning": "Ocasionalmente, os bloqueios de arquivo podem impedir a renomeação de arquivos que estão sendo semeados. Você pode desabilitar temporariamente a semeadura e usar a função de renomeação do Radarr como uma solução alternativa.",
"CopyUsingHardlinksHelpText": "Usar vínculos reais ao tentar copiar arquivos de torrents que ainda estão sendo semeados",
"CopyUsingHardlinksHelpText": "Os hardlinks permitem que o Radarr importe torrents de propagação para a pasta do filme sem ocupar espaço extra em disco ou copiar todo o conteúdo do arquivo. Hardlinks só funcionarão se a origem e o destino estiverem no mesmo volume",
"CopyToClipboard": "Copiar para área de transferência",
"ConsideredAvailable": "Considerado disponível",
"ConnectSettingsSummary": "Notificações, conexões com servidores/reprodutores de mídia, e scripts personalizados",
@@ -449,7 +449,7 @@
"ListUpdateInterval": "Intervalo de atualização da lista",
"ListTagsHelpText": "Os itens na lista de tags serão adicionados com",
"ListSyncLevelHelpTextWarning": "Os arquivos de filme serão excluídos permanentemente, o que pode resultar na limpeza de sua biblioteca se suas listas estiverem vazias",
"ListSyncLevelHelpText": "Os filmes na biblioteca serão removidos ou deixarão de ser monitorados se não estiverem na sua lista",
"ListSyncLevelHelpText": "Os filmes na biblioteca serão tratados com base na sua seleção se eles caírem ou não aparecerem na(s) sua(s) lista(s)",
"ListsSettingsSummary": "Listas de importação, exclusões de lista",
"ListSettings": "Configurações de listas",
"Lists": "Listas",
@@ -693,7 +693,7 @@
"ShowDateAdded": "Mostrar data de adição",
"ShowCutoffUnmetIconHelpText": "Mostrar ícone para arquivos quando o limite não foi atingindo",
"ShowCertification": "Mostrar certificação",
"ShowAdvanced": "Mostrar avançado",
"ShowAdvanced": "Mostrar opções avançadas",
"ShouldMonitorHelpText": "Os filmes ou coleções adicionados por esta lista devem ser adicionados como monitorados",
"SettingsWeekColumnHeader": "Cabeçalho da coluna da semana",
"SettingsTimeFormat": "Formato de hora",
@@ -1083,8 +1083,8 @@
"RemoveFailed": "Falha na Remoção",
"RemoveCompleted": "Remover Completos",
"RemoveDownloadsAlert": "As configurações de remoção foram movidas para configurações individuais do cliente na tabela acima.",
"OnApplicationUpdate": "Na Atualização do Aplicativo",
"OnApplicationUpdateHelpText": "Na Atualização do Aplicativo",
"OnApplicationUpdate": "Ao atualizar o aplicativo",
"OnApplicationUpdateHelpText": "Ao atualizar o aplicativo",
"DiscordUrlInSlackNotification": "Você tem uma notificação do Discord configurado como uma notificação do Slack. Definir isso como uma notificação do Discord para melhor funcionalidade. Com efeito, notificações são: {0}",
"AnnouncedMsg": "Filme foi anunciado",
"IndexerDownloadClientHelpText": "Especificar qual cliente de download é utilizado para baixar a partir deste indexador",
@@ -1096,7 +1096,7 @@
"ClickToChangeReleaseGroup": "Clique para alterar o grupo do lançamento",
"Filters": "Filtros",
"RemotePath": "Caminho Remoto",
"SizeLimit": "Tamanho Limite",
"SizeLimit": "Tamanho limite",
"ImdbRating": "Avaliação no IMDb",
"TmdbRating": "Avaliação no TMDb",
"TmdbVotes": "Votos no TMDb",
@@ -1115,7 +1115,7 @@
"RefreshMonitoredIntervalHelpText": "Com que frequência atualizar downloads monitorados de clientes de download, no mínimo 1 minuto",
"RssSyncHelpText": "Intervalo em minutos. Defina como zero para desabilitar (isso interromperá todas as capturas de liberação automática)",
"InstanceName": "Nome da instância",
"InstanceNameHelpText": "Nome da instância na guia e para o nome do aplicativo Syslog",
"InstanceNameHelpText": "Nome da instância na guia e para o nome do aplicativo do Syslog",
"AllCollectionsHiddenDueToFilter": "Todos os filmes estão ocultos devido ao filtro aplicado.",
"Collections": "Coleções",
"MonitorMovies": "Monitorar Filmes",

View File

@@ -420,7 +420,7 @@
"EnableInteractiveSearchHelpText": "当手动搜索启用时使用",
"EnableInteractiveSearch": "启用手动搜索",
"EnabledHelpText": "在 Radarr 中启用该列表",
"EnableCompletedDownloadHandlingHelpText": "自动从下载客户端导入已下载的歌曲",
"EnableCompletedDownloadHandlingHelpText": "自动从下载客户端导入已完成的下载内容",
"Enabled": "已启用",
"EnableColorImpairedMode": "启用色障模式",
"EnableAutomaticSearchHelpTextWarning": "当手动搜索启用时使用",
@@ -452,7 +452,7 @@
"CreateGroup": "创建组",
"CreateEmptyMovieFolders": "为影片创建空文件夹",
"CouldNotConnectSignalR": "无法连接至SignalR不会升级UI",
"CopyUsingHardlinksHelpText": "拷贝文件时torrents文件还在做种中则使用硬链接",
"CopyUsingHardlinksHelpText": "硬链接 (Hardlinks) 允许 Radarr 将还在做种中的文件导入到影片文件夹中而不占用额外的存储空间或者复制文件的全部内容。硬链接 (Hardlinks) 仅能在源文件和目标文件在同一磁盘卷中使用",
"ConnectSettingsSummary": "通知、与媒体服务器/播放器的链接、自定义脚本",
"DownloadClientSettings": "下载客户端设置",
"DownloadClients": "下载客户端",
@@ -569,7 +569,7 @@
"AddingTag": "添加标签",
"AddImportExclusionHelpText": "防止列表中的电影被添加到 Radarr 中",
"AddExclusion": "添加例外",
"AddedToDownloadQueue": "已添加到下载队列",
"AddedToDownloadQueue": "已添加到下载队列",
"Added": "已添加",
"Actions": "操作",
"ImportListSyncIntervalHelpText": "多久Radarr同步一次您的影片列表最小值为6小时",
@@ -628,7 +628,7 @@
"LoadingMovieExtraFilesFailed": "读取影片附加文件失败",
"LoadingMovieCreditsFailed": "读取影片评分失败",
"ListSyncLevelHelpTextWarning": "影片文件会被永久删除,如果你的列表是空的,这可能会导致您的媒体库被清除",
"ListSyncLevelHelpText": "媒体库中的影片如果不在您的列表中则会被移除或者不再监控",
"ListSyncLevelHelpText": "媒体库中的影片如果没有出现或者不在您的列表中,则将会按照您的选择进行处理",
"LastWriteTime": "最后写入时间",
"LastDuration": "上一次用时",
"InteractiveImportErrMovie": "必须为每个已选择文件选择影片",
@@ -636,7 +636,7 @@
"InstallLatest": "安装最新版",
"IndexerStatusCheckSingleClientMessage": "搜刮器因错误不可用:{0}",
"IndexerStatusCheckAllClientMessage": "所有搜刮器都因错误不可用",
"IndexerSearchCheckNoInteractiveMessage": "没有任何索引器开启了手动搜索,因此 Radarr不会提供任何手动搜索的结果",
"IndexerSearchCheckNoInteractiveMessage": "没有可用的交互式搜索的索引器,因此 Radarr 不会提供任何交互式搜索的结果",
"IndexerRssHealthCheckNoIndexers": "没有任何索引器开启了RSS同步Radarr不会自动抓取新发布的影片",
"IndexerLongTermStatusCheckSingleClientMessage": "由于故障6小时下列索引器都已不可用{0}",
"IndexerLongTermStatusCheckAllClientMessage": "由于故障超过6小时所有索引器均不可用",
@@ -745,7 +745,7 @@
"SearchCutoffUnmet": "搜索未满足终止条件的",
"RadarrSupportsAnyDownloadClient": "Radarr支持许多常用的的torrent和usenet下载客户端。",
"VideoCodec": "视频编码",
"QualitySettings": "歌曲质量配置设置",
"QualitySettings": "媒体质量设置",
"UseHardlinksInsteadOfCopy": "使用硬链接代替复制",
"RecycleBinHelpText": "影片文件会被移动到回收站以替代永久删除",
"Redownload": "重新下载",
@@ -766,7 +766,7 @@
"Table": "表格",
"WaitingToImport": "等待导入",
"QualityOrLangCutoffHasNotBeenMet": "影片质量和语言未满足终止监控条件",
"QualityProfiles": "歌曲质量配置",
"QualityProfiles": "媒体质量配置",
"ProfilesSettingsSummary": "影片质量,语言和延时配置",
"WeekColumnHeader": "日期格式",
"YesCancel": "是,取消",
@@ -783,10 +783,10 @@
"RemovedMovieCheckSingleMessage": "影片“{0}”已从TMDb移除",
"UpgradeUntilThisQualityIsMetOrExceeded": "升级直到影片质量超出或者满足",
"SettingsWeekColumnHeader": "日期格式",
"ShowQualityProfileHelpText": "在海报下显示歌曲质量",
"ShowQualityProfileHelpText": "在海报下显示媒体质量配置",
"ReleaseRejected": "版本被拒绝",
"UnmappedFilesOnly": "未映射的文件",
"Quality": "歌曲质量",
"Quality": "媒体质量",
"TheLogLevelDefault": "默认的日志等级为“Info”可以被修改在",
"RestartReloadNote": "注意Radarr将在恢复过程中自动重启并重新加载UI。",
"RequiredRestrictionPlaceHolder": "添加新限制",
@@ -818,7 +818,7 @@
"QualityCutoffHasNotBeenMet": "影片还未满足质量配置",
"UISettingsSummary": "日历、日期和色弱模式选项",
"Scheduled": "计划中",
"ShowQualityProfile": "显示歌曲质量配置",
"ShowQualityProfile": "显示媒体质量配置",
"IndexerRssHealthCheckNoAvailableIndexers": "由于索引器错误所有支持rss的索引器暂时不可用",
"KeepAndUnmonitorMovie": "保持不监控影片",
"RadarrSupportsAnyIndexer": "Radarr支持任何使用Newznab标准的搜刮器以及下面列出的其他搜刮器。",
@@ -875,7 +875,7 @@
"NoAltTitle": "没有其他标题。",
"PreviewRenameHelpText": "小提示:要预览重命名,选择“取消”并点击任何影片标题并且使用",
"PtpOldSettingsCheckMessage": "下列PassThePopcorn搜刮器有已启用的设置请更新{0}",
"QualityDefinitions": "歌曲质量定义",
"QualityDefinitions": "媒体质量定义",
"RegularExpressionsCanBeTested": "正则表达式可供测试 ",
"ReleaseTitle": "歌曲发布标题",
"RemoveHelpTextWarning": "移除操作会从下载客户端中删除任务和已下载文件。",
@@ -987,7 +987,7 @@
"MovieExcludedFromAutomaticAdd": "影片已被排除在自动添加之外",
"MovieDetailsPreviousMovie": "影片详细:前一个",
"MovieDetailsNextMovie": "影片详细:下一个",
"MovieChat": "Movie Chat",
"MovieChat": "MovieChat.org",
"MovieAlreadyExcluded": "影片已排除",
"Mode": "模式",
"MinimumLimits": "最小限制",
@@ -1010,7 +1010,7 @@
"GrabReleaseMessageText": "Radarr无法确定这个发布版本是哪部电影Radarr可能无法自动导入此版本你想要获取“{0}”吗?",
"FeatureRequests": "功能建议",
"Extension": "扩展",
"Discord": "Discord",
"Discord": "冲突",
"CustomFormatUnknownConditionOption": "未知的条件“{1}”的选项“{0}”",
"Retention": "保留",
"ChmodGroupHelpText": "组名称或GID。对于远程文件系统请使用GID。",

View File

@@ -42,11 +42,9 @@ namespace NzbDrone.Core.MediaCover
try
{
using (var image = Image.Load(source))
{
image.Mutate(x => x.Resize(0, height));
image.Save(destination);
}
using var image = Image.Load(source);
image.Mutate(x => x.Resize(0, height));
image.Save(destination);
}
catch
{

View File

@@ -72,6 +72,7 @@ namespace NzbDrone.Core.MediaFiles
}
public static HashSet<string> Extensions => new HashSet<string>(_fileExtensions.Keys, StringComparer.OrdinalIgnoreCase);
public static HashSet<string> DiskExtensions => new HashSet<string>(new[] { ".img", ".iso", ".vob" }, StringComparer.OrdinalIgnoreCase);
public static Quality GetQualityForExtension(string extension)
{

View File

@@ -154,7 +154,7 @@ namespace NzbDrone.Core.MediaFiles.MediaInfo
}
Logger.ForDebugEvent()
.Message("Unknown audio format: '{0}' in '{1}'.", mediaInfo.RawStreamData, sceneName)
.Message("Unknown audio format: '{0}' in '{1}'. Streams: {2}", audioFormat, sceneName, mediaInfo.RawStreamData)
.WriteSentryWarn("UnknownAudioFormatFFProbe", mediaInfo.ContainerFormat, mediaInfo.AudioFormat, audioCodecID)
.Log();
@@ -236,8 +236,12 @@ namespace NzbDrone.Core.MediaFiles.MediaInfo
return "AV1";
}
if (videoFormat == "vp6" ||
videoFormat == "vp7" ||
if (videoFormat.Contains("vp6"))
{
return "VP6";
}
if (videoFormat == "vp7" ||
videoFormat == "vp8" ||
videoFormat == "vp9")
{
@@ -257,13 +261,15 @@ namespace NzbDrone.Core.MediaFiles.MediaInfo
videoFormat == "rv20" ||
videoFormat == "rv30" ||
videoFormat == "rv40" ||
videoFormat == "cinepak")
videoFormat == "cinepak" ||
videoFormat == "rawvideo" ||
videoFormat == "msvideo1")
{
return "";
}
Logger.ForDebugEvent()
.Message("Unknown video format: '{0}' in '{1}'.", mediaInfo.RawStreamData, sceneName)
.Message("Unknown video format: '{0}' in '{1}'. Streams: {2}", videoFormat, sceneName, mediaInfo.RawStreamData)
.WriteSentryWarn("UnknownVideoFormatFFProbe", mediaInfo.ContainerFormat, videoFormat, videoCodecID)
.Log();

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using FFMpegCore;
using FFMpegCore.Enums;
using NLog;
using NzbDrone.Common.Disk;
using NzbDrone.Common.Extensions;
@@ -55,6 +56,11 @@ namespace NzbDrone.Core.MediaFiles.MediaInfo
throw new FileNotFoundException("Media file does not exist: " + filename);
}
if (MediaFileExtensions.DiskExtensions.Contains(Path.GetExtension(filename)))
{
return null;
}
// TODO: Cache media info by path, mtime and length so we don't need to read files multiple times
try
{
@@ -62,6 +68,7 @@ namespace NzbDrone.Core.MediaFiles.MediaInfo
var ffprobeOutput = FFProbe.GetStreamJson(filename, ffOptions: new FFOptions { ExtraArguments = "-probesize 50000000" });
var analysis = FFProbe.AnalyseStreamJson(ffprobeOutput);
var primaryVideoStream = GetPrimaryVideoStream(analysis);
if (analysis.PrimaryAudioStream?.ChannelLayout.IsNullOrWhiteSpace() ?? true)
{
@@ -71,26 +78,26 @@ namespace NzbDrone.Core.MediaFiles.MediaInfo
var mediaInfoModel = new MediaInfoModel();
mediaInfoModel.ContainerFormat = analysis.Format.FormatName;
mediaInfoModel.VideoFormat = analysis.PrimaryVideoStream?.CodecName;
mediaInfoModel.VideoCodecID = analysis.PrimaryVideoStream?.CodecTagString;
mediaInfoModel.VideoProfile = analysis.PrimaryVideoStream?.Profile;
mediaInfoModel.VideoBitrate = analysis.PrimaryVideoStream?.BitRate ?? 0;
mediaInfoModel.VideoMultiViewCount = analysis.PrimaryVideoStream?.Tags?.ContainsKey("stereo_mode") ?? false ? 2 : 1;
mediaInfoModel.VideoBitDepth = GetPixelFormat(analysis.PrimaryVideoStream?.PixelFormat)?.Components.Min(x => x.BitDepth) ?? 8;
mediaInfoModel.VideoColourPrimaries = analysis.PrimaryVideoStream?.ColorPrimaries;
mediaInfoModel.VideoTransferCharacteristics = analysis.PrimaryVideoStream?.ColorTransfer;
mediaInfoModel.DoviConfigurationRecord = analysis.PrimaryVideoStream?.SideDataList?.Find(x => x.GetType().Name == nameof(DoviConfigurationRecordSideData)) as DoviConfigurationRecordSideData;
mediaInfoModel.Height = analysis.PrimaryVideoStream?.Height ?? 0;
mediaInfoModel.Width = analysis.PrimaryVideoStream?.Width ?? 0;
mediaInfoModel.VideoFormat = primaryVideoStream?.CodecName;
mediaInfoModel.VideoCodecID = primaryVideoStream?.CodecTagString;
mediaInfoModel.VideoProfile = primaryVideoStream?.Profile;
mediaInfoModel.VideoBitrate = primaryVideoStream?.BitRate ?? 0;
mediaInfoModel.VideoMultiViewCount = primaryVideoStream?.Tags?.ContainsKey("stereo_mode") ?? false ? 2 : 1;
mediaInfoModel.VideoBitDepth = GetPixelFormat(primaryVideoStream?.PixelFormat)?.Components.Min(x => x.BitDepth) ?? 8;
mediaInfoModel.VideoColourPrimaries = primaryVideoStream?.ColorPrimaries;
mediaInfoModel.VideoTransferCharacteristics = primaryVideoStream?.ColorTransfer;
mediaInfoModel.DoviConfigurationRecord = primaryVideoStream?.SideDataList?.Find(x => x.GetType().Name == nameof(DoviConfigurationRecordSideData)) as DoviConfigurationRecordSideData;
mediaInfoModel.Height = primaryVideoStream?.Height ?? 0;
mediaInfoModel.Width = primaryVideoStream?.Width ?? 0;
mediaInfoModel.AudioFormat = analysis.PrimaryAudioStream?.CodecName;
mediaInfoModel.AudioCodecID = analysis.PrimaryAudioStream?.CodecTagString;
mediaInfoModel.AudioProfile = analysis.PrimaryAudioStream?.Profile;
mediaInfoModel.AudioBitrate = analysis.PrimaryAudioStream?.BitRate ?? 0;
mediaInfoModel.RunTime = GetBestRuntime(analysis.PrimaryAudioStream?.Duration, analysis.PrimaryVideoStream?.Duration, analysis.Format.Duration);
mediaInfoModel.RunTime = GetBestRuntime(analysis.PrimaryAudioStream?.Duration, primaryVideoStream?.Duration, analysis.Format.Duration);
mediaInfoModel.AudioStreamCount = analysis.AudioStreams.Count;
mediaInfoModel.AudioChannels = analysis.PrimaryAudioStream?.Channels ?? 0;
mediaInfoModel.AudioChannelPositions = analysis.PrimaryAudioStream?.ChannelLayout;
mediaInfoModel.VideoFps = analysis.PrimaryVideoStream?.FrameRate ?? 0;
mediaInfoModel.VideoFps = primaryVideoStream?.FrameRate ?? 0;
mediaInfoModel.AudioLanguages = analysis.AudioStreams?.Select(x => x.Language)
.Where(l => l.IsNotNullOrWhiteSpace())
.ToList();
@@ -112,7 +119,7 @@ namespace NzbDrone.Core.MediaFiles.MediaInfo
frames = FFProbe.AnalyseFrameJson(frameOutput);
}
var streamSideData = analysis.PrimaryVideoStream?.SideDataList ?? new ();
var streamSideData = primaryVideoStream?.SideDataList ?? new ();
var framesSideData = frames?.Frames?.Count > 0 ? frames?.Frames[0]?.SideDataList ?? new () : new ();
var sideData = streamSideData.Concat(framesSideData).ToList();
@@ -150,6 +157,19 @@ namespace NzbDrone.Core.MediaFiles.MediaInfo
return video.Value;
}
private VideoStream GetPrimaryVideoStream(IMediaAnalysis mediaAnalysis)
{
if (mediaAnalysis.VideoStreams.Count <= 1)
{
return mediaAnalysis.PrimaryVideoStream;
}
// motion image codec streams are often in front of the main video stream
var codecFilter = new[] { "mjpeg", "png" };
return mediaAnalysis.VideoStreams.FirstOrDefault(s => !codecFilter.Contains(s.CodecName)) ?? mediaAnalysis.PrimaryVideoStream;
}
private FFProbePixelFormat GetPixelFormat(string format)
{
return _pixelFormats.Find(x => x.Name == format);

View File

@@ -8,9 +8,10 @@ using NzbDrone.Common.Extensions;
using NzbDrone.Core.Download;
using NzbDrone.Core.Extras;
using NzbDrone.Core.History;
using NzbDrone.Core.MediaFiles.Commands;
using NzbDrone.Core.MediaFiles.Events;
using NzbDrone.Core.Messaging.Commands;
using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Parser;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Qualities;
@@ -29,6 +30,7 @@ namespace NzbDrone.Core.MediaFiles.MovieImport
private readonly IDiskProvider _diskProvider;
private readonly IHistoryService _historyService;
private readonly IEventAggregator _eventAggregator;
private readonly IManageCommandQueue _commandQueueManager;
private readonly Logger _logger;
public ImportApprovedMovie(IUpgradeMediaFiles movieFileUpgrader,
@@ -37,6 +39,7 @@ namespace NzbDrone.Core.MediaFiles.MovieImport
IDiskProvider diskProvider,
IHistoryService historyService,
IEventAggregator eventAggregator,
IManageCommandQueue commandQueueManager,
Logger logger)
{
_movieFileUpgrader = movieFileUpgrader;
@@ -45,6 +48,7 @@ namespace NzbDrone.Core.MediaFiles.MovieImport
_diskProvider = diskProvider;
_historyService = historyService;
_eventAggregator = eventAggregator;
_commandQueueManager = commandQueueManager;
_logger = logger;
}
@@ -157,6 +161,8 @@ namespace NzbDrone.Core.MediaFiles.MovieImport
{
_logger.Warn(e, "Couldn't import movie " + localMovie);
importResults.Add(new ImportResult(importDecision, "Failed to import movie, Destination already exists."));
_commandQueueManager.Push(new RescanMovieCommand(localMovie.Movie.Id));
}
catch (Exception e)
{

View File

@@ -121,8 +121,8 @@ namespace NzbDrone.Core.MediaFiles.MovieImport.Manual
SceneSource = SceneSource(movie, rootFolder),
ExistingFile = movie.Path.IsParentPath(path),
Size = _diskProvider.GetFileSize(path),
Languages = (languages?.SingleOrDefault() ?? Language.Unknown) == Language.Unknown ? languageParse : languages,
Quality = quality.Quality == Quality.Unknown ? QualityParser.ParseQuality(path) : quality,
Languages = languages?.Count <= 1 && (languages?.SingleOrDefault() ?? Language.Unknown) == Language.Unknown ? languageParse : languages,
Quality = (quality?.Quality ?? Quality.Unknown) == Quality.Unknown ? QualityParser.ParseQuality(path) : quality,
ReleaseGroup = releaseGroup.IsNullOrWhiteSpace() ? Parser.Parser.ParseReleaseGroup(path) : releaseGroup,
};

View File

@@ -61,17 +61,14 @@ namespace NzbDrone.Core.Movies
{
get
{
if (PhysicalRelease.HasValue)
if ((PhysicalRelease.HasValue && PhysicalRelease.Value >= DateTime.UtcNow.AddDays(-21)) ||
(DigitalRelease.HasValue && DigitalRelease.Value >= DateTime.UtcNow.AddDays(-21)) ||
(InCinemas.HasValue && InCinemas.Value >= DateTime.UtcNow.AddDays(-120)))
{
return PhysicalRelease.Value >= DateTime.UtcNow.AddDays(-21);
return true;
}
if (InCinemas.HasValue)
{
return InCinemas.Value >= DateTime.UtcNow.AddDays(-120);
}
return true;
return false;
}
}

View File

@@ -0,0 +1,65 @@
using System.Collections.Generic;
using FluentValidation.Results;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.Movies;
namespace NzbDrone.Core.Notifications.Apprise
{
public class Apprise : NotificationBase<AppriseSettings>
{
public override string Name => "Apprise";
public override string Link => "https://github.com/caronc/apprise";
private readonly IAppriseProxy _proxy;
public Apprise(IAppriseProxy proxy)
{
_proxy = proxy;
}
public override void OnGrab(GrabMessage grabMessage)
{
_proxy.SendNotification(MOVIE_GRABBED_TITLE, grabMessage.Message, Settings);
}
public override void OnDownload(DownloadMessage message)
{
_proxy.SendNotification(MOVIE_DOWNLOADED_TITLE, message.Message, Settings);
}
public override void OnMovieAdded(Movie movie)
{
_proxy.SendNotification(MOVIE_ADDED_TITLE, $"{movie.Title} added to library", Settings);
}
public override void OnMovieFileDelete(MovieFileDeleteMessage deleteMessage)
{
_proxy.SendNotification(MOVIE_FILE_DELETED_TITLE, deleteMessage.Message, Settings);
}
public override void OnMovieDelete(MovieDeleteMessage deleteMessage)
{
_proxy.SendNotification(MOVIE_DELETED_TITLE, deleteMessage.Message, Settings);
}
public override void OnHealthIssue(HealthCheck.HealthCheck healthCheck)
{
_proxy.SendNotification(HEALTH_ISSUE_TITLE, healthCheck.Message, Settings);
}
public override void OnApplicationUpdate(ApplicationUpdateMessage updateMessage)
{
_proxy.SendNotification(APPLICATION_UPDATE_TITLE, updateMessage.Message, Settings);
}
public override ValidationResult Test()
{
var failures = new List<ValidationFailure>();
failures.AddIfNotNull(_proxy.Test(Settings));
return new ValidationResult(failures);
}
}
}

View File

@@ -0,0 +1,7 @@
namespace NzbDrone.Core.Notifications.Apprise
{
public class AppriseError
{
public string Error { get; set; }
}
}

View File

@@ -0,0 +1,18 @@
using System;
using NzbDrone.Common.Exceptions;
namespace NzbDrone.Core.Notifications.Apprise
{
public class AppriseException : NzbDroneException
{
public AppriseException(string message)
: base(message)
{
}
public AppriseException(string message, Exception innerException, params object[] args)
: base(message, innerException, args)
{
}
}
}

View File

@@ -0,0 +1,19 @@
using System.Runtime.Serialization;
namespace NzbDrone.Core.Notifications.Apprise
{
public enum AppriseNotificationType
{
[EnumMember(Value = "info")]
Info,
[EnumMember(Value = "success")]
Success,
[EnumMember(Value = "warning")]
Warning,
[EnumMember(Value = "failure")]
Failure,
}
}

View File

@@ -0,0 +1,15 @@
namespace NzbDrone.Core.Notifications.Apprise
{
public class ApprisePayload
{
public string Urls { get; set; }
public string Title { get; set; }
public string Body { get; set; }
public AppriseNotificationType Type { get; set; }
public string Tag { get; set; }
}
}

View File

@@ -0,0 +1,118 @@
using System;
using System.Linq;
using System.Net;
using FluentValidation.Results;
using NLog;
using NzbDrone.Common.Extensions;
using NzbDrone.Common.Http;
using NzbDrone.Common.Serializer;
namespace NzbDrone.Core.Notifications.Apprise
{
public interface IAppriseProxy
{
void SendNotification(string title, string message, AppriseSettings settings);
ValidationFailure Test(AppriseSettings settings);
}
public class AppriseProxy : IAppriseProxy
{
private readonly IHttpClient _httpClient;
private readonly Logger _logger;
public AppriseProxy(IHttpClient httpClient, Logger logger)
{
_httpClient = httpClient;
_logger = logger;
}
public void SendNotification(string title, string message, AppriseSettings settings)
{
var payload = new ApprisePayload
{
Title = title,
Body = message,
Type = (AppriseNotificationType)settings.NotificationType
};
var requestBuilder = new HttpRequestBuilder(settings.ServerUrl.TrimEnd('/', ' '))
.Post()
.Accept(HttpAccept.Json);
if (settings.ConfigurationKey.IsNotNullOrWhiteSpace())
{
requestBuilder
.Resource("/notify/{configurationKey}")
.SetSegment("configurationKey", settings.ConfigurationKey);
}
else if (settings.StatelessUrls.IsNotNullOrWhiteSpace())
{
requestBuilder.Resource("/notify");
payload.Urls = settings.StatelessUrls;
}
if (settings.Tags.Any())
{
payload.Tag = settings.Tags.Join(",");
}
if (settings.AuthUsername.IsNotNullOrWhiteSpace() || settings.AuthPassword.IsNotNullOrWhiteSpace())
{
requestBuilder.NetworkCredential = new BasicNetworkCredential(settings.AuthUsername, settings.AuthPassword);
}
var request = requestBuilder.Build();
request.Headers.ContentType = "application/json";
request.SetContent(payload.ToJson());
try
{
_httpClient.Execute(request);
}
catch (HttpException ex)
{
_logger.Error(ex, "Unable to send message");
throw new AppriseException("Unable to send Apprise notifications: {0}", ex, ex.Message);
}
}
public ValidationFailure Test(AppriseSettings settings)
{
const string title = "Radarr - Test Notification";
const string body = "Success! You have properly configured your apprise notification settings.";
try
{
SendNotification(title, body, settings);
}
catch (AppriseException ex) when (ex.InnerException is HttpException httpException)
{
if (httpException.Response.StatusCode == HttpStatusCode.Unauthorized)
{
_logger.Error(ex, $"HTTP Auth credentials are invalid: {0}", ex.Message);
return new ValidationFailure("AuthUsername", $"HTTP Auth credentials are invalid: {ex.Message}");
}
if (httpException.Response.Content.IsNotNullOrWhiteSpace())
{
var error = Json.Deserialize<AppriseError>(httpException.Response.Content);
_logger.Error(ex, $"Unable to send test message. Response from API: {0}", error.Error);
return new ValidationFailure(string.Empty, $"Unable to send test message. Response from API: {error.Error}");
}
_logger.Error(ex, "Unable to send test message. Server connection failed: ({0}) {1}", httpException.Response.StatusCode, ex.Message);
return new ValidationFailure("Url", $"Unable to connect to Apprise API. Server connection failed: ({httpException.Response.StatusCode}) {ex.Message}");
}
catch (Exception ex)
{
_logger.Error(ex, "Unable to send test message: {0}", ex.Message);
return new ValidationFailure("Url", $"Unable to send test message: {ex.Message}");
}
return null;
}
}
}

View File

@@ -0,0 +1,74 @@
using System;
using System.Collections.Generic;
using FluentValidation;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.Annotations;
using NzbDrone.Core.ThingiProvider;
using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Notifications.Apprise
{
public class AppriseSettingsValidator : AbstractValidator<AppriseSettings>
{
public AppriseSettingsValidator()
{
RuleFor(c => c.ServerUrl).IsValidUrl();
RuleFor(c => c.ConfigurationKey).NotEmpty()
.When(c => c.StatelessUrls.IsNullOrWhiteSpace())
.WithMessage("Use either Configuration Key or Stateless URLs");
RuleFor(c => c.ConfigurationKey).Matches("^[a-z0-9-]*$")
.WithMessage("Allowed characters a-z, 0-9 and -");
RuleFor(c => c.StatelessUrls).NotEmpty()
.When(c => c.ConfigurationKey.IsNullOrWhiteSpace())
.WithMessage("Use either Configuration Key or Stateless URLs");
RuleFor(c => c.StatelessUrls).Empty()
.When(c => c.ConfigurationKey.IsNotNullOrWhiteSpace())
.WithMessage("Use either Configuration Key or Stateless URLs");
RuleFor(c => c.Tags).Empty()
.When(c => c.StatelessUrls.IsNotNullOrWhiteSpace())
.WithMessage("Stateless URLs do not support tags");
}
}
public class AppriseSettings : IProviderConfig
{
private static readonly AppriseSettingsValidator Validator = new ();
public AppriseSettings()
{
NotificationType = (int)AppriseNotificationType.Info;
Tags = Array.Empty<string>();
}
[FieldDefinition(1, Label = "Apprise Server URL", Type = FieldType.Url, Placeholder = "http://localhost:8000", HelpText = "Apprise server URL, including http(s):// and port if needed", HelpLink = "https://github.com/caronc/apprise-api")]
public string ServerUrl { get; set; }
[FieldDefinition(2, Label = "Apprise Configuration Key", Type = FieldType.Textbox, HelpText = "Configuration Key for the Persistent Storage Solution. Leave empty if Stateless URLs is used.", HelpLink = "https://github.com/caronc/apprise-api#persistent-storage-solution")]
public string ConfigurationKey { get; set; }
[FieldDefinition(3, Label = "Apprise Stateless URLs", Type = FieldType.Textbox, HelpText = "One or more URLs separated by commas identifying where the notification should be sent to. Leave empty if Persistent Storage is used.", HelpLink = "https://github.com/caronc/apprise#productivity-based-notifications")]
public string StatelessUrls { get; set; }
[FieldDefinition(4, Label = "Apprise Notification Type", Type = FieldType.Select, SelectOptions = typeof(AppriseNotificationType))]
public int NotificationType { get; set; }
[FieldDefinition(5, Label = "Apprise Tags", Type = FieldType.Tag, HelpText = "Optionally notify only those tagged accordingly.")]
public IEnumerable<string> Tags { get; set; }
[FieldDefinition(6, Label = "Username", Type = FieldType.Textbox, HelpText = "HTTP Basic Auth Username", Privacy = PrivacyLevel.UserName)]
public string AuthUsername { get; set; }
[FieldDefinition(7, Label = "Password", Type = FieldType.Password, HelpText = "HTTP Basic Auth Password", Privacy = PrivacyLevel.Password)]
public string AuthPassword { get; set; }
public NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));
}
}
}

View File

@@ -29,7 +29,7 @@ namespace NzbDrone.Core.Notifications.Boxcar
public override void OnMovieAdded(Movie movie)
{
_proxy.SendNotification(MOVIE_ADDED_TITLE_BRANDED, $"{movie.Title} added to library", Settings);
_proxy.SendNotification(MOVIE_ADDED_TITLE, $"{movie.Title} added to library", Settings);
}
public override void OnMovieFileDelete(MovieFileDeleteMessage deleteMessage)

View File

@@ -83,30 +83,13 @@ namespace NzbDrone.Core.Notifications.Email
return new ValidationResult(failures);
}
public ValidationFailure Test(EmailSettings settings)
{
const string body = "Success! You have properly configured your email notification settings";
try
{
SendEmail(settings, "Radarr - Test Notification", body);
}
catch (Exception ex)
{
_logger.Error(ex, "Unable to send test email");
return new ValidationFailure("Server", "Unable to send test email");
}
return null;
}
private void SendEmail(EmailSettings settings, string subject, string body, bool htmlBody = false)
{
var email = new MimeMessage();
email.From.Add(ParseAddress("From", settings.From));
email.To.AddRange(settings.To.Select(x => ParseAddress("To", x)));
email.Cc.AddRange(settings.CC.Select(x => ParseAddress("CC", x)));
email.Cc.AddRange(settings.Cc.Select(x => ParseAddress("CC", x)));
email.Bcc.AddRange(settings.Bcc.Select(x => ParseAddress("BCC", x)));
email.Subject = subject;
@@ -129,52 +112,67 @@ namespace NzbDrone.Core.Notifications.Email
throw;
}
_logger.Debug("Finished sending email. Subject: {0}", email.Subject);
_logger.Debug("Finished sending email. Subject: {0}", subject);
}
private void Send(MimeMessage email, EmailSettings settings)
{
using (var client = new SmtpClient())
using var client = new SmtpClient();
client.Timeout = 10000;
var serverOption = SecureSocketOptions.Auto;
if (settings.RequireEncryption)
{
client.Timeout = 10000;
var serverOption = SecureSocketOptions.Auto;
if (settings.RequireEncryption)
if (settings.Port == 465)
{
if (settings.Port == 465)
{
serverOption = SecureSocketOptions.SslOnConnect;
}
else
{
serverOption = SecureSocketOptions.StartTls;
}
serverOption = SecureSocketOptions.SslOnConnect;
}
client.ServerCertificateValidationCallback = _certificateValidationService.ShouldByPassValidationError;
_logger.Debug("Connecting to mail server");
client.Connect(settings.Server, settings.Port, serverOption);
if (!string.IsNullOrWhiteSpace(settings.Username))
else
{
_logger.Debug("Authenticating to mail server");
client.Authenticate(settings.Username, settings.Password);
serverOption = SecureSocketOptions.StartTls;
}
_logger.Debug("Sending to mail server");
client.Send(email);
_logger.Debug("Sent to mail server, disconnecting");
client.Disconnect(true);
_logger.Debug("Disconnecting from mail server");
}
client.ServerCertificateValidationCallback = _certificateValidationService.ShouldByPassValidationError;
_logger.Debug("Connecting to mail server");
client.Connect(settings.Server, settings.Port, serverOption);
if (!string.IsNullOrWhiteSpace(settings.Username))
{
_logger.Debug("Authenticating to mail server");
client.Authenticate(settings.Username, settings.Password);
}
_logger.Debug("Sending to mail server");
client.Send(email);
_logger.Debug("Sent to mail server, disconnecting");
client.Disconnect(true);
_logger.Debug("Disconnecting from mail server");
}
public ValidationFailure Test(EmailSettings settings)
{
const string body = "Success! You have properly configured your email notification settings";
try
{
SendEmail(settings, "Radarr - Test Notification", body);
}
catch (Exception ex)
{
_logger.Error(ex, "Unable to send test email");
return new ValidationFailure("Server", "Unable to send test email");
}
return null;
}
private MailboxAddress ParseAddress(string type, string address)

View File

@@ -16,13 +16,13 @@ namespace NzbDrone.Core.Notifications.Email
RuleFor(c => c.Port).InclusiveBetween(1, 65535);
RuleFor(c => c.From).NotEmpty();
RuleForEach(c => c.To).EmailAddress();
RuleForEach(c => c.CC).EmailAddress();
RuleForEach(c => c.Cc).EmailAddress();
RuleForEach(c => c.Bcc).EmailAddress();
// Only require one of three send fields to be set
RuleFor(c => c.To).NotEmpty().Unless(c => c.Bcc.Any() || c.CC.Any());
RuleFor(c => c.CC).NotEmpty().Unless(c => c.To.Any() || c.Bcc.Any());
RuleFor(c => c.Bcc).NotEmpty().Unless(c => c.To.Any() || c.CC.Any());
RuleFor(c => c.To).NotEmpty().Unless(c => c.Bcc.Any() || c.Cc.Any());
RuleFor(c => c.Cc).NotEmpty().Unless(c => c.To.Any() || c.Bcc.Any());
RuleFor(c => c.Bcc).NotEmpty().Unless(c => c.To.Any() || c.Cc.Any());
}
}
@@ -32,9 +32,10 @@ namespace NzbDrone.Core.Notifications.Email
public EmailSettings()
{
Port = 567;
Port = 587;
To = Array.Empty<string>();
CC = Array.Empty<string>();
Cc = Array.Empty<string>();
Bcc = Array.Empty<string>();
}
@@ -60,7 +61,7 @@ namespace NzbDrone.Core.Notifications.Email
public IEnumerable<string> To { get; set; }
[FieldDefinition(7, Label = "CC Address(es)", HelpText = "Comma separated list of email cc recipients", Placeholder = "example@email.com,example1@email.com", Advanced = true)]
public IEnumerable<string> CC { get; set; }
public IEnumerable<string> Cc { get; set; }
[FieldDefinition(8, Label = "BCC Address(es)", HelpText = "Comma separated list of email bcc recipients", Placeholder = "example@email.com,example1@email.com", Advanced = true)]
public IEnumerable<string> Bcc { get; set; }

View File

@@ -36,12 +36,12 @@ namespace NzbDrone.Core.Notifications.Ntfy
public override void OnMovieFileDelete(MovieFileDeleteMessage deleteMessage)
{
_proxy.SendNotification(MOVIE_FILE_DELETED_TITLE, deleteMessage.Message, Settings);
_proxy.SendNotification(MOVIE_FILE_DELETED_TITLE_BRANDED, deleteMessage.Message, Settings);
}
public override void OnMovieDelete(MovieDeleteMessage deleteMessage)
{
_proxy.SendNotification(MOVIE_DELETED_TITLE, deleteMessage.Message, Settings);
_proxy.SendNotification(MOVIE_DELETED_TITLE_BRANDED, deleteMessage.Message, Settings);
}
public override void OnHealthIssue(HealthCheck.HealthCheck healthCheck)

View File

@@ -37,12 +37,12 @@ namespace NzbDrone.Core.Notifications.PushBullet
public override void OnMovieFileDelete(MovieFileDeleteMessage deleteMessage)
{
_proxy.SendNotification(MOVIE_FILE_DELETED_TITLE, deleteMessage.Message, Settings);
_proxy.SendNotification(MOVIE_FILE_DELETED_TITLE_BRANDED, deleteMessage.Message, Settings);
}
public override void OnMovieDelete(MovieDeleteMessage deleteMessage)
{
_proxy.SendNotification(MOVIE_DELETED_TITLE, deleteMessage.Message, Settings);
_proxy.SendNotification(MOVIE_DELETED_TITLE_BRANDED, deleteMessage.Message, Settings);
}
public override void OnHealthIssue(HealthCheck.HealthCheck healthCheck)

View File

@@ -39,6 +39,7 @@ namespace NzbDrone.Core.Notifications.Telegram
.AddFormParameter("parse_mode", "HTML")
.AddFormParameter("text", text)
.AddFormParameter("disable_notification", settings.SendSilently)
.AddFormParameter("message_thread_id", settings.TopicId)
.Build();
_httpClient.Post(request);
@@ -64,7 +65,16 @@ namespace NzbDrone.Core.Notifications.Telegram
else if (ex is Common.Http.HttpException restException && restException.Response.StatusCode == HttpStatusCode.BadRequest)
{
var error = Json.Deserialize<TelegramError>(restException.Response.Content);
var property = error.Description.ContainsIgnoreCase("chat not found") ? "ChatId" : "BotToken";
var property = "BotToken";
if (error.Description.ContainsIgnoreCase("chat not found") || error.Description.ContainsIgnoreCase("group chat was upgraded to a supergroup chat"))
{
property = "ChatId";
}
else if (error.Description.ContainsIgnoreCase("message thread not found"))
{
property = "TopicId";
}
return new ValidationFailure(property, error.Description);
}

View File

@@ -11,6 +11,8 @@ namespace NzbDrone.Core.Notifications.Telegram
{
RuleFor(c => c.BotToken).NotEmpty();
RuleFor(c => c.ChatId).NotEmpty();
RuleFor(c => c.TopicId).Must(topicId => !topicId.HasValue || topicId > 1)
.WithMessage("Topic ID must be greater than 1 or empty");
}
}
@@ -24,7 +26,10 @@ namespace NzbDrone.Core.Notifications.Telegram
[FieldDefinition(1, Label = "Chat ID", HelpLink = "http://stackoverflow.com/a/37396871/882971", HelpText = "You must start a conversation with the bot or add it to your group to receive messages")]
public string ChatId { get; set; }
[FieldDefinition(2, Label = "Send Silently", Type = FieldType.Checkbox, HelpText = "Sends the message silently. Users will receive a notification with no sound")]
[FieldDefinition(2, Label = "Topic ID", HelpLink = "https://stackoverflow.com/a/75178418", HelpText = "Specify a Topic ID to send notifications to that topic. Leave blank to use the general topic (Supergroups only)")]
public int? TopicId { get; set; }
[FieldDefinition(3, Label = "Send Silently", Type = FieldType.Checkbox, HelpText = "Sends the message silently. Users will receive a notification with no sound")]
public bool SendSilently { get; set; }
public NzbDroneValidationResult Validate()

View File

@@ -41,7 +41,7 @@ namespace NzbDrone.Core.Organizer
private static readonly Regex TitleRegex = new Regex(@"(?<tag>\{(?:imdb-|edition-))?\{(?<prefix>[- ._\[(]*)(?<token>(?:[a-z0-9]+)(?:(?<separator>[- ._]+)(?:[a-z0-9]+))?)(?::(?<customFormat>[a-z0-9|+-]+(?<!-)))?(?<suffix>[-} ._)\]]*)\}",
RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);
public static readonly Regex MovieTitleRegex = new Regex(@"(?<token>\{((?:(Movie|Original))(?<separator>[- ._])(Clean|Original)?(Title|Filename)(The)?)(?::(?<customFormat>[a-z0-9|]+))?\})",
public static readonly Regex MovieTitleRegex = new Regex(@"(?<token>\{((?:(Movie|Original))(?<separator>[- ._])(Clean)?(Original)?(Title|Filename)(The)?)(?::(?<customFormat>[a-z0-9|]+))?\})",
RegexOptions.Compiled | RegexOptions.IgnoreCase);
private static readonly Regex FileNameCleanupRegex = new Regex(@"([- ._])(\1)+", RegexOptions.Compiled);
@@ -247,7 +247,7 @@ namespace NzbDrone.Core.Organizer
{
tokenHandlers["{Movie Title}"] = m => GetLanguageTitle(movie, m.CustomFormat);
tokenHandlers["{Movie CleanTitle}"] = m => CleanTitle(GetLanguageTitle(movie, m.CustomFormat));
tokenHandlers["{Movie Title The}"] = m => TitleThe(movie.Title);
tokenHandlers["{Movie TitleThe}"] = m => TitleThe(movie.Title);
tokenHandlers["{Movie TitleFirstCharacter}"] = m => TitleThe(movie.Title).Substring(0, 1).FirstCharToUpper();
tokenHandlers["{Movie OriginalTitle}"] = m => movie.MovieMetadata.Value.OriginalTitle ?? string.Empty;
tokenHandlers["{Movie CleanOriginalTitle}"] = m => CleanTitle(movie.MovieMetadata.Value.OriginalTitle) ?? string.Empty;

View File

@@ -4,7 +4,6 @@ using System.Linq;
using NLog;
using NzbDrone.Core.DecisionEngine;
using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Languages;
using NzbDrone.Core.Movies;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Parser.RomanNumerals;
@@ -214,31 +213,15 @@ namespace NzbDrone.Core.Parser
possibleTitles.AddRange(searchCriteria.Movie.MovieMetadata.Value.AlternativeTitles.Select(t => t.CleanTitle));
possibleTitles.AddRange(searchCriteria.Movie.MovieMetadata.Value.Translations.Select(t => t.CleanTitle));
var cleanTitle = parsedMovieInfo.PrimaryMovieTitle.CleanMovieTitle();
var cleanTitles = parsedMovieInfo.MovieTitles.Select(t => t.CleanMovieTitle()).ToArray();
foreach (var title in possibleTitles)
if (possibleTitles.Any(pt =>
cleanTitles.Contains(pt)
|| _arabicRomanNumeralMappings.Any(mn =>
cleanTitles.Contains(pt.Replace(mn.ArabicNumeralAsString, mn.RomanNumeralLowerCase))
|| cleanTitles.Any(t => t.Replace(mn.ArabicNumeralAsString, mn.RomanNumeralLowerCase) == pt))))
{
if (title == cleanTitle)
{
possibleMovie = searchCriteria.Movie;
}
foreach (var numeralMapping in _arabicRomanNumeralMappings)
{
var arabicNumeral = numeralMapping.ArabicNumeralAsString;
var romanNumeral = numeralMapping.RomanNumeralLowerCase;
// _logger.Debug(cleanTitle);
if (title.Replace(arabicNumeral, romanNumeral) == cleanTitle)
{
possibleMovie = searchCriteria.Movie;
}
if (title == cleanTitle.Replace(arabicNumeral, romanNumeral))
{
possibleMovie = searchCriteria.Movie;
}
}
possibleMovie = searchCriteria.Movie;
}
if (possibleMovie != null)

View File

@@ -5,24 +5,24 @@
<ItemGroup>
<PackageReference Include="Dapper" Version="2.0.123" />
<PackageReference Include="Equ" Version="2.3.0" />
<PackageReference Include="MailKit" Version="2.15.0" />
<PackageReference Include="MailKit" Version="3.6.0" />
<PackageReference Include="Npgsql" Version="6.0.3" />
<PackageReference Include="Servarr.FFMpegCore" Version="4.7.0-26" />
<PackageReference Include="Servarr.FFprobe" Version="5.1.2.106" />
<PackageReference Include="System.Memory" Version="4.5.5" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="6.0.1" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="6.0.1" />
<PackageReference Include="Servarr.FluentMigrator.Runner" Version="3.3.2.9" />
<PackageReference Include="Servarr.FluentMigrator.Runner.SQLite" Version="3.3.2.9" />
<PackageReference Include="Servarr.FluentMigrator.Runner.Postgres" Version="3.3.2.9" />
<PackageReference Include="FluentValidation" Version="8.6.2" />
<PackageReference Include="SixLabors.ImageSharp" Version="2.1.3" />
<PackageReference Include="SixLabors.ImageSharp" Version="3.0.1" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
<PackageReference Include="NLog" Version="5.0.1" />
<PackageReference Include="System.Data.SQLite.Core.Servarr" Version="1.0.115.5-18" />
<PackageReference Include="MonoTorrent" Version="2.0.7" />
<PackageReference Include="System.Text.Json" Version="6.0.5" />
<PackageReference Include="System.Text.Json" Version="6.0.7" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\NzbDrone.Common\Radarr.Common.csproj" />

View File

@@ -182,9 +182,7 @@ namespace NzbDrone.Core.RootFolders
public string GetBestRootFolderPath(string path)
{
var possibleRootFolder = All().Where(r => r.Path.IsParentPath(path))
.OrderByDescending(r => r.Path.Length)
.FirstOrDefault();
var possibleRootFolder = All().Where(r => r.Path.IsParentPath(path)).MaxBy(r => r.Path.Length);
if (possibleRootFolder == null)
{

View File

@@ -5,10 +5,10 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.Text.Encoding.CodePages" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="6.0.1" />
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerGen" Version="6.3.0" />
<PackageReference Include="DryIoc.dll" Version="5.3.0" />
<PackageReference Include="DryIoc.Microsoft.DependencyInjection" Version="6.1.0" />
<PackageReference Include="DryIoc.dll" Version="5.3.4" />
<PackageReference Include="DryIoc.Microsoft.DependencyInjection" Version="6.1.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\NzbDrone.Common\Radarr.Common.csproj" />

View File

@@ -224,6 +224,8 @@ namespace NzbDrone.Host
appFolderFactory.Register();
pidFileProvider.Write();
configFileProvider.EnsureDefaultConfigFile();
reconfigureLogging.Reconfigure();
EnsureSingleInstance(false, startupContext, singleInstancePolicy);

View File

@@ -4,7 +4,7 @@
<OutputType>Library</OutputType>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="6.0.8" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="6.0.16" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\NzbDrone.Test.Common\Radarr.Test.Common.csproj" />

View File

@@ -4,8 +4,8 @@
<TargetFrameworks>net6.0</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="DryIoc.dll" Version="5.3.0" />
<PackageReference Include="DryIoc.Microsoft.DependencyInjection" Version="6.1.0" />
<PackageReference Include="DryIoc.dll" Version="5.3.4" />
<PackageReference Include="DryIoc.Microsoft.DependencyInjection" Version="6.1.1" />
<PackageReference Include="NLog" Version="5.0.1" />
</ItemGroup>
<ItemGroup>

View File

@@ -26,15 +26,15 @@ namespace Radarr.Api.V3.Calendar
}
[HttpGet("Radarr.ics")]
public IActionResult GetCalendarFeed(int pastDays = 7, int futureDays = 28, string tagList = "", bool unmonitored = false)
public IActionResult GetCalendarFeed(int pastDays = 7, int futureDays = 28, string tags = "", bool unmonitored = false)
{
var start = DateTime.Today.AddDays(-pastDays);
var end = DateTime.Today.AddDays(futureDays);
var tags = new List<int>();
var parsedTags = new List<int>();
if (tagList.IsNotNullOrWhiteSpace())
if (tags.IsNotNullOrWhiteSpace())
{
tags.AddRange(tagList.Split(',').Select(_tagService.GetTag).Select(t => t.Id));
parsedTags.AddRange(tags.Split(',').Select(_tagService.GetTag).Select(t => t.Id));
}
var movies = _movieService.GetMoviesBetweenDates(start, end, unmonitored);
@@ -49,7 +49,7 @@ namespace Radarr.Api.V3.Calendar
foreach (var movie in movies.OrderBy(v => v.Added))
{
if (tags.Any() && tags.None(movie.Tags.Contains))
if (parsedTags.Any() && parsedTags.None(movie.Tags.Contains))
{
continue;
}

View File

@@ -35,7 +35,9 @@ namespace Radarr.Api.V3.ManualImport
item.Movie = processedItem.Movie.ToResource(0);
item.Rejections = processedItem.Rejections;
if (item.Languages.Single() == Language.Unknown)
if (item.Languages?.Count <= 1 && (item.Languages?.SingleOrDefault() ?? Language.Unknown) == Language.Unknown &&
processedItem.Languages.Any())
{
item.Languages = processedItem.Languages;
}
@@ -45,7 +47,7 @@ namespace Radarr.Api.V3.ManualImport
item.Quality = processedItem.Quality;
}
if (item.ReleaseGroup.IsNotNullOrWhiteSpace())
if (item.ReleaseGroup.IsNullOrWhiteSpace())
{
item.ReleaseGroup = processedItem.ReleaseGroup;
}

View File

@@ -562,7 +562,7 @@
}
},
{
"name": "tagList",
"name": "tags",
"in": "query",
"schema": {
"type": "string",

View File

@@ -1,7 +1,9 @@
using System;
using System.IO;
using System.Text;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.StaticFiles;
using Microsoft.Net.Http.Headers;
using NLog;
using NzbDrone.Common.Disk;
using NzbDrone.Common.EnvironmentInfo;
@@ -39,7 +41,10 @@ namespace Radarr.Http.Frontend.Mappers
contentType = "application/octet-stream";
}
return new FileStreamResult(GetContentStream(filePath), contentType);
return new FileStreamResult(GetContentStream(filePath), new MediaTypeHeaderValue(contentType)
{
Encoding = contentType == "text/plain" ? Encoding.UTF8 : null
});
}
_logger.Warn("File {0} not found", filePath);

View File

@@ -1180,10 +1180,10 @@
"@jridgewell/resolve-uri" "^3.0.3"
"@jridgewell/sourcemap-codec" "^1.4.10"
"@microsoft/signalr@6.0.8":
version "6.0.8"
resolved "https://registry.yarnpkg.com/@microsoft/signalr/-/signalr-6.0.8.tgz#e55b4488b352c580c08bab381110cdfe42d4e53c"
integrity sha512-TgvNf8opondnX6nqN2AvWThOMl+CjPwxonhAbBpmLveECcnTuBibJQdiCUA4iwjBz26k2HIiiJ25DYgqXIJVQw==
"@microsoft/signalr@6.0.16":
version "6.0.16"
resolved "https://registry.yarnpkg.com/@microsoft/signalr/-/signalr-6.0.16.tgz#d36498a9b16bf11c0e9213d77d24c0ad8ebffa47"
integrity sha512-wekzRtt2Ti38Ja0OQwLE0EKN0Zm7RI9VilrungwHe5Eej1IwnRYuhpauAqNtwwP3CY2j7uFT4XUk74E2vythTQ==
dependencies:
abort-controller "^3.0.0"
eventsource "^1.0.7"