Public/QualityProfile/New-SonarrQualityProfile.ps1
|
function New-SonarrQualityProfile { <# .SYNOPSIS Creates a new quality profile in Sonarr. .DESCRIPTION Creates a new quality profile in Sonarr. The allowed qualities are specified by name, e.g. 'WEBDL-720p'. The profile is built from Sonarr's own quality profile schema, so the quality ordering and the default quality groupings (such as the 'WEB 720p' group that contains WEBDL-720p and WEBRip-720p) are preserved exactly as Sonarr defines them. Only the qualities named in -AllowedQualities are enabled; any group containing at least one enabled quality is itself enabled. .PARAMETER Name The name of the quality profile to create. .PARAMETER AllowedQualities The names of the qualities to allow in the profile (e.g. 'HDTV-720p', 'WEBDL-1080p', 'Bluray-1080p'). Use Get-SonarrQualityDefinition to see the available quality names. .PARAMETER Cutoff The name of the cutoff quality. Sonarr will stop upgrading once a release of this quality (or better) has been downloaded. Must be one of the allowed qualities. If not specified, the highest ranked of the allowed qualities is used. Where the cutoff quality belongs to a quality group, the group is used as the cutoff, as required by the Sonarr API. .PARAMETER UpgradeAllowed If specified, Sonarr will upgrade already downloaded episodes to better qualities (up to the cutoff). .PARAMETER MinFormatScore The minimum custom format score required for a release to be accepted. Defaults to 0. .PARAMETER CutoffFormatScore The custom format score at which Sonarr stops upgrading. Defaults to 0. .PARAMETER MinUpgradeFormatScore The minimum custom format score improvement required for an upgrade. Defaults to 1. .PARAMETER FormatItems An optional array of custom format score items, each with 'format' (custom format ID) and 'score' properties, e.g. @(@{ format = 3; score = 10 }). .EXAMPLE New-SonarrQualityProfile -Name '720-WEBDL' -AllowedQualities 'WEBDL-720p' .EXAMPLE New-SonarrQualityProfile -Name 'HD' -AllowedQualities 'WEBDL-720p', 'WEBDL-1080p' -Cutoff 'WEBDL-1080p' -UpgradeAllowed .EXAMPLE New-SonarrQualityProfile -Name 'SD Only' -AllowedQualities 'SDTV' -WhatIf .NOTES Use Get-SonarrQualityProfile to see existing quality profiles and Get-SonarrQualityDefinition to see the available quality names. #> [CmdletBinding(SupportsShouldProcess)] param( [Parameter(Mandatory = $true)] [String]$Name, [Parameter(Mandatory = $true)] [ArgumentCompleter({ param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters) try { Get-SonarrQualityDefinition | Where-Object { $_.quality.name -like "$wordToComplete*" } | Sort-Object -Property weight | ForEach-Object { [System.Management.Automation.CompletionResult]::new("'$($_.quality.name)'", $_.quality.name, 'ParameterValue', "Quality ID: $($_.quality.id)") } } catch {} })] [String[]]$AllowedQualities, [Parameter(Mandatory = $false)] [ArgumentCompleter({ param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters) try { # Only offer qualities that have been listed in -AllowedQualities, where that is already known: $Candidates = Get-SonarrQualityDefinition | Sort-Object -Property weight if($fakeBoundParameters.ContainsKey('AllowedQualities')) { $Candidates = $Candidates | Where-Object { $_.quality.name -in $fakeBoundParameters['AllowedQualities'] } } $Candidates | Where-Object { $_.quality.name -like "$wordToComplete*" } | ForEach-Object { [System.Management.Automation.CompletionResult]::new("'$($_.quality.name)'", $_.quality.name, 'ParameterValue', "Quality ID: $($_.quality.id)") } } catch {} })] [String]$Cutoff, [Parameter(Mandatory = $false)] [Switch]$UpgradeAllowed, [Parameter(Mandatory = $false)] [Int]$MinFormatScore = 0, [Parameter(Mandatory = $false)] [Int]$CutoffFormatScore = 0, [Parameter(Mandatory = $false)] [Int]$MinUpgradeFormatScore = 1, [Parameter(Mandatory = $false)] [Object[]]$FormatItems = @() ) #################################################################################################### #Region Import configuration try { Import-Configuration -ErrorAction Stop } catch { throw $_ } #EndRegion #################################################################################################### #Region Check if a profile with the same name already exists Write-Verbose -Message "Checking if a quality profile named '$Name' already exists" try { $Existing = Get-SonarrQualityProfile -Name $Name -ErrorAction Stop if($Existing) { throw "A quality profile named '$Name' already exists (ID: $($Existing.id))." } } catch { throw $_ } #EndRegion #################################################################################################### #Region Validate the supplied qualities against Sonarr's quality definitions try { $QualityDefinitions = Get-SonarrQualityDefinition -ErrorAction Stop if(!$QualityDefinitions) { throw "Could not retrieve quality definitions from Sonarr." } $QualityNames = ($QualityDefinitions | Sort-Object -Property weight).quality.name foreach($Quality in $AllowedQualities) { if($Quality -notin $QualityNames) { throw "Unknown quality '$Quality'. Valid qualities are: $($QualityNames -join ', ')" } } if($PSBoundParameters.ContainsKey('Cutoff') -and $Cutoff -notin $AllowedQualities) { throw "The cutoff quality '$Cutoff' must be one of the allowed qualities." } } catch { throw $_ } #EndRegion #################################################################################################### #Region Build the request body from Sonarr's quality profile schema # The schema gives us every quality in Sonarr's preferred order, along with the default quality groups # (e.g. 'WEB 720p' contains both WEBDL-720p and WEBRip-720p). Building on top of it means the profile we # create matches the structure Sonarr's own UI produces. try { $Body = Invoke-SonarrRequest -Path '/qualityprofile/schema' -Method GET -SuppressWhatIf -ErrorAction Stop if(!$Body -or !$Body.items) { throw "Could not retrieve the quality profile schema from Sonarr." } # Flag the requested qualities as allowed. A group is allowed if any of its members are, and the ID used # to refer to a grouped quality for cutoff purposes is the group's ID, not the quality's own ID: $CutoffIds = @{} $AllowedInSchemaOrder = [System.Collections.Generic.List[String]]::new() foreach($Item in $Body.items) { if($Item.items) { # A quality group: foreach($Member in $Item.items) { $Member.allowed = ($Member.quality.name -in $AllowedQualities) if($Member.allowed) { $CutoffIds[$Member.quality.name] = $Item.id $AllowedInSchemaOrder.Add($Member.quality.name) } } $Item.allowed = [Bool]($Item.items | Where-Object { $_.allowed }) } else { # A standalone quality: $Item.allowed = ($Item.quality.name -in $AllowedQualities) if($Item.allowed) { $CutoffIds[$Item.quality.name] = $Item.quality.id $AllowedInSchemaOrder.Add($Item.quality.name) } } } # Sanity check that every requested quality was found in the schema: $Missing = $AllowedQualities | Where-Object { !$CutoffIds.ContainsKey($_) } if($Missing) { throw "The following qualities were not present in Sonarr's quality profile schema: $($Missing -join ', ')" } # Where no cutoff was given, use the highest ranked allowed quality. The schema lists items from lowest # to highest quality, so that is simply the last allowed one: if(!$PSBoundParameters.ContainsKey('Cutoff')) { $Cutoff = $AllowedInSchemaOrder[-1] Write-Verbose -Message "No cutoff specified, using the highest allowed quality: '$Cutoff'" } $Body.name = $Name $Body.upgradeAllowed = [Bool]$UpgradeAllowed $Body.cutoff = $CutoffIds[$Cutoff] $Body.minFormatScore = $MinFormatScore $Body.cutoffFormatScore = $CutoffFormatScore $Body.minUpgradeFormatScore = $MinUpgradeFormatScore $Body.formatItems = @($FormatItems) } catch { throw $_ } #EndRegion #################################################################################################### #Region make the main request if($PSCmdlet.ShouldProcess("Quality profile '$Name' (allowing: $($AllowedQualities -join ', '); cutoff: $Cutoff)", "Create")) { Write-Verbose -Message "Creating quality profile '$Name' in Sonarr" try { $Result = Invoke-SonarrRequest -Path '/qualityprofile' -Method POST -Body $Body -ErrorAction Stop return $Result } catch { throw $_ } } #EndRegion } |