2026-04-14 17:41:39 +02:00

369 lines
11 KiB
Lua

permissions = {
["player.ban.temporary"] = false,
["player.ban.permanent"] = false,
["player.ban.view"] = false,
["player.ban.edit"] = false,
["player.ban.remove"] = false,
["player.kick"] = false,
["player.spectate"] = false,
["player.teleport.single"] = false,
["player.slap"] = false,
["player.freeze"] = false,
["player.bucket.join"] = false,
["player.bucket.force"] = false,
["player.screenshot"] = false,
["player.mute"] = false,
["player.warn"] = false,
["player.teleport.everyone"] = false,
["player.reports.view"] = false,
["player.reports.claim"] = false,
["player.reports.process"] = false,
["server.cleanup.cars"] = false,
["server.cleanup.props"] = false,
["server.cleanup.peds"] = false,
["server.shortcut.add"] = false,
["server.reminder.add"] = false,
["server.announce"] = false,
["server.convars"] = false,
["server.resources.start"] = false,
["server.resources.stop"] = false,
["server.chat"] = false,
["immune"] = false,
["anon"] = false,
}
function PrintDebugMessage(msg,level)
loglevel = (GetConvarInt("ea_logLevel", 1))
if not level or not tonumber(level) then level = 3 end
if level == 1 and loglevel >= level then -- ERROR Loglevel
Citizen.Trace("^1"..GetCurrentResourceName().."^7: "..msg.."^7\n")
if IsDuplicityVersion() then
for i,k in pairs(GetOnlineAdmins()) do
TriggerClientEvent("EasyAdmin:showNotification", i, string.gsub(msg, "%^%d", ""))
end
else
TriggerEvent("EasyAdmin:showNotification", string.gsub(msg, "%^%d", ""))
end
elseif level == 2 and loglevel >= level then -- WARN Loglevel
Citizen.Trace("^3"..GetCurrentResourceName().."^7: "..msg.."^7\n")
elseif level == 3 and loglevel >= level then -- INFO Loglevel
Citizen.Trace("^0"..GetCurrentResourceName().."^7: "..msg.."^7\n")
elseif level == 4 and loglevel >= level then -- DEV Loglevel
Citizen.Trace("^7"..GetCurrentResourceName().."^7: "..msg.."^7\n")
elseif level > 4 and loglevel >= level then -- anything above 4 shouldn't exist, but kept just in case
Citizen.Trace("^5"..GetCurrentResourceName().."^7: "..msg.."^7\n")
end
end
if IsDuplicityVersion() then
if GetConvar("ea_enableDebugging", "false") ~= "false" or GetConvarInt("ea_logLevel", 1) ~= 1 then
SetConvar("ea_enableDebugging", "false")
if GetConvarInt("ea_logLevel", 1) == 1 then
SetConvar("ea_logLevel", 3)
end
if GetConvarInt("ea_logLevel", 1) > 1 then
PrintDebugMessage("Debug Messages Enabled, Verbosity is ^2"..GetConvarInt("ea_logLevel", 1).."^7.", 2)
end
else
enableDebugging = false
end
end
if not IsDuplicityVersion() then
RegisterNUICallback("keyboardFinished", function(data, cb)
keyboardResult = data.result
keyboardState = data.state
cb('ok')
end)
function ttsSpeechItem(item)
local ttsText = ""
if not item or GetResourceKvpInt('ea_tts') == 0 then return end
if type(item.Text) == "table" then
if item.Text._Text then
ttsText = item.Text._Text
if item.Label then
ttsText = ttsText .. ", " .. item.Label.Text._Text
end
end
elseif type(item.Text) == "function" then
ttsText = item.Base.Text._Text
if item.Checked == true then
ttsText = ttsText .. ", Checked"
elseif item.Checked == false then
ttsText = ttsText .. ", Unchecked"
end
if item.ItemText then
ttsText = ttsText .. ", " .. item.ItemText._Text
end
end
SendNUIMessage({action= "speak", text=ttsText})
end
function ttsSpeechText(text)
if not text or GetResourceKvpInt('ea_tts') == 0 then return end
SendNUIMessage({action= "speak", text=text})
end
end
function displayKeyboardInput(title,default,maxLength)
if alreadyTyping then return nil end
keyboardResult, keyboardState = nil
local label = GetLabelText(title)
SetNuiFocus(true, true)
SendNUIMessage({action= "open", title=label, default=default, maxLength=maxLength, resource=GetCurrentResourceName()})
alreadyTyping = true
while not keyboardState do --While typing is not aborted and not finished, this loop waits
Citizen.Wait(0)
end
alreadyTyping = false
SetNuiFocus(false,false)
if keyboardState == 0 then
return keyboardResult
else
return nil
end
--[[ -- default V Input
DisplayOnscreenKeyboard(1, title, "", default, "", "", "", maxLength)
while UpdateOnscreenKeyboard() ~= 1 and UpdateOnscreenKeyboard() ~= 2 do --While typing is not aborted and not finished, this loop waits
Citizen.Wait(0)
end
if UpdateOnscreenKeyboard() ~= 2 then
local result = GetOnscreenKeyboardResult()
return result
else
return nil
end
]]
end
function copyToClipboard(text)
SendNUIMessage({action= "clip", text=text})
TriggerEvent("EasyAdmin:showNotification", GetLocalisedText("copiedtoclipboard"))
end
function DoesPlayerHavePermission(player, object)
if IsDuplicityVersion() then
local haspermission = false
if (player == 0 or player == "") then
return true
end-- Console. It's assumed this will be an admin with access.
if not string.find(object, "easyadmin.") then -- compatability with outdated plugins
object = "easyadmin."..object
end
if IsPlayerAceAllowed(player,object) then -- check if the player has access to this permission
haspermission = true
PrintDebugMessage(getName(player, true).." has Permissions for "..object..".", 4)
else
haspermission = false
PrintDebugMessage(getName(player, true).." does not have Permissions for "..object..".", 4)
end
return haspermission
else
return (permissions[object] or false)
end
end
exports('DoesPlayerHavePermission', DoesPlayerHavePermission)
function DoesPlayerHavePermissionForCategory(player, object)
for perm in pairs(permissions) do
if string.startswith(perm, object) then
if DoesPlayerHavePermission(player, perm) then
return true
end
end
end
return false
end
exports('DoesPlayerHavePermissionForCategory', DoesPlayerHavePermissionForCategory)
function GetVersion()
local resourceName = GetCurrentResourceName()
local version = GetResourceMetadata(resourceName, 'version', 0)
local is_master = GetResourceMetadata(resourceName, 'is_master', 0) == "yes" or false
return version, is_master
end
exports('GetVersion', GetVersion)
function loadLanguageStrings()
local strfile = LoadResourceFile(GetCurrentResourceName(), "language/"..GetConvar("ea_LanguageName", "en")..".json")
if strfile then
strings = json.decode(strfile)[1]
else
strings = {language=GetConvar("ea_LanguageName", "en")}
end
end
function GetLocalisedText(string)
if not strings then return "Strings not Loaded yet!" end
if not string then return "No String!" end
if strings[string] then
return strings[string]
else
return "String "..string.." not found in "..strings.language
end
end
exports('GetLocalisedText', GetLocalisedText)
function formatDateString(string)
local dateFormat = GetConvar("ea_dateFormat", '%d/%m/%Y %H:%M:%S')
return os.date(dateFormat, string)
end
exports('formatDateString', formatDateString)
function formatShortcuts(thisstring)
if not thisstring then return thisstring end
local cleanString = string.gsub(string.lower(thisstring), " ", "")
for shortcut,value in pairs(MessageShortcuts) do
if string.lower(shortcut) == cleanString then
thisstring = value
end
end
return thisstring
end
exports('formatShortcuts', formatShortcuts)
function formatRightString(thisstring, customWidth)
if not thisstring then return thisstring end -- in case string is nil, just yeet it back.
local width = (customWidth or maxRightTextWidth)
if string.len(thisstring) > width then
thisstring = string.sub(thisstring, 1, width)..".."
end
return thisstring
end
-- some util funcs so i dont have to mess with NativeUI Source Code.
function getMenuItemTitle(item)
if (item.Base and type(item.Base.Text) == "table" and item.Base.Text._Text) then
return item.Base.Text._Text
elseif (item.Text and type(item.Text) == "table" and item.Text._Text) then
return item.Text._Text
end
end
function setMenuItemTitle(item,text)
if (item.Base and type(item.Base.Text) == "table" and item.Base.Text._Text) then
item.Base.Text._Text = text
elseif (item.Text and type(item.Text) == "table" and item.Text._Text) then
item.Text._Text = text
end
end
function getCachedPlayer(playerId)
if CachedPlayers[playerId] then
return CachedPlayers[playerId]
else
return false
end
end
exports('getCachedPlayer', getCachedPlayer)
function math.round(num, numDecimalPlaces)
if numDecimalPlaces and numDecimalPlaces>0 then
local mult = 10^numDecimalPlaces
return math.floor(num * mult + 0.5) / mult
end
return math.floor(num + 0.5)
end
function string.split(inputstr, sep)
if sep == nil then
sep = "%s"
end
local t={} ; i=1
for str in string.gmatch(inputstr, "([^"..sep.."]+)") do
t[i] = str
i = i + 1
end
return t
end
function string.reverse(s)
local r = ""
for p,c in utf8.codes(s) do
r = utf8.char(c)..r
end
return r
end
function string.startswith(string,start)
return string:sub(1,string.len(start))==start
end
--- http://www.lua.org/pil/11.5.html
function Set (list)
local set = {}
for _, l in ipairs(list) do set[l] = true end
return set
end
-- Convert a lua table into a lua syntactically correct string
function table_to_string(tbl)
return json.encode(tbl)
end
function mergeTables(t1, t2)
local t = t1
for i,v in pairs(t2) do
table.insert(t, v)
end
return t
end
-- terrible function to look for URLs in a string
function matchURL(text_with_URLs)
local domains = [[.ac.ad.ae.aero.af.ag.ai.al.am.an.ao.aq.ar.arpa.as.asia.at.au.aw.ax.az.ba.bb.bd.be.bf.bg.bh.bi.biz.bj.bm.bn.bo.br.bs.bt.bv.bw.by.bz.ca.cat.cc.cd.cf.cg.ch.ci.ck.cl.cm.cn.co.com.coop.cr.cs.cu.cv.cx.cy.cz.dd.de.dj.dk.dm.do.dz.ec.edu.ee.eg.eh.er.es.et.eu.fi.firm.fj.fk.fm.fo.fr.fx.ga.gb.gd.ge.gf.gh.gi.gl.gm.gn.gov.gp.gq.gr.gs.gt.gu.gw.gy.hk.hm.hn.hr.ht.hu.id.ie.il.im.in.info.int.io.iq.ir.is.it.je.jm.jo.jobs.jp.ke.kg.kh.ki.km.kn.kp.kr.kw.ky.kz.la.lb.lc.li.lk.lr.ls.lt.lu.lv.ly.ma.mc.md.me.mg.mh.mil.mk.ml.mm.mn.mo.mobi.mp.mq.mr.ms.mt.mu.museum.mv.mw.mx.my.mz.na.name.nato.nc.ne.net.nf.ng.ni.nl.no.nom.np.nr.nt.nu.nz.om.org.pa.pe.pf.pg.ph.pk.pl.pm.pn.post.pr.pro.ps.pt.pw.py.qa.re.ro.ru.rw.sa.sb.sc.sd.se.sg.sh.si.sj.sk.sl.sm.sn.so.sr.ss.st.store.su.sv.sy.sz.tc.td.tel.tf.tg.th.tj.tk.tl.tm.tn.to.tp.tr.travel.tt.tv.tw.tz.ua.ug.uk.um.us.uy.va.vc.ve.vg.vi.vn.vu.web.wf.ws.xxx.ye.yt.yu.za.zm.zr.zw]]
local tlds = {}
for tld in domains:gmatch'%w+' do
tlds[tld] = true
end
local function max4(a,b,c,d) return math.max(a+0, b+0, c+0, d+0) end
local protocols = {[''] = 0, ['http://'] = 0, ['https://'] = 0, ['ftp://'] = 0}
local finished = {}
for pos_start, url, prot, subd, tld, colon, port, slash, path in
text_with_URLs:gmatch'()(([%w_.~!*:@&+$/?%%#-]-)(%w[-.%w]*%.)(%w+)(:?)(%d*)(/?)([%w_.~!*:@&+$/?%%#=-]*))'
do
if protocols[prot:lower()] == (1 - #slash) * #path and not subd:find'%W%W'
and (colon == '' or port ~= '' and port + 0 < 65536)
and (tlds[tld:lower()] or tld:find'^%d+$' and subd:find'^%d+%.%d+%.%d+%.$'
and max4(tld, subd:match'^(%d+)%.(%d+)%.(%d+)%.$') < 256)
then
finished[pos_start] = true
return url
end
end
for pos_start, url, prot, dom, colon, port, slash, path in
text_with_URLs:gmatch'()((%f[%w]%a+://)(%w[-.%w]*)(:?)(%d*)(/?)([%w_.~!*:@&+$/?%%#=-]*))'
do
if not finished[pos_start] and not (dom..'.'):find'%W%W'
and protocols[prot:lower()] == (1 - #slash) * #path
and (colon == '' or port ~= '' and port + 0 < 65536)
then
return url
end
end
end
exports('matchURL', matchURL)