PSAircall.psm1

$Script:PSModuleRoot = $PSScriptRoot
# Importing from [C:\pstemp\public\PSAircall\PSAircall\Private]
# .\PSAircall\Private\ConvertTo-AircallObject.ps1
function ConvertTo-AircallObject
{
    <#
        .SYNOPSIS
        Convert an object to an object with an Aircall type
 
        .DESCRIPTION
        Convert an object to an object with an Aircall type
 
        .PARAMETER InputObject
        Input object
 
        .PARAMETER Type
        Type of the output object
 
        .EXAMPLE
        ConvertTo-AircallObject -InputObject $obj -Type 'Aircall.Number'
    #>


    param (
        [Parameter(Mandatory = $true)]
        [Object[]]$InputObject,

        [Parameter(Mandatory = $true)]
        [string]$Type
    )

    begin
    {
        # Return variable
        $ArrayOutput = @()
    }

    process
    {
        foreach ($Object in $InputObject)
        {
            # Creation of a new object
            $Result = New-Object -TypeName PSObject

            # Specification of the object type
            $Result.PSObject.TypeNames.Insert(0, $Type)

            # Retrieves all properties
            $Properties = Get-Member -InputObject $Object -MemberType NoteProperty

            # For each property, we will add it to the object we have just created
            foreach ($Propertie in $Properties)
            {
                # Incrementally the object
                $Result | Add-Member -MemberType NoteProperty -Name $Propertie.Name -Value $Object.($Propertie.name) -Force
            }

            # Add result to output object
            $ArrayOutput += $Result
        }
    }

    end
    {
        return $ArrayOutput
    }
}

# .\PSAircall\Private\Get-AircallUrl.ps1
function Get-AircallUrl
{
    <#
        .SYNOPSIS
        Get the URL and the method to call according to the requested function
 
        .DESCRIPTION
        Get the URL and the method to call according to the requested function
        Returns a hashtable with the method, url and contenttype
        The contentType and the pagination are default values
 
        .PARAMETER Route
        Name of the function to find the route
 
        .EXAMPLE
        Get-AircallUrl -Route 'Test-AircallSession'
    #>


    [CmdletBinding()]
    [OutputType('System.Collections.Hashtable')]
    param(
        [Parameter(Mandatory = $true)]
        [string]$Route
    )

    begin
    {
        Write-Verbose "[$($MyInvocation.MyCommand.Name)] Function started"
        $ContentType = 'application/json'
        $BaseUri = 'https://api.aircall.io'

        # Test if we already have the list of endpoints
        $AircallUrl = $null
        if (-not $Script:AircallUrlTemp)
        {
            Write-Verbose "[$($MyInvocation.MyCommand.Name)] Attempt to recover endpoints"

            # Splating
            $SplatWeb = @{
                Uri         = $BaseUri
                ContentType = $ContentType
            }

            # Call the url to know the API version
            try
            {
                $ApiRoot = $null
                $ApiRoot = Invoke-WebRequest @SplatWeb
                if (-not $ApiRoot.content)
                {
                    Write-Error -Message ('No result when calling for endpoints')
                    continue
                }
            }
            catch
            {
                Write-Error -Message ('Error to get the endpoints')
                continue
            }

            # Retrieving information from the call
            $ApiRootContent = $null
            $ApiRootContent = $ApiRoot.content | ConvertFrom-Json
            if (-not $ApiRootContent.endpoint)
            {
                Write-Error -Message ('Unable to get the AirCall endpoint.')
                continue
            }
            $SplatWeb.Uri = $ApiRootContent.endpoint

            # Recovery of endpoints with the version recovered just before
            try
            {
                $ApiEndpoint = Invoke-WebRequest @SplatWeb
                $AircallUrl = [PSCustomObject]@{
                    PSTypeName = 'Aircall.Url'
                    Urls       = ( $ApiEndpoint.content | ConvertFrom-Json)
                }

                # Adds endpoints that are not present in the list
                $AircallUrl.Urls | Add-Member -MemberType NoteProperty -Name 'teams' -Value ('{0}/{1}' -f $ApiRootContent.endpoint, 'teams')
                $AircallUrl.Urls | Add-Member -MemberType NoteProperty -Name 'session' -Value ('{0}/{1}' -f $ApiRootContent.endpoint, 'ping')

                # Create a temporary variable to avoid calling the API every time
                $script:AircallUrlTemp = $AircallUrl
            }
            catch
            {
                Write-Error -Message ('Unable to get the list of AirCall endpoint.')
                continue
            }
        } else {
            $AircallUrl = $script:AircallUrlTemp
        }
    }

    process
    {

        # Try split function
        try
        {
            $RouteSplited = $null
            $RouteSplited = $Route.Split('-')
        }
        catch
        {
            Write-Error $_
        }

        # Verb of function
        $FunctionVerb = $RouteSplited[0]

        # Get the action of the function by deleting the name Aircall
        $FunctionAction = $RouteSplited[1].ToLower().Replace('aircall', '')

        #region Get method with verb of function
        switch ($FunctionVerb)
        {
            'New'
            {
                $Method = 'POST'
            }
            'Remove'
            {
                $Method = 'DELETE'
            }
            Default
            {
                $Method = 'GET'
            }
        }
        #endregion

        #region Get URL with the action of the function
        $GetAirCallEndpointName = $null
        $GetAirCallEndpointName = $AircallUrl.Urls | Get-Member -MemberType NoteProperty | Where-Object { $_.name -like "$FunctionAction*" }
        if (-not $GetAirCallEndpointName)
        {
            Write-Error -Message ('No results found for this endpoints {0}' -f $FunctionAction)
            continue
        }

        $Url = $null
        $Url = $AircallUrl.Urls.$($GetAirCallEndpointName.Name)
        if (-not $Url)
        {
            Write-Error -Message ("Can't find the URL for this function {0}" -f $Route)
            continue
        }
        else
        {
            $SplatWeb = @{
                Uri         = $Url
                ContentType = $ContentType
                Method      = $Method
            }
        }
    }

    end
    {
        return $SplatWeb
        Write-Verbose "[$($MyInvocation.MyCommand.Name)] Function ended"
    }
}

# Importing from [C:\pstemp\public\PSAircall\PSAircall\Public]
# .\PSAircall\Public\Clear-AircallSession.ps1
function Clear-AircallSession
{
    <#
        .SYNOPSIS
        Empty the variable containing the information to authenticate
 
        .DESCRIPTION
        Empty the variable containing the information to authenticate
 
        .EXAMPLE
        Clear-AircallSession
    #>


    [CmdletBinding()]
    [OutputType()]
    Param (
    )

    begin
    {
        Write-Verbose "[$($MyInvocation.MyCommand.Name)] Function started"
    }

    process
    {
        $AircallToken = $null
        $script:AircallTokenTemp = $AircallToken
    }

    end
    {
        Write-Verbose "[$($MyInvocation.MyCommand.Name)] Function ended"
    }
}

# .\PSAircall\Public\Invoke-AircallMethod.ps1
function Invoke-AircallMethod
{
    <#
        .SYNOPSIS
        Execute a web request
 
        .DESCRIPTION
        Execute a web request
 
        .PARAMETER URI
        URL that will be called
 
        .PARAMETER Method
        Method used to make the WEB call
        Default GET
 
        .PARAMETER ContentType
        WEB call content type
        Default application/json
 
        .PARAMETER Body
        Content of the request
 
        .PARAMETER Headers
        Headers of the request
        Must be an Aircall.Token object
 
        .EXAMPLE
        Invoke-AircallMethod -URI 'https://api.aircall.io/v1' -Method Get -ContentType 'application/json' -Headers $Headers
    #>


    [CmdletBinding()]
    param(
        [Parameter( Mandatory )]
        [ValidateScript( {
                $null -ne ($_ -as [System.URI]).AbsoluteURI -and ($_ -as [System.URI]).Scheme -match '[http|https]'
            })]
        $URI,

        [Microsoft.PowerShell.Commands.WebRequestMethod]
        $Method = 'GET',

        [String]
        $ContentType,

        [Hashtable]
        $Body,

        [PSTypeName('Aircall.Token')]
        $Headers
    )

    begin
    {
        Write-Verbose "[$($MyInvocation.MyCommand.Name)] Function started"

        # Display an error message if the header is not specified
        if (-not $Headers.headers)
        {
            Write-Error -Message ('No token found. Please use Save-AircallSession before use other command.')
            continue
        }

        #region Constructe IWR Parameter
        $SplatParameters = @{
            Uri         = $Uri
            Method      = $Method
            Headers     = $Headers.headers
            ContentType = $ContentType
            TimeoutSec  = '15'
        }

        # If the Body exists, we add it to the splatting
        if ($Body)
        {
            # We convert the body to JSON before adding it to the splatting
            $SplatParameters.body = $Body | ConvertTo-Json -Compress
        }
        #endregion Constructe IWR Parameter

        #region Execute the actual query
        Write-Verbose "[$($MyInvocation.MyCommand.Name)] $($SplatParameters.Method) $($SplatParameters.Uri)"
        Write-Debug "[$($MyInvocation.MyCommand.Name)] Invoke-WebRequest with `$SplatParameters: $($SplatParameters | Out-String)"
        # Invoke the API
        try
        {
            $WebResponse = Invoke-WebRequest @SplatParameters
        }
        catch
        {
            $Exception = $_
            $WebResponse = $Exception.Exception.Response
        }

        Write-Debug "[$($MyInvocation.MyCommand.Name)] Executed WebRequest. Access `$WebResponse to see details"
        #endregion Execute the actual query
    }

    process
    {
        if ($WebResponse)
        {
            # In PowerShellCore (v6+) the StatusCode of an exception is somewhere else
            $StatusCode = $WebResponse.StatusCode
            if (-not ($StatusCode))
            {
                $StatusCode = $WebResponse.Exception.Response.StatusCode
            }
            Write-Verbose "[$($MyInvocation.MyCommand.Name)] Status code: $($StatusCode)"

            #region Code 400+
            if ($StatusCode.value__ -ge 400)
            {
                Write-Error $Exception
            }
            #endregion Code 400+

            #region Code 399-
            else
            {
                if ($WebResponse.Content)
                {
                    # Convert the JSON result to Object
                    $getContent = $WebResponse.Content | ConvertFrom-Json

                    # Retrieves all properties excluding the META property
                    $getContentProperties = ($getContent | Get-Member -MemberType NoteProperty | Where-Object { $_.name -ne 'meta' }).name

                    # Return the content of the answer with the filtered properties
                    ($getContent).$getContentProperties

                    # If I have a URL for the following page, I recursive
                    if ($getContent.meta.next_page_link)
                    {
                        $splatNextPage = @{
                            Uri         = $getContent.meta.next_page_link
                            Method      = $Method
                            Headers     = $Headers
                            ContentType = $ContentType
                        }
                        Invoke-AircallMethod @splatNextPage
                    }
                }
                else
                {
                    # No content, although statusCode < 400
                    # This could be wanted behavior of the API
                    Write-Verbose "[$($MyInvocation.MyCommand.Name)] No content was returned from."
                }
            }
            #endregion Code 399-
        }
        else
        {
            Write-Verbose "[$($MyInvocation.MyCommand.Name)] No Web result object was returned from. This is unusual!"
        }
    }

    end
    {
        Write-Verbose "[$($MyInvocation.MyCommand.Name)] Function ended"
    }
}

# .\PSAircall\Public\Save-AircallSession.ps1
function Save-AircallSession
{
    <#
        .SYNOPSIS
        Create a token with the identifiers and save in a script variable
 
        .DESCRIPTION
        Create a token with the identifiers and save in a script variable
 
        .PARAMETER ID
        ID to authenticate to the API
 
        .PARAMETER Key
        The key to authenticate to the API
 
        .EXAMPLE
        Save-AircallSession -ID $ID_API -Key $KEY_API
    #>


    [CmdletBinding()]
    [OutputType()]
    Param (
        [Parameter(Mandatory = $true)]
        [string]$ID,

        [Parameter(Mandatory = $true)]
        [string]$Key
    )

    begin
    {
        Write-Verbose "[$($MyInvocation.MyCommand.Name)] Function started"
    }

    process
    {
        # Concatenate ID with the key
        $Auth = $ID + ':' + $Key

        # Encode value in Bytes
        $Encoded = [System.Text.Encoding]::UTF8.GetBytes($Auth)

        # Convert the base 64
        $AuthorizationInfo = [System.Convert]::ToBase64String($Encoded)

        # Created the header
        $Headers = @{'Authorization' = "Basic $($AuthorizationInfo)" }

        # Create return object with special type
        $AircallToken = [PSCustomObject]@{
            PSTypeName = 'Aircall.Token'
            headers    = $Headers
        }

        # Add object to script variable
        # Used for each call
        $script:AircallTokenTemp = $AircallToken
    }

    end
    {
        Write-Verbose "[$($MyInvocation.MyCommand.Name)] Function ended"
    }
}

# .\PSAircall\Public\Number\Get-AircallNumber.ps1
function Get-AircallNumber
{
    <#
        .SYNOPSIS
        Retrieves information from a number
 
        .DESCRIPTION
        Retrieves information from a number
 
        .PARAMETER Number
        Object of a phone number
        Mandatory but can be replaced by the ID
 
        .PARAMETER ID
        ID of a phone number
        Mandatory but can be replaced by the Number parameter
        Only integer
 
        .EXAMPLE
        Get-AircallNumber -number $Number
 
        .EXAMPLE
        Get-AircallNumber -ID '202030'
 
        .EXAMPLE
        $Number | Get-AircallNumber
    #>


    [CmdletBinding()]
    [OutputType('Aircall.Number')]
    Param (
        [Parameter(Mandatory,
            ParameterSetName = 'Number',
            ValueFromPipeline)]
        [PSTypeName('Aircall.Number')]
        $Number,

        [Parameter(Mandatory,
            ParameterSetName = 'ID')]
        [int[]]
        $ID,

        [Parameter(Mandatory,
            ParameterSetName = 'All')]
        [switch]
        $All,

        [Parameter(
            ParameterSetName = 'All')]
        [ValidateRange(0, 50)]
        [int]
        $per_page = 50,

        [Parameter(
            ParameterSetName = 'All')]
        [ValidateSet('asc', 'desc')]
        [string]
        $order = 'asc'
    )

    begin
    {
        Write-Verbose "[$($MyInvocation.MyCommand.Name)] Function started"

        # Get url, method, contentType
        $SplatWeb = Get-AircallUrl -Route $MyInvocation.MyCommand.Name

        # Add token in header
        $SplatWeb.Headers = $Script:AircallTokenTemp

        # Get base of URL
        $BaseUri = $SplatWeb.uri

        # Output hashtable
        $UserInformation = @()

        # Type of output object
        $ObjectType = 'Aircall.Number'
    }

    process
    {
        # Try to get specifics users
        if (-not $All)
        {
            # If number parameter is set, replace ID variable by ID of number
            if ($Number)
            {
                $ID = $Number.id
            }

            # For each ID of number, call API
            foreach ($U in $ID)
            {

                # Generate URL
                $SplatWeb.uri = '{0}/{1}' -f $BaseUri, [int]$U

                # Try to call API
                try
                {
                    # Call API
                    $GetAircallResult = $null
                    $GetAircallResult = Invoke-AircallMethod @SplatWeb

                    # Convert object to Aircall Object
                    $UserInformation += ConvertTo-AircallObject -InputObject $GetAircallResult -Type $ObjectType
                }
                catch
                {
                    Write-Error $_
                }
            }
        }
        else
        {
            # Add per_page rate and order
            $SplatWeb.uri = '{0}?per_page={1}&order={2}' -f $SplatWeb.uri, $per_page, $order

            # Try to get all users
            try
            {
                # Call API
                $GetAircallResult = $null
                $GetAircallResult = Invoke-AircallMethod @SplatWeb

                # Convert object to Aircall Object
                $UserInformation = ConvertTo-AircallObject -InputObject $GetAircallResult -Type $ObjectType
            }
            catch
            {
                Write-Error $_
            }
        }
    }

    end
    {
        return $UserInformation
        Write-Verbose "[$($MyInvocation.MyCommand.Name)] Function ended"
    }
}

# .\PSAircall\Public\Ping\Test-AircallSession.ps1
function Test-AircallSession
{
    <#
        .SYNOPSIS
        Checks if the session information is valid
 
        .DESCRIPTION
        Checks if the session information is valid
        It uses a route to test authentication
 
        .EXAMPLE
        Test-AircallSession
    #>


    [CmdletBinding()]
    [OutputType('Object')]
    Param (
    )

    begin
    {
        Write-Verbose "[$($MyInvocation.MyCommand.Name)] Function started"

        # Get url, method, contentType
        $SplatWeb = Get-AircallUrl -Route $MyInvocation.MyCommand.Name

        # Add token in header
        $SplatWeb.Headers = $Script:AircallTokenTemp
    }

    process
    {
        try
        {
            # Call API
            $GetAircallResult = $null
            $GetAircallResult = Invoke-AircallMethod @SplatWeb
        }
        catch
        {
            Write-Error $_
        }
    }

    end
    {
        return $GetAircallResult
        Write-Verbose "[$($MyInvocation.MyCommand.Name)] Function ended"
    }
}

# .\PSAircall\Public\Teams\Get-AircallTeam.ps1
function Get-AircallTeam
{
    <#
        .SYNOPSIS
        Retrieves information from a team
 
        .DESCRIPTION
        Retrieves information from a team
 
        .PARAMETER Team
        Object of a team
        Mandatory but can be replaced by the ID
 
        .PARAMETER ID
        ID of a team
        Mandatory but can be replaced by the Team parameter
        Only integer
 
        .EXAMPLE
        Get-AircallTeam -Team $Team
 
        .EXAMPLE
        Get-AircallTeam -ID '202030'
 
        .EXAMPLE
        $Team | Get-AircallTeam
    #>


    [CmdletBinding()]
    [OutputType('Aircall.Team')]
    Param (
        [Parameter(Mandatory,
            ParameterSetName = 'Team',
            ValueFromPipeline)]
        [PSTypeName('Aircall.Team')]
        $Team,

        [Parameter(Mandatory,
            ParameterSetName = 'ID')]
        [int[]]
        $ID,

        [Parameter(Mandatory,
            ParameterSetName = 'All')]
        [switch]
        $All,

        [Parameter(
            ParameterSetName = 'All')]
        [ValidateRange(0, 50)]
        [int]
        $per_page = 50,

        [Parameter(
            ParameterSetName = 'All')]
        [ValidateSet('asc', 'desc')]
        [string]
        $order = 'asc'
    )

    begin
    {
        Write-Verbose "[$($MyInvocation.MyCommand.Name)] Function started"

        # Get url, method, contentType
        $SplatWeb = Get-AircallUrl -Route $MyInvocation.MyCommand.Name

        # Add token in header
        $SplatWeb.Headers = $Script:AircallTokenTemp

        # Get base of URL
        $BaseURI = $SplatWeb.uri

        # Output hashtable
        $TeamInformation = @()

        # Type of output object
        $ObjectType = 'Aircall.Team'
    }

    process
    {
        # Try to get specifics users
        if (-not $All)
        {

            # If team parameter is set, replace ID variable by ID of team
            if ($Team)
            {
                $ID = $Team.id
            }

            # For each ID of team, call API
            foreach ($U in $ID)
            {
                # Generate URL
                $SplatWeb.uri = '{0}/{1}' -f $BaseURI, [int]$U

                # Try to call API
                try
                {
                    # Call API
                    $GetAircallResult = $null
                    $GetAircallResult = Invoke-AircallMethod @SplatWeb

                    # Convert object to Aircall Object
                    $TeamInformation += ConvertTo-AircallObject -InputObject $GetAircallResult -Type $ObjectType
                }
                catch
                {
                    Write-Error $_
                }
            }
        }
        else
        {
            # Add per_page rate and order
            $SplatWeb.uri = '{0}?per_page={1}&order={2}' -f $SplatWeb.uri, $per_page, $order

            # Try to get all users
            try
            {
                # Call API
                $GetAircallResult = $null
                $GetAircallResult = Invoke-AircallMethod @SplatWeb

                # Convert object to Aircall Object
                $TeamInformation = ConvertTo-AircallObject -InputObject $GetAircallResult -Type $ObjectType
            }
            catch
            {
                Write-Error $_
            }
        }
    }

    end
    {
        return $TeamInformation
        Write-Verbose "[$($MyInvocation.MyCommand.Name)] Function ended"
    }
}

# .\PSAircall\Public\Teams\New-AircallTeam.ps1
function New-AircallTeam
{
    <#
        .SYNOPSIS
        Creation of a team
 
        .DESCRIPTION
        Creation of a team
 
        .PARAMETER Name
        Name of the team
        Mandatory and must not already exist
 
        .EXAMPLE
        New-AircallTeam -Name 'Marketing'
    #>


    [CmdletBinding(SupportsShouldProcess)]
    [OutputType('Aircall.Team')]
    Param (
        [Parameter(Mandatory,
            ValueFromPipeline)]
        [string[]]$Name
    )

    begin
    {
        Write-Verbose "[$($MyInvocation.MyCommand.Name)] Function started"

        # Get url, method, contentType
        $SplatWeb = Get-AircallUrl -Route $MyInvocation.MyCommand.Name

        # Add token in header
        $SplatWeb.Headers = $Script:AircallTokenTemp

        # Output hashtable
        $TeamInformation = @()

        # Type of output object
        $ObjectType = 'Aircall.Team'
    }

    process
    {

        foreach ($N in $Name)
        {
            try
            {
                # Create body splatting
                $SplatWeb.body = @{
                    name = $N
                }

                # Call API

                if ($PSCmdlet.ShouldProcess($N))
                {
                    $GetAircallResult = $null
                    $GetAircallResult = Invoke-AircallMethod @SplatWeb
                    if ($GetAircallResult)
                    {
                        # Convert object to Aircall Object
                        $TeamInformation += ConvertTo-AircallObject -InputObject $GetAircallResult -Type $ObjectType

                    }
                }
            }
            catch
            {
                Write-Error $_
            }
        }
    }

    end
    {
        return $TeamInformation
        Write-Verbose "[$($MyInvocation.MyCommand.Name)] Function ended"
    }
}

# .\PSAircall\Public\Teams\Remove-AircallTeam.ps1
function Remove-AircallTeam
{
    <#
        .SYNOPSIS
        Delete a team
 
        .DESCRIPTION
        Delete a team
 
        .PARAMETER Team
        Object of a team
        Mandatory but can be replaced by the ID
 
        .PARAMETER ID
        ID of a team
        Mandatory but can be replaced by the Team parameter
        Only integer
 
        .EXAMPLE
        Remove-AircallTeam -Team $Team
 
        .EXAMPLE
        Remove-AircallTeam -ID '202030'
 
        .EXAMPLE
        $Team | Remove-AircallTeam
    #>


    [CmdletBinding(SupportsShouldProcess)]
    Param (
        [Parameter(Mandatory,
            ParameterSetName = 'Team',
            ValueFromPipeline)]
        [PSTypeName('Aircall.Team')]
        $Team,

        [Parameter(Mandatory,
            ParameterSetName = 'ID')]
        [int[]]
        $ID
    )

    begin
    {
        Write-Verbose "[$($MyInvocation.MyCommand.Name)] Function started"

        # Get url, method, contentType
        $SplatWeb = Get-AircallUrl -Route $MyInvocation.MyCommand.Name

        # Add token in header
        $SplatWeb.Headers = $Script:AircallTokenTemp

        # Get base of URL
        $BaseUri = $SplatWeb.uri
    }

    process
    {
        # If team parameter is set, replace ID variable by ID of team
        if ($Team)
        {
            $ID = $Team.id
        }

        # For each ID of team, call API
        foreach ($U in $ID)
        {
            # Generate URL
            $SplatWeb.uri = '{0}/{1}' -f $BaseUri, [int]$U

            # Try to call API
            try
            {
                # Call API
                if ($PSCmdlet.ShouldProcess($U))
                {
                    Invoke-AircallMethod @SplatWeb | Out-Null
                }
            }
            catch
            {
                Write-Error $_

            }
        }
    }

    end
    {
        Write-Verbose "[$($MyInvocation.MyCommand.Name)] Function ended"
    }
}

# .\PSAircall\Public\Users\Get-AircallUser.ps1
function Get-AircallUser
{
    <#
        .SYNOPSIS
        Retrieve a user's information
 
        .DESCRIPTION
        Retrieve a user's information
 
        .PARAMETER User
        Object of a user
        Mandatory but can be replaced by the ID
 
        .PARAMETER ID
        ID of a user
        Mandatory but can be replaced by the User parameter
        Only integer
 
        .EXAMPLE
        Get-AircallUser -User $User
 
        .EXAMPLE
        Get-AircallUser -ID '202030'
 
        .EXAMPLE
        $User | Get-AircallUser
 
        .EXAMPLE
        Get-AircallUsers | Get-AircallUser
        Retrieve all users and get the information for each user
    #>


    [CmdletBinding()]
    [OutputType('Aircall.User')]
    Param (
        [Parameter(Mandatory,
            ParameterSetName = 'User',
            ValueFromPipeline)]
        [PSTypeName('Aircall.User')]
        $User,

        [Parameter(Mandatory,
            ParameterSetName = 'ID')]
        [int[]]
        $ID,

        [Parameter(Mandatory,
            ParameterSetName = 'All')]
        [switch]
        $All,

        [Parameter(
            ParameterSetName = 'All')]
        [ValidateRange(0, 50)]
        [int]
        $per_page = 50,

        [Parameter(
            ParameterSetName = 'All')]
        [ValidateSet('asc', 'desc')]
        [string]
        $order = 'asc'
    )

    begin
    {
        Write-Verbose "[$($MyInvocation.MyCommand.Name)] Function started"

        # Get url, method, contentType
        $SplatWeb = Get-AircallUrl -Route $MyInvocation.MyCommand.Name

        # Add token in header
        $SplatWeb.Headers = $Script:AircallTokenTemp

        # Get base of URL
        $BaseUri = $SplatWeb.uri

        # Output hashtable
        $userInformation = @()

        # Type of output object
        $ObjectType = 'Aircall.User'
    }

    process
    {
        # Try to get specifics users
        if (-not $All)
        {
            # If user parameter is set, replace ID variable by ID of user
            if ($User)
            {
                $ID = $User.id
            }

            # For each ID of user, call API
            foreach ($U in $ID)
            {
                # Generate URL
                $SplatWeb.uri = '{0}/{1}' -f $BaseUri, [int]$U

                # Try to call API
                try
                {
                    # Call API
                    $GetAircallResult = $null
                    $GetAircallResult = Invoke-AircallMethod @SplatWeb

                    # Convert object to Aircall Object
                    $userInformation += ConvertTo-AircallObject -InputObject $GetAircallResult -Type $ObjectType
                }
                catch
                {
                    Write-Error $_
                }
            }
        }
        else
        {
            # Add per_page rate and order
            $SplatWeb.uri = '{0}?per_page={1}&order={2}' -f $SplatWeb.uri, $per_page, $order

            try
            {
                # Call API
                $GetAircallResult = $null
                $GetAircallResult = Invoke-AircallMethod @SplatWeb

                # Convert object to Aircall Object
                $userInformation = ConvertTo-AircallObject -InputObject $GetAircallResult -Type $ObjectType
            }
            catch
            {
                Write-Error $_
            }
        }
    }

    end
    {
        return $userInformation
        Write-Verbose "[$($MyInvocation.MyCommand.Name)] Function ended"
    }
}

# .\PSAircall\Public\Users\New-AircallUser.ps1
function New-AircallUser
{
    <#
        .SYNOPSIS
        Creation of a user
 
        .DESCRIPTION
        Creation of a user
 
        .PARAMETER Email
        Name of the team
        Mandatory and must not already exist
 
        .PARAMETER FirstName
        First name of a user
 
        .PARAMETER LastName
        Last name of a user
 
        .PARAMETER AvailabilityStatus
        Account availability.
        Only three choices: available, custom, unavailable
        Default: Available
 
        .PARAMETER IsAdmin
        If the user is admin or not
        Default False
 
        .EXAMPLE
        New-AircallUser -Email 'joe.doe@aircall.com' -FirstName 'Joe' -LastName 'Doe'
 
        .EXAMPLE
        New-AircallUser -Email 'joe.doe@aircall.com' -FirstName 'Joe' -LastName 'Doe' -isAdmin $true -AvailabilityStatus unavailable
    #>


    [CmdletBinding(SupportsShouldProcess)]
    [OutputType('Aircall.User')]
    Param (
        [Parameter(Mandatory,
            ValueFromPipeline)]
        [string]$Email,

        [Parameter(Mandatory,
            ValueFromPipeline)]
        [string]$FirstName,

        [Parameter(Mandatory,
            ValueFromPipeline)]
        [string]$LastName,

        [Parameter(ValueFromPipeline)]
        [ValidateSet('available', 'custom', 'unavailable')]
        [string]$AvailabilityStatus = 'available',

        [Parameter(ValueFromPipeline)]
        [switch]$IsAdmin = $false
    )

    begin
    {
        Write-Verbose "[$($MyInvocation.MyCommand.Name)] Function started"

        # Get url, method, contentType
        $SplatWeb = Get-AircallUrl -Route $MyInvocation.MyCommand.Name

        # Add token in header
        $SplatWeb.Headers = $Script:AircallTokenTemp

        # Output hashtable
        $userInformation = @()

        # Type of output object
        $ObjectType = 'Aircall.User'
    }

    process
    {
        try
        {
            # Create body splatting
            $SplatWeb.body = @{
                email               = $Email
                first_name          = $FirstName
                last_name           = $LastName
                availability_status = $AvailabilityStatus
                is_admin            = $IsAdmin
            }

            # Call API
            $GetAircallResult = $null
            if ($PSCmdlet.ShouldProcess($Email))
            {
                $GetAircallResult = Invoke-AircallMethod @SplatWeb

                # Convert object to Aircall Object
                $userInformation += ConvertTo-AircallObject -InputObject $GetAircallResult -Type $ObjectType
            }
        }
        catch
        {
            Write-Error $_
        }
    }

    end
    {
        return $userInformation
        Write-Verbose "[$($MyInvocation.MyCommand.Name)] Function ended"
    }
}

# .\PSAircall\Public\Users\Remove-AircallUser.ps1
function Remove-AircallUser
{
    <#
        .SYNOPSIS
        Delete a user
 
        .DESCRIPTION
        Delete a user
 
        .PARAMETER Team
        Object of a User
        Mandatory but can be replaced by the ID
 
        .PARAMETER ID
        ID of a user
        Mandatory but can be replaced by the User parameter
        Only integer
 
        .EXAMPLE
        Remove-AircallUser -User $User
 
        .EXAMPLE
        Remove-AircallUser -ID '202030'
 
        .EXAMPLE
        $User | Remove-AircallUser
    #>


    [CmdletBinding(SupportsShouldProcess)]
    Param (
        [Parameter(Mandatory,
            ParameterSetName = 'User',
            ValueFromPipeline)]
        [PSTypeName('Aircall.User')]
        $User,

        [Parameter(Mandatory,
            ParameterSetName = 'ID')]
        [int[]]
        $ID
    )

    begin
    {
        Write-Verbose "[$($MyInvocation.MyCommand.Name)] Function started"

        # Get url, method, contentType
        $SplatWeb = Get-AircallUrl -Route $MyInvocation.MyCommand.Name

        # Add token in header
        $SplatWeb.Headers = $Script:AircallTokenTemp

        # Get base of URL
        $BaseUri = $SplatWeb.uri
    }

    process
    {
        # If user parameter is set, replace ID variable by ID of user
        if ($User)
        {
            $ID = $User.id
        }

        # For each ID of user, call API
        foreach ($U in $ID)
        {
            # Generate URL
            $SplatWeb.uri = '{0}/{1}' -f $BaseUri, [int]$U

            # Try to call API
            try
            {
                # Call API
                if ($PSCmdlet.ShouldProcess($U))
                {
                    Invoke-AircallMethod @SplatWeb
                }
            }
            catch
            {
                Write-Error $_
            }
        }
    }

    end
    {
        Write-Verbose "[$($MyInvocation.MyCommand.Name)] Function ended"
    }
}