local QBCore = exports['qb-core']:GetCoreObject() local currentArtifact = GetConvar('version', 'unknown') local updateInProgress = false -- Hilfsfunktionen local function hasPermission(source) local Player = QBCore.Functions.GetPlayer(source) if not Player then return false end for _, group in pairs(Config.AllowedGroups) do if QBCore.Functions.HasPermission(source, group) then return true end end return false end local function sendDiscordLog(message) if not Config.DiscordWebhook.enabled then return end PerformHttpRequest(Config.DiscordWebhook.url, function(err, text, headers) end, 'POST', json.encode({ username = Config.DiscordWebhook.botName, content = message }), { ['Content-Type'] = 'application/json' }) end local function notifyAdmins(message) local players = QBCore.Functions.GetPlayers() for _, playerId in pairs(players) do if hasPermission(playerId) then TriggerClientEvent('QBCore:Notify', playerId, message, 'primary', 10000) end end end local function getCurrentArtifact() -- Versuche aktuelle Version aus verschiedenen Quellen zu ermitteln local version = GetConvar('version', '') if version and version ~= '' then local artifact = string.match(version, 'v1%.0%.0%.(%d+)') if artifact then return tonumber(artifact) end end return nil end local function checkForUpdates() if updateInProgress then return end print('[FX-Updater] Prüfe auf Updates...') PerformHttpRequest('https://runtime.fivem.net/artifacts/fivem/build_proot_linux/master/', function(errorCode, resultData, resultHeaders) if errorCode == 200 then -- Parse die neueste Artifact-Nummer aus der HTML-Antwort local latestArtifact = nil for artifact in string.gmatch(resultData, '(%d+)%-[a-f0-9]+/') do local num = tonumber(artifact) if not latestArtifact or num > latestArtifact then latestArtifact = num end end if latestArtifact and latestArtifact >= Config.RequiredArtifact then local currentArt = getCurrentArtifact() if not currentArt or latestArtifact > currentArt then local message = string.format(Config.Notifications.updateAvailable, latestArtifact) print('[FX-Updater] ' .. message) notifyAdmins(message) sendDiscordLog('🔄 ' .. message) if Config.AutoUpdate then Citizen.SetTimeout(5000, function() performUpdate(latestArtifact) end) end end end else print('[FX-Updater] Fehler beim Prüfen auf Updates: ' .. errorCode) end end, 'GET', '', {}) end local function createBackup() if not Config.BackupEnabled then return true end local timestamp = os.date('%Y%m%d_%H%M%S') local backupDir = Config.BackupPath .. 'backup_' .. timestamp -- Erstelle Backup-Verzeichnis os.execute('mkdir -p "' .. backupDir .. '"') -- Sichere wichtige Dateien os.execute('cp server.cfg "' .. backupDir .. '/"') os.execute('cp -r resources "' .. backupDir .. '/"') os.execute('cp -r server-data "' .. backupDir .. '/" 2>/dev/null || true') print('[FX-Updater] Backup erstellt: ' .. backupDir) return true end function performUpdate(targetArtifact) if updateInProgress then return end updateInProgress = true print('[FX-Updater] Starte Update auf Artifact ' .. targetArtifact) notifyAdmins(Config.Notifications.updateStarted) sendDiscordLog('🔄 Update gestartet auf Artifact ' .. targetArtifact) -- Warnung an alle Spieler TriggerClientEvent('chatMessage', -1, '[SERVER]', {255, 165, 0}, 'Server wird in 30 Sekunden für ein Update neu gestartet!') Citizen.SetTimeout(30000, function() -- Backup erstellen if not createBackup() then print('[FX-Updater] Backup fehlgeschlagen!') updateInProgress = false return end -- Download-URL erstellen local downloadUrl = string.format( 'https://runtime.fivem.net/artifacts/fivem/build_proot_linux/master/%d-*/fx.tar.xz', targetArtifact ) -- Update-Script erstellen und ausführen local updateScript = [[ #!/bin/bash echo "FXServer Update gestartet..." # Download neue Version wget -O fx-new.tar.xz "]] .. downloadUrl .. [[" if [ $? -eq 0 ]; then # Entpacken mkdir -p temp-update cd temp-update tar -xf ../fx-new.tar.xz cd .. # Installation cp temp-update/run.sh ./ cp -r temp-update/alpine ./ chmod +x run.sh chmod +x alpine/opt/cfx-server/FXServer # Aufräumen rm -rf temp-update fx-new.tar.xz echo "Update abgeschlossen, starte Server..." # Server neu starten ./run.sh +exec server.cfg & else echo "Download fehlgeschlagen!" exit 1 fi ]] -- Script in Datei schreiben local file = io.open('update_fx.sh', 'w') if file then file:write(updateScript) file:close() -- Script ausführbar machen und ausführen os.execute('chmod +x update_fx.sh') -- Server beenden und Update starten print('[FX-Updater] Server wird beendet für Update...') notifyAdmins(Config.Notifications.updateCompleted) sendDiscordLog('✅ Update wird durchgeführt, Server startet neu...') Citizen.SetTimeout(2000, function() os.execute('./update_fx.sh') os.exit() -- Server beenden end) else print('[FX-Updater] Konnte Update-Script nicht erstellen!') updateInProgress = false end end) end -- Events RegisterNetEvent('fx-updater:checkUpdate', function() local src = source if not hasPermission(src) then TriggerClientEvent('QBCore:Notify', src, Config.Notifications.noPermission, 'error') return end checkForUpdates() end) RegisterNetEvent('fx-updater:forceUpdate', function(targetArtifact) local src = source if not hasPermission(src) then TriggerClientEvent('QBCore:Notify', src, Config.Notifications.noPermission, 'error') return end targetArtifact = targetArtifact or Config.RequiredArtifact performUpdate(targetArtifact) end) RegisterNetEvent('fx-updater:getVersion', function() local src = source if not hasPermission(src) then TriggerClientEvent('QBCore:Notify', src, Config.Notifications.noPermission, 'error') return end local current = getCurrentArtifact() or 'Unbekannt' local message = string.format(Config.Notifications.currentVersion, current) TriggerClientEvent('QBCore:Notify', src, message, 'primary') end) -- Commands QBCore.Commands.Add('fxupdate', 'Prüfe auf FXServer Updates', {}, false, function(source, args) if not hasPermission(source) then TriggerClientEvent('QBCore:Notify', source, Config.Notifications.noPermission, 'error') return end TriggerEvent('fx-updater:checkUpdate') end, Config.AllowedGroups) QBCore.Commands.Add('fxforceupdate', 'Erzwinge FXServer Update', {{name = 'artifact', help = 'Artifact Nummer (optional)'}}, false, function(source, args) if not hasPermission(source) then TriggerClientEvent('QBCore:Notify', source, Config.Notifications.noPermission, 'error') return end local targetArtifact = args[1] and tonumber(args[1]) or Config.RequiredArtifact TriggerEvent('fx-updater:forceUpdate', targetArtifact) end, Config.AllowedGroups) QBCore.Commands.Add('fxversion', 'Zeige aktuelle FXServer Version', {}, false, function(source, args) if not hasPermission(source) then TriggerClientEvent('QBCore:Notify', source, Config.Notifications.noPermission, 'error') return end TriggerEvent('fx-updater:getVersion') end, Config.AllowedGroups) -- Auto-Check Timer if Config.CheckInterval > 0 then Citizen.CreateThread(function() while true do Citizen.Wait(Config.CheckInterval) checkForUpdates() end end) end -- Beim Server-Start prüfen Citizen.CreateThread(function() Citizen.Wait(10000) -- Warte 10 Sekunden nach Server-Start checkForUpdates() end) print('[FX-Updater] Resource gestartet!')