1
0
mirror of https://github.com/Radarr/Radarr.git synced 2026-04-18 21:35:51 -04:00

Compare commits

..

14 Commits

Author SHA1 Message Date
Qstick
5d9d3a84cc Fixed: Fix NullRef in Subtitle Service due to #4924
(cherry picked from commit 89ee7d4452ae3b476e24aede89b668a3df2344fc)
2022-08-20 23:02:49 +00:00
Weblate
a4ddae0ccc Translated using Weblate (German) [skip ci]
Currently translated at 100.0% (1145 of 1145 strings)

Translated using Weblate (Romanian) [skip ci]

Currently translated at 88.7% (1016 of 1145 strings)

Translated using Weblate (Russian) [skip ci]

Currently translated at 99.9% (1144 of 1145 strings)

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

Currently translated at 100.0% (1145 of 1145 strings)

Co-authored-by: AlexR-sf <omg.portal.supp@gmail.com>
Co-authored-by: Jessie <1355239678@qq.com>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: emanuelsipos <emanuelsipos1@gmail.com>
Co-authored-by: reloxx <reloxx@interia.pl>
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/de/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/ro/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/ru/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/zh_CN/
Translation: Servarr/Radarr
2022-08-19 21:33:34 -05:00
Servarr
d730161800 Automated API Docs update 2022-08-18 22:45:47 -05:00
Qstick
66c1af0555 New: (API) Get Collection by TmdbId 2022-08-18 22:37:15 -05:00
Chris
dca00db317 Added: Ntfy provider for notifications. (#7455)
* Added: Ntfy provider for notifications.

* Changed: Clean up of validation and fields for ntfy

* Fixed: Unused title setting, and spelling issue.
2022-08-18 20:12:06 -05:00
Chris
812e5ac5a3 Fixed: Postgres secret regex now less greedy
[common]
2022-08-18 21:36:22 +01:00
Chris
d01bae92bf Fixed: Regex in log cleanser taking 10+ minutes on messages longer than 100k. (#7481) 2022-08-18 13:00:58 +01:00
Qstick
1a6bf51741 New: Add support for Plex Edition tags in naming 2022-08-16 23:04:46 -05:00
Qstick
f3e7843150 New: Make Plex imdb tags conditional 2022-08-16 23:04:46 -05:00
Qstick
886b9b1c05 Fixed: Correctly map movie by original title on import
Fixes #7348
2022-08-15 23:16:22 -05:00
Qstick
d8891ee4ea Fixed: UI Error on Collection Filter
Fixes #7474
2022-08-14 16:33:40 -05:00
Qstick
192dd9c137 Fixed: Allow 0 Min on Size CustomFormat Condition
Fixes #7476
2022-08-14 16:19:28 -05:00
Gylesie
b549fddf95 New: Add Slovak Language 2022-08-13 16:25:32 -05:00
Qstick
c1f538ed97 Bump version to 4.2.2 2022-08-13 15:48:22 -05:00
25 changed files with 551 additions and 83 deletions

View File

@@ -9,7 +9,7 @@ variables:
testsFolder: './_tests' testsFolder: './_tests'
yarnCacheFolder: $(Pipeline.Workspace)/.yarn yarnCacheFolder: $(Pipeline.Workspace)/.yarn
nugetCacheFolder: $(Pipeline.Workspace)/.nuget/packages nugetCacheFolder: $(Pipeline.Workspace)/.nuget/packages
majorVersion: '4.2.1' majorVersion: '4.2.2'
minorVersion: $[counter('minorVersion', 2000)] minorVersion: $[counter('minorVersion', 2000)]
radarrVersion: '$(majorVersion).$(minorVersion)' radarrVersion: '$(majorVersion).$(minorVersion)'
buildName: '$(Build.SourceBranchName).$(radarrVersion)' buildName: '$(Build.SourceBranchName).$(radarrVersion)'

View File

@@ -116,7 +116,7 @@ export const filterPredicates = {
const predicate = filterTypePredicates[type]; const predicate = filterTypePredicates[type];
const { collection } = item; const { collection } = item;
return predicate(collection ? collection.name : '', filterValue); return predicate(collection ? collection.title : '', filterValue);
}, },
originalLanguage: function(item, filterValue, type) { originalLanguage: function(item, filterValue, type) {

View File

@@ -341,8 +341,8 @@ export const defaultState = {
const collectionList = items.reduce((acc, movie) => { const collectionList = items.reduce((acc, movie) => {
if (movie.collection) { if (movie.collection) {
acc.push({ acc.push({
id: movie.collection.name, id: movie.collection.title,
name: movie.collection.name name: movie.collection.title
}); });
} }

View File

@@ -18,7 +18,7 @@ namespace NzbDrone.Common.Instrumentation
new Regex(@"iptorrents\.com/[/a-z0-9?&;]*?(?:[?&;](u|tp)=(?<secret>[^&=;]+?))+(?= |;|&|$)", RegexOptions.Compiled | RegexOptions.IgnoreCase), new Regex(@"iptorrents\.com/[/a-z0-9?&;]*?(?:[?&;](u|tp)=(?<secret>[^&=;]+?))+(?= |;|&|$)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
new Regex(@"/fetch/[a-z0-9]{32}/(?<secret>[a-z0-9]{32})", RegexOptions.Compiled), new Regex(@"/fetch/[a-z0-9]{32}/(?<secret>[a-z0-9]{32})", RegexOptions.Compiled),
new Regex(@"getnzb.*?(?<=\?|&)(r)=(?<secret>[^&=]+?)(?= |&|$)", RegexOptions.Compiled | RegexOptions.IgnoreCase), new Regex(@"getnzb.*?(?<=\?|&)(r)=(?<secret>[^&=]+?)(?= |&|$)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
new Regex(@"(?<=[?& ;])[^=]*?(_?(?<!use|get_)token|username|passwo?rd)=(?<secret>[^&=]+?)(?= |&|$|;)", RegexOptions.Compiled | RegexOptions.IgnoreCase), new Regex(@"\b[^;=]*?(_?(?<!use|get_)token|username|passwo?rd)=(?<secret>[^&=]+?)(?= |&|$|;)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
// Trackers Announce Keys; Designed for Qbit Json; should work for all in theory // Trackers Announce Keys; Designed for Qbit Json; should work for all in theory
new Regex(@"announce(\.php)?(/|%2f|%3fpasskey%3d)(?<secret>[a-z0-9]{16,})|(?<secret>[a-z0-9]{16,})(/|%2f)announce"), new Regex(@"announce(\.php)?(/|%2f|%3fpasskey%3d)(?<secret>[a-z0-9]{16,})|(?<secret>[a-z0-9]{16,})(/|%2f)announce"),

View File

@@ -0,0 +1,67 @@
using System.Collections.Generic;
using System.Linq;
using FizzWare.NBuilder;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.CustomFormats;
using NzbDrone.Core.MediaFiles;
using NzbDrone.Core.Movies;
using NzbDrone.Core.Organizer;
using NzbDrone.Core.Qualities;
using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.OrganizerTests.FileNameBuilderTests
{
[TestFixture]
public class EditionTagsFixture : CoreTest<FileNameBuilder>
{
private Movie _movie;
private MovieFile _movieFile;
private NamingConfig _namingConfig;
[SetUp]
public void Setup()
{
_movie = Builder<Movie>
.CreateNew()
.With(s => s.Title = "South Park")
.Build();
_movieFile = new MovieFile { Quality = new QualityModel(), ReleaseGroup = "SonarrTest" };
_namingConfig = NamingConfig.Default;
_namingConfig.RenameMovies = true;
Mocker.GetMock<INamingConfigService>()
.Setup(c => c.GetConfig()).Returns(_namingConfig);
Mocker.GetMock<IQualityDefinitionService>()
.Setup(v => v.Get(Moq.It.IsAny<Quality>()))
.Returns<Quality>(v => Quality.DefaultQualityDefinitions.First(c => c.Quality == v));
Mocker.GetMock<ICustomFormatService>()
.Setup(v => v.All())
.Returns(new List<CustomFormat>());
}
[Test]
public void should_add_edition_tag()
{
_movieFile.Edition = "Uncut";
_namingConfig.StandardMovieFormat = "{Movie Title} [{Edition Tags}]";
Subject.BuildFileName(_movie, _movieFile)
.Should().Be("South Park [Uncut]");
}
[TestCase("{Movie Title} {edition-{Edition Tags}}")]
public void should_conditional_hide_edition_tags_in_plex_format(string movieFormat)
{
_movieFile.Edition = "";
_namingConfig.StandardMovieFormat = movieFormat;
Subject.BuildFileName(_movie, _movieFile)
.Should().Be("South Park");
}
}
}

View File

@@ -1,4 +1,4 @@
using FizzWare.NBuilder; using FizzWare.NBuilder;
using FluentAssertions; using FluentAssertions;
using NUnit.Framework; using NUnit.Framework;
using NUnit.Framework.Internal; using NUnit.Framework.Internal;
@@ -47,5 +47,25 @@ namespace NzbDrone.Core.Test.OrganizerTests.FileNameBuilderTests
Subject.GetMovieFolder(_movie) Subject.GetMovieFolder(_movie)
.Should().Be($"Movie Title ({_movie.TmdbId})"); .Should().Be($"Movie Title ({_movie.TmdbId})");
} }
[Test]
public void should_add_imdb_tag()
{
_namingConfig.MovieFolderFormat = "{Movie Title} {imdb-{ImdbId}}";
Subject.GetMovieFolder(_movie)
.Should().Be($"Movie Title {{imdb-{_movie.ImdbId}}}");
}
[Test]
public void should_skip_imdb_tag_if_null()
{
_namingConfig.MovieFolderFormat = "{Movie Title} {imdb-{ImdbId}}";
_movie.ImdbId = null;
Subject.GetMovieFolder(_movie)
.Should().Be($"Movie Title");
}
} }
} }

View File

@@ -342,6 +342,16 @@ namespace NzbDrone.Core.Test.ParserTests
result.Languages.Should().BeEquivalentTo(Language.Bengali); result.Languages.Should().BeEquivalentTo(Language.Bengali);
} }
[TestCase("Movie.Title.1994.HDTV.x264.SK-iCZi")]
[TestCase("Movie.Title.2019.1080p.HDTV.x265.iNTERNAL.SK-iCZi")]
[TestCase("Movie.Title.2018.SLOVAK.DUAL.2160p.UHD.BluRay.x265-iCZi")]
[TestCase("Movie.Title.1990.SLOVAK.HDTV.x264-iCZi")]
public void should_parse_language_slovak(string postTitle)
{
var result = Parser.Parser.ParseMovieTitle(postTitle);
result.Languages.Should().BeEquivalentTo(Language.Slovak);
}
[TestCase("Movie.Title.en.sub")] [TestCase("Movie.Title.en.sub")]
[TestCase("Movie Title.eng.sub")] [TestCase("Movie Title.eng.sub")]
[TestCase("Movie.Title.eng.forced.sub")] [TestCase("Movie.Title.eng.forced.sub")]

View File

@@ -10,7 +10,7 @@ namespace NzbDrone.Core.CustomFormats
{ {
public SizeSpecificationValidator() public SizeSpecificationValidator()
{ {
RuleFor(c => c.Min).GreaterThan(0); RuleFor(c => c.Min).GreaterThanOrEqualTo(0);
RuleFor(c => c.Max).GreaterThan(c => c.Min); RuleFor(c => c.Max).GreaterThan(c => c.Min);
} }
} }

View File

@@ -5,6 +5,11 @@ namespace NzbDrone.Core.Extras.Subtitles
{ {
public class SubtitleFile : ExtraFile public class SubtitleFile : ExtraFile
{ {
public SubtitleFile()
{
LanguageTags = new List<string>();
}
public Language Language { get; set; } public Language Language { get; set; }
} }
} }

View File

@@ -105,6 +105,7 @@ namespace NzbDrone.Core.Languages
public static Language Ukrainian => new Language(32, "Ukrainian"); public static Language Ukrainian => new Language(32, "Ukrainian");
public static Language Persian => new Language(33, "Persian"); public static Language Persian => new Language(33, "Persian");
public static Language Bengali => new Language(34, "Bengali"); public static Language Bengali => new Language(34, "Bengali");
public static Language Slovak => new Language(35, "Slovak");
public static Language Any => new Language(-1, "Any"); public static Language Any => new Language(-1, "Any");
public static Language Original => new Language(-2, "Original"); public static Language Original => new Language(-2, "Original");
@@ -149,6 +150,7 @@ namespace NzbDrone.Core.Languages
Ukrainian, Ukrainian,
Persian, Persian,
Bengali, Bengali,
Slovak,
Any, Any,
Original Original
}; };

View File

@@ -1142,5 +1142,6 @@
"UnableToLoadCollections": "Sammlungen können nicht geladen werden", "UnableToLoadCollections": "Sammlungen können nicht geladen werden",
"InstanceName": "Instanzname", "InstanceName": "Instanzname",
"InstanceNameHelpText": "Instanzname im Browser-Tab und für Syslog-Anwendungsname", "InstanceNameHelpText": "Instanzname im Browser-Tab und für Syslog-Anwendungsname",
"RottenTomatoesRating": "Tomato Bewertung" "RottenTomatoesRating": "Tomato Bewertung",
"TotalMovies": "Filme insgesamt"
} }

View File

@@ -44,7 +44,7 @@
"Activity": "Activitate", "Activity": "Activitate",
"Actions": "Acțiuni", "Actions": "Acțiuni",
"About": "Despre", "About": "Despre",
"IndexerStatusCheckAllClientMessage": "Niciun indexator nu este disponibil datorită eșuărilor", "IndexerStatusCheckAllClientMessage": "Niciun indexator nu este disponibil datorită erorilor",
"IndexersSettingsSummary": "Restricții pentru indexatori și apariții", "IndexersSettingsSummary": "Restricții pentru indexatori și apariții",
"IndexerSearchCheckNoInteractiveMessage": "Niciun indexator cu Căutare interactivă nu este activ, Radarr nu va afișa niciun rezultat de căutare interactivă", "IndexerSearchCheckNoInteractiveMessage": "Niciun indexator cu Căutare interactivă nu este activ, Radarr nu va afișa niciun rezultat de căutare interactivă",
"IndexerSearchCheckNoAvailableIndexersMessage": "Toți indexatorii ce suportă căutare sunt indisponibili temporar datorită erorilor", "IndexerSearchCheckNoAvailableIndexersMessage": "Toți indexatorii ce suportă căutare sunt indisponibili temporar datorită erorilor",
@@ -62,11 +62,11 @@
"Ignored": "Ignorat", "Ignored": "Ignorat",
"iCalLink": "Legătură iCal", "iCalLink": "Legătură iCal",
"Host": "Gazdă", "Host": "Gazdă",
"History": "Istorie", "History": "Istoric",
"HideAdvanced": "Ascunde Avansat", "HideAdvanced": "Ascunde Avansat",
"Health": "Sănătate", "Health": "Sănătate",
"GrabSelected": "Prinderea selectată", "GrabSelected": "Prinderea selectată",
"Grabbed": "Prins", "Grabbed": "În curs de descărcare",
"Genres": "Genuri", "Genres": "Genuri",
"GeneralSettingsSummary": "Port, SSL, utilizator/parolă, proxy, statistici și actualizări", "GeneralSettingsSummary": "Port, SSL, utilizator/parolă, proxy, statistici și actualizări",
"General": "General", "General": "General",
@@ -76,7 +76,7 @@
"Folder": "Dosar", "Folder": "Dosar",
"Filter": "Filtru", "Filter": "Filtru",
"Files": "Fișiere", "Files": "Fișiere",
"Filename": "Numele Fișierului", "Filename": "Numele fișierului",
"FileManagement": "Administrarea de fișiere", "FileManagement": "Administrarea de fișiere",
"FailedDownloadHandling": "Procesarea descărcării a eșuat", "FailedDownloadHandling": "Procesarea descărcării a eșuat",
"Failed": "Eșuat", "Failed": "Eșuat",
@@ -84,7 +84,7 @@
"Events": "Evenimente", "Events": "Evenimente",
"Edit": "Editează", "Edit": "Editează",
"Downloaded": "Descărcat", "Downloaded": "Descărcat",
"DownloadClientStatusCheckSingleClientMessage": "Clienții de descărcare sunt indisponibili datorită erorii: {0}", "DownloadClientStatusCheckSingleClientMessage": "Clienții de descărcare sunt indisponibili datorită erorilor: {0}",
"DownloadClientStatusCheckAllClientMessage": "Toți clienții de descărcare sunt indisponibili datorită erorilor", "DownloadClientStatusCheckAllClientMessage": "Toți clienții de descărcare sunt indisponibili datorită erorilor",
"ProfilesSettingsSummary": "Calitate, Limbă și Profile de Întârziere", "ProfilesSettingsSummary": "Calitate, Limbă și Profile de Întârziere",
"Profiles": "Profile", "Profiles": "Profile",
@@ -143,9 +143,9 @@
"Language": "Limbă", "Language": "Limbă",
"KeyboardShortcuts": "Scurtături din tastatură", "KeyboardShortcuts": "Scurtături din tastatură",
"Info": "Info", "Info": "Info",
"IndexerStatusCheckSingleClientMessage": "Indexator indisponibil datorită erorilor: {0}", "IndexerStatusCheckSingleClientMessage": "Indexatoare indisponibile datorită erorilor: {0}",
"ImportExistingMovies": "Importă Filme Existente", "ImportExistingMovies": "Importă Filme Existente",
"HealthNoIssues": "Nicio problemă în configurare", "HealthNoIssues": "Nicio problemă de configurare",
"HardlinkCopyFiles": "Hardlink/Copiază Fișiere", "HardlinkCopyFiles": "Hardlink/Copiază Fișiere",
"Extension": "Extensie", "Extension": "Extensie",
"Error": "Eroare", "Error": "Eroare",
@@ -168,7 +168,7 @@
"QualityProfile": "Profil de Calitate", "QualityProfile": "Profil de Calitate",
"QualityDefinitions": "Definiții de calitate", "QualityDefinitions": "Definiții de calitate",
"Quality": "Calitate", "Quality": "Calitate",
"PtpOldSettingsCheckMessage": "Următorul indexer PassThePopcorn are setări depreciate și ar trebui actualizate: {0}", "PtpOldSettingsCheckMessage": "Următoarele indexatoare PassThePopcorn au setări depreciate și ar trebui actualizate: {0}",
"ProxyCheckResolveIpMessage": "Nu am putut găsi adresa IP pentru Hostul Proxy Configurat {0}", "ProxyCheckResolveIpMessage": "Nu am putut găsi adresa IP pentru Hostul Proxy Configurat {0}",
"ProxyCheckFailedToTestMessage": "Nu am putut testa proxy: {0}", "ProxyCheckFailedToTestMessage": "Nu am putut testa proxy: {0}",
"ProxyCheckBadRequestMessage": "Testul proxy a eșuat. StatusCode: {0}", "ProxyCheckBadRequestMessage": "Testul proxy a eșuat. StatusCode: {0}",
@@ -260,7 +260,7 @@
"Queue": "Coadă", "Queue": "Coadă",
"QualitySettingsSummary": "Calitate - mărimi și denumiri", "QualitySettingsSummary": "Calitate - mărimi și denumiri",
"AutoRedownloadFailedHelpText": "Căutați automat și încercați să descărcați o versiune diferită", "AutoRedownloadFailedHelpText": "Căutați automat și încercați să descărcați o versiune diferită",
"BackupIntervalHelpText": "Interval între copiile de rezervă automate", "BackupIntervalHelpText": "Interval între crearea copiile de siguranță automate",
"ApplyTagsHelpTexts1": "Cum se aplică etichete filmelor selectate", "ApplyTagsHelpTexts1": "Cum se aplică etichete filmelor selectate",
"CustomFormatUnknownCondition": "Stare necunoscută pentru formatul personalizat „{0}”", "CustomFormatUnknownCondition": "Stare necunoscută pentru formatul personalizat „{0}”",
"QualitySettings": "Setări de calitate", "QualitySettings": "Setări de calitate",
@@ -337,7 +337,7 @@
"ThisCannotBeCancelled": "Acest lucru nu poate fi anulat odată pornit fără a reporni Radarr.", "ThisCannotBeCancelled": "Acest lucru nu poate fi anulat odată pornit fără a reporni Radarr.",
"TorrentDelayHelpText": "Întârziați în câteva minute pentru a aștepta înainte de a apuca un torent", "TorrentDelayHelpText": "Întârziați în câteva minute pentru a aștepta înainte de a apuca un torent",
"Trigger": "Declanșator", "Trigger": "Declanșator",
"UnableToAddANewIndexerPleaseTryAgain": "Imposibil de adăugat un nou indexer, încercați din nou.", "UnableToAddANewIndexerPleaseTryAgain": "Nu se poate adăuga un nou indexator, vă rugăm să încercați din nou.",
"UnableToAddANewNotificationPleaseTryAgain": "Imposibil de adăugat o nouă notificare, încercați din nou.", "UnableToAddANewNotificationPleaseTryAgain": "Imposibil de adăugat o nouă notificare, încercați din nou.",
"UnableToAddANewRemotePathMappingPleaseTryAgain": "Imposibil de adăugat o nouă mapare a căilor la distanță, încercați din nou.", "UnableToAddANewRemotePathMappingPleaseTryAgain": "Imposibil de adăugat o nouă mapare a căilor la distanță, încercați din nou.",
"UnableToImportCheckLogs": "Descărcat - Imposibil de importat: verificați jurnalele pentru detalii", "UnableToImportCheckLogs": "Descărcat - Imposibil de importat: verificați jurnalele pentru detalii",
@@ -369,7 +369,7 @@
"Importing": "Importând", "Importing": "Importând",
"AcceptConfirmationModal": "Acceptați Modul de confirmare", "AcceptConfirmationModal": "Acceptați Modul de confirmare",
"LastExecution": "Ultima executare", "LastExecution": "Ultima executare",
"DBMigration": "Migrarea DB", "DBMigration": "Migrarea BD",
"Manual": "Manual", "Manual": "Manual",
"OnHealthIssue": "Cu privire la problema sănătății", "OnHealthIssue": "Cu privire la problema sănătății",
"OnImport": "La import", "OnImport": "La import",
@@ -388,8 +388,8 @@
"AvailabilityDelayHelpText": "Suma de timp înainte sau după data disponibilă pentru căutarea filmului", "AvailabilityDelayHelpText": "Suma de timp înainte sau după data disponibilă pentru căutarea filmului",
"Announced": "Anunțat", "Announced": "Anunțat",
"AddRemotePathMapping": "Adăugați maparea căilor la distanță", "AddRemotePathMapping": "Adăugați maparea căilor la distanță",
"BackupRetentionHelpText": "Copiile de rezervă automate mai vechi de perioada de păstrare vor fi curățate automat", "BackupRetentionHelpText": "Copiile de siguranță automate mai vechi decât perioada de păstrare vor fi curățate automat",
"Backups": "Copii de rezervă", "Backups": "Copii de siguranță",
"BeforeUpdate": "Înainte de actualizare", "BeforeUpdate": "Înainte de actualizare",
"BindAddress": "Adresa de legare", "BindAddress": "Adresa de legare",
"CancelProcessing": "Anulați procesarea", "CancelProcessing": "Anulați procesarea",
@@ -404,7 +404,7 @@
"DeleteMovieFolderLabel": "Ștergeți dosarul filmului", "DeleteMovieFolderLabel": "Ștergeți dosarul filmului",
"DockerUpdater": "actualizați containerul de andocare pentru a primi actualizarea", "DockerUpdater": "actualizați containerul de andocare pentru a primi actualizarea",
"EditGroups": "Editați grupurile", "EditGroups": "Editați grupurile",
"EditIndexer": "Editați Indexer", "EditIndexer": "Editați indexator",
"Enabled": "Activat", "Enabled": "Activat",
"ExcludeMovie": "Excludeți filmul", "ExcludeMovie": "Excludeți filmul",
"ExcludeTitle": "Excludeți {0}? Acest lucru îl va împiedica pe Radarr să adauge automat prin sincronizarea listei.", "ExcludeTitle": "Excludeți {0}? Acest lucru îl va împiedica pe Radarr să adauge automat prin sincronizarea listei.",
@@ -413,7 +413,7 @@
"HttpHttps": "HTTP (S)", "HttpHttps": "HTTP (S)",
"ICalFeed": "Feed iCal", "ICalFeed": "Feed iCal",
"ICalHttpUrlHelpText": "Copiați această adresă URL către clienții dvs. sau faceți clic pentru a vă abona dacă browserul dvs. acceptă webcal", "ICalHttpUrlHelpText": "Copiați această adresă URL către clienții dvs. sau faceți clic pentru a vă abona dacă browserul dvs. acceptă webcal",
"Add": "Adăuga", "Add": "Adaugă",
"AddCustomFormat": "Adăugați format personalizat", "AddCustomFormat": "Adăugați format personalizat",
"AddDelayProfile": "Adăugați un profil de întârziere", "AddDelayProfile": "Adăugați un profil de întârziere",
"AddDownloadClient": "Adăugați client de descărcare", "AddDownloadClient": "Adăugați client de descărcare",
@@ -440,7 +440,7 @@
"ChmodFolderHelpTextWarning": "Acest lucru funcționează numai dacă utilizatorul care rulează Radarr este proprietarul fișierului. Este mai bine să vă asigurați că clientul de descărcare setează corect permisiunile.", "ChmodFolderHelpTextWarning": "Acest lucru funcționează numai dacă utilizatorul care rulează Radarr este proprietarul fișierului. Este mai bine să vă asigurați că clientul de descărcare setează corect permisiunile.",
"ChmodGroup": "chmod Group", "ChmodGroup": "chmod Group",
"ChmodGroupHelpText": "Numele grupului sau gid. Utilizați gid pentru sistemele de fișiere la distanță.", "ChmodGroupHelpText": "Numele grupului sau gid. Utilizați gid pentru sistemele de fișiere la distanță.",
"DeleteBackup": "Ștergeți Backup", "DeleteBackup": "Ștergeți copie de siguranță",
"DeleteCustomFormat": "Ștergeți formatul personalizat", "DeleteCustomFormat": "Ștergeți formatul personalizat",
"DeletedMsg": "Filmul a fost șters din TMDb", "DeletedMsg": "Filmul a fost șters din TMDb",
"DeleteDownloadClient": "Ștergeți clientul de descărcare", "DeleteDownloadClient": "Ștergeți clientul de descărcare",
@@ -448,12 +448,12 @@
"Connection": "Conexiuni", "Connection": "Conexiuni",
"CantFindMovie": "De ce nu-mi găsesc filmul?", "CantFindMovie": "De ce nu-mi găsesc filmul?",
"CertificateValidationHelpText": "Modificați cât de strictă este validarea certificării HTTPS", "CertificateValidationHelpText": "Modificați cât de strictă este validarea certificării HTTPS",
"AddIndexer": "Adăugați Indexer", "AddIndexer": "Adăugați Indexator",
"AutomaticSearch": "Căutare automată", "AutomaticSearch": "Căutare automată",
"ClientPriority": "Prioritatea clientului", "ClientPriority": "Prioritatea clientului",
"CertificationCountry": "Țara certificării", "CertificationCountry": "Țara certificării",
"CertificationCountryHelpText": "Selectați Țara pentru certificări de film", "CertificationCountryHelpText": "Selectați Țara pentru certificări de film",
"HomePage": "Pagina principala", "HomePage": "Pagina principală",
"IncludeHealthWarningsHelpText": "Includeți avertismente de sănătate", "IncludeHealthWarningsHelpText": "Includeți avertismente de sănătate",
"InvalidFormat": "Format invalid", "InvalidFormat": "Format invalid",
"LastDuration": "lastDuration", "LastDuration": "lastDuration",
@@ -508,7 +508,7 @@
"ShowGenres": "Afișați genurile", "ShowGenres": "Afișați genurile",
"SuggestTranslationChange": "Sugerează modificarea traducerii", "SuggestTranslationChange": "Sugerează modificarea traducerii",
"TestAllClients": "Testați toți clienții", "TestAllClients": "Testați toți clienții",
"TestAllIndexers": "Testați toți indexatorii", "TestAllIndexers": "Testați toate indexatoarele",
"TestAllLists": "Testați toate listele", "TestAllLists": "Testați toate listele",
"Queued": "În așteptare", "Queued": "În așteptare",
"TMDb": "TMDb", "TMDb": "TMDb",
@@ -524,8 +524,8 @@
"DetailedProgressBarHelpText": "Afișați textul pe bara de progres", "DetailedProgressBarHelpText": "Afișați textul pe bara de progres",
"EnableSSL": "Activați SSL", "EnableSSL": "Activați SSL",
"IncludeCustomFormatWhenRenaming": "Includeți format personalizat la redenumire", "IncludeCustomFormatWhenRenaming": "Includeți format personalizat la redenumire",
"IndexerLongTermStatusCheckAllClientMessage": "Toți indexatorii nu sunt disponibili din cauza unor eșecuri de mai mult de 6 ore", "IndexerLongTermStatusCheckAllClientMessage": "Toți indexatorii sunt indisponibili datorită erorilor de mai mult de 6 ore",
"IndexerLongTermStatusCheckSingleClientMessage": "Indexatori indisponibili din cauza unor eșecuri de mai mult de 6 ore: {0}", "IndexerLongTermStatusCheckSingleClientMessage": "Indexatori indisponibili datorită erorilor de mai mult de 6 ore: {0}",
"LoadingMovieCreditsFailed": "Încărcarea creditelor filmului nu a reușit", "LoadingMovieCreditsFailed": "Încărcarea creditelor filmului nu a reușit",
"LoadingMovieExtraFilesFailed": "Încărcarea fișierelor suplimentare ale filmului nu a reușit", "LoadingMovieExtraFilesFailed": "Încărcarea fișierelor suplimentare ale filmului nu a reușit",
"LoadingMovieFilesFailed": "Încărcarea fișierelor film a eșuat", "LoadingMovieFilesFailed": "Încărcarea fișierelor film a eșuat",
@@ -559,7 +559,7 @@
"CleanLibraryLevel": "Nivel de bibliotecă curat", "CleanLibraryLevel": "Nivel de bibliotecă curat",
"BranchUpdate": "Sucursală de utilizat pentru actualizarea Radarr", "BranchUpdate": "Sucursală de utilizat pentru actualizarea Radarr",
"BranchUpdateMechanism": "Ramură utilizată de mecanismul extern de actualizare", "BranchUpdateMechanism": "Ramură utilizată de mecanismul extern de actualizare",
"BypassProxyForLocalAddresses": "Bypass Proxy pentru adrese locale", "BypassProxyForLocalAddresses": "Nu folosiți Proxy pentru adrese locale",
"MovieTitleHelpText": "Titlul filmului de exclus (poate avea orice sens)", "MovieTitleHelpText": "Titlul filmului de exclus (poate avea orice sens)",
"Local": "Local", "Local": "Local",
"MovieYear": "Anul filmului", "MovieYear": "Anul filmului",
@@ -641,7 +641,7 @@
"ClickToChangeQuality": "Faceți clic pentru a schimba calitatea", "ClickToChangeQuality": "Faceți clic pentru a schimba calitatea",
"CloneFormatTag": "Etichetă de format clonare", "CloneFormatTag": "Etichetă de format clonare",
"CloneIndexer": "Clonă Indexer", "CloneIndexer": "Clonă Indexer",
"CloneProfile": "Profil de clonare", "CloneProfile": "Clonați profil",
"CloseCurrentModal": "Închideți modul curent", "CloseCurrentModal": "Închideți modul curent",
"ColonReplacement": "Înlocuirea colonului", "ColonReplacement": "Înlocuirea colonului",
"ColonReplacementFormatHelpText": "Schimbați modul în care Radarr gestionează înlocuirea colonului", "ColonReplacementFormatHelpText": "Schimbați modul în care Radarr gestionează înlocuirea colonului",
@@ -666,7 +666,7 @@
"DefaultDelayProfile": "Acesta este profilul implicit. Se aplică tuturor filmelor care nu au un profil explicit.", "DefaultDelayProfile": "Acesta este profilul implicit. Se aplică tuturor filmelor care nu au un profil explicit.",
"DelayingDownloadUntilInterp": "Întârzierea descărcării până la {0} la {1}", "DelayingDownloadUntilInterp": "Întârzierea descărcării până la {0} la {1}",
"DelayProfile": "Profile de întârziere", "DelayProfile": "Profile de întârziere",
"DeleteBackupMessageText": "Sigur doriți să ștergeți copia de rezervă „{0}”?", "DeleteBackupMessageText": "Sigur doriți să ștergeți copia de siguranță „{0}”?",
"DeleteDelayProfile": "Ștergeți profilul de întârziere", "DeleteDelayProfile": "Ștergeți profilul de întârziere",
"DeleteDownloadClientMessageText": "Sigur doriți să ștergeți clientul de descărcare „{0}”?", "DeleteDownloadClientMessageText": "Sigur doriți să ștergeți clientul de descărcare „{0}”?",
"DeleteEmptyFolders": "Ștergeți folderele goale", "DeleteEmptyFolders": "Ștergeți folderele goale",
@@ -686,13 +686,13 @@
"DestinationPath": "Calea de destinație", "DestinationPath": "Calea de destinație",
"DestinationRelativePath": "Calea relativă a destinației", "DestinationRelativePath": "Calea relativă a destinației",
"DetailedProgressBar": "Bara de progres detaliată", "DetailedProgressBar": "Bara de progres detaliată",
"Discord": "Discordie", "Discord": "Discord",
"Docker": "Docher", "Docker": "Docker",
"Donations": "Donații", "Donations": "Donații",
"DoneEditingGroups": "Efectuat editarea grupurilor", "DoneEditingGroups": "Efectuat editarea grupurilor",
"DoNotPrefer": "Nu preferați", "DoNotPrefer": "Nu preferați",
"DoNotUpgradeAutomatically": "Nu faceți upgrade automat", "DoNotUpgradeAutomatically": "Nu faceți upgrade automat",
"DownloadClientSettings": "Descărcați setările clientului", "DownloadClientSettings": "Setări client de descărcare",
"DownloadClientUnavailable": "Clientul de descărcare nu este disponibil", "DownloadClientUnavailable": "Clientul de descărcare nu este disponibil",
"DownloadedAndMonitored": "Descărcat (monitorizat)", "DownloadedAndMonitored": "Descărcat (monitorizat)",
"DownloadedButNotMonitored": "Descărcat (fără monitorizare)", "DownloadedButNotMonitored": "Descărcat (fără monitorizare)",
@@ -708,10 +708,10 @@
"EditPerson": "Editați persoana", "EditPerson": "Editați persoana",
"EditQualityProfile": "Editați profilul de calitate", "EditQualityProfile": "Editați profilul de calitate",
"EditRestriction": "Editați restricția", "EditRestriction": "Editați restricția",
"Enable": "Permite", "Enable": "Activați",
"EnableAutoHelpText": "Dacă este activată, Filme vor fi adăugate automat la Radarr din această listă", "EnableAutoHelpText": "Dacă este activată, Filme vor fi adăugate automat la Radarr din această listă",
"EnableAutomaticAdd": "Activați adăugarea automată", "EnableAutomaticAdd": "Activați adăugarea automată",
"EnableAutomaticSearch": "Activați Căutarea automată", "EnableAutomaticSearch": "Activați căutarea automată",
"EnableAutomaticSearchHelpText": "Va fi utilizat atunci când căutările automate sunt efectuate prin interfața de utilizare sau de către Radarr", "EnableAutomaticSearchHelpText": "Va fi utilizat atunci când căutările automate sunt efectuate prin interfața de utilizare sau de către Radarr",
"EnableColorImpairedMode": "Activați modul afectat de culoare", "EnableColorImpairedMode": "Activați modul afectat de culoare",
"EnableColorImpairedModeHelpText": "Stil modificat pentru a permite utilizatorilor cu deficiențe de culoare să distingă mai bine informațiile codificate prin culoare", "EnableColorImpairedModeHelpText": "Stil modificat pentru a permite utilizatorilor cu deficiențe de culoare să distingă mai bine informațiile codificate prin culoare",
@@ -722,7 +722,7 @@
"EnableMediaInfoHelpText": "Extrageți informații video, cum ar fi rezoluția, runtime și informații despre codec din fișiere. Acest lucru necesită ca Radarr să citească părți ale fișierului care pot provoca activitate ridicată pe disc sau rețea în timpul scanărilor.", "EnableMediaInfoHelpText": "Extrageți informații video, cum ar fi rezoluția, runtime și informații despre codec din fișiere. Acest lucru necesită ca Radarr să citească părți ale fișierului care pot provoca activitate ridicată pe disc sau rețea în timpul scanărilor.",
"EnableRSS": "Activați RSS", "EnableRSS": "Activați RSS",
"EnableSslHelpText": " Necesită repornirea în funcție de administrator pentru a intra în vigoare", "EnableSslHelpText": " Necesită repornirea în funcție de administrator pentru a intra în vigoare",
"Ended": "Încheiat", "Ended": "Finalizat",
"ErrorLoadingContents": "Eroare la încărcarea conținutului", "ErrorLoadingContents": "Eroare la încărcarea conținutului",
"ErrorLoadingPreviews": "Eroare la încărcarea previzualizărilor", "ErrorLoadingPreviews": "Eroare la încărcarea previzualizărilor",
"ErrorRestoringBackup": "Eroare la restaurarea copiei de rezervă", "ErrorRestoringBackup": "Eroare la restaurarea copiei de rezervă",
@@ -751,7 +751,7 @@
"FollowPerson": "Urmărește persoana", "FollowPerson": "Urmărește persoana",
"ForMoreInformationOnTheIndividualDownloadClients": "Pentru mai multe informații despre clienții individuali de descărcare, faceți clic pe butoanele de informații.", "ForMoreInformationOnTheIndividualDownloadClients": "Pentru mai multe informații despre clienții individuali de descărcare, faceți clic pe butoanele de informații.",
"ForMoreInformationOnTheIndividualIndexers": "Pentru mai multe informații despre indexatorii individuali, faceți clic pe butoanele de informații.", "ForMoreInformationOnTheIndividualIndexers": "Pentru mai multe informații despre indexatorii individuali, faceți clic pe butoanele de informații.",
"GeneralSettings": "setari generale", "GeneralSettings": "Setări generale",
"Global": "Global", "Global": "Global",
"GoToInterp": "Accesați {0}", "GoToInterp": "Accesați {0}",
"Grab": "Apuca", "Grab": "Apuca",
@@ -776,7 +776,7 @@
"IncludeRecommendationsHelpText": "Includeți filmele recomandate de Radarr în vizualizarea descoperire", "IncludeRecommendationsHelpText": "Includeți filmele recomandate de Radarr în vizualizarea descoperire",
"IncludeUnmonitored": "Includeți Unmonitored", "IncludeUnmonitored": "Includeți Unmonitored",
"ImportMovies": "Importați filme", "ImportMovies": "Importați filme",
"IndexerPriority": "Prioritatea indexerului", "IndexerPriority": "Prioritatea indexatorului",
"IndexerPriorityHelpText": "Prioritatea indexerului de la 1 (cea mai mare) la 50 (cea mai mică). Implicit: 25.", "IndexerPriorityHelpText": "Prioritatea indexerului de la 1 (cea mai mare) la 50 (cea mai mică). Implicit: 25.",
"IndexerSettings": "Setări Indexer", "IndexerSettings": "Setări Indexer",
"InstallLatest": "Instalați cele mai recente", "InstallLatest": "Instalați cele mai recente",
@@ -875,7 +875,7 @@
"Retention": "Retenţie", "Retention": "Retenţie",
"RetentionHelpText": "Numai Usenet: Setați la zero pentru a seta pentru păstrarea nelimitată", "RetentionHelpText": "Numai Usenet: Setați la zero pentru a seta pentru păstrarea nelimitată",
"RSS": "RSS", "RSS": "RSS",
"RSSIsNotSupportedWithThisIndexer": "RSS nu este acceptat cu acest indexer", "RSSIsNotSupportedWithThisIndexer": "RSS nu este suportat de acest indexator",
"RSSSyncInterval": "Interval de sincronizare RSS", "RSSSyncInterval": "Interval de sincronizare RSS",
"RSSSyncIntervalHelpTextWarning": "Acest lucru se va aplica tuturor indexatorilor, vă rugăm să urmați regulile stabilite de aceștia", "RSSSyncIntervalHelpTextWarning": "Acest lucru se va aplica tuturor indexatorilor, vă rugăm să urmați regulile stabilite de aceștia",
"SaveSettings": "Salvează setările", "SaveSettings": "Salvează setările",
@@ -974,7 +974,7 @@
"UnableToLoadGeneralSettings": "Nu se pot încărca setările generale", "UnableToLoadGeneralSettings": "Nu se pot încărca setările generale",
"UnableToLoadHistory": "Istoricul nu poate fi încărcat", "UnableToLoadHistory": "Istoricul nu poate fi încărcat",
"UnableToLoadIndexerOptions": "Nu se pot încărca opțiunile indexerului", "UnableToLoadIndexerOptions": "Nu se pot încărca opțiunile indexerului",
"UnableToLoadIndexers": "Imposibil de încărcat indexatori", "UnableToLoadIndexers": "Nu se pot încărca indexatoarele",
"UnableToLoadLanguages": "Nu se pot încărca limbile", "UnableToLoadLanguages": "Nu se pot încărca limbile",
"UnableToLoadListExclusions": "Imposibil de încărcat excluderile din listă", "UnableToLoadListExclusions": "Imposibil de încărcat excluderile din listă",
"UnableToLoadManualImportItems": "Imposibil de încărcat articole de import manual", "UnableToLoadManualImportItems": "Imposibil de încărcat articole de import manual",
@@ -1052,7 +1052,7 @@
"Blocklisted": "Listă Neagră", "Blocklisted": "Listă Neagră",
"AreYouSureYouWantToRemoveSelectedItemFromQueue": "Sigur doriți să eliminați {0} elementul {1} din coadă?", "AreYouSureYouWantToRemoveSelectedItemFromQueue": "Sigur doriți să eliminați {0} elementul {1} din coadă?",
"BlocklistReleases": "Lansare pe lista neagră", "BlocklistReleases": "Lansare pe lista neagră",
"Filters": "Filtru", "Filters": "Filtre",
"List": "Liste", "List": "Liste",
"LocalPath": "Calea locală", "LocalPath": "Calea locală",
"RemotePath": "Calea la distanță", "RemotePath": "Calea la distanță",

View File

@@ -170,7 +170,7 @@
"ExcludeTitle": "Исключить {0}? Radarr не будет автоматически добавлять сканируя лист.", "ExcludeTitle": "Исключить {0}? Radarr не будет автоматически добавлять сканируя лист.",
"InCinemasMsg": "Фильмы в кинотеатрах", "InCinemasMsg": "Фильмы в кинотеатрах",
"IncludeRecommendationsHelpText": "Включить в отображении найденного фильмы рекомендованные Radar", "IncludeRecommendationsHelpText": "Включить в отображении найденного фильмы рекомендованные Radar",
"IndexerPriorityHelpText": "Приоритет индексаторов от 1 (наивысший) до 50 (низший). По-умолчанию: 25.", "IndexerPriorityHelpText": "Приоритет индексатора от 1 (самый высокий) до 50 (самый низкий). По умолчанию: 25. Используется при захвате выпусков в качестве средства разрешения конфликтов для равных в остальном выпусков, Radarr по-прежнему будет использовать все включенные индексаторы для синхронизации и поиска RSS.",
"IndexerSearchCheckNoAvailableIndexersMessage": "Все индексаторы с возможностью поиска временно выключены из-за ошибок", "IndexerSearchCheckNoAvailableIndexersMessage": "Все индексаторы с возможностью поиска временно выключены из-за ошибок",
"KeyboardShortcuts": "Горячие клавиши", "KeyboardShortcuts": "Горячие клавиши",
"CantFindMovie": "Почему я не могу найти фильм?", "CantFindMovie": "Почему я не могу найти фильм?",
@@ -244,7 +244,7 @@
"ApplyTagsHelpTexts2": "Добавить: добавить ярлыки к существующему списку", "ApplyTagsHelpTexts2": "Добавить: добавить ярлыки к существующему списку",
"AptUpdater": "Используйте apt для установки обновления", "AptUpdater": "Используйте apt для установки обновления",
"AuthForm": "Формы (Страница авторизации)", "AuthForm": "Формы (Страница авторизации)",
"AreYouSureYouWantToRemoveSelectedItemsFromQueue": "Вы уверены, что хотите удалить {0} элемент{1} из очереди?", "AreYouSureYouWantToRemoveSelectedItemsFromQueue": "Вы уверены, что хотите удалить {0} элемент из очереди?",
"BeforeUpdate": "До обновления", "BeforeUpdate": "До обновления",
"BuiltIn": "Встроено", "BuiltIn": "Встроено",
"CalendarOptions": "Настройки календаря", "CalendarOptions": "Настройки календаря",
@@ -742,12 +742,12 @@
"ChmodFolderHelpText": "Восьмеричный, применяется при импорте / переименовании к медиа-папкам и файлам (без битов выполнения)", "ChmodFolderHelpText": "Восьмеричный, применяется при импорте / переименовании к медиа-папкам и файлам (без битов выполнения)",
"CheckDownloadClientForDetails": "проверьте клиент загрузки для более подробной информации", "CheckDownloadClientForDetails": "проверьте клиент загрузки для более подробной информации",
"CertValidationNoLocal": "Отключено для локальных адресов", "CertValidationNoLocal": "Отключено для локальных адресов",
"CertificateValidationHelpText": "Изменить строгое подтверждение сертификации НТТР", "CertificateValidationHelpText": "Измените строгую проверку сертификации HTTPS. Не меняйте, если вы не понимаете риски.",
"BypassProxyForLocalAddresses": "Обход прокси для локальных адресов", "BypassProxyForLocalAddresses": "Обход прокси для локальных адресов",
"BranchUpdateMechanism": "Ветвь, используемая внешним механизмом обновления", "BranchUpdateMechanism": "Ветвь, используемая внешним механизмом обновления",
"BranchUpdate": "Ветвь для обновления Radarr", "BranchUpdate": "Ветвь для обновления Radarr",
"Branch": "Ветка", "Branch": "Ветка",
"BindAddressHelpText": "Действительный IP4-адрес или '*' для всех интерфейсов", "BindAddressHelpText": "Действительный IPv4-адрес или '*' для всех интерфейсов",
"BackupFolderHelpText": "Относительные пути будут в каталоге AppData Radarr", "BackupFolderHelpText": "Относительные пути будут в каталоге AppData Radarr",
"AvailabilityDelayHelpText": "Время до или после доступной даты для поиска фильма", "AvailabilityDelayHelpText": "Время до или после доступной даты для поиска фильма",
"AvailabilityDelay": "Задержка доступности", "AvailabilityDelay": "Задержка доступности",
@@ -908,7 +908,7 @@
"TimeFormat": "Формат времени", "TimeFormat": "Формат времени",
"Time": "Время", "Time": "Время",
"ThisConditionMatchesUsingRegularExpressions": "Это условие соответствует использованию регулярных выражений. Обратите внимание, что символы {0} имеют особое значение и требуют экранирования с помощью {1}", "ThisConditionMatchesUsingRegularExpressions": "Это условие соответствует использованию регулярных выражений. Обратите внимание, что символы {0} имеют особое значение и требуют экранирования с помощью {1}",
"ThisCannotBeCancelled": "Нельзя отменить после запуска без перезапуска Radarr.", "ThisCannotBeCancelled": "Это действие нельзя отменить после запуска без отключения всех ваших индексаторов.",
"TheLogLevelDefault": "Уровень журнала по умолчанию - «Информация» и может быть изменен в", "TheLogLevelDefault": "Уровень журнала по умолчанию - «Информация» и может быть изменен в",
"TestAllLists": "Тестировать все листы", "TestAllLists": "Тестировать все листы",
"TestAllIndexers": "Тестировать все индексаторы", "TestAllIndexers": "Тестировать все индексаторы",
@@ -982,7 +982,7 @@
"ShowCertification": "Показать сертификаты", "ShowCertification": "Показать сертификаты",
"ShowAsAllDayEvents": "Показывать как мероприятия на весь день", "ShowAsAllDayEvents": "Показывать как мероприятия на весь день",
"ShowAdvanced": "Показать расширенные", "ShowAdvanced": "Показать расширенные",
"ShouldMonitorHelpText": "Если включено, фильмы, добавленные в этот список, добавляются и отслеживаются", "ShouldMonitorHelpText": "Если включено, фильмы или коллекции, добавленные в этот список, будут добавлены, как отслеживаемые",
"SettingsWeekColumnHeaderHelpText": "Отображается над каждым столбцом, когда неделя активна", "SettingsWeekColumnHeaderHelpText": "Отображается над каждым столбцом, когда неделя активна",
"SettingsWeekColumnHeader": "Заголовок столбца недели", "SettingsWeekColumnHeader": "Заголовок столбца недели",
"SettingsTimeFormat": "Формат времени", "SettingsTimeFormat": "Формат времени",
@@ -1015,7 +1015,7 @@
"Security": "Безопасность", "Security": "Безопасность",
"Seconds": "Секунды", "Seconds": "Секунды",
"SearchSelected": "Искать выделенные", "SearchSelected": "Искать выделенные",
"SearchOnAddHelpText": "Искать фильмы в этом списке при добавлении в Radarr", "SearchOnAddHelpText": "Искать фильмы в этом списке при добавлении в библиотеку",
"SearchOnAdd": "Искать при добавлении", "SearchOnAdd": "Искать при добавлении",
"SearchMovie": "Поиск фильма", "SearchMovie": "Поиск фильма",
"SearchMissing": "Поиск пропавших", "SearchMissing": "Поиск пропавших",
@@ -1103,10 +1103,44 @@
"ImdbVotes": "IMDb оценок", "ImdbVotes": "IMDb оценок",
"Duration": "Длительность", "Duration": "Длительность",
"Rating": "Рейтинг", "Rating": "Рейтинг",
"List": "Списки", "List": "Список",
"RssSyncHelpText": "Интервал в минутах. Установите 0 чтобы выключить (остановит все автоматические захваты релизов)", "RssSyncHelpText": "Интервал в минутах. Установите 0, чтобы выключить (остановит все автоматические захваты релизов)",
"AllCollectionsHiddenDueToFilter": "Все фильмы спрятаны в соответствии с фильтром.", "AllCollectionsHiddenDueToFilter": "Все фильмы скрыты в соответствии с фильтром.",
"Collections": "Коллекция", "Collections": "Коллекции",
"MonitorMovies": "Отслеживать фильм", "MonitorMovies": "Отслеживать фильм",
"NoCollections": "Фильмов не найдено. Для начала вам нужно добавить новый фильм или импортировать уже существующие." "NoCollections": "Коллекции не найдены. Для начала вам нужно добавить новый фильм или импортировать несколько существующих.",
"CollectionOptions": "Параметры коллекции",
"CollectionShowDetailsHelpText": "Показать статус и свойства коллекции",
"CollectionShowOverviewsHelpText": "Показать обзоры коллекций",
"CollectionShowPostersHelpText": "Показать постеры предметов коллекции",
"EditCollection": "Редактировать коллекцию",
"Auto": "Авто",
"MonitorCollection": "Отслеживание коллекции",
"MonitoredCollectionHelpText": "Контролировать, чтобы фильмы из этой коллекции автоматически добавлялись в библиотеку",
"MovieAndCollection": "Фильм и коллекция",
"MovieCollectionMissingRoot": "Отсутствует корневая папка для коллекции фильмов: {0}",
"MovieCollectionMultipleMissingRoots": "Для коллекций фильмов отсутствуют несколько корневых папок: {0}",
"MovieOnly": "Только фильм",
"ShowCollectionDetails": "Показать статус коллекции",
"OnMovieAddedHelpText": "Добавлено в фильм",
"RefreshCollections": "Обновить коллекции",
"RefreshMonitoredIntervalHelpText": "Как часто обновлять отслеживаемые загрузки с клиентов загрузки, минимум 1 минута",
"Never": "Никогда",
"OriginalTitle": "Оригинальное название",
"CollectionsSelectedInterp": "{0} коллекций выбрано",
"UnableToLoadCollections": "Не удалось загрузить коллекции",
"OnMovieAdded": "Добавлено в фильм",
"OriginalLanguage": "Язык оригинала",
"SearchOnAddCollectionHelpText": "Поиск фильмов в этой коллекции при добавлении в библиотеку",
"ShowOverview": "Показать обзор",
"ShowPosters": "Показать постеры",
"TotalMovies": "Всего фильмов",
"Waiting": "Ожидание",
"ChooseImportMode": "Выберите режим импорта",
"InstanceName": "Имя экземпляра",
"InstanceNameHelpText": "Имя экземпляра на вкладке и для имени приложения системного журнала",
"RottenTomatoesRating": "Tomato рейтинг",
"Started": "Запущено",
"Database": "База данных",
"From": "из"
} }

View File

@@ -637,7 +637,7 @@
"InstallLatest": "安装最新版", "InstallLatest": "安装最新版",
"IndexerStatusCheckSingleClientMessage": "搜刮器因错误不可用:{0}", "IndexerStatusCheckSingleClientMessage": "搜刮器因错误不可用:{0}",
"IndexerStatusCheckAllClientMessage": "所有搜刮器都因错误不可用", "IndexerStatusCheckAllClientMessage": "所有搜刮器都因错误不可用",
"IndexerSearchCheckNoInteractiveMessage": "没有任何索引器开启了手动搜索Radarr 不会提供任何手动搜索的结果", "IndexerSearchCheckNoInteractiveMessage": "没有任何索引器开启了手动搜索,因此Radarr 不会提供任何手动搜索的结果",
"IndexerRssHealthCheckNoIndexers": "没有任何索引器开启了RSS同步Radarr不会自动抓取新发布的影片", "IndexerRssHealthCheckNoIndexers": "没有任何索引器开启了RSS同步Radarr不会自动抓取新发布的影片",
"IndexerLongTermStatusCheckSingleClientMessage": "由于故障6小时下列索引器都已不可用{0}", "IndexerLongTermStatusCheckSingleClientMessage": "由于故障6小时下列索引器都已不可用{0}",
"IndexerLongTermStatusCheckAllClientMessage": "由于故障超过6小时所有索引器均不可用", "IndexerLongTermStatusCheckAllClientMessage": "由于故障超过6小时所有索引器均不可用",
@@ -1142,5 +1142,6 @@
"RottenTomatoesRating": "烂番茄指数", "RottenTomatoesRating": "烂番茄指数",
"ShowPosters": "显示海报", "ShowPosters": "显示海报",
"OnMovieAdded": "电影添加时", "OnMovieAdded": "电影添加时",
"OnMovieAddedHelpText": "电影添加时" "OnMovieAddedHelpText": "电影添加时",
"TotalMovies": "电影总数"
} }

View File

@@ -119,10 +119,18 @@ namespace NzbDrone.Core.Movies
return FindByTitle(new List<string> { title }, year, otherTitles, candidates); return FindByTitle(new List<string> { title }, year, otherTitles, candidates);
} }
public Movie FindByTitle(List<string> cleanTitles, int? year, List<string> otherTitles, List<Movie> candidates) public Movie FindByTitle(List<string> titles, int? year, List<string> otherTitles, List<Movie> candidates)
{ {
var cleanTitles = titles.Select(t => t.CleanMovieTitle().ToLowerInvariant());
var result = candidates.Where(x => cleanTitles.Contains(x.MovieMetadata.Value.CleanTitle)).FirstWithYear(year); var result = candidates.Where(x => cleanTitles.Contains(x.MovieMetadata.Value.CleanTitle)).FirstWithYear(year);
if (result == null)
{
result =
candidates.Where(movie => cleanTitles.Contains(movie.MovieMetadata.Value.CleanOriginalTitle)).FirstWithYear(year);
}
if (result == null) if (result == null)
{ {
result = result =

View File

@@ -0,0 +1,66 @@
using System.Collections.Generic;
using FluentValidation.Results;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.Movies;
namespace NzbDrone.Core.Notifications.Ntfy
{
public class Ntfy : NotificationBase<NtfySettings>
{
private readonly INtfyProxy _proxy;
public Ntfy(INtfyProxy proxy)
{
_proxy = proxy;
}
public override string Name => "ntfy.sh";
public override string Link => "https://ntfy.sh/";
public override void OnGrab(GrabMessage grabMessage)
{
_proxy.SendNotification(MOVIE_GRABBED_TITLE_BRANDED, grabMessage.Message, Settings);
}
public override void OnDownload(DownloadMessage message)
{
_proxy.SendNotification(MOVIE_DOWNLOADED_TITLE_BRANDED, message.Message, Settings);
}
public override void OnMovieAdded(Movie movie)
{
_proxy.SendNotification(MOVIE_ADDED_TITLE_BRANDED, $"{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_BRANDED, healthCheck.Message, Settings);
}
public override void OnApplicationUpdate(ApplicationUpdateMessage updateMessage)
{
_proxy.SendNotification(APPLICATION_UPDATE_TITLE_BRANDED, 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,18 @@
using System;
using NzbDrone.Common.Exceptions;
namespace NzbDrone.Core.Notifications.Ntfy
{
public class NtfyException : NzbDroneException
{
public NtfyException(string message)
: base(message)
{
}
public NtfyException(string message, Exception innerException, params object[] args)
: base(message, innerException, args)
{
}
}
}

View File

@@ -0,0 +1,11 @@
namespace NzbDrone.Core.Notifications.Ntfy
{
public enum NtfyPriority
{
Min = 1,
Low = 2,
Default = 3,
High = 4,
Max = 5
}
}

View File

@@ -0,0 +1,138 @@
using System;
using System.Linq;
using System.Net;
using FluentValidation.Results;
using NLog;
using NzbDrone.Common.Extensions;
using NzbDrone.Common.Http;
namespace NzbDrone.Core.Notifications.Ntfy
{
public interface INtfyProxy
{
void SendNotification(string title, string message, NtfySettings settings);
ValidationFailure Test(NtfySettings settings);
}
public class NtfyProxy : INtfyProxy
{
private const string DEFAULT_PUSH_URL = "https://ntfy.sh";
private readonly IHttpClient _httpClient;
private readonly Logger _logger;
public NtfyProxy(IHttpClient httpClient, Logger logger)
{
_httpClient = httpClient;
_logger = logger;
}
public void SendNotification(string title, string message, NtfySettings settings)
{
var error = false;
var serverUrl = settings.ServerUrl.IsNullOrWhiteSpace() ? NtfyProxy.DEFAULT_PUSH_URL : settings.ServerUrl;
foreach (var topic in settings.Topics)
{
var request = BuildTopicRequest(serverUrl, topic);
try
{
SendNotification(title, message, request, settings);
}
catch (NtfyException ex)
{
_logger.Error(ex, "Unable to send test message to {0}", topic);
error = true;
}
}
if (error)
{
throw new NtfyException("Unable to send Ntfy notifications to all topics");
}
}
private HttpRequestBuilder BuildTopicRequest(string serverUrl, string topic)
{
var trimServerUrl = serverUrl.TrimEnd('/');
var requestBuilder = new HttpRequestBuilder($"{trimServerUrl}/{topic}").Post();
return requestBuilder;
}
public ValidationFailure Test(NtfySettings settings)
{
try
{
const string title = "Radarr - Test Notification";
const string body = "This is a test message from Radarr";
SendNotification(title, body, settings);
}
catch (HttpException ex)
{
if (ex.Response.StatusCode == HttpStatusCode.Unauthorized || ex.Response.StatusCode == HttpStatusCode.Forbidden)
{
_logger.Error(ex, "Authorization is required");
return new ValidationFailure("UserName", "Authorization is required");
}
_logger.Error(ex, "Unable to send test message");
return new ValidationFailure("ServerUrl", "Unable to send test message");
}
catch (Exception ex)
{
_logger.Error(ex, "Unable to send test message");
return new ValidationFailure("", "Unable to send test message");
}
return null;
}
private void SendNotification(string title, string message, HttpRequestBuilder requestBuilder, NtfySettings settings)
{
try
{
requestBuilder.Headers.Add("X-Title", title);
requestBuilder.Headers.Add("X-Message", message);
requestBuilder.Headers.Add("X-Priority", settings.Priority.ToString());
if (settings.Tags.Any())
{
requestBuilder.Headers.Add("X-Tags", settings.Tags.Join(","));
}
if (!settings.ClickUrl.IsNullOrWhiteSpace())
{
requestBuilder.Headers.Add("X-Click", settings.ClickUrl);
}
var request = requestBuilder.Build();
if (!settings.UserName.IsNullOrWhiteSpace() && !settings.Password.IsNullOrWhiteSpace())
{
request.Credentials = new BasicNetworkCredential(settings.UserName, settings.Password);
}
_httpClient.Execute(request);
}
catch (HttpException ex)
{
if (ex.Response.StatusCode == HttpStatusCode.Unauthorized || ex.Response.StatusCode == HttpStatusCode.Forbidden)
{
_logger.Error(ex, "Authorization is required");
throw;
}
throw new NtfyException("Unable to send text message: {0}", ex, ex.Message);
}
}
}
}

View File

@@ -0,0 +1,63 @@
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.Ntfy
{
public class NtfySettingsValidator : AbstractValidator<NtfySettings>
{
public NtfySettingsValidator()
{
RuleFor(c => c.Topics).NotEmpty();
RuleFor(c => c.Priority).InclusiveBetween(1, 5);
RuleFor(c => c.ServerUrl).IsValidUrl().When(c => !c.ServerUrl.IsNullOrWhiteSpace());
RuleFor(c => c.ClickUrl).IsValidUrl().When(c => !c.ClickUrl.IsNullOrWhiteSpace());
RuleFor(c => c.UserName).NotEmpty().When(c => !c.Password.IsNullOrWhiteSpace());
RuleFor(c => c.Password).NotEmpty().When(c => !c.UserName.IsNullOrWhiteSpace());
RuleForEach(c => c.Topics).NotEmpty().Matches("[a-zA-Z0-9_-]+").Must(c => !InvalidTopics.Contains(c)).WithMessage("Invalid topic");
}
private static List<string> InvalidTopics => new List<string> { "announcements", "app", "docs", "settings", "stats", "mytopic-rw", "mytopic-ro", "mytopic-wo" };
}
public class NtfySettings : IProviderConfig
{
private static readonly NtfySettingsValidator Validator = new NtfySettingsValidator();
public NtfySettings()
{
Topics = Array.Empty<string>();
Priority = 3;
}
[FieldDefinition(0, Label = "Server Url", Type = FieldType.Url, HelpLink = "https://ntfy.sh/docs/install/", HelpText = "Leave blank to use public server (https://ntfy.sh)", Placeholder = "https://ntfy.sh")]
public string ServerUrl { get; set; }
[FieldDefinition(1, Label = "User Name", HelpText = "Optional Authorization", Privacy = PrivacyLevel.UserName)]
public string UserName { get; set; }
[FieldDefinition(2, Label = "Password", Type = FieldType.Password, HelpText = "Optional Password", Privacy = PrivacyLevel.Password)]
public string Password { get; set; }
[FieldDefinition(3, Label = "Priority", Type = FieldType.Select, SelectOptions = typeof(NtfyPriority))]
public int Priority { get; set; }
[FieldDefinition(4, Label = "Topics", HelpText = "List of Topics to send notifications to", Type = FieldType.Tag, Placeholder = "Topic1234,Topic4321")]
public IEnumerable<string> Topics { get; set; }
[FieldDefinition(5, Label = "Ntfy Tags and Emojis", Type = FieldType.Tag, HelpText = "Optional list of tags or emojis to use", Placeholder = "warning,skull", HelpLink = "https://ntfy.sh/docs/emojis/")]
public IEnumerable<string> Tags { get; set; }
[FieldDefinition(6, Label = "Click Url", Type = FieldType.Url, HelpText = "Optional link when user clicks notification", Placeholder = "https://myserver.example.com/radarr")]
public string ClickUrl { get; set; }
public NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));
}
}
}

View File

@@ -38,20 +38,9 @@ namespace NzbDrone.Core.Organizer
private readonly ICustomFormatService _formatService; private readonly ICustomFormatService _formatService;
private readonly Logger _logger; private readonly Logger _logger;
private static readonly Regex TitleRegex = new Regex(@"\{(?<prefix>[- ._\[(]*)(?<token>(?:[a-z0-9]+)(?:(?<separator>[- ._]+)(?:[a-z0-9]+))?)(?::(?<customFormat>[a-z0-9|]+))?(?<suffix>[- ._)\]]*)\}", 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); RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);
private static readonly Regex TagsRegex = new Regex(@"(?<tags>\{tags(?:\:0+)?})",
RegexOptions.Compiled | RegexOptions.IgnoreCase);
public static readonly Regex SeasonEpisodePatternRegex = new Regex(@"(?<separator>(?<=})[- ._]+?)?(?<seasonEpisode>s?{season(?:\:0+)?}(?<episodeSeparator>[- ._]?[ex])(?<episode>{episode(?:\:0+)?}))(?<separator>[- ._]+?(?={))?",
RegexOptions.Compiled | RegexOptions.IgnoreCase);
public static readonly Regex AbsoluteEpisodePatternRegex = new Regex(@"(?<separator>(?<=})[- ._]+?)?(?<absolute>{absolute(?:\:0+)?})(?<separator>[- ._]+?(?={))?",
RegexOptions.Compiled | RegexOptions.IgnoreCase);
public static readonly Regex AirDateRegex = new Regex(@"\{Air(\s|\W|_)Date\}", RegexOptions.Compiled | RegexOptions.IgnoreCase);
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); RegexOptions.Compiled | RegexOptions.IgnoreCase);
@@ -61,11 +50,6 @@ namespace NzbDrone.Core.Organizer
private static readonly Regex ScenifyRemoveChars = new Regex(@"(?<=\s)(,|<|>|\/|\\|;|:|'|""|\||`|~|!|\?|@|$|%|^|\*|-|_|=){1}(?=\s)|('|:|\?|,)(?=(?:(?:s|m)\s)|\s|$)|(\(|\)|\[|\]|\{|\})", RegexOptions.Compiled | RegexOptions.IgnoreCase); private static readonly Regex ScenifyRemoveChars = new Regex(@"(?<=\s)(,|<|>|\/|\\|;|:|'|""|\||`|~|!|\?|@|$|%|^|\*|-|_|=){1}(?=\s)|('|:|\?|,)(?=(?:(?:s|m)\s)|\s|$)|(\(|\)|\[|\]|\{|\})", RegexOptions.Compiled | RegexOptions.IgnoreCase);
private static readonly Regex ScenifyReplaceChars = new Regex(@"[\/]", RegexOptions.Compiled | RegexOptions.IgnoreCase); private static readonly Regex ScenifyReplaceChars = new Regex(@"[\/]", RegexOptions.Compiled | RegexOptions.IgnoreCase);
//TODO: Support Written numbers (One, Two, etc) and Roman Numerals (I, II, III etc)
private static readonly Regex MultiPartCleanupRegex = new Regex(@"(?:\(\d+\)|(Part|Pt\.?)\s?\d+)$", RegexOptions.Compiled | RegexOptions.IgnoreCase);
private static readonly char[] EpisodeTitleTrimCharacters = new[] { ' ', '.', '?' };
private static readonly Regex TitlePrefixRegex = new Regex(@"^(The|An|A) (.*?)((?: *\([^)]+\))*)$", RegexOptions.Compiled | RegexOptions.IgnoreCase); private static readonly Regex TitlePrefixRegex = new Regex(@"^(The|An|A) (.*?)((?: *\([^)]+\))*)$", RegexOptions.Compiled | RegexOptions.IgnoreCase);
private static readonly Regex ReservedDeviceNamesRegex = new Regex(@"^(?:aux|com[1-9]|con|lpt[1-9]|nul|prn)\.", RegexOptions.Compiled | RegexOptions.IgnoreCase); private static readonly Regex ReservedDeviceNamesRegex = new Regex(@"^(?:aux|com[1-9]|con|lpt[1-9]|nul|prn)\.", RegexOptions.Compiled | RegexOptions.IgnoreCase);
@@ -133,7 +117,7 @@ namespace NzbDrone.Core.Organizer
AddQualityTokens(tokenHandlers, movie, movieFile); AddQualityTokens(tokenHandlers, movie, movieFile);
AddMediaInfoTokens(tokenHandlers, movieFile); AddMediaInfoTokens(tokenHandlers, movieFile);
AddMovieFileTokens(tokenHandlers, movieFile); AddMovieFileTokens(tokenHandlers, movieFile);
AddTagsTokens(tokenHandlers, movieFile); AddEditionTagsTokens(tokenHandlers, movieFile);
AddCustomFormats(tokenHandlers, movie, movieFile, customFormats); AddCustomFormats(tokenHandlers, movie, movieFile, customFormats);
var splitPatterns = pattern.Split(new char[] { '\\', '/' }, StringSplitOptions.RemoveEmptyEntries); var splitPatterns = pattern.Split(new char[] { '\\', '/' }, StringSplitOptions.RemoveEmptyEntries);
@@ -193,7 +177,7 @@ namespace NzbDrone.Core.Organizer
AddQualityTokens(tokenHandlers, movie, movieFile); AddQualityTokens(tokenHandlers, movie, movieFile);
AddMediaInfoTokens(tokenHandlers, movieFile); AddMediaInfoTokens(tokenHandlers, movieFile);
AddMovieFileTokens(tokenHandlers, movieFile); AddMovieFileTokens(tokenHandlers, movieFile);
AddTagsTokens(tokenHandlers, movieFile); AddEditionTagsTokens(tokenHandlers, movieFile);
} }
else else
{ {
@@ -297,7 +281,7 @@ namespace NzbDrone.Core.Organizer
return movie.Title; return movie.Title;
} }
private void AddTagsTokens(Dictionary<string, Func<TokenMatch, string>> tokenHandlers, MovieFile movieFile) private void AddEditionTagsTokens(Dictionary<string, Func<TokenMatch, string>> tokenHandlers, MovieFile movieFile)
{ {
if (movieFile.Edition.IsNotNullOrWhiteSpace()) if (movieFile.Edition.IsNotNullOrWhiteSpace())
{ {
@@ -497,6 +481,7 @@ namespace NzbDrone.Core.Organizer
var tokenMatch = new TokenMatch var tokenMatch = new TokenMatch
{ {
RegexMatch = match, RegexMatch = match,
Tag = match.Groups["tag"].Value,
Prefix = match.Groups["prefix"].Value, Prefix = match.Groups["prefix"].Value,
Separator = match.Groups["separator"].Value, Separator = match.Groups["separator"].Value,
Suffix = match.Groups["suffix"].Value, Suffix = match.Groups["suffix"].Value,
@@ -531,7 +516,7 @@ namespace NzbDrone.Core.Organizer
if (!replacementText.IsNullOrWhiteSpace()) if (!replacementText.IsNullOrWhiteSpace())
{ {
replacementText = tokenMatch.Prefix + replacementText + tokenMatch.Suffix; replacementText = tokenMatch.Tag + tokenMatch.Prefix + replacementText + tokenMatch.Suffix;
} }
return replacementText; return replacementText;
@@ -598,6 +583,7 @@ namespace NzbDrone.Core.Organizer
internal sealed class TokenMatch internal sealed class TokenMatch
{ {
public Match RegexMatch { get; set; } public Match RegexMatch { get; set; }
public string Tag { get; set; }
public string Prefix { get; set; } public string Prefix { get; set; }
public string Separator { get; set; } public string Separator { get; set; }
public string Suffix { get; set; } public string Suffix { get; set; }

View File

@@ -42,7 +42,8 @@ namespace NzbDrone.Core.Parser
new IsoLanguage("uk", "", "ukr", "Ukrainian", Language.Ukrainian), new IsoLanguage("uk", "", "ukr", "Ukrainian", Language.Ukrainian),
new IsoLanguage("fa", "", "fas", "Persian", Language.Persian), new IsoLanguage("fa", "", "fas", "Persian", Language.Persian),
new IsoLanguage("be", "", "ben", "Bengali", Language.Bengali), new IsoLanguage("be", "", "ben", "Bengali", Language.Bengali),
new IsoLanguage("lt", "", "lit", "Lithuanian", Language.Lithuanian) new IsoLanguage("lt", "", "lit", "Lithuanian", Language.Lithuanian),
new IsoLanguage("sk", "", "slk", "Slovak", Language.Slovak)
}; };
public static IsoLanguage Find(string isoCode) public static IsoLanguage Find(string isoCode)

View File

@@ -32,7 +32,8 @@ namespace NzbDrone.Core.Parser
private static readonly Regex CaseSensitiveLanguageRegex = new Regex(@"(?:(?i)(?<!SUB[\W|_|^]))(?:(?<lithuanian>\bLT\b)| private static readonly Regex CaseSensitiveLanguageRegex = new Regex(@"(?:(?i)(?<!SUB[\W|_|^]))(?:(?<lithuanian>\bLT\b)|
(?<czech>\bCZ\b)| (?<czech>\bCZ\b)|
(?<polish>\bPL\b)| (?<polish>\bPL\b)|
(?<bulgarian>\bBG\b))(?:(?i)(?![\W|_|^]SUB))", (?<bulgarian>\bBG\b))(?:(?i)(?![\W|_|^]SUB))|
(?<slovak>\bSK\b)",
RegexOptions.Compiled | RegexOptions.IgnorePatternWhitespace); RegexOptions.Compiled | RegexOptions.IgnorePatternWhitespace);
private static readonly Regex SubtitleLanguageRegex = new Regex(".+?[-_. ](?<iso_code>[a-z]{2,3})(?:[-_. ]forced)?$", RegexOptions.Compiled | RegexOptions.IgnoreCase); private static readonly Regex SubtitleLanguageRegex = new Regex(".+?[-_. ](?<iso_code>[a-z]{2,3})(?:[-_. ]forced)?$", RegexOptions.Compiled | RegexOptions.IgnoreCase);
@@ -182,6 +183,11 @@ namespace NzbDrone.Core.Parser
languages.Add(Language.Bengali); languages.Add(Language.Bengali);
} }
if (lowerTitle.Contains("slovak"))
{
languages.Add(Language.Slovak);
}
// Case sensitive // Case sensitive
var caseSensitiveMatch = CaseSensitiveLanguageRegex.Match(title); var caseSensitiveMatch = CaseSensitiveLanguageRegex.Match(title);
@@ -205,6 +211,11 @@ namespace NzbDrone.Core.Parser
languages.Add(Language.Bulgarian); languages.Add(Language.Bulgarian);
} }
if (caseSensitiveMatch.Groups["slovak"].Captures.Cast<Capture>().Any())
{
languages.Add(Language.Slovak);
}
var matches = LanguageRegex.Matches(title); var matches = LanguageRegex.Matches(title);
foreach (Match match in matches) foreach (Match match in matches)

View File

@@ -53,9 +53,25 @@ namespace Radarr.Api.V3.Collections
} }
[HttpGet] [HttpGet]
public List<CollectionResource> GetCollections() public List<CollectionResource> GetCollections(int? tmdbId)
{ {
return MapToResource(_collectionService.GetAllCollections()).ToList(); var collectionResources = new List<CollectionResource>();
if (tmdbId.HasValue)
{
var collection = _collectionService.FindByTmdbId(tmdbId.Value);
if (collection != null)
{
collectionResources.AddIfNotNull(MapToResource(collection));
}
}
else
{
collectionResources = MapToResource(_collectionService.GetAllCollections()).ToList();
}
return collectionResources;
} }
[RestPutById] [RestPutById]

View File

@@ -589,6 +589,16 @@
"tags": [ "tags": [
"Collection" "Collection"
], ],
"parameters": [
{
"name": "tmdbId",
"in": "query",
"schema": {
"type": "integer",
"format": "int32"
}
}
],
"responses": { "responses": {
"200": { "200": {
"description": "Success", "description": "Success",