PSEmby.psm1
<# Code in this file will be added to the beginning of the .psm1. For example, you should place any using statements here. #> Function Add-UriQueryParameters { [cmdletbinding()] param ( [string]$Uri, [hashtable]$Parameters ) $Uri.Trim('?') + '?' + (($Parameters.Keys | ForEach-Object {"$_=$($Parameters[$_] -join ',')"}) -join '&') } Function Get-EmbyItem { [cmdletbinding()] param ( [string]$ParentId, [ValidateSet('Budget','Chapters','DateCreated','Genres','HomePageUrl','IndexOptions', 'MediaStreams','Overview','ParentId','Path','People','ProviderIds', 'PrimaryImageAspectRatio','Revenue','SortName','Studios','Taglines')] [string[]]$Fields, [ValidateSet('AggregateFolder','Audio','BoxSet','Channel','CollectionFolder','Episode', 'Folder','Genre','Movie','MusicAlbum','MusicArtist','MusicGenre','Person','Playlist', 'Season','Series','Studio','Trailer','UserRootFolder','UserView','Video')] [string[]]$IncludeItemTypes, [ValidateSet('AggregateFolder','Audio','BoxSet','Channel','CollectionFolder','Episode', 'Folder','Genre','Movie','MusicAlbum','MusicArtist','MusicGenre','Person','Playlist', 'Season','Series','Studio','Trailer','UserRootFolder','UserView','Video')] [string[]]$ExcludeItemTypes, [bool]$Recursive, [ValidateSet('Ascending','Descending')] [string]$SortOrder, [int]$Limit ) $apiPath = '/emby/items' if ($PSBoundParameters.Keys.Count -gt 0) { $apiPath = Add-UriQueryParameters -Uri $apiPath -Parameters $PSBoundParameters } (Invoke-EmbyApi -Method 'Get' -ApiPath $apiPath).Items } Function Get-EmbyUsers { [cmdletbinding( DefaultParameterSetName = 'All' )] param ( [Parameter( ParameterSetName = 'ById', Mandatory )] [string]$Id, [Parameter( ParameterSetName = 'All' )] [bool]$IsHidden, [Parameter( ParameterSetName = 'All' )] [bool]$IsDisabled ) $apiPath = '/emby/users' if ($PSCmdlet.ParameterSetName -eq 'All' -and $PSBoundParameters.Keys.Count -gt 0) { $apiPath = Add-UriQueryParameters -Uri $apiPath -Parameters $PSBoundParameters } elseif ($PSCmdlet.ParameterSetName -eq 'ById') { $apiPath = "$apiPath/$Id" } Invoke-EmbyApi -Method Get -ApiPath $apiPath } Function Invoke-EmbyApi { [cmdletbinding()] param ( [string]$BaseUri = $config['Servers'][$config['Server']]['BaseUri'], [string]$ApiPath, [ValidateSet('Get','Post')] [string]$Method ) $headers = @{ Accept = 'application/json' } $headers['X-Emby-Token'] = $config['Servers'][$config['Server']]['AccessToken'] $uri = "$BaseUri/$ApiPath" Invoke-RestMethod -Method $Method -Uri $uri -Headers $headers } Function Refresh-EmbyItem { [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseApprovedVerbs", "")] [cmdletbinding()] param ( [Parameter( Mandatory, ValueFromPipelineByPropertyName )] [string]$Id, [bool]$Recursive = $true, [ValidateSet('Default','FullRefresh')] [string]$ImageRefreshMode = 'Default', [ValidateSet('Default','FullRefresh')] [string]$MetadataRefreshMode = 'Default', [bool]$ReplaceAllMetadata = $false, [bool]$ReplaceAllImages = $false ) Begin { } Process { $apiPath = "/emby/items/$id/refresh" if ($PSBoundParameters.Keys.Count -gt 0) { $apiPath = Add-UriQueryParameters -Uri $apiPath -Parameters $PSBoundParameters } Invoke-EmbyApi -Method 'Post' -ApiPath $apiPath } End { } } Function Get-PSEmbyConfig { [cmdletbinding()] param ( [switch]$AsHashtable, [switch]$Silent ) # Test to be sure the config variable exists as expected if ((Get-Variable config -Scope Script -ErrorAction SilentlyContinue) -and $config.psobject.TypeNames[0] -eq 'System.Collections.Hashtable' -and $config.Keys -contains 'Server' -and $config.Keys -contains 'Servers' ) { Write-Verbose '$config exists' # Output the config if (-not ($Silent.IsPresent)) { if ($AsHashtable.IsPresent){ Write-Verbose 'Outputting as hashtable' $config } else { Write-Verbose 'Outputting as json' $config | ConvertTo-Json } } } else { Write-Verbose '$config does not exist' $path = Get-PSEmbyConfigPath if (Test-Path $path) { Write-Verbose 'Get-PSEmbyConfigPath exists' # Import the config $script:config = Get-Content $path | ConvertFrom-Json -AsHashtable } else { Write-Verbose 'Get-PSEmbyConfigPath does not exist' # Create the config New-PSEmbyConfig $params = @{ Silent = $Silent.IsPresent AsHashtable = $AsHashtable.IsPresent } Get-PSEmbyConfig @params } if (-not($Silent.IsPresent)) { if ($AsHashtable.IsPresent){ Write-Verbose 'Outputting as hashtable' $config } else { Write-Verbose 'Outputting as json' $config | ConvertTo-Json } } } } Function Get-PSEmbyConfigPath { Param ( $FileName = 'config.json' ) if ($PSVersionTable.PSVersion.Major -ge 6) { if ($IsLinux) { $saveDir = $env:HOME } elseif ($IsWindows) { $saveDir = $env:USERPROFILE } } else { $saveDir = $env:USERPROFILE } "$saveDir\.psemby\$FileName" } Function Import-PSEmbyConfig { [CmdletBinding()] Param ( ) $script:configPath = "$PSScriptRoot\config.json" $script:config = Get-Content $configPath | ConvertFrom-Json -AsHashtable } Function New-PSEmbyConfig { [cmdletbinding( SupportsShouldProcess, ConfirmImpact = 'None' )] Param ( ) if ($PSCmdlet.ShouldProcess("$PSScriptRoot\config.json")) { $script:config = Get-Content "$PSScriptRoot\config.json" | ConvertFrom-Json -AsHashtable } Save-PSEmbyConfig } Function Pop-PSEmbyConfig { [cmdletbinding()] param ( ) if ($configStack.Count -ge 1) { $script:config = $configStack.Pop() if (-not($DontSave.IsPresent)) { Save-PSEmbyConfig } } else { Write-Warning "There is nothing in the config stack. Be sure to use 'Push-PSEmbyConfig' first." } } Function Push-PSEmbyConfig { [cmdletbinding()] param ( ) $configStack.Push($config.Clone()) } Function Save-PSEmbyConfig { [cmdletbinding()] Param ( [switch]$Force ) $path = Get-PSEmbyConfigPath $dir = Split-Path $path if (-not(Test-Path $dir -PathType Container)) { New-Item $dir -ItemType Directory } if (-not(Test-Path $path -PathType Leaf)) { New-Item $path -ItemType File } if ($Force.IsPresent) { $config | ConvertTo-Json | Out-File $path -Force } else { $config | ConvertTo-Json | Out-File $path } } Function Set-PSEmbyConfig { [cmdletbinding( SupportsShouldProcess, ConfirmImpact = 'Low' )] Param ( [ValidateNotNullOrEmpty()] [ArgumentCompleter({ $config['Servers'].Keys })] [string]$Server = $config['Server'], [ValidateSet('ServerToken','UserCredentials')] [string]$Type, [pscredential]$UserCredential, [string]$NewServerName, [string]$BaseUri, [string]$AccessToken, [string]$RedirectUri, [switch]$DontSave ) $changed = $false foreach ($key in ($config['Servers'][$config['Server']].Keys | Where-Object {$PSBoundParameters.Keys -contains $_})) { if ($PSCmdlet.ShouldProcess($key)) { $script:config['Servers']["$Server"]["$key"] = $PSBoundParameters["$key"] } $changed = $true } foreach ($key in ($config['Module'].Keys | Where-Object {$PSBoundParameters.Keys -contains $_})) { if ($PSCmdlet.ShouldProcess($key)) { $script:config['Module']["$key"] = $PSBoundParameters["$key"] } $changed = $true } if ($PSBoundParameters.Keys -contains 'NewServerName') { if ($PSCmdlet.ShouldProcess($key)) { $tmp = $config['Servers'][$Server] $config['Servers'].Remove($Server) $script:config['Servers'][$NewServerName] = $tmp Set-PSEmbyRunningConfig -Server $NewServerName } $changed = $true } if ($changed) { if(-not($DontSave.IsPresent)){ Write-Verbose 'Saving' Save-PSEmbyConfig } } } Function Set-PSEmbyRunningConfig { [cmdletbinding( SupportsShouldProcess, ConfirmImpact = 'Low' )] Param ( [ArgumentCompleter({ $config['Servers'].Keys })] [string]$Server ) if ($PSCmdlet.ShouldProcess($Server)) { $config['Server'] = $Server } } Function Test-PSEmbyConfig { [cmdletbinding()] [OutputType([Bool])] Param ( ) $noErrors = $true if ($config['Servers'].Keys -notcontains $config['Server']) { Write-Error "Server '$($config['Server'])' is not present in the config." $noErrors = $false } if ($noErrors){ $nonNullParams = 'AccessToken','AccessTokenExpires','RefreshToken','Location' foreach ($param in $nonNullParams) { if ($config['Servers'][$config['Server']][$param].Length -eq 0) { Write-Error "No value for '$param' for server '$($config['Server'])' in the config" $noErrors = $false } } } return $noErrors } <# Code in this file will be added to the end of the .psm1. For example, you should set variables or other environment settings here. #> Get-PSEmbyConfig -Silent |