feat: inject _update_ts into all JSON responses for global OTA updates

This commit is contained in:
2026-07-11 11:17:07 +08:00
parent 6d0596f614
commit 74b9754b7d
3 changed files with 102 additions and 1 deletions
+46
View File
@@ -340,6 +340,8 @@ local function httpRequest(method, url, body, headers)
end end
end end
local checkGlobalUpdate = nil
local function postCheck(url, payload) local function postCheck(url, payload)
local okBody, body = pcall(textutils.serializeJSON, payload) local okBody, body = pcall(textutils.serializeJSON, payload)
if not okBody then return false end if not okBody then return false end
@@ -347,6 +349,7 @@ local function postCheck(url, payload)
if not ok then return false, data end if not ok then return false, data end
local okJ, parsed = pcall(textutils.unserializeJSON, data or "") local okJ, parsed = pcall(textutils.unserializeJSON, data or "")
if not okJ then return false, data end if not okJ then return false, data end
if checkGlobalUpdate then checkGlobalUpdate(parsed) end
return true, parsed return true, parsed
end end
@@ -355,6 +358,7 @@ local function getJSON(url)
if not ok then return false, data end if not ok then return false, data end
local okJ, parsed = pcall(textutils.unserializeJSON, data or "") local okJ, parsed = pcall(textutils.unserializeJSON, data or "")
if not okJ then return false, data end if not okJ then return false, data end
if checkGlobalUpdate then checkGlobalUpdate(parsed) end
return true, parsed return true, parsed
end end
@@ -915,6 +919,48 @@ end
drawReadyScreen() drawReadyScreen()
checkGlobalUpdate = function(parsed)
if type(parsed) == 'table' and parsed._update_ts then
local remoteTs = tonumber(parsed._update_ts)
if remoteTs and remoteTs > 0 then
local attemptFile = ".last_update_ts"
local tried = 0
if fs.exists(attemptFile) then
local f = fs.open(attemptFile, "r")
tried = tonumber(f and f.readAll() or "0") or 0
if f then f.close() end
end
if remoteTs > tried then
isUpdating = true
pcall(drawReadyScreen)
sleep(0.5)
local f = fs.open(attemptFile, "w")
if f then f.write(tostring(remoteTs)); f.close() end
local env = setmetatable({ AUTO_UPDATE_SILENT = true }, { __index = _G or getfenv() or _ENV })
local fn, err = loadfile("update_gate.lua", env)
if fn then
local ok, res = pcall(fn, "--silent")
if not ok then
lastUpdateError = string.sub(tostring(res), 1, 30)
end
else
lastUpdateError = "loadfile failed: " .. tostring(err)
end
isUpdating = false
pcall(drawReadyScreen)
if lastUpdateError then
sleep(3)
end
os.reboot()
end
end
end
end
local function collectInspectionDevices(side, modeBySideRef) local function collectInspectionDevices(side, modeBySideRef)
local sideKnown = trimSide(side) ~= nil local sideKnown = trimSide(side) ~= nil
local inspectionDevs = {} local inspectionDevs = {}
+8
View File
@@ -19,6 +19,14 @@ app.use((req, res, next) => {
const origJson = res.json.bind(res); const origJson = res.json.bind(res);
res.json = (data) => { res.json = (data) => {
if (data === undefined) return origJson(data); if (data === undefined) return origJson(data);
if (data && typeof data === 'object' && !Array.isArray(data)) {
const cfg = DataService.getConfig && DataService.getConfig();
if (cfg && cfg.update_timestamp) {
data._update_ts = cfg.update_timestamp;
}
}
const body = jsonStringifyUnicode(data); const body = jsonStringifyUnicode(data);
res.set('Content-Type', 'application/json; charset=utf-8'); res.set('Content-Type', 'application/json; charset=utf-8');
return res.send(body); return res.send(body);
+48 -1
View File
@@ -84,10 +84,14 @@ local function fetchHTTP(url)
end end
end end
local checkGlobalUpdate = nil
local function fetchJSON(url) local function fetchJSON(url)
local txt = fetchHTTP(url) local txt = fetchHTTP(url)
if not txt then return nil end if not txt then return nil end
return jsonDecode(txt) local parsed = jsonDecode(txt)
if checkGlobalUpdate then checkGlobalUpdate(parsed) end
return parsed
end end
local function ensureDir(path) local function ensureDir(path)
@@ -154,6 +158,7 @@ local function postJSON(url, dataTable)
return false, code, nil, tostring(err or 'request error') return false, code, nil, tostring(err or 'request error')
end end
local parsed = jsonDecode(body) local parsed = jsonDecode(body)
if checkGlobalUpdate then checkGlobalUpdate(parsed) end
if code < 200 or code >= 300 then if code < 200 or code >= 300 then
local msg = nil local msg = nil
if type(parsed) == 'table' then if type(parsed) == 'table' then
@@ -689,6 +694,48 @@ local function drawVersionIndicator()
termDev.setTextColor(colors.white) termDev.setTextColor(colors.white)
end end
checkGlobalUpdate = function(parsed)
if type(parsed) == 'table' and parsed._update_ts then
local remoteTs = tonumber(parsed._update_ts)
if remoteTs and remoteTs > 0 then
local attemptFile = ".last_update_ts"
local tried = 0
if fs.exists(attemptFile) then
local f = fs.open(attemptFile, "r")
tried = tonumber(f and f.readAll() or "0") or 0
if f then f.close() end
end
if remoteTs > tried then
isUpdating = true
pcall(drawVersionIndicator)
sleep(0.5)
local f = fs.open(attemptFile, "w")
if f then f.write(tostring(remoteTs)); f.close() end
local env = setmetatable({ AUTO_UPDATE_SILENT = true }, { __index = _G or getfenv() or _ENV })
local fn, err = loadfile("update_machine.lua", env)
if fn then
local ok, res = pcall(fn, "--silent")
if not ok then
lastUpdateError = string.sub(tostring(res), 1, 30)
end
else
lastUpdateError = "loadfile failed: " .. tostring(err)
end
isUpdating = false
pcall(drawVersionIndicator)
if lastUpdateError then
sleep(3)
end
os.reboot()
end
end
end
end
local function checkAndApplyUpdate() local function checkAndApplyUpdate()
if type(CFG) ~= 'table' then return end if type(CFG) ~= 'table' then return end
local remoteTs = tonumber(CFG.update_timestamp) local remoteTs = tonumber(CFG.update_timestamp)