Add manual download watch mode
This commit is contained in:
+109
-1
@@ -17,6 +17,8 @@ $queue = [System.Collections.Queue]::new()
|
||||
$queueIds = [System.Collections.Generic.HashSet[string]]::new()
|
||||
$activeJobs = [System.Collections.ArrayList]::new()
|
||||
$activeIds = [System.Collections.Generic.HashSet[string]]::new()
|
||||
$pendingDownloads = [System.Collections.ArrayList]::new()
|
||||
$claimedDownloadPaths = [System.Collections.Generic.HashSet[string]]::new([System.StringComparer]::OrdinalIgnoreCase)
|
||||
$stats = [ordered]@{
|
||||
total = 0
|
||||
completed = 0
|
||||
@@ -238,6 +240,7 @@ function Get-QueueSnapshot {
|
||||
return [pscustomobject]@{
|
||||
maxWorkers = $MaxWorkers
|
||||
queued = $script:queue.Count
|
||||
pendingDownloads = $script:pendingDownloads.Count
|
||||
activeCount = $active.Count
|
||||
active = if ($active.Count) { ($active | Select-Object -First 1).title } else { "" }
|
||||
activeJobs = $active
|
||||
@@ -302,7 +305,7 @@ function Show-Dashboard {
|
||||
Write-Host "Library: $libraryRoot"
|
||||
Write-Host "Logs: $logs"
|
||||
Write-Host ""
|
||||
Write-Host ("Workers: {0}/{1} Queue: {2} Done: {3}/{4} Failed: {5} Progress: {6}%" -f $snapshot.activeCount, $snapshot.maxWorkers, $snapshot.queued, $snapshot.done, $snapshot.total, $snapshot.failed, $snapshot.percent)
|
||||
Write-Host ("Workers: {0}/{1} Queue: {2} Waiting downloads: {3} Done: {4}/{5} Failed: {6} Progress: {7}%" -f $snapshot.activeCount, $snapshot.maxWorkers, $snapshot.queued, $snapshot.pendingDownloads, $snapshot.done, $snapshot.total, $snapshot.failed, $snapshot.percent)
|
||||
Write-Host ("{0} {1}/{2}" -f (Format-ProgressBar $snapshot.done $snapshot.total), $snapshot.done, $snapshot.total) -ForegroundColor Cyan
|
||||
Write-Host ""
|
||||
|
||||
@@ -439,6 +442,93 @@ function Save-UploadedTrack {
|
||||
return Add-TracksToQueue @($track) "$($Payload.pageUrl)"
|
||||
}
|
||||
|
||||
function Get-DownloadsRoot {
|
||||
$path = Join-Path $env:USERPROFILE "Downloads"
|
||||
if (Test-Path -LiteralPath $path) { return $path }
|
||||
return ""
|
||||
}
|
||||
|
||||
function Test-StableDownloadFile {
|
||||
param([System.IO.FileInfo]$File, [string]$Ext)
|
||||
|
||||
if (-not $File -or -not $File.Exists) { return $false }
|
||||
if ($File.Name -like "*.crdownload" -or $File.Name -like "*.tmp") { return $false }
|
||||
if ($File.Extension.TrimStart(".").ToLowerInvariant() -ne $Ext) { return $false }
|
||||
if ($File.Length -lt 131072) { return $false }
|
||||
return ((Get-Date) - $File.LastWriteTime).TotalSeconds -ge 2
|
||||
}
|
||||
|
||||
function Find-ExpectedDownloadFile {
|
||||
param($Expected)
|
||||
|
||||
$downloads = Get-DownloadsRoot
|
||||
if (-not $downloads) { return $null }
|
||||
$ext = "$($Expected.Format)".TrimStart(".").ToLowerInvariant()
|
||||
$registeredAt = [DateTime]$Expected.RegisteredAt
|
||||
$candidates = Get-ChildItem -LiteralPath $downloads -File -Filter "*.$ext" -ErrorAction SilentlyContinue |
|
||||
Where-Object {
|
||||
-not $script:claimedDownloadPaths.Contains($_.FullName) -and
|
||||
$_.CreationTime -ge $registeredAt.AddSeconds(-10) -and
|
||||
(Test-StableDownloadFile $_ $ext)
|
||||
} |
|
||||
Sort-Object CreationTime
|
||||
|
||||
return @($candidates)[0]
|
||||
}
|
||||
|
||||
function Register-ExpectedDownloads {
|
||||
param($Payload)
|
||||
|
||||
$format = "$($Payload.format)".TrimStart(".").ToLowerInvariant()
|
||||
if ($format -notin @("mp3", "wav")) { throw "format must be mp3 or wav" }
|
||||
$tracks = @($Payload.tracks)
|
||||
if (-not $tracks.Count) { throw "tracks is empty" }
|
||||
|
||||
$missing = Get-MissingTracks $tracks
|
||||
$added = 0
|
||||
foreach ($track in @($missing.missing)) {
|
||||
$id = "$($track.id)".Trim()
|
||||
if (-not $id) { continue }
|
||||
$alreadyPending = @($script:pendingDownloads | Where-Object { $_.Id -eq $id -and $_.Format -eq $format }).Count -gt 0
|
||||
if ($alreadyPending -or $script:queueIds.Contains($id) -or $script:activeIds.Contains($id)) { continue }
|
||||
[void]$script:pendingDownloads.Add([pscustomobject]@{
|
||||
Id = $id
|
||||
Title = "$($track.title)"
|
||||
Track = $track
|
||||
Format = $format
|
||||
PageUrl = "$($Payload.pageUrl)"
|
||||
RegisteredAt = Get-Date
|
||||
})
|
||||
$added++
|
||||
}
|
||||
|
||||
return [pscustomobject]@{
|
||||
added = $added
|
||||
pending = $script:pendingDownloads.Count
|
||||
existingRequested = @($missing.existingRequested).Count
|
||||
missingRequested = @($missing.missing).Count
|
||||
invalidRequested = $missing.invalid
|
||||
}
|
||||
}
|
||||
|
||||
function Update-ExpectedDownloads {
|
||||
if (-not $script:pendingDownloads.Count) { return }
|
||||
|
||||
for ($index = $script:pendingDownloads.Count - 1; $index -ge 0; $index--) {
|
||||
$expected = $script:pendingDownloads[$index]
|
||||
$file = Find-ExpectedDownloadFile $expected
|
||||
if (-not $file) { continue }
|
||||
|
||||
[void]$script:claimedDownloadPaths.Add($file.FullName)
|
||||
$track = $expected.Track
|
||||
$track | Add-Member -NotePropertyName "localAudioPath" -NotePropertyValue $file.FullName -Force
|
||||
$track | Add-Member -NotePropertyName "localAudioExt" -NotePropertyValue $expected.Format -Force
|
||||
$result = Add-TracksToQueue @($track) "$($expected.PageUrl)"
|
||||
$script:pendingDownloads.RemoveAt($index)
|
||||
Write-Host "Picked downloaded $($expected.Format): $($expected.Title) <- $($file.Name) queued=$($result.queued)"
|
||||
}
|
||||
}
|
||||
|
||||
function Get-ExistingSunoIds {
|
||||
param([string]$Root)
|
||||
|
||||
@@ -501,6 +591,7 @@ Show-Dashboard -Force
|
||||
|
||||
try {
|
||||
while ($true) {
|
||||
Update-ExpectedDownloads
|
||||
Update-Queue
|
||||
if (-not $listener.Pending()) {
|
||||
Start-Sleep -Milliseconds 500
|
||||
@@ -526,6 +617,7 @@ try {
|
||||
artist = $ArtistName
|
||||
queued = $snapshot.queued
|
||||
active = $snapshot.active
|
||||
pendingDownloads = $snapshot.pendingDownloads
|
||||
activeCount = $snapshot.activeCount
|
||||
activeJobs = $snapshot.activeJobs
|
||||
next = $snapshot.next
|
||||
@@ -581,6 +673,22 @@ try {
|
||||
continue
|
||||
}
|
||||
|
||||
if ($request.Method -eq "POST" -and $request.Path -eq "/expect-downloads") {
|
||||
$payload = $request.Body | ConvertFrom-Json
|
||||
$result = Register-ExpectedDownloads $payload
|
||||
Write-Host "Waiting for browser downloads: added=$($result.added), pending=$($result.pending), format=$($payload.format)"
|
||||
Write-Response $stream 200 "OK" (@{
|
||||
ok = $true
|
||||
added = $result.added
|
||||
pendingDownloads = $result.pending
|
||||
existingRequested = $result.existingRequested
|
||||
missingRequested = $result.missingRequested
|
||||
invalidRequested = $result.invalidRequested
|
||||
downloadsRoot = Get-DownloadsRoot
|
||||
} | ConvertTo-Json -Compress)
|
||||
continue
|
||||
}
|
||||
|
||||
if ($request.Method -eq "POST" -and $request.Path -eq "/process") {
|
||||
$manifest = $request.Body | ConvertFrom-Json
|
||||
if (-not $manifest.tracks -or @($manifest.tracks).Count -eq 0) {
|
||||
|
||||
Reference in New Issue
Block a user