PSSonarr.psm1
function Add-SonarrSeries { <# .SYNOPSIS Add a series to Sonarr by IMDB, TMDB, or TVDB ID. .SYNTAX Add-SonarrSeries -IMDBID <String> -QualityProfileId <Int32> [-MonitorOption <String>] [-Search] [<CommonParameters>] Add-SonarrSeries -TMDBID <String> -QualityProfileId <Int32> [-MonitorOption <String>] [-Search] [<CommonParameters>] Add-SonarrSeries -TVDBID <String> -QualityProfileId <Int32> [-MonitorOption <String>] [-Search] [<CommonParameters>] .DESCRIPTION Adds a series to Sonarr using external database IDs. The function will search for the series using the provided ID, then add it to Sonarr with the specified quality profile and monitoring options. .PARAMETER IMDBID The IMDB ID of the series to add. Can include or exclude the 'tt' prefix. .PARAMETER TMDBID The TMDB (The Movie Database) ID of the series to add. .PARAMETER TVDBID The TVDB (TheTVDB) ID of the series to add. .PARAMETER QualityProfileId The ID of the quality profile to assign to the series. .PARAMETER MonitorOption The monitoring option for the series. Valid values are: 'all', 'firstSeason', 'lastSeason', 'future', 'missing', 'existing', 'recent', 'pilot', 'monitorSpecials', 'unmonitorSpecials', 'none'. Defaults to 'all'. .PARAMETER Search If specified, initiates a search for missing episodes after adding the series. .EXAMPLE Add-SonarrSeries -IMDBID 'tt0944947' -QualityProfileId 1 -MonitorOption 'all' -Search .EXAMPLE Add-SonarrSeries -TVDBID '121361' -QualityProfileId 2 -MonitorOption 'future' .NOTES The series must exist in the external database (IMDB, TMDB, or TVDB) and be findable through Sonarr's lookup service. #> [CmdletBinding()] param( [Parameter(Mandatory = $true, ParameterSetName = 'IMDB')] [ValidatePattern('^(tt)?\d{5,9}$')] [String]$IMDBID, [Parameter(Mandatory = $true, ParameterSetName = 'TMDB')] [ValidatePattern('^\d{1,9}$')] [String]$TMDBID, [Parameter(Mandatory = $true, ParameterSetName = 'TVDB')] [String]$TVDBID, [Parameter(Mandatory = $true)] [int] $QualityProfileId, [Parameter(Mandatory = $false)] [ValidateSet('all', 'firstSeason', 'lastSeason', 'future', 'missing', 'existing', 'recent', 'pilot', 'monitorSpecials', 'unmonitorSpecials', 'none')] $MonitorOption = 'all', [Parameter(Mandatory = $false)] [Switch]$Search ) #################################################################################################### #Region Import configuration try { Import-Configuration -ErrorAction Stop } catch { throw $_ } #EndRegion #################################################################################################### # If using IMDB, ensure the ID is in the correct format if($ParameterSetName -eq 'IMDBID' -and $IMDBID -notmatch '^tt') { $IMDBID = 'tt' + $IMDBID } #################################################################################################### #Region Check if already in Sonarr before attempting an addition Write-Verbose -Message "Checking if the series already exists" try { if($IMDBID) { $Series = Get-SonarrSeries -IMDBID $IMDBID -ErrorAction Stop } elseif($TMDBID) { $Series = Get-SonarrSeries -TMDBID $TMDBID -ErrorAction Stop } elseif($TVDBID) { $Series = Get-SonarrSeries -TVDBID $TVDBID -ErrorAction Stop } if($Series) { Write-Warning "Series already exists in Sonarr!" return } } catch { throw $_ } #EndRegion #################################################################################################### #Region Define the path, parameters, headers and URI try { $Path = '/series/lookup' if($TVDBID) { $Params = @{ term = "tvdb%3A$($TVDBID)" } } elseif($IMDBID) { $Params = @{ term = "imdb%3A$($IMDBID)" } } # Generate the headers and URI $Headers = Get-Headers $Uri = Get-APIUri -RestEndpoint $Path -Params $Params } catch { throw $_ } #EndRegion #################################################################################################### #Region Search for the series (we need to get the data before adding it) Write-Verbose -Message "Using Sonarr lookup service to find the series" try { if($IMDBID) { $Series = Search-SonarrSeries -IMDBID $IMDBID -ErrorAction Stop } elseif($TMDBID) { $Series = Search-SonarrSeries -TMDBID $TMDBID -ErrorAction Stop } elseif($TVDBID) { $Series = Search-SonarrSeries -TVDBID $TVDBID -ErrorAction Stop } if(!$Series) { throw "Could not find the series to add" } } catch { throw $_ } #EndRegion ############################################################################# #Region Append data try { $Series | Add-Member -MemberType NoteProperty -Name 'qualityProfileId' -Value $QualityProfileId -Force $Series | Add-Member -MemberType NoteProperty -Name 'languageProfileId' -Value 1 -Force $Series | Add-Member -MemberType NoteProperty -Name 'seasonFolder' -Value $True -Force $Series | Add-Member -MemberType NoteProperty -Name 'monitored' -Value $True -Force $Series | Add-Member -MemberType NoteProperty -Name 'rootFolderPath' -Value $Config.RootFolderPath -Force if($Search) { $Series | Add-Member -MemberType NoteProperty -Name 'addOptions' -Value $( [PSCustomObject]@{ monitor = $MonitorOption searchForMissingEpisodes = $true ignoreEpisodesWithFiles = $false ignoreEpisodesWithoutFiles = $false } ) -Force } else { $Series | Add-Member -MemberType NoteProperty -Name 'addOptions' -Value $( [PSCustomObject]@{ monitor = $MonitorOption searchForMissingEpisodes = $false searchForCutoffUnmetEpisodes = $false ignoreEpisodesWithFiles = $false ignoreEpisodesWithoutFiles = $false } ) -Force } } catch { throw $_ } #EndRegion #################################################################################################### #Region Define the path, parameters, headers and URI try { $Data = $Series | ConvertTo-Json -Depth 5 $DataEncoded = ([System.Text.Encoding]::UTF8.GetBytes($Data)) $Headers = Get-Headers $Path = '/series' $Uri = Get-APIUri -RestEndpoint $Path } catch { throw $_ } #EndRegion #################################################################################################### #Region make the main request Write-Verbose "Adding: $Uri" try { Invoke-RestMethod -Uri $Uri -Headers $Headers -Method Post -ContentType "application/json" -Body $DataEncoded -ErrorAction Stop } catch { throw $_ } #EndRegion } function Get-SonarrQualityProfile { <# .SYNOPSIS Retrieves quality profiles from Sonarr. .SYNTAX Get-SonarrQualityProfile [<CommonParameters>] Get-SonarrQualityProfile -Id <String> [<CommonParameters>] Get-SonarrQualityProfile -Name <String> [<CommonParameters>] .DESCRIPTION Retrieves quality profile information from Sonarr. Can return all quality profiles or filter by specific criteria such as ID or name. .PARAMETER Id The quality profile ID to retrieve. .PARAMETER Name The name of the quality profile to retrieve. .EXAMPLE Get-SonarrQualityProfile .EXAMPLE Get-SonarrQualityProfile -Id '1' .EXAMPLE Get-SonarrQualityProfile -Name 'HD-1080p' .NOTES When no parameters are specified, all quality profiles in Sonarr are returned. #> [CmdletBinding(DefaultParameterSetName = 'All')] param( [Parameter(Mandatory = $false, ParameterSetName = 'Id')] [String]$Id, [Parameter(Mandatory = $false, ParameterSetName = 'Name')] [String]$Name ) #################################################################################################### #Region Import configuration try { Import-Configuration -ErrorAction Stop } catch { throw $_ } #EndRegion #################################################################################################### #Region Define the path, parameters, headers and URI try { $Path = '/qualityprofile' if($PSCmdlet.ParameterSetName -eq 'Id' -and $Id) { $Path += "/$Id" } # Generate the headers and URI $Headers = Get-Headers $Uri = Get-APIUri -RestEndpoint $Path -Params $Params } catch { throw $_ } #EndRegion #################################################################################################### #Region make the main request Write-Verbose "Querying: $Uri" try { $Data = Invoke-RestMethod -Uri $Uri -Headers $Headers -Method Get -ContentType 'application/json' -ErrorAction Stop if($Data) { if($Name) { $Data = $Data | Where-Object { $_.name -eq $Name } } return $Data } } catch { throw $_ } } function Get-SonarrSeries { <# .SYNOPSIS Retrieves series from Sonarr. .SYNTAX Get-SonarrSeries [<CommonParameters>] Get-SonarrSeries -Id <String> [<CommonParameters>] Get-SonarrSeries -Name <String> [<CommonParameters>] Get-SonarrSeries -IMDBID <String> [<CommonParameters>] Get-SonarrSeries -TMDBID <String> [<CommonParameters>] Get-SonarrSeries -TVDBID <String> [<CommonParameters>] .DESCRIPTION Retrieves series information from Sonarr. Can return all series or filter by specific criteria such as ID, name, or external database IDs. .PARAMETER Id The Sonarr series ID to retrieve. .PARAMETER Name The name or title of the series to retrieve. Searches both title and originalTitle fields. .PARAMETER IMDBID The IMDB ID of the series to retrieve. Can include or exclude the 'tt' prefix. .PARAMETER TMDBID The TMDB (The Movie Database) ID of the series to retrieve. .PARAMETER TVDBID The TVDB (TheTVDB) ID of the series to retrieve. .EXAMPLE Get-SonarrSeries .EXAMPLE Get-SonarrSeries -Id '1' .EXAMPLE Get-SonarrSeries -Name 'Game of Thrones' .EXAMPLE Get-SonarrSeries -IMDBID 'tt0944947' .NOTES When no parameters are specified, all series in Sonarr are returned. #> [CmdletBinding(DefaultParameterSetName = 'All')] param( [Parameter(Mandatory = $false, ParameterSetName = 'Id')] [String]$Id, [Parameter(Mandatory = $false, ParameterSetName = 'Name')] [Alias('Title')] [String]$Name, [Parameter(Mandatory = $false, ParameterSetName = 'IMDBID')] [ValidatePattern('^(tt)?\d{5,9}$')] [String]$IMDBID, [Parameter(Mandatory = $true, ParameterSetName = 'TMDBID')] [String]$TMDBID, [Parameter(Mandatory = $false, ParameterSetName = 'TVDBID')] [ValidatePattern('^\d{1,9}$')] [String]$TVDBID ) #################################################################################################### #Region Import configuration try { Import-Configuration -ErrorAction Stop } catch { throw $_ } #EndRegion #################################################################################################### # If using IMDB, ensure the ID is in the correct format if($ParameterSetName -eq 'IMDBID' -and $IMDBID -notmatch '^tt') { $IMDBID = 'tt' + $IMDBID } #################################################################################################### #Region Define the path, parameters, headers and URI try { $Path = '/series' if($PSCmdlet.ParameterSetName -eq 'Id' -and $Id) { $Path += "/$Id" } # Generate the headers and URI $Headers = Get-Headers $Uri = Get-APIUri -RestEndpoint $Path -Params $Params } catch { throw $_ } #EndRegion #################################################################################################### #Region make the main request Write-Verbose "Querying: $Uri" try { $Data = Invoke-RestMethod -Uri $Uri -Headers $Headers -Method Get -ContentType 'application/json' -ErrorAction Stop if($Data) { # Filter results based on parameters if specified switch($PSCmdlet.ParameterSetName) { 'Name' { $Data = $Data | Where-Object { $_.title -eq $Name -or $_.originalTitle -eq $Name } } 'IMDBID' { if($IMDBID -notmatch '^tt') { $IMDBID = 'tt' + $IMDBID } $Data = $Data | Where-Object { $_.imdbId -eq "$IMDBID" } } 'TMDBID' { $Data = $Data | Where-Object { $_.tmdbId -eq $TMDBID } } 'TVDBID' { $Data = $Data | Where-Object { $_.tvdbId -eq $TVDBID } } } return $Data } else { Write-Verbose -Message 'No result found.' return } } catch { throw $_ } #EndRegion } function Remove-SonarrSeries { <# .SYNOPSIS Removes a series from Sonarr. .SYNTAX Remove-SonarrSeries -Id <String> [-WhatIf] [-Confirm] [<CommonParameters>] .DESCRIPTION Removes a series from Sonarr using the series ID. This function supports WhatIf and Confirm parameters for safe execution. .PARAMETER Id The Sonarr series ID to remove. Accepts pipeline input by property name. .EXAMPLE Remove-SonarrSeries -Id '123' .EXAMPLE Get-SonarrSeries -Name 'Old Show' | Remove-SonarrSeries .EXAMPLE Remove-SonarrSeries -Id '123' -WhatIf .NOTES This function supports pipeline input and confirmation prompts for safe series removal. #> [CmdletBinding(SupportsShouldProcess)] param( [Parameter(Mandatory, ValueFromPipelineByPropertyName)] [String]$Id ) begin { #################################################################################################### #Region Import configuration try { Import-Configuration -ErrorAction Stop } catch { throw $_ } #EndRegion } process { #################################################################################################### #Region Define the path, parameters, headers and URI try { $Path = '/series/' + $Id $Uri = Get-APIUri -RestEndpoint $Path $Headers = Get-Headers } catch { throw $_ } #EndRegion #################################################################################################### #Region make the main request if($PSCmdlet.ShouldProcess("Series with ID: $Id", "Remove")) { Write-Verbose -Message "Removing series with ID $Id" try { Invoke-RestMethod -Uri $Uri -Headers $Headers -Method Delete -ContentType 'application/json' -ErrorAction Stop } catch { Write-Error "Failed to remove series with ID $Id. Error: $($_.Exception.Message)" } } #EndRegion } } function Search-SonarrSeries { <# .SYNOPSIS Search to find a series in order to add to Sonarr. .SYNTAX Search-SonarrSeries -Name <String> [-ExactMatch] [<CommonParameters>] Search-SonarrSeries -IMDBID <String> [<CommonParameters>] Search-SonarrSeries -TMDBID <String> [<CommonParameters>] Search-SonarrSeries -TVDBID <String> [<CommonParameters>] .DESCRIPTION This uses the lookup service within Sonarr to search for a series by name, TVDB ID, or IMDB ID. It does not search your local Sonarr library, but rather The Movie Database (TMDb). .PARAMETER Name The name of the series to search for. .PARAMETER TMDBID The TMDB ID of the series to search for. .PARAMETER TVDBID The TVDB ID of the series to search for. .PARAMETER IMDBID The IMDB ID of the series to search for. .EXAMPLE Search-SonarrSeries -Name "The Matrix" .NOTES If you have the IMDB ID or TVDB ID of a series, it's better to use this to search. #> [CmdletBinding()] param( [Parameter(Mandatory = $true, ParameterSetName = 'Name')] [String]$Name, [Parameter(Mandatory = $false, ParameterSetName = 'Name')] [Switch]$ExactMatch, [Parameter(Mandatory = $true, ParameterSetName = 'IMDBID')] [ValidatePattern('^(tt)?\d{5,9}$')] [String]$IMDBID, [Parameter(Mandatory = $true, ParameterSetName = 'TMDBID')] [String]$TMDBID, [Parameter(Mandatory = $true, ParameterSetName = 'TVDBID')] [String]$TVDBID ) #################################################################################################### #Region Import configuration try { Import-Configuration -ErrorAction Stop } catch { throw $_ } #EndRegion #################################################################################################### # If using IMDB, ensure the ID is in the correct format if($ParameterSetName -eq 'IMDBID' -and $IMDBID -notmatch '^tt') { $IMDBID = 'tt' + $IMDBID } #################################################################################################### #Region Define the path, parameters, headers and URI try { $Path = "/series/lookup" if($Name) { $Params = @{ term = $Name } } elseif($IMDBID) { $Params = @{ term = "imdb:$($IMDBID)" } } elseif($TMDBID) { $Params = @{ term = "tmdb:$($TMDBID)" } } elseif($TVDBID) { $Params = @{ term = "tvdb:$($TVDBID)" } } else { throw 'You must specify a name, TVDBID, or IMDBID.' } # Generate the headers and URI $Headers = Get-Headers $Uri = Get-APIUri -RestEndpoint $Path -Params $Params } catch { throw $_ } #EndRegion #################################################################################################### #Region make the main request Write-Verbose "Querying: $Uri" try { $Data = Invoke-RestMethod -Uri $Uri -Headers $Headers -Method Get -ContentType 'application/json' -ErrorAction Stop if($Data) { # If ExactMatch is specified, filter the results to only include the exact match if($ExactMatch) { $Data = $Data | Where-Object { $_.title -eq $Name } } return $Data } else { Write-Warning -Message "No series found." return } } catch { throw $_ } #EndRegion } function Set-SonarrConfiguration { <# .SYNOPSIS Sets the configuration for connecting to a Sonarr server instance. .SYNTAX Set-SonarrConfiguration -Server <String> -APIKey <String> -RootFolderPath <String> [-Port <Int32>] [-Protocol <String>] [-APIVersion <Int32>] [-Default <Boolean>] [<CommonParameters>] .DESCRIPTION Saves Sonarr server connection settings including server address, port, API key, and API version to a JSON configuration file. The configuration is stored in the user's home directory under .PSSonarr/PSSonarrConfig.json. .PARAMETER Server The URL or hostname of the Sonarr server (e.g. 'myserver.domain.com') .PARAMETER Port The port number that Sonarr is listening on. Defaults to 8989. .PARAMETER Protocol The protocol to use for connecting to the Sonarr server. Defaults to 'http'. .PARAMETER APIKey The API key from your Sonarr instance. Can be found in Sonarr under Settings > General. .PARAMETER APIVersion The version of the Sonarr API to use. Defaults to 3. .PARAMETER RootFolderPath The root folder path where movies are stored. .PARAMETER Default If set to true, marks this server configuration as the default instance for PSSonarr commands. Defaults to true. .EXAMPLE Set-SonarrConfiguration -Server 'myserver.domain.com' -APIKey 'myapikey' -RootFolderPath 'D:\Movies' .NOTES File: Set-SonarrConfiguration.ps1 The configuration file will be created at $HOME/.PSSonarr/PSSonarrConfig.json #> param ( [Parameter(Mandatory = $true)] [ValidatePattern('^[a-zA-Z0-9.-]+$')] [string]$Server, [Parameter(Mandatory = $false)] [int]$Port = 8989, [Parameter(Mandatory = $false)] [ValidateSet("http", "https")] [string]$Protocol = "http", [Parameter(Mandatory = $true)] [string]$APIKey, [Parameter(Mandatory = $false)] [Int]$APIVersion = "3", [Parameter(Mandatory = $true)] [string]$RootFolderPath, [Parameter(Mandatory = $false)] [bool]$Default = $true ) ############################################################################# #Region Ensure required paths exist and load existing configuration $ConfigDir = Join-Path $HOME ".PSSonarr" if(-not (Test-Path -Path $ConfigDir -PathType Container)) { try { New-Item -Path $ConfigDir -ItemType Directory -ErrorAction Stop | Out-Null } catch { throw $_ } } # Path to the configuration file $ConfigPath = Join-Path $ConfigDir "PSSonarrConfig.json" # If the file exists, load existing data if(Test-Path -Path $ConfigPath -PathType Leaf) { [Array]$ConfigData = Get-Content -Path $ConfigPath | ConvertFrom-Json } else { $ConfigData = @() } #EndRegion ############################################################################# # If the user has passed default as $False, but there is no existing default server (excluding itself) with # default set to $true, then we'll force this server to be the default. if($Default -eq $false -and ($ConfigData | Where-Object { $_.Default -eq $true -and $_.Server -ne $Server }).Count -eq 0) { Write-Warning -Message "No default server found. Forcing this server to be the default." $Default = $true } #################################################################################################### # Set all servers to Default = $false: $ConfigData | ForEach-Object ( { $_.Default = $false } ) $Found = $false foreach($Entry in $ConfigData) { # If the server and port already exist in the configuration, update the rest of the data # that could have changed: if($Entry.Server -eq $Server -and $Entry.Port -eq $Port) { $Entry.Protocol = $Protocol $Entry.APIKey = $APIKey $Entry.APIVersion = $APIVersion $Entry.RootFolderPath = $RootFolderPath $Entry.Default = $Default $Found = $true } } # If we didn't find the server in the configuration, this would be a new entry: if($Found -eq $false) { #Construct an object with the data we want to save $ServerObject = [Ordered]@{ "Server" = $Server "Port" = $Port "Protocol" = $Protocol "APIKey" = $APIKey "APIVersion" = $APIVersion "RootFolderPath" = $RootFolderPath "Default" = $Default } $ConfigData += $ServerObject } #################################################################################################### #Region Convert to JSON and save to file Write-Verbose -Message "Saving configuration to: $ConfigPath" try { # We want to make sure that $ConfigData is always an array before we export it, to ensure we can add # additional servers. Don't pipe $ConfigData directly to ConvertTo-Json, otherwise the first time around # it'll create an object instead of an array. ConvertTo-Json -InputObject $ConfigData -ErrorAction Stop | Set-Content -Path $ConfigPath -Force -ErrorAction Stop } catch { throw $_ } Write-Verbose -Message "Configuration saved successfully to: $ConfigPath" } function Set-SonarrSeasonStatus { <# .SYNOPSIS Sets the monitoring status of a specific season in Sonarr. .SYNTAX Set-SonarrSeasonStatus -Id <Int32> -SeasonNumber <Int32> -Monitored <Boolean> [<CommonParameters>] .DESCRIPTION Updates the monitoring status of a specific season for a series in Sonarr. When a season is monitored, Sonarr will automatically search for and download episodes from that season. When unmonitored, episodes from that season will not be automatically downloaded. .PARAMETER Id The Sonarr series ID containing the season to update. .PARAMETER SeasonNumber The season number to update (e.g., 1 for Season 1, 0 for Specials). .PARAMETER Monitored Boolean value indicating whether the season should be monitored (True) or unmonitored (False). .EXAMPLE Set-SonarrSeasonStatus -Id 123 -SeasonNumber 1 -Monitored $true .EXAMPLE Set-SonarrSeasonStatus -Id 456 -SeasonNumber 3 -Monitored $false .NOTES This function specifically modifies individual season monitoring status within a series. #> [CmdletBinding()] param( [Parameter(Mandatory = $True)] [Int]$Id, [Parameter(Mandatory = $True)] [Int]$SeasonNumber, [Parameter(Mandatory = $True)] [Boolean]$Monitored ) #################################################################################################### #Region Import configuration try { Import-Configuration -ErrorAction Stop } catch { throw $_ } #EndRegion #################################################################################################### #Region Get the series try { $Series = Get-SonarrSeries -Id $Id -ErrorAction Stop if(!$Series) { throw "Series with ID $Id not found." } } catch { throw $_ } #EndRegion #################################################################################################### #Region Define the path, parameters, headers and URI try { if($Series.overview) { $Series.overview = Convert-SmartPunctuation -String $Series.overview } # Set the monitored status ($Series.seasons | Where-Object { $_.seasonNumber -eq $SeasonNumber }).monitored = [bool]$Monitored # Encode the body $BodyJSON = ($Series | ConvertTo-Json -Depth 5) $BodyEncoded = ([System.Text.Encoding]::UTF8.GetBytes($BodyJSON)) $Path = '/series/' + "$Id" # Generate the headers and URI $Headers = Get-Headers $Uri = Get-APIUri -RestEndpoint $Path -Params $Params } catch { throw $_ } #EndRegion #################################################################################################### #Region make the main request Write-Verbose "Querying $Uri" try { Invoke-RestMethod -Uri $Uri -Headers $Headers -Method Put -ContentType 'application/json' -Body $BodyEncoded -ErrorAction Stop } catch { throw $_ } #EndRegion } function Set-SonarrSeriesStatus { <# .SYNOPSIS Sets the monitoring status of a series in Sonarr. .SYNTAX Set-SonarrSeriesStatus -Id <Int32> -SeasonNumber <Int32> -Monitored <Boolean> [<CommonParameters>] .DESCRIPTION Updates the monitoring status of a series in Sonarr. When a series is monitored, Sonarr will automatically search for and download episodes. When unmonitored, episodes will not be automatically downloaded. .PARAMETER Id The Sonarr series ID to update. .PARAMETER SeasonNumber The season number (currently not used in this function - appears to be a parameter naming issue). .PARAMETER Monitored Boolean value indicating whether the series should be monitored (True) or unmonitored (False). .EXAMPLE Set-SonarrSeriesStatus -Id 123 -SeasonNumber 1 -Monitored $true .EXAMPLE Set-SonarrSeriesStatus -Id 456 -SeasonNumber 1 -Monitored $false .NOTES This function modifies the overall series monitoring status, not individual seasons. #> [CmdletBinding()] param( [Parameter(Mandatory = $True)] [Int]$Id, [Parameter(Mandatory = $True)] [Int]$SeasonNumber, [Parameter(Mandatory = $True)] [Boolean]$Monitored ) #################################################################################################### #Region Import configuration try { Import-Configuration -ErrorAction Stop } catch { throw $_ } #EndRegion #################################################################################################### #Region Get the series try { $Series = Get-SonarrSeries -Id $Id -ErrorAction Stop if(!$Series) { throw "Series with ID $Id not found." } } catch { throw $_ } #EndRegion #################################################################################################### #Region Define the path, parameters, headers and URI try { if($Series.overview) { $Series.overview = Convert-SmartPunctuation -String $Series.overview } # Set the monitored status $Series.monitored = [bool]$Monitored # Encode the body $BodyJSON = ($Series | ConvertTo-Json -Depth 5) $BodyEncoded = ([System.Text.Encoding]::UTF8.GetBytes($BodyJSON)) $Path = '/series/' + "$Id" # Generate the headers and URI $Headers = Get-Headers $Uri = Get-APIUri -RestEndpoint $Path -Params $Params } catch { throw $_ } #EndRegion #################################################################################################### #Region make the main request Write-Verbose "Querying $Uri" try { Invoke-RestMethod -Uri $Uri -Headers $Headers -Method Put -ContentType 'application/json' -Body $BodyEncoded -ErrorAction Stop } catch { throw $_ } #EndRegion } function Convert-SmartPunctuation { <# .SYNOPSIS Aims to replace some comment smart characters with their ASCII equivalents. .DESCRIPTION Aims to replace some comment smart characters with their ASCII equivalents. This file needs BOM encoding in order to correctly 'store' the smart characters. .PARAMETER String The string to clean .EXAMPLE Convert-SmartPunctuation "This is a ‘test’" Outputs: This is a 'test' #> [CmdletBinding()] Param ( [Parameter(Mandatory = $true, Position = 0)] [String]$String ) Begin { } Process { $String = $String -replace "’", "'" $String = $String -replace "‘", "'" $String = $String -replace '“', '"' $String = $String -replace '”', '"' $String = $String -replace '–', '-' return $string } End { } } function Get-APIUri { [CmdletBinding()] [OutputType([System.String])] param( [Parameter(Mandatory = $true)] [String] $RestEndpoint, [Parameter(Mandatory = $false)] [System.Collections.IDictionary] $Params ) # If the endpoint starts with /, strip it off: if($RestEndpoint.StartsWith('/')) { $RestEndpoint = $RestEndpoint.Substring(1) } # Join the parameters as key=value pairs, and concatenate them with & if($Params.Count -gt 0) { [String]$ParamString = "?" + (($Params.GetEnumerator() | ForEach-Object { $_.Name + '=' + $_.Value }) -join '&') } else { [String]$ParamString = $Null } return "$($Config.Protocol)://$($Config.Server):$($Config.Port)/api/v$($Config.APIVersion)/$($RestEndpoint)$($ParamString)" } function Get-Headers { [CmdletBinding()] param( ) return @{ 'X-Api-Key' = $Config.APIKey } } function Import-Configuration { [CmdletBinding()] param( ) $FileName = 'PSSonarrConfig.json' $FilePath = "$HOME/.PSSonarr/$FileName" if(Test-Path $FilePath) { try { $Script:Config = Get-Content $FilePath -ErrorAction Stop | ConvertFrom-Json -ErrorAction Stop } catch { throw $_ } # Refine to our default server: $Script:Config = $Script:Config | Where-Object { $_.Default -eq $True } if(!$Script:Config) { throw "No default server found in $FilePath. Please run Set-SonarrConfiguration." } } else { throw "Config file not found at $FilePath. Please run Set-SonarrConfiguration." } } |