Freshdesk.psm1

$baseUrl = "https://guidnew.freshdesk.com/api/v2";

<#
.SYNOPSIS
Connects to Freshdesk.
 
.DESCRIPTION
Credentials can be persisted using https://www.powershellgallery.com/packages/CredentialsManager/ by setting the parameter UseCredentialsManager to $True.
o $Credential -eq $Null -and $UseCredentialsManager -eq $Null -> credentials are requested and are not persisted
o $Credential -ne $Null -and $UseCredentialsManager -eq $Null -> passed credentials are used and not persisted
o $Credential -ne $Null -and $UseCredentialsManager -ne $Null -> passed credentials are used and persisted
o $Credential -eq $Null -and $UseCredentialsManager -ne $Null -> Persisted credentials are used
 
.PARAMETER Credential
Credential to access Freshdesk with. I not provided they get requested.
 
.PARAMETER UseCredentialsManager
If $True, credentials are read and written using the CredentialsManager. Only Password part, containing the APIKey, is used.
 
#>

function Connect-FD
{
    [CmdletBinding()]
    Param(
       [PSCredential]$Credential,
       [Boolean]$UseCredentialsManager = $False
    ) #end param

    # check module prerequisites
    if($UseCredentialsManager)
    {
        $module = Get-Module -ListAvailable -Name "CredentialsManager";
        if (!$module) { throw "Module 'CredentialsManager' needed. Please install executing 'Install-Module -Name CredentialsManager' as Administrator."; }
    }
    
    if($UseCredentialsManager -and $Credential -eq $Null)
    {
        $Credential = Read-Credential -ListAvailable | Where { $_.Environment -eq "Freshdesk" }
    }
    if(!$Credential) { $Credential = Get-Credential -Message "Please enter API Key for Freshdesk as username (password can be anything)."; }
    if($UseCredentialsManager) 
    { 
        Write-Credential "Freshdesk" -Credential $Credential; 
    }

    $script:base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $Credential.UserName,$Credential.Password)))
}

<#
.SYNOPSIS
Get Tickets by Filter from Freshdesk
 
.DESCRIPTION
If no ticket is found, an empty array is returned.
 
.PARAMETER FilterName
Name of filter to get tickets for.
 
#>

function Get-FDTickets
{
    [CmdletBinding()]
    Param(
       [string]$FilterName
    )

    if(!$script:base64AuthInfo) { Connect-FD -UseCredentialsManager $True; }

    $parameters = @{ }
    if($Name) { $parameters.Add("filter", $FilterName) }
    $uri = New-HttpQueryString "${baseUrl}/tickets" $parameters

    $response = Invoke-RestMethod -Uri $uri -Method Get -ContentType "application/json" -Headers @{Authorization=("Basic {0}" -f $script:base64AuthInfo)};

    return $response
}

<#
.SYNOPSIS
Add a Ticket
 
.DESCRIPTION
 
.PARAMETER Subject
Subject of the ticket to create.
 
.PARAMETER Mail
Mail of Ticket requester.
 
.PARAMETER Description
Description of the ticket to create.
 
.PARAMETER Type
Type to set ticket to.
 
#>

function Add-FDTicket
{
    [CmdletBinding()]
    Param(
       [Parameter(Mandatory=$true)][string]$Subject,
       [Parameter(Mandatory=$true)][string]$Mail,
       [string]$Description = "<div></div>",
       [string]$Type
    )

    if(!$script:base64AuthInfo) { Connect-FD -UseCredentialsManager $True; }

    $parameters = @{ }
    $uri = New-HttpQueryString "${baseUrl}/tickets" $parameters

    # Also Subject and description should be optional but needed to be passed. So for description we use a defaultvalue of empty html
    if(!$Description) { $Description = "<div></div>" }
    
    $body = @{ subject=$Subject; email=$Mail; description=$Description};
    if($Type) { $body.Add("type", $Type) }
    # documentation says that these values are default if not set, put request fails if they are not passed.
    $body.Add("priority", 1)
    $body.Add("status", 2)
    $bodyAsJson = ConvertTo-JSON( $body );

    $response = Invoke-RestMethod -Uri $uri -Method Post -Body $bodyAsJson -ContentType "application/json" -Headers @{Authorization=("Basic {0}" -f $script:base64AuthInfo)};

    return $response
}

<#
.SYNOPSIS
Modify a Ticket
 
.DESCRIPTION
 
.PARAMETER Id
Id of ticket to get.
 
.PARAMETER Mail
Mail of Ticket requester.
 
.PARAMETER Type
Type to set ticket to.
 
#>

function Edit-FDTicket
{
    [CmdletBinding()]
    Param(
       [Parameter(Mandatory=$true)][int]$Id,
       [string]$Mail,
       [string]$Type
    )

    if(!$script:base64AuthInfo) { Connect-FD -UseCredentialsManager $True; }

    $parameters = @{ }
    $uri = New-HttpQueryString "${baseUrl}/tickets/${Id}" $parameters

    $body = @{};
    if($Mail) { $body.Add("email", $Mail) }
    if($Type) { $body.Add("type", $Type) }
    $bodyAsJson = ConvertTo-JSON( $body );

    $response = Invoke-RestMethod -Uri $uri -Method Put -Body $bodyAsJson -ContentType "application/json" -Headers @{Authorization=("Basic {0}" -f $script:base64AuthInfo)};

    return $response
}

<#
.SYNOPSIS
Get Ticket by Id
 
.DESCRIPTION
 
.PARAMETER Id
Id of ticket to get.
 
#>

function Get-FDTicket
{
    [CmdletBinding()]
    Param(
       [Parameter(Mandatory=$true)][int]$Id
    )

    if(!$script:base64AuthInfo) { Connect-FD -UseCredentialsManager $True; }

    $parameters = @{ }
    $uri = New-HttpQueryString "${baseUrl}/tickets/${Id}" $parameters

    $response = Invoke-RestMethod -Uri $uri -Method Get -ContentType "application/json" -Headers @{Authorization=("Basic {0}" -f $script:base64AuthInfo)};

    return $response
}

<#
.SYNOPSIS
Get Contact by Id
 
.DESCRIPTION
 
.PARAMETER Id
Id of contact to receive.
 
#>

function Get-FDContact
{
    [CmdletBinding()]
    Param(
       [Parameter(Mandatory=$true)][string]$Id
    )

    if(!$script:base64AuthInfo) { Connect-FD -UseCredentialsManager $True; }

    $parameters = @{ }
    $uri = New-HttpQueryString "${baseUrl}/contacts/${Id}" $parameters

    $response = Invoke-RestMethod -Uri $uri -Method Get -ContentType "application/json" -Headers @{Authorization=("Basic {0}" -f $script:base64AuthInfo)};
    return $response
}

<#
.SYNOPSIS
Get Contact by Mail
 
.DESCRIPTION
 
.PARAMETER Mail
Mail of contact to receive.
 
#>

function Get-FDContactByMail
{
    [CmdletBinding()]
    Param(
       [Parameter(Mandatory=$true)][string]$Mail
    )

    if(!$script:base64AuthInfo) { Connect-FD -UseCredentialsManager $True; }

    $parameters = @{ "query"="`"email:'${Mail}'`""}
    $uri = New-HttpQueryString "${baseUrl}/search/contacts" $parameters

    $response = Invoke-RestMethod -Uri $uri -Method Get -ContentType "application/json" -Headers @{Authorization=("Basic {0}" -f $script:base64AuthInfo)};
    if($response.total -eq 0) { return @(); }

    return $response.results
}

## Private Functions

function New-HttpQueryString
{
    [CmdletBinding()]
    param 
    (
        [Parameter(Mandatory = $true)][String]$Uri,
        [Parameter(Mandatory = $true)][Hashtable]$QueryParameter
    )
 
    # Add System.Web
    Add-Type -AssemblyName System.Web
 
    # Create a http name value collection from an empty string
    $nvCollection = [System.Web.HttpUtility]::ParseQueryString([String]::Empty)
 
    foreach ($key in $QueryParameter.Keys)
    {
        $nvCollection.Add($key, $QueryParameter.$key)
    }
 
    # Build the uri
    $uriRequest = [System.UriBuilder]$uri
    $uriRequest.Query = $nvCollection.ToString()
 
    return $uriRequest.Uri.OriginalString
}