Last active
August 3, 2022 20:31
-
-
Save AlexanderHolmeset/5d9d9180a1aa8ff4eb2474b8e859ad95 to your computer and use it in GitHub Desktop.
TeamsFiletypesStatistics
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
### Teams Filetype Statistics ### | |
### Version 1.1 ### | |
### Author: Alexander Holmeset ### | |
### Email: [email protected] ### | |
### Twitter: twitter.com/alexholmeset ### | |
### Blog: alexholmeset.blog ### | |
#Need Azure App registration with Groupd.Read.All and Site.Read.All permissions. | |
$TenantId = "xxxxxxxx" | |
$ClientID = "xxxxxxxx" | |
$ClientSecret = "xxxxxxxx" | |
$TeamsStatsTotal = [PSCustomObject]@() | |
$stopwatch = [system.diagnostics.stopwatch]::StartNew() | |
function Get-MSGraphAppToken{ | |
<# .SYNOPSIS | |
Get an app based authentication token required for interacting with Microsoft Graph API | |
.PARAMETER TenantID | |
A tenant ID should be provided. | |
.PARAMETER ClientID | |
Application ID for an Azure AD application. Uses by default the Microsoft Intune PowerShell application ID. | |
.PARAMETER ClientSecret | |
Web application client secret. | |
.EXAMPLE | |
# Manually specify username and password to acquire an authentication token: | |
Get-MSGraphAppToken -TenantID $TenantID -ClientID $ClientID -ClientSecert = $ClientSecret | |
.NOTES | |
Author: Jan Ketil Skanke | |
Contact: @JankeSkanke | |
Created: 2020-15-03 | |
Updated: 2020-15-03 | |
Version history: | |
1.0.0 - (2020-03-15) Function created | |
#> | |
[CmdletBinding()] | |
param ( | |
[parameter(Mandatory = $true, HelpMessage = "Your Azure AD Directory ID should be provided")] | |
[ValidateNotNullOrEmpty()] | |
[string]$TenantID, | |
[parameter(Mandatory = $true, HelpMessage = "Application ID for an Azure AD application")] | |
[ValidateNotNullOrEmpty()] | |
[string]$ClientID, | |
[parameter(Mandatory = $true, HelpMessage = "Azure AD Application Client Secret.")] | |
[ValidateNotNullOrEmpty()] | |
[string]$ClientSecret | |
) | |
Process { | |
$ErrorActionPreference = "Stop" | |
# Construct URI | |
$uri = "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token" | |
# Construct Body | |
$body = @{ | |
client_id = $clientId | |
scope = "https://graph.microsoft.com/.default" | |
client_secret = $clientSecret | |
grant_type = "client_credentials" | |
} | |
try { | |
$MyTokenRequest = Invoke-WebRequest -Method Post -Uri $uri -ContentType "application/x-www-form-urlencoded" -Body $body -UseBasicParsing | |
$MyToken =($MyTokenRequest.Content | ConvertFrom-Json).access_token | |
If(!$MyToken){ | |
Write-Warning "Failed to get Graph API access token!" | |
Exit 1 | |
} | |
$MyHeader = @{"Authorization" = "Bearer $MyToken" } | |
} | |
catch [System.Exception] { | |
Write-Warning "Failed to get Access Token, Error message: $($_.Exception.Message)"; break | |
} | |
return $MyHeader | |
} | |
} | |
#Generate Graph API Token | |
$global:Header = Get-MSGraphAppToken -TenantID $TenantId -ClientID $ClientID -ClientSecret $ClientSecret | |
#URL to SharePoint list with expand fields. | |
$currentUri = "https://graph.microsoft.com/v1.0/groups?`$filter=resourceProvisioningOptions/Any(x:x eq 'Team')" | |
#Gets entrys in SharePoint list. | |
$Teams = while (-not [string]::IsNullOrEmpty($currentUri)) { | |
# API Call | |
# Write-Host "`r`nQuerying $currentUri..." -ForegroundColor Yellow | |
$apiCall = Invoke-WebRequest -Method "GET" -Uri $currentUri -ContentType "application/json" -Headers $global:Header -ErrorAction Stop -UseBasicParsing | |
$nextLink = $null | |
$currentUri = $null | |
if ($apiCall.Content) { | |
# Check if any data is left | |
$nextLink = $apiCall.Content | ConvertFrom-Json | Select-Object '@odata.nextLink' | |
$currentUri = $nextLink.'@odata.nextLink' | |
$apiCall.Content | ConvertFrom-Json | |
} | |
} | |
$Teams = $Teams.value | |
$count = 0 | |
foreach($team in $teams){ | |
If($stopwatch.Elapsed.minutes -gt 40) { | |
$stopwatch = [system.diagnostics.stopwatch]::StartNew() | |
#Generate Graph API Token | |
$global:Header = Get-MSGraphAppToken -TenantID $TenantId -ClientID $ClientID -ClientSecret $ClientSecret | |
} | |
$count++ | |
$count | |
$filetypes = @() | |
$teamschannelsURL = "https://graph.microsoft.com/v1.0/teams/$($team.id)/channels" | |
$teamchannels = (Invoke-RestMethod -Method "GET" -Uri $teamschannelsURL -ContentType "application/json" -Headers $global:Header -ErrorAction Stop -UseBasicParsing).value | |
foreach($channel in $teamchannels){ | |
if($channel.membershiptype -eq "private"){ | |
$channelURL = $teamschannelsURL+"/$($channel.id)/filesfolder" | |
$channelinfo = (Invoke-RestMethod -Method "GET" -Uri $channelURL -ContentType "application/json" -Headers $global:Header -ErrorAction Stop -UseBasicParsing).parentReference.driveid | |
$driveurl = "https://graph.microsoft.com/v1.0/drives/$channelinfo/list" | |
$PrivateList = Invoke-RestMethod -Method "GET" -Uri $driveurl -ContentType "application/json" -Headers $global:Header -ErrorAction Stop -UseBasicParsing | |
$PrivateListID = $PrivateList.id | |
$PrivateSiteID = ((($PrivateList.parentReference).siteid).split(".com,")[1]).split(",")[0] | |
$PrivateSharePointDocumentsURL = "https://graph.microsoft.com/v1.0/sites/$privatesiteid/lists/$privatelistid/items" | |
$currentUri = $PrivateSharePointDocumentsURL | |
#Gets entrys in SharePoint list. | |
$Documents = @() | |
$Documents = while (-not [string]::IsNullOrEmpty($currentUri)) { | |
# API Call | |
# Write-Host "`r`nQuerying $currentUri..." -ForegroundColor Yellow | |
$apiCall = Invoke-WebRequest -Method "GET" -Uri $currentUri -ContentType "application/json" -Headers $global:Header -ErrorAction Stop -UseBasicParsing | |
$nextLink = $null | |
$currentUri = $null | |
if ($apiCall.Content) { | |
# Check if any data is left | |
$nextLink = $apiCall.Content | ConvertFrom-Json | Select-Object '@odata.nextLink' | |
$currentUri = $nextLink.'@odata.nextLink' | |
$apiCall.Content | ConvertFrom-Json | |
} | |
} | |
$Documents = $Documents.value | Where-Object{($_.contenttype).name -eq "Document"} | |
$filetypes += $Documents.weburl -replace '.*\.' | select-string -Pattern '^[^\s]{3,4}$' | |
} | |
} | |
$TeamSharePointID = @() | |
$TeamSharePointID = $team.proxyAddresses | Where-Object { $_ -like 'SPO:*' } | |
$TeamSharePointID = ($TeamSharePointID.split("SPO:SPO_")[1]).split("@SPO_")[0] | |
$SharePointListsURL = "https://graph.microsoft.com/v1.0/sites/$TeamSharePointID/lists/" | |
$SharePointList = (Invoke-RestMethod -Method "GET" -Uri $SharePointListsURL -ContentType "application/json" -Headers $global:Header -ErrorAction Stop -UseBasicParsing).value | where-object { $_.name -eq 'Shared Documents' } | |
$SharePointDocumentsURL = @() | |
$SharePointDocumentsURL = $SharePointListsURL+$SharePointList.id+"/items" | |
#URL to SharePoint list with expand fields. | |
$currentUri = $SharePointDocumentsURL | |
#Gets entrys in SharePoint list. | |
$Documents = @() | |
$Documents = while (-not [string]::IsNullOrEmpty($currentUri)) { | |
# API Call | |
# Write-Host "`r`nQuerying $currentUri..." -ForegroundColor Yellow | |
$apiCall = try{Invoke-WebRequest -Method "GET" -Uri $currentUri -ContentType "application/json" -Headers $global:Header -ErrorAction Stop -UseBasicParsing} Catch{Start-Sleep -Seconds 10;Invoke-WebRequest -Method "GET" -Uri $currentUri -ContentType "application/json" -Headers $global:Header -ErrorAction Stop -UseBasicParsing } | |
$nextLink = $null | |
$currentUri = $null | |
if ($apiCall.Content) { | |
# Check if any data is left | |
$nextLink = $apiCall.Content | ConvertFrom-Json | Select-Object '@odata.nextLink' | |
$currentUri = $nextLink.'@odata.nextLink' | |
$apiCall.Content | ConvertFrom-Json | |
} | |
} | |
$Documents = $Documents.value | Where-Object{($_.contenttype).name -eq "Document"} | |
$filetypes += $Documents.weburl -replace '.*\.' | select-string -Pattern '^[^\s]{3,4}$' | |
$filetypesUnique = $filetypes | Sort-Object -Unique | |
write-output "FileTypes Unique: $($filetypesUnique.count)" | |
foreach($filetype in $filetypesUnique){ | |
$datemodified = @() | |
$datemodified = (($datemodified = $Documents | Where-Object { $_.weburl -like "*$filetype" } ).lastModifiedDateTime | Sort-Object -descending)[0] | |
If(!$datemodified){$datemodified = 0} | |
$TeamStatsObject = @() | |
$TeamStatsObject = [PSCustomObject]@{ | |
Displayname = $team.displayName | |
ObjectID = $team.id | |
Type = $filetype | |
Count = ($filetypes | Where-Object { $_ -eq $filetype }).count | |
LastModified = $datemodified | |
} | |
$TeamsStatsTotal += $TeamStatsObject | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment