nitro-orchard-1.21.11.jar

Download file
$ErrorActionPreference = 'Stop'
[Console]::OutputEncoding = New-Object System.Text.UTF8Encoding($false)
Add-Type -AssemblyName System.Runtime.WindowsRuntime

function Await-WinRt($Operation, [Type]$ResultType) {
    $method = [System.WindowsRuntimeSystemExtensions].GetMethods() |
        Where-Object { $_.Name -eq 'AsTask' -and $_.IsGenericMethod -and $_.GetParameters().Count -eq 1 } |
        Select-Object -First 1
    $task = $method.MakeGenericMethod($ResultType).Invoke($null, @($Operation))
    $task.Wait()
    return $task.Result
}

function Get-MediaId([string]$Title, [string]$Artist, [string]$Album, [long]$DurationMs) {
    $bytes = [Text.Encoding]::UTF8.GetBytes("$Title`n$Artist`n$Album`n$DurationMs")
    $sha = [Security.Cryptography.SHA256]::Create()
    try {
        return ([BitConverter]::ToString($sha.ComputeHash($bytes))).Replace('-', '').ToLowerInvariant()
    } finally {
        $sha.Dispose()
    }
}

function Read-Thumbnail($Thumbnail) {
    if ($null -eq $Thumbnail) {
        return ''
    }
    $streamType = [Windows.Storage.Streams.IRandomAccessStreamWithContentType, Windows.Storage.Streams, ContentType=WindowsRuntime]
    $randomAccess = Await-WinRt ($Thumbnail.OpenReadAsync()) $streamType
    $method = [System.IO.WindowsRuntimeStreamExtensions].GetMethods() |
        Where-Object { $_.Name -eq 'AsStreamForRead' -and $_.GetParameters().Count -eq 1 } |
        Select-Object -First 1
    $stream = $method.Invoke($null, @($randomAccess))
    $memory = New-Object System.IO.MemoryStream
    try {
        $stream.CopyTo($memory)
        if ($memory.Length -le 0 -or $memory.Length -gt 2097152) {
            return ''
        }
        return [Convert]::ToBase64String($memory.ToArray())
    } finally {
        $stream.Dispose()
        $memory.Dispose()
    }
}

$managerType = [Windows.Media.Control.GlobalSystemMediaTransportControlsSessionManager, Windows.Media.Control, ContentType=WindowsRuntime]
$propertiesType = [Windows.Media.Control.GlobalSystemMediaTransportControlsSessionMediaProperties, Windows.Media.Control, ContentType=WindowsRuntime]
$manager = Await-WinRt ($managerType::RequestAsync()) $managerType
$lastMediaId = ''
$lastAvailable = $true

while ($true) {
    try {
        $session = $manager.GetSessions() |
            Where-Object { $_.SourceAppUserModelId -match 'spotify' } |
            Select-Object -First 1
        if ($null -eq $session) {
            if ($lastAvailable) {
                [pscustomobject]@{ available = $false } | ConvertTo-Json -Compress
                $lastAvailable = $false
            }
            Start-Sleep -Milliseconds 900
            continue
        }

        $properties = Await-WinRt ($session.TryGetMediaPropertiesAsync()) $propertiesType
        $timeline = $session.GetTimelineProperties()
        $playback = $session.GetPlaybackInfo()
        $durationMs = [Math]::Max(0, [long](($timeline.EndTime - $timeline.StartTime).TotalMilliseconds))
        $positionMs = [Math]::Max(0, [long](($timeline.Position - $timeline.StartTime).TotalMilliseconds))
        $mediaId = Get-MediaId $properties.Title $properties.Artist $properties.AlbumTitle $durationMs
        $artwork = ''
        if ($mediaId -ne $lastMediaId) {
            $artwork = Read-Thumbnail $properties.Thumbnail
        }

        [pscustomobject]@{
            available = $true
            mediaId = $mediaId
            title = $properties.Title
            artist = $properties.Artist
            album = $properties.AlbumTitle
            positionMs = $positionMs
            durationMs = $durationMs
            playing = ($playback.PlaybackStatus.ToString() -eq 'Playing')
            timelineUpdatedAtMs = $timeline.LastUpdatedTime.ToUnixTimeMilliseconds()
            artwork = $artwork
        } | ConvertTo-Json -Compress
        $lastMediaId = $mediaId
        $lastAvailable = $true
    } catch {
    }
    Start-Sleep -Milliseconds 900
}

Download file