206 lines
5.8 KiB
Lua
206 lines
5.8 KiB
Lua
-- ============================================================
|
||
-- startup.lua – Auto-updater pour repo Gitea privé
|
||
-- ============================================================
|
||
|
||
-- ============================================================
|
||
-- Chargement de la configuration
|
||
-- ============================================================
|
||
|
||
local function loadConfig(path)
|
||
if not fs.exists(path) then
|
||
error("[Config] Fichier '" .. path .. "' introuvable !")
|
||
end
|
||
|
||
local config = {}
|
||
local f = fs.open(path, "r")
|
||
local line = f.readLine()
|
||
while line do
|
||
-- Ignorer les lignes vides et les commentaires (#)
|
||
if line ~= "" and not line:match("^%s*#") then
|
||
local key, value = line:match("^([^=]+)=(.+)$")
|
||
if key and value then
|
||
config[trim(key)] = trim(value)
|
||
end
|
||
end
|
||
line = f.readLine()
|
||
end
|
||
f.close()
|
||
return config
|
||
end
|
||
|
||
local function validateConfig(cfg)
|
||
local required = { "gitea_base", "user", "repo", "branch", "program", "remote_ver", "check_interval" }
|
||
for _, key in ipairs(required) do
|
||
if not cfg[key] then
|
||
error("[Config] Clé manquante dans config.cfg : '" .. key .. "'")
|
||
end
|
||
end
|
||
cfg.check_interval = tonumber(cfg.check_interval)
|
||
if not cfg.check_interval then
|
||
error("[Config] 'check_interval' doit être un nombre.")
|
||
end
|
||
end
|
||
|
||
-- ============================================================
|
||
-- Utilitaires fichiers
|
||
-- ============================================================
|
||
|
||
local function readFile(path)
|
||
if not fs.exists(path) then return nil end
|
||
local f = fs.open(path, "r")
|
||
local content = f.readAll()
|
||
f.close()
|
||
return content
|
||
end
|
||
|
||
local function writeFile(path, content)
|
||
local f = fs.open(path, "w")
|
||
f.write(content)
|
||
f.close()
|
||
end
|
||
|
||
function trim(s)
|
||
return s:gsub("%s+", "")
|
||
end
|
||
|
||
-- ============================================================
|
||
-- Gestion du token
|
||
-- ============================================================
|
||
|
||
local function loadToken(path)
|
||
local token = readFile(path or ".token")
|
||
if not token then
|
||
error("[Updater] Fichier '.token' introuvable !\n"
|
||
.. "Crée-le avec : echo 'ton_token' > .token")
|
||
end
|
||
return trim(token)
|
||
end
|
||
|
||
-- ============================================================
|
||
-- HTTP avec auth Gitea
|
||
-- ============================================================
|
||
|
||
local function buildRawUrl(cfg, filepath)
|
||
return cfg.gitea_base
|
||
.. "/" .. cfg.user
|
||
.. "/" .. cfg.repo
|
||
.. "/raw/branch/" .. cfg.branch
|
||
.. "/" .. filepath
|
||
end
|
||
|
||
local function fetchWithToken(url, token)
|
||
local ok, res = pcall(function()
|
||
return http.get(url, {
|
||
["Authorization"] = "token " .. token,
|
||
["Accept"] = "application/json",
|
||
})
|
||
end)
|
||
|
||
if not ok or not res then
|
||
return nil, "Requête échouée vers : " .. url
|
||
end
|
||
|
||
local code = res.getResponseCode()
|
||
if code == 401 then
|
||
res.close()
|
||
return nil, "Token invalide ou expiré (401)"
|
||
elseif code == 404 then
|
||
res.close()
|
||
return nil, "Fichier introuvable sur le repo (404)"
|
||
elseif code ~= 200 then
|
||
res.close()
|
||
return nil, "Erreur HTTP " .. code
|
||
end
|
||
|
||
local content = res.readAll()
|
||
res.close()
|
||
return content, nil
|
||
end
|
||
|
||
-- ============================================================
|
||
-- Logique de mise à jour
|
||
-- ============================================================
|
||
|
||
local function checkAndUpdate(cfg, token)
|
||
print("[Updater] Vérification des mises à jour...")
|
||
|
||
local remoteVersion, err = fetchWithToken(buildRawUrl(cfg, cfg.remote_ver), token)
|
||
if not remoteVersion then
|
||
print("[Updater] " .. err)
|
||
return false
|
||
end
|
||
remoteVersion = trim(remoteVersion)
|
||
|
||
local localVersion = readFile(".version")
|
||
if localVersion then localVersion = trim(localVersion) end
|
||
|
||
if remoteVersion == localVersion then
|
||
print("[Updater] Déjà à jour (v" .. remoteVersion .. ").")
|
||
return false
|
||
end
|
||
|
||
local prevVersion = localVersion or "aucune"
|
||
print("[Updater] Mise à jour : v" .. prevVersion .. " → v" .. remoteVersion)
|
||
|
||
local newProgram, dlErr = fetchWithToken(buildRawUrl(cfg, cfg.program), token)
|
||
if not newProgram then
|
||
print("[Updater] Échec du téléchargement : " .. dlErr)
|
||
return false
|
||
end
|
||
|
||
writeFile(cfg.program, newProgram)
|
||
writeFile(".version", remoteVersion)
|
||
print("[Updater] Mise à jour appliquée (v" .. remoteVersion .. ").")
|
||
return true
|
||
end
|
||
|
||
-- ============================================================
|
||
-- Programme principal
|
||
-- ============================================================
|
||
|
||
local function runProgram(cfg)
|
||
print("[Updater] Lancement de " .. cfg.program .. "...")
|
||
shell.run(cfg.program)
|
||
print("[Updater] Le programme s'est arrêté.")
|
||
end
|
||
|
||
local function watcherLoop(cfg, token)
|
||
while true do
|
||
sleep(cfg.check_interval)
|
||
local updated = checkAndUpdate(cfg, token)
|
||
if updated then
|
||
print("[Updater] Redémarrage dans 2 secondes...")
|
||
sleep(2)
|
||
return
|
||
end
|
||
end
|
||
end
|
||
|
||
local function main()
|
||
print("=== Auto-updater Gitea ===")
|
||
|
||
local cfg = loadConfig("config.cfg")
|
||
validateConfig(cfg)
|
||
print("[Config] Configuration chargée.")
|
||
|
||
local token = loadToken(".token")
|
||
print("[Updater] Token chargé.")
|
||
|
||
checkAndUpdate(cfg, token)
|
||
|
||
if not fs.exists(cfg.program) then
|
||
print("[Updater] Aucun programme disponible. Abandon.")
|
||
return
|
||
end
|
||
|
||
parallel.waitForAny(
|
||
function() runProgram(cfg) end,
|
||
function() watcherLoop(cfg, token) end
|
||
)
|
||
|
||
print("[Updater] Redémarrage du système...")
|
||
sleep(1)
|
||
os.reboot()
|
||
end
|
||
|
||
main() |