From e7788b2bb447886d2f5fc599fb0fab6b606f1aa8 Mon Sep 17 00:00:00 2001 From: Ihsan <122683406+rwixy@users.noreply.github.com> Date: Sat, 18 Jul 2026 14:42:02 +0530 Subject: [PATCH] feat: integrate Medal.tv globally --- [core]/esx_lib/config.lua | 24 ++++++++++++++++++++++++ [core]/esx_lib/fxmanifest.lua | 5 +++++ [core]/esx_lib/html/medal.html | 10 ++++++++++ [core]/esx_lib/html/medal.js | 13 +++++++++++++ [core]/esx_lib/imports/medal/client.lua | 18 ++++++++++++++++++ [core]/esx_lib/resource/medal/client.lua | 22 ++++++++++++++++++++++ 6 files changed, 92 insertions(+) create mode 100644 [core]/esx_lib/config.lua create mode 100644 [core]/esx_lib/html/medal.html create mode 100644 [core]/esx_lib/html/medal.js create mode 100644 [core]/esx_lib/imports/medal/client.lua create mode 100644 [core]/esx_lib/resource/medal/client.lua diff --git a/[core]/esx_lib/config.lua b/[core]/esx_lib/config.lua new file mode 100644 index 00000000..da94e619 --- /dev/null +++ b/[core]/esx_lib/config.lua @@ -0,0 +1,24 @@ +Config = {} + +---@class MedalClipOptions +---@field duration integer +---@field captureDelayMs integer +---@field alertType 'Default'|'Disabled'|'SoundOnly'|'OverlayOnly' + +---@class MedalConfig +---@field enabled boolean +---@field publicKey string +---@field eventName string +---@field clipOptions MedalClipOptions + +---@type MedalConfig +Config.Medal = { + enabled = true, + publicKey = 'pub_82qkpMKV77AkpqLSgWsxLlDyfzpPI7Vw', + eventName = 'Death', + clipOptions = { + duration = 30, + captureDelayMs = 0, + alertType = 'Default' + } +} \ No newline at end of file diff --git a/[core]/esx_lib/fxmanifest.lua b/[core]/esx_lib/fxmanifest.lua index d0a98222..5ed51ec2 100644 --- a/[core]/esx_lib/fxmanifest.lua +++ b/[core]/esx_lib/fxmanifest.lua @@ -8,13 +8,18 @@ author 'ESX Team' version '0.01' description 'Official ESX library' +ui_page 'html/medal.html' + files { 'imports.lua', 'imports/**/client.lua', 'imports/**/shared.lua', + 'html/medal.html', + 'html/medal.js', } shared_scripts { + 'config.lua', 'resource/init.lua', 'resource/**/shared.lua', } diff --git a/[core]/esx_lib/html/medal.html b/[core]/esx_lib/html/medal.html new file mode 100644 index 00000000..f1722bd0 --- /dev/null +++ b/[core]/esx_lib/html/medal.html @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/[core]/esx_lib/html/medal.js b/[core]/esx_lib/html/medal.js new file mode 100644 index 00000000..8c291074 --- /dev/null +++ b/[core]/esx_lib/html/medal.js @@ -0,0 +1,13 @@ +window.addEventListener('message', function (event) { + var data = event.data; + if (!data || data.action !== 'medalClip') return; + + fetch('http://localhost:12665/api/v1/event/invoke', { + method: 'POST', + headers: { + 'publicKey': data.publicKey, + 'Content-Type': 'application/json' + }, + body: JSON.stringify(data.payload) + }).catch(function () {}); +}); diff --git a/[core]/esx_lib/imports/medal/client.lua b/[core]/esx_lib/imports/medal/client.lua new file mode 100644 index 00000000..ff10c292 --- /dev/null +++ b/[core]/esx_lib/imports/medal/client.lua @@ -0,0 +1,18 @@ +local medal = {} + +function medal.getConfig() + return exports['esx_lib']:getMedalConfig() +end + +function medal.triggerClip(publicKey, eventName, clipOptions) + local cfg = medal.getConfig() + if not cfg or not cfg.enabled then return end + + exports['esx_lib']:triggerMedalClip( + publicKey or cfg.publicKey, + eventName or cfg.eventName, + clipOptions or cfg.clipOptions + ) +end + +return medal \ No newline at end of file diff --git a/[core]/esx_lib/resource/medal/client.lua b/[core]/esx_lib/resource/medal/client.lua new file mode 100644 index 00000000..8053def2 --- /dev/null +++ b/[core]/esx_lib/resource/medal/client.lua @@ -0,0 +1,22 @@ +xLib.getMedalConfig = function() + return Config.Medal +end + +xLib.triggerMedalClip = function(publicKey, eventName, clipOptions) + if not publicKey or publicKey == '' then return end + + SendNUIMessage({ + action = 'medalClip', + publicKey = publicKey, + payload = { + eventId = ('esx-clip-%s-%s'):format(GetPlayerServerId(PlayerId()), GetGameTimer()), + eventName = eventName or 'Event', + triggerActions = { 'SaveClip' }, + clipOptions = clipOptions or { + duration = 30, + captureDelayMs = 0, + alertType = 'Default' + } + } + }) +end \ No newline at end of file