-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Showing
8 changed files
with
370 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
# JetBrains | ||
.idea/ | ||
*.iml | ||
*.iws | ||
|
||
# Visual Studio Code | ||
.vscode/ | ||
.history | ||
|
||
# Mac | ||
.DS_Store |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
MIT License | ||
|
||
Copyright (c) 2023 Azuriom | ||
Copyright (c) 2023 FullGreen.GN | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
# AzLink-FiveM | ||
|
||
[![Latest release](https://img.shields.io/github/v/release/Azuriom/AzLink-FiveM?style=flat-square)](https://github.com/Azuriom/AzLink-FiveM/releases) | ||
[![Chat](https://img.shields.io/discord/625774284823986183?color=5865f2&label=Discord&logo=discord&logoColor=fff&style=flat-square)](https://azuriom.com/discord) | ||
|
||
AzLink-FiveM is a [FiveM](https://fivem.net/) resource to link a FiveM server with Azuriom. | ||
|
||
## Download | ||
|
||
You can download the plugin on [Azuriom's website](https://azuriom.com/azlink) or in the [GitHub releases](https://github.com/Azuriom/AzLink-FiveM/releases). | ||
|
||
## Installation | ||
|
||
1. Copy the resources files in `azlink` folder inside `resources` | ||
2. Execute the following command: | ||
``` | ||
start azlink | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
fx_version 'cerulean' | ||
game 'gta5' | ||
|
||
author 'Azuriom & FullGreen.GN' | ||
description 'Link your Azuriom website with your FiveM server.' | ||
version '1.0.0' | ||
|
||
server_scripts { | ||
'server/main.lua', | ||
'server/http.lua', | ||
'server/commands.lua', | ||
'server/system.js', | ||
} | ||
|
||
server_only 'yes' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
local function setupAzLink(baseUrl, siteKey) | ||
AzLink.Config.url = baseUrl | ||
AzLink.Config.site_key = siteKey | ||
|
||
AzLink.Ping():next(function(response) | ||
print('Linked to the website successfully.') | ||
|
||
AzLink.Config.type = response.game == 'fivem' and 'steam' or 'cfx' | ||
AzLink.SaveConfig() | ||
end) | ||
end | ||
|
||
RegisterCommand('azlink', function(source, args) | ||
if args[1] == 'setup' then | ||
if args[2] == nil or args[3] == nil then | ||
print('You must first add this server in your Azuriom admin dashboard, in the "Servers" section.') | ||
|
||
return | ||
end | ||
|
||
setupAzLink(args[2], args[3]) | ||
|
||
return | ||
end | ||
|
||
if args[1] == 'status' then | ||
local result = AzLink.Ping() | ||
|
||
if result == nil then | ||
print('AzLink is not configured yet, use the "setup" subcommand first.') | ||
return | ||
end | ||
|
||
result:next(function() | ||
print('Connected to the website successfully.') | ||
end) | ||
|
||
return | ||
end | ||
|
||
if args[1] == 'fetch' then | ||
local result = AzLink.Fetch(true) | ||
|
||
if result == nil then | ||
print('AzLink is not configured yet, use the "setup" subcommand first.') | ||
return | ||
end | ||
|
||
result:next(function() | ||
print('Data has been fetched successfully.') | ||
end) | ||
|
||
return | ||
end | ||
|
||
print('Unknown subcommand. Must be "setup", "status" or "fetch".') | ||
end, true) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
local fetcher = {} | ||
local httpClient = {} | ||
|
||
function fetcher:run(sendFullData) | ||
local data = AzLink.GetServerData(sendFullData) | ||
local result = promise.new() | ||
|
||
httpClient:request('POST', '', data):next(function(commands) | ||
fetcher:dispatchCommands(commands) | ||
|
||
result:resolve(commands) | ||
end, function(code) | ||
if code == 0 then | ||
print('Unable to connect to the website...') | ||
else | ||
print('An HTTP error occurred, code ' .. code) | ||
end | ||
end) | ||
|
||
return result | ||
end | ||
|
||
function fetcher:dispatchCommands(data) | ||
if not data.commands then | ||
return | ||
end | ||
|
||
local total = 0 | ||
|
||
for _, commandData in pairs(data.commands) do | ||
local playerId | ||
|
||
if data.game == 'fivem-cfx' then | ||
playerId = AzLink.GetPlayerByCfxId(commandData.uid) | ||
else | ||
playerId = AzLink.GetPlayerBySteamId64(commandData.uid) | ||
end | ||
|
||
local info = playerId and AzLink.GetPlayerInfo(playerId) or { } | ||
local name = playerId and GetPlayerName(playerId) or commandData.name | ||
local display = name .. ' (' .. commandData.uid .. ')' | ||
|
||
for _, command in pairs(commandData.values) do | ||
local playerCommand = command:gsub('{player}', name) | ||
playerCommand = playerCommand:gsub('{id}', playerId or -1) | ||
playerCommand = playerCommand:gsub('{fivem_id}', info.fivem or commandData.uid) | ||
playerCommand = playerCommand:gsub('{steam_id}', info.steam64 or commandData.uid) | ||
|
||
print('Dispatching command to ' .. display .. ': ' .. playerCommand) | ||
|
||
ExecuteCommand(playerCommand) | ||
end | ||
|
||
total = total + 1 | ||
end | ||
|
||
if total > 0 then | ||
print('Dispatched commands to ' .. total .. ' players.') | ||
end | ||
end | ||
|
||
function httpClient:request(requestMethod, endpoint, data) | ||
local result = promise.new() | ||
|
||
PerformHttpRequest(AzLink.Config.url .. '/api/azlink' .. endpoint, function(code, body) | ||
if code < 200 or code >= 300 then | ||
result:reject(code) | ||
|
||
return | ||
end | ||
|
||
result:resolve(body and json.decode(body) or body) | ||
end, requestMethod, data and json.encode(data) or '', { | ||
['Azuriom-Link-Token'] = AzLink.Config.site_key, | ||
['Accept'] = 'application/json', | ||
['Content-type'] = 'application/json', | ||
['User-Agent'] = 'AzLink FiveM v' .. AZLINK_VERSION, | ||
}) | ||
|
||
return result | ||
end | ||
|
||
AzLink.Fetcher = fetcher | ||
AzLink.HttpClient = httpClient |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
AZLINK_VERSION = '0.1.0' | ||
|
||
AzLink = AzLink or { } | ||
AzLink.Config = { } | ||
|
||
AzLink.lastSent = 0 | ||
AzLink.lastFullSent = 0 | ||
|
||
function AzLink.Fetch(force) | ||
local timer = GetGameTimer() | ||
local siteKey = AzLink.Config.site_key | ||
local baseUrl = AzLink.Config.url | ||
|
||
if siteKey == nil or baseUrl == nil then | ||
return nil | ||
end | ||
|
||
if not force and timer - AzLink.lastSent < 15 * 1000 then | ||
return nil | ||
end | ||
|
||
local sendFull = os.date("*t").min % 15 == 0 and timer - AzLink.lastFullSent > 60 * 1000 | ||
|
||
AzLink.lastSent = timer | ||
|
||
if sendFull then | ||
AzLink.lastFullSent = timer | ||
end | ||
|
||
return AzLink.Fetcher:run(sendFull) | ||
end | ||
|
||
function AzLink.Ping() | ||
local siteKey = AzLink.Config.site_key | ||
local baseUrl = AzLink.Config.url | ||
|
||
if siteKey == nil or baseUrl == nil then | ||
return nil | ||
end | ||
|
||
local result = promise.new() | ||
|
||
AzLink.HttpClient:request('GET', '', data):next(function(response) | ||
result:resolve(response) | ||
end, function(status) | ||
if status == 0 then | ||
print('Unable to connect to the website...') | ||
else | ||
print('An HTTP error occurred: ' .. status) | ||
end | ||
end) | ||
|
||
return result | ||
end | ||
|
||
function AzLink.GetServerData(includeFullData) | ||
local players = {} | ||
|
||
for _, playerId in ipairs(GetPlayers()) do | ||
local playerInfo = AzLink.GetPlayerInfo(playerId) | ||
|
||
table.insert(players, { | ||
uid = AzLink.Config.type == 'cfx' and playerInfo.fivem or playerInfo.steam64, | ||
name = GetPlayerName(playerId), | ||
}) | ||
end | ||
|
||
local baseData = { | ||
platform = { | ||
type = 'FIVEM', | ||
name = 'FiveM', | ||
version = 'cerulean', | ||
}, | ||
version = AZLINK_VERSION, | ||
players = players, | ||
maxPlayers = GetConvarInt('sv_maxclients', 32), | ||
full = includeFullData, | ||
} | ||
|
||
if includeFullData then | ||
baseData.system = exports.azlink.systemUsage() | ||
end | ||
|
||
return baseData | ||
end | ||
|
||
function AzLink.SaveConfig() | ||
local jsonConfig = json.encode(AzLink.Config, { indent = true }) | ||
SaveResourceFile(GetCurrentResourceName(), 'config.json', jsonConfig) | ||
end | ||
|
||
function AzLink.GetPlayerByCfxId(id) | ||
return AzLink.GetPlayerByIdentifier('fivem:' .. id) | ||
end | ||
|
||
function AzLink.GetPlayerBySteamId64(steamId64) | ||
local id = string.format('%x', steamId64) | ||
|
||
return AzLink.GetPlayerByIdentifier('steam:' .. id) | ||
end | ||
|
||
function AzLink.GetPlayerByIdentifier(id) | ||
for _, playerId in ipairs(GetPlayers()) do | ||
for _, value in pairs(GetPlayerIdentifiers(playerId)) do | ||
if value == id then | ||
return playerId | ||
end | ||
end | ||
end | ||
|
||
return nil | ||
end | ||
|
||
function AzLink.GetPlayerInfo(player) | ||
local info = {} | ||
|
||
for _, value in pairs(GetPlayerIdentifiers(player)) do | ||
if string.sub(value, 1, 6) == 'steam:' then | ||
info.hex = string.sub(value, 7) | ||
info.steam64 = tonumber(info.hex, 16) | ||
elseif string.sub(value, 1, 6) == 'fivem:' then | ||
info.fivem = string.sub(value, 7) | ||
end | ||
end | ||
|
||
return info | ||
end | ||
|
||
local jsonConfig = LoadResourceFile(GetCurrentResourceName(), 'config.json') | ||
|
||
if jsonConfig ~= nil then | ||
AzLink.Config = json.decode(jsonConfig) | ||
end | ||
|
||
Citizen.CreateThread(function() | ||
while true do | ||
Citizen.Wait(60 * 1000) -- 1 minute (in ms) | ||
AzLink.Fetch() | ||
end | ||
end) | ||
|
||
print('AzLink successfully enabled.') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
// We are using JavaScript to get system usage information through Node.js, | ||
// as it's not possible directly in Lua. | ||
const process = require('node:process') | ||
|
||
const updateInterval = 5_000_000 // 5 seconds (in microseconds) | ||
|
||
let currentCpuLoad = -1 | ||
let lastCpuUsage = process.cpuUsage() | ||
|
||
setInterval(() => { | ||
const currentUsage = process.cpuUsage(lastCpuUsage) | ||
currentCpuLoad = (currentUsage.user + currentUsage.system) / updateInterval | ||
lastCpuUsage = currentUsage | ||
}, updateInterval / 1000) | ||
|
||
exports('systemUsage', () => { | ||
return { | ||
ram: process.memoryUsage.rss() / 1024 / 1024, | ||
cpu: currentCpuLoad.toFixed(2), | ||
} | ||
}) |