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