Public/Support/Helper/Get-MatchingPatternForCallRestriction.ps1

# Module: TeamsFunctions
# Function: Tenant Voice Configuration
# Author: David Eberhardt
# Updated: 29-AUG-2022
# Status: RC




function Get-MatchingPatternForCallRestriction {
  <#
  .SYNOPSIS
    Returns matching patterns for Voice Routes restricted to specific levels
  .DESCRIPTION
    Returns a custom Object containing matching patterns for different Call Restrictions applied to Voice Routes
    Builds on the information provided in Get-ISO3166Country and returns custom Object containing matching patterns.
    The Object contains the Patterns for the following Call Restriction levels
    - Unrestricted is hardcoded to '.*'
    - International is allowing all Calls starting with a + or Emergency Services Numbers
    - National is allowing all Calls starting with a + followed by the Country Dial Code or Emergency Services Numbers
    - The Emergency Services Pattern is currently hardcoded/catch-all.
    Please see notes for details
  .PARAMETER Country
    ISO 3166-alpha2 - Two Letter Country Code or
    ISO 3166-alpha3 - Three Letter Country Code. A match must be found through Get-ISO3166Country.
  .EXAMPLE
    Get-MatchingPatternForCallRestriction -Country DE
 
    Returns entry for Country "Germany" queried from the TwoLetterCode (ISO3166-Alpha2) DE
  .EXAMPLE
    Get-MatchingPatternForCallRestriction -Country AUT
 
    Returns entry for Country "Austria" queried from the ThreeLetterCode (ISO3166-Alpha3) AUT
  .INPUTS
    System.String
  .OUTPUTS
    System.Object
  .NOTES
    This CmdLet builds on Get-ISO3166Country and expects a match to be found there. From most to least restrictive:
    EmergencyOnly: Allowing only Calls to these numbers
      '<EmergencyPattern>'
    National: All Calls starting with a + followed by the Country Dial Code or Emergency Services Numbers
      '^+<CountryDialCode>|<EmergencyPattern>'
    International: Allowing all Calls starting with a + or Emergency Services Numbers
      '^+|<EmergencyPattern>'
    Unrestricted: Hardcoded to allow all calls
        '.*'
 
    The Pattern for Unrestricted is hardcoded to '.*'
    The Pattern for International is allowing all Calls starting with a + or Emergency Services Numbers
    The Pattern for National is allowing all Calls starting with a + followed by the Country Dial Code or Emergency Services Numbers
    The Emergency Services Pattern is currently hardcoded.
    A catch-all matching pattern covering most countries' Service Numbers ('any 2-5 digit number') is used
    If a more granular pattern is available, this pattern is added here over time.
 
    This CmdLet was initially geared towards querying the UC DialPlans API to return the Emergency Services pattern
    This is not yet available as the API requires a key to return usable data.
  .COMPONENT
    SupportingFunction
  .FUNCTIONALITY
    Retruns a List of matching patterns for different Call Restrictions for one ISO3166 Country
  .LINK
    https://github.com/DEberhardt/TeamsFunctions/tree/main/docs/Get-MatchingPatternForCallRestriction.md
  .LINK
    https://github.com/DEberhardt/TeamsFunctions/tree/main/docs/about_Supporting_Functions.md
  .LINK
    https://github.com/DEberhardt/TeamsFunctions/tree/main/docs/
  #>


  [CmdletBinding()]
  [OutputType([System.Object[]])]

  param (
    [Parameter(HelpMessage = 'ISO3166-alpha-2 or alpha-3 country code')]
    [ValidatePattern('^([A-Z])?[A-Z][A-Z]$')]
    $Country
  )

  begin {
    Show-FunctionStatus -Level RC
    Write-Verbose -Message "[BEGIN ] $($MyInvocation.MyCommand.Name)"
    Write-Verbose -Message "Need help? Online: $global:TeamsFunctionsHelpURLBase$($MyInvocation.MyCommand.Name)`.md"

    # Setting Preference Variables according to Upstream settings
    if (-not $PSBoundParameters.ContainsKey('Verbose')) { $VerbosePreference = $PSCmdlet.SessionState.PSVariable.GetValue('VerbosePreference') }
    if (-not $PSBoundParameters.ContainsKey('Confirm')) { $ConfirmPreference = $PSCmdlet.SessionState.PSVariable.GetValue('ConfirmPreference') }
    if (-not $PSBoundParameters.ContainsKey('WhatIf')) { $WhatIfPreference = $PSCmdlet.SessionState.PSVariable.GetValue('WhatIfPreference') }
    if (-not $PSBoundParameters.ContainsKey('Debug')) { $DebugPreference = $PSCmdlet.SessionState.PSVariable.GetValue('DebugPreference') } else { $DebugPreference = 'Continue' }
    if ( $PSBoundParameters.ContainsKey('InformationAction')) { $InformationPreference = $PSCmdlet.SessionState.PSVariable.GetValue('InformationAction') } else { $InformationPreference = 'Continue' }


    # Querying ISO Country
    $ISO3166CountryParams = @{
      $(if ( $Country.length -EQ 2 ) { 'TwoLetterCode' } else { 'ThreeLetterCode' } ) = $Country
    }
    $ISOCountry = Get-ISO3166Country @ISO3166CountryParams

    if ( -not $ISOCountry ) {
      throw "Country '$Country' not found in Get-ISOCountryCode - no restrictions can be populated"
    }

    # UC Dial Plans Demo key (to be replaced/refactored)
    $ApiKey = 'abc1234567890xyz'
  }

  process {

    $DialCode = $ISOCountry.DialCode

    #TODO This could be done via UC DialPlans API
    # Determining Service pattern
    if ( $DialCode -match '^1(?<npa>[0-9]{3})' ) {
      # NORAM numbering scheme
      $CountryDialCode = 1
      $NORAMnpaCode = $matches.npa
      #$NORAMnxxCode = "TBC" #unknown how to retrieve this!
      $Delimiter = "npa=$NORAMnpaCode&nxx=$NORAMnxxCode"
    }
    else {
      # rest of the World - as-is
      $CountryDialCode = $DialCode
      #$AreaDialCode = "TBC" #unknown how to retrieve this!
      #$Delimiter = "areacode=$AreaDialCode"
    }
    $URI = "https://www.ucdialplans.com/queryapi/?countrycode=$CountryDialCode&$Delimiter&apikey=$ApiKey"

    try {
      #$UCDialPlan = Invoke-RestMethod -Method Get -Uri $URI -ErrorAction Stop
      #$EMSpattern = $UCDialPlan.data.routes.service.pattern
      throw
    }
    catch {
      $EMSpattern = $null
    }

    # Hard-coding Service pattern
    #TODO This could be replaced by the above
    $EMS = '^(000|[19]([0-9]{2})|[0-9]11)$' # Catch-All for most prominent three-digit Emergency Numbers
    $SVN = '^[0-9]{2-5}$' # Catch-All 2-5 digit number, not the best, but servicable
    $TBC = "$EMS|$SVN"
    $EMSPattern = switch ($ISOCountry.TwoLetterCode) {
      'AD' { "$TBC" }
      'AE' { "$TBC" }
      'AF' { "$TBC" }
      'AG' { "$TBC" }
      'AI' { "$TBC" }
      'AL' { "$TBC" }
      'AM' { "$TBC" }
      'AO' { "$TBC" }
      'AQ' { "$TBC" }
      'AR' { "$TBC" }
      'AS' { "$TBC" }
      'AT' { "$TBC" }
      'AU' { "$TBC" }
      'AW' { "$TBC" }
      'AX' { "$TBC" }
      'AZ' { "$TBC" }
      'BA' { "$TBC" }
      'BB' { "$TBC" }
      'BD' { "$TBC" }
      'BE' { "$TBC" }
      'BF' { "$TBC" }
      'BG' { "$TBC" }
      'BH' { "$TBC" }
      'BI' { "$TBC" }
      'BJ' { "$TBC" }
      'BL' { "$TBC" }
      'BM' { "$TBC" }
      'BN' { "$TBC" }
      'BO' { "$TBC" }
      'BQ' { "$TBC" }
      'BR' { "$TBC" }
      'BS' { "$TBC" }
      'BT' { "$TBC" }
      'BV' { "$TBC" }
      'BW' { "$TBC" }
      'BY' { "$TBC" }
      'BZ' { "$TBC" }
      'CA' { "$TBC" }
      'CC' { "$TBC" }
      'CD' { "$TBC" }
      'CF' { "$TBC" }
      'CG' { "$TBC" }
      'CH' { "$TBC" }
      'CI' { "$TBC" }
      'CK' { "$TBC" }
      'CL' { "$TBC" }
      'CM' { "$TBC" }
      'CN' { "$TBC" }
      'CO' { "$TBC" }
      'CR' { "$TBC" }
      'CU' { "$TBC" }
      'CV' { "$TBC" }
      'CW' { "$TBC" }
      'CX' { "$TBC" }
      'CY' { "$TBC" }
      'CZ' { "$TBC" }
      'DE' { "$TBC" }
      'DJ' { "$TBC" }
      'DK' { "$TBC" }
      'DM' { "$TBC" }
      'DO' { "$TBC" }
      'DZ' { "$TBC" }
      'EC' { "$TBC" }
      'EE' { "$TBC" }
      'EG' { "$TBC" }
      'EH' { "$TBC" }
      'ER' { "$TBC" }
      'ES' { "$TBC" }
      'ET' { "$TBC" }
      'FI' { "$TBC" }
      'FJ' { "$TBC" }
      'FK' { "$TBC" }
      'FM' { "$TBC" }
      'FO' { "$TBC" }
      'FR' { "$TBC" }
      'GA' { "$TBC" }
      'GB' { "$TBC" }
      'GD' { "$TBC" }
      'GE' { "$TBC" }
      'GF' { "$TBC" }
      'GG' { "$TBC" }
      'GH' { "$TBC" }
      'GI' { "$TBC" }
      'GL' { "$TBC" }
      'GM' { "$TBC" }
      'GN' { "$TBC" }
      'GP' { "$TBC" }
      'GQ' { "$TBC" }
      'GR' { "$TBC" }
      'GS' { "$TBC" }
      'GT' { "$TBC" }
      'GU' { "$TBC" }
      'GW' { "$TBC" }
      'GY' { "$TBC" }
      'HK' { "$TBC" }
      'HM' { "$TBC" }
      'HN' { "$TBC" }
      'HR' { "$TBC" }
      'HT' { "$TBC" }
      'HU' { "$TBC" }
      'ID' { "$TBC" }
      'IE' { "$TBC" }
      'IL' { "$TBC" }
      'IM' { "$TBC" }
      'IN' { "$TBC" }
      'IO' { "$TBC" }
      'IQ' { "$TBC" }
      'IR' { "$TBC" }
      'IS' { "$TBC" }
      'IT' { "$TBC" }
      'JE' { "$TBC" }
      'JM' { "$TBC" }
      'JO' { "$TBC" }
      'JP' { "$TBC" }
      'KE' { "$TBC" }
      'KG' { "$TBC" }
      'KH' { "$TBC" }
      'KI' { "$TBC" }
      'KM' { "$TBC" }
      'KN' { "$TBC" }
      'KP' { "$TBC" }
      'KR' { "$TBC" }
      'KW' { "$TBC" }
      'KY' { "$TBC" }
      'KZ' { "$TBC" }
      'LA' { "$TBC" }
      'LB' { "$TBC" }
      'LC' { "$TBC" }
      'LI' { "$TBC" }
      'LK' { "$TBC" }
      'LR' { "$TBC" }
      'LS' { "$TBC" }
      'LT' { "$TBC" }
      'LU' { "$TBC" }
      'LV' { "$TBC" }
      'LY' { "$TBC" }
      'MA' { "$TBC" }
      'MC' { "$TBC" }
      'MD' { "$TBC" }
      'ME' { "$TBC" }
      'MF' { "$TBC" }
      'MG' { "$TBC" }
      'MH' { "$TBC" }
      'MK' { "$TBC" }
      'ML' { "$TBC" }
      'MM' { "$TBC" }
      'MN' { "$TBC" }
      'MO' { "$TBC" }
      'MP' { "$TBC" }
      'MQ' { "$TBC" }
      'MR' { "$TBC" }
      'MS' { "$TBC" }
      'MT' { "$TBC" }
      'MU' { "$TBC" }
      'MV' { "$TBC" }
      'MW' { "$TBC" }
      'MX' { "$TBC" }
      'MY' { "$TBC" }
      'MZ' { "$TBC" }
      'NA' { "$TBC" }
      'NC' { "$TBC" }
      'NE' { "$TBC" }
      'NF' { "$TBC" }
      'NG' { "$TBC" }
      'NI' { "$TBC" }
      'NL' { "$TBC" }
      'NO' { "$TBC" }
      'NP' { "$TBC" }
      'NR' { "$TBC" }
      'NU' { "$TBC" }
      'NZ' { "$TBC" }
      'OM' { "$TBC" }
      'PA' { "$TBC" }
      'PE' { "$TBC" }
      'PF' { "$TBC" }
      'PG' { "$TBC" }
      'PH' { "$TBC" }
      'PK' { "$TBC" }
      'PL' { "$TBC" }
      'PM' { "$TBC" }
      'PN' { "$TBC" }
      'PR' { "$TBC" }
      'PS' { "$TBC" }
      'PT' { "$TBC" }
      'PW' { "$TBC" }
      'PY' { "$TBC" }
      'QA' { "$TBC" }
      'RE' { "$TBC" }
      'RO' { "$TBC" }
      'RS' { "$TBC" }
      'RU' { "$TBC" }
      'RW' { "$TBC" }
      'SA' { "$TBC" }
      'SB' { "$TBC" }
      'SC' { "$TBC" }
      'SD' { "$TBC" }
      'SE' { "$TBC" }
      'SG' { "$TBC" }
      'SH' { "$TBC" }
      'SI' { "$TBC" }
      'SJ' { "$TBC" }
      'SK' { "$TBC" }
      'SL' { "$TBC" }
      'SM' { "$TBC" }
      'SN' { "$TBC" }
      'SO' { "$TBC" }
      'SR' { "$TBC" }
      'SS' { "$TBC" }
      'ST' { "$TBC" }
      'SV' { "$TBC" }
      'SX' { "$TBC" }
      'SY' { "$TBC" }
      'SZ' { "$TBC" }
      'TC' { "$TBC" }
      'TD' { "$TBC" }
      'TF' { "$TBC" }
      'TG' { "$TBC" }
      'TH' { "$TBC" }
      'TJ' { "$TBC" }
      'TK' { "$TBC" }
      'TL' { "$TBC" }
      'TM' { "$TBC" }
      'TN' { "$TBC" }
      'TO' { "$TBC" }
      'TR' { "$TBC" }
      'TT' { "$TBC" }
      'TV' { "$TBC" }
      'TW' { "$TBC" }
      'TZ' { "$TBC" }
      'UA' { "$TBC" }
      'UG' { "$TBC" }
      'UM' { "$TBC" }
      'US' { "$TBC" }
      'UY' { "$TBC" }
      'UZ' { "$TBC" }
      'VA' { "$TBC" }
      'VC' { "$TBC" }
      'VE' { "$TBC" }
      'VG' { "$TBC" }
      'VI' { "$TBC" }
      'VN' { "$TBC" }
      'VU' { "$TBC" }
      'WF' { "$TBC" }
      'WS' { "$TBC" }
      'XK' { "$TBC" }
      'YE' { "$TBC" }
      'YT' { "$TBC" }
      'ZA' { "$TBC" }
      'ZM' { "$TBC" }
      'ZW' { "$TBC" }
    }

    # Each Call Restriction level will need a matching pattern for the route
    $Output = [PSCustomObject][ordered]@{
      PSTypeName           = 'PowerShell.TeamsFunctsions.VoiceRoute.CallRestriction'
      Country              = $ISOCountry.Name
      DialCode             = $ISOCountry.DialCode
      UnrestrictedPattern  = '.*'
      InternationalPattern = "^\+|$EMSPattern"
      NationalPattern      = "^\+$CountryDialCode|$EMSPattern"
      EmergencyOnlyPattern = "$EMSPattern"
    }

    return $Output
  }

  end {
    Write-Verbose -Message "[END ] $($MyInvocation.MyCommand)"
  }
} # Get-MatchingPatternForCallRestriction