param( [Parameter(Mandatory = $true)] [string[]]$Team, [switch]$Exact ) $config = Get-Content -Path ./config.json -Raw | ConvertFrom-Json $tenantId = $config.tenantId $clientID = $config.clientID $clientSecret = (ConvertTo-SecureString $config.clientSecret -AsPlainText -Force ) $Scope = "https://graph.microsoft.com/.default" $authToken = Get-MsalToken -ClientId $clientID -ClientSecret $clientSecret -TenantId $tenantId -Scopes $Scope Write-Host "Processing $($Team.Count) teams: $($Team -join ', ')" $Headers = @{ "Authorization" = "Bearer $($authToken.AccessToken)" "Content-type" = "application/json" } $allTeams = @() $teamsResponse = Invoke-WebRequest -Uri "https://graph.microsoft.com/v1.0/teams/" -Headers $Headers -Method GET $aadTeams = $teamsResponse.Content | ConvertFrom-Json $allTeams += $aadTeams.value if ($aadTeams.'@odata.nextLink') { do { $teamsResponse = Invoke-WebRequest -Uri $aadTeams.'@odata.nextLink' -Headers $Headers -Method GET $aadTeams = $teamsResponse.Content | ConvertFrom-Json $allTeams += $aadTeams.value } until (!$aadTeams.'@odata.nextLink') } $aadTeams = $allTeams foreach ($requestedTeam in $Team) { Write-Host "`nProcessing team: $requestedTeam" $channels = [System.Collections.ArrayList]::New() $foundTeam = $false foreach ($teams in $aadTeams) { if ($foundTeam) { break } $teamMatches = if ($Exact) { $teams.displayName -eq $requestedTeam } else { $teams.displayName -like "$($requestedTeam)*" } if ($teamMatches) { Write-Host "Found matching team: $($teams.displayName)" $apiUri = "https://graph.microsoft.com/v1.0/teams/$($teams.id)/channels" $response = Invoke-WebRequest -Headers $Headers -Uri $apiUri -Method GET try { $teamResponse = $response.Content | ConvertFrom-Json -ErrorAction Stop } catch { $teamResponse = [System.Web.HttpUtility]::JavaScriptStringDeserializer.Deserialize($response.Content, [System.Object]) } $channelList = $null if ($teamResponse.value) { $channelList = $teamResponse.value } elseif ($teamResponse.PSObject.Properties['value']) { $channelList = $teamResponse.PSObject.Properties['value'].Value } else { $rawContent = $response.Content if ($rawContent -match '"value":\s*\[(.*?)\]') { $jsonArray = "[$($matches[1])]" $channelList = $jsonArray | ConvertFrom-Json } } if ($channelList) { Write-Host "Processing $($channelList.Count) channels for team: $($teams.displayName)" foreach ($channel in $channelList) { Start-Sleep -Milliseconds 250 $folderResponse = Invoke-WebRequest -Headers $Headers -Uri "https://graph.microsoft.com/v1.0/teams/$($teams.id)/channels/$($channel.id)/filesFolder" -Method GET $channelFolder = $folderResponse.Content | ConvertFrom-Json $DriveID = $channelFolder.parentReference.driveId $displayName = $channelFolder.name -replace " ", "_" -replace ",", "" $Result = [PSCustomObject]@{ displayName = $displayName driveID = $DriveID membershipType = $channel.membershipType teamName = $teams.displayName } [void]$channels.Add($Result) Write-Host "Added channel: $displayName with DriveID: $DriveID" } } else { Write-Host "WARNING: No channels found for team: $($teams.displayName)" } $foundTeam = $true } } if ($channels.Count -eq 0) { Write-Host "ERROR: No channels were processed for team: $requestedTeam" continue } Write-Host "Total channels processed for $requestedTeam`: $($channels.Count)" $uniqueDrives = $channels | Sort-Object -Property driveID -Unique | Select-Object displayName, driveID, membershipType, teamName Write-Host "Unique drives found for $requestedTeam`: $($uniqueDrives.Count)" $uniqueDrives | ForEach-Object { if ($_.membershipType -eq 'standard') { $_.displayName = $_.teamName -replace " ", "_" } } $UnionName = "$($channels[0].teamName)_union" -replace " ", "_" $RcloneFileName = $UnionName -replace "_union", "" foreach ($drive in $uniqueDrives) { $config = Get-Content -Path ./remote-template.conf -Raw $remote = $config -f $drive.displayName, $drive.driveID Add-Content -Value $remote -Path "./$RcloneFileName.conf" Write-Host "Added remote config for: $($drive.displayName)" } if ($uniqueDrives.Count -ge 2) { $teamNames = $($uniqueDrives.displayName -join [Environment]::NewLine) -replace "\n", ": " $teamNames = "$teamNames" + ":" $union = Get-Content -Path ./union-template.conf -Raw $unionConf = $union -f $UnionName, $teamNames Add-Content -Value $unionConf -Path "./$RcloneFileName.conf" Write-Host "Generated union config: $UnionName" } else { Write-Host "Skipping union creation - only $($uniqueDrives.Count) remote(s) found (union requires 2+)" } Write-Host "Generated config file: $RcloneFileName.conf" }