using System; using System.Collections.Generic; using System.Collections.Specialized; using FluentValidation.Results; using NLog; using NzbDrone.Common.Disk; using NzbDrone.Common.Extensions; using NzbDrone.Common.Processes; using NzbDrone.Core.HealthCheck; using NzbDrone.Core.ThingiProvider; using NzbDrone.Core.Validation; namespace NzbDrone.Core.Notifications.CustomScript { public class CustomScript : NotificationBase { private readonly IDiskProvider _diskProvider; private readonly IProcessProvider _processProvider; private readonly Logger _logger; public CustomScript(IDiskProvider diskProvider, IProcessProvider processProvider, Logger logger) { _diskProvider = diskProvider; _processProvider = processProvider; _logger = logger; } public override string Name => "Custom Script"; public override string Link => "https://wiki.servarr.com/Prowlarr_Settings#Connections"; public override ProviderMessage Message => new ProviderMessage("Testing will execute the script with the EventType set to Test, ensure your script handles this correctly", ProviderMessageType.Warning); public override void OnHealthIssue(HealthCheck.HealthCheck healthCheck) { var environmentVariables = new StringDictionary(); environmentVariables.Add("Prowlarr_EventType", "HealthIssue"); environmentVariables.Add("Prowlarr_Health_Issue_Level", Enum.GetName(typeof(HealthCheckResult), healthCheck.Type)); environmentVariables.Add("Prowlarr_Health_Issue_Message", healthCheck.Message); environmentVariables.Add("Prowlarr_Health_Issue_Type", healthCheck.Source.Name); environmentVariables.Add("Prowlarr_Health_Issue_Wiki", healthCheck.WikiUrl.ToString() ?? string.Empty); ExecuteScript(environmentVariables); } public override ValidationResult Test() { var failures = new List(); if (!_diskProvider.FileExists(Settings.Path)) { failures.Add(new NzbDroneValidationFailure("Path", "File does not exist")); } foreach (var systemFolder in SystemFolders.GetSystemFolders()) { if (systemFolder.IsParentPath(Settings.Path)) { failures.Add(new NzbDroneValidationFailure("Path", $"Must not be a descendant of '{systemFolder}'")); } } if (failures.Empty()) { try { var environmentVariables = new StringDictionary(); environmentVariables.Add("Prowlarr_EventType", "Test"); var processOutput = ExecuteScript(environmentVariables); if (processOutput.ExitCode != 0) { failures.Add(new NzbDroneValidationFailure(string.Empty, $"Script exited with code: {processOutput.ExitCode}")); } } catch (Exception ex) { _logger.Error(ex); failures.Add(new NzbDroneValidationFailure(string.Empty, ex.Message)); } } return new ValidationResult(failures); } private ProcessOutput ExecuteScript(StringDictionary environmentVariables) { _logger.Debug("Executing external script: {0}", Settings.Path); var processOutput = _processProvider.StartAndCapture(Settings.Path, Settings.Arguments, environmentVariables); _logger.Debug("Executed external script: {0} - Status: {1}", Settings.Path, processOutput.ExitCode); _logger.Debug("Script Output: \r\n{0}", string.Join("\r\n", processOutput.Lines)); return processOutput; } private bool ValidatePathParent(string possibleParent, string path) { return possibleParent.IsParentPath(path); } } }