v3 version
This commit is contained in:
parent
c4fa4ae57f
commit
0200572011
|
|
@ -37,23 +37,45 @@ foreach ($module in $requiredModules) {
|
||||||
|
|
||||||
function Connect-GraphWithDebug {
|
function Connect-GraphWithDebug {
|
||||||
try {
|
try {
|
||||||
# Required scopes for OneDrive access
|
|
||||||
$scopes = @(
|
$scopes = @(
|
||||||
"Files.Read.All",
|
"Files.Read.All",
|
||||||
"Files.ReadWrite.All",
|
"Files.ReadWrite.All",
|
||||||
|
"Files.Read",
|
||||||
|
"Files.ReadWrite",
|
||||||
"offline_access",
|
"offline_access",
|
||||||
"openid",
|
"openid",
|
||||||
"profile"
|
"profile"
|
||||||
)
|
)
|
||||||
|
|
||||||
Write-Host "Connecting to Microsoft Graph..."
|
Write-Host "Connecting to Microsoft Graph..."
|
||||||
Connect-MgGraph -Scopes $scopes
|
# Force a new token by disconnecting first
|
||||||
|
Disconnect-MgGraph -ErrorAction SilentlyContinue
|
||||||
|
|
||||||
# Get and display current connection info
|
# Try to connect and verify the connection worked
|
||||||
|
Connect-MgGraph -Scopes $scopes
|
||||||
$context = Get-MgContext
|
$context = Get-MgContext
|
||||||
|
|
||||||
|
if (-not $context -or [string]::IsNullOrEmpty($context.Account)) {
|
||||||
|
Write-Error "Failed to authenticate with Microsoft Graph - no valid context"
|
||||||
|
return $false
|
||||||
|
}
|
||||||
|
|
||||||
Write-Host "Connected as: $($context.Account)"
|
Write-Host "Connected as: $($context.Account)"
|
||||||
Write-Host "Scopes: $($context.Scopes -join ', ')"
|
Write-Host "Scopes: $($context.Scopes -join ', ')"
|
||||||
|
|
||||||
|
# Verify we can actually access the API
|
||||||
|
try {
|
||||||
|
$testDrive = Get-MgDrive -Filter "driveType eq 'personal'" -ErrorAction Stop | Select-Object -First 1
|
||||||
|
if (-not $testDrive) {
|
||||||
|
Write-Error "Could not access OneDrive after authentication"
|
||||||
|
return $false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
Write-Error "Failed to verify Graph API access: $_"
|
||||||
|
return $false
|
||||||
|
}
|
||||||
|
|
||||||
return $true
|
return $true
|
||||||
}
|
}
|
||||||
catch {
|
catch {
|
||||||
|
|
@ -92,19 +114,6 @@ function Get-DriveItems {
|
||||||
|
|
||||||
Write-Host "Found $($items.Count) items in specified folder"
|
Write-Host "Found $($items.Count) items in specified folder"
|
||||||
|
|
||||||
# Debug output for first few items
|
|
||||||
$items | Select-Object -First 50000 | ForEach-Object {
|
|
||||||
Write-Host "`nItem: $($_.Name)"
|
|
||||||
Write-Host "Type: $($_.File.MimeType)"
|
|
||||||
Write-Host "ID: $($_.Id)"
|
|
||||||
|
|
||||||
# Additional debug info for photos
|
|
||||||
if ($_.Photo) {
|
|
||||||
Write-Host "Photo metadata found!"
|
|
||||||
$_.Photo | Format-List | Out-String | Write-Host
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $items
|
return $items
|
||||||
}
|
}
|
||||||
catch {
|
catch {
|
||||||
|
|
@ -142,6 +151,14 @@ function Test-DownloadItem {
|
||||||
}
|
}
|
||||||
|
|
||||||
Write-Host "Downloading to: $fileName"
|
Write-Host "Downloading to: $fileName"
|
||||||
|
|
||||||
|
# Try to refresh token before download
|
||||||
|
$context = Get-MgContext
|
||||||
|
if (-not $context -or $context.ExpiresOn -le (Get-Date)) {
|
||||||
|
Write-Host "Token expired or missing, reconnecting..." -ForegroundColor Yellow
|
||||||
|
Connect-GraphWithDebug | Out-Null
|
||||||
|
}
|
||||||
|
|
||||||
Get-MgDriveItemContent -DriveId $drive.Id -DriveItemId $ItemId -OutFile $fileName
|
Get-MgDriveItemContent -DriveId $drive.Id -DriveItemId $ItemId -OutFile $fileName
|
||||||
|
|
||||||
if (Test-Path $fileName) {
|
if (Test-Path $fileName) {
|
||||||
|
|
@ -152,6 +169,20 @@ function Test-DownloadItem {
|
||||||
}
|
}
|
||||||
catch {
|
catch {
|
||||||
Write-Error "Download failed: $_"
|
Write-Error "Download failed: $_"
|
||||||
|
Write-Host "Attempting to reconnect and retry..." -ForegroundColor Yellow
|
||||||
|
|
||||||
|
try {
|
||||||
|
Connect-GraphWithDebug | Out-Null
|
||||||
|
Get-MgDriveItemContent -DriveId $drive.Id -DriveItemId $ItemId -OutFile $fileName
|
||||||
|
|
||||||
|
if (Test-Path $fileName) {
|
||||||
|
Write-Host "Successfully downloaded on retry: $fileName" -ForegroundColor Green
|
||||||
|
return $true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
Write-Error "Retry download failed: $_"
|
||||||
|
}
|
||||||
return $false
|
return $false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -161,55 +192,47 @@ function Get-LivePhotoBundle {
|
||||||
[Parameter(Mandatory)]
|
[Parameter(Mandatory)]
|
||||||
$item,
|
$item,
|
||||||
[Parameter(Mandatory)]
|
[Parameter(Mandatory)]
|
||||||
$drive,
|
$drive
|
||||||
[Parameter(Mandatory)]
|
|
||||||
$AccessToken
|
|
||||||
)
|
)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if ($item.File.MimeType -eq "image/heic") {
|
if ($item.File.MimeType -eq "image/heic") {
|
||||||
Write-Host "Found HEIC file: $($item.Name)" -ForegroundColor Cyan
|
Write-Host "`nDetailed HEIC Analysis:" -ForegroundColor Cyan
|
||||||
|
Write-Host "------------------------"
|
||||||
|
Write-Host "File Name: $($item.Name)"
|
||||||
|
Write-Host "File Size: $($item.Size) bytes"
|
||||||
|
|
||||||
|
# Try to download video directly using the same item ID
|
||||||
$baseName = [System.IO.Path]::GetFileNameWithoutExtension($item.Name)
|
$baseName = [System.IO.Path]::GetFileNameWithoutExtension($item.Name)
|
||||||
|
|
||||||
# Get the video component using the direct video format API
|
|
||||||
$videoPath = Join-Path $SaveTo "$baseName.mov"
|
$videoPath = Join-Path $SaveTo "$baseName.mov"
|
||||||
$tmpFile = Join-Path $SaveTo "tmp-file.mov"
|
|
||||||
|
|
||||||
if (-not (Test-Path $videoPath)) {
|
# Use the same video download URL format as the original script
|
||||||
Write-Host "Attempting to download video component..."
|
$videoUri = "https://api.onedrive.com/v1.0/drive/items/$($item.Id)/content?format=video"
|
||||||
|
Write-Host "Attempting direct video download: $videoUri"
|
||||||
|
|
||||||
|
try {
|
||||||
|
$response = Invoke-MgGraphRequest -Method GET -Uri $videoUri -OutputFilePath $videoPath
|
||||||
|
|
||||||
# Use exactly the same endpoint and headers as original script
|
if ((Test-Path $videoPath) -and (Get-Item $videoPath).Length -gt 0) {
|
||||||
$videoUri = "https://api.onedrive.com/v1.0/drive/items/$($item.Id)/content?format=video"
|
Write-Host "Successfully downloaded video component" -ForegroundColor Green
|
||||||
Write-Host "Using video endpoint: $videoUri"
|
return $true
|
||||||
|
} else {
|
||||||
try {
|
Write-Host "Downloaded file appears to be invalid" -ForegroundColor Yellow
|
||||||
# Use exact same headers as original script
|
Remove-Item $videoPath -ErrorAction SilentlyContinue
|
||||||
$headers = @{
|
|
||||||
'Authorization' = "BEARER $AccessToken" # Note: BEARER in uppercase
|
|
||||||
}
|
|
||||||
|
|
||||||
Write-Host "Calling OneDrive API for video..."
|
|
||||||
$WebRequest = Invoke-WebRequest -Method "GET" -Uri $videoUri -Header $headers -ErrorAction SilentlyContinue -OutFile $tmpFile -PassThru
|
|
||||||
Write-Host "WebRequest: Done Calling OneDrive API"
|
|
||||||
if ((Test-Path $tmpFile) -and (Get-Item $tmpFile).Length -gt 0) {
|
|
||||||
$fileName = ($WebRequest.Headers.'Content-Disposition'.Split('=',2)[-1]).Trim('"')
|
|
||||||
if ($fileName) {
|
|
||||||
Write-Host "Renaming $tmpFile to $fileName"
|
|
||||||
if (Test-Path $videoPath) {
|
|
||||||
Remove-Item $videoPath
|
|
||||||
}
|
|
||||||
Rename-Item -Path $tmpFile -NewName $fileName
|
|
||||||
return $true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch {
|
}
|
||||||
Write-Host "Failed to download video component: $_" -ForegroundColor Red
|
catch {
|
||||||
Remove-Item $tmpFile -ErrorAction SilentlyContinue
|
Write-Host "Direct video download failed, trying alternative methods..." -ForegroundColor Yellow
|
||||||
}
|
Write-Host "Error details:" -ForegroundColor Red
|
||||||
} else {
|
Write-Host "Status Code: $($_.Exception.Response.StatusCode.value__)" -ForegroundColor Red
|
||||||
Write-Host "Video file already exists: $videoPath" -ForegroundColor Yellow
|
Write-Host "Status Description: $($_.Exception.Response.StatusDescription)" -ForegroundColor Red
|
||||||
return $true
|
Write-Host "Error Message: $($_.Exception.Message)" -ForegroundColor Red
|
||||||
|
Write-Host "Request URI: $videoUri" -ForegroundColor Red
|
||||||
|
|
||||||
|
# Write full error object for debugging
|
||||||
|
Write-Debug "Full Error Object:"
|
||||||
|
Write-Debug ($_ | Format-List -Force | Out-String)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return $false
|
return $false
|
||||||
|
|
@ -296,57 +319,83 @@ if (!(Test-Path $SaveTo)) {
|
||||||
New-Item -ItemType Directory -Force -Path $SaveTo
|
New-Item -ItemType Directory -Force -Path $SaveTo
|
||||||
}
|
}
|
||||||
|
|
||||||
# Get both authentication tokens
|
# Get Graph API token with retry
|
||||||
Write-Host "Getting Graph API token..."
|
$maxRetries = 3
|
||||||
if (Connect-GraphWithDebug) {
|
$retryCount = 0
|
||||||
Write-Host "`nGetting OneDrive Photos token..."
|
$connected = $false
|
||||||
$photosToken = Get-ODPhotosToken
|
|
||||||
|
while (-not $connected -and $retryCount -lt $maxRetries) {
|
||||||
|
$retryCount++
|
||||||
|
Write-Host "`nAttempting Graph API connection (Attempt $retryCount of $maxRetries)..."
|
||||||
|
|
||||||
Write-Host "`nQuerying OneDrive items..."
|
if (Connect-GraphWithDebug) {
|
||||||
$items = Get-DriveItems -FolderPath $PathToScan
|
$connected = $true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
if ($items) {
|
if ($retryCount -lt $maxRetries) {
|
||||||
# Get drive reference
|
Write-Host "Connection failed. Waiting 5 seconds before retry..."
|
||||||
$drive = Get-MgDrive -Filter "driveType eq 'personal'" | Select-Object -First 1
|
Start-Sleep -Seconds 5
|
||||||
if (-not $drive) {
|
|
||||||
Write-Error "Could not get drive reference"
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
Write-Host "`nProcessing items for Live Photos..."
|
|
||||||
foreach ($item in $items) {
|
|
||||||
Write-Host "`nChecking item: $($item.Name)"
|
|
||||||
|
|
||||||
# Process only HEIC files
|
|
||||||
if ($item.File.MimeType -eq "image/heic") {
|
|
||||||
Write-Host "Found HEIC file, checking for Live Photo components..."
|
|
||||||
|
|
||||||
# Download the HEIC file if it doesn't exist
|
|
||||||
try {
|
|
||||||
$result = Test-DownloadItem -ItemId $item.Id -SavePath $SaveTo -item $item
|
|
||||||
if ($result) {
|
|
||||||
# Try to get the video component, passing all items and the photos token
|
|
||||||
$hasVideo = Get-LivePhotoBundle -item $item -drive $drive -AccessToken $photosToken.'AccessToken-OneDrive.ReadWrite'
|
|
||||||
if ($hasVideo) {
|
|
||||||
Write-Host "Successfully processed Live Photo bundle for: $($item.Name)" -ForegroundColor Green
|
|
||||||
} else {
|
|
||||||
Write-Host "No Live Photo video component found for: $($item.Name)" -ForegroundColor Yellow
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch {
|
|
||||||
Write-Host "Error processing $($item.Name): $_" -ForegroundColor Red
|
|
||||||
}
|
|
||||||
|
|
||||||
# Add a small delay between items
|
|
||||||
Start-Sleep -Milliseconds 500
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Write-Host "`nCompleted processing Live Photos"
|
|
||||||
} else {
|
|
||||||
Write-Host "No items found to process"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (-not $connected) {
|
||||||
|
Write-Error "Failed to connect to Graph API after $maxRetries attempts. Exiting."
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get both authentication tokens
|
||||||
|
Write-Host "`nGetting OneDrive Photos token..."
|
||||||
|
$photosToken = Get-ODPhotosToken
|
||||||
|
if (-not $photosToken) {
|
||||||
|
Write-Error "Failed to get OneDrive Photos token. Exiting."
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get drive reference first
|
||||||
|
$drive = Get-MgDrive -Filter "driveType eq 'personal'" | Select-Object -First 1
|
||||||
|
if (-not $drive) {
|
||||||
|
Write-Error "Could not get drive reference"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host "`nQuerying OneDrive items..."
|
||||||
|
$items = Get-DriveItems -FolderPath $PathToScan
|
||||||
|
if (-not $items) {
|
||||||
|
Write-Error "No items found or error occurred while fetching items"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host "`nProcessing items for Live Photos..."
|
||||||
|
foreach ($item in $items) {
|
||||||
|
Write-Host "`nChecking item: $($item.Name)"
|
||||||
|
|
||||||
|
# Process only HEIC files
|
||||||
|
if ($item.File.MimeType -eq "image/heic") {
|
||||||
|
Write-Host "Found HEIC file, checking for Live Photo components..."
|
||||||
|
|
||||||
|
# Download the HEIC file if it doesn't exist
|
||||||
|
try {
|
||||||
|
$result = Test-DownloadItem -ItemId $item.Id -SavePath $SaveTo -item $item
|
||||||
|
if ($result) {
|
||||||
|
# Try to get the video component, passing all items and the photos token
|
||||||
|
$hasVideo = Get-LivePhotoBundle -item $item -drive $drive
|
||||||
|
if ($hasVideo) {
|
||||||
|
Write-Host "Successfully processed Live Photo bundle for: $($item.Name)" -ForegroundColor Green
|
||||||
|
} else {
|
||||||
|
Write-Host "No Live Photo video component found for: $($item.Name)" -ForegroundColor Yellow
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
Write-Host "Error processing $($item.Name): $_" -ForegroundColor Red
|
||||||
|
}
|
||||||
|
|
||||||
|
# Add a small delay between items
|
||||||
|
Start-Sleep -Milliseconds 500
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host "`nCompleted processing Live Photos"
|
||||||
|
|
||||||
Write-Host "`nDebug script completed"
|
Write-Host "`nDebug script completed"
|
||||||
Loading…
Reference in New Issue