aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md11
-rw-r--r--T2R.ps1156
-rw-r--r--config.json5
-rw-r--r--remote-template.conf1
4 files changed, 126 insertions, 47 deletions
diff --git a/README.md b/README.md
index fab25bb..b52b484 100644
--- a/README.md
+++ b/README.md
@@ -13,8 +13,8 @@ Becuase microsoft dont like to make things easy and create sharepoint subsites f
3. Once the app has been made make note of the Application (client) ID and Directory (tennant) ID
4. Go to Certificates & Secrets > Client secrets and create a new client secret, set the expire and click add
5. Once it has been generated make a note of the Value, once you change page that will be stared out and you wont be able to see it again.
-6. In your T2R.ps1 set the `tennantId`, `clientID` and `client secret (Value)`
-7. in the remote-template.conf set the `client ID`, `client secret (value)` and `tennantID`
+6. In your config.json set the `tennantId`, `clientID` and `client secret (Value)`
+7. in the remote-template.conf set the `client ID`, `client secret (value)`, `tennantID` and replace `<tenant>` with your tenantID
8. Go to `API permissions > Add a permission > Microsoft Graph > Application permissions` and add the below permissions
```plain
@@ -32,13 +32,10 @@ Team.ReadBasic.All
Sites.Read.All
```
-1. Once the permissions have been set and your remote-template.conf and the top 2 lines of the T2R.ps1 is filled in, run T2R.ps1 and enter your team name
-2. Wait a few seconds for it to do its thing and you should see rclone.conf show up
-3. run `rclone lsd --config ./rclone TEAM_NAME_union:` to see a list of the root folders for the team it has pulled
-
## Usage
- Run the script
- Enter your team name when it asks
- Wait
-- Run `rclone lsd --config ./rclone TEAM_NAME_union:` when the script is finished
+- Run `rclone lsd --config ./rclone TEAM_NAME_union:` when the script is finished to confirm you can see everything
+- If the team only contains standard channels it will create a config with 1 remote
diff --git a/T2R.ps1 b/T2R.ps1
index 288b4ee..514551f 100644
--- a/T2R.ps1
+++ b/T2R.ps1
@@ -1,10 +1,17 @@
-$tenantId = "00000000-0000-0000-0000-000000000000"
-$clientID = "00000000-0000-0000-0000-000000000000"
-$clientSecret = (ConvertTo-SecureString "CLIENT_SECRET_VALUE" -AsPlainText -Force )
+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
-$TeamsTeam = Read-Host "Enter team name"
+Write-Host "Processing $($Team.Count) teams: $($Team -join ', ')"
$Headers = @{
"Authorization" = "Bearer $($authToken.AccessToken)"
@@ -12,48 +19,119 @@ $Headers = @{
}
$allTeams = @()
-$aadTeams = (Invoke-RestMethod -Uri "https://graph.microsoft.com/v1.0/teams/" -Headers $Headers -Method Get -ContentType "application/json")
+$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 {
- $aadTeams = (Invoke-RestMethod -Uri $aadTeams.'@odata.nextLink' -Headers $Headers -Method Get -ContentType "application/json")
+ $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
-$channels = [System.Collections.ArrayList]::New()
-
-foreach ($teams in $aadTeams) {
- if ($teams.displayName -like "$($TeamsTeam)*") {
- $apiUri = "https://graph.microsoft.com/v1.0/teams/$($teams.id)/channels"
- $Team = Invoke-RestMethod -Headers $Headers -Uri $apiUri -Method GET
- $channelList = $Team.Value
- foreach ($channel in $channelList) {
- $channelFolder = Invoke-RestMethod -Headers $Headers -Uri "https://graph.microsoft.com/v1.0/teams/$($teams.id)/channels/$($channel.id)/filesFolder" -Method GET
- $DriveID = $channelFolder.parentReference.driveId
- $displayName = $channelFolder.name -replace " ", "_" -replace ",", ""
- $Result = [PSCustomObject]@{
- displayName = $displayName
- driveID = $DriveID
- membershipType = $channel.membershipType
- teamName = $teams.displayName
+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)"
}
- [void]$channels.Add($Result)
+ $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 " ", "_"
}
- }
-}
-
-$uniqueDrives = $channels | Sort-Object -Property driveID -Unique | Select-Object displayName, driveID, membershipType, teamName
-$uniqueDrives | ForEach-Object { if ($_.membershipType -eq 'standard') { $_.displayName = $_.teamName -replace " ", "_" } }
-foreach ($drive in $uniqueDrives) {
- $config = Get-Content -Path ./remote-template.conf -Raw
- $remote = $config -f $drive.displayName, $drive.driveID
- Add-Content -Value $remote -Path ./rclone.conf
-}
-
-$teamNames = $($uniqueDrives.displayName -join [Environment]::NewLine) -replace "\n", ": "
-$teamNames = $teamNames + ":"
-$union = Get-Content -Path ./union-template.conf -Raw
-$unionConf = $union -f "$($channels[0].teamName)_union", $teamNames
-Add-Content -Value $unionConf -Path ./rclone.conf \ No newline at end of file
+ }
+
+ $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"
+} \ No newline at end of file
diff --git a/config.json b/config.json
new file mode 100644
index 0000000..5d5646b
--- /dev/null
+++ b/config.json
@@ -0,0 +1,5 @@
+{
+ "tenantId": "",
+ "clientID": "",
+ "clientSecret": ""
+} \ No newline at end of file
diff --git a/remote-template.conf b/remote-template.conf
index 8918da9..38e77fc 100644
--- a/remote-template.conf
+++ b/remote-template.conf
@@ -10,4 +10,3 @@ access_scopes = Files.Read Files.Read.All Sites.Read.All offline_access
link_scope = organization
auth_url = https://login.microsoftonline.com/<tenant>/oauth2/v2.0/authorize
token_url = https://login.microsoftonline.com/<tenant>/oauth2/v2.0/token
-