Functions/Public/Zoom.ps1
|
# Zoom integration functions Function Get-ZoomAccessToken { <# .SYNOPSIS Get a Zoom OAuth access token for a given Zoom tenant. Needed to run other Zoom API queries. .DESCRIPTION Get a Zoom OAuth access token for a given Zoom tenant. Needed to run other Zoom API queries. .PARAMETER ClientID The client ID for the Zoom app. .PARAMETER ClientSecret The MS client secret for the application granted access to Azure AD. .PARAMETER MSTenantID The MS tenant ID for the O365 customer granted access to Azure AD. .EXAMPLE $AuthToken = Get-MSGraphAccessToken -MSClientID 41a228ad-db6c-4e4e-4184-6d8a1175a35f -MSClientSecret 43Rk5Xl3K349w-pFf0i_Rt45Qd~ArqkE32. -MSTenantID 17e1e614-8119-48ab-8ba1-6ff1d94a6930 Obtains an authtoken for the given tenant using secret-based auth and saves the results for use in other commands in a variable called $AuthToken .EXAMPLE $AuthToken = Get-MSGraphAccessToken -MSClientID 029834092-234234-234234-23442343 -MSTenantID 234234234-234234-234-23-42342342 -CertFriendlyName 'CertAuth' -CertStore LocalMachine Obtains an authtoken for the given tenant using certificate auth and saves the results for use in other commands in a variable called $AuthToken .NOTES Version 1.0 #> Param ( [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [string]$ClientID, [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [string]$ClientSecret, [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [string]$RedirectURI ) Process { # Get the details from the tenant's Zoom config $ZoomConfig = Get-NectarZoomConfig Try { # Get initial authorization code $Body = @{ response_type = 'code' redirect_uri = $RedirectURI client_id = $ZoomConfig.apiClientID } $AuthURI = "https://zoom.us/oauth/authorize?response_type=code&redirect_uri=$RedirectURI&client_id=$($ZoomConfig.apiClientID)" Write-Verbose $AuthURI $AuthCode = Invoke-RestMethod -Method GET -URI $AuthURI Return $AuthCode # Get Base64-encoded representation of Client_ID:Client_Secret $ClientDetailsText = "$($ZoomConfig.apiClientID):$($ZoomConfig.apiClientSecret)" Write-Verbose "ClientDetails: $ClientDetailsText" $Bytes = [System.Text.Encoding]::UTF8.GetBytes($ClientDetailsText) $ClientDetails64 =[Convert]::ToBase64String($Bytes) $Headers = @{ Authorization = "Basic $ClientDetails64" 'Content-Type' = 'application/x-www-form-urlencoded' } Write-Verbose "AuthHeader: Basic $CLientDetails64" $Body = @{ code = $ZoomConfig.verificationToken grant_type = 'authorization_code' redirect_uri = $RedirectURI } $URI = "https://zoom.us/oauth/token" Write-Verbose $URI $JSONAuth = Invoke-RestMethod -Method POST -URI $URI -Headers $Headers -Body $Body $AuthToken = $JSONAuth.access_token Return $JSONAuth } Catch { Write-Error "Failed to get access token. Ensure the values for ClientID and ClientSecret are correct. $($_.Exception.Message)" If ($PSCmdlet.MyInvocation.BoundParameters["ErrorAction"] -ne "SilentlyContinue") { Get-JSONErrorStream -JSONResponse $_ } } } } Function Get-NectarZoomConfig { <# .SYNOPSIS Returns information about the Nectar DXP Zoom configuration .DESCRIPTION Returns information about the Nectar DXP Zoom configuration. Requires a global admin account. Not available to tenant-level admins. .EXAMPLE Get-NectarZoomConfig .NOTES Version 1.0 #> [Alias("gnzc")] [cmdletbinding()] Param ( [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [string]$TenantName ) Begin { Connect-NectarCloud } Process { Try { If (!$TenantName) { $TenantName = Get-NectarDefaultTenantName } $URI = "https://$Global:NectarCloud/aapi/clouddatasources/configuration/zoom?tenant=$TenantName" Write-Verbose $URI $JSON = Invoke-RestMethod -Method GET -URI $URI -Headers $Global:NectarAuthHeader Return $JSON.data } Catch { Write-Error 'No tenant Zoom data found or insufficient permissions. $($_.Exception.Message)' If ($PSCmdlet.MyInvocation.BoundParameters["ErrorAction"] -ne "SilentlyContinue") { Get-JSONErrorStream -JSONResponse $_ } } } } Function Get-NectarZoomOAuthApp { <# .SYNOPSIS Returns information about any configured Zoom OAuth applications on the server .DESCRIPTION Returns information about any configured Zoom OAuth applications on the server. Requires a global admin account. Not available to tenant-level admins. .PARAMETER ID The ID of a specific Zoom OAuth application. .EXAMPLE Get-NectarZoomOAuthApp .NOTES Version 1.0 #> [Alias("gnzoa")] [cmdletbinding()] Param ( [Parameter(Mandatory=$False)] [int]$ID ) Begin { Connect-NectarCloud } Process { Try { $URI = "https://$Global:NectarCloud/aapi/client/oauth/zoom" Write-Verbose $URI If ($ID) { $URI += "/$ID" } $JSON = Invoke-RestMethod -Method GET -URI $URI -Headers $Global:NectarAuthHeader Return $JSON.data } Catch { Write-Error 'No Zoom OAuth apps found or insufficient permissions. $($_.Exception.Message)' If ($PSCmdlet.MyInvocation.BoundParameters["ErrorAction"] -ne "SilentlyContinue") { Get-JSONErrorStream -JSONResponse $_ } } } } Function New-NectarZoomOAuthApp { <# .SYNOPSIS Creates a new Zoom OAuth application on the server .DESCRIPTION Creates a new Zoom OAuth application on the server. Requires a global admin account. Not available to tenant-level admins. .PARAMETER DisplayName The MS client ID for the application granted access to Azure AD. .PARAMETER ClientID The Zoom OAuth application Client ID. .PARAMETER ClientSecret The Zoom OAuth application Client secret. .PARAMETER VerificationToken The Zoom OAuth application verification token .EXAMPLE New-NectarZoomOAuthApp -DisplayName 'Contoso_Global' -ClientID 'abcdefWEwrelj32324' -ClientSecret 'asfd90832jn3mvknaswui3' -VerificationToken '09432jpg43in9024323rsdvf' .NOTES Version 1.0 #> [Alias("nnzoa")] [cmdletbinding()] Param ( [Parameter(ValueFromPipelineByPropertyName, Mandatory=$True)] [string]$DisplayName, [Parameter(ValueFromPipelineByPropertyName, Mandatory=$True)] [string]$ClientID, [Parameter(ValueFromPipelineByPropertyName, Mandatory=$True)] [string]$ClientSecret, [Parameter(ValueFromPipelineByPropertyName, Mandatory=$True)] [string]$VerificationToken ) Begin { Connect-NectarCloud } Process { Try { # Build the JSON body for creating the config $ZoomBody = @{ displayName = $DisplayName clientId = $ClientID clientSecret = $ClientSecret verificationToken = $VerificationToken } $ZoomJSONBody = $ZoomBody | ConvertTo-Json $URI = "https://$Global:NectarCloud/aapi/client/oauth/zoom" Write-Verbose $URI $JSON = Invoke-RestMethod -Method POST -URI $URI -Headers $Global:NectarAuthHeader -Body $ZoomJSONBody -ContentType 'application/json; charset=utf-8' Return $JSON.data } Catch { Write-Error "Cound not create Zoom OAuth application. $($_.Exception.Message)" If ($PSCmdlet.MyInvocation.BoundParameters["ErrorAction"] -ne "SilentlyContinue") { Get-JSONErrorStream -JSONResponse $_ } } } } Function Set-NectarZoomOAuthApp { <# .SYNOPSIS Updates an existing Zoom OAuth application on the server .DESCRIPTION Updates an existing Zoom OAuth application on the server. Requires a global admin account. Not available to tenant-level admins. .PARAMETER ID The ID of the OAuth application to modify. Obtain via Get-NectarZoomOAuthApp .PARAMETER DisplayName The MS client ID for the application granted access to Azure AD. .PARAMETER ClientID The Zoom OAuth application Client ID. .PARAMETER ClientSecret The Zoom OAuth application Client secret. .PARAMETER VerificationToken The Zoom OAuth application verification token .EXAMPLE Set-NectarZoomOAuthApp -ID 1 -DisplayName 'Contoso_Global' .NOTES Version 1.0 #> [Alias("snzoa")] [cmdletbinding()] Param ( [Parameter(ValueFromPipelineByPropertyName, Mandatory=$True)] [int]$ID, [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [string]$DisplayName, [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [string]$ClientID, [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [string]$ClientSecret, [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [string]$VerificationToken ) Begin { Connect-NectarCloud } Process { Try { # Get the existing Zoom OAuth app configuration $ZoomBody = Get-NectarZoomOAuthApp -ID $ID $ZoomBody = $ZoomBody | Select-Object -Property * -ExcludeProperty ID # Remove ID and other common params (like Verbose) from PSBoundParameters $PSBoundParameters.Remove('ID') | Out-Null ForEach ($Param in $PSBoundParameters.GetEnumerator()) { # Skip any common parameters (Debug, Verbose, etc) If ([System.Management.Automation.PSCmdlet]::CommonParameters -contains $Param.key) { Continue } $ZoomBody.$($Param.Key) = $Param.Value } $ZoomJSONBody = $ZoomBody | ConvertTo-Json Write-Verbose $ZoomJSONBody $URI = "https://$Global:NectarCloud/aapi/client/oauth/zoom/$ID" Write-Verbose $URI $JSON = Invoke-RestMethod -Method PUT -URI $URI -Headers $Global:NectarAuthHeader -Body $ZoomJSONBody -ContentType 'application/json; charset=utf-8' Return $JSON.data } Catch { Write-Error "Cound not update Zoom OAuth application. $($_.Exception.Message)" If ($PSCmdlet.MyInvocation.BoundParameters["ErrorAction"] -ne "SilentlyContinue") { Get-JSONErrorStream -JSONResponse $_ } } } } Function Remove-NectarZoomOAuthApp { <# .SYNOPSIS Removes an existing Zoom OAuth application on the server .DESCRIPTION Removes an existing Zoom OAuth application on the server. Requires a global admin account. Not available to tenant-level admins. .PARAMETER ID The ID of the OAuth application to remove. Obtain via Get-NectarZoomOAuthApp .EXAMPLE Remove-NectarZoomOAuthApp -ID 1 .NOTES Version 1.0 #> [Alias("rnzoa")] [cmdletbinding()] Param ( [Parameter(ValueFromPipelineByPropertyName, Mandatory=$True)] [int]$ID ) Begin { Connect-NectarCloud } Process { Try { $URI = "https://$Global:NectarCloud/aapi/client/oauth/zoom/$ID" Write-Verbose $URI $NULL = Invoke-RestMethod -Method DELETE -URI $URI -Headers $Global:NectarAuthHeader } Catch { Write-Error "Cound not remove Zoom OAuth application. $($_.Exception.Message)" If ($PSCmdlet.MyInvocation.BoundParameters["ErrorAction"] -ne "SilentlyContinue") { Get-JSONErrorStream -JSONResponse $_ } } } } Function Get-NectarZoomAuthURL { <# .SYNOPSIS Returns the Nectar DXP Zoom authorization URL needed for connecting Nectar DXP to Zoom .DESCRIPTION Returns the Nectar DXP Zoom authorization URL needed for connecting Nectar DXP to Zoom .EXAMPLE Get-NectarZoomAuthURL .NOTES Version 1.0 #> [Alias("gnzau")] [cmdletbinding()] Param ( [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [string]$TenantName ) Begin { Connect-NectarCloud } Process { Try { If (!$TenantName) { $TenantName = Get-NectarDefaultTenantName } $URI = "https://$Global:NectarCloud/aapi/zoom/oauth/url?tenant=$TenantName" Write-Verbose $URI $JSON = Invoke-RestMethod -Method GET -URI $URI -Headers $Global:NectarAuthHeader Return $JSON.data } Catch { Write-Error "No tenant Zoom data found or insufficient permissions. $($_.Exception.Message)" If ($PSCmdlet.MyInvocation.BoundParameters["ErrorAction"] -ne "SilentlyContinue") { Get-JSONErrorStream -JSONResponse $_ } } } } Function Get-ZoomAccessToken_LEGACY { <# .SYNOPSIS Get a Zoom JWT access token for a given Zoom tenant. Needed to run other Zoom API queries. .DESCRIPTION Get a Zoom access token for a given Zoom tenant. Needed to run other Zoom API queries. Generates a JSON Web Ticket (JWT) .EXAMPLE $AuthToken = Get-ZoomAccessToken -APIKey yourapikey -APISecret yourapisecret .NOTES Version 1.0 #> Param( [Parameter(Mandatory = $False)] [ValidateSet('HS256', 'HS384', 'HS512')] $Algorithm = 'HS256', $type = $null, [Parameter(Mandatory = $True)] [string]$APIKey = $null, [int]$ValidforSeconds = 86400, [Parameter(Mandatory = $True)] $APISecret = $null ) $exp = [int][double]::parse((Get-Date -Date $((Get-Date).addseconds($ValidforSeconds).ToUniversalTime()) -UFormat %s)) # Grab Unix Epoch Timestamp and add desired expiration. [hashtable]$header = @{alg = $Algorithm; typ = $type} [hashtable]$payload = @{iss = $APIKey; exp = $exp} $headerjson = $header | ConvertTo-Json -Compress $payloadjson = $payload | ConvertTo-Json -Compress $headerjsonbase64 = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($headerjson)).Split('=')[0].Replace('+', '-').Replace('/', '_') $payloadjsonbase64 = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($payloadjson)).Split('=')[0].Replace('+', '-').Replace('/', '_') $ToBeSigned = $headerjsonbase64 + "." + $payloadjsonbase64 $SigningAlgorithm = switch ($Algorithm) { "HS256" {New-Object System.Security.Cryptography.HMACSHA256} "HS384" {New-Object System.Security.Cryptography.HMACSHA384} "HS512" {New-Object System.Security.Cryptography.HMACSHA512} } $SigningAlgorithm.Key = [System.Text.Encoding]::UTF8.GetBytes($APISecret) $Signature = [Convert]::ToBase64String($SigningAlgorithm.ComputeHash([System.Text.Encoding]::UTF8.GetBytes($ToBeSigned))).Split('=')[0].Replace('+', '-').Replace('/', '_') $Token = "$headerjsonbase64.$payloadjsonbase64.$Signature" Return $Token } Function Get-ZoomMeeting { <# .SYNOPSIS Return a list of Zoom meetings. .DESCRIPTION Return a list of Zoom meetings. .PARAMETER MeetingID Return information about a specific meeting. Provide meeting ID or UUID. Don't use with From/To date range .PARAMETER Type Return live, past or past meetings with only one participant. Defaults to past .PARAMETER FromDateTime Start of date/time range to query. UTC, inclusive. Time range is based on the call start time. Defaults to yesterday. .PARAMETER ToDateTime End of date/time range to query. UTC, inclusive. Defaults to today .PARAMETER TenantName The name of the Nectar DXP tenant. Used in multi-tenant configurations. .PARAMETER APIKey The Zoom API key for the application granted access to Zoom. .PARAMETER APISecret The Zoom API secret for the application granted access to Zoom. .PARAMETER AuthToken The authorization token used for this request. Normally obtained via Get-ZoomAccessToken .PARAMETER PageSize The number of results to return per page. Defaults to 30. .EXAMPLE Get-ZoomMeetings -AuthToken $AuthToken Returns all past Zoom meetings from the previous 24 hours .NOTES Version 1.0 #> Param ( [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [Alias("uuid")] [string]$MeetingID, [Parameter(Mandatory = $False)] [ValidateSet('past', 'pastone', 'live')] $Type = 'past', [Parameter(Mandatory=$False)] [string]$FromDateTime = ((Get-Date).AddDays(-1).ToString('yyyy-MM-dd')), [Parameter(Mandatory=$False)] [string]$ToDateTime = (Get-Date -Format 'yyyy-MM-dd'), [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [string]$TenantName, [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [string]$APIKey, [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [string]$APISecret, [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [string]$AuthToken, [Parameter(Mandatory=$False)] [ValidateRange(1,300)] [int]$PageSize = 30 ) Process { Try { # Use globally set tenant name, if one was set and not explicitly included in the command If ($Global:NectarTenantName -And !$PSBoundParameters.ContainsKey('TenantName')) { $TenantName = $Global:NectarTenantName } ElseIf ($TenantName) { If ($TenantName -NotIn $Global:NectarTenantList) { $TList = $Global:NectarTenantList -join ', ' Throw "Could not find a tenant with the name $TenantName on https://$Global:NectarCloud. Select one of $TList. $($_.Exception.Message)" } } If ($APIKey) { $AuthToken = Get-ZoomAccessToken -APIKey $APIKey -APISecret $APISecret } ElseIf (!$AuthToken) { $AuthToken = Get-NectarMSTeamsConfig -TenantName $TenantName | Get-MSGraphAccessToken } } Catch { Write-Error "Could not obtain authorization token. $($_.Exception.Message)" If ($PSCmdlet.MyInvocation.BoundParameters["ErrorAction"] -ne "SilentlyContinue") { Get-JSONErrorStream -JSONResponse $_ } } If ($AuthToken) { $Headers = @{ Authorization = "Bearer $AuthToken" } If ($MeetingID) { $URI = "https://api.zoom.us/v2/metrics/meetings/$MeetingID" $Body = @{ type = $Type } $JSON = Invoke-RestMethod -Method GET -URI $URI -Headers $Headers -Body $Body $JSON } Else { $URI = "https://api.zoom.us/v2/metrics/meetings" $Body = @{ from = $FromDateTime to = $ToDateTime type = $Type page_size = $PageSize } $JSON = Invoke-RestMethod -Method GET -URI $URI -Headers $Headers -Body $Body $JSON.meetings # If there is more than one page, use next_page_token to iterate through the pages While ($JSON.next_page_token) { $Body.next_page_token = $JSON.next_page_token $JSON = Invoke-RestMethod -Method GET -URI $URI -Headers $Headers -Body $Body $JSON.meetings } } Clear-Variable -Name AuthToken } } } Function Get-ZoomMeetingParticipants { <# .SYNOPSIS Return a list of Zoom meeting participants for a given meeting and their connection details. .DESCRIPTION Return a list of Zoom meeting participants for a given meeting and their connection details. .PARAMETER MeetingID The ID of the meeting. Provide meeting ID or UUID. .PARAMETER Type Return live, past or past meetings with only one participant. Defaults to past .PARAMETER TenantName The name of the Nectar DXP tenant. Used in multi-tenant configurations. .PARAMETER APIKey The Zoom API key for the application granted access to Zoom. .PARAMETER APISecret The Zoom API secret for the application granted access to Zoom. .PARAMETER AuthToken The authorization token used for this request. Normally obtained via Get-ZoomAccessToken .PARAMETER PageSize The number of results to return per page. Defaults to 30. .EXAMPLE Get-ZoomMeetingParticipants 928340928 -AuthToken $AuthToken Returns participant information from a specific meeting .NOTES Version 1.0 #> Param ( [Parameter(ValueFromPipelineByPropertyName, Mandatory=$True)] [Alias("uuid")] [string]$MeetingID, [Parameter(Mandatory = $False)] [ValidateSet('past', 'pastone', 'live')] [string]$Type = 'past', [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [string]$TenantName, [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [string]$APIKey, [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [string]$APISecret, [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [string]$AuthToken, [Parameter(Mandatory=$False)] [ValidateRange(1,300)] [int]$PageSize = 30 ) Process { Try { # Use globally set tenant name, if one was set and not explicitly included in the command If ($Global:NectarTenantName -And !$PSBoundParameters.ContainsKey('TenantName')) { $TenantName = $Global:NectarTenantName } ElseIf ($TenantName) { If ($TenantName -NotIn $Global:NectarTenantList) { $TList = $Global:NectarTenantList -join ', ' Throw "Could not find a tenant with the name $TenantName on https://$Global:NectarCloud. Select one of $TList. $($_.Exception.Message)" } } If ($APIKey) { $AuthToken = Get-ZoomAccessToken -APIKey $APIKey -APISecret $APISecret } ElseIf (!$AuthToken) { $AuthToken = Get-NectarMSTeamsConfig -TenantName $TenantName | Get-MSGraphAccessToken } } Catch { Write-Error "Could not obtain authorization token. $($_.Exception.Message)" If ($PSCmdlet.MyInvocation.BoundParameters["ErrorAction"] -ne "SilentlyContinue") { Get-JSONErrorStream -JSONResponse $_ } } If ($AuthToken) { $Headers = @{ Authorization = "Bearer $AuthToken" } $URI = "https://api.zoom.us/v2/metrics/meetings/$MeetingID/participants" $Body = @{ type = $Type page_size = $PageSize } $JSON = Invoke-RestMethod -Method GET -URI $URI -Headers $Headers -Body $Body $JSON.participants # If there is more than one page, use next_page_token to iterate through the pages While ($JSON.next_page_token) { $Body.next_page_token = $JSON.next_page_token $JSON = Invoke-RestMethod -Method GET -URI $URI -Headers $Headers -Body $Body $JSON.participants } Clear-Variable -Name AuthToken } } } Function Get-ZoomMeetingParticipantQoS { <# .SYNOPSIS Return the participant QoS from a given meeting. .DESCRIPTION Return the participant QoS from a given meeting. .PARAMETER MeetingID Return information about a specific meeting. .PARAMETER ParticipantID Return information about a specific participant in a given meeting. Optional .PARAMETER Type Return live, past or past meetings with only one participant. Defaults to past .PARAMETER TenantName The name of the Nectar DXP tenant. Used in multi-tenant configurations. .PARAMETER APIKey The Zoom API key for the application granted access to Zoom. .PARAMETER APISecret The Zoom API secret for the application granted access to Zoom. .PARAMETER AuthToken The authorization token used for this request. Normally obtained via Get-ZoomAccessToken .PARAMETER PageSize The number of results to return per page. Defaults to 30. .EXAMPLE Get-ZoomMeetingParticipantQoS 928340928 -AuthToken $AuthToken Returns all past Zoom meetings from the previous 24 hours .NOTES Version 1.0 #> Param ( [Parameter(ValueFromPipelineByPropertyName, Mandatory=$True)] [Alias("uuid")] [string]$MeetingID, [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [string]$ParticipantID, [Parameter(Mandatory = $False)] [ValidateSet('past', 'pastone', 'live')] [string]$Type = 'past', [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [string]$TenantName, [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [string]$APIKey, [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [string]$APISecret, [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [string]$AuthToken, [Parameter(Mandatory=$False)] [ValidateRange(1,300)] [int]$PageSize = 30 ) Process { Try { # Use globally set tenant name, if one was set and not explicitly included in the command If ($Global:NectarTenantName -And !$PSBoundParameters.ContainsKey('TenantName')) { $TenantName = $Global:NectarTenantName } ElseIf ($TenantName) { If ($TenantName -NotIn $Global:NectarTenantList) { $TList = $Global:NectarTenantList -join ', ' Throw "Could not find a tenant with the name $TenantName on https://$Global:NectarCloud. Select one of $TList. $($_.Exception.Message)" } } If ($APIKey) { $AuthToken = Get-ZoomAccessToken -APIKey $APIKey -APISecret $APISecret } ElseIf (!$AuthToken) { $AuthToken = Get-NectarMSTeamsConfig -TenantName $TenantName | Get-MSGraphAccessToken } } Catch { Write-Error "Could not obtain authorization token. $($_.Exception.Message)" If ($PSCmdlet.MyInvocation.BoundParameters["ErrorAction"] -ne "SilentlyContinue") { Get-JSONErrorStream -JSONResponse $_ } } If ($AuthToken) { $Headers = @{ Authorization = "Bearer $AuthToken" } If ($ParticipantID) { $URI = "https://api.zoom.us/v2/metrics/meetings/$MeetingID/participants/$ParticipantID/qos" $Body = @{ type = $Type } $JSON = Invoke-RestMethod -Method GET -URI $URI -Headers $Headers -Body $Body $JSON } Else { $URI = "https://api.zoom.us/v2/metrics/meetings/$MeetingID/participants/qos" $Body = @{ type = $Type page_size = $PageSize } $JSON = Invoke-RestMethod -Method GET -URI $URI -Headers $Headers -Body $Body $JSON.participants # If there is more than one page, use next_page_token to iterate through the pages While ($JSON.next_page_token) { $Body.next_page_token = $JSON.next_page_token $JSON = Invoke-RestMethod -Method GET -URI $URI -Headers $Headers -Body $Body $JSON.participants } } Clear-Variable -Name AuthToken } } } ################################################################################################################################################# # # # Informational Functions # # # |