PSImmich.psm1

#Region './prefix.ps1' -1

# The content of this file will be prepended to the top of the psm1 module file. This is useful for custom module setup is needed on import.

#EndRegion './prefix.ps1' 3
#Region './Classes/ImmichSession.class.ps1' -1

[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingConvertToSecureStringWithPlainText', '', Justification = 'JWT token retreived in plain text')]
class ImmichSession
{
    [string]$BaseUri
    [string]$AuthMethod
    [securestring]$AccessToken
    [pscredential]$Credential
    [securestring]$JWT
    [string]$APIUri
    [string]$ImmichVersion
    [string]$SessionID

    ImmichSession ([string]$BaseUri, [securestring]$AccessToken)
    {
        Write-Debug -Message 'ImmichSession.Class; Running constructor accesstoken'
        $this.SessionID = (New-Guid).Guid
        $this.BaseUri = $BaseUri
        $this.APIUri = "$BaseUri/api"
        $this.AuthMethod = 'AccessToken'
        $this.AccessToken = $AccessToken
        $this.GetStatus()
        Write-Verbose -Message "Connected to Immich instance at $($this.BaseUri) with AccessToken"
    }

    ImmichSession ([string]$BaseUri, [pscredential]$Credential)
    {
        Write-Debug -Message 'ImmichSession.Class; Running constructor credential'
        $this.SessionID = (New-Guid).Guid
        $this.BaseUri = $BaseUri
        $this.APIUri = "$BaseUri/api"
        $this.AuthMethod = 'Credential'
        $this.Credential = $Credential
        $this.AuthenticateCredential()
        $this.GetStatus()
        Write-Verbose -Message "Connected to Immich instance at $($this.BaseUri) with Credentials"
    }

    hidden AuthenticateCredential()
    {
        $BodyObject = @{
            password = $this.Credential.GetNetworkCredential().Password
            email    = $this.Credential.Username
        }
        $JWTResponse = InvokeImmichRestMethod -NoAuth -Method:'Post' -ImmichSession $this -RelativePath '/auth/login' -Body $BodyObject
        $this.JWT = ConvertTo-SecureString -String $JWTResponse.accessToken -AsPlainText -Force
        $this.AccessToken = ConvertTo-SecureString -String $JWTResponse.accessToken -AsPlainText -Force
        Remove-Variable -Name JWTResponse
    }

    hidden GetStatus()
    {
        $Status = InvokeImmichRestMethod -Method:'Get' -ImmichSession $this -RelativePath '/server-info/version'
        $this.ImmichVersion = "$($Status.Major).$($Status.Minor).$($Status.Patch)"
        Remove-Variable -Name Status
    }
}
#EndRegion './Classes/ImmichSession.class.ps1' 57
#Region './Private/ConvertFromSecureString.ps1' -1

function ConvertFromSecureString
{
    <#
    .DESCRIPTION
        Function that retreives the original value of the securestring. Obsolete in Windows Core becuase
        ConvertFrom-SecureString has an AsPlainText parameter but this function is instead used for
        Windows Powershell backwars compatiblity.
    .PARAMETER SecureString
        Defines the input securestring variable.
    .EXAMPLE
        ConvertFromSecureString
    #>

    param(
        [securestring]$SecureString
    )

    # Windows Powershell does not include ConvertFrom-SecureString -AsPlainText parameter.
    if ($PSVersionTable.PSEdition -eq 'Desktop')
    {
        $BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($SecureString)
        $UnsecurePassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)
        [Runtime.InteropServices.Marshal]::ZeroFreeBSTR($BSTR)
    }
    # Due to text encoding differences between windows and linux PtrToStringAuto does not work as expected with BSTR
    elseif ($PSVersionTable.PSEdition -eq 'Core')
    {
        $UnsecurePassword = ConvertFrom-SecureString -SecureString $ImmichSession.AccessToken -AsPlainText
    }

    return ($UnsecurePassword -join '')
}
#EndRegion './Private/ConvertFromSecureString.ps1' 32
#Region './Private/InvokeImmichRestMethod.ps1' -1

function InvokeImmichRestMethod
{
    <#
    .DESCRIPTION
        Function that is responsible for making the rest api web call
    .PARAMETER NoAuth
        Specifies that the REST API call do not need authentication
    .PARAMETER Method
        Defines the method to use when calling the REST API, valid values GET,POST etc.
    .PARAMETER ImmichSession
        A ImmichSession object to use for the call.
    .PARAMETER RelativePath
        The REST API path relative to the base URL
    .PARAMETER Body
        Defines body attributes for the REST API call
    .PARAMETER Headers
        Defines header attributes for the REST API call
    .PARAMETER QueryParameters
         Defines QueryParameters for the REST API call
    .PARAMETER ContentType
        Defines the contenttype for the request
    .PARAMETER OutFilePath
        Defines an output directory
    .EXAMPLE
        InvokeImmichRestMethod
    #>

    [CmdletBinding()] # Enabled advanced function support
    param(
        [switch]$NoAuth,
        [string]$Method,
        [immichsession]$ImmichSession,
        [string]$RelativePath,
        [hashtable]$Body = @{},
        [hashtable]$Headers = @{},
        [hashtable]$QueryParameters = @{},
        [string]$ContentType = 'application/json',
        [System.IO.FileInfo]$OutFilePath
    )

    if (-not $ImmichSession)
    {
        Write-Debug -Message 'InvokeImmichRestMethod; No ImmichSession passed as parameter'
        if ($script:ImmichSession)
        {
            Write-Debug -Message 'InvokeImmichRestMethod; ImmichSession found in script scope'
            $ImmichSession = $script:ImmichSession
        }
        else
        {
            Write-Error -Message 'No Immich Session established, please call Connect-Immich'
        }
    }

    $InvokeRestMethodSplat = @{
        Method = $Method
        Uri    = "$($ImmichSession.ApiUri)$($RelativePath)"
    }

    if (-not $NoAuth)
    {
        switch ($ImmichSession.AuthMethod)
        {
            'Credential'
            {
                $Headers.Authorization = "Bearer $($ImmichSession.JWT)"
            }
            'AccessToken'
            {
                $Headers.'X-API-Key' = ConvertFromSecureString -SecureString $ImmichSession.AccessToken
            }
        }
    }

    if ($Headers.Keys.Count -gt 0)
    {
        $InvokeRestMethodSplat.Headers = $Headers
    }
    if ($InvokeRestMethodSplat.Method -eq 'Get')
    {
        if ($Body.Keys.Count -gt 0 )
        {
            $InvokeRestMethodSplat.Body = $Body
        }
        if ($QueryParameters)
        {
            $InvokeRestMethodSplat.Uri += '?'
            $QueryParameterStringArray = foreach ($QueryParameter in $QueryParameters.Keys)
            {
                switch ($QueryParameters.$QueryParameter.GetType().Name)
                {
                    'string'
                    {
                        "$($QueryParameter)=$($QueryParameters.$QueryParameter)"
                    }
                    'boolean'
                    {
                        "$($QueryParameter)=$($QueryParameters.$QueryParameter.ToString().ToLower())"
                    }
                    'int32'
                    {
                        "$($QueryParameter)=$($QueryParameters.$QueryParameter)"
                    }
                    'datetime'
                    {
                        "$($QueryParameter)=$($QueryParameters.$QueryParameter.ToString('yyyy-MM-ddTHH:mm:ss'))"
                    }
                    default
                    {
                        Write-Warning -Message "Unknown type of queryparameter $QueryParameter : $($QueryParameters.$QueryParameter.GetType().Name)"
                    }
                }
            }
            $InvokeRestMethodSplat.Uri += [URI]::EscapeUriString(($QueryParameterStringArray -join '&'))
        }
    }
    elseif (@('Post', 'Put', 'Delete', 'Patch') -contains $InvokeRestMethodSplat.Method)
    {
        # Might need to be changed, some post requests require formdata
        $InvokeRestMethodSplat.Body = $Body | ConvertTo-Json -Compress
        $InvokeRestMethodSplat.ContentType = $ContentType
    }
    else
    {
        Write-Error -Message "Unknown method: $($InvokeRestMethodSplat.Method), unable to perform api call" -ErrorAction Stop
    }


    Write-Debug -Message "InvokeImmichRestMethod; Calling Invoke-RestMethod with settings`r`n$($InvokeRestMethodSplat | ConvertTo-Json)"

    if ($ContentType -eq 'application/octet-stream' -and $Method -eq 'Get')
    {
        Invoke-RestMethod @InvokeRestMethodSplat -Verbose:$false -OutFile $OutFilePath
    }
    else
    {
        Invoke-RestMethod @InvokeRestMethodSplat -Verbose:$false | ForEach-Object { $_ }
    }

}


#endregion
#EndRegion './Private/InvokeImmichRestMethod.ps1' 143
#Region './Private/SelectBinding.ps1' -1

function SelectBinding
{
    <#
    .DESCRIPTION
        Function that is extracts what parameters the cmdlet was called with
    .PARAMETER Binding
        PSBoundParameters object should be passed
    .PARAMETER SelectProperty
        String array of the properties that should be extracted.
    .EXAMPLE
        SelectBinding
    #>

    param(
        $Binding,
        [string[]]$SelectProperty
    )

    $ReturnHash = @{}

    # Only process binded parameters that we are intreseted in
    foreach ($Parameter in ($Binding.Keys | Where-Object { $SelectProperty -contains $PSItem }))
    {
        # Typecast switch to string
        if ($Binding[$Parameter] -is [switch])
        {
            $ReturnHash.Add($Parameter, (($Binding[$Parameter] -as [boolean]).ToString().ToLower()))
        }
        # Typecast boolean to string
        elseif ($Binding[$Parameter] -is [boolean])
        {
            $ReturnHash.Add($Parameter, ($Binding[$Parameter].ToString().ToLower()))
        }
        # Else add the value unaltered
        else
        {
            $ReturnHash.Add($Parameter, $Binding[$Parameter])
        }
    }
    return $ReturnHash

}
#EndRegion './Private/SelectBinding.ps1' 42
#Region './Private/Write-PSProgress.ps1' -1

function Write-PSProgress
{
    <#
    .SYNOPSIS
        Wrapper for PSProgress
    .DESCRIPTION
        This function will automatically calculate items/sec, eta, time remaining
        as well as set the update frequency in case the there are a lot of items processing fast.
    .PARAMETER Activity
        Defines the activity name for the progressbar
    .PARAMETER Id
        Defines a unique ID for this progressbar, this is used when nesting progressbars
    .PARAMETER Target
        Defines a arbitrary text for the currently processed item
    .PARAMETER ParentId
        Defines the ID of a parent progress bar
    .PARAMETER Completed
        Explicitly tells powershell to set the progress bar as completed removing
        it from view. In some cases the progress bar will linger if this is not done.
    .PARAMETER Counter
        The currently processed items counter
    .PARAMETER Total
        The total number of items to process
    .PARAMETER StartTime
        Sets the start datetime for the progressbar, this is required to calculate items/sec, eta and time remaining
    .PARAMETER DisableDynamicUpdateFrquency
        Disables the dynamic update frequency function and every item will update the status of the progressbar
    .PARAMETER NoTimeStats
        Disables calculation of items/sec, eta and time remaining
    .EXAMPLE
        1..10000 | foreach-object -begin {$StartTime = Get-Date} -process {
            Write-PSProgress -Activity 'Looping' -Target $PSItem -Counter $PSItem -Total 10000 -StartTime $StartTime
        }
        Explanation of the function or its result. You can include multiple examples with additional .EXAMPLE lines
    #>


    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true, Position = 0, ParameterSetName = 'Standard')]
        [Parameter(Mandatory = $true, Position = 0, ParameterSetName = 'Completed')]
        [string]
        $Activity,

        [Parameter(Position = 1, ParameterSetName = 'Standard')]
        [Parameter(Position = 1, ParameterSetName = 'Completed')]
        [ValidateRange(0, 2147483647)]
        [int]
        $Id,

        [Parameter(Position = 2, ParameterSetName = 'Standard')]
        [string]
        $Target,

        [Parameter(Position = 3, ParameterSetName = 'Standard')]
        [Parameter(Position = 3, ParameterSetName = 'Completed')]
        [ValidateRange(-1, 2147483647)]
        [int]
        $ParentId,

        [Parameter(Position = 4, ParameterSetname = 'Completed')]
        [switch]
        $Completed,

        [Parameter(Mandatory = $true, Position = 5, ParameterSetName = 'Standard')]
        [long]
        $Counter,

        [Parameter(Mandatory = $true, Position = 6, ParameterSetName = 'Standard')]
        [long]
        $Total,

        [Parameter(Position = 7, ParameterSetName = 'Standard')]
        [datetime]
        $StartTime,

        [Parameter(Position = 8, ParameterSetName = 'Standard')]
        [switch]
        $DisableDynamicUpdateFrquency,

        [Parameter(Position = 9, ParameterSetName = 'Standard')]
        [switch]
        $NoTimeStats
    )

    # Define current timestamp
    $TimeStamp = (Get-Date)

    # Define a dynamic variable name for the global starttime variable
    $StartTimeVariableName = ('ProgressStartTime_{0}' -f $Activity.Replace(' ', ''))

    # Manage global start time variable
    if ($PSBoundParameters.ContainsKey('Completed') -and (Get-Variable -Name $StartTimeVariableName -Scope Global -ErrorAction SilentlyContinue))
    {
        # Remove the global starttime variable if the Completed switch parameter is users
        try
        {
            Remove-Variable -Name $StartTimeVariableName -ErrorAction Stop -Scope Global
        }
        catch
        {
            throw $_
        }
    }
    elseif (-not (Get-Variable -Name $StartTimeVariableName -Scope Global -ErrorAction SilentlyContinue))
    {
        # Global variable do not exist, create global variable
        if ($null -eq $StartTime)
        {
            # No start time defined with parameter, use current timestamp as starttime
            Set-Variable -Name $StartTimeVariableName -Value $TimeStamp -Scope Global
            $StartTime = $TimeStamp
        }
        else
        {
            # Start time defined with parameter, use that value as starttime
            Set-Variable -Name $StartTimeVariableName -Value $StartTime -Scope Global
        }
    }
    else
    {
        # Global start time variable is defined, collect and use it
        $StartTime = Get-Variable -Name $StartTimeVariableName -Scope Global -ErrorAction Stop -ValueOnly
    }

    # Define frequency threshold
    $Frequency = [Math]::Ceiling($Total / 100)
    switch ($PSCmdlet.ParameterSetName)
    {
        'Standard'
        {
            # Only update progress is any of the following is true
            # - DynamicUpdateFrequency is disabled
            # - Counter matches a mod of defined frequecy
            # - Counter is 0
            # - Counter is equal to Total (completed)
            if (($DisableDynamicUpdateFrquency) -or ($Counter % $Frequency -eq 0) -or ($Counter -eq 1) -or ($Counter -eq $Total))
            {

                # Calculations for both timestats and without
                $Percent = [Math]::Round(($Counter / $Total * 100), 0)

                # Define count progress string status
                $CountProgress = ('{0}/{1}' -f $Counter, $Total)

                # If percent would turn out to be more than 100 due to incorrect total assignment revert back to 100% to avoid that write-progress throws
                if ($Percent -gt 100)
                {
                    $Percent = 100
                }

                # Define write-progress splat hash
                $WriteProgressSplat = @{
                    Activity         = $Activity
                    PercentComplete  = $Percent
                    CurrentOperation = $Target
                }

                # Add ID if specified
                if ($Id)
                {
                    $WriteProgressSplat.Id = $Id
                }

                # Add ParentID if specified
                if ($ParentId)
                {
                    $WriteProgressSplat.ParentId = $ParentId
                }

                # Calculations for either timestats and without
                if ($NoTimeStats)
                {
                    $WriteProgressSplat.Status = ('{0} - {1}%' -f $CountProgress, $Percent)
                }
                else
                {
                    # Total seconds elapsed since start
                    $TotalSeconds = ($TimeStamp - $StartTime).TotalSeconds

                    # Calculate items per sec processed (IpS)
                    $ItemsPerSecond = ([Math]::Round(($Counter / $TotalSeconds), 2))

                    # Calculate seconds spent per processed item (for ETA)
                    $SecondsPerItem = if ($Counter -eq 0)
                    {
                        0
                    }
                    else
                    {
 ($TotalSeconds / $Counter)
                    }

                    # Calculate seconds remainging
                    $SecondsRemaing = ($Total - $Counter) * $SecondsPerItem
                    $WriteProgressSplat.SecondsRemaining = $SecondsRemaing

                    # Calculate ETA
                    $ETA = $(($Timestamp).AddSeconds($SecondsRemaing).ToShortTimeString())

                    # Add findings to write-progress splat hash
                    $WriteProgressSplat.Status = ('{0} - {1}% - ETA: {2} - IpS {3}' -f $CountProgress, $Percent, $ETA, $ItemsPerSecond)
                }

                # Call writeprogress
                Write-Progress @WriteProgressSplat
            }
        }
        'Completed'
        {
            Write-Progress -Activity $Activity -Id $Id -Completed
        }
    }
}
#EndRegion './Private/Write-PSProgress.ps1' 214
#Region './Public/Activity/Add-IMActivity.ps1' -1

function Add-IMActivity
{
    <#
    .DESCRIPTION
        Adds a new activity to an album
    .PARAMETER Session
        Optionally define a immich session object to use. This is useful when you are connected to more than one immich instance.

        -Session $Session
    .PARAMETER albumId
        Defines a album id to be retreived
    .PARAMETER assetId
        Defines a specific assetid to retreive activities for.
    .PARAMETER comment
        Defines the comment to post.
    .PARAMETER type
        Defines the type of activities to retreive, valid values are comment or like.
    .EXAMPLE
        Add-IMActivity

        Adds a new activity to an album
    #>


    [CmdletBinding()]
    param(
        [Parameter()]
        [ImmichSession]
        $Session = $null,

        [Parameter(Mandatory, ValueFromPipelineByPropertyName, ValueFromPipeline)]
        [string]
        $albumId,

        [Parameter()]
        [string]
        $assetId,

        [Parameter()]
        [string]
        $comment,

        [Parameter()]
        [ValidateSet('comment', 'like')]
        [string]
        $type
    )

    BEGIN
    {
        $BodyParameters = @{}
        $BodyParameters += (SelectBinding -Binding $PSBoundParameters -SelectProperty 'albumId', 'assetId', 'comment', 'type')
    }

    PROCESS
    {
        InvokeImmichRestMethod -Method Post -RelativePath '/activity' -ImmichSession:$Session -Body $BodyParameters
    }

}
#endregion
#EndRegion './Public/Activity/Add-IMActivity.ps1' 61
#Region './Public/Activity/Get-IMActivity.ps1' -1

function Get-IMActivity
{
    <#
    .DESCRIPTION
        Retreives album activity
    .PARAMETER Session
        Optionally define a immich session object to use. This is useful when you are connected to more than one immich instance.

        -Session $Session
    .PARAMETER albumId
        Defines a album id to be retreived
    .PARAMETER assetId
        Defines a specific assetid to retreive activities for.
    .PARAMETER level
        Defines the level of activities to retreive, valid values are album or asset.
    .PARAMETER type
        Defines the type of activities to retreive, valid values are comment or like.
    .PARAMETER userId
        Defines a specific user to retreive activities for.
    .EXAMPLE
        Get-IMActivity

        Retreives album activity
    #>


    [CmdletBinding()]
    param(
        [Parameter()]
        [ImmichSession]
        $Session = $null,

        [Parameter(Mandatory, ValueFromPipelineByPropertyName, ValueFromPipeline)]
        [string]
        $albumId,

        [Parameter()]
        [string]
        $assetId,

        [Parameter()]
        [ValidateSet('album', 'asset')]
        [string]
        $level,

        [Parameter()]
        [ValidateSet('comment', 'like')]
        [string]
        $type,

        [Parameter()]
        [string]
        $userId
    )

    BEGIN
    {
        $QueryParameters = @{}
        $QueryParameters += (SelectBinding -Binding $PSBoundParameters -SelectProperty 'albumId', 'assetId', 'level', 'type', 'userId')
    }

    PROCESS
    {
        InvokeImmichRestMethod -Method Get -RelativePath '/activity' -ImmichSession:$Session -QueryParameters $QueryParameters
    }

}
#endregion
#EndRegion './Public/Activity/Get-IMActivity.ps1' 68
#Region './Public/Activity/Get-IMActivityStatistic.ps1' -1

function Get-IMActivityStatistic
{
    <#
    .DESCRIPTION
        Retreives album activity
    .PARAMETER Session
        Optionally define a immich session object to use. This is useful when you are connected to more than one immich instance.

        -Session $Session
    .PARAMETER albumId
        Defines a album id to be retreived
    .PARAMETER assetId
        Defines a specific assetid to retreive activities for.
    .EXAMPLE
        Get-IMActivityStatistic

        Retreives album activity
    #>


    [CmdletBinding()]
    param(
        [Parameter()]
        [ImmichSession]
        $Session = $null,

        [Parameter(Mandatory, ValueFromPipelineByPropertyName, ValueFromPipeline)]
        [string]
        $albumId,

        [Parameter()]
        [string]
        $assetId
    )

    BEGIN
    {
        $QueryParameters = @{}
        $QueryParameters += (SelectBinding -Binding $PSBoundParameters -SelectProperty 'albumId', 'assetId')
    }

    PROCESS
    {
        InvokeImmichRestMethod -Method Get -RelativePath '/activity/statistics' -ImmichSession:$Session -QueryParameters $QueryParameters
    }

}
#endregion
#EndRegion './Public/Activity/Get-IMActivityStatistic.ps1' 48
#Region './Public/Activity/Remove-IMActivity.ps1' -1

function Remove-IMActivity
{
    <#
    .DESCRIPTION
        Removes a activity
    .PARAMETER Session
        Optionally define a immich session object to use. This is useful when you are connected to more than one immich instance.

        -Session $Session
    .PARAMETER Id
        Defines the activity id to be remove
    .EXAMPLE
        Remove-IMActivity

        Removes a activity
    #>


    [CmdletBinding(SupportsShouldProcess)]
    param(
        [Parameter()]
        [ImmichSession]
        $Session = $null,

        [Parameter(Mandatory, ValueFromPipelineByPropertyName, ValueFromPipeline)]
        [string]
        $id
    )

    PROCESS
    {
        if ($PSCmdlet.ShouldProcess($id, 'DELETE')) {
            InvokeImmichRestMethod -Method DELETE -RelativePath "/activity/$id" -ImmichSession:$Session
        }
    }

}
#endregion
#EndRegion './Public/Activity/Remove-IMActivity.ps1' 38
#Region './Public/Album/Add-IMAlbumAsset.ps1' -1

function Add-IMAlbumAsset
{
    <#
    .DESCRIPTION
        Add assets to album
    .PARAMETER Session
        Optionally define a immich session object to use. This is useful when you are connected to more than one immich instance.

        -Session $Session
    .PARAMETER albumId
        Defines albumId to add assets to
    .PARAMETER assetid
        Defines the assetIds to add to the album
    .EXAMPLE
        Add-IMAlbumAsset

        Add assets to album
    #>


    [CmdletBinding(SupportsShouldProcess)]
    param(
        [Parameter()]
        [ImmichSession]
        $Session = $null,

        [Parameter(Mandatory)]
        [string]
        $albumId,

        [Parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)]
        [Alias('id')]
        [string[]]
        $assetId
    )

    BEGIN
    {
        $BodyParameters = @{
            ids = [string[]]@()
        }
    }

    PROCESS
    {
        $assetId | ForEach-Object {
            $BodyParameters.ids += $PSItem
        }
    }

    END
    {
        InvokeImmichRestMethod -Method PUT -RelativePath "/album/$albumid/assets" -ImmichSession:$Session -Body:$BodyParameters
    }
}
#endregion
#EndRegion './Public/Album/Add-IMAlbumAsset.ps1' 56
#Region './Public/Album/Add-IMAlbumUser.ps1' -1

function Add-IMAlbumUser
{
    <#
    .DESCRIPTION
        Add user to album
    .PARAMETER Session
        Optionally define a immich session object to use. This is useful when you are connected to more than one immich instance.

        -Session $Session
    .PARAMETER albumId
        Defines albumId to add assets to
    .PARAMETER userId
        Defines the assetIds to add to the album
    .EXAMPLE
        Add-IMAlbumUser

        Add user to album
    #>


    [CmdletBinding(SupportsShouldProcess)]
    param(
        [Parameter()]
        [ImmichSession]
        $Session = $null,

        [Parameter(Mandatory)]
        [string]
        $albumId,

        [Parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)]
        [Alias('id')]
        [string[]]
        $userId
    )

    BEGIN
    {
        $BodyParameters = @{
            sharedUserIds = [string[]]@()
        }
    }

    PROCESS
    {
        $userId | ForEach-Object {
            $BodyParameters.sharedUserIds += $PSItem
        }
    }

    END
    {
        InvokeImmichRestMethod -Method PUT -RelativePath "/album/$albumid/users" -ImmichSession:$Session -Body:$BodyParameters
    }
}
#endregion
#EndRegion './Public/Album/Add-IMAlbumUser.ps1' 56
#Region './Public/Album/Get-IMAlbum.ps1' -1

function Get-IMAlbum
{
    <#
    .DESCRIPTION
        Retreives Immich asset
    .PARAMETER Session
        Optionally define a immich session object to use. This is useful when you are connected to more than one immich instance.

        -Session $Session
    .PARAMETER albumId
        Defines an albumId to query
    .PARAMETER assetId
        Only returns albums that contain the asset
    .PARAMETER shared
        Defines weather to return shared albums or not.
    .PARAMETER withoutAssets
        Defines weather to return assets as part of the object
    .EXAMPLE
        Get-IMAlbum

        Retreives Immich asset
    #>


    [CmdletBinding(DefaultParameterSetName = 'list-shared')]
    param(
        [Parameter()]
        [ImmichSession]
        $Session = $null,

        [Parameter(Mandatory, ParameterSetName = 'id', ValueFromPipelineByPropertyName, ValueFromPipeline)]
        [Alias('id')]
        [string]
        $albumId,

        [Parameter(Mandatory, ParameterSetName = 'list-asset')]
        [string]
        $assetId,

        [Parameter(ParameterSetName = 'id')]
        [switch]
        $withoutAssets,

        [Parameter(ParameterSetName = 'list-shared')]
        [boolean]
        $shared
    )

    BEGIN
    {
        switch ($PSCmdlet.ParameterSetName)
        {
            'list-shared'
            {
                $QueryParameters = @{}
                $QueryParameters += (SelectBinding -Binding $PSBoundParameters -SelectProperty 'shared')
            }
            'list-asset'
            {
                $QueryParameters = @{}
                $QueryParameters += (SelectBinding -Binding $PSBoundParameters -SelectProperty 'assetId')
            }
            'id'
            {
                $QueryParameters = @{}
                $QueryParameters += (SelectBinding -Binding $PSBoundParameters -SelectProperty 'withoutAssets')
            }
        }
    }

    PROCESS
    {
        switch ($PSCmdlet.ParameterSetName)
        {
            'list-shared'
            {
                InvokeImmichRestMethod -Method Get -RelativePath '/album' -ImmichSession:$Session -QueryParameters $QueryParameters
            }
            'id'
            {
                InvokeImmichRestMethod -Method Get -RelativePath "/album/$albumId" -ImmichSession:$Session -QueryParameters $QueryParameters
            }
            'list-asset'
            {
                InvokeImmichRestMethod -Method Get -RelativePath '/album' -ImmichSession:$Session -QueryParameters $QueryParameters
            }
        }
    }

}
#endregion
#EndRegion './Public/Album/Get-IMAlbum.ps1' 91
#Region './Public/Album/Get-IMAlbumCount.ps1' -1

function Get-IMAlbumCount
{
    <#
    .DESCRIPTION
        Retreives Immich asset
    .PARAMETER Session
        Optionally define a immich session object to use. This is useful when you are connected to more than one immich instance.

        -Session $Session
    .EXAMPLE
        Get-IMAlbumCount

        Retreives Immich album count
    #>


    [CmdletBinding(DefaultParameterSetName = 'list-shared')]
    param(
        [Parameter()]
        [ImmichSession]
        $Session = $null
    )

    InvokeImmichRestMethod -Method Get -RelativePath '/album/count' -ImmichSession:$Session

}
#endregion
#EndRegion './Public/Album/Get-IMAlbumCount.ps1' 27
#Region './Public/Album/New-IMAlbum.ps1' -1

function New-IMAlbum
{
    <#
    .DESCRIPTION
        Adds a new an album
    .PARAMETER Session
        Optionally define a immich session object to use. This is useful when you are connected to more than one immich instance.

        -Session $Session
    .PARAMETER albumName
        Defines the name of the new album
    .PARAMETER assetIds
        Defines a list of assets to add to the album
    .PARAMETER description
        Defines a description for the album
    .PARAMETER sharedWithUserIds
        Defines a list of user id to share the album to
    .EXAMPLE
        New-IMAlbum

        Adds a new an album
    #>

    [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '', Justification = 'Do not agree, new initiates an entity not previously known to the system, that should not cause issues.')]
    [CmdletBinding()]
    param(
        [Parameter()]
        [ImmichSession]
        $Session = $null,

        [Parameter(Mandatory)]
        [string]
        $albumName,

        [Parameter()]
        [string[]]
        $assetIds,

        [Parameter()]
        [string]
        $description,

        [Parameter()]
        [string[]]
        $sharedWithUserIds
    )

    BEGIN
    {
        $BodyParameters = @{}
        $BodyParameters += (SelectBinding -Binding $PSBoundParameters -SelectProperty 'albumName', 'assetIds', 'description', 'sharedWithUserIds')
    }

    PROCESS
    {
        InvokeImmichRestMethod -Method Post -RelativePath '/album' -ImmichSession:$Session -Body $BodyParameters
    }

}
#endregion
#EndRegion './Public/Album/New-IMAlbum.ps1' 60
#Region './Public/Album/Remove-IMAlbum.ps1' -1

function Remove-IMAlbum
{
    <#
    .DESCRIPTION
        Removes an Immich album
    .PARAMETER Session
        Optionally define a immich session object to use. This is useful when you are connected to more than one immich instance.

        -Session $Session
    .PARAMETER albumId
        Defines the asset ids that should be removed. Accepts pipeline input.
    .EXAMPLE
        Remove-IMAlbum

        Removes an Immich album
    #>


    [CmdletBinding(SupportsShouldProcess)]
    param(
        [Parameter()]
        [ImmichSession]
        $Session = $null,

        [Parameter(Mandatory, ValueFromPipelineByPropertyName, ValueFromPipeline)]
        [Alias('id')]
        [string[]]
        $albumId
    )

    PROCESS
    {
        # We loop through IDs because ids can be provided as an array to the parameter in which case the process block only gets called once.
        $albumId | ForEach-Object {
            $CurrentID = $PSItem
            if ($PSCmdlet.ShouldProcess($CurrentID, 'DELETE'))
            {
                InvokeImmichRestMethod -Method Delete -RelativePath "/album/$CurrentID" -ImmichSession:$Session
            }
        }
    }
}
#endregion
#EndRegion './Public/Album/Remove-IMAlbum.ps1' 43
#Region './Public/Album/Remove-IMAlbumAsset.ps1' -1

function Remove-IMAlbumAsset
{
    <#
    .DESCRIPTION
        Remove assets from album
    .PARAMETER Session
        Optionally define a immich session object to use. This is useful when you are connected to more than one immich instance.

        -Session $Session
    .PARAMETER albumId
        Defines albumId to remove assets from
    .PARAMETER assetid
        Defines the assetIds to remove from the album
    .EXAMPLE
        Remove-IMAlbumAsset

        Remove assets from album
    #>


    [CmdletBinding(SupportsShouldProcess)]
    param(
        [Parameter()]
        [ImmichSession]
        $Session = $null,

        [Parameter(Mandatory)]
        [string]
        $albumId,

        [Parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)]
        [Alias('id')]
        [string[]]
        $assetId
    )

    BEGIN
    {
        $BodyParameters = @{
            ids = [string[]]@()
        }
    }

    PROCESS
    {
        $assetId | ForEach-Object {
            $BodyParameters.ids += $PSItem
        }
    }

    END
    {
        if ($PSCmdlet.ShouldProcess(($BodyParameters.ids -join ','), 'DELETE'))
        {
            InvokeImmichRestMethod -Method DELETE -RelativePath "/album/$albumid/assets" -ImmichSession:$Session -Body:$BodyParameters
        }
    }
}
#endregion
#EndRegion './Public/Album/Remove-IMAlbumAsset.ps1' 59
#Region './Public/Album/Remove-IMAlbumUser.ps1' -1

function Remove-IMAlbumUser
{
    <#
    .DESCRIPTION
        Remove user from album
    .PARAMETER Session
        Optionally define a immich session object to use. This is useful when you are connected to more than one immich instance.

        -Session $Session
    .PARAMETER albumId
        Defines albumId to remove assets from
    .PARAMETER userId
        Defines the userId to remove from the album
    .EXAMPLE
        Remove-IMAlbumUser

        Remove user from album
    #>


    [CmdletBinding(SupportsShouldProcess)]
    param(
        [Parameter()]
        [ImmichSession]
        $Session = $null,

        [Parameter(Mandatory)]
        [string]
        $albumId,

        [Parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)]
        [Alias('id')]
        [string[]]
        $userId
    )

    PROCESS
    {
        $userId | ForEach-Object {
            if ($PSCmdlet.ShouldProcess($PSItem, 'DELETE'))
            {
                InvokeImmichRestMethod -Method DELETE -RelativePath "/album/$albumid/user/$psitem" -ImmichSession:$Session
            }
        }
    }

}
#endregion
#EndRegion './Public/Album/Remove-IMAlbumUser.ps1' 48
#Region './Public/Album/Set-IMAlbum.ps1' -1

function Set-IMAlbum
{
    <#
    .DESCRIPTION
        Updates an Immich album
    .PARAMETER Session
        Optionally define a immich session object to use. This is useful when you are connected to more than one immich instance.

        -Session $Session
    .PARAMETER ids
        Defines ids to update
    .PARAMETER albumName
        Defines a new album name
    .PARAMETER albumThumbnailAssetId
        Defines a UUID for a new thumbnail asset
    .PARAMETER description
        Defines a new description for the album
    .PARAMETER isActivityEnabled
        Defines weather activity feed should be enabled
    .EXAMPLE
        Set-IMAlbum

        Update an Immich album
    .NOTES
        Covers updateAssets, updateAsset
    #>


    [CmdletBinding(SupportsShouldProcess)]
    param(
        [Parameter()]
        [ImmichSession]
        $Session = $null,

        [Parameter(Mandatory, ValueFromPipelineByPropertyName, ValueFromPipeline)]
        [Alias('id', 'albumId')]
        [string[]]
        $ids,

        [Parameter()]
        [string]
        $albumName,

        [Parameter()]
        [string]
        $albumThumbnailAssetId,

        [Parameter()]
        [string]
        $description,

        [Parameter()]
        [boolean]
        $isActivityEnabled
    )

    BEGIN
    {
        $BodyParameters = @{}
        $BodyParameters += (SelectBinding -Binding $PSBoundParameters -SelectProperty 'albumName', 'albumThumbnailAssetId', 'description', 'isActivityEnabled')
    }

    PROCESS
    {
        $ids | ForEach-Object {
            if ($PSCmdlet.ShouldProcess($PSItem, 'Update'))
            {
                InvokeImmichRestMethod -Method PATCH -RelativePath "/album/$PSItem" -ImmichSession:$Session -Body:$BodyParameters
            }
        }
    }
}
#endregion
#EndRegion './Public/Album/Set-IMAlbum.ps1' 73
#Region './Public/APIKey/Get-IMAPIKey.ps1' -1

function Get-IMAPIKey
{
    <#
    .DESCRIPTION
        Retreives Immich api key
    .PARAMETER Session
        Optionally define a immich session object to use. This is useful when you are connected to more than one immich instance.

        -Session $Session
    .PARAMETER id
        Defines an api key id to query
    .EXAMPLE
        Get-IMAPIKey

        Retreives Immich api key
    #>


    [CmdletBinding(DefaultParameterSetName = 'list')]
    param(
        [Parameter()]
        [ImmichSession]
        $Session = $null,

        [Parameter(Mandatory, ParameterSetName = 'id', ValueFromPipelineByPropertyName, ValueFromPipeline)]
        [string[]]
        $id
    )

    PROCESS
    {
        $id | ForEach-Object {
            $CurrentID = $PSItem
            switch ($PSCmdlet.ParameterSetName)
            {
                'list'
                {
                    InvokeImmichRestMethod -Method Get -RelativePath '/api-key' -ImmichSession:$Session
                }
                'id'
                {
                    InvokeImmichRestMethod -Method Get -RelativePath "/api-key/$CurrentID" -ImmichSession:$Session
                }
            }
        }
    }

}
#endregion
#EndRegion './Public/APIKey/Get-IMAPIKey.ps1' 49
#Region './Public/APIKey/New-IMAPIKey.ps1' -1

function New-IMAPIKey
{
    <#
    .DESCRIPTION
        Adds a new an api key
    .PARAMETER Session
        Optionally define a immich session object to use. This is useful when you are connected to more than one immich instance.

        -Session $Session
    .PARAMETER name
        Defines the name of the new album
    .EXAMPLE
        New-IMAPIKey

        Adds a new an api key
    #>

    [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '', Justification = 'Do not agree, new initiates an entity not previously known to the system, that should not cause issues.')]
    [CmdletBinding()]
    param(
        [Parameter()]
        [ImmichSession]
        $Session = $null,

        [Parameter(Mandatory)]
        [string]
        $name
    )

    BEGIN
    {
        $BodyParameters = @{}
        $BodyParameters += (SelectBinding -Binding $PSBoundParameters -SelectProperty 'name')
    }

    PROCESS
    {
        InvokeImmichRestMethod -Method POST -RelativePath '/api-key' -ImmichSession:$Session -Body $BodyParameters
    }

}
#endregion
#EndRegion './Public/APIKey/New-IMAPIKey.ps1' 42
#Region './Public/APIKey/Remove-IMAPIKey.ps1' -1

function Remove-IMAPIKey
{
    <#
    .DESCRIPTION
        Removes Immich api key
    .PARAMETER Session
        Optionally define a immich session object to use. This is useful when you are connected to more than one immich instance.

        -Session $Session
    .PARAMETER id
        Defines an api key id to remove
    .EXAMPLE
        Remove-IMAPIKey

        Remove Immich api key
    #>

    [CmdletBinding(SupportsShouldProcess)]
    param(
        [Parameter()]
        [ImmichSession]
        $Session = $null,

        [Parameter(Mandatory, ValueFromPipelineByPropertyName, ValueFromPipeline)]
        [string[]]
        $id
    )

    PROCESS
    {
        $id | ForEach-Object {
            $CurrentID = $PSItem
            if ($PSCmdlet.ShouldProcess($CurrentID, 'DELETE'))
            {
                InvokeImmichRestMethod -Method DELETE -RelativePath "/api-key/$CurrentID" -ImmichSession:$Session
            }
        }
    }

}
#endregion
#EndRegion './Public/APIKey/Remove-IMAPIKey.ps1' 41
#Region './Public/APIKey/Set-IMAPIKey.ps1' -1

function Set-IMAPIKey
{
    <#
    .DESCRIPTION
        Sets name of an apikey
    .PARAMETER Session
        Optionally define a immich session object to use. This is useful when you are connected to more than one immich instance.

        -Session $Session
    .PARAMETER id
        Defines the id of the API key
    .PARAMETER name
        Defines the name of the new album
    .EXAMPLE
        Set-IMAPIKey

        Sets name of an apikey
    #>

    [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '', Justification = 'Do not agree, new initiates an entity not previously known to the system, that should not cause issues.')]
    [CmdletBinding()]
    param(
        [Parameter()]
        [ImmichSession]
        $Session = $null,

        [Parameter(Mandatory, ValueFromPipelineByPropertyName, ValueFromPipeline)]
        [string]
        $id,

        [Parameter(Mandatory)]
        [string]
        $name

    )

    BEGIN
    {
        $BodyParameters = @{}
        $BodyParameters += (SelectBinding -Binding $PSBoundParameters -SelectProperty 'name')
    }

    PROCESS
    {
        InvokeImmichRestMethod -Method PUT -RelativePath "/api-key/$id" -ImmichSession:$Session -Body $BodyParameters
    }

}
#endregion
#EndRegion './Public/APIKey/Set-IMAPIKey.ps1' 49
#Region './Public/Asset/Add-IMAsset.ps1' -1

function Add-IMAsset
{
    <#
    .DESCRIPTION
        Adds an Immich asset
    .PARAMETER Session
        Optionally define a immich session object to use. This is useful when you are connected to more than one immich instance.

        -Session $Session
    .PARAMETER FilePath
        Defines the asset ids that should be removed. Accepts pipeline input.
    .PARAMETER Duration
        asd
    .PARAMETER isArchived
        asd
    .PARAMETER isFavorite
        asd
    .PARAMETER isOffline
        asd
    .PARAMETER isReadOnly
        asd
    .PARAMETER isVisible
        asd
    .PARAMETER libraryId
        asd
    .EXAMPLE
        Add-IMAsset

        Removes an Immich asset
    .NOTES
        Covers API deleteAssets
    #>

    [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', '', Justification = 'FP, retreived through PSBoundParameters')]
    [CmdletBinding(SupportsShouldProcess)]
    param(
        [Parameter()]
        [ImmichSession]
        $Session = $null,

        [Parameter(Mandatory, ValueFromPipelineByPropertyName, ValueFromPipeline)]
        [System.IO.FileInfo[]]
        $FilePath,

        [Parameter()]
        [string]
        $Duration,

        [Parameter()]
        [switch]
        $isArchived,

        [Parameter()]
        [switch]
        $isFavorite ,

        [Parameter()]
        [switch]
        $isOffline ,

        [Parameter()]
        [switch]
        $isReadOnly,

        [Parameter()]
        [switch]
        $isVisible,

        [Parameter()]
        [string]
        $libraryId

    )

    BEGIN
    {
        # Do not run on Windows Powershell
        if ($PSVersionTable.PSEdition -eq 'Desktop')
        {
            Write-Warning -Message 'Add-IMAsset is not currently supported on Windows Powershell, please use Powershell Core on Windows instead.'
            break
        }
        if (-not $ImmichSession)
        {
            Write-Debug -Message 'InvokeImmichRestMethod; No ImmichSession passed as parameter'
            if ($script:ImmichSession)
            {
                Write-Debug -Message 'InvokeImmichRestMethod; ImmichSession found in script scope'
                $ImmichSession = $script:ImmichSession
            }
            else
            {
                Write-Error -Message 'No Immich Session established, please call Connect-Immich'
            }
        }


    }

    PROCESS
    {
        $FilePath | ForEach-Object {
            $FileInfo = Get-Item -Path $PSItem.FullName
            $Uri = "$($ImmichSession.ApiUri)/asset/upload"
            $Header = @{
                'Accept'    = 'application/json'
                'x-api-key' = ConvertFromSecureString -SecureString $ImmichSession.AccessToken
            }
            $Form = @{}
            $Form += (SelectBinding -Binding $PSBoundParameters -SelectProperty 'Duration', 'isArchived', 'isFavorite', 'isOffline', 'isReadOnly', 'isVisible', 'libraryId')
            $Form += @{
                deviceAssetId  = $FileInfo.Name
                deviceId       = 'PSImmich'
                fileCreatedAt  = $FileInfo.CreationTime.ToString('yyyy-MM-ddTHH:mm:ss')
                fileModifiedAt = $FileInfo.LastWriteTime.ToString('yyyy-MM-ddTHH:mm:ss')
                assetData      = $FileInfo
            }
            $Result = Invoke-WebRequest -Uri $Uri -Method Post -Headers $Header -Form $Form -ContentType 'multipart/form-data'
            $Result.Content | ConvertFrom-Json | Get-IMAsset
        }
    }
}
#EndRegion './Public/Asset/Add-IMAsset.ps1' 122
#Region './Public/Asset/Get-IMAsset.ps1' -1

function Get-IMAsset
{
    <#
    .DESCRIPTION
        Retreives Immich asset
    .PARAMETER Session
        Optionally define a immich session object to use. This is useful when you are connected to more than one immich instance.

        -Session $Session
    .PARAMETER id
        Defines a specific asset id to be retreived
    .PARAMETER isFavorite
        Defines if faviorites should be returned or not. Do not specify if either should be returned.
    .PARAMETER isArchived
        Defines if archvied assets should be returned or not. Do not specify if either should be returned.
    .PARAMETER skip
        Defines skip
    .PARAMETER take
        Defines take
    .PARAMETER updatedAfter
        Deinfes updatedAfter
    .PARAMETER updatedBefore
        Defines updatedBefore
    .PARAMETER userId
        Defines userId
    .PARAMETER deviceID
        Defines a device id
    .EXAMPLE
        Get-IMAsset

        Retreives Immich asset
    .NOTES
        Covers api getAllAssets,getAllUserAssetsByDeviceId,getAssetInfo
    #>


    [CmdletBinding(DefaultParameterSetName = 'list')]
    param(
        [Parameter()]
        [ImmichSession]
        $Session = $null,

        [Parameter(Mandatory, ParameterSetName = 'deviceid')]
        [string]
        $deviceID,

        [Parameter(Mandatory, ParameterSetName = 'id', ValueFromPipelineByPropertyName, ValueFromPipeline)]
        [string]
        $id,

        [Parameter(ParameterSetName = 'list')]
        [boolean]
        $isFavorite,

        [Parameter(ParameterSetName = 'list')]
        [boolean]
        $isArchived,

        [Parameter(ParameterSetName = 'list')]
        [int]
        $skip,

        [Parameter(ParameterSetName = 'list')]
        [int]
        $take,

        [Parameter(ParameterSetName = 'list')]
        [datetime]
        $updatedAfter,

        [Parameter(ParameterSetName = 'list')]
        [datetime]
        $updatedBefore,

        [Parameter(ParameterSetName = 'list')]
        [string]
        $userId
    )

    BEGIN
    {
        if (@('list', 'id') -contains $PSCmdlet.ParameterSetName)
        {
            $QueryParameters = @{}
            $QueryParameters += (SelectBinding -Binding $PSBoundParameters -SelectProperty 'isFavorite', 'isArchived', 'skip', 'take', 'updatedAfter', 'updatedBefore', 'userId', 'key')
        }
    }

    PROCESS
    {
        switch ($PSCmdlet.ParameterSetName)
        {
            'list'
            {
                InvokeImmichRestMethod -Method Get -RelativePath '/asset' -ImmichSession:$Session -QueryParameters $QueryParameters
            }
            'id'
            {
                InvokeImmichRestMethod -Method Get -RelativePath "/asset/$id" -ImmichSession:$Session -QueryParameters $QueryParameters
            }
            'deviceid'
            {
                InvokeImmichRestMethod -Method Get -RelativePath "/asset/device/$deviceid" -ImmichSession:$Session | Get-IMAsset
            }
        }
    }

}
#endregion
#EndRegion './Public/Asset/Get-IMAsset.ps1' 109
#Region './Public/Asset/Get-IMCuratedLocation.ps1' -1

function Get-IMCuratedLocation
{
    <#
    .DESCRIPTION
        Retreives Immich curated locations
    .PARAMETER Session
        Optionally define a immich session object to use. This is useful when you are connected to more than one immich instance.

        -Session $Session
    .EXAMPLE
        Get-IMCuratedLocation

        Retreives Immich curated locations
    .NOTES
        Covers API getCuratedLocations
    #>


    [CmdletBinding()]
    param(
        [Parameter()][ImmichSession]$Session = $null
    )

    InvokeImmichRestMethod -Method Get -RelativePath '/asset/curated-locations' -ImmichSession:$Session

}
#endregion
#EndRegion './Public/Asset/Get-IMCuratedLocation.ps1' 27
#Region './Public/Asset/Get-IMCuratedObject.ps1' -1

function Get-IMCuratedObject
{
    <#
    .DESCRIPTION
        Retreives Immich curated objects
    .PARAMETER Session
        Optionally define a immich session object to use. This is useful when you are connected to more than one immich instance.

        -Session $Session
    .EXAMPLE
        Get-IMCuratedObject

        Retreives Immich curated objects
    .NOTES
        Covers API getCuratedObjects
    #>


    [CmdletBinding()]
    param(
        [Parameter()][ImmichSession]$Session = $null
    )

    InvokeImmichRestMethod -Method Get -RelativePath '/asset/curated-objects' -ImmichSession:$Session

}
#endregion
#EndRegion './Public/Asset/Get-IMCuratedObject.ps1' 27
#Region './Public/Asset/Remove-IMAsset.ps1' -1

function Remove-IMAsset
{
    <#
    .DESCRIPTION
        Removes an Immich asset
    .PARAMETER Session
        Optionally define a immich session object to use. This is useful when you are connected to more than one immich instance.

        -Session $Session
    .PARAMETER ids
        Defines the asset ids that should be removed. Accepts pipeline input.
    .PARAMETER force
        Performs a hard delete bypassing the Trash
    .EXAMPLE
        Remove-IMAsset

        Removes an Immich asset
    .NOTES
        Covers API deleteAssets
    #>


    [CmdletBinding(SupportsShouldProcess)]
    param(
        [Parameter()]
        [ImmichSession]
        $Session = $null,

        [Parameter(Mandatory, ValueFromPipelineByPropertyName, ValueFromPipeline)]
        [string[]]
        [Alias('id')]
        $ids,

        [Parameter()]
        [switch]
        $force
    )

    BEGIN
    {
        $BodyParameters = @{
            ids = @()
        }
        $BodyParameters += (SelectBinding -Binding $PSBoundParameters -SelectProperty 'force')
    }

    PROCESS
    {
        $ids | ForEach-Object {
            $BodyParameters.ids += $psitem
        }
    }

    END
    {
        if ($PSCmdlet.ShouldProcess(($BodyParameters.ids -join ','), 'DELETE'))
        {
            InvokeImmichRestMethod -Method Delete -RelativePath '/asset' -ImmichSession:$Session -Body:$BodyParameters
        }
    }

}
#endregion
#EndRegion './Public/Asset/Remove-IMAsset.ps1' 63
#Region './Public/Asset/Save-IMAsset.ps1' -1

function Save-IMAsset
{
    <#
    .DESCRIPTION
        Save Immich asset
    .PARAMETER Session
        Optionally define a immich session object to use. This is useful when you are connected to more than one immich instance.

        -Session $Session
    .PARAMETER id
        Defines a specific asset id to be retreived
    .PARAMETER isThumb
        Defines if faviorites should be returned or not. Do not specify if either should be returned.
    .PARAMETER isWeb
        Defines if archvied assets should be returned or not. Do not specify if either should be returned.
    .PARAMETER Path
        Defines filepath for outputfile
    .EXAMPLE
        Save-IMAsset

        Save Immich asset
    #>


    [CmdletBinding()]
    param(
        [Parameter()]
        [ImmichSession]
        $Session = $null,

        [Parameter(Mandatory, ValueFromPipelineByPropertyName, ValueFromPipeline)]
        [string]
        $id,

        [Parameter()]
        [switch]
        $isThumb,

        [Parameter()]
        [switch]
        $isWeb,

        [Parameter()]
        [System.IO.DirectoryInfo]
        $Path
    )

    BEGIN
    {
        $QueryParameters = @{}
        $QueryParameters += (SelectBinding -Binding $PSBoundParameters -SelectProperty 'isThumb', 'isWeb')
    }

    PROCESS
    {
        $id | ForEach-Object {
            $CurrentID = $PSItem
            $AssetObject = Get-IMAsset -Id $CurrentID
            $OutputPath = Join-Path -Path $Path -ChildPath $AssetObject.originalFileName
            if ($PSVersionTable.PSEdition -eq 'Desktop')
            {
                $SavedProgressPreference = $global:ProgressPreference
                $global:ProgressPreference = 'SilentlyContinue'
            }
            InvokeImmichRestMethod -Method Get -RelativePath "/asset/file/$CurrentID" -ImmichSession:$Session -QueryParameters $QueryParameters -ContentType 'application/octet-stream' -OutFilePath $OutputPath
            if ($PSVersionTable.PSEdition -eq 'Desktop')
            {
                $global:ProgressPreference = $SavedProgressPreference
            }
        }
    }

}
#endregion
#EndRegion './Public/Asset/Save-IMAsset.ps1' 74
#Region './Public/Asset/Set-IMAsset.ps1' -1

function Set-IMAsset
{
    <#
    .DESCRIPTION
        Updates an Immich asset
    .PARAMETER Session
        Optionally define a immich session object to use. This is useful when you are connected to more than one immich instance.

        -Session $Session
    .PARAMETER ids
        asd
    .PARAMETER dateTimeOriginal
        asd
    .PARAMETER isArchived
        asd
    .PARAMETER isFavorite
        asd
    .PARAMETER latitude
        asd
    .PARAMETER longitude
        asd
    .PARAMETER removeParent
        asd
    .PARAMETER stackParentId
        asd
    .PARAMETER description
        asd
    .EXAMPLE
        Set-IMAsset

        Update an Immich asset
    .NOTES
        Covers updateAssets, updateAsset
    #>


    [CmdletBinding(SupportsShouldProcess, DefaultParameterSetName = 'batch')]
    param(
        [Parameter()]
        [ImmichSession]
        $Session = $null,

        [Parameter(Mandatory, ValueFromPipelineByPropertyName, ValueFromPipeline, ParameterSetName = 'batch')]
        [Parameter(Mandatory, ValueFromPipelineByPropertyName, ValueFromPipeline, ParameterSetName = 'id')]
        [Alias('id')]
        [string[]]
        $ids,

        [Parameter(ParameterSetName = 'batch')]
        [Parameter(ParameterSetName = 'id')]
        [string]
        $dateTimeOriginal,

        [Parameter(ParameterSetName = 'batch')]
        [Parameter(ParameterSetName = 'id')]
        [boolean]
        $isArchived,

        [Parameter(ParameterSetName = 'batch')]
        [Parameter(ParameterSetName = 'id')]
        [boolean]
        $isFavorite,

        [Parameter(ParameterSetName = 'batch')]
        [Parameter(ParameterSetName = 'id')]
        [Int32]
        $latitude,

        [Parameter(ParameterSetName = 'batch')]
        [Parameter(ParameterSetName = 'id')]
        [int32]
        $longitude,

        [Parameter(ParameterSetName = 'batch')]
        [switch]
        $removeParent,

        [Parameter(ParameterSetName = 'batch')]
        [string]
        $stackParentId,

        [Parameter(ParameterSetName = 'id')]
        [string]
        $description
    )

    BEGIN
    {
        switch ($PSCmdlet.ParameterSetName)
        {
            'batch'
            {
                $BodyParameters = @{
                    ids = @()
                }
                $BodyParameters += (SelectBinding -Binding $PSBoundParameters -SelectProperty 'dateTimeOriginal', 'isFavorite', 'isArchived', 'latitude', 'longitude', 'removeParent', 'stackParentId')
            }
            'id'
            {
                $BodyParameters = @{}
                $BodyParameters += (SelectBinding -Binding $PSBoundParameters -SelectProperty 'dateTimeOriginal', 'isFavorite', 'isArchived', 'latitude', 'longitude', 'description')
            }
        }
    }

    PROCESS
    {
        switch ($PSCmdlet.ParameterSetName)
        {
            'batch'
            {
                $ids | ForEach-Object {
                    $BodyParameters.ids += $psitem
                }
            }
            'id'
            {
                foreach ($id in $ids)
                {
                    if ($PSCmdlet.ShouldProcess(($BodyParameters.ids -join ','), 'PUT'))
                    {
                        InvokeImmichRestMethod -Method Put -RelativePath "/asset/$id" -ImmichSession:$Session -Body:$BodyParameters
                    }
                }
            }
        }
    }

    END
    {
        switch ($PSCmdlet.ParameterSetName)
        {
            'batch'
            {
                if ($PSCmdlet.ShouldProcess(($BodyParameters.ids -join ','), 'PUT'))
                {
                    InvokeImmichRestMethod -Method Put -RelativePath '/asset' -ImmichSession:$Session -Body:$BodyParameters
                }
            }
        }
    }

}
#endregion
#EndRegion './Public/Asset/Set-IMAsset.ps1' 144
#Region './Public/ServerInfo/Get-IMServer.ps1' -1

function Get-IMServer
{
    <#
    .DESCRIPTION
        Retreives all Immich server info properties
    .PARAMETER Session
        Optionally define a immich session object to use. This is useful when you are connected to more than one immich instance.

        -Session $Session
    .EXAMPLE
        Get-IMServer

        Retreives all Immich server info properties
    #>


    [CmdletBinding()]
    param(
        [Parameter()][ImmichSession]$Session = $null
    )

    $ResultObject = [ordered]@{}
    $Results = [array]@()
    $Results += Get-IMServerConfig -Session:$Session | Add-Member -MemberType NoteProperty -Name 'ObjectType' -Value 'Config' -PassThru
    $Results += Get-IMServerFeature -Session:$Session | Add-Member -MemberType NoteProperty -Name 'ObjectType' -Value 'Feature' -PassThru
    $Results += Get-IMServerInfo -Session:$Session | Add-Member -MemberType NoteProperty -Name 'ObjectType' -Value 'Info' -PassThru
    $Results += Get-IMServerStatistic -Session:$Session | Add-Member -MemberType NoteProperty -Name 'ObjectType' -Value 'Stats' -PassThru
    $Results += Get-IMServerVersion -Session:$Session | Add-Member -MemberType NoteProperty -Name 'ObjectType' -Value 'Version' -PassThru
    $Results += Get-IMSupportedMediaType -Session:$Session | Add-Member -MemberType NoteProperty -Name 'ObjectType' -Value 'Media' -PassThru
    $Results += Get-IMTheme -Session:$Session | Add-Member -MemberType NoteProperty -Name 'ObjectType' -Value 'Theme' -PassThru
    $Results += Test-IMPing -Session:$Session | Add-Member -MemberType NoteProperty -Name 'ObjectType' -Value 'Ping' -PassThru

    foreach ($Result in $Results)
    {
        foreach ($property in ($Result.PSObject.Properties.Name | Sort-Object))
        {
            if ($property -eq 'ObjectType')
            {
                continue
            }
            $ResultObject.Add("$($Result.ObjectType)_$Property", $Result.$Property)
        }
    }
    return [pscustomobject]$ResultObject

}
#endregion
#EndRegion './Public/ServerInfo/Get-IMServer.ps1' 47
#Region './Public/ServerInfo/Get-IMServerConfig.ps1' -1

function Get-IMServerConfig
{
    <#
    .DESCRIPTION
        Retreives Immich server config
    .PARAMETER Session
        Optionally define a immich session object to use. This is useful when you are connected to more than one immich instance.

        -Session $Session
    .EXAMPLE
        Get-IMServerConfig

        Retreives Immich server config
    #>


    [CmdletBinding()]
    param(
        [Parameter()][ImmichSession]$Session = $null
    )

    InvokeImmichRestMethod -noauth -Method Get -RelativePath '/server-info/config' -ImmichSession:$Session

}
#endregion
#EndRegion './Public/ServerInfo/Get-IMServerConfig.ps1' 25
#Region './Public/ServerInfo/Get-IMServerFeature.ps1' -1

function Get-IMServerFeature
{
    <#
    .DESCRIPTION
        Retreives Immich server feature
    .PARAMETER Session
        Optionally define a immich session object to use. This is useful when you are connected to more than one immich instance.

        -Session $Session
    .EXAMPLE
        Get-IMServerFeature

        Retreives Immich server feature
    #>


    [CmdletBinding()]
    param(
        [Parameter()][ImmichSession]$Session = $null
    )

    InvokeImmichRestMethod -noauth -Method Get -RelativePath '/server-info/features' -ImmichSession:$Session

}
#endregion
#EndRegion './Public/ServerInfo/Get-IMServerFeature.ps1' 25
#Region './Public/ServerInfo/Get-IMServerInfo.ps1' -1

function Get-IMServerInfo
{
    <#
    .DESCRIPTION
        Retreives Immich server info
    .PARAMETER Session
        Optionally define a immich session object to use. This is useful when you are connected to more than one immich instance.

        -Session $Session
    .EXAMPLE
        Get-IMServerInfo

        Retreives Immich server info
    #>


    [CmdletBinding()]
    param(
        [Parameter()][ImmichSession]$Session = $null
    )

    InvokeImmichRestMethod -Method Get -RelativePath '/server-info' -ImmichSession:$Session

}
#endregion
#EndRegion './Public/ServerInfo/Get-IMServerInfo.ps1' 25
#Region './Public/ServerInfo/Get-IMServerStatistic.ps1' -1

function Get-IMServerStatistic
{
    <#
    .DESCRIPTION
        Retreives Immich server statistic
    .PARAMETER Session
        Optionally define a immich session object to use. This is useful when you are connected to more than one immich instance.

        -Session $Session
    .EXAMPLE
        Get-IMServerStatistic

        Retreives Immich server statistic
    #>


    [CmdletBinding()]
    param(
        [Parameter()][ImmichSession]$Session = $null
    )

    InvokeImmichRestMethod -Method Get -RelativePath '/server-info/statistics' -ImmichSession:$Session

}
#endregion
#EndRegion './Public/ServerInfo/Get-IMServerStatistic.ps1' 25
#Region './Public/ServerInfo/Get-IMServerVersion.ps1' -1

function Get-IMServerVersion
{
    <#
    .DESCRIPTION
        Retreives Immich server version
    .PARAMETER Session
        Optionally define a immich session object to use. This is useful when you are connected to more than one immich instance.

        -Session $Session
    .EXAMPLE
        Get-IMServerVersion

        Retreives Immich server version
    #>


    [CmdletBinding()]
    param(
        [Parameter()][ImmichSession]$Session = $null
    )

    $Result = InvokeImmichRestMethod -noauth -Method Get -RelativePath '/server-info/version' -ImmichSession:$Session
    return [pscustomobject]@{
        version = "$($Result.Major).$($Result.Minor).$($Result.Patch)"
    }

}
#endregion
#EndRegion './Public/ServerInfo/Get-IMServerVersion.ps1' 28
#Region './Public/ServerInfo/Get-IMSupportedMediaType.ps1' -1

function Get-IMSupportedMediaType
{
    <#
    .DESCRIPTION
        Retreives Immich supported media type
    .PARAMETER Session
        Optionally define a immich session object to use. This is useful when you are connected to more than one immich instance.

        -Session $Session
    .EXAMPLE
        Get-IMSupportedMediaType

        Retreives Immich supported media type
    #>


    [CmdletBinding()]
    param(
        [Parameter()][ImmichSession]$Session = $null
    )

    InvokeImmichRestMethod -noauth -Method Get -RelativePath '/server-info/media-types' -ImmichSession:$Session

}
#endregion
#EndRegion './Public/ServerInfo/Get-IMSupportedMediaType.ps1' 25
#Region './Public/ServerInfo/Get-IMTheme.ps1' -1

function Get-IMTheme
{
    <#
    .DESCRIPTION
        Retreives Immich theme CSS
    .PARAMETER Session
        Optionally define a immich session object to use. This is useful when you are connected to more than one immich instance.

        -Session $Session
    .EXAMPLE
        Get-IMTheme

        Retreives Immich theme CSS
    #>


    [CmdletBinding()]
    param(
        [Parameter()][ImmichSession]$Session = $null
    )

    InvokeImmichRestMethod -Method Get -RelativePath '/server-info/theme' -ImmichSession:$Session

}
#endregion
#EndRegion './Public/ServerInfo/Get-IMTheme.ps1' 25
#Region './Public/ServerInfo/Test-IMPing.ps1' -1

function Test-IMPing
{
    <#
    .DESCRIPTION
        Ping Immich instance
    .PARAMETER Session
        Optionally define a immich session object to use. This is useful when you are connected to more than one immich instance.

        -Session $Session
    .EXAMPLE
        Test-IMPing

        Ping Immich instance
    #>


    [CmdletBinding()]
    param(
        [Parameter()][ImmichSession]$Session = $null
    )

    $Result = InvokeImmichRestMethod -noauth -Method Get -RelativePath '/server-info/ping' -ImmichSession:$Session
    if ($Result.res -eq 'pong')
    {
        return [pscustomobject]@{responds = $true }
    }
    else
    {
        return [pscustomobject]@{responds = $false }
    }

}
#endregion
#EndRegion './Public/ServerInfo/Test-IMPing.ps1' 33
#Region './Public/Session/Connect-Immich.ps1' -1

function Connect-Immich
{
    <#
    .DESCRIPTION
        Connect to a Immich instance
    .PARAMETER BaseURL
        Defines the base URL to the immich instance

        -BaseURL 'https://immich.domain.com'
    .PARAMETER AccessToken
        Connects to immich using a access token. This AccessToken can be generated from the Immich Web GUI.

        -AccessToken 'ABoR54bB1NUc4aNY0F2PhppP1tVDu2Husr3vEbPUsw5'
    .PARAMETER Credential
        Connect to immich using username and password. Parameter accepts a PSCredentials object

        -Credential (Get-Credential)
    .PARAMETER PassThru
        This parameter will cause the function to return a ImmichSession object that can be stored in a variable and referensed with the -Session parameter on most cmdlets.

        -PassThru
    .EXAMPLE
        Connect-Immich -BaseURL 'https://immich.domain.com' -AccessToken 'ABoR54bB1NUc4aNY0F2PhppP1tVDu2Husr3vEbPUsw5'

        Connect using access token
    .EXAMPLE
        Connect-Immich -BaseURL 'https://immich.domain.com' -Credentials (Get-Credential)

        Connect using username and password
    #>

    [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingConvertToSecureStringWithPlainText', '', Justification = 'AccessToken')]

    [CmdletBinding()]
    param(
        [Parameter(Mandatory)][string]$BaseURL,
        [Parameter(ParameterSetName = 'AccessToken')][string]$AccessToken,
        [Parameter(ParameterSetName = 'Credentials')][pscredential]$Credential,
        [switch]$PassThru
    )

    switch ($PSCmdlet.ParameterSetName)
    {
        'AccessToken'
        {
            $AccessTokenSS = ConvertTo-SecureString -String $AccessToken -AsPlainText -Force
            Remove-Variable -Name AccessToken
            $script:ImmichSession = [ImmichSession]::New($BaseURL, $AccessTokenSS)
        }
        'Credentials'
        {
            $script:ImmichSession = [ImmichSession]::New($BaseURL, $Credential)
        }
    }

    if ($Passthru)
    {
        return $script:ImmichSession
    }
}
#EndRegion './Public/Session/Connect-Immich.ps1' 60
#Region './Public/Session/Disconnect-Immich.ps1' -1

function Disconnect-Immich
{
    <#
    .DESCRIPTION
        Disconnect and cleanup session configuration
    .PARAMETER Session
        Defines a ImmichSession object that will be disconnected and cleaned up.
    .EXAMPLE
        Disconnect-Immich

        Disconnect from the default immich session
    .EXAMPLE
        Disconnect-Immich -Session $Session

        Disconnect the specified session
    #>


    [CmdletBinding()]
    param(
        [Parameter()][ImmichSession]$Session = $null
    )

    InvokeImmichRestMethod -Method Post -RelativePath '/auth/logout' -ImmichSession:$Session

    # Remove ImmichSession variable
    if ($Session)
    {
        if ($script:ImmichSession.SessionID -eq $Session.SessionID)
        {
            Remove-Variable ImmichSession -Scope Script
        }
    }
    else
    {
        Remove-Variable ImmichSession -Scope Script
    }

}
#EndRegion './Public/Session/Disconnect-Immich.ps1' 39
#Region './Public/Session/Get-IMSession.ps1' -1

function Get-IMSession
{
    <#
    .DESCRIPTION
        Displays the Immich Session object.
    .PARAMETER Session
        Optionally define a immich session object to use. This is useful when you are connected to more than one immich instance.

        -Session $Session
    .EXAMPLE
        Get-PSession

        Returns the ImmichSession, if none is specified, it tries to retreive the default
    #>


    [CmdletBinding()]
    param(
        [Parameter()][ImmichSession]$Session = $null
    )

    if ($Session)
    {
        Write-Debug -Message 'Get-PSession; ImmichSession was passed as parameter'
        return $Session
    }
    elseif ($script:ImmichSession)
    {
        Write-Debug -Message 'Get-PSession; ImmichSession found in script scope'
        return $script:ImmichSession
    }
    else
    {
        Write-Error -Message 'No Immich Session established, please call Connect-Immich'
    }
}
#endregion
#EndRegion './Public/Session/Get-IMSession.ps1' 37
#Region './Public/Session/Invoke-ImmichMethod.ps1' -1

function Invoke-ImmichMethod
{
    <#
    .DESCRIPTION
        Invokes command
    .PARAMETER Session
        Optionally define a immich session object to use. This is useful when you are connected to more than one immich instance.

        -Session $Session
    .PARAMETER Headers
        Headers
    .PARAMETER QueryParameters
        Query parameters
    .PARAMETER BodyParameters
        Body parameters
    .PARAMETER Method
        Method
    .PARAMETER RelativeURI
        RelativePath
    .PARAMETER ContentType
        ContentType
    .PARAMETER OutFilePath
        OutFilePath
    .EXAMPLE
        Invoke-ImmichMethod

        Retreives all Immich server info properties
    #>


    [CmdletBinding()]
    param(
        [Parameter()][ImmichSession]$Session = $null,

        [Parameter()][hashtable]$Headers,

        [Parameter()][hashtable]$QueryParameters,

        [Parameter()][hashtable]$BodyParameters,

        [Parameter()][string]$Method,

        [Parameter()][string]$RelativeURI,

        [Parameter()][string]$ContentType = 'application/json',

        [Parameter()][system.io.fileinfo]$OutFilePath
    )

    $Parameters = @{
        Method       = $Method
        RelativePath = $RelativeURI
        ContentType  = $ContentType
    }

    if ($QueryParameters)
    {
        $Parameters.QueryParameters = $QueryParameters
    }

    if ($BodyParameters)
    {
        $Parameters.BodyParameters = $BodyParameters
    }
    if ($Headers)
    {
        $Parameters.Headers = $Headers
    }
    if ($OutFilePath)
    {
        $Parameters.OutFilePath = $OutFilePath
    }

    InvokeImmichRestMethod @Parameters -Session:$Session

}
#endregion
#EndRegion './Public/Session/Invoke-ImmichMethod.ps1' 77
#Region './suffix.ps1' -1

# The content of this file will be appended to the top of the psm1 module file. This is useful for custom procesedures after all module functions are loaded.
#EndRegion './suffix.ps1' 2