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

Commit

Permalink
Merge pull request #22 from Sonoran-Software/release/2.2.1
Browse files Browse the repository at this point in the history
Release/2.2.1
  • Loading branch information
nathanctech authored Sep 13, 2020
2 parents 096ee15 + b0d3248 commit 1b9309c
Show file tree
Hide file tree
Showing 20 changed files with 1,077 additions and 892 deletions.
1,718 changes: 859 additions & 859 deletions sonoran_livemap/dist/livemap.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion sonorancad/config.CHANGEME.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"communityID": "",
"apiKey": "",
"apiUrl": "https://api.sonorancad.com/",
"mode": "production",
"postTime": 5000,
"serverId": "1",
"serverType": "standalone",
Expand Down
16 changes: 15 additions & 1 deletion sonorancad/core/client.lua
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,18 @@ AddEventHandler("SonoranCAD::core:recvClientConfig", function(config)
Config[k] = v
end
Config.inited = true
end)
end)

if Config.devHiddenSwitch then
Citizen.CreateThread(function()
SetDiscordAppId(747991263172755528)
SetDiscordRichPresenceAsset("cad_logo")
SetDiscordRichPresenceAssetSmall("sonoran_logo")
while true do
SetRichPresence("Developing SonoranCAD!")
Wait(5000)
SetRichPresence("sonorancad.com")
Wait(5000)
end
end)
end
6 changes: 3 additions & 3 deletions sonorancad/core/commands.lua
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@
update - attempt to auto-update
]]

local function dumpInfo()
function dumpInfo()
local version = GetResourceMetadata(GetCurrentResourceName(), "version", 0)
local pluginList, loadedPlugins, disabledPlugins = GetPluginLists()
local pluginVersions = {}
for k, v in pairs(pluginList) do
if Config.plugins[v] then
table.insert(pluginVersions, ("%s [%s]"):format(v, Config.plugins[v].version))
table.insert(pluginVersions, ("%s [%s/%s]"):format(v, Config.plugins[v].version, Config.plugins[v].latestVersion))
end
end
return ([[
Expand All @@ -36,7 +36,7 @@ Disabled Plugins
]]):format(version, table.concat(pluginVersions, ", "), table.concat(loadedPlugins, ", "), table.concat(disabledPlugins, ", "))
end

local function dumpPlugin(name)
function dumpPlugin(name)
local pluginDetail = {}
if not Config.plugins[name] then
print("Bad plugin: "..name)
Expand Down
3 changes: 2 additions & 1 deletion sonorancad/core/configuration.lua
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ Config = {
}

local conf = LoadResourceFile(GetCurrentResourceName(), "config.json")
if not conf then
if not conf or conf == nil then
errorLog("Failed to load core configuration. Ensure config.json is present.")
assert(false, "Invalid configuration file.")
return
end
for k, v in pairs(json.decode(conf)) do
Expand Down
48 changes: 48 additions & 0 deletions sonorancad/core/html/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<!DOCTYPE html>
<html>
<head>
<title>SonoranCAD Info Page</title>

<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
</head>
<body>
<div id="passwordDiv">
<form>
API Key: <input type="text" id="password" name="password"/><input type="button" id="apisubmit" value="Submit"/>
</form>
</div>
<div id="infoDiv"></div>
<div id="consoleDiv"></div>

<script type="text/javascript">
const api = document.getElementById("apisubmit")
api.addEventListener('click', e => {
fetch('/sonorancad/info', {
method: 'post',
body: JSON.stringify({
password: document.querySelector("#password").value
})
}).then(res => res.json()).then(res => {
let passDiv = document.getElementById("passwordDiv");
let infoDiv = document.getElementById("infoDiv");
let consoleDiv = document.getElementById("consoleDiv");
if (res.error) {
infoDiv.style.color = '#aa0000';
infoDiv.innerHTML = "An error occurred.";
infoDiv.style.display == "none";
} else {
infoDiv.style.color = '#000000';
infoDiv.style.display == "block";
// passDiv.style.display == "none";
infoDiv.innerHTML = res.cadInfo
infoDiv.innerHTML += res.config
consoleDiv.innerHTML = res.console
}


})
})
</script>
</body>
</html>
1 change: 1 addition & 0 deletions sonorancad/core/http.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ exports('HandleHttpRequest', (dest, callback, method, data, headers) => {
callback(500, "", {});
return;
}
options.headers['X-SonoranCAD-Version'] = GetResourceMetadata(GetCurrentResourceName(), "version", 0)

const req = https.request(options, (res) => {
let output = "";
Expand Down
42 changes: 42 additions & 0 deletions sonorancad/core/httpd.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
local function getConfig()
local config = LoadResourceFile(GetCurrentResourceName(), "config.json")
return config
end

SetHttpHandler(function(req, res)
local path = req.path
local method = req.method

if method == 'POST' and path == '/info' then
req.setDataHandler(function(body)
if not body then
res.send(json.encode({["error"] = "bad request"}))
return
end
local data = json.decode(body)
if not data then
res.send(json.encode({["error"] = "bad request"}))
return
end
if data.password ~= Config.apiKey then
res.send(json.encode({["error"] = "bad request"}))
return
end
res.send(json.encode({
["status"] = "ok",
["cadInfo"] = string.gsub(dumpInfo(), "\n", "<br />"),
["config"] = string.gsub(getConfig(), "\r\n", "<br />")..string.gsub(json.encode(Config.plugins), "}", "} <br />"),
["console"] = string.gsub(GetConsoleBuffer(), "\n", "<br />")
}))

end)
else
if path == '/' then
local html = LoadResourceFile(GetCurrentResourceName(), '/core/html/index.html')
res.send(html)
else
res.send("hmm")
end
end

end)
15 changes: 14 additions & 1 deletion sonorancad/core/plugin_loader.lua
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ local function LoadVersionFile(pluginName)
end
end

local NagMessages = {}

CreateThread(function()
Wait(1)
for k, v in pairs(Config.plugins) do
Expand All @@ -44,8 +46,10 @@ CreateThread(function()
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
infoLog(("Plugin Updater: %s has an available update! %s -> %s - Download at: %s"):format(k, version.version, remote.version, remote.download_url.."releases/"))
local nag = ("Plugin Updater: %s has an available update! %s -> %s - Download at: %s"):format(k, version.version, remote.version, remote.download_url.."releases/")
warnLog(nag)
end
if remote.configVersion ~= nil then
local myversion = version.configVersion ~= nil and version.configVersion or "0.0"
Expand Down Expand Up @@ -96,4 +100,13 @@ CreateThread(function()
if #disabledPlugins > 0 then
warnLog(("Disabled Plugins: %s"):format(table.concat(disabledPlugins, ", ")))
end
end)

CreateThread(function()
while true do
Wait(1000*60*60)
for k, v in ipairs(NagMessages) do
warnLog(v)
end
end
end)
95 changes: 80 additions & 15 deletions sonorancad/core/server.lua
Original file line number Diff line number Diff line change
@@ -1,7 +1,25 @@
Plugins = {}

ApiUrls = {
production = "https://api.sonorancad.com/",
development = "https://cadapi.dev.sonoransoftware.com/"
}

function getApiUrl()
if Config.mode == nil then
return ApiUrls.production
else
if ApiUrls[Config.mode] ~= nil then
return ApiUrls[Config.mode]
else
assert(false, "Invalid mode. Valid values are production, development")
end
end
end

CreateThread(function()
Wait(1)
Config.apiUrl = getApiUrl()
infoLog(("Loaded community ID %s with API URL: %s"):format(Config.communityID, Config.apiUrl))
end)

Expand Down Expand Up @@ -56,38 +74,85 @@ EndpointsRequireId = {
["GET_CHARACTERS"] = true,
["CHECK_APIID"] = true,
["APPLY_PERMISSION_KEY"] = true,
["BAN_USER"] = true
["BAN_USER"] = true,
["KICK_USER"] = true
}



function registerApiType(type, endpoint)
ApiEndpoints[type] = endpoint
end

local rateLimitedEndpoints = {}

function performApiRequest(postData, type, cb)
-- apply required headers
local payload = {}
payload["id"] = Config.communityID
payload["key"] = Config.apiKey
payload["type"] = type
payload["data"] = postData
payload["type"] = type
local endpoint = nil
local apiUrl = Config.apiUrl
if ApiEndpoints[type] ~= nil then
endpoint = ApiEndpoints[type]
end
if endpoint == "support" then
apiUrl = "https://api.sonoransoftware.com/"
else
apiUrl = getApiUrl()
end
assert(type ~= nil, "No type specified, invalid request.")
local url = apiUrl..tostring(endpoint).."/"..tostring(type:lower())
if rateLimitedEndpoints[type] == nil then
PerformHttpRequest(url, function(statusCode, res, headers)
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
errorLog(("API ERROR: Invalid endpoint (URL: %s). Ensure you're using a valid endpoint."):format(url))
else
cb(res, true)
end
elseif statusCode == 404 then -- handle 404 requests, like from CHECK_APIID
cb(res, false)
elseif statusCode == 429 then -- rate limited :(
rateLimitedEndpoints[type] = true
warnLog(("You are being ratelimited (last request made to %s) - Ignoring all API requests to this endpoint for 30 seconds. If this is happening frequently, please review your configuration to ensure you're not sending data too quickly."):format(type))
SetTimeout(30000, function()
rateLimitedEndpoints[type] = nil
infoLog(("Endpoint %s no longer ignored."):format(type))
end)
else
errorLog(("CAD API ERROR (from %s): %s %s"):format(url, statusCode, res))
end
end, "POST", json.encode(payload), {["Content-Type"]="application/json"})
else
debugLog(("Endpoint %s is ratelimited. Dropped request: %s"):format(type, json.encode(payload)))
end
PerformHttpRequest(apiUrl..tostring(endpoint), function(statusCode, res, headers)
--debugPrint(("type %s called with post data %s to url %s"):format(type, json.encode(payload), Config.apiUrl..tostring(endpoint)))
if statusCode == 200 and res ~= nil then
--debugPrint("result: "..tostring(res))
cb(res, true)
elseif statusCode == 404 then -- handle 404 requests, like from CHECK_APIID
cb(res, false)
else
errorLog(("CAD API ERROR: %s %s"):format(statusCode, res))
end
end, "POST", json.encode(payload), {["Content-Type"]="application/json"})

end
end

-- Metrics
CreateThread(function()
registerApiType("HEARTBEAT", "general")
while true do
-- Wait a few seconds for server startup
Wait(5000)
local coreVersion = GetResourceMetadata(GetCurrentResourceName(), "version", 0)
local plugins = {}
local playerCount = GetNumPlayerIndices()
for k, v in pairs(Config.plugins) do
table.insert(plugins, {["name"] = k, ["version"] = v.version, ["latest"] = v.latestVersion, ["enabled"] = v.enabled})
end
local payload = {
coreVersion = coreVersion,
commId = Config.communityID,
playerCount = playerCount,
plugins = plugins
}
debugLog(("Heartbeat: %s"):format(json.encode(payload)))
performApiRequest(payload, "HEARTBEAT", function() end)
Wait(1000*60*60)
end
end)
7 changes: 3 additions & 4 deletions sonorancad/fxmanifest.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ games {'gta5'}

author 'Sonoran CAD'
description 'Sonoran CAD FiveM Integration'
version '2.2.0'
version '2.2.1'

server_scripts {
'core/http.js'
Expand All @@ -13,6 +13,7 @@ server_scripts {
,'core/logging.lua'
,'core/server.lua'
,'core/commands.lua'
,'core/httpd.lua'
,'plugins/**/config_*.lua'
,'plugins/**/sv_*.lua'
,'plugins/**/sv_*.js'
Expand All @@ -26,6 +27,4 @@ client_scripts {
,'plugins/**/config_*.lua'
,'plugins/**/cl_*.lua'
,'plugins/**/cl_*.js'
}

dependency 'mysql-async' -- remove if not using ESX
}
1 change: 1 addition & 0 deletions sonorancad/plugins/forcereg
Submodule forcereg added at 8fa28a
1 change: 1 addition & 0 deletions sonorancad/plugins/kick
Submodule kick added at 4b03ec
2 changes: 1 addition & 1 deletion sonorancad/plugins/livemap
2 changes: 1 addition & 1 deletion sonorancad/plugins/locations
2 changes: 1 addition & 1 deletion sonorancad/plugins/lookups
2 changes: 1 addition & 1 deletion sonorancad/plugins/pushevents
2 changes: 1 addition & 1 deletion sonorancad/plugins/wraithv2
2 changes: 1 addition & 1 deletion sonorancad/version.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"resource" : "2.2.0"
"resource" : "2.2.1"
}

0 comments on commit 1b9309c

Please sign in to comment.