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

Compare commits

..

1 Commits

Author SHA1 Message Date
Mark McDowall
27316b4239 New: Parse anime version with a space before 'v'
(cherry picked from commit e9123982f33ab35ca022f91f345da05fef23d6dc)
2022-09-25 07:26:51 +00:00
27 changed files with 101 additions and 153 deletions

2
.github/FUNDING.yml vendored
View File

@@ -1,6 +1,6 @@
# These are supported funding model platforms # These are supported funding model platforms
github: radarr github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: # Replace with a single Patreon username patreon: # Replace with a single Patreon username
open_collective: radarr open_collective: radarr
ko_fi: # Replace with a single Ko-fi username ko_fi: # Replace with a single Ko-fi username

View File

@@ -45,11 +45,11 @@ body:
- **Database**: Sqlite 3.36.0 - **Database**: Sqlite 3.36.0
value: | value: |
- OS: - OS:
- Radarr: - Radarr:
- Docker Install: - Docker Install:
- Using Reverse Proxy: - Using Reverse Proxy:
- Browser: - Browser:
- Database: - Database:
render: markdown render: markdown
validations: validations:
required: true required: true

View File

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

View File

@@ -7,12 +7,8 @@ on:
concurrency: azuresync-${{ github.event.issue.number }} concurrency: azuresync-${{ github.event.issue.number }}
permissions: {}
jobs: jobs:
alert: alert:
permissions:
issues: write # to update issue body
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: danhellem/github-actions-issue-to-work-item@master - uses: danhellem/github-actions-issue-to-work-item@master

View File

@@ -5,13 +5,8 @@ on:
schedule: schedule:
- cron: '0 0 * * *' - cron: '0 0 * * *'
permissions: {}
jobs: jobs:
lock: lock:
permissions:
issues: write # to lock issues (dessant/lock-threads)
pull-requests: write # to lock PRs (dessant/lock-threads)
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: dessant/lock-threads@v2 - uses: dessant/lock-threads@v2

View File

@@ -4,12 +4,8 @@ on:
issues: issues:
types: [labeled, unlabeled, reopened] types: [labeled, unlabeled, reopened]
permissions: {}
jobs: jobs:
support: support:
permissions:
issues: write # to modify issues
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: dessant/support-requests@v2 - uses: dessant/support-requests@v2

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.3.0' majorVersion: '4.2.4'
minorVersion: $[counter('minorVersion', 2000)] minorVersion: $[counter('minorVersion', 2000)]
radarrVersion: '$(majorVersion).$(minorVersion)' radarrVersion: '$(majorVersion).$(minorVersion)'
buildName: '$(Build.SourceBranchName).$(radarrVersion)' buildName: '$(Build.SourceBranchName).$(radarrVersion)'

View File

@@ -0,0 +1,24 @@
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.Parser;
using NzbDrone.Core.Qualities;
using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.ParserTests
{
[TestFixture]
public class AnimeVersionFixture : CoreTest
{
[TestCase("Anime Title - S01E01 - (BD 1080p HEVC FLAC) [Dual Audio] [Group]", 1)]
[TestCase("Anime Title - S01E01v2 - (BD 1080p HEVC FLAC) [Dual Audio] [Group]", 2)]
[TestCase("Anime Title - S01E01 v2 - (BD 1080p HEVC FLAC) [Dual Audio] [Group]", 2)]
[TestCase("[SubsPlease] Anime Title - 01 (1080p) [B1F227CF]", 1)]
[TestCase("[SubsPlease] Anime Title - 01v2 (1080p) [B1F227CF]", 2)]
[TestCase("[SubsPlease] Anime Title - 01 v2 (1080p) [B1F227CF]", 2)]
public void should_be_able_to_parse_repack(string title, int version)
{
var result = QualityParser.ParseQuality(title);
result.Revision.Version.Should().Be(version);
}
}
}

View File

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

View File

@@ -105,7 +105,6 @@ namespace NzbDrone.Core.Test.ParserTests
[TestCase("Movie Title (2009) (2160p PMTP WEB-DL Hybrid H265 DV HDR10+ 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("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")] [TestCase("Movie.Should.Not.Use.Dots.2022.1080p.BluRay.x265.10bit.Tigole", "Tigole")]
[TestCase("Movie.Title.2005.2160p.UHD.BluRay.TrueHD 7.1.Atmos.x265 - HQMUX", "HQMUX")]
public void should_parse_exception_release_group(string title, string expected) public void should_parse_exception_release_group(string title, string expected)
{ {
Parser.Parser.ParseReleaseGroup(title).Should().Be(expected); Parser.Parser.ParseReleaseGroup(title).Should().Be(expected);

View File

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

View File

@@ -1,5 +1,4 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using NzbDrone.Core.Datastore; using NzbDrone.Core.Datastore;
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;
@@ -8,7 +7,6 @@ namespace NzbDrone.Core.ImportLists.ImportListMovies
public interface IImportListMovieRepository : IBasicRepository<ImportListMovie> public interface IImportListMovieRepository : IBasicRepository<ImportListMovie>
{ {
List<ImportListMovie> GetAllForLists(List<int> listIds); List<ImportListMovie> GetAllForLists(List<int> listIds);
bool ExistsByMetadataId(int metadataId);
} }
public class ImportListMovieRepository : BasicRepository<ImportListMovie>, IImportListMovieRepository public class ImportListMovieRepository : BasicRepository<ImportListMovie>, IImportListMovieRepository
@@ -22,12 +20,5 @@ namespace NzbDrone.Core.ImportLists.ImportListMovies
{ {
return Query(x => listIds.Contains(x.ListId)); return Query(x => listIds.Contains(x.ListId));
} }
public bool ExistsByMetadataId(int metadataId)
{
var movies = Query(x => x.MovieMetadataId == metadataId);
return movies.Any();
}
} }
} }

View File

@@ -15,7 +15,6 @@ namespace NzbDrone.Core.ImportLists.ImportListMovies
List<ImportListMovie> SyncMoviesForList(List<ImportListMovie> listMovies, int listId); List<ImportListMovie> SyncMoviesForList(List<ImportListMovie> listMovies, int listId);
void RemoveListMovie(ImportListMovie listMovie); void RemoveListMovie(ImportListMovie listMovie);
ImportListMovie GetById(int id); ImportListMovie GetById(int id);
bool ExistsByMetadataId(int metadataId);
} }
public class ImportListMovieService : IImportListMovieService, IHandleAsync<ProviderDeletedEvent<IImportList>> public class ImportListMovieService : IImportListMovieService, IHandleAsync<ProviderDeletedEvent<IImportList>>
@@ -80,10 +79,5 @@ namespace NzbDrone.Core.ImportLists.ImportListMovies
var moviesOnList = _importListMovieRepository.GetAllForLists(new List<int> { message.ProviderId }); var moviesOnList = _importListMovieRepository.GetAllForLists(new List<int> { message.ProviderId });
_importListMovieRepository.DeleteMany(moviesOnList); _importListMovieRepository.DeleteMany(moviesOnList);
} }
public bool ExistsByMetadataId(int metadataId)
{
return _importListMovieRepository.ExistsByMetadataId(metadataId);
}
} }
} }

View File

@@ -30,7 +30,7 @@
"NoListRecommendations": "No s'han trobat elements de llista ni recomanacions; per començar, podeu afegir una pel·lícula nova, importar-ne algunes existents o afegir una llista.", "NoListRecommendations": "No s'han trobat elements de llista ni recomanacions; per començar, podeu afegir una pel·lícula nova, importar-ne algunes existents o afegir una llista.",
"NotAvailable": "No disponible", "NotAvailable": "No disponible",
"PreferAndUpgrade": "Marca preferit i actualitza", "PreferAndUpgrade": "Marca preferit i actualitza",
"QualityProfileInUse": "No es pot suprimir un perfil de qualitat usat a una pel·lícula, llista o col·lecció", "QualityProfileInUse": "No es pot suprimir un perfil de qualitat usat a una pel·lícula",
"RadarrTags": "Etiquetes de Radarr", "RadarrTags": "Etiquetes de Radarr",
"Reddit": "Reddit", "Reddit": "Reddit",
"RSSSyncInterval": "Interval de sincronització RSS", "RSSSyncInterval": "Interval de sincronització RSS",
@@ -594,7 +594,7 @@
"IndexersSettingsSummary": "Indexadors i restriccions de llançament", "IndexersSettingsSummary": "Indexadors i restriccions de llançament",
"IndexerStatusCheckAllClientMessage": "Tots els indexadors no estan disponibles a causa d'errors", "IndexerStatusCheckAllClientMessage": "Tots els indexadors no estan disponibles a causa d'errors",
"IndexerStatusCheckSingleClientMessage": "Els indexadors no estan disponibles a causa d'errors: {0}", "IndexerStatusCheckSingleClientMessage": "Els indexadors no estan disponibles a causa d'errors: {0}",
"IndexerTagHelpText": "Utilitzeu aquest indexador només per a pel·lícules amb almenys una etiqueta coincident. Deixeu-ho en blanc per utilitzar-ho amb totes les pel·lícules.", "IndexerTagHelpText": "Utilitzeu aquest indexador només per a pel·lícules amb almenys una etiqueta coincident. Deixa en blanc per utilitzar-lo amb totes les pel·lícules.",
"InstallLatest": "Instal·la l'últim", "InstallLatest": "Instal·la l'últim",
"LanguageHelpText": "Idioma per a llançaments", "LanguageHelpText": "Idioma per a llançaments",
"Large": "Gran", "Large": "Gran",
@@ -804,7 +804,7 @@
"RemotePathMappingCheckFilesLocalWrongOSPath": "El client de baixada local {0} ha informat de fitxers a {1}, però el camí {2} no és vàlid. Reviseu la configuració del vostre client de baixada.", "RemotePathMappingCheckFilesLocalWrongOSPath": "El client de baixada local {0} ha informat de fitxers a {1}, però el camí {2} no és vàlid. Reviseu la configuració del vostre client de baixada.",
"RemotePathMappingCheckFilesWrongOSPath": "El client de baixada remota {0} ha informat de fitxers a {1}, però el camí {2} no és vàlid. Reviseu els mapes de camins remots i baixeu la configuració del client.", "RemotePathMappingCheckFilesWrongOSPath": "El client de baixada remota {0} ha informat de fitxers a {1}, però el camí {2} no és vàlid. Reviseu els mapes de camins remots i baixeu la configuració del client.",
"RemotePathMappingCheckFolderPermissions": "Radarr pot veure però no accedir al directori de descàrregues {0}. Error de permisos probable.", "RemotePathMappingCheckFolderPermissions": "Radarr pot veure però no accedir al directori de descàrregues {0}. Error de permisos probable.",
"RemotePathMappingCheckGenericPermissions": "El client de baixada {0} col·loca les baixades a {1}, però Radarr no pot veure aquest directori. És possible que hàgiu d'ajustar els permisos de la carpeta.", "RemotePathMappingCheckGenericPermissions": "El client de baixada {0} col·loca les baixades a {1}, però Radarr no pot veure aquest directori. És possible que hàgiu d'ajustar els permisos de la carpeta.",
"RemotePathMappingCheckImportFailed": "Radarr no ha pogut importar una pel·lícula. Comproveu els vostres registres per obtenir més informació.", "RemotePathMappingCheckImportFailed": "Radarr no ha pogut importar una pel·lícula. Comproveu els vostres registres per obtenir més informació.",
"RemotePathMappingCheckLocalFolderMissing": "El client de descàrrega remota {0} col·loca les baixades a {1}, però sembla que aquest directori no existeix. És probable que falti o sigui incorrecte l'assignació de camins remots.", "RemotePathMappingCheckLocalFolderMissing": "El client de descàrrega remota {0} col·loca les baixades a {1}, però sembla que aquest directori no existeix. És probable que falti o sigui incorrecte l'assignació de camins remots.",
"RemotePathMappingCheckLocalWrongOSPath": "El client de baixada local {0} col·loca les baixades a {1}, però el camí {2} no és vàlid. Reviseu la configuració del vostre client de baixada.", "RemotePathMappingCheckLocalWrongOSPath": "El client de baixada local {0} col·loca les baixades a {1}, però el camí {2} no és vàlid. Reviseu la configuració del vostre client de baixada.",

View File

@@ -339,7 +339,7 @@
"ChangeHasNotBeenSavedYet": "Änderung wurde noch nicht gespeichert", "ChangeHasNotBeenSavedYet": "Änderung wurde noch nicht gespeichert",
"CheckForFinishedDownloadsInterval": "Intervall zum prüfen von fertigen Downloads", "CheckForFinishedDownloadsInterval": "Intervall zum prüfen von fertigen Downloads",
"CleanLibraryLevel": "Mediathek aufräumen", "CleanLibraryLevel": "Mediathek aufräumen",
"ClickToChangeLanguage": "Sprache ändern ...", "ClickToChangeLanguage": "Sprache ändern...",
"ClickToChangeQuality": "Hier klicken um die Qualität zu ändern", "ClickToChangeQuality": "Hier klicken um die Qualität zu ändern",
"ClientPriority": "Priorität", "ClientPriority": "Priorität",
"CloneFormatTag": "Format Tag kopieren", "CloneFormatTag": "Format Tag kopieren",
@@ -889,7 +889,7 @@
"RadarrUpdated": "Radarr wurde aktualisiert", "RadarrUpdated": "Radarr wurde aktualisiert",
"RadarrCalendarFeed": "Radarr Kalender Feed", "RadarrCalendarFeed": "Radarr Kalender Feed",
"QueueIsEmpty": "Warteschlange ist leer", "QueueIsEmpty": "Warteschlange ist leer",
"QualityProfileInUse": "Ein Qualitätsprofil mit zugeordneten Filmen, Listen oder Sammlungen kann nicht gelöscht werden", "QualityProfileInUse": "Ein Qualitätsprofil mit zugeordneten Filmen kann nicht gelöscht werden",
"QualityOrLangCutoffHasNotBeenMet": "Qualität oder Sprache haben die Schwelle noch nicht erreicht", "QualityOrLangCutoffHasNotBeenMet": "Qualität oder Sprache haben die Schwelle noch nicht erreicht",
"QualityLimitsHelpText": "Limitierungen werden automatisch an die Filmlänge angepasst.", "QualityLimitsHelpText": "Limitierungen werden automatisch an die Filmlänge angepasst.",
"QualitiesHelpText": "Qualitätsprofile oben sind mehr bevorzugt. Profile in einer Gruppe sind gleichgestellt. Nur ausgewählte werden gesucht", "QualitiesHelpText": "Qualitätsprofile oben sind mehr bevorzugt. Profile in einer Gruppe sind gleichgestellt. Nur ausgewählte werden gesucht",

View File

@@ -1006,7 +1006,7 @@
"TorrentDelayTime": "Torrent-vertraging: {0}", "TorrentDelayTime": "Torrent-vertraging: {0}",
"TorrentsDisabled": "Torrents uitgeschakeld", "TorrentsDisabled": "Torrents uitgeschakeld",
"Trace": "Spoor", "Trace": "Spoor",
"Trailer": "Trailer", "Trailer": "Aanhangwagen",
"Trakt": "Trakt", "Trakt": "Trakt",
"Trigger": "In gang zetten", "Trigger": "In gang zetten",
"UnableToImportCheckLogs": "Gedownload - Kan niet importeren: controleer de logboeken voor details", "UnableToImportCheckLogs": "Gedownload - Kan niet importeren: controleer de logboeken voor details",

View File

@@ -79,7 +79,7 @@
"BranchUpdate": "更新Radarr的分支", "BranchUpdate": "更新Radarr的分支",
"Branch": "分支", "Branch": "分支",
"Calendar": "日历", "Calendar": "日历",
"BindAddressHelpText": "有效的 IP4 地址或以'*'代表所有地址", "BindAddressHelpText": "192.168.50.189:7878",
"BackupRetentionHelpText": "早于保留周期的自动备份将被自动清除", "BackupRetentionHelpText": "早于保留周期的自动备份将被自动清除",
"BackupNow": "马上备份", "BackupNow": "马上备份",
"BackupIntervalHelpText": "自动备份时间间隔", "BackupIntervalHelpText": "自动备份时间间隔",
@@ -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小时所有索引器均不可用",
@@ -775,7 +775,7 @@
"Updates": "更新", "Updates": "更新",
"UnableToLoadRestrictions": "无法加载限制条件", "UnableToLoadRestrictions": "无法加载限制条件",
"UnmonitoredHelpText": "在iCal订阅中包含未监控的电影", "UnmonitoredHelpText": "在iCal订阅中包含未监控的电影",
"QualityProfileInUse": "无法删除已指定给影片、列表、收藏的质量配置", "QualityProfileInUse": "无法删除已指定给影片的质量配置",
"UnableToLoadQualities": "无法加载影片质量", "UnableToLoadQualities": "无法加载影片质量",
"UnmappedFolders": "未映射的文件夹", "UnmappedFolders": "未映射的文件夹",
"RecycleBinCleanupDaysHelpTextWarning": "回收站中的文件在超出选择的天数后会被自动清理", "RecycleBinCleanupDaysHelpTextWarning": "回收站中的文件在超出选择的天数后会被自动清理",
@@ -1143,7 +1143,5 @@
"ShowPosters": "显示海报", "ShowPosters": "显示海报",
"OnMovieAdded": "电影添加时", "OnMovieAdded": "电影添加时",
"OnMovieAddedHelpText": "电影添加时", "OnMovieAddedHelpText": "电影添加时",
"TotalMovies": "电影总数", "TotalMovies": "电影总数"
"ApplicationUrlHelpText": "此应用的外部URL包含 http(s)://端口和基本URL",
"ApplicationURL": "程序URL"
} }

View File

@@ -1,3 +1,5 @@
using System.Collections.Generic;
using System.Linq;
using NLog; using NLog;
using NzbDrone.Core.CustomFormats; using NzbDrone.Core.CustomFormats;
using NzbDrone.Core.DecisionEngine; using NzbDrone.Core.DecisionEngine;
@@ -9,16 +11,19 @@ namespace NzbDrone.Core.MediaFiles.MovieImport.Specifications
{ {
public class UpgradeSpecification : IImportDecisionEngineSpecification public class UpgradeSpecification : IImportDecisionEngineSpecification
{ {
private readonly ICustomFormatCalculationService _customFormatCalculationService;
private readonly Logger _logger; private readonly Logger _logger;
public UpgradeSpecification(ICustomFormatCalculationService customFormatCalculationService, Logger logger) public UpgradeSpecification(ICustomFormatCalculationService customFormatCalculationService, Logger logger)
{ {
_customFormatCalculationService = customFormatCalculationService;
_logger = logger; _logger = logger;
} }
public Decision IsSatisfiedBy(LocalMovie localMovie, DownloadClientItem downloadClientItem) public Decision IsSatisfiedBy(LocalMovie localMovie, DownloadClientItem downloadClientItem)
{ {
var qualityComparer = new QualityModelComparer(localMovie.Movie.Profile); var qualityComparer = new QualityModelComparer(localMovie.Movie.Profile);
var preferredWordScore = GetCustomFormatScore(localMovie);
if (localMovie.Movie.MovieFileId > 0) if (localMovie.Movie.MovieFileId > 0)
{ {
@@ -37,9 +42,47 @@ namespace NzbDrone.Core.MediaFiles.MovieImport.Specifications
_logger.Debug("This file isn't a quality upgrade for movie. Skipping {0}", localMovie.Path); _logger.Debug("This file isn't a quality upgrade for movie. Skipping {0}", localMovie.Path);
return Decision.Reject("Not a quality upgrade for existing movie file(s)"); return Decision.Reject("Not a quality upgrade for existing movie file(s)");
} }
movieFile.Movie = localMovie.Movie;
var customFormats = _customFormatCalculationService.ParseCustomFormat(movieFile);
var movieFileCustomFormatScore = localMovie.Movie.Profile.CalculateCustomFormatScore(customFormats);
if (qualityCompare == 0 && preferredWordScore < movieFileCustomFormatScore)
{
_logger.Debug("This file isn't a custom format upgrade for movie. Skipping {0}", localMovie.Path);
return Decision.Reject("Not a custom format upgrade for existing movie file(s)");
}
} }
return Decision.Accept(); return Decision.Accept();
} }
private int GetCustomFormatScore(LocalMovie localMovie)
{
var movie = localMovie.Movie;
var fileFormats = new List<CustomFormat>();
var folderFormats = new List<CustomFormat>();
var clientFormats = new List<CustomFormat>();
if (localMovie.FileMovieInfo != null)
{
fileFormats = _customFormatCalculationService.ParseCustomFormat(localMovie.FileMovieInfo, movie);
}
if (localMovie.FolderMovieInfo != null)
{
folderFormats = _customFormatCalculationService.ParseCustomFormat(localMovie.FolderMovieInfo, movie);
}
if (localMovie.DownloadClientMovieInfo != null)
{
clientFormats = _customFormatCalculationService.ParseCustomFormat(localMovie.DownloadClientMovieInfo, movie);
}
var formats = fileFormats.Union(folderFormats.Union(clientFormats)).ToList();
return movie.Profile.CalculateCustomFormatScore(formats);
}
} }
} }

View File

@@ -1,5 +1,4 @@
using System.Collections.Generic; using System.Collections.Generic;
using NzbDrone.Core.ImportLists.ImportListMovies;
namespace NzbDrone.Core.Movies namespace NzbDrone.Core.Movies
{ {
@@ -12,20 +11,15 @@ namespace NzbDrone.Core.Movies
List<MovieMetadata> GetMoviesByCollectionTmdbId(int collectionId); List<MovieMetadata> GetMoviesByCollectionTmdbId(int collectionId);
bool Upsert(MovieMetadata movie); bool Upsert(MovieMetadata movie);
bool UpsertMany(List<MovieMetadata> movies); bool UpsertMany(List<MovieMetadata> movies);
void DeleteMany(List<MovieMetadata> movies);
} }
public class MovieMetadataService : IMovieMetadataService public class MovieMetadataService : IMovieMetadataService
{ {
private readonly IMovieMetadataRepository _movieMetadataRepository; private readonly IMovieMetadataRepository _movieMetadataRepository;
private readonly IMovieService _movieService;
private readonly IImportListMovieService _importListMovieService;
public MovieMetadataService(IMovieMetadataRepository movieMetadataRepository, IMovieService movieService, IImportListMovieService importListMovieService) public MovieMetadataService(IMovieMetadataRepository movieMetadataRepository)
{ {
_movieMetadataRepository = movieMetadataRepository; _movieMetadataRepository = movieMetadataRepository;
_movieService = movieService;
_importListMovieService = importListMovieService;
} }
public MovieMetadata FindByTmdbId(int tmdbId) public MovieMetadata FindByTmdbId(int tmdbId)
@@ -62,16 +56,5 @@ namespace NzbDrone.Core.Movies
{ {
return _movieMetadataRepository.UpsertMany(movies); return _movieMetadataRepository.UpsertMany(movies);
} }
public void DeleteMany(List<MovieMetadata> movies)
{
foreach (var movie in movies)
{
if (!_importListMovieService.ExistsByMetadataId(movie.Id) && !_movieService.ExistsByMetadataId(movie.Id))
{
_movieMetadataRepository.Delete(movie);
}
}
}
} }
} }

View File

@@ -1,6 +1,5 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Linq; using System.Linq;
using Dapper; using Dapper;
using NzbDrone.Core.Datastore; using NzbDrone.Core.Datastore;
@@ -31,7 +30,6 @@ namespace NzbDrone.Core.Movies
List<int> AllMovieTmdbIds(); List<int> AllMovieTmdbIds();
Dictionary<int, List<int>> AllMovieTags(); Dictionary<int, List<int>> AllMovieTags();
List<int> GetRecommendations(); List<int> GetRecommendations();
bool ExistsByMetadataId(int metadataId);
} }
public class MovieRepository : BasicRepository<Movie>, IMovieRepository public class MovieRepository : BasicRepository<Movie>, IMovieRepository
@@ -369,12 +367,5 @@ namespace NzbDrone.Core.Movies
return recommendations; return recommendations;
} }
public bool ExistsByMetadataId(int metadataId)
{
var movies = Query(x => x.MovieMetadataId == metadataId);
return movies.Any();
}
} }
} }

View File

@@ -48,7 +48,6 @@ namespace NzbDrone.Core.Movies
List<int> GetRecommendedTmdbIds(); List<int> GetRecommendedTmdbIds();
bool MoviePathExists(string folder); bool MoviePathExists(string folder);
void RemoveAddOptions(Movie movie); void RemoveAddOptions(Movie movie);
bool ExistsByMetadataId(int metadataId);
} }
public class MovieService : IMovieService, IHandle<MovieFileAddedEvent>, public class MovieService : IMovieService, IHandle<MovieFileAddedEvent>,
@@ -390,11 +389,6 @@ namespace NzbDrone.Core.Movies
return _movieRepository.GetRecommendations(); return _movieRepository.GetRecommendations();
} }
public bool ExistsByMetadataId(int metadataId)
{
return _movieRepository.ExistsByMetadataId(metadataId);
}
public void Handle(MovieFileAddedEvent message) public void Handle(MovieFileAddedEvent message)
{ {
var movie = message.MovieFile.Movie; var movie = message.MovieFile.Movie;

View File

@@ -1,5 +1,4 @@
using System; using System;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using NLog; using NLog;
using NzbDrone.Common.Instrumentation.Extensions; using NzbDrone.Common.Instrumentation.Extensions;
@@ -49,7 +48,6 @@ namespace NzbDrone.Core.Movies
_logger.ProgressInfo("Updating info for {0}", collection.Title); _logger.ProgressInfo("Updating info for {0}", collection.Title);
MovieCollection collectionInfo; MovieCollection collectionInfo;
List<MovieMetadata> movies;
try try
{ {
@@ -70,27 +68,8 @@ namespace NzbDrone.Core.Movies
collection.LastInfoSync = DateTime.UtcNow; collection.LastInfoSync = DateTime.UtcNow;
collection.Images = collectionInfo.Images; collection.Images = collectionInfo.Images;
movies = collectionInfo.Movies; collectionInfo.Movies.ForEach(x => x.CollectionTmdbId = collection.TmdbId);
movies.ForEach(x => x.CollectionTmdbId = collection.TmdbId); _movieMetadataService.UpsertMany(collectionInfo.Movies);
var existingMetaForCollection = _movieMetadataService.GetMoviesByCollectionTmdbId(collection.TmdbId);
var updateList = new List<MovieMetadata>();
foreach (var remoteMovie in movies)
{
var existing = existingMetaForCollection.FirstOrDefault(e => e.TmdbId == remoteMovie.TmdbId);
if (existingMetaForCollection.Any(x => x.TmdbId == remoteMovie.TmdbId))
{
existingMetaForCollection.Remove(existing);
}
updateList.Add(remoteMovie);
}
_movieMetadataService.UpsertMany(updateList);
_movieMetadataService.DeleteMany(existingMetaForCollection);
_logger.Debug("Finished collection refresh for {0}", collection.Title); _logger.Debug("Finished collection refresh for {0}", collection.Title);

View File

@@ -60,8 +60,6 @@ namespace NzbDrone.Core.Notifications.CustomScript
environmentVariables.Add("Radarr_Download_Client", message.DownloadClientName ?? string.Empty); environmentVariables.Add("Radarr_Download_Client", message.DownloadClientName ?? string.Empty);
environmentVariables.Add("Radarr_Download_Client_Type", message.DownloadClientType ?? string.Empty); environmentVariables.Add("Radarr_Download_Client_Type", message.DownloadClientType ?? string.Empty);
environmentVariables.Add("Radarr_Download_Id", message.DownloadId ?? string.Empty); environmentVariables.Add("Radarr_Download_Id", message.DownloadId ?? string.Empty);
environmentVariables.Add("Radarr_Release_CustomFormat", string.Join("|", remoteMovie.CustomFormats));
environmentVariables.Add("Radarr_Release_CustomFormatScore", remoteMovie.CustomFormatScore.ToString());
ExecuteScript(environmentVariables); ExecuteScript(environmentVariables);
} }

View File

@@ -151,7 +151,7 @@ namespace NzbDrone.Core.Parser
//Handle Exception Release Groups that don't follow -RlsGrp; Manual List //Handle Exception Release Groups that don't follow -RlsGrp; Manual List
// name only...BE VERY CAREFUL WITH THIS, HIGH CHANCE OF FALSE POSITIVES // 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|Tigole|HQMUX)", 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 WordDelimiterRegex = new Regex(@"(\s|\.|,|_|-|=|'|\|)+", RegexOptions.Compiled);
private static readonly Regex SpecialCharRegex = new Regex(@"(\&|\:|\\|\/)+", RegexOptions.Compiled); private static readonly Regex SpecialCharRegex = new Regex(@"(\&|\:|\\|\/)+", RegexOptions.Compiled);
@@ -265,15 +265,7 @@ namespace NzbDrone.Core.Parser
if (simpleTitleReplaceString.IsNotNullOrWhiteSpace()) if (simpleTitleReplaceString.IsNotNullOrWhiteSpace())
{ {
if (match[0].Groups["title"].Success) simpleReleaseTitle = simpleReleaseTitle.Replace(simpleTitleReplaceString, simpleTitleReplaceString.Contains(".") ? "A.Movie" : "A Movie");
{
simpleReleaseTitle = simpleReleaseTitle.Remove(match[0].Groups["title"].Index, match[0].Groups["title"].Length)
.Insert(match[0].Groups["title"].Index, simpleTitleReplaceString.Contains(".") ? "A.Movie" : "A Movie");
}
else
{
simpleReleaseTitle = simpleReleaseTitle.Replace(simpleTitleReplaceString, simpleTitleReplaceString.Contains(".") ? "A.Movie" : "A Movie");
}
} }
result.ReleaseGroup = ParseReleaseGroup(simpleReleaseTitle); result.ReleaseGroup = ParseReleaseGroup(simpleReleaseTitle);

View File

@@ -50,7 +50,7 @@ namespace NzbDrone.Core.Parser
private static readonly Regex RepackRegex = new Regex(@"\b(?<repack>repack|rerip)\b", private static readonly Regex RepackRegex = new Regex(@"\b(?<repack>repack|rerip)\b",
RegexOptions.Compiled | RegexOptions.IgnoreCase); RegexOptions.Compiled | RegexOptions.IgnoreCase);
private static readonly Regex VersionRegex = new Regex(@"\dv(?<version>\d)\b|\[v(?<version>\d)\]", private static readonly Regex VersionRegex = new Regex(@"\d[-._ ]?v(?<version>\d)[-._ ]|\[v(?<version>\d)\]",
RegexOptions.Compiled | RegexOptions.IgnoreCase); RegexOptions.Compiled | RegexOptions.IgnoreCase);
private static readonly Regex RealRegex = new Regex(@"\b(?<real>REAL)\b", private static readonly Regex RealRegex = new Regex(@"\b(?<real>REAL)\b",

View File

@@ -41,7 +41,7 @@ namespace Radarr.Api.V3.Calendar
} }
[HttpGet] [HttpGet]
public List<MovieResource> GetCalendar(DateTime? start, DateTime? end, bool unmonitored = false) public List<MovieResource> GetCalendar(DateTime? start, DateTime? end, bool unmonitored = false, bool includeArtist = false)
{ {
var startUse = start ?? DateTime.Today; var startUse = start ?? DateTime.Today;
var endUse = end ?? DateTime.Today.AddDays(2); var endUse = end ?? DateTime.Today.AddDays(2);

View File

@@ -453,6 +453,14 @@
"type": "boolean", "type": "boolean",
"default": false "default": false
} }
},
{
"name": "includeArtist",
"in": "query",
"schema": {
"type": "boolean",
"default": false
}
} }
], ],
"responses": { "responses": {