Public/Get-iPilotNumber.ps1

Function Get-iPilotNumber {
    <#
        .Synopsis
        Displays a list of numbers and FOC date if not yet ported.

        .Description
        Returns numbers in iPilot domain with optional filters.

        .Parameter FilterByFirstName
        Filter results by user's First Name.

        .Parameter FilterByLastName
        Filter results by user's Last Name.

        .Parameter FilterByTelephoneNumber
        Filter results by TelephoneNumber (10-digits or less for a partial match).

        .Parameter FilterByUserPrincipalName
        Filter results by user's User Principal Name.

        .Parameter FilterByNote
        Filter results by user's iPilot Note field value.

        .Parameter FilterByStatus
        Filter results by iPilot status.

        .Parameter ApiVersion
        Version of the NuWave iPilot to use. Defaults to v1.

        .Parameter iPilotDomain
        iPilot Domain Name.

        .Parameter NumberOfRecords
        Total number of records returned by API (limit 32767)

        .Parameter PageSize
        Number of records returned by API for paging (limit 100)

        .Parameter Credential
        Credentials for iPilot API

        .Example
        # Get numbers with the status set to Ported in the contoso.com iPilot domain
        Get-iPilotNumber -Status Ported -iPilotDomain contoso.com

        .Example
        # Get numbers with the Sales Note in the contoso.com iPilot domain with Verbose output
        Get-iPilotNumber -FilterBy Note -Note "Sales" -iPilotDomain contoso.com -Verbose

        .Example
        # Get all numbers not assigned to a user
        Get-iPilotNumber -Available

        .Example
        # Get all numbers assigned to a user
        Get-iPilotNumber -UserPrincipalNameAssigned
    #>

    Param (
        [System.String] 
            $FilterByUserPrincipalName,
        [ValidateSet("All","Activated","Cancelled","Confirmed","Complete","Disconnect","New","OtherReject","Pending","PendingDisconnect","ReceivedFOC","Rejected","Removed","Save","Sent","TelephoneInvactiveDisconnected")]
        [System.String] 
            $FilterByStatus,
        [System.String] 
            $FilterByFirstName,
        [System.String] 
            $FilterByLastName,
        [System.String]
            $FilterByNote,
        [System.Int64] [ValidateRange(1,9999999999)]
            $FilterByTelephoneNumber,
        [Switch]
            $Available,
        [Switch] 
            $UserPrincipalNameAssigned,
        [System.String]
            $ApiUrl = "https://api.nuwave.com", 
        [System.String]
            $ApiKey, 
        [System.String]
            $ApiVersion = "v1",
        [System.String]
            $iPilotDomain,
        [System.Int16]
            $NumberOfRecords = [System.Int16]::MaxValue,
        [System.Int16] [ValidateRange(1,100)]
            $PageSize = 100,
        [System.Management.Automation.PSCredential] 
            $Credential,
        [Switch]
            $Verbose,
        [Switch]
            $Debug
     )

    Begin {
        # UserPrincipalName validation
        If ($FilterByUserPrincipalName -and $FilterByUserPrincipalName -notlike "*@*.*") {
            throw "Check the formatting of the user's User Principal Name. Format should be jdoe@contoso.com"
        }

        # Set iPilot Domain
        if (!$global:iPilotDomain -and !$iPilotDomain) {
            throw "Run Get-iPilotTeamsDomain or provide domain using -iPilotDomain"
        } elseif (!$iPilotDomain) {
            $iPilotDomain = $global:iPilotDomain
            Write-Verbose "iPilot Domain: $iPilotDomain"
        } # else use passed in iPilotDomain

        if ($Available.IsPresent -and $UserPrincipalNameAssigned.IsPresent) {
            throw "Conflicting switches in use. Can use -Available or -UserPrincipalNameAssigned but not both."
        }
    }

    Process {
        # Verbose Switch
        if($PSBoundParameters.containskey("Verbose")) {
            $PreviousVerbosePreference = $VerbosePreference
            $VerbosePreference = "continue"
        }

        # Debug Switch
        if($PSBoundParameters.containskey("Debug")) {
            $PreviousDebugPreference = $DebugPreference
            $DebugPreference = "continue"
        }

        # Get/re-use OAuth Token
        Initialize-iPilotSession -ApiUrl $ApiUrl -ApiVersion $ApiVersion -ApiKey $ApiKey -Credential $Credential

        # Determine if paging is needed
        if ($NumberOfRecords -le $PageSize) {
            $Pages = 1
        } else {
            $Pages = [math]::Ceiling($NumberOfRecords/$PageSize)
            Write-Verbose "Pages Needed (Batches of $PageSize): $Pages"
        }

        #region Add each filter to the Uri

            $Filter = $null
            Add-Type -AssemblyName System.Web

            # Available Numbers
            if ($Available.IsPresent) {
                Write-Verbose "Filtering by Assigned set to No"
                $Filter += "&assigned=false"
            }

            # UPN is present
            if ($UserPrincipalNameAssigned.IsPresent) {
                Write-Verbose "Filtering by UPN set to Added"
                $Filter += "&upn=added"
            }
                
            # First Name
            If ($FilterByFirstName) {
                $FilterByFirstName = [System.Web.HttpUtility]::UrlPathEncode($FilterByFirstName) 
                Write-Verbose "Filtering by Status set to $FilterByFirstName"
                $Filter += "&firstname=$FilterByFirstName"
            }

            # Last Name
            If ($FilterByLastName) {
                $FilterByLastName = [System.Web.HttpUtility]::UrlPathEncode($FilterByLastName) 
                Write-Verbose "Filtering by Last Name set to $FilterByLastName"
                $Filter += "&lastname=$FilterByLastName"
            }

            # TelephoneNumber
            If ($FilterByTelephoneNumber) {
                Write-Verbose "Filtering by telephone number containing: $FilterByTelephoneNumber"
                $Filter += "&telephoneNumber=$FilterByTelephoneNumber"
            }

            # UserPrincipalName
            If ($FilterByUserPrincipalName) {
                Write-Verbose "Filtering by UserPrincipalName: $FilterByUserPrincipalName"
                $Filter += "&upn=$FilterByUserPrincipalName"
            }

            # Note
            If ($FilterByNote) {
                $FilterByNote = [System.Web.HttpUtility]::UrlPathEncode($FilterByNote) 
                Write-Verbose "Filtering by Note set to $FilterByNote"
                $Filter += "&note=$FilterByNote"
            }

            # Status
            If ($FilterByStatus) {

                # Convert status to API value
                $FilterByStatusEncoded = switch ($FilterByStatus) {
                    All {"ALL"}
                    Activated {"ACTIVATED"}
                    Cancelled {"CANCELLED"}
                    Confirmed {"COMFIRMED"}
                    Complete {"COMPLETE"}
                    Disconnect {"DISCONNECT"}
                    New {"NEW"}
                    OtherReject {"OTHER REJECT - PLEASE SEE NOTES"}
                    Pending {"PENDING"}
                    PendingDisconnect {"PENDING DISCONNECT"}
                    #Ported {"Ported"}
                    ReceivedFOC {"RECEIVED FOC"}
                    Rejected {"REJECTED"}
                    Removed {"REMOVED"}
                    Save {"SAVE"}
                    Sent {"SENT"}
                    TelephoneInvactiveDisconnected {"TN INACTIVE/DISCONNECTED"}
                }

                # All status filter
                if ($FilterByStatusEncoded -eq "ALL") {
                    Write-Verbose "All status filter specified, using no status filter"
                } else {
                    Write-Verbose "Filtering by Status set to $FilterByStatusEncoded (Unencoded: $FilterByStatus)"
                    $Filter += "&status=$FilterByStatusEncoded"    
                }
            }

        #endregion Add each filter to the Uri

        # Execute the REST API
        $GetiPilotNumberRequestUri = "$ApiUrl/$ApiVersion/msteams/$iPilotDomain/numbers"
        Try {
            
            # Loop request for # of required pages
            $GetiPilotNumberResponses = @()
            $Page = 1

            Do {

                # Limit number of records if last page should return less than $PageSize records
                Write-Debug "Page = $Page"
                Write-Debug "PageSize = $Pagesize"

                # Splat Invoke-RestMethod parameters
                $RequestUri = $GetiPilotNumberRequestUri + "?limit=$PageSize&page=$Page" + $Filter 
                Write-Verbose "Method: Get`nRequest Uri: $RequestUri"
                $GetiPilotAvailableNumberInvokeParams = @{
                    Uri = $RequestUri
                    Method = "Get"
                    Headers = @{
                        "X-Access-Token" = $global:iPilotOAuthToken.access_token
                        "x-api-key"      = $global:iPilotApiKey
                    }        
                } 

                # Get reponse
                $GetiPilotNumberResponse = Invoke-RestMethod @GetiPilotAvailableNumberInvokeParams
                $GetiPilotNumberResponses += $GetiPilotNumberResponse
                Write-Debug "GetiPilotNumberResponse:`n$($GetiPilotNumberResponse | Format-Table -AutoSize | Out-String)"
                Write-Verbose "GetiPilotNumberResponse Count:$($GetiPilotNumberResponses.Count)"
                
                # Exit loop if number of records returned is less than the requested number of records
                if (($GetiPilotNumberResponse.Count -eq 0) -or $GetiPilotNumberResponse.status -like "No data found*") {
                    Write-Debug "Reponse on page $Page is empty, breaking out of loop"
                    Write-Verbose "Total number of numbers returned for filters specified ($($GetiPilotNumberResponses.Count))"
                    break
                }
            } While (($Page = $Page + 1) -le $Pages)

        } Catch {
            Write-Error "Failed to retreive iPilot Phone Number(s)`nRequestUri: $($RequestUri). Error: $($_)"
            break
        }

        # Return Available Numbers
        if ($GetiPilotNumberResponses.Count -ge 1) {

            # Change to PascalCase
            $TelephoneNumbers = $GetiPilotNumberResponses | 
                Select-Object @{Name = 'TelephoneNumber' ; Expression = {$_.tn}},
                @{Name = 'OrderType' ; Expression = {$_.orderType}},
                @{Name = 'Type' ; Expression = {$_.type}},
                @{Name = 'SubType' ; Expression = {$_.subType}},
                @{Name = 'RouteLabel' ; Expression = {$_.routeLabel}},
                @{Name = 'UserID' ; Expression = {$_.provisionUser.id}},
                @{Name = 'UserPrincipalName' ; Expression = {$_.provisionUser.upn}},
                @{Name = 'FirstName' ; Expression = {$_.provisionUser.firstName}},
                @{Name = 'LastName' ; Expression = {$_.provisionUser.lastName}},
                @{Name = 'Note' ; Expression = {$_.provisionUser.note}},
                @{Name = 'ProvisionUserStatus' ; Expression = {$_.provisionUser.status}},
                @{Name = 'TelephoneNumberPortInDetails' ; Expression = {$_.tnPortinDetails}},
                @{Name = 'TelephoneNumberFeatures' ; Expression = {$_.tnFeatures}},
                @{Name = 'Status' ; Expression = {$_.status}},
                @{Name = 'ProvisionUser' ; Expression = {$_.provisionUser}},
                @{Name = 'ActivatedDate' ; Expression = {$_.activatatedDate}}

            if ($UserPrincipalNameAssigned.IsPresent) {
                Write-Verbose "Filtering results to numbers with UserPrincipalName assigned"
                $TelephoneNumbers = $TelephoneNumbers | Where-Object {$_.UserPrincipalName}
            }

            return $TelephoneNumbers
            
        } else {
            Write-Error "No available numbers using the specified filters."
            return $null
        }

        # Verbose Switch
        if($PSBoundParameters.containskey("Verbose")) {
            $VerbosePreference = $PreviousVerbosePreference
        }

        # Debug Switch
        if($PSBoundParameters.containskey("Debug")) {
            $DebugPreference = $PreviousDebugPreference
        }
    }
}