Skip to content
This repository has been archived by the owner on Nov 13, 2024. It is now read-only.

Commit

Permalink
2.4.0 Release
Browse files Browse the repository at this point in the history
Release/2.4.0
  • Loading branch information
nathanctech authored Jan 27, 2021
2 parents d782cc5 + 53c6ae5 commit 03cf416
Show file tree
Hide file tree
Showing 20 changed files with 175 additions and 95 deletions.
24 changes: 14 additions & 10 deletions sonoran_updatehelper/s.lua
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,21 @@ CreateThread(function()
file = io.open(GetResourcePath(GetCurrentResourceName()).."/run.lock", "a+")
io.input(file)
line = io.read()
if line ~= "1" then
file:close()
os.remove(GetResourcePath(GetCurrentResourceName()).."/run.lock")
print("sonoran_updatehelper is for internal use and should not be started as a resource.")
return
end
file:close()
ExecuteCommand("refresh")
Wait(1000)
for k, v in pairs(ManagedResources) do
ExecuteCommand("restart "..v)
if line == "core" or line == "plugin" then
ExecuteCommand("refresh")
Wait(1000)
if line == "core" then
for k, v in pairs(ManagedResources) do
ExecuteCommand("restart "..v)
Wait(1000)
end
elseif line == "plugin" then
print("Restarting sonorancad resource for plugin updates...")
ExecuteCommand("restart sonorancad")
end
else
os.remove(GetResourcePath(GetCurrentResourceName()).."/run.lock")
print("sonoran_updatehelper is for internal use and should not be started as a resource.")
end
end)
1 change: 0 additions & 1 deletion sonorancad/config.CHANGEME.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
"mode": "production",
"postTime": 5000,
"serverId": "1",
"serverType": "standalone",
"primaryIdentifier": "steam",
"apiSendEnabled": true,
"debugMode": false,
Expand Down
14 changes: 9 additions & 5 deletions sonorancad/core/commands.lua
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
update - attempt to auto-update
]]

registerApiType("UPLOAD_LOGS", "support")

function dumpInfo()
local version = GetResourceMetadata(GetCurrentResourceName(), "version", 0)
local pluginList, loadedPlugins, disabledPlugins = GetPluginLists()
Expand Down Expand Up @@ -98,8 +100,6 @@ Console Buffer
end
end)
end

registerApiType("UPLOAD_LOGS", "support")
RegisterCommand("sonoran", function(source, args, rawCommand)
if source ~= 0 then
print("Console only command")
Expand All @@ -116,7 +116,8 @@ SonoranCAD Help
info - dump version info, configuration
support - dump useful data for support staff
plugin <name> - show info about a plugin (config)
update - Run auto-updater
update - Run core updater
pluginupdate - Run plugin updater
]])
elseif args[1] == "debugmode" then
Config.debugMode = not Config.debugMode
Expand All @@ -125,8 +126,6 @@ SonoranCAD Help
print(dumpInfo())
elseif args[1] == "support" and args[2] ~= nil then
sendSupportLogs(args[2])
elseif args[1] == "verify" then --verify - run hash checks to confirm all files are untampered
return
elseif args[1] == "plugin" and args[2] then
if Config.plugins[args[2]] then
print(dumpPlugin(args[2]))
Expand All @@ -142,6 +141,11 @@ SonoranCAD Help
f:write(GetConsoleBuffer())
f:close()
infoLog("Wrote buffer to "..savePath)
elseif args[1] == "pluginupdate" then
infoLog("Scanning for plugin updates...")
for k, v in pairs(Config.plugins) do
CheckForPluginUpdate(k)
end
else
print("Missing command. Try \"sonoran help\" for help.")
end
Expand Down
3 changes: 0 additions & 3 deletions sonorancad/core/configuration.lua
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ Config = {
apiUrl = nil,
postTime = nil,
serverId = nil,
serverType = nil,
primaryIdentifier = nil,
apiSendEnabled = nil,
debugMode = nil,
Expand Down Expand Up @@ -69,7 +68,6 @@ AddEventHandler("SonoranCAD::core::getConfig", function()
communityID = Config.communityID,
apiKey = Config.apiKey,
postTime = Config.postTime,
serverType = Config.serverType,
apiSendEnabled = Config.apiSendEnabled
})
TriggerEvent("SonoranCAD::core:configData", config)
Expand All @@ -81,7 +79,6 @@ AddEventHandler("SonoranCAD::core:sendClientConfig", function()
communityID = Config.communityID,
postTime = Config.postTime,
serverId = Config.serverId,
serverType = Config.serverType,
primaryIdentifier = Config.primaryIdentifier,
apiSendEnabled = Config.apiSendEnabled,
debugMode = Config.debugMode,
Expand Down
3 changes: 1 addition & 2 deletions sonorancad/core/http.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@ exports('HandleHttpRequest', (dest, callback, method, data, headers) => {
headers: headers
}
if (method == "POST") {
options.headers['Content-Type'] = 'application/json',
options.headers['Content-Length'] = byteCount(data)
options.headers['Content-Type'] = 'application/json'
}
else if (method != "GET") {
console.error("Invalid request. Only GET/POST supported. Method: " + method);
Expand Down
127 changes: 96 additions & 31 deletions sonorancad/core/plugin_loader.lua
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
Provides logic for checking loaded plugins after startup
]]

local PluginsWereUpdated = false

local function LoadVersionFile(pluginName)
local f = LoadResourceFile(GetCurrentResourceName(), ("plugins/%s/%s/version_%s.json"):format(pluginName, pluginName, pluginName))
if f then
Expand All @@ -20,7 +22,86 @@ local function LoadVersionFile(pluginName)
end
end

local NagMessages = {}
local function doRestart()
CreateThread(function()
if not Config.allowUpdateWithPlayers and GetNumPlayerIndices() > 0 then
infoLog("Delaying auto-update until server is empty.")
return
end
warnLog("Auto-restarting...")
local f = assert(io.open(GetResourcePath("sonoran_updatehelper").."/run.lock", "w+"))
f:write("plugin")
f:close()
Wait(5000)
ExecuteCommand("ensure sonoran_updatehelper")
end)
end

local function downloadPlugin(name, url)
local releaseUrl = ("%s/archive/latest.zip"):format(url)
PerformHttpRequest(releaseUrl, function(code, data, headers)
if code == 200 then
local savePath = GetResourcePath(GetCurrentResourceName()).."/pluginupdates/"..name..".zip"
local f = assert(io.open(savePath, 'wb'))
f:write(data)
f:close()
local unzipPath = GetResourcePath(GetCurrentResourceName()).."/plugins/"..name.."/"
debugLog("Unzipping to: "..unzipPath)
exports[GetCurrentResourceName()]:UnzipFolder(savePath, name, unzipPath)
os.remove(savePath)
infoLog(("Plugin %s successfully downloaded."):format(name))
PluginsWereUpdated = true
else
errorLog(("Failed to download from %s: %s %s"):format(realUrl, code, data))
end
end, "GET")
end

function CheckForPluginUpdate(name, checkUrl)
local plugin = Config.plugins[name]
if plugin == nil then
errorLog(("Plugin %s not found."):format(name))
return
elseif plugin.check_url == nil then
warnLog(("Plugin %s does not have check_url set. Please update it manually."):format(name))
return
end
PerformHttpRequestS(plugin.check_url, function(code, data, headers)
if code == 200 then
local remote = json.decode(data)
if remote == nil then
warnLog(("Failed to get a valid response for %s. Skipping."):format(k))
debugLog(("Raw output for %s: %s"):format(k, data))
else
Config.plugins[name].latestVersion = remote.version
Config.plugins[name].download_url = remote.download_url
local latestVersion = string.gsub(remote.version, "%.","")
local localVersion = string.gsub(plugin.version, "%.", "")
if localVersion < latestVersion then
warnLog(("Plugin Updater: %s has an available update! %s -> %s"):format(name, plugin.version, remote.version))
if remote.download_url ~= nil then
if Config.allowAutoUpdate then
infoLog(("Attempting to automatically update %s..."):format(name))
downloadPlugin(name, remote.download_url)
PluginsWereUpdated = true
else
warnLog("Automatic updates are disabled. Please update this plugin ASAP.")
end
end
end
if remote.configVersion ~= nil then
local myversion = plugin.configVersion ~= nil and plugin.configVersion or "0.0"
if remote.configVersion ~= plugin.configVersion then
infoLog(("Plugin Updater: %s has a new configuration version. You should look at the template configuration file (CHANGEMEconfig_%s.lua) and update your configuration."):format(name, name))
end
end
end

else
errorLog(("Failed to check plugin updates for %s: %s %s"):format(k, code, data))
end
end, "GET")
end

CreateThread(function()
Wait(1)
Expand All @@ -41,33 +122,10 @@ CreateThread(function()
local version = json.decode(f)
debugLog(("Loaded plugin %s (%s)"):format(k, version.version))
Config.plugins[k].version = version.version
if version.check_url ~= "" then
PerformHttpRequestS(version.check_url, function(code, data, headers)
if code == 200 then
local remote = json.decode(data)
if remote == nil then
warnLog(("Failed to get a valid response for %s. Skipping."):format(k))
debugLog(("Raw output for %s: %s"):format(k, data))
else
Config.plugins[k].latestVersion = remote.version
if remote.version ~= version.version then
local nag = ("Plugin Updater: %s has an available update! %s -> %s - Download at: %s"):format(k, version.version, remote.version, remote.download_url)
warnLog(nag)
table.insert(NagMessages, nag)
end
if remote.configVersion ~= nil then
local myversion = version.configVersion ~= nil and version.configVersion or "0.0"
if remote.configVersion ~= version.configVersion then
infoLog(("Plugin Updater: %s has a new configuration version. You should look at the template configuration file (CHANGEMEconfig_%s.lua) and update your configuration."):format(k, k))
end
end
end

else
errorLog(("Failed to check plugin updates for %s: %s %s"):format(k, code, data))
end
end, "GET")
end
Config.plugins[k].check_url = version.check_url
Config.plugins[k].download_url = version.download_url
Config.plugins[k].configVersion = version.configVersion or "1.0"
CheckForPluginUpdate(k)
if version.minCoreVersion ~= nil then
local coreVersion = GetResourceMetadata(GetCurrentResourceName(), "version", 0)
local minVersion = string.gsub(version.minCoreVersion, "%.","")
Expand Down Expand Up @@ -98,13 +156,20 @@ CreateThread(function()
if #disabledPlugins > 0 then
warnLog(("Disabled Plugins: %s"):format(table.concat(disabledPlugins, ", ")))
end
if PluginsWereUpdated then
doRestart()
end
end)

CreateThread(function()
while true do
Wait(1000*60*60)
for k, v in ipairs(NagMessages) do
warnLog(v)
Wait(10000)
if PluginsWereUpdated then
doRestart()
end
Wait(60000*10)
for k, v in pairs(Config.plugins) do
CheckForPluginUpdate(k)
end
end
end)
13 changes: 8 additions & 5 deletions sonorancad/core/server.lua
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ function getApiUrl()
if ApiUrls[Config.mode] ~= nil then
return ApiUrls[Config.mode]
else
Config.critError = true
assert(false, "Invalid mode. Valid values are production, development")
end
end
Expand All @@ -26,13 +27,14 @@ CreateThread(function()
ApiVersion = tonumber(string.sub(result, 1, 1))
if ApiVersion < 2 then
errorLog("ERROR: Your community cannot use any plugins requiring the API. Please purchase a subscription of Standard or higher.")
assert(false)
Config.critError = true
end
debugLog(("Set version %s from response %s"):format(ApiVersion, result))
infoLog(("Loaded community ID %s with API URL: %s"):format(Config.communityID, Config.apiUrl))
end)
if Config.primaryIdentifier == "steam" and GetConvar("steam_webapiKey", "none") == "none" then
errorLog("You have set SonoranCAD to Steam mode, but have not configured a Steam Web API key. Please see FXServer documentation. SonoranCAD will not function in Steam mode without this set.")
Config.critError = true
end
end)

Expand Down Expand Up @@ -88,13 +90,15 @@ function performApiRequest(postData, type, cb)
if ApiEndpoints[type] ~= nil then
endpoint = ApiEndpoints[type]
end
local url = ""
if endpoint == "support" then
apiUrl = "https://api.sonoransoftware.com/"
url = apiUrl..tostring(endpoint).."/"
else
apiUrl = getApiUrl()
url = apiUrl..tostring(endpoint).."/"..tostring(type:lower())
end
assert(type ~= nil, "No type specified, invalid request.")
local url = apiUrl..tostring(endpoint).."/"..tostring(type:lower())
if Config.critError then
return
elseif not Config.apiSendEnabled then
Expand All @@ -106,7 +110,7 @@ function performApiRequest(postData, type, cb)
debugLog(("type %s called with post data %s to url %s"):format(type, json.encode(payload), url))
if statusCode == 200 and res ~= nil then
debugLog("result: "..tostring(res))
if res == "Sonoran CAD: Backend Service Reached" then
if res == "Sonoran CAD: Backend Service Reached" or res == "Backend Service Reached" then
errorLog(("API ERROR: Invalid endpoint (URL: %s). Ensure you're using a valid endpoint."):format(url))
else
cb(res, true)
Expand Down Expand Up @@ -159,7 +163,6 @@ CreateThread(function()
serverId = Config.serverId,
plugins = plugins
}
debugLog(("Heartbeat: %s"):format(json.encode(payload)))
performApiRequest(payload, "HEARTBEAT", function() end)
Wait(1000*60*60)
end
Expand All @@ -176,7 +179,7 @@ RegisterNetEvent("SonoranCAD::core:PlayerReady")
AddEventHandler("SonoranCAD::core:PlayerReady", function()
local ids = GetIdentifiers(source)
if ids[Config.primaryIdentifier] == nil then
warnLog(("Player %s connected, but did not have an %s ID."):format(Config.primaryIdentifier))
warnLog(("Player %s connected, but did not have an %s ID."):format(source, Config.primaryIdentifier))

end
end)
20 changes: 20 additions & 0 deletions sonorancad/core/unzipper/unzip.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,24 @@ var fs = require("fs");

exports('UnzipFile', (file, dest) => {
fs.createReadStream(file).pipe(unzipper.Extract({ path: dest}));
});

exports('UnzipFolder', (file, name, dest) => {
fs.createReadStream(file).pipe(unzipper.Parse())
.on('entry', function(entry) {
var fileName = entry.path;
const type = entry.type;
const fprefix = "sonoran_" + name + "-latest/" + name + "/"
const file = fileName.replace(/^.*[/]/, '');
if (fileName.indexOf(fprefix) > -1 && type == "File") {
if (fs.existsSync(dest + "/" + name)) {
entry.pipe(fs.createWriteStream(dest + "/" + name + "/" + file));
} else {
entry.pipe(fs.createWriteStream(dest + "/" + file));
}

} else {
entry.autodrain();
}
})
});
4 changes: 2 additions & 2 deletions sonorancad/core/updater.lua
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ local function doUnzip(path)
end
warnLog("Auto-restarting...")
local f = assert(io.open(GetResourcePath("sonoran_updatehelper").."/run.lock", "w+"))
f:write("1")
f:write("core")
f:close()
Wait(5000)
ExecuteCommand("ensure sonoran_updatehelper")
Expand Down Expand Up @@ -100,7 +100,7 @@ CreateThread(function()
else
infoLog("Server is empty, restarting resources...")
local f = assert(io.open(GetResourcePath("sonoran_updatehelper").."/run.lock", "w+"))
f:write("1")
f:write("core")
f:close()
ExecuteCommand("ensure sonoran_updatehelper")
end
Expand Down
Loading

0 comments on commit 03cf416

Please sign in to comment.