Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
Co-authored-by: FullGreen <[email protected]>
  • Loading branch information
MrMicky-FR committed Dec 5, 2023
0 parents commit 8ff351a
Show file tree
Hide file tree
Showing 8 changed files with 370 additions and 0 deletions.
11 changes: 11 additions & 0 deletions .gitignore
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
22 changes: 22 additions & 0 deletions LICENSE
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.
18 changes: 18 additions & 0 deletions README.md
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
```
15 changes: 15 additions & 0 deletions fxmanifest.lua
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'
57 changes: 57 additions & 0 deletions server/commands.lua
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)
84 changes: 84 additions & 0 deletions server/http.lua
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
142 changes: 142 additions & 0 deletions server/main.lua
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.')
21 changes: 21 additions & 0 deletions server/system.js
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),
}
})

0 comments on commit 8ff351a

Please sign in to comment.