commit c96834ee4dc18d69063d214f3c10f43e171f65e5 Author: thibaud-lclr Date: Wed Mar 25 20:31:36 2026 +0000 Add main.lua diff --git a/main.lua b/main.lua new file mode 100644 index 0000000..b5c8a59 --- /dev/null +++ b/main.lua @@ -0,0 +1,206 @@ +-- ============================================================ +-- 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() \ No newline at end of file