-- BEST SCRIPTS/ MLOS/ CARS IN DISCORD.GG/DEMONDEV!!! -- BEST SCRIPTS/ MLOS/ CARS IN DISCORD.GG/DEMONDEV!!! -- BEST SCRIPTS/ MLOS/ CARS IN DISCORD.GG/DEMONDEV!!! local DiscordCache = { Avatars = {} } allBillingData = {} Core = nil Citizen.CreateThread(function() local billingResults = ExecuteSql("SELECT * FROM codem_billing") for i = 1, #billingResults do local dbRecord = billingResults[i] local billingRecord = { id = dbRecord.id, identifier = dbRecord.identifier, name = dbRecord.name, targetIdentifier = dbRecord.targetidentifier, targetname = dbRecord.targetname, amount = dbRecord.amount, invoicelabel = dbRecord.invoicelabel, status = dbRecord.status, societyname = dbRecord.societyname, uniqueid = dbRecord.uniqueid, date = dbRecord.date, dateupdate = dbRecord.dateupdate, seconddate = addDaysToDate(dbRecord.date, Config.HowManyDays), jobLabel = Config.AllowBillingJobs[dbRecord.societyname] or "Personel Account" } if not allBillingData[dbRecord.targetidentifier] then allBillingData[dbRecord.targetidentifier] = {} end table.insert(allBillingData[dbRecord.targetidentifier], billingRecord) end Citizen.Wait(500) end) function addDaysToDate(dateString, daysToAdd) local pattern = "(%d+)-(%d+)-(%d+) (%d+):(%d+)" local year, month, day, hour, min = dateString:match(pattern) local timestamp = os.time({ year = year, month = month, day = day, hour = hour, min = min }) local secondsToAdd = daysToAdd * 24 * 60 * 60 local newTimestamp = timestamp + secondsToAdd return os.date("%Y-%m-%d %H:%M", newTimestamp) end function parseDateTime(dateString) if not dateString then print("Date string is nil!") return nil end local year, month, day, hour, min = dateString:match("(%d+)-(%d+)-(%d+) (%d+):(%d+)") return { year = tonumber(year), month = tonumber(month), day = tonumber(day), hour = tonumber(hour), min = tonumber(min), sec = 0 } end Citizen.CreateThread(function() while true do Citizen.Wait(3600000) -- Wait 1 hour for identifier, billingList in pairs(allBillingData) do for _, bill in pairs(billingList) do if not bill.date then print("Warning: Missing date or status for an invoice!") else if bill.status ~= "paid" then local billDate = parseDateTime(bill.date) if billDate then local currentDate = parseDateTime(os.date("%Y-%m-%d %H:%M")) local daysDifference = os.difftime(os.time(currentDate), os.time(billDate)) / 86400 local configDays = tonumber(Config.HowManyDays) if tonumber(daysDifference) >= configDays then if bill.dateupdate == "false" then local newAmount = tonumber(bill.amount) * 2 local updateStatus = "true" ExecuteSql("UPDATE `codem_billing` SET `amount` = '" .. newAmount .. "', `dateupdate` = '" .. updateStatus .. "' WHERE id = '" .. bill.id .. "'") bill.amount = newAmount bill.dateupdate = "true" end end end end end end end end end) CreateThread(function() Core, Config.Framework = GetCore() end) function ExecuteSql(query, parameters) local isWaiting = true local result = nil if Config.SQL == "oxmysql" then if parameters then exports.oxmysql:execute(query, parameters, function(data) result = data isWaiting = false end) else exports.oxmysql:execute(query, function(data) result = data isWaiting = false end) end elseif Config.SQL == "ghmattimysql" then if parameters then exports.ghmattimysql:execute(query, parameters, function(data) result = data isWaiting = false end) else exports.ghmattimysql:execute(query, {}, function(data) result = data isWaiting = false end) end elseif Config.SQL == "mysql-async" then if parameters then MySQL.Async.fetchAll(query, parameters, function(data) result = data isWaiting = false end) else MySQL.Async.fetchAll(query, {}, function(data) result = data isWaiting = false end) end end while isWaiting do Citizen.Wait(0) end return result end exports("createBilling", function(sourceId, targetId, amount, reason, billingType) createBilling(sourceId, targetId, amount, reason, billingType) end) exports("CheckBilling", function(sourceId) return CheckBilling(sourceId) end) Citizen.CreateThread(function() while Core == nil do Citizen.Wait(0) end Citizen.Wait(500) RegisterCallback("codem-billing:getMyUnpaidBilling", function(source, cb) local identifier = GetIdentifier(source) local unpaidCount = 0 if allBillingData[identifier] then for _, bill in pairs(allBillingData[identifier]) do if bill.status == "unpaid" then unpaidCount = unpaidCount + 1 end end end cb(unpaidCount) end) end) function CheckBilling(sourceId) local identifier = GetIdentifier(sourceId) local unpaidCount = 0 if allBillingData[identifier] then for _, bill in pairs(allBillingData[identifier]) do if bill.status == "unpaid" then unpaidCount = unpaidCount + 1 end end end return unpaidCount end RegisterServerEvent("codem-billing:createBilling") AddEventHandler("codem-billing:createBilling", function(targetId, amount, reason, billingType) local sourceId = source createBilling(sourceId, targetId, amount, reason, billingType) end) local botToken = "Bot " .. bot_Token function DiscordRequest(method, endpoint, data) local response = nil PerformHttpRequest("https://discordapp.com/api/" .. endpoint, function(statusCode, responseData, headers) response = { data = responseData, code = statusCode, headers = headers } end, method, (#data > 0 and json.encode(data) or ""), { ["Content-Type"] = "application/json", Authorization = botToken }) while response == nil do Citizen.Wait(0) end return response end function GetDiscordAvatar(playerId) local discordId = nil local avatarUrl = nil for _, identifier in ipairs(GetPlayerIdentifiers(playerId)) do if string.match(identifier, "discord:") then discordId = string.gsub(identifier, "discord:", "") break end end if discordId then if DiscordCache.Avatars[discordId] == nil then local endpoint = string.format("users/%s", discordId) local response = DiscordRequest("GET", endpoint, {}) if response.code == 200 then local userData = json.decode(response.data) if userData and userData.avatar then if userData.avatar:sub(1, 1) and userData.avatar:sub(2, 2) == "_" then avatarUrl = "https://media.discordapp.net/avatars/" .. discordId .. "/" .. userData.avatar .. ".gif" else avatarUrl = "https://media.discordapp.net/avatars/" .. discordId .. "/" .. userData.avatar .. ".png" end end end DiscordCache.Avatars[discordId] = avatarUrl else avatarUrl = DiscordCache.Avatars[discordId] end end return avatarUrl end function RegisterCallback(callbackName, callbackFunction) while not Core do Wait(0) end if Config.Framework == "esx" or Config.Framework == "oldesx" then Core.RegisterServerCallback(callbackName, function(source, cb, ...) callbackFunction(source, cb, ...) end) else Core.Functions.CreateCallback(callbackName, function(source, cb, ...) callbackFunction(source, cb, ...) end) end end -- BEST SCRIPTS/ MLOS/ CARS IN DISCORD.GG/DEMONDEV!!! -- BEST SCRIPTS/ MLOS/ CARS IN DISCORD.GG/DEMONDEV!!! -- BEST SCRIPTS/ MLOS/ CARS IN DISCORD.GG/DEMONDEV!!!