mirror of
https://github.com/Radarr/Radarr.git
synced 2026-03-05 13:21:25 -05:00
Compare commits
16 Commits
v5.27.5.10
...
v5.27.2.10
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8bef9b4da7 | ||
|
|
787c387036 | ||
|
|
0525256115 | ||
|
|
5767e181b7 | ||
|
|
1cf3ef5dff | ||
|
|
b6bad2398c | ||
|
|
16308e4b1c | ||
|
|
bd7465fae4 | ||
|
|
c0d70485c3 | ||
|
|
c743383912 | ||
|
|
d93c1d7808 | ||
|
|
0e2e7e4259 | ||
|
|
e6b27512c9 | ||
|
|
dae5e86b2c | ||
|
|
71f032d175 | ||
|
|
5a6db29dbd |
@@ -9,7 +9,7 @@ variables:
|
||||
testsFolder: './_tests'
|
||||
yarnCacheFolder: $(Pipeline.Workspace)/.yarn
|
||||
nugetCacheFolder: $(Pipeline.Workspace)/.nuget/packages
|
||||
majorVersion: '5.26.2'
|
||||
majorVersion: '5.27.2'
|
||||
minorVersion: $[counter('minorVersion', 2000)]
|
||||
radarrVersion: '$(majorVersion).$(minorVersion)'
|
||||
buildName: '$(Build.SourceBranchName).$(radarrVersion)'
|
||||
|
||||
@@ -54,11 +54,11 @@ function Tag({ id, label }: TagProps) {
|
||||
setIsDeleteTagModalOpen(true);
|
||||
}, []);
|
||||
|
||||
const handleConfirmDeleteTag = useCallback(() => {
|
||||
const handleDeleteTagModalClose = useCallback(() => {
|
||||
setIsDeleteTagModalOpen(false);
|
||||
}, []);
|
||||
|
||||
const handleDeleteTagModalClose = useCallback(() => {
|
||||
const handleConfirmDeleteTag = useCallback(() => {
|
||||
dispatch(deleteTag({ id }));
|
||||
}, [id, dispatch]);
|
||||
|
||||
|
||||
@@ -96,14 +96,22 @@ function merge(initialState, persistedState) {
|
||||
return computedState;
|
||||
}
|
||||
|
||||
const KEY = 'radarr';
|
||||
|
||||
const config = {
|
||||
slicer,
|
||||
serialize,
|
||||
merge,
|
||||
key: 'radarr'
|
||||
key: window.Radarr.instanceName.toLowerCase().replace(/ /g, '_') || KEY
|
||||
};
|
||||
|
||||
export default function createPersistState() {
|
||||
// Migrate existing local storage value to new key if it does not already exist.
|
||||
// Leave old value as-is in case there are multiple instances using the same key.
|
||||
if (config.key !== KEY && localStorage.getItem(KEY) && !localStorage.getItem(config.key)) {
|
||||
localStorage.setItem(config.key, localStorage.getItem(KEY));
|
||||
}
|
||||
|
||||
// Migrate existing local storage before proceeding
|
||||
const persistedState = JSON.parse(localStorage.getItem(config.key));
|
||||
migrate(persistedState);
|
||||
|
||||
@@ -85,7 +85,7 @@ namespace NzbDrone.Core.DecisionEngine
|
||||
|
||||
if (remoteMovie.Movie == null)
|
||||
{
|
||||
decision = new DownloadDecision(remoteMovie, new DownloadRejection(DownloadRejectionReason.UnknownMovie, "Unknown Movie. Unable to identify correct movie using release name."));
|
||||
decision = new DownloadDecision(remoteMovie, new DownloadRejection(DownloadRejectionReason.UnknownMovie, pushedRelease ? "Unknown Movie. Unable to match to existing movie in Library using release title." : "Unknown Movie. Unable to match to correct movie using release title."));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -152,17 +152,18 @@ namespace NzbDrone.Core.Indexers.Newznab
|
||||
}
|
||||
}
|
||||
|
||||
if (SupportsSearch)
|
||||
if (SupportsSearch && searchCriteria.Movie.Year > 0)
|
||||
{
|
||||
chain.AddTier();
|
||||
var queryTitles = TextSearchEngine == "raw" ? searchCriteria.SceneTitles : searchCriteria.CleanSceneTitles;
|
||||
|
||||
foreach (var queryTitle in queryTitles)
|
||||
{
|
||||
var searchQuery = queryTitle;
|
||||
|
||||
if (!Settings.RemoveYear)
|
||||
{
|
||||
searchQuery = $"{searchQuery} {searchCriteria.Movie.Year}";
|
||||
searchQuery += $" {searchCriteria.Movie.Year}";
|
||||
}
|
||||
|
||||
chain.Add(GetPagedRequests(MaxPages,
|
||||
|
||||
@@ -2019,5 +2019,18 @@
|
||||
"NotificationsAppriseSettingsIncludePosterHelpText": "Inclou el pòster al missatge",
|
||||
"CloneImportList": "Clonar llista d'importació",
|
||||
"DefaultNameCopiedImportList": "{name} - Còpia",
|
||||
"ReleaseProfile": "Perfil de llançament"
|
||||
"ReleaseProfile": "Perfil de llançament",
|
||||
"CountMissingMoviesFromLibrary": "{count} pel·lícules que manquen de la biblioteca",
|
||||
"ShowPhysicalReleaseCalendarHelpText": "Mostra els llançaments físics en els esdeveniments del calendari",
|
||||
"CinemaRelease": "Llançament en cinemes",
|
||||
"ShowDigitalRelease": "Mostra la versió digital",
|
||||
"ICalReleaseTypesMoviesHelpText": "Inclou només pel·lícules amb tipus de llançament específics al canal iCal. Si no s'especifica, s'utilitzen totes les opcions.",
|
||||
"ShowDigitalReleaseCalendarHelpText": "Mostra els llançaments digitals en els esdeveniments del calendari",
|
||||
"RemoveRootFolderMoviesMessageText": "Esteu segur que voleu eliminar la carpeta arrel '{path}'? Els fitxers i carpetes no s'eliminaran del disc, i les pel·lícules d'aquesta carpeta arrel no s'eliminaran de {appName}.",
|
||||
"ICalReleaseTypes": "Tipus de llançament",
|
||||
"Keywords": "Paraules clau",
|
||||
"ShowPhysicalRelease": "Mostra la versió física",
|
||||
"ShowCinemaRelease": "Mostra el llançament del cinema",
|
||||
"ShowCinemaReleaseCalendarHelpText": "Mostra els llançaments de cinema en els esdeveniments del calendari",
|
||||
"AutoTaggingSpecificationKeyword": "Paraula(es) clau"
|
||||
}
|
||||
|
||||
@@ -1976,5 +1976,32 @@
|
||||
"EditMovieCollectionModalHeader": "Bearbeiten - {title}",
|
||||
"DownloadClientUTorrentProviderMessage": "uTorrent ist dafür bekannt, dass es Kryptominer, Malware und Werbung enthält. Wir empfehlen dringend einen anderen Client zu wählen.",
|
||||
"DefaultNameCopiedImportList": "{name} – Kopieren",
|
||||
"ReleaseProfile": "Release-Profil"
|
||||
"ReleaseProfile": "Release-Profil",
|
||||
"ImportListsTraktSettingsCertificationMovieHelpText": "Filtriere Filme nach einem Zertifikat(NR,G,PG,PG-13,R,NC-17)(Beistrich getrennt)",
|
||||
"ImportListsTraktSettingsRatingMovieHelpText": "Sortiere Filme nach Bewertung (0-100)",
|
||||
"ImportListsTraktSettingsPopularListTypeRecommendedMoviesByWeek": "Empfohlene Filme nach Woche",
|
||||
"ImportListsTraktSettingsPopularListTypeRecommendedMoviesByYear": "Empfohlene Filme nach Jahr",
|
||||
"ImportListsTraktSettingsPopularListTypeTopWatchedMoviesByMonth": "Am meisten geschaute Filme nach Monat",
|
||||
"IndexerSettingsBaseUrl": "Basis-Url",
|
||||
"ImportListsTraktSettingsPopularListTypeTopWatchedMoviesByWeek": "Am meisten geschaute Filme nach Woche",
|
||||
"ImportListsTraktSettingsYearsMovieHelpText": "Filme nach Jahr oder Jahresspanne filtern",
|
||||
"IndexerNewznabSettingsCategoriesHelpText": "Dropdown-Liste, mindestens eine Kategorie muss ausgewählt werden.",
|
||||
"GrabbedAt": "Geholt am {date}",
|
||||
"CinemaRelease": "Kinostart",
|
||||
"FailedAt": "Fehlgeschlagen am {date}",
|
||||
"ImportListsTraktSettingsLimitMovieHelpText": "Die Anzahl der abzurufenden Filme begrenzen",
|
||||
"ImportListsTraktSettingsPopularListTypePopularMovies": "Beliebte Filme",
|
||||
"ImportListsTraktSettingsPopularListTypeRecommendedMoviesByMonth": "Empfohlene Filme nach Monat",
|
||||
"ImportListsTraktSettingsPopularListTypeRecommendedMoviesOfAllTime": "Empfohlene Filme aller Zeiten",
|
||||
"ImportListsTraktSettingsPopularListTypeTopWatchedMoviesByYear": "Am meisten geschaute Filme nach Jahr",
|
||||
"ImportListsTraktSettingsPopularListTypeTopWatchedMoviesOfAllTime": "Am meisten geschaute Filme aller Zeiten",
|
||||
"ImportListsTraktSettingsPopularListTypeTrendingMovies": "Filme im Trend",
|
||||
"IndexerSettingsRemoveYear": "Entferne Jahr vom Suchfilter",
|
||||
"AutoTaggingSpecificationStudio": "Filmstudio(s)",
|
||||
"ImportListsRadarrSettingsApiKeyHelpText": "API-KEY von der {appName} Instanz für den Import von (Radarr 3.0 oder älter)",
|
||||
"ImportListsRadarrSettingsFullUrlHelpText": "URL, mit Port von der {appName} Instanz für den Import von (Radarr 3.0 oder älter)",
|
||||
"AutoTaggingSpecificationKeyword": "Schlüsselwort(e)",
|
||||
"BlocklistedAt": "Zur Sperrliste hinzugefügt am {date}",
|
||||
"CloneImportList": "Import Liste importieren",
|
||||
"FileSize": "Dateigröße"
|
||||
}
|
||||
|
||||
@@ -1328,6 +1328,10 @@
|
||||
"NotificationsPushBulletSettingsDeviceIds": "Device IDs",
|
||||
"NotificationsPushBulletSettingsDeviceIdsHelpText": "List of device IDs (leave blank to send to all devices)",
|
||||
"NotificationsPushcutSettingsApiKeyHelpText": "API Keys can be managed in the Account view of the Pushcut app",
|
||||
"NotificationsPushcutSettingsIncludePoster": "Include Poster",
|
||||
"NotificationsPushcutSettingsIncludePosterHelpText": "Include poster with notification",
|
||||
"NotificationsPushcutSettingsMetadataLinks": "Metadata Links",
|
||||
"NotificationsPushcutSettingsMetadataLinksHelpText": "Add a links to series metadata when sending notifications",
|
||||
"NotificationsPushcutSettingsNotificationName": "Notification Name",
|
||||
"NotificationsPushcutSettingsNotificationNameHelpText": "Notification name from Notifications tab of the Pushcut app",
|
||||
"NotificationsPushcutSettingsTimeSensitive": "Time Sensitive",
|
||||
|
||||
@@ -2021,5 +2021,6 @@
|
||||
"Keywords": "Avainsanat",
|
||||
"CloneImportList": "Monista tuontilista",
|
||||
"DefaultNameCopiedImportList": "{name} (kopio)",
|
||||
"ReleaseProfile": "Julkaisuprofiili"
|
||||
"ReleaseProfile": "Julkaisuprofiili",
|
||||
"CinemaRelease": "Teatterijulkaisu"
|
||||
}
|
||||
|
||||
@@ -668,7 +668,7 @@
|
||||
"RemovedFromTaskQueue": "Supprimé de la file d'attente des tâches",
|
||||
"RemoveCompletedDownloadsHelpText": "Supprimer les téléchargements importés de l'historique du client de téléchargement",
|
||||
"Remove": "Retirer",
|
||||
"ReleaseRejected": "Libération rejetée",
|
||||
"ReleaseRejected": "Release rejetée",
|
||||
"ReleaseDates": "Date de sortie",
|
||||
"RegularExpressionsCanBeTested": "Les expressions régulières peuvent être testées [ici]({url}).",
|
||||
"RefreshMovie": "Actualiser le film",
|
||||
@@ -976,7 +976,7 @@
|
||||
"RemotePathMappingCheckLocalWrongOSPath": "Le client de téléchargement {downloadClientName} met les téléchargements dans {path} mais il ne s'agit pas d'un chemin {osName} valide. Vérifiez les paramètres de votre client de téléchargement.",
|
||||
"RemotePathMappingCheckFilesGenericPermissions": "Le client de téléchargement {downloadClientName} met les téléchargements dans {path} mais {appName} ne peut voir ce répertoire. Il est possible que vous ayez besoin d'ajuster les permissions de ce dossier.",
|
||||
"RemotePathMappingCheckFilesLocalWrongOSPath": "Le client de téléchargement {downloadClientName} met les téléchargements dans {path} mais il ne s'agit pas d'un chemin {osName} valide. Vérifiez les paramètres de votre client de téléchargement.",
|
||||
"BypassDelayIfHighestQualityHelpText": "Ignorer le délai lorsque la libération a la qualité activée la plus élevée dans le profil de qualité avec le protocole préféré",
|
||||
"BypassDelayIfHighestQualityHelpText": "Ignorer le délai lorsque la release a la qualité activée la plus élevée dans le profil de qualité avec le protocole préféré",
|
||||
"ClickToChangeReleaseGroup": "Cliquez pour changer de groupe de diffusion",
|
||||
"AnnouncedMovieDescription": "Le film est annoncé",
|
||||
"Filters": "Filtres",
|
||||
@@ -1116,7 +1116,7 @@
|
||||
"IMDbId": "Identifiant TMDb",
|
||||
"DisabledForLocalAddresses": "Désactivée pour les adresses IP locales",
|
||||
"BypassDelayIfAboveCustomFormatScore": "Ignorer si le score du format personnalisé est supérieur",
|
||||
"BypassDelayIfAboveCustomFormatScoreHelpText": "Activer le contournement lorsque la libération a un score supérieur au score minimum configuré pour le format personnalisé",
|
||||
"BypassDelayIfAboveCustomFormatScoreHelpText": "Activer le contournement lorsque la release a un score supérieur au score minimum configuré pour le format personnalisé",
|
||||
"BypassDelayIfAboveCustomFormatScoreMinimumScore": "Score minimum pour le format personnalisé",
|
||||
"AuthenticationRequired": "Authentification requise",
|
||||
"AuthenticationRequiredHelpText": "Modifier les demandes pour lesquelles l'authentification est requise. Ne rien modifier si vous n'en comprenez pas les risques.",
|
||||
|
||||
@@ -2031,5 +2031,6 @@
|
||||
"CloneImportList": "Копировать список импорта",
|
||||
"DefaultNameCopiedImportList": "{name} - Копировать",
|
||||
"ReleaseProfile": "Профиль релиза",
|
||||
"CountMissingMoviesFromLibrary": "{count} отсутствующих фильмов в библиотеке"
|
||||
"CountMissingMoviesFromLibrary": "{count} отсутствующих фильмов в библиотеке",
|
||||
"RemoveRootFolderMoviesMessageText": "Вы уверены, что хотите удалить корневой каталог '{path}'? Файлы и папки не будут удалены с диска, а фильмы в этом корневом каталоге не будут удалены из {appName}."
|
||||
}
|
||||
|
||||
@@ -1082,5 +1082,6 @@
|
||||
"ImportListsTraktSettingsCertification": "การรับรอง",
|
||||
"ImportListsTraktSettingsGenres": "ประเภท",
|
||||
"ImportListsTraktSettingsRating": "การให้คะแนน",
|
||||
"IndexerHDBitsSettingsMediums": "ปานกลาง"
|
||||
"IndexerHDBitsSettingsMediums": "ปานกลาง",
|
||||
"AddANewPath": "เพิ่มเส้นทางใหม่"
|
||||
}
|
||||
|
||||
@@ -2031,5 +2031,6 @@
|
||||
"CloneImportList": "İçe Aktarma Listesini Klonla",
|
||||
"DefaultNameCopiedImportList": "{name} - Kopyala",
|
||||
"ReleaseProfile": "Sürüm Profili",
|
||||
"CountMissingMoviesFromLibrary": "{count} kitaplıkta eksik film"
|
||||
"CountMissingMoviesFromLibrary": "{count} kitaplıkta eksik film",
|
||||
"RemoveRootFolderMoviesMessageText": "'{path}' kök klasörünü kaldırmak istediğinizden emin misiniz? Dosya ve klasörler diskten silinmez ve bu kök klasördeki filmler {appName} 'dan kaldırılmaz."
|
||||
}
|
||||
|
||||
@@ -1878,7 +1878,7 @@
|
||||
"CustomFormatsSpecificationMinimumSizeHelpText": "必须大于该尺寸才会发布",
|
||||
"CustomFormatsSpecificationMinimumYear": "最小年份",
|
||||
"CustomFormatsSpecificationResolution": "分辨率",
|
||||
"CustomFormatsSpecificationSource": "代码",
|
||||
"CustomFormatsSpecificationSource": "源",
|
||||
"AutoTaggingSpecificationGenre": "类型",
|
||||
"AutoTaggingSpecificationMaximumYear": "最大年份",
|
||||
"Mixed": "混合",
|
||||
|
||||
@@ -210,7 +210,7 @@ namespace NzbDrone.Core.MediaFiles.MediaInfo
|
||||
|
||||
if (videoFormat == "mpeg4" || videoFormat.Contains("msmpeg4"))
|
||||
{
|
||||
if (videoCodecID == "XVID")
|
||||
if (videoCodecID.ToUpperInvariant() == "XVID")
|
||||
{
|
||||
return "XviD";
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace NzbDrone.Core.MediaFiles
|
||||
{
|
||||
public interface IRenameMovieFileService
|
||||
{
|
||||
List<RenameMovieFilePreview> GetRenamePreviews(int movieId);
|
||||
List<RenameMovieFilePreview> GetRenamePreviews(List<int> movieIds);
|
||||
}
|
||||
|
||||
public class RenameMovieFileService : IRenameMovieFileService,
|
||||
@@ -49,12 +49,18 @@ namespace NzbDrone.Core.MediaFiles
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public List<RenameMovieFilePreview> GetRenamePreviews(int movieId)
|
||||
public List<RenameMovieFilePreview> GetRenamePreviews(List<int> movieIds)
|
||||
{
|
||||
var movie = _movieService.GetMovie(movieId);
|
||||
var file = _mediaFileService.GetFilesByMovie(movieId);
|
||||
var movies = _movieService.GetMovies(movieIds);
|
||||
var movieFiles = _mediaFileService.GetFilesByMovies(movieIds).ToLookup(f => f.MovieId);
|
||||
|
||||
return GetPreviews(movie, file).OrderByDescending(m => m.MovieId).ToList(); // TODO: Would really like to not have these be lists
|
||||
return movies.SelectMany(movie =>
|
||||
{
|
||||
var files = movieFiles[movie.Id].ToList();
|
||||
|
||||
return GetPreviews(movie, files);
|
||||
})
|
||||
.ToList();
|
||||
}
|
||||
|
||||
private IEnumerable<RenameMovieFilePreview> GetPreviews(Movie movie, List<MovieFile> files)
|
||||
|
||||
16
src/NzbDrone.Core/Notifications/NotificationMetadataLink.cs
Normal file
16
src/NzbDrone.Core/Notifications/NotificationMetadataLink.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
namespace NzbDrone.Core.Notifications
|
||||
{
|
||||
public class NotificationMetadataLink
|
||||
{
|
||||
public MetadataLinkType? Type { get; set; }
|
||||
public string Label { get; set; }
|
||||
public string Link { get; set; }
|
||||
|
||||
public NotificationMetadataLink(MetadataLinkType? type, string label, string link)
|
||||
{
|
||||
Type = type;
|
||||
Label = label;
|
||||
Link = link;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
using System.Collections.Generic;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Movies;
|
||||
|
||||
namespace NzbDrone.Core.Notifications;
|
||||
|
||||
public static class NotificationMetadataLinkGenerator
|
||||
{
|
||||
public static List<NotificationMetadataLink> GenerateLinks(Movie movie, IEnumerable<int> metadataLinks)
|
||||
{
|
||||
var links = new List<NotificationMetadataLink>();
|
||||
|
||||
if (movie == null)
|
||||
{
|
||||
return links;
|
||||
}
|
||||
|
||||
foreach (var type in metadataLinks)
|
||||
{
|
||||
var linkType = (MetadataLinkType)type;
|
||||
|
||||
if (linkType == MetadataLinkType.Imdb && movie.ImdbId.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
links.Add(new NotificationMetadataLink(MetadataLinkType.Imdb, "IMDb", $"https://www.imdb.com/title/{movie.ImdbId}"));
|
||||
}
|
||||
|
||||
if (linkType == MetadataLinkType.Tmdb && movie.TmdbId > 0)
|
||||
{
|
||||
links.Add(new NotificationMetadataLink(MetadataLinkType.Tmdb, "TMDb", $"https://www.themoviedb.org/movie/{movie.TmdbId}"));
|
||||
}
|
||||
}
|
||||
|
||||
return links;
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using FluentValidation.Results;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.MediaCover;
|
||||
using NzbDrone.Core.Movies;
|
||||
|
||||
namespace NzbDrone.Core.Notifications.Pushcut
|
||||
@@ -30,47 +31,57 @@ namespace NzbDrone.Core.Notifications.Pushcut
|
||||
|
||||
public override void OnGrab(GrabMessage grabMessage)
|
||||
{
|
||||
_proxy.SendNotification(MOVIE_GRABBED_TITLE, grabMessage?.Message, Settings);
|
||||
_proxy.SendNotification(MOVIE_GRABBED_TITLE, grabMessage?.Message, GetPosterUrl(grabMessage.Movie), GetLinks(grabMessage.Movie), Settings);
|
||||
}
|
||||
|
||||
public override void OnDownload(DownloadMessage downloadMessage)
|
||||
{
|
||||
_proxy.SendNotification(downloadMessage.OldMovieFiles.Any() ? MOVIE_UPGRADED_TITLE : MOVIE_DOWNLOADED_TITLE, downloadMessage.Message, Settings);
|
||||
_proxy.SendNotification(downloadMessage.OldMovieFiles.Any() ? MOVIE_UPGRADED_TITLE : MOVIE_DOWNLOADED_TITLE, downloadMessage.Message, GetPosterUrl(downloadMessage.Movie), GetLinks(downloadMessage.Movie), Settings);
|
||||
}
|
||||
|
||||
public override void OnMovieAdded(Movie movie)
|
||||
{
|
||||
_proxy.SendNotification(MOVIE_ADDED_TITLE, $"{movie.Title} added to library", Settings);
|
||||
_proxy.SendNotification(MOVIE_ADDED_TITLE, $"{movie.Title} added to library", GetPosterUrl(movie), GetLinks(movie), Settings);
|
||||
}
|
||||
|
||||
public override void OnMovieFileDelete(MovieFileDeleteMessage deleteMessage)
|
||||
{
|
||||
_proxy.SendNotification(MOVIE_FILE_DELETED_TITLE, deleteMessage.Message, Settings);
|
||||
_proxy.SendNotification(MOVIE_FILE_DELETED_TITLE, deleteMessage.Message, GetPosterUrl(deleteMessage.Movie), GetLinks(deleteMessage.Movie), Settings);
|
||||
}
|
||||
|
||||
public override void OnMovieDelete(MovieDeleteMessage deleteMessage)
|
||||
{
|
||||
_proxy.SendNotification(MOVIE_DELETED_TITLE, deleteMessage.Message, Settings);
|
||||
_proxy.SendNotification(MOVIE_DELETED_TITLE, deleteMessage.Message, GetPosterUrl(deleteMessage.Movie), GetLinks(deleteMessage.Movie), Settings);
|
||||
}
|
||||
|
||||
public override void OnHealthIssue(HealthCheck.HealthCheck healthCheck)
|
||||
{
|
||||
_proxy.SendNotification(HEALTH_ISSUE_TITLE_BRANDED, healthCheck.Message, Settings);
|
||||
_proxy.SendNotification(HEALTH_ISSUE_TITLE_BRANDED, healthCheck.Message, null, new List<NotificationMetadataLink>(), Settings);
|
||||
}
|
||||
|
||||
public override void OnHealthRestored(HealthCheck.HealthCheck previousCheck)
|
||||
{
|
||||
_proxy.SendNotification(HEALTH_RESTORED_TITLE_BRANDED, $"The following issue is now resolved: {previousCheck.Message}", Settings);
|
||||
_proxy.SendNotification(HEALTH_RESTORED_TITLE_BRANDED, $"The following issue is now resolved: {previousCheck.Message}", null, new List<NotificationMetadataLink>(), Settings);
|
||||
}
|
||||
|
||||
public override void OnApplicationUpdate(ApplicationUpdateMessage updateMessage)
|
||||
{
|
||||
_proxy.SendNotification(APPLICATION_UPDATE_TITLE_BRANDED, updateMessage.Message, Settings);
|
||||
_proxy.SendNotification(APPLICATION_UPDATE_TITLE_BRANDED, updateMessage.Message, null, new List<NotificationMetadataLink>(), Settings);
|
||||
}
|
||||
|
||||
public override void OnManualInteractionRequired(ManualInteractionRequiredMessage manualInteractionRequiredMessage)
|
||||
{
|
||||
_proxy.SendNotification(MANUAL_INTERACTION_REQUIRED_TITLE_BRANDED, manualInteractionRequiredMessage.Message, Settings);
|
||||
_proxy.SendNotification(MANUAL_INTERACTION_REQUIRED_TITLE_BRANDED, manualInteractionRequiredMessage.Message, null, new List<NotificationMetadataLink>(), Settings);
|
||||
}
|
||||
|
||||
private string GetPosterUrl(Movie movie)
|
||||
{
|
||||
return movie.MovieMetadata.Value.Images.FirstOrDefault(x => x.CoverType == MediaCoverTypes.Poster)?.RemoteUrl;
|
||||
}
|
||||
|
||||
private List<NotificationMetadataLink> GetLinks(Movie movie)
|
||||
{
|
||||
return NotificationMetadataLinkGenerator.GenerateLinks(movie, Settings.MetadataLinks);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace NzbDrone.Core.Notifications.Pushcut
|
||||
{
|
||||
public class PushcutPayload
|
||||
@@ -5,5 +7,13 @@ namespace NzbDrone.Core.Notifications.Pushcut
|
||||
public string Title { get; set; }
|
||||
public string Text { get; set; }
|
||||
public bool? IsTimeSensitive { get; set; }
|
||||
public string Image { get; set; }
|
||||
public List<PushcutAction> Actions;
|
||||
}
|
||||
|
||||
public class PushcutAction
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string Url { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace NzbDrone.Core.Notifications.Pushcut
|
||||
{
|
||||
public interface IPushcutProxy
|
||||
{
|
||||
void SendNotification(string title, string message, PushcutSettings settings);
|
||||
void SendNotification(string title, string message, string posterUrl, List<NotificationMetadataLink> links, PushcutSettings settings);
|
||||
ValidationFailure Test(PushcutSettings settings);
|
||||
}
|
||||
|
||||
@@ -29,20 +29,37 @@ namespace NzbDrone.Core.Notifications.Pushcut
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public void SendNotification(string title, string message, PushcutSettings settings)
|
||||
public void SendNotification(string title, string message, string posterUrl, List<NotificationMetadataLink> links, PushcutSettings settings)
|
||||
{
|
||||
if (settings == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var request = new HttpRequestBuilder("https://api.pushcut.io/v1/notifications/{notificationName}")
|
||||
.SetSegment("notificationName", settings?.NotificationName)
|
||||
.SetHeader("API-Key", settings?.ApiKey)
|
||||
.Accept(HttpAccept.Json)
|
||||
.Build();
|
||||
|
||||
var payload = new PushcutPayload
|
||||
{
|
||||
Title = title,
|
||||
Text = message,
|
||||
IsTimeSensitive = settings?.TimeSensitive
|
||||
IsTimeSensitive = settings?.TimeSensitive,
|
||||
Image = settings.IncludePoster ? posterUrl : null,
|
||||
Actions = new List<PushcutAction>()
|
||||
};
|
||||
|
||||
foreach (var link in links)
|
||||
{
|
||||
payload.Actions.Add(new PushcutAction
|
||||
{
|
||||
Name = link.Label,
|
||||
Url = link.Link
|
||||
});
|
||||
}
|
||||
|
||||
request.Method = HttpMethod.Post;
|
||||
request.Headers.ContentType = "application/json";
|
||||
request.SetContent(payload.ToJson());
|
||||
@@ -64,7 +81,7 @@ namespace NzbDrone.Core.Notifications.Pushcut
|
||||
{
|
||||
const string title = "Radarr Test Title";
|
||||
const string message = "Success! You have properly configured your Pushcut notification settings.";
|
||||
SendNotification(title, message, settings);
|
||||
SendNotification(title, message, null, new List<NotificationMetadataLink>(), settings);
|
||||
}
|
||||
catch (PushcutException pushcutException) when (pushcutException.InnerException is HttpException httpException)
|
||||
{
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using FluentValidation;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using NzbDrone.Core.Validation;
|
||||
@@ -15,7 +16,7 @@ namespace NzbDrone.Core.Notifications.Pushcut
|
||||
|
||||
public class PushcutSettings : NotificationSettingsBase<PushcutSettings>
|
||||
{
|
||||
private static readonly PushcutSettingsValidator Validator = new ();
|
||||
private static readonly PushcutSettingsValidator Validator = new PushcutSettingsValidator();
|
||||
|
||||
[FieldDefinition(0, Label = "NotificationsPushcutSettingsNotificationName", Type = FieldType.Textbox, HelpText = "NotificationsPushcutSettingsNotificationNameHelpText")]
|
||||
public string NotificationName { get; set; }
|
||||
@@ -26,6 +27,12 @@ namespace NzbDrone.Core.Notifications.Pushcut
|
||||
[FieldDefinition(2, Label = "NotificationsPushcutSettingsTimeSensitive", Type = FieldType.Checkbox, HelpText = "NotificationsPushcutSettingsTimeSensitiveHelpText")]
|
||||
public bool TimeSensitive { get; set; }
|
||||
|
||||
[FieldDefinition(3, Label = "NotificationsPushcutSettingsIncludePoster", Type = FieldType.Checkbox, HelpText = "NotificationsPushcutSettingsIncludePosterHelpText")]
|
||||
public bool IncludePoster { get; set; }
|
||||
|
||||
[FieldDefinition(4, Label = "NotificationsPushcutSettingsMetadataLinks", Type = FieldType.Select, SelectOptions = typeof(MetadataLinkType), HelpText = "NotificationsPushcutSettingsMetadataLinksHelpText")]
|
||||
public IEnumerable<int> MetadataLinks { get; set; } = new List<int>();
|
||||
|
||||
public override NzbDroneValidationResult Validate()
|
||||
{
|
||||
return new NzbDroneValidationResult(Validator.Validate(this));
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="6.0.35" />
|
||||
<PackageReference Include="Microsoft.Data.SqlClient" Version="2.1.7" />
|
||||
<PackageReference Include="Npgsql" Version="7.0.10" />
|
||||
<PackageReference Include="Polly" Version="8.5.2" />
|
||||
<PackageReference Include="Polly" Version="8.6.0" />
|
||||
<PackageReference Include="Servarr.FFMpegCore" Version="4.7.0-26" />
|
||||
<PackageReference Include="Servarr.FFprobe" Version="5.1.4.112" />
|
||||
<PackageReference Include="System.Memory" Version="4.6.3" />
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace Radarr.Api.V3.ImportLists
|
||||
.SetValidator(importListExclusionExistsValidator);
|
||||
|
||||
SharedValidator.RuleFor(c => c.MovieTitle).NotEmpty();
|
||||
SharedValidator.RuleFor(c => c.MovieYear).GreaterThan(0);
|
||||
SharedValidator.RuleFor(c => c.MovieYear).GreaterThanOrEqualTo(0);
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
|
||||
@@ -8,6 +8,7 @@ using NzbDrone.Core.Qualities;
|
||||
using Radarr.Api.V3.CustomFormats;
|
||||
using Radarr.Api.V3.Movies;
|
||||
using Radarr.Http;
|
||||
using Radarr.Http.REST;
|
||||
|
||||
namespace Radarr.Api.V3.ManualImport
|
||||
{
|
||||
@@ -37,6 +38,11 @@ namespace Radarr.Api.V3.ManualImport
|
||||
[Consumes("application/json")]
|
||||
public object ReprocessItems([FromBody] List<ManualImportReprocessResource> items)
|
||||
{
|
||||
if (items is { Count: 0 })
|
||||
{
|
||||
throw new BadRequestException("items must be provided");
|
||||
}
|
||||
|
||||
foreach (var item in items)
|
||||
{
|
||||
var processedItem = _manualImportService.ReprocessItem(item.Path, item.DownloadId, item.MovieId, item.ReleaseGroup, item.Quality, item.Languages, item.IndexerFlags);
|
||||
|
||||
@@ -2,6 +2,7 @@ using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using NzbDrone.Core.MediaFiles;
|
||||
using Radarr.Http;
|
||||
using Radarr.Http.REST;
|
||||
|
||||
namespace Radarr.Api.V3.Movies
|
||||
{
|
||||
@@ -16,9 +17,14 @@ namespace Radarr.Api.V3.Movies
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public List<RenameMovieResource> GetMovies(int movieId)
|
||||
public List<RenameMovieResource> GetMovies([FromQuery(Name = "movieId")] List<int> movieIds)
|
||||
{
|
||||
return _renameMovieFileService.GetRenamePreviews(movieId).ToResource();
|
||||
if (movieIds is not { Count: not 0 })
|
||||
{
|
||||
throw new BadRequestException("movieId must be provided");
|
||||
}
|
||||
|
||||
return _renameMovieFileService.GetRenamePreviews(movieIds).ToResource();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7333,8 +7333,11 @@
|
||||
"name": "movieId",
|
||||
"in": "query",
|
||||
"schema": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user