1
0
mirror of https://github.com/Radarr/Radarr.git synced 2026-03-05 13:21:25 -05:00

Compare commits

...

16 Commits

Author SHA1 Message Date
Denis Gheorghescu
8bef9b4da7 New:(Pushcut) Improved Notification Details (#10897) 2025-07-19 10:43:18 -04:00
Mark McDowall
787c387036 Return error if Manual Import called without items
(cherry picked from commit 4bdb0408f1bafa38b777a41babb1a775f99a94c1)
2025-07-09 16:19:57 -05:00
bakerboy448
0525256115 Bump version to 5.27.2 2025-07-08 18:37:58 -05:00
bakerboy448
5767e181b7 New: Improve Reject for Unknown Movie Messaging (#11063) 2025-07-08 18:25:51 -05:00
Mark McDowall
1cf3ef5dff New: Improve stored UI settings for multiple instances under the same host
Closes #10671
Fixes #11146

(cherry picked from commit 6677fd11168de6dbf78d03bfedf67b89dfe1df53)
2025-07-08 18:07:52 -05:00
Weblate
b6bad2398c Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: ACHN SYPS <achn.syps@gmail.com>
Co-authored-by: EdiTurn <yyxstter@gmail.com>
Co-authored-by: Hugoren Martinako <aumpfbahn@gmail.com>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: josef <josef.holzapfel@proton.me>
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/ca/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/de/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/th/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/zh_CN/
Translation: Servarr/Radarr
2025-07-08 18:06:46 -05:00
nuxen
16308e4b1c Fixed: xvid not always detected correctly (#11138) 2025-07-07 20:00:13 -05:00
bakerboy448
bd7465fae4 Fixed: Allow Discover Exclusions of Movies without Year (Year 0)
Fixes #11135
2025-06-28 09:07:26 -05:00
Weblate
c0d70485c3 Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: Gallyam Biktashev <gallyamb@gmail.com>
Co-authored-by: GkhnGRBZ <gkhn.gurbuz@hotmail.com>
Co-authored-by: HanaO00 <lwin24452@gmail.com>
Co-authored-by: Oskari Lavinto <olavinto@protonmail.com>
Co-authored-by: Weblate <noreply@weblate.org>
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/fi/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/fr/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/ru/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/tr/
Translation: Servarr/Radarr
2025-06-19 18:20:22 -05:00
Bogdan
c743383912 Fixed: Deleting tags from UI
Fixes #11131
2025-06-16 20:34:00 +03:00
Servarr
d93c1d7808 Automated API Docs update 2025-06-16 20:22:31 +03:00
nuxen
0e2e7e4259 New: Support for multiple movieIds in Rename API endpoint 2025-06-16 19:09:19 +03:00
Bogdan
e6b27512c9 Bump version to 5.27.1 2025-06-15 09:20:29 +03:00
Bogdan
dae5e86b2c Fixed: Skip title searches for Newznab/Torznab indexers when movie year is missing
Prevents useless text searches of `Movie Title 0` when year is missing.

Fixes #10569
2025-06-14 13:20:11 +03:00
Bogdan
71f032d175 Bump Polly to 8.6.0 2025-06-11 23:13:54 +03:00
Bogdan
5a6db29dbd Bump version to 5.27.0 2025-06-11 23:11:20 +03:00
27 changed files with 217 additions and 43 deletions

View File

@@ -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)'

View File

@@ -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]);

View File

@@ -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);

View File

@@ -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
{

View File

@@ -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,

View File

@@ -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"
}

View File

@@ -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"
}

View File

@@ -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",

View File

@@ -2021,5 +2021,6 @@
"Keywords": "Avainsanat",
"CloneImportList": "Monista tuontilista",
"DefaultNameCopiedImportList": "{name} (kopio)",
"ReleaseProfile": "Julkaisuprofiili"
"ReleaseProfile": "Julkaisuprofiili",
"CinemaRelease": "Teatterijulkaisu"
}

View File

@@ -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.",

View File

@@ -2031,5 +2031,6 @@
"CloneImportList": "Копировать список импорта",
"DefaultNameCopiedImportList": "{name} - Копировать",
"ReleaseProfile": "Профиль релиза",
"CountMissingMoviesFromLibrary": "{count} отсутствующих фильмов в библиотеке"
"CountMissingMoviesFromLibrary": "{count} отсутствующих фильмов в библиотеке",
"RemoveRootFolderMoviesMessageText": "Вы уверены, что хотите удалить корневой каталог '{path}'? Файлы и папки не будут удалены с диска, а фильмы в этом корневом каталоге не будут удалены из {appName}."
}

View File

@@ -1082,5 +1082,6 @@
"ImportListsTraktSettingsCertification": "การรับรอง",
"ImportListsTraktSettingsGenres": "ประเภท",
"ImportListsTraktSettingsRating": "การให้คะแนน",
"IndexerHDBitsSettingsMediums": "ปานกลาง"
"IndexerHDBitsSettingsMediums": "ปานกลาง",
"AddANewPath": "เพิ่มเส้นทางใหม่"
}

View File

@@ -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."
}

View File

@@ -1878,7 +1878,7 @@
"CustomFormatsSpecificationMinimumSizeHelpText": "必须大于该尺寸才会发布",
"CustomFormatsSpecificationMinimumYear": "最小年份",
"CustomFormatsSpecificationResolution": "分辨率",
"CustomFormatsSpecificationSource": "代码",
"CustomFormatsSpecificationSource": "",
"AutoTaggingSpecificationGenre": "类型",
"AutoTaggingSpecificationMaximumYear": "最大年份",
"Mixed": "混合",

View File

@@ -210,7 +210,7 @@ namespace NzbDrone.Core.MediaFiles.MediaInfo
if (videoFormat == "mpeg4" || videoFormat.Contains("msmpeg4"))
{
if (videoCodecID == "XVID")
if (videoCodecID.ToUpperInvariant() == "XVID")
{
return "XviD";
}

View File

@@ -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)

View 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;
}
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}
}

View File

@@ -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; }
}
}

View File

@@ -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)
{

View File

@@ -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));

View File

@@ -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" />

View File

@@ -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]

View File

@@ -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);

View File

@@ -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();
}
}
}

View File

@@ -7333,8 +7333,11 @@
"name": "movieId",
"in": "query",
"schema": {
"type": "integer",
"format": "int32"
"type": "array",
"items": {
"type": "integer",
"format": "int32"
}
}
}
],