1
0
mirror of https://github.com/Radarr/Radarr.git synced 2026-03-29 18:15:37 -04:00

Compare commits

...

23 Commits

Author SHA1 Message Date
Weblate
e72f8097fb Translated using Weblate (Spanish) [skip ci]
Currently translated at 97.8% (1120 of 1145 strings)

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

Currently translated at 22.4% (257 of 1145 strings)

Translated using Weblate (Catalan) [skip ci]

Currently translated at 100.0% (1145 of 1145 strings)

Translated using Weblate (Chinese (Traditional) (zh_TW)) [skip ci]

Currently translated at 0.8% (10 of 1145 strings)

Translated using Weblate (Hungarian) [skip ci]

Currently translated at 100.0% (1145 of 1145 strings)

Translated using Weblate (Catalan) [skip ci]

Currently translated at 100.0% (1145 of 1145 strings)

Translated using Weblate (Catalan) [skip ci]

Currently translated at 0.1% (1 of 1145 strings)

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

Currently translated at 100.0% (1145 of 1145 strings)

Translated using Weblate (Polish) [skip ci]

Currently translated at 99.9% (1144 of 1145 strings)

Translated using Weblate (Finnish) [skip ci]

Currently translated at 100.0% (1145 of 1145 strings)

Translated using Weblate (Chinese (Simplified) (zh_CN)) [skip ci]

Currently translated at 100.0% (1144 of 1144 strings)

Translated using Weblate (French) [skip ci]

Currently translated at 98.3% (1125 of 1144 strings)

Translated using Weblate (Hungarian) [skip ci]

Currently translated at 100.0% (1144 of 1144 strings)

Co-authored-by: Anonymous <noreply@weblate.org>
Co-authored-by: Csaba <csab0825@gmail.com>
Co-authored-by: Havok Dan <havokdan@yahoo.com.br>
Co-authored-by: M0C <pigers@gmail.com>
Co-authored-by: Michael Maldonado <michael@maldonado.tech>
Co-authored-by: Oskari Lavinto <olavinto@protonmail.com>
Co-authored-by: Sytha <tharaud.sylvain@gmail.com>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: beefnoodle <acer.wang@protonmail.com>
Co-authored-by: dtalens <databio@gmail.com>
Co-authored-by: libsu <libsu@qq.com>
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/ca/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/es/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/fi/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/fr/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/hu/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/nb_NO/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/pl/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/pt_BR/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/zh_CN/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/zh_TW/
Translation: Servarr/Radarr
2022-08-13 13:49:13 -05:00
Qstick
3eec088306 Regenerate yarn.lock 2022-08-13 13:31:46 -05:00
Qstick
ad097dd1a2 Bump Sentry to 3.20.1 2022-08-13 12:55:49 -05:00
Qstick
b4b38a5318 Bump dotnet to 6.0.8 2022-08-13 12:40:52 -05:00
psylenced
b0717a0803 Changed: Removed Tigole from ExceptionRelease match as is checked in ExceptionReleaseExact. 2022-08-13 12:21:35 -05:00
psylenced
4d1d08d345 Fixed: Tigole release group not being parsed and matched correctly, requiring manual import. 2022-08-13 12:21:35 -05:00
psylenced
e689817508 Fixed: Configured recycle bin is excluded from import. 2022-08-13 12:03:03 -05:00
Qstick
3b191caf16 Really fix Original Language in Language CF Specification
Co-Authored-By: François-Xavier Payet <fx.payet@tfdn.org>
2022-08-13 12:02:10 -05:00
Qstick
cc6ca0b067 Better Sentry Filtering for AggregateException children 2022-08-12 23:33:27 -05:00
Qstick
57cb63fb18 Run Postgres tests on 20.04 2022-08-12 23:32:58 -05:00
Qstick
20f709d22a Fixed: Blank Collection on MovieDetails when no Collection for Movie 2022-08-12 22:55:42 -05:00
Qstick
5d8775ac96 Remove non-functional filters for Trakt Lists
Fixes #7464
2022-08-12 22:42:38 -05:00
Qstick
4890972e16 Fixed: Original CF shouldn't need to be named "Original"
Fixes #7473
2022-08-12 22:31:41 -05:00
Qstick
40dc808f61 Fixed NullRef in Skyhook Proxy during List Sync 2022-08-12 22:19:24 -05:00
bakerboy448
97077e09d2 Fixed: Remove Notifiarr Environment Option 2022-08-09 20:23:26 -05:00
Chris
9ba7027d00 Fixed: Trakt list request now uses correct rules for generating slug (#7449)
* Changed: Parser.ToUrlSlug now has optional parameters to define how it works in edge cases based on provider.

* Fixed: Trakt list request now uses correct rules for generating slug on site.

* Added: Unit tests for slug parser.

* Fixed: Null and blank parameters to ToSlugUrl parser. Added tests.
2022-08-07 22:18:06 -05:00
Qstick
9903e70925 Fixed: Allow blank ReleaseGroup and Edition from MovieFile edit
Fixes #7453
2022-08-07 22:05:27 -05:00
Qstick
3a6f3666f5 Fixed: Don't process files that don't have a supported media file extension
Co-Authored-By: Mark McDowall <markus101@users.noreply.github.com>
2022-08-07 21:54:39 -05:00
Qstick
915c66be50 Fixed: Avoid failure if list contains same movie but without tmdbid
Fixes #7454
2022-08-07 21:47:46 -05:00
javaisbetterthanpython
70b22e483a Fixed: Log correct path when moving movies (#7439)
Fixes #7440
2022-07-25 18:17:52 -05:00
Deathspike
cad1191da5 Fixed: Watch state not preserved on metadata rewrite (#7436) 2022-07-23 12:17:26 -05:00
Qstick
43910af127 Fixed: NullRefException in TorrentRssParser
From 6c494e9a92
2022-07-21 20:11:45 -05:00
Qstick
f01c477b81 Bump Version to 4.2.1 2022-07-21 15:31:32 -04:00
35 changed files with 1522 additions and 1138 deletions

View File

@@ -1,7 +1,6 @@
{
"paths": [
"frontend/src/**/*.js",
"src/NzbDrone.Core/Localization/Core/*.json"
"frontend/src/**/*.js"
],
"ignored": [
"**/node_modules/**/*"

View File

@@ -9,13 +9,13 @@ variables:
testsFolder: './_tests'
yarnCacheFolder: $(Pipeline.Workspace)/.yarn
nugetCacheFolder: $(Pipeline.Workspace)/.nuget/packages
majorVersion: '4.2.0'
majorVersion: '4.2.1'
minorVersion: $[counter('minorVersion', 2000)]
radarrVersion: '$(majorVersion).$(minorVersion)'
buildName: '$(Build.SourceBranchName).$(radarrVersion)'
sentryOrg: 'servarr'
sentryUrl: 'https://sentry.servarr.com'
dotnetVersion: '6.0.300'
dotnetVersion: '6.0.400'
nodeVersion: '16.X'
innoVersion: '6.2.0'
windowsImage: 'windows-2022'
@@ -549,7 +549,7 @@ stages:
Radarr__Postgres__Password: 'radarr'
pool:
vmImage: 'ubuntu-18.04'
vmImage: ${{ variables.linuxImage }}
timeoutInMinutes: 10
@@ -687,7 +687,7 @@ stages:
Radarr__Postgres__Password: 'radarr'
pool:
vmImage: 'ubuntu-18.04'
vmImage: ${{ variables.linuxImage }}
steps:
- task: UseDotNet@2

View File

@@ -165,11 +165,11 @@ export const actionHandlers = handleThunks({
requestData.quality = quality;
}
if (releaseGroup) {
if (releaseGroup !== undefined) {
requestData.releaseGroup = releaseGroup;
}
if (edition) {
if (edition !== undefined) {
requestData.edition = edition;
}
@@ -201,11 +201,11 @@ export const actionHandlers = handleThunks({
props.quality = quality;
}
if (edition) {
if (edition !== undefined) {
props.edition = edition;
}
if (releaseGroup) {
if (releaseGroup !== undefined) {
props.releaseGroup = releaseGroup;
}

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.5",
"@microsoft/signalr": "6.0.8",
"@sentry/browser": "6.18.2",
"@sentry/integrations": "6.18.2",
"classnames": "2.3.1",

View File

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

View File

@@ -20,7 +20,21 @@ namespace NzbDrone.Common.Test.InstrumentationTests
private static Exception[] FilteredExceptions = new Exception[]
{
new UnauthorizedAccessException()
new UnauthorizedAccessException(),
new AggregateException(new Exception[]
{
new UnauthorizedAccessException(),
new UnauthorizedAccessException()
})
};
private static Exception[] NonFilteredExceptions = new Exception[]
{
new AggregateException(new Exception[]
{
new UnauthorizedAccessException(),
new NotImplementedException()
})
};
[SetUp]
@@ -63,6 +77,14 @@ namespace NzbDrone.Common.Test.InstrumentationTests
_subject.IsSentryMessage(log).Should().BeFalse();
}
[Test]
[TestCaseSource("NonFilteredExceptions")]
public void should_not_filter_event_for_filtered_exception_types(Exception ex)
{
var log = GivenLogEvent(LogLevel.Error, ex, "test");
_subject.IsSentryMessage(log).Should().BeTrue();
}
[Test]
[TestCaseSource("FilteredExceptions")]
public void should_not_filter_event_for_filtered_exception_types_if_filtering_disabled(Exception ex)

View File

@@ -229,21 +229,48 @@ namespace NzbDrone.Common.Instrumentation.Sentry
{
if (FilterEvents)
{
var sqlEx = logEvent.Exception as SQLiteException;
if (sqlEx != null && FilteredSQLiteErrors.Contains(sqlEx.ResultCode))
var exceptions = new List<Exception>();
var aggEx = logEvent.Exception as AggregateException;
if (aggEx != null && aggEx.InnerExceptions.Count > 0)
{
return false;
exceptions.AddRange(aggEx.InnerExceptions);
}
else
{
exceptions.Add(logEvent.Exception);
}
if (FilteredExceptionTypeNames.Contains(logEvent.Exception.GetType().Name))
// If any are sentry then send to sentry
foreach (var ex in exceptions)
{
return false;
var isSentry = true;
var sqlEx = ex as SQLiteException;
if (sqlEx != null && !FilteredSQLiteErrors.Contains(sqlEx.ResultCode))
{
isSentry = false;
}
if (FilteredExceptionTypeNames.Contains(ex.GetType().Name))
{
isSentry = false;
}
if (FilteredExceptionMessages.Any(x => ex.Message.Contains(x)))
{
isSentry = false;
}
if (isSentry)
{
return true;
}
}
if (FilteredExceptionMessages.Any(x => logEvent.Exception.Message.Contains(x)))
{
return false;
}
// The exception or aggregate exception children were not sentry exceptions
return false;
}
return true;

View File

@@ -10,10 +10,10 @@
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="NLog" Version="5.0.1" />
<PackageReference Include="NLog.Extensions.Logging" Version="5.0.0" />
<PackageReference Include="Sentry" Version="3.15.0" />
<PackageReference Include="Sentry" Version="3.20.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.4" />
<PackageReference Include="System.Text.Json" Version="6.0.5" />
<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" />

View File

@@ -103,6 +103,7 @@ namespace NzbDrone.Core.Test.ParserTests
[TestCase("Movie Title (2022) (2160p ATV WEB-DL Hybrid H265 DV HDR DDP Atmos 5.1 English - HONE)", "HONE")]
[TestCase("Movie Title (2009) (2160p PMTP WEB-DL Hybrid H265 DV HDR10+ DDP Atmos 5.1 English - HONE)", "HONE")]
[TestCase("Why.Cant.You.Use.Normal.Characters.2021.2160p.UHD.HDR10+.BluRay.TrueHD.Atmos.7.1.x265-ZØNEHD", "ZØNEHD")]
[TestCase("Movie.Should.Not.Use.Dots.2022.1080p.BluRay.x265.10bit.Tigole", "Tigole")]
public void should_parse_exception_release_group(string title, string expected)
{
Parser.Parser.ParseReleaseGroup(title).Should().Be(expected);

View File

@@ -0,0 +1,161 @@
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.ParserTests
{
[TestFixture]
public class SlugParserFixture : CoreTest
{
[TestCase("tèst", "test")]
[TestCase("têst", "test")]
[TestCase("tëst", "test")]
[TestCase("tËst", "test")]
[TestCase("áccent", "accent")]
[TestCase("àccent", "accent")]
[TestCase("âccent", "accent")]
[TestCase("Äccent", "accent")]
[TestCase("åccent", "accent")]
[TestCase("acceñt", "accent")]
[TestCase("ßtest", "test")]
[TestCase("œtest", "test")]
[TestCase("Œtest", "test")]
[TestCase("Øtest", "test")]
public void should_replace_accents(string input, string result)
{
Parser.Parser.ToUrlSlug(input).Should().Be(result);
}
[TestCase("Test'Result")]
[TestCase("Test$Result")]
[TestCase("Test(Result")]
[TestCase("Test)Result")]
[TestCase("Test*Result")]
[TestCase("Test?Result")]
[TestCase("Test/Result")]
[TestCase("Test=Result")]
[TestCase("Test\\Result")]
public void should_replace_special_characters(string input)
{
Parser.Parser.ToUrlSlug(input).Should().Be("testresult");
}
[TestCase("ThIS IS A MiXeD CaSe SensItIvE ValUe")]
public void should_lowercase_capitals(string input)
{
Parser.Parser.ToUrlSlug(input).Should().Be("this-is-a-mixed-case-sensitive-value");
}
[TestCase("test----")]
[TestCase("test____")]
[TestCase("test-_--_")]
public void should_trim_trailing_dashes_and_underscores(string input)
{
Parser.Parser.ToUrlSlug(input).Should().Be("test");
}
[TestCase("test result")]
[TestCase("test result")]
public void should_replace_spaces_with_dash(string input)
{
Parser.Parser.ToUrlSlug(input).Should().Be("test-result");
}
[TestCase("test result", "test-result")]
[TestCase("test-----result", "test-result")]
[TestCase("test_____result", "test_result")]
public void should_replace_double_occurence(string input, string result)
{
Parser.Parser.ToUrlSlug(input).Should().Be(result);
}
[TestCase("Test'Result")]
[TestCase("Test$Result")]
[TestCase("Test(Result")]
[TestCase("Test)Result")]
[TestCase("Test*Result")]
[TestCase("Test?Result")]
[TestCase("Test/Result")]
[TestCase("Test=Result")]
[TestCase("Test\\Result")]
public void should_replace_special_characters_with_dash_when_enabled(string input)
{
Parser.Parser.ToUrlSlug(input, true).Should().Be("test-result");
}
[TestCase("Test'Result")]
[TestCase("Test$Result")]
[TestCase("Test(Result")]
[TestCase("Test)Result")]
[TestCase("Test*Result")]
[TestCase("Test?Result")]
[TestCase("Test/Result")]
[TestCase("Test=Result")]
[TestCase("Test\\Result")]
public void should__not_replace_special_characters_with_dash_when_disabled(string input)
{
Parser.Parser.ToUrlSlug(input, false).Should().Be("testresult");
}
[TestCase("test----", "-_", "test")]
[TestCase("test____", "-_", "test")]
[TestCase("test-_-_", "-_", "test")]
[TestCase("test----", "-", "test")]
[TestCase("test____", "-", "test____")]
[TestCase("test-_-_", "-", "test-_-_")]
[TestCase("test----", "_", "test----")]
[TestCase("test____", "_", "test")]
[TestCase("test-_-_", "_", "test-_-")]
[TestCase("test----", "", "test----")]
[TestCase("test____", "", "test____")]
[TestCase("test-_-_", "", "test-_-_")]
public void should_trim_trailing_dashes_and_underscores_based_on_list(string input, string trimList, string result)
{
Parser.Parser.ToUrlSlug(input, false, trimList, "").Should().Be(result);
}
[TestCase("test----result", "-_", "test-result")]
[TestCase("test____result", "-_", "test_result")]
[TestCase("test_-_-result", "-_", "test-result")]
[TestCase("test-_-_result", "-_", "test_result")]
[TestCase("test----result", "-", "test-result")]
[TestCase("test____result", "-", "test____result")]
[TestCase("test-_-_result", "-", "test-_-_result")]
[TestCase("test----result", "_", "test----result")]
[TestCase("test____result", "_", "test_result")]
[TestCase("test-_-_result", "_", "test-_-_result")]
[TestCase("test----result", "", "test----result")]
[TestCase("test____result", "", "test____result")]
[TestCase("test-_-_result", "", "test-_-_result")]
public void should_replace_duplicate_characters_based_on_list(string input, string deduplicateChars, string result)
{
Parser.Parser.ToUrlSlug(input, false, "", deduplicateChars).Should().Be(result);
}
[Test]
public void should_handle_null_trim_parameters()
{
Parser.Parser.ToUrlSlug("test", false, null, "-_").Should().Be("test");
}
[Test]
public void should_handle_null_dedupe_parameters()
{
Parser.Parser.ToUrlSlug("test", false, "-_", null).Should().Be("test");
}
[Test]
public void should_handle_empty_trim_parameters()
{
Parser.Parser.ToUrlSlug("test", false, "", "-_").Should().Be("test");
}
[Test]
public void should_handle_empty_dedupe_parameters()
{
Parser.Parser.ToUrlSlug("test", false, "-_", "").Should().Be("test");
}
}
}

View File

@@ -8,6 +8,7 @@ using Moq;
using NUnit.Framework;
using NzbDrone.Common.Disk;
using NzbDrone.Common.EnvironmentInfo;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.Movies;
using NzbDrone.Core.RootFolders;
using NzbDrone.Core.Test.Framework;
@@ -151,5 +152,107 @@ namespace NzbDrone.Core.Test.RootFolderTests
unmappedFolders.Count.Should().BeGreaterThan(0);
unmappedFolders.Should().NotContain(u => u.Name == subFolder);
}
[TestCase("")]
[TestCase(null)]
public void should_handle_non_configured_recycle_bin(string recycleBinPath)
{
var rootFolder = Builder<RootFolder>.CreateNew()
.With(r => r.Path = @"C:\Test\TV")
.Build();
if (OsInfo.IsNotWindows)
{
rootFolder = Builder<RootFolder>.CreateNew()
.With(r => r.Path = @"/Test/TV")
.Build();
}
var subFolders = new[]
{
"Series1",
"Series2",
"Series3"
};
var folders = subFolders.Select(f => Path.Combine(@"C:\Test\TV", f)).ToArray();
if (OsInfo.IsNotWindows)
{
folders = subFolders.Select(f => Path.Combine(@"/Test/TV", f)).ToArray();
}
Mocker.GetMock<IConfigService>()
.Setup(s => s.RecycleBin)
.Returns(recycleBinPath);
Mocker.GetMock<IRootFolderRepository>()
.Setup(s => s.Get(It.IsAny<int>()))
.Returns(rootFolder);
Mocker.GetMock<IMovieRepository>()
.Setup(s => s.AllMoviePaths())
.Returns(new Dictionary<int, string>());
Mocker.GetMock<IDiskProvider>()
.Setup(s => s.GetDirectories(rootFolder.Path))
.Returns(folders);
var unmappedFolders = Subject.Get(rootFolder.Id, true).UnmappedFolders;
unmappedFolders.Count.Should().Be(3);
}
[Test]
public void should_exclude_recycle_bin()
{
var rootFolder = Builder<RootFolder>.CreateNew()
.With(r => r.Path = @"C:\Test\TV")
.Build();
if (OsInfo.IsNotWindows)
{
rootFolder = Builder<RootFolder>.CreateNew()
.With(r => r.Path = @"/Test/TV")
.Build();
}
var subFolders = new[]
{
"Series1",
"Series2",
"Series3",
"BIN"
};
var folders = subFolders.Select(f => Path.Combine(@"C:\Test\TV", f)).ToArray();
if (OsInfo.IsNotWindows)
{
folders = subFolders.Select(f => Path.Combine(@"/Test/TV", f)).ToArray();
}
var recycleFolder = Path.Combine(OsInfo.IsNotWindows ? @"/Test/TV" : @"C:\Test\TV", "BIN");
Mocker.GetMock<IConfigService>()
.Setup(s => s.RecycleBin)
.Returns(recycleFolder);
Mocker.GetMock<IRootFolderRepository>()
.Setup(s => s.Get(It.IsAny<int>()))
.Returns(rootFolder);
Mocker.GetMock<IMovieRepository>()
.Setup(s => s.AllMoviePaths())
.Returns(new Dictionary<int, string>());
Mocker.GetMock<IDiskProvider>()
.Setup(s => s.GetDirectories(rootFolder.Path))
.Returns(folders);
var unmappedFolders = Subject.Get(rootFolder.Id, true).UnmappedFolders;
unmappedFolders.Count.Should().Be(3);
unmappedFolders.Should().NotContain(u => u.Name == "BIN");
}
}
}

View File

@@ -34,7 +34,7 @@ namespace NzbDrone.Core.CustomFormats
protected override bool IsSatisfiedByWithoutNegate(ParsedMovieInfo movieInfo)
{
var comparedLanguage = movieInfo != null && Name == "Original" && movieInfo.ExtraInfo.ContainsKey("OriginalLanguage")
var comparedLanguage = movieInfo != null && Value == Language.Original.Id && movieInfo.ExtraInfo.ContainsKey("OriginalLanguage")
? (Language)movieInfo.ExtraInfo["OriginalLanguage"]
: (Language)Value;
return movieInfo?.Languages?.Contains(comparedLanguage) ?? false;

View File

@@ -305,6 +305,8 @@ namespace NzbDrone.Core.Extras.Metadata.Consumers.Xbmc
details.Add(new XElement("trailer", "plugin://plugin.video.youtube/play/?video_id=" + movie.MovieMetadata.Value.YouTubeTrailerId));
details.Add(new XElement("watched", watched));
if (movieFile.MediaInfo != null)
{
var sceneName = movieFile.GetSceneOrFileName();

View File

@@ -167,6 +167,7 @@ namespace NzbDrone.Core.ImportLists
{
var mappedMovies = reports.Select(m => _movieSearch.MapMovieToTmdbMovie(new MovieMetadata { Title = m.Title, TmdbId = m.TmdbId, ImdbId = m.ImdbId, Year = m.Year }))
.Where(x => x != null)
.DistinctBy(x => x.TmdbId)
.ToList();
_movieMetadataService.UpsertMany(mappedMovies);

View File

@@ -27,7 +27,13 @@ namespace NzbDrone.Core.ImportLists.Trakt.List
{
var link = string.Empty;
var listName = Parser.Parser.ToUrlSlug(Settings.Listname.Trim());
// Trakt slug rules:
// - replace all special characters with a dash
// - replaces multiple dashes with a single dash
// - allows underscore as a valid character
// - does not trim underscore from the end
// - allows multiple underscores in a row
var listName = Parser.Parser.ToUrlSlug(Settings.Listname.Trim(), true, "-", "-");
link += $"users/{Settings.Username.Trim()}/lists/{listName}/items/movies?limit={Settings.Limit}";
var request = new ImportListRequest(_traktProxy.BuildTraktRequest(link, HttpMethod.Get, Settings.AccessToken));

View File

@@ -1,4 +1,6 @@
using System.Text.RegularExpressions;
using FluentValidation;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.Annotations;
namespace NzbDrone.Core.ImportLists.Trakt.Popular
@@ -9,6 +11,24 @@ namespace NzbDrone.Core.ImportLists.Trakt.Popular
: base()
{
RuleFor(c => c.TraktListType).NotNull();
// Loose validation @TODO
RuleFor(c => c.Rating)
.Matches(@"^\d+\-\d+$", RegexOptions.IgnoreCase)
.When(c => c.Rating.IsNotNullOrWhiteSpace())
.WithMessage("Not a valid rating");
// Any valid certification
RuleFor(c => c.Certification)
.Matches(@"^\bNR\b|\bG\b|\bPG\b|\bPG\-13\b|\bR\b|\bNC\-17\b$", RegexOptions.IgnoreCase)
.When(c => c.Certification.IsNotNullOrWhiteSpace())
.WithMessage("Not a valid cerification");
// Loose validation @TODO
RuleFor(c => c.Years)
.Matches(@"^\d+(\-\d+)?$", RegexOptions.IgnoreCase)
.When(c => c.Years.IsNotNullOrWhiteSpace())
.WithMessage("Not a valid year or range of years");
}
}
@@ -23,5 +43,17 @@ namespace NzbDrone.Core.ImportLists.Trakt.Popular
[FieldDefinition(1, Label = "List Type", Type = FieldType.Select, SelectOptions = typeof(TraktPopularListType), HelpText = "Type of list you're seeking to import from")]
public int TraktListType { get; set; }
[FieldDefinition(2, Label = "Rating", HelpText = "Filter movies by rating range (0-100)")]
public string Rating { get; set; }
[FieldDefinition(3, Label = "Certification", HelpText = "Filter movies by a certification (NR,G,PG,PG-13,R,NC-17), (Comma Separated)")]
public string Certification { get; set; }
[FieldDefinition(4, Label = "Genres", HelpText = "Filter movies by Trakt Genre Slug (Comma Separated) Only for Popular Lists")]
public string Genres { get; set; }
[FieldDefinition(5, Label = "Years", HelpText = "Filter movies by year or year range")]
public string Years { get; set; }
}
}

View File

@@ -1,5 +1,4 @@
using System;
using System.Text.RegularExpressions;
using FluentValidation;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.Annotations;
@@ -29,24 +28,6 @@ namespace NzbDrone.Core.ImportLists.Trakt
.WithMessage("Must authenticate with Trakt")
.When(c => c.AccessToken.IsNotNullOrWhiteSpace() && c.RefreshToken.IsNotNullOrWhiteSpace());
// Loose validation @TODO
RuleFor(c => c.Rating)
.Matches(@"^\d+\-\d+$", RegexOptions.IgnoreCase)
.When(c => c.Rating.IsNotNullOrWhiteSpace())
.WithMessage("Not a valid rating");
// Any valid certification
RuleFor(c => c.Certification)
.Matches(@"^\bNR\b|\bG\b|\bPG\b|\bPG\-13\b|\bR\b|\bNC\-17\b$", RegexOptions.IgnoreCase)
.When(c => c.Certification.IsNotNullOrWhiteSpace())
.WithMessage("Not a valid cerification");
// Loose validation @TODO
RuleFor(c => c.Years)
.Matches(@"^\d+(\-\d+)?$", RegexOptions.IgnoreCase)
.When(c => c.Years.IsNotNullOrWhiteSpace())
.WithMessage("Not a valid year or range of years");
// Limit not smaller than 1 and not larger than 100
RuleFor(c => c.Limit)
.GreaterThan(0)
@@ -62,10 +43,6 @@ namespace NzbDrone.Core.ImportLists.Trakt
public TraktSettingsBase()
{
SignIn = "startOAuth";
Rating = "0-100";
Certification = "NR,G,PG,PG-13,R,NC-17";
Genres = "";
Years = "";
Limit = 100;
}
@@ -84,18 +61,6 @@ namespace NzbDrone.Core.ImportLists.Trakt
[FieldDefinition(0, Label = "Auth User", Type = FieldType.Textbox, Hidden = HiddenType.Hidden)]
public string AuthUser { get; set; }
[FieldDefinition(1, Label = "Rating", HelpText = "Filter movies by rating range (0-100)")]
public string Rating { get; set; }
[FieldDefinition(2, Label = "Certification", HelpText = "Filter movies by a certification (NR,G,PG,PG-13,R,NC-17), (Comma Separated)")]
public string Certification { get; set; }
[FieldDefinition(3, Label = "Genres", HelpText = "Filter movies by Trakt Genre Slug (Comma Separated) Only for Popular Lists")]
public string Genres { get; set; }
[FieldDefinition(4, Label = "Years", HelpText = "Filter movies by year or year range")]
public string Years { get; set; }
[FieldDefinition(5, Label = "Limit", HelpText = "Limit the number of movies to get")]
public int Limit { get; set; }

View File

@@ -73,7 +73,7 @@ namespace NzbDrone.Core.Indexers
{
if (InfoHashElementName.IsNotNullOrWhiteSpace())
{
return item.FindDecendants(InfoHashElementName).FirstOrDefault().Value;
return item.FindDecendants(InfoHashElementName).FirstOrDefault()?.Value;
}
var magnetUrl = GetMagnetUrl(item);
@@ -96,7 +96,7 @@ namespace NzbDrone.Core.Indexers
{
if (MagnetElementName.IsNotNullOrWhiteSpace())
{
var magnetURL = item.FindDecendants(MagnetElementName).FirstOrDefault().Value;
var magnetURL = item.FindDecendants(MagnetElementName).FirstOrDefault()?.Value;
if (magnetURL.IsNotNullOrWhiteSpace() && magnetURL.StartsWith("magnet:"))
{
return magnetURL;

View File

@@ -166,7 +166,7 @@
"ShowCinemaRelease": "Mostra la data d'estrena",
"StandardMovieFormat": "Format de pel·lícula estàndard",
"Started": "Començat",
"StartSearchForMissingMovie": "Comenceu a cercar la pel·lícula absent",
"StartSearchForMissingMovie": "Comenceu a cercar per pel·lícula absent",
"TableOptionsColumnsMessage": "Trieu quines columnes són visibles i en quin ordre apareixen",
"CollectionOptions": "Opcions de col·leccions",
"CollectionShowPostersHelpText": "Mostra cartells d'articles de la col·lecció",
@@ -335,7 +335,7 @@
"Week": "Setmana",
"WeekColumnHeader": "Capçalera de la columna de la setmana",
"Weeks": "Setmanes",
"WhatsNew": "Novetats",
"WhatsNew": "Que hi ha de nou?",
"MovieIsUnmonitored": "La pel·lícula no està monitorada",
"MovieNaming": "Denominació de pel·lícules",
"Backup": "Còpia de seguretat",
@@ -584,12 +584,12 @@
"IndexerJackettAll": "Indexadors que utilitzen el punt final \"tot\" no compatible amb Jackett: {0}",
"IndexerLongTermStatusCheckAllClientMessage": "Tots els indexadors no estan disponibles a causa d'errors durant més de 6 hores",
"IndexerLongTermStatusCheckSingleClientMessage": "Els indexadors no estan disponibles a causa d'errors durant més de 6 hores: {0}",
"IndexerPriorityHelpText": "Prioritat de l'indexador d'1 (la més alta) a 50 (la més baixa). Per defecte: 25. S'utilitza quan s'agafa llançaments com a desempat per a versions iguals, Radarr encara utilitzarà tots els indexadors habilitats per a la sincronització i la cerca RSS.",
"IndexerPriorityHelpText": "Prioritat de l'indexador d'1 (la més alta) a 50 (la més baixa). Per defecte: 25. S'utilitza quan s'agafa llançaments com a desempat per a versions iguals, Radarr encara utilitzarà tots els indexadors habilitats per a la sincronització i la cerca RSS",
"IndexerRssHealthCheckNoAvailableIndexers": "Tots els indexadors compatibles amb rss no estan disponibles temporalment a causa d'errors recents de l'indexador",
"IndexerRssHealthCheckNoIndexers": "No hi ha indexadors disponibles amb la sincronització RSS activada, Radarr no capturarà les noves versions automàticament",
"IndexerSearchCheckNoAutomaticMessage": "No hi ha indexadors disponibles amb la cerca automàtica activada, Radarr no proporcionarà cap resultat de cerca automàtica",
"IndexerSearchCheckNoAvailableIndexersMessage": "Tots els indexadors amb capacitat de cerca no estan disponibles temporalment a causa d'errors recents de l'indexador",
"IndexerSearchCheckNoInteractiveMessage": "No hi ha indexadors disponibles amb la cerca interactiva activada, Radarr no proporcionarà cap resultat de cerca interactiva",
"IndexerSearchCheckNoInteractiveMessage": "No hi ha indexadors amb la cerca interactiva activada, Radarr no obtindrà cap resultat de cerca",
"IndexerSettings": "Configuració de l'indexador",
"IndexersSettingsSummary": "Indexadors i restriccions de llançament",
"IndexerStatusCheckAllClientMessage": "Tots els indexadors no estan disponibles a causa d'errors",
@@ -715,7 +715,7 @@
"OrganizeConfirm": "Esteu segur que voleu organitzar tots els fitxers de les {0} pel·lícules seleccionades?",
"OrganizeModalAllPathsRelative": "Tots els camins són relatius a:",
"OrganizeModalDisabled": "El canvi de nom està desactivat, no hi ha res per canviar el nom",
"OrganizeModalNamingPattern": "Patró de nom",
"OrganizeModalNamingPattern": "Patró de reanomenat:",
"OrganizeModalSuccess": "Èxit! La feina està acabada, no hi ha fitxers per canviar el nom.",
"OrganizeSelectedMovies": "Organitza les pel·lícules seleccionades",
"Original": "Original",
@@ -838,7 +838,7 @@
"RequiredRestrictionHelpText": "El llançament ha de contenir almenys un d'aquests termes (no distingeix entre majúscules i minúscules)",
"RequiredRestrictionPlaceHolder": "Afegeix una nova restricció",
"RescanAfterRefreshHelpText": "Torneu a escanejar la carpeta de la pel·lícula després d'actualitzar la pel·lícula",
"RescanAfterRefreshHelpTextWarning": "Radarr no detectarà automàticament els canvis als fitxers quan no estigui configurat com a \"Sempre\".",
"RescanAfterRefreshHelpTextWarning": "Radarr no detectarà automàticament els canvis als fitxers quan no estigui configurat com a \"Sempre\"",
"RescanMovieFolderAfterRefresh": "Torna a escanejar la carpeta de pel·lícules després de l'actualització",
"Reset": "Restableix",
"ResetAPIKey": "Restableix la clau de l'API",

View File

@@ -1119,5 +1119,6 @@
"ChooseImportMode": "Elegir Modo de Importación",
"CollectionOptions": "Opciones de la Colección",
"CollectionShowDetailsHelpText": "Mostrar el estado y propiedades de la colección",
"CollectionShowOverviewsHelpText": "Mostrar resumenes de la colección"
"CollectionShowOverviewsHelpText": "Mostrar resumenes de la colección",
"CollectionShowPostersHelpText": "Mostrar póster de artículos de colección"
}

View File

@@ -1142,5 +1142,6 @@
"OnMovieAddedHelpText": "Film hozzáadásakor",
"ShowPosters": "Poszterek megjelenítése",
"InstanceNameHelpText": "Példánynév a böngésző lapon és a syslog alkalmazás neve",
"RottenTomatoesRating": "Tomato Értékelés"
"RottenTomatoesRating": "Tomato Értékelés",
"TotalMovies": "Összes film"
}

View File

@@ -254,5 +254,6 @@
"Language": "språk",
"List": "Liste",
"New": "Ny",
"RemotePathMappings": "Ekstern portmapping"
"RemotePathMappings": "Ekstern portmapping",
"Languages": "språk"
}

View File

@@ -1,7 +1,14 @@
{
"About": "關於",
"Add": "添加",
"Add": "新增",
"AcceptConfirmationModal": "接受確認模式",
"Actions": "‎行動‎",
"Activity": "‎活動‎"
"Actions": "執行",
"Activity": "‎活動‎",
"AddIndexer": "新增索引",
"AddingTag": "新增標籤",
"AddDownloadClient": "新增下載器",
"Added": "以新增",
"Age": "年齡",
"All": "全部",
"Analytics": "分析"
}

View File

@@ -5,6 +5,7 @@ using System.Linq;
using NLog;
using NzbDrone.Common.Disk;
using NzbDrone.Common.EnvironmentInfo;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.DecisionEngine;
using NzbDrone.Core.Download;
@@ -260,6 +261,20 @@ namespace NzbDrone.Core.MediaFiles
};
}
var extension = Path.GetExtension(fileInfo.Name);
if (extension.IsNullOrWhiteSpace() || !MediaFileExtensions.Extensions.Contains(extension))
{
_logger.Debug("[{0}] has an unsupported extension: '{1}'", fileInfo.FullName, extension);
return new List<ImportResult>
{
new ImportResult(new ImportDecision(new LocalMovie { Path = fileInfo.FullName },
new Rejection($"Invalid video file, unsupported extension: '{extension}'")),
$"Invalid video file, unsupported extension: '{extension}'")
};
}
if (downloadClientItem == null)
{
if (_diskProvider.IsFileLocked(fileInfo.FullName))

View File

@@ -344,7 +344,16 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
yearStr = $" {movie.Year}";
}
newMovie = SearchForNewMovie(movie.Title + yearStr).FirstOrDefault()?.MovieMetadata ?? null;
var newMovieObject = SearchForNewMovie(movie.Title + yearStr).FirstOrDefault();
if (newMovieObject == null)
{
newMovie = null;
}
else
{
newMovie = newMovieObject.MovieMetadata;
}
}
if (newMovie == null)

View File

@@ -56,7 +56,7 @@ namespace NzbDrone.Core.Movies
_diskProvider.CreateFolder(new DirectoryInfo(destinationPath).Parent.FullName);
_diskTransferService.TransferFolder(sourcePath, destinationPath, TransferMode.Move);
_logger.ProgressInfo("{0} moved successfully to {1}", movie.Title, movie.Path);
_logger.ProgressInfo("{0} moved successfully to {1}", movie.Title, destinationPath);
_eventAggregator.PublishEvent(new MovieMovedEvent(movie, sourcePath, destinationPath));
}

View File

@@ -1,8 +0,0 @@
namespace NzbDrone.Core.Notifications.Notifiarr
{
public enum NotifiarrEnvironment
{
Live,
Development
}
}

View File

@@ -79,7 +79,7 @@ namespace NzbDrone.Core.Notifications.Notifiarr
{
try
{
var url = settings.Environment == (int)NotifiarrEnvironment.Development ? "https://dev.notifiarr.com" : "https://notifiarr.com";
var url = "https://notifiarr.com";
var requestBuilder = new HttpRequestBuilder(url + "/api/v1/notification/radarr/" + settings.APIKey).Post();
requestBuilder.AddFormParameter("instanceName", settings.InstanceName).Build();

View File

@@ -21,8 +21,6 @@ namespace NzbDrone.Core.Notifications.Notifiarr
public string APIKey { get; set; }
[FieldDefinition(1, Label = "Instance Name", Advanced = true, HelpText = "Unique name for this instance", HelpLink = "https://notifiarr.com")]
public string InstanceName { get; set; }
[FieldDefinition(2, Label = "Environment", Advanced = true, Type = FieldType.Select, SelectOptions = typeof(NotifiarrEnvironment), HelpText = "Live unless told otherwise", HelpLink = "https://notifiarr.com")]
public int Environment { get; set; }
public NzbDroneValidationResult Validate()
{

View File

@@ -147,11 +147,11 @@ namespace NzbDrone.Core.Parser
//Handle Exception Release Groups that don't follow -RlsGrp; Manual List
//groups whose releases end with RlsGroup) or RlsGroup]
private static readonly Regex ExceptionReleaseGroupRegex = new Regex(@"(?<releasegroup>(Tigole|Joy|YIFY|YTS.MX|YTS.LT|FreetheFish|afm72|Anna|Bandi|Ghost|Kappa|MONOLITH|Qman|RZeroX|SAMPA|Silence|theincognito|t3nzin|Vyndros|HDO|DusIctv|DHD|SEV|CtrlHD|-ZR-|ADC|XZVN|RH|Kametsu|r00t|HONE)(?=\]|\)))", RegexOptions.IgnoreCase | RegexOptions.Compiled);
private static readonly Regex ExceptionReleaseGroupRegex = new Regex(@"(?<releasegroup>(Joy|YIFY|YTS.MX|YTS.LT|FreetheFish|afm72|Anna|Bandi|Ghost|Kappa|MONOLITH|Qman|RZeroX|SAMPA|Silence|theincognito|t3nzin|Vyndros|HDO|DusIctv|DHD|SEV|CtrlHD|-ZR-|ADC|XZVN|RH|Kametsu|r00t|HONE)(?=\]|\)))", RegexOptions.IgnoreCase | RegexOptions.Compiled);
//Handle Exception Release Groups that don't follow -RlsGrp; Manual List
// name only...BE VERY CAREFUL WITH THIS, HIGH CHANCE OF FALSE POSITIVES
private static readonly Regex ExceptionReleaseGroupRegexExact = new Regex(@"(?<releasegroup>KRaLiMaRKo|E\.N\.D|D\-Z0N3|Koten_Gars|BluDragon|ZØNEHD)", RegexOptions.IgnoreCase | RegexOptions.Compiled);
private static readonly Regex ExceptionReleaseGroupRegexExact = new Regex(@"(?<releasegroup>KRaLiMaRKo|E\.N\.D|D\-Z0N3|Koten_Gars|BluDragon|ZØNEHD|Tigole)", RegexOptions.IgnoreCase | RegexOptions.Compiled);
private static readonly Regex WordDelimiterRegex = new Regex(@"(\s|\.|,|_|-|=|'|\|)+", RegexOptions.Compiled);
private static readonly Regex SpecialCharRegex = new Regex(@"(\&|\:|\\|\/)+", RegexOptions.Compiled);
@@ -401,7 +401,7 @@ namespace NzbDrone.Core.Parser
return null;
}
public static string ToUrlSlug(string value)
public static string ToUrlSlug(string value, bool invalidDashReplacement = false, string trimEndChars = "-_", string deduplicateChars = "-_")
{
//First to lower case
value = value.ToLowerInvariant();
@@ -412,14 +412,23 @@ namespace NzbDrone.Core.Parser
//Replace spaces
value = Regex.Replace(value, @"\s", "-", RegexOptions.Compiled);
//Should invalid characters be replaced with dash or empty string?
string replaceCharacter = invalidDashReplacement ? "-" : string.Empty;
//Remove invalid chars
value = Regex.Replace(value, @"[^a-z0-9\s-_]", "", RegexOptions.Compiled);
value = Regex.Replace(value, @"[^a-z0-9\s-_]", replaceCharacter, RegexOptions.Compiled);
//Trim dashes from end
value = value.Trim('-', '_');
//Trim dashes or underscores from end, or user defined character set
if (!string.IsNullOrEmpty(trimEndChars))
{
value = value.Trim(trimEndChars.ToCharArray());
}
//Replace double occurences of - or _
value = Regex.Replace(value, @"([-_]){2,}", "$1", RegexOptions.Compiled);
//Replace double occurrences of - or _, or user defined character set
if (!string.IsNullOrEmpty(deduplicateChars))
{
value = Regex.Replace(value, @"([" + deduplicateChars + "]){2,}", "$1", RegexOptions.Compiled);
}
return value;
}

View File

@@ -9,7 +9,7 @@
<PackageReference Include="Npgsql" Version="6.0.3" />
<PackageReference Include="Servarr.FFMpegCore" Version="4.7.0-26" />
<PackageReference Include="Servarr.FFprobe" Version="5.0.1.93" />
<PackageReference Include="System.Memory" Version="4.5.4" />
<PackageReference Include="System.Memory" Version="4.5.5" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="6.0.1" />
@@ -22,7 +22,7 @@
<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.5" />
<PackageReference Include="System.Text.Json" Version="6.0.4" />
<PackageReference Include="System.Text.Json" Version="6.0.5" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\NzbDrone.Common\Radarr.Common.csproj" />

View File

@@ -148,12 +148,18 @@ namespace NzbDrone.Core.RootFolders
var possibleMovieFolders = _diskProvider.GetDirectories(path).ToList();
var unmappedFolders = possibleMovieFolders.Except(moviePaths.Select(s => s.Value), PathEqualityComparer.Instance).ToList();
foreach (string unmappedFolder in unmappedFolders)
var recycleBinPath = _configService.RecycleBin;
foreach (var unmappedFolder in unmappedFolders)
{
var di = new DirectoryInfo(unmappedFolder.Normalize());
if ((!di.Attributes.HasFlag(FileAttributes.System) && !di.Attributes.HasFlag(FileAttributes.Hidden)) || di.Attributes.ToString() == "-1")
{
results.Add(new UnmappedFolder { Name = di.Name, Path = di.FullName });
if (string.IsNullOrWhiteSpace(recycleBinPath) || di.FullName.PathNotEquals(recycleBinPath))
{
results.Add(new UnmappedFolder { Name = di.Name, Path = di.FullName });
}
}
}

View File

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

View File

@@ -94,6 +94,8 @@ namespace Radarr.Api.V3.Movies
var translatedTitle = movieTranslation?.Title ?? model.Title;
var translatedOverview = movieTranslation?.Overview ?? model.MovieMetadata.Value.Overview;
var collection = model.MovieMetadata.Value.CollectionTmdbId > 0 ? new MovieCollection { Title = model.MovieMetadata.Value.CollectionTitle, TmdbId = model.MovieMetadata.Value.CollectionTmdbId } : null;
return new MovieResource
{
Id = model.Id,
@@ -141,7 +143,7 @@ namespace Radarr.Api.V3.Movies
MovieFile = movieFile,
YouTubeTrailerId = model.MovieMetadata.Value.YouTubeTrailerId,
Studio = model.MovieMetadata.Value.Studio,
Collection = new MovieCollection { Title = model.MovieMetadata.Value.CollectionTitle, TmdbId = model.MovieMetadata.Value.CollectionTmdbId },
Collection = collection,
Popularity = model.MovieMetadata.Value.Popularity
};
}

2096
yarn.lock

File diff suppressed because it is too large Load Diff