mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-12 08:21:02 +02:00
Fix Switch OTA parser for GitHub releases/latest JSON.
Scan asset objects by brace bounds instead of an 800-byte window so browser_download_url survives fat uploader blocks; mirror logic in Lua and add realistic API fixtures.
This commit is contained in:
+59
-16
@@ -47,7 +47,43 @@ function SwitchOta.versionFromOtaAsset(name)
|
||||
return name:match(SwitchOta.OTA_ASSET_PATTERN)
|
||||
end
|
||||
|
||||
-- Parse GitHub releases/latest JSON (minimal: tag_name + assets[].name/browser_download_url).
|
||||
local function findJsonObjectStart(jsonText, pos)
|
||||
if type(jsonText) ~= "string" or not pos or pos < 1 then return nil end
|
||||
local depth = 0
|
||||
local p = pos
|
||||
while p >= 1 do
|
||||
local c = jsonText:sub(p, p)
|
||||
if c == "}" then
|
||||
depth = depth + 1
|
||||
elseif c == "{" then
|
||||
if depth == 0 then return p end
|
||||
depth = depth - 1
|
||||
end
|
||||
p = p - 1
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
local function findJsonObjectEnd(jsonText, objectStart)
|
||||
if type(jsonText) ~= "string" or not objectStart then return nil end
|
||||
if jsonText:sub(objectStart, objectStart) ~= "{" then return nil end
|
||||
local depth = 1
|
||||
local p = objectStart + 1
|
||||
local len = #jsonText
|
||||
while p <= len do
|
||||
local c = jsonText:sub(p, p)
|
||||
if c == "{" then
|
||||
depth = depth + 1
|
||||
elseif c == "}" then
|
||||
depth = depth - 1
|
||||
if depth == 0 then return p + 1 end
|
||||
end
|
||||
p = p + 1
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Parse GitHub releases/latest JSON (tag_name + assets[].name/browser_download_url).
|
||||
-- Returns { tag, version, assetName, downloadUrl } or nil + reason.
|
||||
function SwitchOta.parseRelease(jsonText)
|
||||
if type(jsonText) ~= "string" or jsonText == "" then
|
||||
@@ -58,24 +94,31 @@ function SwitchOta.parseRelease(jsonText)
|
||||
local version = tag:match("^v?(%d+%.%d+%.%d+)$")
|
||||
if not version then return nil, "bad_tag" end
|
||||
|
||||
local assetName, downloadUrl
|
||||
for block in jsonText:gmatch("%b{}") do
|
||||
local name = block:match('"name"%s*:%s*"(.-)"')
|
||||
local cursor = 1
|
||||
while true do
|
||||
local nameKeyPos = jsonText:find('"name"', cursor, true)
|
||||
if not nameKeyPos then break end
|
||||
local tail = jsonText:sub(nameKeyPos)
|
||||
local name = tail:match('"name"%s*:%s*"(.-)"')
|
||||
if name and SwitchOta.isOtaAssetName(name) then
|
||||
assetName = name
|
||||
downloadUrl = block:match('"browser_download_url"%s*:%s*"(.-)"')
|
||||
break
|
||||
local assetStart = findJsonObjectStart(jsonText, nameKeyPos)
|
||||
local assetEnd = assetStart and findJsonObjectEnd(jsonText, assetStart)
|
||||
if assetStart and assetEnd and assetEnd > nameKeyPos then
|
||||
local assetBlock = jsonText:sub(assetStart, assetEnd - 1)
|
||||
local downloadUrl = assetBlock:match('"browser_download_url"%s*:%s*"(.-)"')
|
||||
if downloadUrl and downloadUrl ~= "" then
|
||||
return {
|
||||
tag = tag,
|
||||
version = version,
|
||||
assetName = name,
|
||||
downloadUrl = downloadUrl,
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
cursor = nameKeyPos + 6
|
||||
end
|
||||
if not assetName then return nil, "missing_ota_asset" end
|
||||
if not downloadUrl or downloadUrl == "" then return nil, "missing_download_url" end
|
||||
|
||||
return {
|
||||
tag = tag,
|
||||
version = version,
|
||||
assetName = assetName,
|
||||
downloadUrl = downloadUrl,
|
||||
}
|
||||
return nil, "missing_ota_asset"
|
||||
end
|
||||
|
||||
-- Decide check outcome given installed version and parsed release.
|
||||
|
||||
Reference in New Issue
Block a user