Skip to content

Commit

Permalink
Merge pull request #606 from nanddeepn/teams-pstn-call-logs
Browse files Browse the repository at this point in the history
New script sample to Export Microsoft Teams PSTN call logs
  • Loading branch information
pkbullock authored Oct 25, 2023
2 parents a9f9360 + 7c676a6 commit 7e98920
Show file tree
Hide file tree
Showing 5 changed files with 283 additions and 0 deletions.
222 changes: 222 additions & 0 deletions scripts/teams-export-pstn-call-logs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,222 @@
---
plugin: add-to-gallery
---

# Export Microsoft Teams PSTN Call Logs

## Summary

This script exports the log of PSTN calls for a given duration.

![Example Screenshot](assets/example.png)

## Permissions

The PowerShell version of the script requires Microsoft Entra ID App Registration with the Application Permission as follows:
1. CallRecord-PstnCalls.Read.All
2. CallRecords.Read.All

![Permission](assets/API_Permissions.png)

> Note: You can skip this step, if you are planning to use CLI for Microsoft 365.
## Implementation

- Open Windows PowerShell ISE
- Create a new file
- Copy the code below
- Save the file and run it

# [PowerShell](#tab/ps)

```powershell
[CmdletBinding()]
param (
[parameter(Mandatory)][string] $TenantID,
[parameter(Mandatory)][string] $ClientID,
[parameter(Mandatory)][string] $ClientSecret,
[parameter(Mandatory)][DateTime] $StartDate,
[parameter(Mandatory = $false)][DateTime] $EndDate = (Get-Date)
)
function Get-AccessToken {
# Construct URI
$uri = "https://login.microsoftonline.com/$TenantID/oauth2/v2.0/token"
# Construct Body
$body = @{
client_id = $ClientID
client_secret = $ClientSecret
scope = 'https://graph.microsoft.com/.default'
grant_type = 'client_credentials'
}
# Fix for issue: The underlying connection was closed
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
# Get OAuth 2.0 Token
$tokenRequest = Invoke-WebRequest -Method Post -Uri $uri -ContentType 'application/x-www-form-urlencoded' -Body $body -UseBasicParsing
# Access Token
return ($tokenRequest.Content | ConvertFrom-Json).access_token
}
function Get-GraphQueryOutput {
param(
[parameter(Mandatory = $true)][String] $Uri
)
$retryCount = 0
$maxRetries = 3
$pauseDuration = 2
$token = Get-AccessToken
$allRecords = @()
while ($Uri) {
try {
Write-Host "Invoking Graph query: $($Uri)"
$query = Invoke-RestMethod -Method Get -Uri $Uri -ContentType 'application/json;odata.metadata=none' -Headers @{Authorization = "Bearer $token" }
$recordToAdd = ($query | Select-Object Value).Value
if (-not $recordToAdd) {
$recordToAdd = $query
}
$allRecords += $recordToAdd
if ($query.'@odata.nextLink') {
# set the url to get the next page of records
$Uri = $query.'@odata.nextLink'
}
else {
$Uri = $null
}
}
catch {
Write-Host "StatusCode: " $_.Exception.Response.StatusCode.value__
Write-Host "StatusDescription:" $_.Exception.Response.StatusDescription
if ($_.Exception.Response.StatusCode.value__ -eq 401) {
$token = Get-AccessToken
}
if ($_.ErrorDetails.Message) {
Write-Host "Inner Error: $_.ErrorDetails.Message" -ForegroundColor Red
}
if ($_.Exception.Response.StatusCode.value__ -eq 404) {
# If the error is "Not Found", let us not retry
$retryCount = $maxRetries + 1
}
if ($retryCount -ge $maxRetries) {
# Not going to retry again
$Uri = $null
Write-Host "Not going to retry..." -ForegroundColor Red
}
else {
$retryCount += 1
$pauseDuration = $pauseDuration * 5
Write-Host "Retry attempt $retryCount after a $pauseDuration second pause..." -ForegroundColor Yellow
Start-Sleep -Seconds $pauseDuration
}
}
}
return $allRecords
}
Start-Transcript -Path ".\PSTN-Logs-$((Get-Date).toString("dd-MM-yyyy")).log"
$timeSpan = New-TimeSpan -Start (Get-Date -Date $StartDate) -End (Get-Date -Date $EndDate)
if ($timeSpan.Days -gt 90) {
Write-Host "The maximum number of days between StartDate and EndDate cannot exceed 90" -ForegroundColor Red
Write-Host "Please try again with a smaller time span." -ForegroundColor Red
Exit
}
$fromDateTime = Get-Date -Date $StartDate -Format "yyyy-MM-dd"
$toDateTime = Get-Date -Date $EndDate -Format "yyyy-MM-dd"
$callRecords = Get-GraphQueryOutput -Uri "https://graph.microsoft.com/v1.0/communications/callRecords/getPstnCalls(fromDateTime=$fromDateTime,toDateTime=$toDateTime)"
ForEach ($record in $callRecords) {
$reportLine = [PSCustomObject][Ordered]@{
"id" = $record.id
"callId" = $record.callId
"userId" = $record.userId
"userPrincipalName" = $record.userPrincipalName
"userDisplayName" = $record.userDisplayName
"startDateTime" = $record.startDateTime
"endDateTime" = $record.endDateTime
"duration" = $record.duration
"charge" = $record.charge
"callType" = $record.callType
"currency" = $record.currency
"calleeNumber" = $record.calleeNumber
"usageCountryCode" = $record.usageCountryCode
"tenantCountryCode" = $record.tenantCountryCode
"connectionCharge" = $record.connectionCharge
"callerNumber" = $record.callerNumber
"destinationContext" = $record.destinationContext
"destinationName" = $record.destinationName
"conferenceId" = $record.conferenceId
"licenseCapability" = $record.licenseCapability
"inventoryType" = $record.inventoryType
}
$reportLine | Export-Csv -NoTypeInformation -Path ".\PSTN-Data-$((Get-Date).toString("dd-MM-yyyy")).csv" -Encoding UTF8 -Append
}
Write-Host "Finished!" -ForegroundColor Green
Stop-Transcript
```
[!INCLUDE [More about PowerShell](../../docfx/includes/MORE-PS.md)]

# [CLI for Microsoft 365](#tab/cli-m365-ps)

```powershell
[CmdletBinding()]
param (
[parameter(Mandatory)][DateTime] $StartDate,
[parameter(Mandatory = $false)][DateTime] $EndDate = (Get-Date)
)
begin {
Write-Host "Connecting..." -ForegroundColor Yellow
$m365Status = m365 status
if ($m365Status -match "Logged Out") {
m365 login
}
}
process {
$fromDateTime = Get-Date -Date $StartDate -Format "yyyy-MM-dd"
$toDateTime = Get-Date -Date $EndDate -Format "yyyy-MM-dd"
m365 teams report pstncalls --fromDateTime $fromDateTime --toDateTime $toDateTime --output csv | Out-File -FilePath ".\PSTN-Data-$((Get-Date).toString("dd-MM-yyyy")).csv"
}
end {
Write-Host "Finished!" -ForegroundColor Green
}
```

[!INCLUDE [More about CLI for Microsoft 365](../../docfx/includes/MORE-CLIM365.md)]

***

## Contributors

| Author(s) |
|-----------|
| [Nanddeep Nachan](https://github.com/nanddeepn) |
| [Smita Nachan](https://github.com/SmitaNachan) |

## Credits

The retry invoke REST method requests in PowerShell, when an error occurs is inspired from [this blog](https://blogs.aaddevsup.xyz/2021/01/retry-invoke-restmethod-requests-in-powershell-when-an-error-occurs/).

[!INCLUDE [DISCLAIMER](../../docfx/includes/DISCLAIMER.md)]
<img src="https://m365-visitor-stats.azurewebsites.net/script-samples/scripts/teams-export-pstn-call-logs" aria-hidden="true" />
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
61 changes: 61 additions & 0 deletions scripts/teams-export-pstn-call-logs/assets/sample.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
[
{
"name": "teams-pstn-call-logs",
"source": "pnp",
"title": "Export Microsoft Teams PSTN call logs",
"shortDescription": "Exports the log of PSTN calls for a given duration",
"url": "https://pnp.github.io/script-samples/teams-export-pstn-call-logs/README.html",
"longDescription": [
"Exports the log of PSTN calls for a given duration."
],
"creationDateTime": "2023-10-24",
"updateDateTime": "2023-10-24",
"products": [
"Teams"
],
"metadata": [
{
"key": "cli-for-microsoft365",
"value": "7.0.0"
}
],
"tags": [
"Invoke-WebRequest",
"Invoke-RestMethod",
"m365 login",
"m365 teams report pstncalls"
],
"categories": [
"Report"
],
"thumbnails": [
{
"type": "image",
"order": 100,
"url": "https://raw.githubusercontent.com/pnp/script-samples/main/scripts/teams-export-pstn-call-logs/assets/preview.png",
"alt": "Export Microsoft Teams PSTN call logs"
}
],
"authors": [
{
"gitHubAccount": "nanddeepn",
"pictureUrl": "https://github.com/nanddeepn.png",
"name": "Nanddeep Nachan"
},
{
"gitHubAccount": "SmitaNachan",
"company": "",
"pictureUrl": "https://github.com/SmitaNachan.png",
"name": "Smita Nachan"
}
],
"references": [
{
"name": "Want to learn more about CLI for Microsoft 365 and the commands",
"description": "Check out the CLI for Microsoft 365 site to get started and for the reference to the commands.",
"url": "https://aka.ms/cli-m365"
}
]
}
]

0 comments on commit 7e98920

Please sign in to comment.