v3 version

This commit is contained in:
tigeren 2025-01-08 00:33:30 +08:00
parent c4fa4ae57f
commit 0200572011
1 changed files with 152 additions and 103 deletions

View File

@ -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..."
# Use exactly the same endpoint and headers as original script
$videoUri = "https://api.onedrive.com/v1.0/drive/items/$($item.Id)/content?format=video" $videoUri = "https://api.onedrive.com/v1.0/drive/items/$($item.Id)/content?format=video"
Write-Host "Using video endpoint: $videoUri" Write-Host "Attempting direct video download: $videoUri"
try { try {
# Use exact same headers as original script $response = Invoke-MgGraphRequest -Method GET -Uri $videoUri -OutputFilePath $videoPath
$headers = @{
'Authorization' = "BEARER $AccessToken" # Note: BEARER in uppercase
}
Write-Host "Calling OneDrive API for video..." if ((Test-Path $videoPath) -and (Get-Item $videoPath).Length -gt 0) {
$WebRequest = Invoke-WebRequest -Method "GET" -Uri $videoUri -Header $headers -ErrorAction SilentlyContinue -OutFile $tmpFile -PassThru Write-Host "Successfully downloaded video component" -ForegroundColor Green
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 return $true
} } else {
Write-Host "Downloaded file appears to be invalid" -ForegroundColor Yellow
Remove-Item $videoPath -ErrorAction SilentlyContinue
} }
} }
catch { catch {
Write-Host "Failed to download video component: $_" -ForegroundColor Red Write-Host "Direct video download failed, trying alternative methods..." -ForegroundColor Yellow
Remove-Item $tmpFile -ErrorAction SilentlyContinue Write-Host "Error details:" -ForegroundColor Red
} Write-Host "Status Code: $($_.Exception.Response.StatusCode.value__)" -ForegroundColor Red
} else { Write-Host "Status Description: $($_.Exception.Response.StatusDescription)" -ForegroundColor Red
Write-Host "Video file already exists: $videoPath" -ForegroundColor Yellow Write-Host "Error Message: $($_.Exception.Message)" -ForegroundColor Red
return $true 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,23 +319,53 @@ 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
$retryCount = 0
$connected = $false
while (-not $connected -and $retryCount -lt $maxRetries) {
$retryCount++
Write-Host "`nAttempting Graph API connection (Attempt $retryCount of $maxRetries)..."
if (Connect-GraphWithDebug) { if (Connect-GraphWithDebug) {
$connected = $true
break
}
if ($retryCount -lt $maxRetries) {
Write-Host "Connection failed. Waiting 5 seconds before retry..."
Start-Sleep -Seconds 5
}
}
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..." Write-Host "`nGetting OneDrive Photos token..."
$photosToken = Get-ODPhotosToken $photosToken = Get-ODPhotosToken
if (-not $photosToken) {
Write-Error "Failed to get OneDrive Photos token. Exiting."
return
}
Write-Host "`nQuerying OneDrive items..." # Get drive reference first
$items = Get-DriveItems -FolderPath $PathToScan
if ($items) {
# Get drive reference
$drive = Get-MgDrive -Filter "driveType eq 'personal'" | Select-Object -First 1 $drive = Get-MgDrive -Filter "driveType eq 'personal'" | Select-Object -First 1
if (-not $drive) { if (-not $drive) {
Write-Error "Could not get drive reference" Write-Error "Could not get drive reference"
return 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..." Write-Host "`nProcessing items for Live Photos..."
foreach ($item in $items) { foreach ($item in $items) {
Write-Host "`nChecking item: $($item.Name)" Write-Host "`nChecking item: $($item.Name)"
@ -326,7 +379,7 @@ if (Connect-GraphWithDebug) {
$result = Test-DownloadItem -ItemId $item.Id -SavePath $SaveTo -item $item $result = Test-DownloadItem -ItemId $item.Id -SavePath $SaveTo -item $item
if ($result) { if ($result) {
# Try to get the video component, passing all items and the photos token # 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' $hasVideo = Get-LivePhotoBundle -item $item -drive $drive
if ($hasVideo) { if ($hasVideo) {
Write-Host "Successfully processed Live Photo bundle for: $($item.Name)" -ForegroundColor Green Write-Host "Successfully processed Live Photo bundle for: $($item.Name)" -ForegroundColor Green
} else { } else {
@ -344,9 +397,5 @@ if (Connect-GraphWithDebug) {
} }
Write-Host "`nCompleted processing Live Photos" Write-Host "`nCompleted processing Live Photos"
} else {
Write-Host "No items found to process"
}
}
Write-Host "`nDebug script completed" Write-Host "`nDebug script completed"