Public/AutoAttendant/Update-TeamsAutoAttendantMenu.ps1

# Module: TeamsFunctions
# Function: AutoAttendant
# Author: David Eberhardt
# Updated: 01-OCT-2022
# Status: RC




function Update-TeamsAutoAttendantMenu {
  <#
  .SYNOPSIS
    Updates a Menu Object for an existing Auto Attendant
  .DESCRIPTION
    Updates a Menu Object with Prompt and/or MenuOptions or any Menu Settings to update existing Auto Attendants
    This Cmdlet aims to update full Menus only. Updating Menus that Redirect or Disconnect will throw an Error.
    Use this Cmdlet to update the Name, Prompt, add or replace one or more Menu Options or set Search Method or DialByName.
  .PARAMETER Menu
    Menu Object. Required. Accepts Pipeline Input of a Menu Object or a Call Flow Object
  .PARAMETER Prompts
    A Prompts Object, String or Full path to AudioFile.
    A Prompts Object will be used as is, otherwise it will be created dependent of the provided String
    A String will be used as Text-to-Voice. A File path ending in .wav, .mp3 or .wma will be used to create a recording.
  .PARAMETER MenuOptions
    MenuOptions objects created with either New-TeamsAutoAttendantMenuOption or New-CsAutoAttenantMenuOption.
    Options that have a DtmfResponse that is present get replaced
    Options that have a DtmfResponse that is not yet part of the menu will be added.
    NOTE: Please update the Prompt to reflect these new options for the caller
  .PARAMETER RemoveMenuOption
    MenuOption(s) to be removed from the menu. This is processed before the provided Menu Options are parsed
  .PARAMETER Name
    Optional. Sets the Name of the Menu to this value if possible.
  .PARAMETER EnableDialByName
    Boolean. Enables Dial by Name for the Menu.
  .PARAMETER DirectorySearchMethod
    String. Sets the Directory Search Method: None, ByName, ByExtension
  .EXAMPLE
    Update-TeamsAutoAttendantMenu -Menu $Menu -Prompts "Press 1 for Sales..." -MenuOptions $MenuOptions
 
    Updates the Menu Prompt with the provided Text-to-Voice string
  .EXAMPLE
    Update-TeamsAutoAttendantMenu -Menu $Menu -Prompts $Prompts -MenuOptions $MenuOptions
 
    Updates the Menu Prompt with the Prompts-Object and parses each Menu Option provided in the Array $MenuOptions.
    Options that have a DtmfResponse that is present get replaced
    Options that have a DtmfResponse that is not yet part of the menu will be added.
  .INPUTS
    System.Object
  .OUTPUTS
    System.Object
  .NOTES
    This CmdLet does deliberately not offer the same options as New-TeamsAutoAttendantMenu does.
    The use-case for this Cmdlet is to be called by Update-TeamsAutoAttendant CmdLets and to simplify updating of a Menu with Menu Options
    New-TeamsAutoAttendantMenu can be used to create a whole new Menu if it is desired to be replaced.
 
    To define Menu Options manually, please see:
    https://docs.microsoft.com/en-us/powershell/module/skype/new-csautoattendantmenuoption?view=skype-ps
 
    Please see 'Set up an auto attendant' for details:
    https://docs.microsoft.com/en-us/MicrosoftTeams/create-a-phone-system-auto-attendant?WT.mc_id=TeamsAdminCenterCSH
  .COMPONENT
    TeamsAutoAttendant
  .FUNCTIONALITY
    Updates a Menu Object that is used in Auto Attendants
  .LINK
    https://github.com/DEberhardt/TeamsFunctions/tree/main/docs/Update-TeamsAutoAttendantMenu.md
  .LINK
    https://github.com/DEberhardt/TeamsFunctions/tree/main/docs/about_TeamsAutoAttendant.md
  .LINK
    https://github.com/DEberhardt/TeamsFunctions/tree/main/docs/
  .LINK
    https://docs.microsoft.com/en-us/MicrosoftTeams/create-a-phone-system-auto-attendant?WT.mc_id=TeamsAdminCenterCSH
  .LINK
    https://docs.microsoft.com/en-us/powershell/module/skype/new-csautoattendantmenuoption?view=skype-ps
  #>


  [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'Medium', PositionalBinding = $false)]
  [Alias('Update-TeamsAAMenu')]
  [OutputType([object])]

  param(
    [Parameter(ValueFromPipeline, ValueFromPipelineByPropertyName, HelpMessage = 'Menu Object to be updated')]
    [object]$Menu,

    [Parameter(HelpMessage = 'Greeting Object to be updated')]
    [object]$Prompts,

    [Parameter(HelpMessage = 'MenuOptions Object to be added or replaced')]
    [object[]]$MenuOptions,

    [Parameter(HelpMessage = 'MenuOptions Object to be removed')]
    [ValidateSet(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 'Pound', 'Star')]
    [Alias('DtmfResponseTone')]
    [string[]]$RemoveMenuOption,

    [Parameter(HelpMessage = 'Optional Name of the Menu')]
    [ValidateLength(5, 63)]
    [string]$Name,

    [Parameter(HelpMessage = 'Enables Dial by Name')]
    [boolean]$DialByNameEnabled,

    [Parameter(HelpMessage = 'Search Method')]
    [ValidateSet('None', 'ByName', 'ByExtension')]
    $DirectorySearchMethod

  ) #param

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

    # Asserting AzureAD Connection
    if ( -not $script:TFPSSA) { $script:TFPSSA = Assert-AzureADConnection; if ( -not $script:TFPSSA ) { break } }

    # Asserting MicrosoftTeams Connection
    if ( -not (Assert-MicrosoftTeamsConnection) ) { break }

    # 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' }


  } #begin

  process {
    Write-Verbose -Message "[PROCESS] $($MyInvocation.MyCommand)"

    # Excluding Menus that Redirect or Disconnect
    if ($Menu.MenuOptions.Count -eq 1 -and $Menu.MenuOptions.DtmfResponse -eq 'Automatic' ) {
      throw "Menu set to '$($Menu.MenuOptions.Action)' - Menu option not applicable here. Please provide a Menu with Menu Options"
    }

    #region Settings
    if ($PSBoundParameters.ContainsKey('Name')) {
      Write-Verbose -Message "Menu '$($Menu.Name)' - Name changed to '$Name'"
      $Menu.Name = "$Name"
    }

    if ($PSBoundParameters.ContainsKey('EnableDialByName')) {
      Write-Verbose -Message "Menu '$($Menu.Name)' - EnableDialByName changed to '$EnableDialByName'"
      $Menu.EnableDialByName = $EnableDialByName
    }

    if ($PSBoundParameters.ContainsKey('DirectorySearchMethod')) {
      Write-Verbose -Message "Menu '$($Menu.Name)' - DirectorySearchMethod changed to '$DirectorySearchMethod'"
      $Menu.DirectorySearchMethod = $DirectorySearchMethod
    }
    #endregion

    #region Prompt
    if ($PSBoundParameters.ContainsKey('Prompts')) {
      $PromptsType = ($Prompts | Get-Member | Select-Object TypeName -First 1).TypeName
      switch ($PromptsType) {
        'Deserialized.Microsoft.Rtc.Management.Hosted.OAA.Models.Prompt' {
          Write-Verbose -Message 'Call Flow - Prompts provided is a Prompt Object'
          $Menu.Prompts = $Prompts
        }
        'Microsoft.Rtc.Management.Hosted.OAA.Models.Prompt' {
          Write-Verbose -Message 'Call Flow - Prompts provided is a Prompt Object'
          $Menu.Prompts = $Prompts
        }
        'System.String' {
          Write-Verbose -Message 'Call Flow - Greeting provided as a String'
          # Process Greeting
          try {
            $PromptsObject = New-TeamsAutoAttendantPrompt -String "$Prompts"
            if ($PromptsObject) {
              Write-Verbose -Message 'Prompts - Adding Prompt to Menu'
              $Menu.Prompts = $PromptsObject
            }
          }
          catch {
            Write-Warning -Message "Menu '$($Menu.Name)' - Prompts - Error creating prompt. Omitting Greeting. Exception Message: $($_.Exception.Message)"
          }
        }

        default {
          Write-Error -Message 'Type not accepted as a Greeting/Prompt, please provide a Prompts Object or a String' -ErrorAction Stop
        }
      }
    }
    #endregion

    # Defining Object to replace MenuOptions on Menu
    [System.Collections.Generic.List[object]]$MenuOptionsObject = $Menu.MenuOptions

    #region RemoveMenuOption
    if ($PSBoundParameters.ContainsKey('RemoveMenuOption')) {
      foreach ( $Option in $RemoveMenuOption) {
        $DtmfResponse = 'Tone' + $Option
        $OptionToRemove = $MenuOptionsObject | Where-Object DtmfResponse -EQ $DtmfResponse
        Write-Verbose -Message "RemoveMenuOption - Removing Options with DtmfResponse '$DtmfResponse'"
        $OptionToRemove | ForEach-Object { [void]$MenuOptionsObject.Remove($_) }
      }
      $Menu.MenuOptions = $MenuOptionsObject
    }
    #endregion

    #region MenuOptions
    if ($PSBoundParameters.ContainsKey('MenuOptions')) {
      foreach ( $Option in $MenuOptions) {
        $Selection = $Option.DtmfResponse -replace 'Tone', ''
        $ReplaceMenuOption = $MenuOptionsObject | Where-Object DtmfResponse -EQ $Option.DtmfResponse
        if ( $ReplaceMenuOption ) {
          Write-Verbose -Message "MenuOptions - Replacing Option with DtmfResponse '$($Option.DtmfResponse)'"
          if ( $Force -or $PSCmdlet.ShouldProcess("$($Menu.Name)", "Replace Menu Option $Selection in Menu") ) {
            $ReplaceMenuOption = $Option
            Write-Information "INFO: Menu '$($Menu.Name)' - Menu Option '$Selection' replaced"
          }
        }
        else {
          Write-Verbose -Message "MenuOptions - Adding Option with DtmfResponse '$($Option.DtmfResponse)'"
          if ( $Force -or $PSCmdlet.ShouldProcess("$($Menu.Name)", "Add Menu Option $Selection in Menu") ) {
            [void]$MenuOptionsObject.Add($Option)
            Write-Information "INFO: Menu '$($Menu.Name)' - Menu Option '$Selection' added"
          }
        }
      }
      $Menu.MenuOptions = $MenuOptionsObject
    }
    #endregion

    # OUTPUT
    Write-Output $Menu

  } #process

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

  } #end
} # Update-TeamsAutoAttendantMenu