mirror of
https://github.com/SpotX-Official/SpotX.git
synced 2026-06-14 03:16:33 +10:00
@@ -1613,6 +1613,92 @@ function injection {
|
||||
}
|
||||
|
||||
|
||||
function Extract-WebpackModules {
|
||||
param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$InputFile
|
||||
)
|
||||
|
||||
$scriptStart = Get-Date
|
||||
Write-Debug "=== Script execution started ==="
|
||||
Write-Debug "Input file: $InputFile"
|
||||
|
||||
function Encode-UTF16LE {
|
||||
param([byte[]]$Bytes)
|
||||
$str = [System.Text.Encoding]::UTF8.GetString($Bytes)
|
||||
[System.Text.Encoding]::Unicode.GetBytes($str)
|
||||
}
|
||||
|
||||
$StartMarker = [System.Text.Encoding]::UTF8.GetBytes("var __webpack_modules__={")
|
||||
$EndMarker = [System.Text.Encoding]::UTF8.GetBytes("//# sourceMappingURL=xpui-modules.js.map")
|
||||
|
||||
[byte[]]$fileContent = [System.IO.File]::ReadAllBytes($InputFile)
|
||||
|
||||
$isUTF16LE = $false
|
||||
if ($fileContent.Length -ge 2 -and $fileContent[0] -eq 0xFF -and $fileContent[1] -eq 0xFE) {
|
||||
$isUTF16LE = $true
|
||||
}
|
||||
elseif ($fileContent.Length -gt 100 -and $fileContent[1] -eq 0x00) {
|
||||
$isUTF16LE = $true
|
||||
}
|
||||
if (-not $isUTF16LE) {
|
||||
Write-Error "File is not in UTF-16LE format: $InputFile"
|
||||
exit 1
|
||||
}
|
||||
|
||||
$searchStartMarker = Encode-UTF16LE -Bytes $StartMarker
|
||||
$searchEndMarker = Encode-UTF16LE -Bytes $EndMarker
|
||||
|
||||
function IndexOfBytes($haystack, $needle, [int]$startIndex = 0) {
|
||||
if ($startIndex -lt 0) { $startIndex = 0 }
|
||||
$haystackLength = $haystack.Length
|
||||
$needleLength = $needle.Length
|
||||
$searchLimit = $haystackLength - $needleLength
|
||||
if ($searchLimit -lt $startIndex) { return -1 }
|
||||
$firstNeedleByte = $needle[0]
|
||||
for ($i = $startIndex; $i -le $searchLimit; $i++) {
|
||||
if ($haystack[$i] -eq $firstNeedleByte) {
|
||||
$found = $true
|
||||
for ($j = 1; $j -lt $needleLength; $j++) {
|
||||
if ($haystack[$i + $j] -ne $needle[$j]) {
|
||||
$found = $false
|
||||
break
|
||||
}
|
||||
}
|
||||
if ($found) { return $i }
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
$startIdx = IndexOfBytes $fileContent $searchStartMarker 2
|
||||
if ($startIdx -eq -1) {
|
||||
Write-Error "Start marker not found"
|
||||
exit 1
|
||||
}
|
||||
Write-Debug "Start marker found at index $startIdx"
|
||||
|
||||
$endMarkerSearchOffset = $startIdx + $searchStartMarker.Length
|
||||
$endIdx = IndexOfBytes $fileContent $searchEndMarker $endMarkerSearchOffset
|
||||
if ($endIdx -eq -1) {
|
||||
Write-Error "End marker not found after index $endMarkerSearchOffset"
|
||||
exit 1
|
||||
}
|
||||
Write-Debug "End marker found at absolute index $endIdx"
|
||||
|
||||
$endDataIdx = $endIdx + $searchEndMarker.Length
|
||||
$length = $endDataIdx - $startIdx
|
||||
|
||||
Write-Debug "Decoding data from UTF-16LE..."
|
||||
$decodedString = [System.Text.Encoding]::Unicode.GetString($fileContent, $startIdx, $length)
|
||||
|
||||
$scriptEnd = Get-Date
|
||||
$duration = [math]::Round(($scriptEnd - $scriptStart).TotalSeconds, 1)
|
||||
Write-Debug "=== Execution completed in $duration seconds ==="
|
||||
|
||||
return $decodedString
|
||||
}
|
||||
|
||||
|
||||
Write-Host ($lang).ModSpoti`n
|
||||
|
||||
@@ -1663,13 +1749,85 @@ if (!($test_js) -and !($test_spa)) {
|
||||
Exit
|
||||
}
|
||||
|
||||
If ($test_spa) {
|
||||
if ($test_spa) {
|
||||
|
||||
Add-Type -Assembly 'System.IO.Compression.FileSystem'
|
||||
|
||||
# Check for the presence of xpui.js in the xpui.spa archive
|
||||
try {
|
||||
$archive_spa = [System.IO.Compression.ZipFile]::OpenRead($xpui_spa_patch)
|
||||
$xpuiJsEntry = $archive_spa.GetEntry('xpui.js')
|
||||
$xpuiSnapshotEntry = $archive_spa.GetEntry('xpui-snapshot.js')
|
||||
if (($null -eq $xpuiJsEntry) -and ($null -ne $xpuiSnapshotEntry)) {
|
||||
|
||||
$snapshot_x64 = Join-Path $spotifyDirectory 'v8_context_snapshot.bin'
|
||||
$snapshot_arm64 = Join-Path $spotifyDirectory 'v8_context_snapshot.arm64.bin'
|
||||
|
||||
$v8_snapshot = switch ($true) {
|
||||
{ Test-Path $snapshot_x64 } { $snapshot_x64; break }
|
||||
{ Test-Path $snapshot_arm64 } { $snapshot_arm64; break }
|
||||
default { $null }
|
||||
}
|
||||
if ($v8_snapshot) {
|
||||
$modules = Extract-WebpackModules -InputFile $v8_snapshot
|
||||
|
||||
function Update-ZipEntry {
|
||||
param (
|
||||
[Parameter(Mandatory)]
|
||||
$archive,
|
||||
[Parameter(Mandatory)]
|
||||
[string]$entryName,
|
||||
[string]$newEntryName = $null,
|
||||
[string]$prepend = $null,
|
||||
[scriptblock]$contentTransform = $null
|
||||
)
|
||||
$entry = $archive.GetEntry($entryName)
|
||||
if ($entry) {
|
||||
$tmpFile = [System.IO.Path]::GetTempFileName()
|
||||
$reader = New-Object IO.StreamReader($entry.Open())
|
||||
$content = $reader.ReadToEnd()
|
||||
$reader.Close()
|
||||
$entry.Delete()
|
||||
if ($prepend) { $content = "$prepend`n$content" }
|
||||
if ($contentTransform) { $content = & $contentTransform $content }
|
||||
[System.IO.File]::WriteAllText($tmpFile, $content)
|
||||
[System.IO.Compression.ZipFileExtensions]::CreateEntryFromFile($archive, $tmpFile, $(if ($newEntryName) { $newEntryName } else { $entryName })) | Out-Null
|
||||
Remove-Item $tmpFile
|
||||
}
|
||||
}
|
||||
|
||||
$firstLine = ($modules -split "`r?`n")[0]
|
||||
|
||||
$archive_spa.Dispose()
|
||||
$archive_spa = [System.IO.Compression.ZipFile]::Open($xpui_spa_patch, [System.IO.Compression.ZipArchiveMode]::Update)
|
||||
|
||||
Update-ZipEntry -archive $archive_spa -entryName 'xpui-snapshot.js' -prepend $firstLine
|
||||
Update-ZipEntry -archive $archive_spa -entryName 'xpui-snapshot.js' -newEntryName 'xpui.js'
|
||||
Update-ZipEntry -archive $archive_spa -entryName 'xpui-snapshot.css' -newEntryName 'xpui.css'
|
||||
Update-ZipEntry -archive $archive_spa -entryName 'index.html' -contentTransform {
|
||||
param($c)
|
||||
$c -replace 'xpui-snapshot.js', 'xpui.js' -replace 'xpui-snapshot.css', 'xpui.css'
|
||||
}
|
||||
}
|
||||
else {
|
||||
Write-Warning "v8_context_snapshot file not found"
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Write-Warning "Error: $($_.Exception.Message)"
|
||||
}
|
||||
finally {
|
||||
if ($null -ne $archive_spa) {
|
||||
$archive_spa.Dispose()
|
||||
}
|
||||
}
|
||||
|
||||
$bak_spa = Join-Path (Join-Path $env:APPDATA 'Spotify\Apps') 'xpui.bak'
|
||||
$test_bak_spa = Test-Path -Path $bak_spa
|
||||
|
||||
# Make a backup copy of xpui.spa if it is original
|
||||
Add-Type -Assembly 'System.IO.Compression.FileSystem'
|
||||
$zip = [System.IO.Compression.ZipFile]::Open($xpui_spa_patch, 'update')
|
||||
$entry = $zip.GetEntry('xpui.js')
|
||||
$reader = New-Object System.IO.StreamReader($entry.Open())
|
||||
@@ -1771,7 +1929,7 @@ If ($test_spa) {
|
||||
|
||||
if ([version]$offline -ge [version]"1.2.28.581" -and [version]$offline -le [version]"1.2.57.463") {
|
||||
|
||||
if ([version]$offline -ge [version]"1.2.45.454") { $typefile = "xpui.js"}
|
||||
if ([version]$offline -ge [version]"1.2.45.454") { $typefile = "xpui.js" }
|
||||
|
||||
else { $typefile = "xpui-routes-search.js" }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user