Files
community_bridge/modules/version/server/VersionChecker.lua
T
MrNewb 69703e803f feat(version): improve version comparison and patch notes display
- Added CompareVersions function for accurate semantic version comparison.
- Refactored patch notes fetching into fetchPatchNotes, supporting both GitHub and Tebex sources.
- Improved error handling for invalid repository formats and missing version metadata.
- Enhanced update notification logic to use latest GitHub release and display patch notes for newer versions.
- Now triggers version check on resource start using updated logic.
- Fully backwards compatible
2025-07-30 14:46:27 -04:00

113 lines
5.1 KiB
Lua

Version = Version or {}
local function padVersion(v)
local parts = {}
for n in v:gmatch("%d+") do
table.insert(parts, tonumber(n))
end
while #parts < 3 do
table.insert(parts, 0)
end
return parts
end
function CompareVersions(v1, v2)
local a, b = padVersion(v1), padVersion(v2)
for i = 1, 3 do
if a[i] < b[i] then return -1
elseif a[i] > b[i] then return 1
end
end
return 0
end
local function fetchPatchNotes(branch, resource, username, reponame, localVersion, tebex, actualRepoPath)
local rawUrl = ('https://raw.githubusercontent.com/%s/%s/%s/resources.json'):format(username, reponame, branch)
PerformHttpRequest(rawUrl, function(noteStatus, noteBody)
if noteStatus == 200 then
local patchData = json.decode(noteBody)
if not patchData then return end
local allVersions = patchData[resource]
if allVersions and type(allVersions) == "table" then
local notesToPrint = {}
for versionStr, notes in pairs(allVersions) do
if CompareVersions(versionStr, localVersion) > 0 and type(notes) == "table" then
table.insert(notesToPrint, {version = versionStr, notes = notes})
end
end
table.sort(notesToPrint, function(a, b)
return CompareVersions(a.version, b.version) < 0
end)
if #notesToPrint > 0 then
if tebex then
rawUrl = "https://portal.cfx.re/assets/granted-assets"
elseif actualRepoPath then
local repoUser, repoName = actualRepoPath:match("([^/]+)/([^/]+)")
if repoUser and repoName then
rawUrl = ('https://github.com/%s/%s/releases/latest'):format(repoUser, repoName)
end
end
print(('^1An update is available for %s (current version: %s)\r\n - ^5Please download the latest version from %s^7'):format(reponame, localVersion, rawUrl))
print('^3Patch Notes:^7')
for _, entry in ipairs(notesToPrint) do
print(('^2Version %s:^7'):format(entry.version))
for _, line in ipairs(entry.notes) do
print((' - %s'):format(line))
end
end
end
end
elseif branch == "main" then
fetchPatchNotes("master", resource, username, reponame, localVersion, tebex)
end
end, 'GET')
end
--- Checks for updates to a resource by comparing the local version (from fxmanifest.lua) with the latest release on GitHub, and optionally prints patch notes if using the template.
--- Example - Version.VersionChecker("TheOrderFivem/patchnotes", true, true, "community_bridge", "TheOrderFivem/community_bridge")
---@param repoPath string
---@param tebex boolean
---@param showPatchNotes boolean
---@param actualResourceName string
---@param actualRepoPathIfGithub string this is the githubAccount/repoName if the resource is hosted on github, otherwise it will use the repoPath initially passed, this is not needed for tebex = true
---@return nil
function Version.VersionChecker(repoPath, tebex, showPatchNotes, actualResourceName, actualRepoPathIfGithub)
local username, reponame = repoPath:match("([^/]+)/([^/]+)")
if not username or not reponame then
return Prints.Error('^1Invalid repository format. Expected format: "username/reponame"^0')
end
local resource = actualResourceName or reponame
local localVersionRaw = GetResourceMetadata(resource, "version", 0)
if not localVersionRaw then
return print(('^1[ERROR]^7 No version metadata found for resource "%s". Ensure fxmanifest.lua contains a valid version string.'):format(resource))
end
local localVersion = localVersionRaw:match('%d+%.%d+%.%d+') or localVersionRaw
if not showPatchNotes then
PerformHttpRequest(('https://api.github.com/repos/%s/%s/releases/latest'):format(username, reponame), function(status, response)
if status ~= 200 then return end
local latest = json.decode(response).tag_name:match('%d+%.%d+%.%d+')
if not latest or latest == localVersion or localVersion:gsub('%D', '') >= latest:gsub('%D', '') then return end
local url = tebex and "https://portal.cfx.re/assets/granted-assets" or json.decode(response).html_url
print(('^1An update is available for %s (current version: %s)\r\n - ^5Please download the latest version from %s^7'):format(reponame, localVersion, url))
end, 'GET')
return
end
fetchPatchNotes("main", resource, username, reponame, localVersion, tebex, actualRepoPathIfGithub)
end
AddEventHandler('onResourceStart', function(resourceName)
if GetCurrentResourceName() ~= resourceName then return end
Version.VersionChecker("TheOrderFivem/patchnotes", false, true, "community_bridge", "TheOrderFivem/community_bridge")
end)
return Version