├── qb-phone ├── .gitattributes ├── html │ ├── js │ │ ├── camera.js │ │ ├── config.js │ │ ├── calculator.js │ │ ├── ping.js │ │ ├── jobcenter.js │ │ ├── wenmo.js │ │ ├── lsbn.js │ │ ├── gopro.js │ │ ├── details.js │ │ ├── garage.js │ │ ├── mail.js │ │ ├── taxi.js │ │ ├── gallery.js │ │ ├── casino.js │ │ └── debt.js │ ├── img │ │ ├── card.jpg │ │ ├── taxi.png │ │ ├── LSBNlogo.png │ │ ├── apps │ │ │ ├── RSL.png │ │ │ ├── job.png │ │ │ ├── clock.png │ │ │ ├── debt.png │ │ │ ├── house.png │ │ │ ├── info.png │ │ │ ├── lsbn.png │ │ │ ├── mail.png │ │ │ ├── notes.png │ │ │ ├── phone.png │ │ │ ├── ping.png │ │ │ ├── wenmo.png │ │ │ ├── camera.png │ │ │ ├── contacts.png │ │ │ ├── crypto.png │ │ │ ├── details.png │ │ │ ├── discord.png │ │ │ ├── facetime.png │ │ │ ├── gallery.png │ │ │ ├── garage.png │ │ │ ├── invoice.png │ │ │ ├── messages.png │ │ │ ├── politie.png │ │ │ ├── racing.png │ │ │ ├── safari.png │ │ │ ├── services.png │ │ │ ├── settings.png │ │ │ ├── taxiapp.png │ │ │ ├── twatter.png │ │ │ ├── weather.png │ │ │ ├── bank-logo.png │ │ │ ├── calcilator.png │ │ │ ├── calculator.png │ │ │ ├── documents.png │ │ │ ├── employment.png │ │ │ ├── jobcenter.png │ │ │ ├── details1213.png │ │ │ ├── whatsapp-chat.png │ │ │ ├── Advertisements.png │ │ │ └── whatsapp-chatlight.png │ │ ├── default.png │ │ ├── erpinger.png │ │ ├── nphone.png │ │ ├── employment.png │ │ ├── samsung-s10.png │ │ ├── samsung-s102.png │ │ ├── backgrounds │ │ │ ├── bg.png │ │ │ ├── yp.png │ │ │ └── default-qbcore.png │ │ ├── default-QBCore.jpg │ │ └── map-photo-ping.png │ └── css │ │ ├── tooltip.css │ │ ├── z-style.css │ │ ├── camera.css │ │ ├── lsbn.css │ │ ├── taxi.css │ │ ├── calculator.css │ │ ├── ping.css │ │ ├── casino.css │ │ ├── gopro.css │ │ ├── wenmo.css │ │ ├── mail.css │ │ ├── debt.css │ │ ├── gallery.css │ │ ├── details.css │ │ └── jobcenter.css ├── assets │ └── dialing.ogg ├── server │ ├── versionchecker.lua │ ├── cleanup.lua │ ├── taxi.lua │ ├── gallery.lua │ ├── news.lua │ ├── commands.lua │ ├── pings.lua │ ├── wenmo.lua │ ├── advertisements.lua │ ├── betting.lua │ ├── whatsapp.lua │ ├── twitter.lua │ ├── invoices.lua │ ├── mail.lua │ ├── documents.lua │ ├── garage.lua │ └── crypto.lua ├── client │ ├── trucker.lua │ ├── taxi.lua │ ├── gallery.lua │ ├── news.lua │ ├── wenmo.lua │ ├── crypto.lua │ ├── gopro.lua │ ├── debt.lua │ ├── betting.lua │ ├── pings.lua │ ├── houses.lua │ ├── jobcenter.lua │ ├── notification.lua │ ├── mail.lua │ ├── invoices.lua │ ├── advertisements.lua │ ├── documents.lua │ ├── garage.lua │ ├── twitter.lua │ ├── groups.lua │ ├── whatsapp.lua │ ├── racing.lua │ └── employment.lua ├── fxmanifest.lua ├── shared │ └── shared.lua ├── Exports.MD ├── qb-phone.sql └── README.md └── README.md /qb-phone/.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /qb-phone/html/js/camera.js: -------------------------------------------------------------------------------- 1 | function setUpCameraApp(url){ 2 | $('.phone-tab-button').click(); 3 | } -------------------------------------------------------------------------------- /qb-phone/assets/dialing.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jnccloud/Renewed-Phone-Wahyu-Adi/HEAD/qb-phone/assets/dialing.ogg -------------------------------------------------------------------------------- /qb-phone/html/img/card.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jnccloud/Renewed-Phone-Wahyu-Adi/HEAD/qb-phone/html/img/card.jpg -------------------------------------------------------------------------------- /qb-phone/html/img/taxi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jnccloud/Renewed-Phone-Wahyu-Adi/HEAD/qb-phone/html/img/taxi.png -------------------------------------------------------------------------------- /qb-phone/html/img/LSBNlogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jnccloud/Renewed-Phone-Wahyu-Adi/HEAD/qb-phone/html/img/LSBNlogo.png -------------------------------------------------------------------------------- /qb-phone/html/img/apps/RSL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jnccloud/Renewed-Phone-Wahyu-Adi/HEAD/qb-phone/html/img/apps/RSL.png -------------------------------------------------------------------------------- /qb-phone/html/img/apps/job.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jnccloud/Renewed-Phone-Wahyu-Adi/HEAD/qb-phone/html/img/apps/job.png -------------------------------------------------------------------------------- /qb-phone/html/img/default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jnccloud/Renewed-Phone-Wahyu-Adi/HEAD/qb-phone/html/img/default.png -------------------------------------------------------------------------------- /qb-phone/html/img/erpinger.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jnccloud/Renewed-Phone-Wahyu-Adi/HEAD/qb-phone/html/img/erpinger.png -------------------------------------------------------------------------------- /qb-phone/html/img/nphone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jnccloud/Renewed-Phone-Wahyu-Adi/HEAD/qb-phone/html/img/nphone.png -------------------------------------------------------------------------------- /qb-phone/html/img/apps/clock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jnccloud/Renewed-Phone-Wahyu-Adi/HEAD/qb-phone/html/img/apps/clock.png -------------------------------------------------------------------------------- /qb-phone/html/img/apps/debt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jnccloud/Renewed-Phone-Wahyu-Adi/HEAD/qb-phone/html/img/apps/debt.png -------------------------------------------------------------------------------- /qb-phone/html/img/apps/house.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jnccloud/Renewed-Phone-Wahyu-Adi/HEAD/qb-phone/html/img/apps/house.png -------------------------------------------------------------------------------- /qb-phone/html/img/apps/info.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jnccloud/Renewed-Phone-Wahyu-Adi/HEAD/qb-phone/html/img/apps/info.png -------------------------------------------------------------------------------- /qb-phone/html/img/apps/lsbn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jnccloud/Renewed-Phone-Wahyu-Adi/HEAD/qb-phone/html/img/apps/lsbn.png -------------------------------------------------------------------------------- /qb-phone/html/img/apps/mail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jnccloud/Renewed-Phone-Wahyu-Adi/HEAD/qb-phone/html/img/apps/mail.png -------------------------------------------------------------------------------- /qb-phone/html/img/apps/notes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jnccloud/Renewed-Phone-Wahyu-Adi/HEAD/qb-phone/html/img/apps/notes.png -------------------------------------------------------------------------------- /qb-phone/html/img/apps/phone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jnccloud/Renewed-Phone-Wahyu-Adi/HEAD/qb-phone/html/img/apps/phone.png -------------------------------------------------------------------------------- /qb-phone/html/img/apps/ping.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jnccloud/Renewed-Phone-Wahyu-Adi/HEAD/qb-phone/html/img/apps/ping.png -------------------------------------------------------------------------------- /qb-phone/html/img/apps/wenmo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jnccloud/Renewed-Phone-Wahyu-Adi/HEAD/qb-phone/html/img/apps/wenmo.png -------------------------------------------------------------------------------- /qb-phone/html/img/employment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jnccloud/Renewed-Phone-Wahyu-Adi/HEAD/qb-phone/html/img/employment.png -------------------------------------------------------------------------------- /qb-phone/html/img/apps/camera.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jnccloud/Renewed-Phone-Wahyu-Adi/HEAD/qb-phone/html/img/apps/camera.png -------------------------------------------------------------------------------- /qb-phone/html/img/apps/contacts.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jnccloud/Renewed-Phone-Wahyu-Adi/HEAD/qb-phone/html/img/apps/contacts.png -------------------------------------------------------------------------------- /qb-phone/html/img/apps/crypto.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jnccloud/Renewed-Phone-Wahyu-Adi/HEAD/qb-phone/html/img/apps/crypto.png -------------------------------------------------------------------------------- /qb-phone/html/img/apps/details.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jnccloud/Renewed-Phone-Wahyu-Adi/HEAD/qb-phone/html/img/apps/details.png -------------------------------------------------------------------------------- /qb-phone/html/img/apps/discord.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jnccloud/Renewed-Phone-Wahyu-Adi/HEAD/qb-phone/html/img/apps/discord.png -------------------------------------------------------------------------------- /qb-phone/html/img/apps/facetime.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jnccloud/Renewed-Phone-Wahyu-Adi/HEAD/qb-phone/html/img/apps/facetime.png -------------------------------------------------------------------------------- /qb-phone/html/img/apps/gallery.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jnccloud/Renewed-Phone-Wahyu-Adi/HEAD/qb-phone/html/img/apps/gallery.png -------------------------------------------------------------------------------- /qb-phone/html/img/apps/garage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jnccloud/Renewed-Phone-Wahyu-Adi/HEAD/qb-phone/html/img/apps/garage.png -------------------------------------------------------------------------------- /qb-phone/html/img/apps/invoice.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jnccloud/Renewed-Phone-Wahyu-Adi/HEAD/qb-phone/html/img/apps/invoice.png -------------------------------------------------------------------------------- /qb-phone/html/img/apps/messages.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jnccloud/Renewed-Phone-Wahyu-Adi/HEAD/qb-phone/html/img/apps/messages.png -------------------------------------------------------------------------------- /qb-phone/html/img/apps/politie.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jnccloud/Renewed-Phone-Wahyu-Adi/HEAD/qb-phone/html/img/apps/politie.png -------------------------------------------------------------------------------- /qb-phone/html/img/apps/racing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jnccloud/Renewed-Phone-Wahyu-Adi/HEAD/qb-phone/html/img/apps/racing.png -------------------------------------------------------------------------------- /qb-phone/html/img/apps/safari.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jnccloud/Renewed-Phone-Wahyu-Adi/HEAD/qb-phone/html/img/apps/safari.png -------------------------------------------------------------------------------- /qb-phone/html/img/apps/services.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jnccloud/Renewed-Phone-Wahyu-Adi/HEAD/qb-phone/html/img/apps/services.png -------------------------------------------------------------------------------- /qb-phone/html/img/apps/settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jnccloud/Renewed-Phone-Wahyu-Adi/HEAD/qb-phone/html/img/apps/settings.png -------------------------------------------------------------------------------- /qb-phone/html/img/apps/taxiapp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jnccloud/Renewed-Phone-Wahyu-Adi/HEAD/qb-phone/html/img/apps/taxiapp.png -------------------------------------------------------------------------------- /qb-phone/html/img/apps/twatter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jnccloud/Renewed-Phone-Wahyu-Adi/HEAD/qb-phone/html/img/apps/twatter.png -------------------------------------------------------------------------------- /qb-phone/html/img/apps/weather.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jnccloud/Renewed-Phone-Wahyu-Adi/HEAD/qb-phone/html/img/apps/weather.png -------------------------------------------------------------------------------- /qb-phone/html/img/samsung-s10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jnccloud/Renewed-Phone-Wahyu-Adi/HEAD/qb-phone/html/img/samsung-s10.png -------------------------------------------------------------------------------- /qb-phone/html/img/samsung-s102.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jnccloud/Renewed-Phone-Wahyu-Adi/HEAD/qb-phone/html/img/samsung-s102.png -------------------------------------------------------------------------------- /qb-phone/html/img/apps/bank-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jnccloud/Renewed-Phone-Wahyu-Adi/HEAD/qb-phone/html/img/apps/bank-logo.png -------------------------------------------------------------------------------- /qb-phone/html/img/apps/calcilator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jnccloud/Renewed-Phone-Wahyu-Adi/HEAD/qb-phone/html/img/apps/calcilator.png -------------------------------------------------------------------------------- /qb-phone/html/img/apps/calculator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jnccloud/Renewed-Phone-Wahyu-Adi/HEAD/qb-phone/html/img/apps/calculator.png -------------------------------------------------------------------------------- /qb-phone/html/img/apps/documents.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jnccloud/Renewed-Phone-Wahyu-Adi/HEAD/qb-phone/html/img/apps/documents.png -------------------------------------------------------------------------------- /qb-phone/html/img/apps/employment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jnccloud/Renewed-Phone-Wahyu-Adi/HEAD/qb-phone/html/img/apps/employment.png -------------------------------------------------------------------------------- /qb-phone/html/img/apps/jobcenter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jnccloud/Renewed-Phone-Wahyu-Adi/HEAD/qb-phone/html/img/apps/jobcenter.png -------------------------------------------------------------------------------- /qb-phone/html/img/backgrounds/bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jnccloud/Renewed-Phone-Wahyu-Adi/HEAD/qb-phone/html/img/backgrounds/bg.png -------------------------------------------------------------------------------- /qb-phone/html/img/backgrounds/yp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jnccloud/Renewed-Phone-Wahyu-Adi/HEAD/qb-phone/html/img/backgrounds/yp.png -------------------------------------------------------------------------------- /qb-phone/html/img/default-QBCore.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jnccloud/Renewed-Phone-Wahyu-Adi/HEAD/qb-phone/html/img/default-QBCore.jpg -------------------------------------------------------------------------------- /qb-phone/html/img/map-photo-ping.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jnccloud/Renewed-Phone-Wahyu-Adi/HEAD/qb-phone/html/img/map-photo-ping.png -------------------------------------------------------------------------------- /qb-phone/html/img/apps/details1213.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jnccloud/Renewed-Phone-Wahyu-Adi/HEAD/qb-phone/html/img/apps/details1213.png -------------------------------------------------------------------------------- /qb-phone/html/img/apps/whatsapp-chat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jnccloud/Renewed-Phone-Wahyu-Adi/HEAD/qb-phone/html/img/apps/whatsapp-chat.png -------------------------------------------------------------------------------- /qb-phone/html/img/apps/Advertisements.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jnccloud/Renewed-Phone-Wahyu-Adi/HEAD/qb-phone/html/img/apps/Advertisements.png -------------------------------------------------------------------------------- /qb-phone/html/img/apps/whatsapp-chatlight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jnccloud/Renewed-Phone-Wahyu-Adi/HEAD/qb-phone/html/img/apps/whatsapp-chatlight.png -------------------------------------------------------------------------------- /qb-phone/html/img/backgrounds/default-qbcore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jnccloud/Renewed-Phone-Wahyu-Adi/HEAD/qb-phone/html/img/backgrounds/default-qbcore.png -------------------------------------------------------------------------------- /qb-phone/server/versionchecker.lua: -------------------------------------------------------------------------------- 1 | if not lib.versionCheck('Renewed-Scripts/qb-phone') then print('Please update to latest qb-phone') end 2 | if not lib.checkDependency('ox_lib', '3.6.0') then print('Please update to ox_lib version 3.6.0') end -------------------------------------------------------------------------------- /qb-phone/client/trucker.lua: -------------------------------------------------------------------------------- 1 | -- NUI Callback 2 | RegisterNUICallback('GetTruckerData', function(_, cb) 3 | local TruckerMeta = PlayerData.metadata.jobrep.trucker 4 | local TierData = exports['qb-trucker']:GetTier(TruckerMeta) 5 | cb(TierData) 6 | end) -------------------------------------------------------------------------------- /qb-phone/html/js/config.js: -------------------------------------------------------------------------------- 1 | Config = [] 2 | 3 | Config.HeaderDisabledApps = [ 4 | "bank", 5 | "whatsapp", 6 | "garage", 7 | "crypto", 8 | "racing", 9 | "houses", 10 | "services", 11 | "trucker", 12 | ] 13 | 14 | Config.DefaultCryptoPage = "general"; -------------------------------------------------------------------------------- /qb-phone/html/js/calculator.js: -------------------------------------------------------------------------------- 1 | function data(val){ 2 | calc.display.value += val; 3 | } 4 | function ac(){ 5 | calc.display.value = ""; 6 | } 7 | function c(){ 8 | calc.display.value = calc.display.value.slice(0, -1); 9 | } 10 | function equal(){ 11 | calc.display.value = eval(calc.display.value); 12 | } -------------------------------------------------------------------------------- /qb-phone/html/js/ping.js: -------------------------------------------------------------------------------- 1 | $(document).on('click', '#ping-send', function(e){ 2 | e.preventDefault(); 3 | var IDPlayer = $(".ierplol").val(); 4 | if (IDPlayer >= 1){ 5 | $.post('https://qb-phone/SendPingPlayer', JSON.stringify({ 6 | id: IDPlayer 7 | })); 8 | $(".ierplol").val(""); 9 | } 10 | }); -------------------------------------------------------------------------------- /qb-phone/html/css/tooltip.css: -------------------------------------------------------------------------------- 1 | @import "https://assets.nopixel.net/web/fonts/gilroy/stylesheet.css"; 2 | 3 | .tooltip-inner { 4 | font-size: 11px; 5 | color: white; 6 | } 7 | 8 | .toggle.ios, .toggle-on.ios, .toggle-off.ios { 9 | border-radius: 20px; 10 | } 11 | 12 | .toggle.ios .toggle-handle { 13 | border-radius: 20px; 14 | } 15 | 16 | .custom-control, .custom-switch, .custom-control-input { 17 | color: white 18 | } 19 | -------------------------------------------------------------------------------- /qb-phone/html/css/z-style.css: -------------------------------------------------------------------------------- 1 | #z-style-expert{ 2 | background: linear-gradient(158deg, rgba(24,25,46,1) 0%, rgba(15,18,27,1) 32%, rgba(24,25,46,1) 68%, rgba(15,18,27,1) 100%); 3 | 4 | background: #2c465f; 5 | background: #0d1218c0; 6 | 7 | background: #f5a15b; 8 | background: #c27e47; 9 | 10 | background: #8ee074; 11 | background: #6cac59; 12 | 13 | box-shadow: 0rem 0rem 0.2rem 0.02rem #000000a6; 14 | 15 | background: #227ea5; 16 | 17 | } -------------------------------------------------------------------------------- /qb-phone/client/taxi.lua: -------------------------------------------------------------------------------- 1 | RegisterNUICallback('GetAvailableTaxiDrivers', function(_, cb) 2 | local drivers = lib.callback.await('qb-phone:server:GetAvailableTaxiDrivers', false) 3 | cb(drivers) 4 | end) 5 | 6 | RegisterNetEvent('qb-phone:OpenAvailableTaxi', function() 7 | local taxiMenu = {} 8 | 9 | -- TO BE WRITTEN 10 | 11 | lib.registerContext({ 12 | id = 'taxi_call_menu', 13 | title = 'Available Taxis', 14 | options = taxiMenu 15 | }) 16 | lib.showContext('taxi_call_menu') 17 | end) -------------------------------------------------------------------------------- /qb-phone/client/gallery.lua: -------------------------------------------------------------------------------- 1 | -- NUI Callback 2 | 3 | RegisterNUICallback('GetGalleryData', function(_, cb) 4 | local data = PhoneData.Images 5 | cb(data) 6 | end) 7 | 8 | RegisterNUICallback('DeleteImage', function(image,cb) 9 | TriggerServerEvent('qb-phone:server:RemoveImageFromGallery',image) 10 | Wait(400) 11 | TriggerServerEvent('qb-phone:server:getImageFromGallery') 12 | cb(true) 13 | end) 14 | 15 | -- Events 16 | 17 | RegisterNetEvent('qb-phone:refreshImages', function(images) 18 | PhoneData.Images = images 19 | end) -------------------------------------------------------------------------------- /qb-phone/server/cleanup.lua: -------------------------------------------------------------------------------- 1 | -- we only do this at the start of the server because its resource intensive and might lagg your database depending on the amount of data that needs to be dropped -- 2 | AddEventHandler('onResourceStart', function(resource) 3 | if resource == GetCurrentResourceName() then 4 | Wait(100) 5 | MySQL.query.await('DELETE FROM phone_tweets WHERE `date` < NOW() - INTERVAL ? hour', {Config.TweetDuration}) 6 | MySQL.query.await('DELETE FROM player_mails WHERE `date` < NOW() - INTERVAL ? hour', {Config.MailDuration}) 7 | end 8 | end) -------------------------------------------------------------------------------- /qb-phone/client/news.lua: -------------------------------------------------------------------------------- 1 | -- NUI Callback 2 | 3 | RegisterNUICallback('Send_lsbn_ToChat', function(data, cb) 4 | TriggerServerEvent('qb-phone:server:Send_lsbn_ToChat', data) 5 | cb("ok") 6 | end) 7 | 8 | RegisterNUICallback('GetLSBNchats', function(data, cb) 9 | TriggerServerEvent('qb-phone:server:GetLSBNchats', data) 10 | cb("ok") 11 | end) 12 | 13 | -- Events 14 | 15 | RegisterNetEvent('qb-phone:LSBN-reafy-for-add', function(data, toggle, text) 16 | if toggle then 17 | TriggerEvent('qb-phone:client:CustomNotification', 18 | "LSBN", 19 | text, 20 | "fas fa-bullhorn", 21 | "#d8e212", 22 | 1500 23 | ) 24 | end 25 | 26 | SendNUIMessage({ 27 | action = "AddNews", 28 | data = data, 29 | }) 30 | end) -------------------------------------------------------------------------------- /qb-phone/html/js/jobcenter.js: -------------------------------------------------------------------------------- 1 | function LoadJobCenter(){ 2 | $.post('https://qb-phone/GetJobCentersJobs', JSON.stringify({}), function(Jobs){ 3 | $(".job-list").html(""); 4 | for (const [_, v] of Object.entries(Jobs)) { 5 | var AddOption = 6 | '
'+ 7 | ' 
'+v.label+'
' 8 | $('.job-list').append(AddOption); 9 | } 10 | }); 11 | }; 12 | 13 | $(document).on('click', '#job-icon-class', function(e){ 14 | e.preventDefault(); 15 | var event = $(this).data('event') 16 | $.post('https://qb-phone/CasinoPhoneJobCenter', JSON.stringify({ 17 | event: event, 18 | })); 19 | }); -------------------------------------------------------------------------------- /qb-phone/client/wenmo.lua: -------------------------------------------------------------------------------- 1 | -- NUI Callback 2 | 3 | RegisterNUICallback('wenmo_givemoney_toID', function(data) 4 | TriggerServerEvent('qb-phone:server:wenmo_givemoney_toID', data) 5 | end) 6 | 7 | RegisterNetEvent('QBCore:Client:OnMoneyChange', function(type, amount, changeType, reason) 8 | if type == "bank" then 9 | if changeType == 'remove' then 10 | SendNUIMessage({ 11 | action = "ChangeMoney_Wenmo", 12 | Color = "#f5a15b", 13 | Amount = "-$"..amount, 14 | Reason = reason or "", 15 | }) 16 | else 17 | SendNUIMessage({ 18 | action = "ChangeMoney_Wenmo", 19 | Color = "#8ee074", 20 | Amount = "+$"..amount, 21 | Reason = reason or "", 22 | }) 23 | end 24 | end 25 | end) 26 | -------------------------------------------------------------------------------- /qb-phone/client/crypto.lua: -------------------------------------------------------------------------------- 1 | -- NUI Callback 2 | 3 | RegisterNUICallback('GetCryptosFromDegens', function(_, cb) 4 | cb(Config.CryptoCoins) 5 | end) 6 | 7 | 8 | RegisterNUICallback('BuyCrypto', function(data, cb) 9 | TriggerServerEvent('qb-phone:server:PurchaseCrypto', data.metadata, data.amount) 10 | 11 | cb("ok") 12 | end) 13 | 14 | RegisterNUICallback('SellCrypto', function(data, cb) 15 | TriggerServerEvent('qb-phone:server:SellCrypto', data.metadata, data.amount) 16 | cb("ok") 17 | end) 18 | 19 | RegisterNUICallback('ExchangeCrypto', function(data, cb) 20 | TriggerServerEvent('qb-phone:server:ExchangeCrypto', data.metadata, data.amount, data.stateid) 21 | 22 | cb("ok") 23 | end) 24 | 25 | RegisterNetEvent('qb-phone:client:UpdateCrypto', function() 26 | SendNUIMessage({ 27 | action = "UpdateCrypto", 28 | PlayerData = PlayerData, 29 | }) 30 | end) 31 | -------------------------------------------------------------------------------- /qb-phone/client/gopro.lua: -------------------------------------------------------------------------------- 1 | if GetResourceState('brazzers-cameras') == 'started' then 2 | RegisterNUICallback('SetupGoPros', function(_, cb) 3 | local list = Config.BrazzersCameras and exports['brazzers-cameras']:GetMyCams() or {} 4 | cb(list) 5 | end) 6 | 7 | RegisterNUICallback('gopro-viewcam', function(data, cb) 8 | if not data then return end 9 | TriggerEvent('Renewed-Cameras:ViewCamera', tonumber(data.id)) 10 | cb("ok") 11 | end) 12 | 13 | RegisterNUICallback('gopro-track', function(data, cb) 14 | TriggerEvent('Renewed-Cameras:client:TrackCam', data.id) 15 | if not data then return end 16 | cb("ok") 17 | end) 18 | 19 | RegisterNUICallback('gopro-transfer', function(data, cb) 20 | if not data then return end 21 | TriggerEvent("Renewed-Cameras:client:GrantAccess", tonumber(data.id), tonumber(data.stateid)) 22 | cb("ok") 23 | end) 24 | end -------------------------------------------------------------------------------- /qb-phone/server/taxi.lua: -------------------------------------------------------------------------------- 1 | lib.callback.register('qb-phone:server:GetAvailableTaxiDrivers', function(_) 2 | local TaxiDrivers = {} 3 | 4 | for i = 1, #Config.TaxiJob do 5 | local job = Config.TaxiJob[i] 6 | TaxiDrivers[job.Job] = {} 7 | TaxiDrivers[job.Job].Players = {} 8 | end 9 | 10 | for _, v in pairs(QBCore.Functions.GetPlayers()) do 11 | local Player = QBCore.Functions.GetPlayer(v) 12 | if Player then 13 | local job = Player.PlayerData.job.name 14 | if TaxiDrivers[job] and Player.PlayerData.job.onduty then 15 | TaxiDrivers[job].Players[#(TaxiDrivers[job].Players)+1] = { 16 | Name = Player.PlayerData.charinfo.firstname .. " " .. Player.PlayerData.charinfo.lastname, 17 | Phone = Player.PlayerData.charinfo.phone, 18 | } 19 | end 20 | end 21 | end 22 | return TaxiDrivers 23 | end) -------------------------------------------------------------------------------- /qb-phone/fxmanifest.lua: -------------------------------------------------------------------------------- 1 | fx_version 'cerulean' 2 | game 'gta5' 3 | 4 | author 'qb-phone Edit' 5 | description 'A NoPixel inspired edit of QBCore\'s Phone.' 6 | version '1.0.0' 7 | 8 | dependencies { 9 | 'ox_lib', 10 | } 11 | 12 | ui_page 'html/index.html' 13 | 14 | shared_scripts { 15 | 'config.lua', 16 | 'shared/shared.lua', 17 | '@qb-apartments/config.lua', 18 | '@qb-garages/config.lua', 19 | '@ox_lib/init.lua' 20 | } 21 | 22 | client_scripts { 23 | 'client/*.lua', 24 | } 25 | 26 | server_scripts { 27 | '@oxmysql/lib/MySQL.lua', 28 | 'server/*.lua', 29 | } 30 | 31 | files { 32 | 'html/*.html', 33 | 'html/js/*.js', 34 | 'html/img/*.png', 35 | 'html/css/*.css', 36 | 'html/img/backgrounds/*.png', 37 | 'html/img/apps/*.png', 38 | } 39 | 40 | lua54 'yes' 41 | 42 | dependency 'qb-target' 43 | 44 | escrow_ignore { 45 | 'config.lua', 46 | 'client/jobcenter.lua', 47 | 'server/employment.lua', 48 | } -------------------------------------------------------------------------------- /qb-phone/html/css/camera.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css?family=Lato&display=swap'); 2 | 3 | .camera-app { 4 | display: none; 5 | height: 108%; 6 | width: 100%; 7 | background: linear-gradient(158deg, rgba(24,25,46,1) 0%, rgba(15,18,27,1) 32%, rgba(24,25,46,1) 68%, rgba(15,18,27,1) 100%); 8 | overflow: hidden; 9 | } 10 | 11 | 12 | .camera-homescreen { 13 | position: absolute; 14 | height: 108%; 15 | width: 100%; 16 | left: 0vh; 17 | } 18 | 19 | 20 | 21 | .loader { 22 | z-index: 1000; 23 | border: 16px solid #f3f3f3; 24 | border-top: 16px solid #3498db; 25 | border-bottom: 16px solid #3498db; 26 | border-radius: 50%; 27 | animation: spin 2s linear infinite; 28 | position: absolute; 29 | top: 50%; 30 | left: 50%; 31 | margin-top: -50px; 32 | margin-left: -50px; 33 | width: 100px; 34 | height: 100px; 35 | } 36 | 37 | @keyframes spin { 38 | 0% { transform: rotate(0deg); } 39 | 100% { transform: rotate(360deg); } 40 | } -------------------------------------------------------------------------------- /qb-phone/server/gallery.lua: -------------------------------------------------------------------------------- 1 | RegisterNetEvent('qb-phone:server:addImageToGallery', function(image) 2 | local src = source 3 | local Player = QBCore.Functions.GetPlayer(src) 4 | exports.oxmysql:insert('INSERT INTO phone_gallery (`citizenid`, `image`) VALUES (?, ?)',{Player.PlayerData.citizenid,image}) 5 | end) 6 | 7 | RegisterNetEvent('qb-phone:server:getImageFromGallery', function() 8 | local src = source 9 | local Player = QBCore.Functions.GetPlayer(src) 10 | local images = exports.oxmysql:executeSync('SELECT * FROM phone_gallery WHERE citizenid = ? ORDER BY `date` DESC',{Player.PlayerData.citizenid}) 11 | TriggerClientEvent('qb-phone:refreshImages', src, images) 12 | end) 13 | 14 | RegisterNetEvent('qb-phone:server:RemoveImageFromGallery', function(data) 15 | local src = source 16 | local Player = QBCore.Functions.GetPlayer(src) 17 | local image = data.image 18 | exports.oxmysql:execute('DELETE FROM phone_gallery WHERE citizenid = ? AND image = ?',{Player.PlayerData.citizenid,image}) 19 | end) -------------------------------------------------------------------------------- /qb-phone/server/news.lua: -------------------------------------------------------------------------------- 1 | local LSBNTable = {} 2 | local LSBNTableID = 0 3 | 4 | RegisterNetEvent('qb-phone:server:Send_lsbn_ToChat', function(data) 5 | LSBNTableID = LSBNTableID + 1 6 | if data.Type == "Text" then 7 | LSBNTable[LSBNTableID] = {['Text'] = data.Text, ['Image'] = "none", ['ID'] = LSBNTableID, ['Type'] = data.Type, ['Time'] = data.Time,} 8 | elseif data.Type == "Image" then 9 | LSBNTable[LSBNTableID] = {['Text'] = data.Text, ['Image'] = data.Image, ['ID'] = LSBNTableID, ['Type'] = data.Type, ['Time'] = data.Time,} 10 | end 11 | local Tables = { 12 | { 13 | ['Text'] = data.Text, ['Image'] = data.Image, ['ID'] = LSBNTableID, ['Type'] = data.Type, ['Time'] = data.Time, 14 | }, 15 | } 16 | TriggerClientEvent('qb-phone:LSBN-reafy-for-add', -1, Tables, true, data.Text) 17 | end) 18 | 19 | RegisterNetEvent('qb-phone:server:GetLSBNchats', function() 20 | local src = source 21 | TriggerClientEvent('qb-phone:LSBN-reafy-for-add', src, LSBNTable, false, nil) 22 | end) -------------------------------------------------------------------------------- /qb-phone/client/debt.lua: -------------------------------------------------------------------------------- 1 | -- NUI Callback 2 | 3 | -- Used for assts and to pay off the entire LOAN 4 | RegisterNUICallback('SendAllPayment', function(data, cb) 5 | -- All your cracked code here brains here 6 | 7 | TriggerServerEvent('Renewed-Debts:server:PayFull', tonumber(data.id)) 8 | 9 | cb("ok") 10 | end) 11 | 12 | RegisterNUICallback('SendMinimumPayment', function(data, cb) 13 | -- All your cracked code here brains here 14 | TriggerServerEvent('Renewed-Debts:server:PayPartial', tonumber(data.id)) 15 | cb("ok") 16 | end) 17 | 18 | 19 | RegisterNUICallback('GetPlayersDebt', function(_, cb) 20 | local debtData = Config.RenewedFinances and exports['qb-finances']:getDebt() or {} 21 | cb(debtData) 22 | end) 23 | 24 | 25 | -- refresh the shit 26 | 27 | RegisterNetEvent('qb-phone:client:refreshDebt', function() 28 | local debtData = Config.RenewedFinances and exports['qb-finances']:getDebt() or {} 29 | SendNUIMessage({ 30 | action = "refreshDebt", 31 | debt = debtData, 32 | }) 33 | end) -------------------------------------------------------------------------------- /qb-phone/server/commands.lua: -------------------------------------------------------------------------------- 1 | QBCore.Commands.Add("setmetadata", "Set Player Metadata (God Only)", {}, false, function(source, args) 2 | local Player = QBCore.Functions.GetPlayer(source) 3 | if args[1] then 4 | if args[1] == "trucker" then 5 | if args[2] then 6 | local newrep = Player.PlayerData.metadata["jobrep"] 7 | newrep.trucker = tonumber(args[2]) 8 | Player.Functions.SetMetaData("jobrep", newrep) 9 | end 10 | end 11 | end 12 | end, "god") 13 | 14 | QBCore.Commands.Add("p#", "Provide Phone Number", {}, false, function(source) 15 | local src = source 16 | local Player = QBCore.Functions.GetPlayer(src) 17 | local PlayerPed = GetPlayerPed(src) 18 | local number = Player.PlayerData.charinfo.phone 19 | local PlayerCoords = GetEntityCoords(PlayerPed) 20 | for _, v in pairs(QBCore.Functions.GetPlayers()) do 21 | local TargetPed = GetPlayerPed(v) 22 | local dist = #(PlayerCoords - GetEntityCoords(TargetPed)) 23 | 24 | if dist < 3.0 then 25 | TriggerClientEvent('chat:addMessage', v, { 26 | color = { 255, 0, 0}, 27 | multiline = true, 28 | args = {"Phone #", number} 29 | }) 30 | end 31 | end 32 | end) 33 | -------------------------------------------------------------------------------- /qb-phone/client/betting.lua: -------------------------------------------------------------------------------- 1 | -- NUI Callback 2 | 3 | RegisterNUICallback('CasinoAddBet', function(data, cb) 4 | TriggerServerEvent('qb-phone:server:CasinoAddBet', data) 5 | cb("ok") 6 | end) 7 | 8 | RegisterNetEvent('qb-phone:client:addbetForAll', function(data) 9 | SendNUIMessage({ 10 | action = "BetAddToApp", 11 | datas = data, 12 | }) 13 | end) 14 | 15 | RegisterNUICallback('BettingAddToTable', function(data, cb) 16 | TriggerServerEvent('qb-phone:server:BettingAddToTable', data) 17 | cb("ok") 18 | end) 19 | 20 | RegisterNUICallback('CasinoDeleteTable', function(_, cb) 21 | TriggerServerEvent('qb-phone:server:DeleteAndClearTable') 22 | cb("ok") 23 | end) 24 | 25 | RegisterNUICallback('CheckHasBetTable', function(_, cb) 26 | local HasTable = lib.callback.await('qb-phone:server:CheckHasBetTable', false) 27 | cb(HasTable) 28 | end) 29 | 30 | RegisterNUICallback('casino_status', function(_, cb) 31 | TriggerServerEvent('qb-phone:server:casino_status') 32 | cb("ok") 33 | end) 34 | 35 | RegisterNUICallback('CheckHasBetStatus', function(_, cb) 36 | local HasStatus = lib.callback.await('qb-phone:server:CheckHasBetStatus', false) 37 | cb(HasStatus) 38 | end) 39 | 40 | RegisterNUICallback('WineridCasino', function(data, cb) 41 | TriggerServerEvent('qb-phone:server:WineridCasino', data) 42 | cb("ok") 43 | end) -------------------------------------------------------------------------------- /qb-phone/server/pings.lua: -------------------------------------------------------------------------------- 1 | RegisterNetEvent("qb-phone:server:sendPing", function(id) 2 | local src = source 3 | local Player = QBCore.Functions.GetPlayer(src) 4 | local Shitter = tonumber(id) 5 | local Other = QBCore.Functions.GetPlayer(Shitter) 6 | local HasVPN = Player.Functions.GetItemByName(Config.VPNItem) 7 | local name = HasVPN and 'Anonymous' or Player.PlayerData.charinfo.firstname 8 | 9 | if not Other then return TriggerClientEvent("QBCore:Notify", src, 'State ID does not exist!', "error") end 10 | 11 | local info = { type = 'ping', Other = Shitter, Player = src, Name = name, OtherName = Other.PlayerData.charinfo.firstname } 12 | if Player.PlayerData.citizenid ~= Other.PlayerData.citizenid then 13 | TriggerClientEvent("qb-phone:client:sendNotificationPing", Shitter, info) 14 | TriggerClientEvent("QBCore:Notify", src, 'Request Sent', "success") 15 | else 16 | TriggerClientEvent("QBCore:Notify", src, 'You cannot send a ping to yourself!', "error") 17 | end 18 | end) 19 | 20 | RegisterNetEvent("qb-phone:server:sendingPing", function(Other, Player, Name, OtherName) 21 | TriggerClientEvent('qb-phone:client:CustomNotification', Player, "PING", OtherName..' Accepted Your Ping!', 'fas fa-map-pin', '#b3e0f2', 7500) 22 | TriggerClientEvent("qb-phone:client:sendPing", Other, Name, GetEntityCoords(GetPlayerPed(Player))) 23 | end) -------------------------------------------------------------------------------- /qb-phone/html/js/wenmo.js: -------------------------------------------------------------------------------- 1 | $(document).on('click', '.wenmo-send-money-btn', function(e){ 2 | e.preventDefault(); 3 | ClearInputNew() 4 | $('#wenmo-box-new-for-give').fadeIn(350); 5 | }); 6 | 7 | $(document).on('click', '#wenmo-send-money-ended', function(e){ 8 | e.preventDefault(); 9 | var ID = $(".wenmo-input-one").val(); 10 | var Amount = $(".wenmo-input-two").val(); 11 | var Reason = $(".wenmo-input-three").val(); 12 | if ((ID && Amount && Reason) != "" && (ID && Amount) >= 1){ 13 | $.post('https://qb-phone/wenmo_givemoney_toID', JSON.stringify({ 14 | ID: ID, 15 | Amount: Amount, 16 | Reason: Reason, 17 | })); 18 | 19 | ClearInputNew() 20 | $('#wenmo-box-new-for-give').fadeIn(350); 21 | } 22 | }); 23 | 24 | $(document).ready(function(){ 25 | window.addEventListener('message', function(event) { 26 | switch(event.data.action) { 27 | case "ChangeMoney_Wenmo": 28 | var date = new Date(); 29 | var Times = date.getHours()+":"+date.getMinutes(); 30 | var AddOption = '
'+event.data.Amount+'
'+Times+'
'+ 31 | '
'+event.data.Reason+'
'+ 32 | '
' 33 | 34 | $('.wenmo-list').prepend(AddOption); 35 | break; 36 | } 37 | }) 38 | }); -------------------------------------------------------------------------------- /qb-phone/server/wenmo.lua: -------------------------------------------------------------------------------- 1 | RegisterNetEvent('qb-phone:server:wenmo_givemoney_toID', function(data) 2 | local src = source 3 | local Ply = QBCore.Functions.GetPlayer(src) 4 | local OtherPly = QBCore.Functions.GetPlayer(tonumber(data.ID)) 5 | local Amount = tonumber(data.Amount) 6 | local Reason = data.Reason 7 | 8 | if src == tonumber(data.ID) then return end 9 | 10 | if not OtherPly then return TriggerClientEvent('QBCore:Notify', src, 'Player not Online', "error") end 11 | 12 | local txt = "Wenmo: "..Reason 13 | 14 | if Ply.PlayerData.money.bank >= Amount then 15 | Ply.Functions.RemoveMoney('bank', Amount, txt) 16 | OtherPly.Functions.AddMoney('bank', Amount, txt) 17 | 18 | if Config.RenewedBanking then 19 | local cid = Ply.PlayerData.citizenid 20 | local name = ("%s %s"):format(Ply.PlayerData.charinfo.firstname, Ply.PlayerData.charinfo.lastname) 21 | 22 | local cid2 = OtherPly.PlayerData.citizenid 23 | local name2 = ("%s %s"):format(OtherPly.PlayerData.charinfo.firstname, OtherPly.PlayerData.charinfo.lastname) 24 | 25 | exports['Renewed-Banking']:handleTransaction(cid, "Wenmo Transaction", Amount, txt, name2, name, "withdraw") 26 | exports['Renewed-Banking']:handleTransaction(cid2, "Wenmo Transaction", Amount, txt, name, name2, "deposit") 27 | end 28 | else 29 | TriggerClientEvent("QBCore:Notify", src, 'You don\'t have enough money!', "error") -- replace this with Phone Notify 30 | end 31 | end) 32 | -------------------------------------------------------------------------------- /qb-phone/client/pings.lua: -------------------------------------------------------------------------------- 1 | local Blip 2 | 3 | -- NUI Callback 4 | 5 | RegisterNetEvent("qb-phone:client:sendPing", function(Name, pos) 6 | if Blip then RemoveBlip(Blip) Blip = nil end 7 | 8 | Blip = AddBlipForCoord(pos.x, pos.y, pos.z) 9 | SetBlipSprite(Blip, 280) 10 | SetBlipDisplay(Blip, 4) 11 | SetBlipScale(Blip, 1.1) 12 | SetBlipAsShortRange(Blip, false) 13 | SetBlipColour(Blip, 0) 14 | BeginTextCommandSetBlipName("STRING") 15 | AddTextComponentSubstringPlayerName(Name..'\'s ping!') 16 | EndTextCommandSetBlipName(Blip) 17 | 18 | TriggerEvent('qb-phone:client:CustomNotification', Name..'\'s Location Marked', "Ping Available For 5 Minutes", 'fas fa-map-pin', '#b3e0f2', 7500) 19 | SetTimeout(60000*5, function() 20 | RemoveBlip(Blip) 21 | Blip = nil 22 | TriggerEvent('qb-phone:client:CustomNotification', Name..'\'s Location Removed', "Ping No Longer Available", 'fas fa-map-pin', '#b3e0f2', 7500) 23 | end) 24 | end) 25 | 26 | RegisterNUICallback('SendPingPlayer', function(data, cb) 27 | TriggerServerEvent('qb-phone:server:sendPing', data.id) 28 | cb('ok') 29 | end) 30 | 31 | -- Events 32 | RegisterNetEvent("qb-phone:client:sendNotificationPing", function(info) 33 | PlaySound(-1, "Click_Fail", "WEB_NAVIGATION_SOUNDS_PHONE", 0, 0, 1) 34 | local success = exports['qb-phone']:PhoneNotification("PING", info.Name..' Incoming Ping', 'fas fa-map-pin', '#b3e0f2', "NONE", 'fas fa-check-circle', 'fas fa-times-circle') 35 | if success then 36 | TriggerServerEvent("qb-phone:server:sendingPing", info.Other, info.Player, info.Name, info.OtherName) 37 | end 38 | end) -------------------------------------------------------------------------------- /qb-phone/shared/shared.lua: -------------------------------------------------------------------------------- 1 | QBCore = exports['qb-core']:GetCoreObject() 2 | 3 | local phoneProp = 0 4 | local phoneModel = joaat("prop_npc_phone_02") 5 | 6 | function CheckAnimLoop() 7 | CreateThread(function() 8 | while PhoneData.AnimationData.lib and PhoneData.AnimationData.anim do 9 | if not IsEntityPlayingAnim(cache.ped, PhoneData.AnimationData.lib, PhoneData.AnimationData.anim, 3) then 10 | lib.requestAnimDict(PhoneData.AnimationData.lib) 11 | TaskPlayAnim(cache.ped, PhoneData.AnimationData.lib, PhoneData.AnimationData.anim, 3.0, 3.0, -1, 50, 0, false, false, false) 12 | end 13 | Wait(500) 14 | end 15 | end) 16 | end 17 | 18 | function newPhoneProp() 19 | deletePhone() 20 | lib.requestModel(phoneModel) 21 | phoneProp = CreateObject(phoneModel, 1.0, 1.0, 1.0, true, true, false) 22 | local bone = GetPedBoneIndex(cache.ped, 28422) 23 | if phoneModel == joaat("prop_cs_phone_01") then 24 | AttachEntityToEntity(phoneProp, cache.ped, bone, 0.0, 0.0, 0.0, 50.0, 320.0, 50.0, true, true, false, false, 2, true) 25 | else 26 | AttachEntityToEntity(phoneProp, cache.ped, bone, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, true, true, false, false, 2, true) 27 | end 28 | end 29 | 30 | function deletePhone() 31 | if phoneProp then 32 | DeleteObject(phoneProp) 33 | phoneProp = 0 34 | end 35 | end 36 | 37 | function DoPhoneAnimation(anim) 38 | local AnimationLib = 'cellphone@' 39 | local AnimationStatus = anim 40 | if cache.vehicle then 41 | AnimationLib = 'anim@cellphone@in_car@ps' 42 | end 43 | lib.requestAnimDict(AnimationLib) 44 | TaskPlayAnim(cache.ped, AnimationLib, AnimationStatus, 3.0, 3.0, -1, 50, 0, false, false, false) 45 | PhoneData.AnimationData.lib = AnimationLib 46 | PhoneData.AnimationData.anim = AnimationStatus 47 | CheckAnimLoop() 48 | end -------------------------------------------------------------------------------- /qb-phone/server/advertisements.lua: -------------------------------------------------------------------------------- 1 | Adverts = {} 2 | 3 | local function GetAdvertFromNumb(src) 4 | for k, v in pairs(Adverts) do 5 | if v.source == src then 6 | return k 7 | end 8 | end 9 | end 10 | 11 | RegisterNetEvent('qb-phone:server:AddAdvert', function(msg, url) 12 | local src = source 13 | local Player = QBCore.Functions.GetPlayer(src) 14 | local name = ("%s %s"):format(Player.PlayerData.charinfo.firstname, Player.PlayerData.charinfo.lastname) 15 | local table = GetAdvertFromNumb(src) 16 | if not url then url = "" else url = url:gsub("[%<>\"()\'$]","") end 17 | 18 | if table then 19 | Adverts[table] = { 20 | message = msg:gsub("[%<>\"()\'$]",""), 21 | name = name, 22 | number = Player.PlayerData.charinfo.phone, 23 | url = url, 24 | source = src, 25 | } 26 | else 27 | Adverts[#Adverts+1] = { 28 | message = msg:gsub("[%<>\"()\'$]",""), 29 | name = name, 30 | number = Player.PlayerData.charinfo.phone, 31 | url = url, 32 | source = src, 33 | } 34 | end 35 | 36 | TriggerClientEvent('qb-phone:client:UpdateAdverts', -1, Adverts, name, src) 37 | end) 38 | 39 | RegisterNetEvent('qb-phone:server:DeleteAdvert', function() 40 | local k = GetAdvertFromNumb(source) 41 | if not k then return end 42 | table.remove(Adverts, k) 43 | TriggerClientEvent('qb-phone:client:UpdateAdverts', -1, Adverts) 44 | end) 45 | 46 | RegisterNetEvent('qb-phone:server:flagAdvert', function(number) 47 | local src = source 48 | local Player = QBCore.Functions.GetPlayerByPhone(number) 49 | local citizenid = Player.PlayerData.citizenid 50 | local name = Player.PlayerData.charinfo.firstname..' '..Player.PlayerData.charinfo.lastname 51 | -- Add some type of log here for admins to keep track of flagged posts 52 | TriggerClientEvent('QBCore:Notify', src, 'Post by '..name.. ' ['..citizenid..'] has been flagged', 'error') 53 | end) 54 | -------------------------------------------------------------------------------- /qb-phone/html/css/lsbn.css: -------------------------------------------------------------------------------- 1 | @import "https://assets.nopixel.net/web/fonts/gilroy/stylesheet.css"; 2 | 3 | .lsbn-app { 4 | display: none; 5 | height: 108%; 6 | width: 100%; 7 | overflow: hidden; 8 | background: linear-gradient(158deg, rgba(24,25,46,1) 0%, rgba(15,18,27,1) 32%, rgba(24,25,46,1) 68%, rgba(15,18,27,1) 100%); 9 | } 10 | 11 | .lsbn-header { 12 | position: absolute; 13 | width: 86%; 14 | height: 10%; 15 | left: 6.5%; 16 | right: 0; 17 | color: white; 18 | /* font-family: 'Gilroy'; */ 19 | font-size: 1.8vh; 20 | /* margin: 0 auto; */ 21 | } 22 | 23 | .lsbn-header > p { 24 | line-height: 12vh; 25 | text-indent: 2vh; 26 | margin: 0 0 0 9vh; 27 | } 28 | 29 | .lsbn-header > span { 30 | position: absolute; 31 | top: 8vh; 32 | left: 9vh; 33 | font-size: 1.2vh; 34 | height: 2vh; 35 | color: white; 36 | } 37 | 38 | .lsbn-list { 39 | position: absolute; 40 | width: 90%; 41 | height: 74%; 42 | margin: 0 auto; 43 | left: 0; 44 | right: 0; 45 | bottom: 3%; 46 | border-radius: .5vh; 47 | overflow-y: scroll; 48 | } 49 | 50 | .lsbn-list::-webkit-scrollbar { 51 | display: none; 52 | } 53 | 54 | 55 | 56 | 57 | 58 | .lsbn-send-news-for-chat{ 59 | position: absolute; 60 | color: whitesmoke; 61 | transition: all 0.2s ease 0s; 62 | display: inline; 63 | border-radius: 4px; 64 | top: 77%; 65 | left: 91%; 66 | z-index: 1; 67 | } 68 | .lsbn-send-news-for-chat:hover{ 69 | color: rgb(187, 187, 187); 70 | } 71 | 72 | .lsbn-logo-style{ 73 | width: 90%; 74 | position: relative; 75 | top: 70%; 76 | margin-left: 5%; 77 | } 78 | 79 | .lsbn-chat-style-main{ 80 | width: 90%; 81 | margin-left: 4%; 82 | margin-bottom: 2%; 83 | padding: 2%; 84 | color: whitesmoke; 85 | background: #2c465f; 86 | border-bottom: 0.1vh solid rgba(245, 245, 245, 0.68); 87 | border-radius: 2px; 88 | } 89 | 90 | .lsbn-chat-time-style{ 91 | text-align: right; 92 | color: #adadad; 93 | } 94 | 95 | .lsbn-chat-to-image-style{ 96 | width: 100%; 97 | } -------------------------------------------------------------------------------- /qb-phone/html/css/taxi.css: -------------------------------------------------------------------------------- 1 | @import "https://assets.nopixel.net/web/fonts/gilroy/stylesheet.css"; 2 | 3 | .taxi-app { 4 | display: none; 5 | height: 108%; 6 | width: 100%; 7 | overflow: hidden; 8 | background: linear-gradient(158deg, rgba(24,25,46,1) 0%, rgba(15,18,27,1) 32%, rgba(24,25,46,1) 68%, rgba(15,18,27,1) 100%); 9 | } 10 | 11 | .taxi-header { 12 | position: absolute; 13 | width: 100%; 14 | height: 12vh; 15 | top: 0; 16 | color: white; 17 | font-size: 1.8vh; 18 | } 19 | 20 | .taxi-taxi-image { 21 | position: absolute; 22 | width: 27vh; 23 | margin: 0 auto; 24 | left: 0; 25 | right: 0; 26 | top: 6vh; 27 | } 28 | 29 | .taxis-list { 30 | position: absolute; 31 | width: 100%; 32 | height: 71%; 33 | margin: 0 auto; 34 | text-align: center; 35 | bottom: 3%; 36 | } 37 | 38 | .taxis-list::-webkit-scrollbar { 39 | display: none; 40 | } 41 | 42 | .taxi-list { 43 | position: relative; 44 | width: 90.0%; 45 | height: 6vh; 46 | margin: auto; 47 | border-bottom: .1vh solid #fff; 48 | } 49 | 50 | .taxi-list-fullname { 51 | position: absolute; 52 | top: 10%; 53 | font-size: 1.3vh; 54 | max-width: 14vh; 55 | white-space: nowrap; 56 | overflow: hidden !important; 57 | text-overflow: ellipsis; 58 | color: white; 59 | } 60 | 61 | .taxi-list-phone { 62 | position: absolute; 63 | top: 50%; 64 | font-size: 1.3vh; 65 | max-width: 14vh; 66 | color: white; 67 | } 68 | 69 | .taxi-list-call { 70 | color: white; 71 | position: absolute; 72 | top: 25%; 73 | transform: rotate(0deg); 74 | right: 0; 75 | font-size: 2vh; 76 | } 77 | 78 | .taxi-list-call:hover i { 79 | color: rgb(179, 179, 179); 80 | } 81 | 82 | .notaxidrivers { 83 | width: 100%; 84 | text-align: center; 85 | font-family: 'Gilroy'; 86 | font-size: 1.7vh; 87 | font-weight: bold; 88 | color: #FFFFFF; 89 | line-height: 20vh; 90 | } 91 | 92 | #taxi-frown { 93 | position: absolute; 94 | top: 15.5%; 95 | left: 41.5%; 96 | font-size: 275%; 97 | color: #FFFFFF; 98 | } 99 | -------------------------------------------------------------------------------- /qb-phone/client/houses.lua: -------------------------------------------------------------------------------- 1 | -- NUI Callback 2 | 3 | RegisterNUICallback('GetPlayerHouses', function(_, cb) 4 | QBCore.Functions.TriggerCallback('qb-phone:server:GetPlayerHouses', function(Houses) 5 | cb(Houses) 6 | end) 7 | end) 8 | 9 | RegisterNUICallback('GetPlayerKeys', function(_, cb) 10 | QBCore.Functions.TriggerCallback('qb-phone:server:GetHouseKeys', function(Keys) 11 | cb(Keys) 12 | end) 13 | end) 14 | 15 | RegisterNUICallback('SetHouseLocation', function(data, cb) 16 | SetNewWaypoint(data.HouseData.HouseData.coords.enter.x, data.HouseData.HouseData.coords.enter.y) 17 | QBCore.Functions.Notify("GPS set to " .. data.HouseData.HouseData.adress .. "!", "success") 18 | cb("ok") 19 | end) 20 | 21 | RegisterNUICallback('RemoveKeyholder', function(data, cb) 22 | TriggerServerEvent('qb-houses:server:removeHouseKey', data.HouseData.name, { 23 | citizenid = data.HolderData.citizenid, 24 | firstname = data.HolderData.charinfo.firstname, 25 | lastname = data.HolderData.charinfo.lastname, 26 | }) 27 | 28 | cb("ok") 29 | end) 30 | 31 | RegisterNUICallback('TransferCid', function(data, cb) 32 | local TransferedCid = data.newBsn 33 | 34 | QBCore.Functions.TriggerCallback('qb-phone:server:TransferCid', function(CanTransfer) 35 | cb(CanTransfer) 36 | end, TransferedCid, data.HouseData) 37 | end) 38 | 39 | RegisterNUICallback('FetchPlayerHouses', function(data, cb) 40 | QBCore.Functions.TriggerCallback('qb-phone:server:MeosGetPlayerHouses', function(result) 41 | cb(result) 42 | end, data.input) 43 | end) 44 | 45 | RegisterNUICallback('SetGPSLocation', function(data, cb) 46 | SetNewWaypoint(data.coords.x, data.coords.y) 47 | QBCore.Functions.Notify('GPS set!', "success") 48 | 49 | cb("ok") 50 | end) 51 | 52 | RegisterNUICallback('SetApartmentLocation', function(data, cb) 53 | local ApartmentData = data.data.appartmentdata 54 | local TypeData = Apartments.Locations[ApartmentData.type] 55 | 56 | SetNewWaypoint(TypeData.coords.enter.x, TypeData.coords.enter.y) 57 | QBCore.Functions.Notify('GPS set!', "success") 58 | 59 | cb("ok") 60 | end) -------------------------------------------------------------------------------- /qb-phone/client/jobcenter.lua: -------------------------------------------------------------------------------- 1 | NoVPN = {} 2 | CreateThread(function () 3 | for _, v in pairs(Config.JobCenter) do 4 | if v.vpn == false then 5 | NoVPN[#NoVPN+1] = v 6 | end 7 | end 8 | end) 9 | 10 | RegisterNUICallback('GetJobCentersJobs', function(data, cb) 11 | local result = QBCore.Functions.HasItem("vpn", 1) 12 | if result then 13 | cb(Config.JobCenter) 14 | else 15 | cb(NoVPN) 16 | end 17 | end) 18 | 19 | RegisterNUICallback('CasinoPhoneJobCenter', function(data) 20 | TriggerEvent(data.event) 21 | end) 22 | 23 | RegisterNetEvent('qb-phone:jobcenter:tow', function() 24 | TriggerEvent('qb-phone:client:CustomNotification', 25 | 'JOB CENTER', 26 | 'GPS Waypoint Set', 27 | 'fas fa-briefcase', 28 | '#2496f2', 29 | 5000 30 | ) 31 | SetNewWaypoint(-191.48, -1158.67) 32 | end) 33 | 34 | RegisterNetEvent('qb-phone:jobcenter:fish', function() 35 | TriggerEvent('qb-phone:client:CustomNotification', 36 | 'JOB CENTER', 37 | 'GPS Waypoint Set', 38 | 'fas fa-briefcase', 39 | '#2496f2', 40 | 5000 41 | ) 42 | SetNewWaypoint(-335.15, 6105.79) 43 | end) 44 | 45 | RegisterNetEvent('qb-phone:jobcenter:postop', function() 46 | TriggerEvent('qb-phone:client:CustomNotification', 47 | 'JOB CENTER', 48 | 'GPS Waypoint Set', 49 | 'fas fa-briefcase', 50 | '#2496f2', 51 | 5000 52 | ) 53 | SetNewWaypoint(-427.78, -2774.04) 54 | end) 55 | 56 | RegisterNetEvent('qb-phone:jobcenter:sanitation', function() 57 | TriggerEvent('qb-phone:client:CustomNotification', 58 | 'JOB CENTER', 59 | 'GPS Waypoint Set', 60 | 'fas fa-briefcase', 61 | '#2496f2', 62 | 5000 63 | ) 64 | SetNewWaypoint(-321.83, -1545.94) 65 | end) 66 | 67 | RegisterNetEvent('qb-phone:jobcenter:pdimpound', function() 68 | TriggerEvent('qb-phone:client:CustomNotification', 69 | 'JOB CENTER', 70 | 'GPS Waypoint Set', 71 | 'fas fa-briefcase', 72 | '#2496f2', 73 | 5000 74 | ) 75 | SetNewWaypoint(442.05, -1013.97) 76 | end) -------------------------------------------------------------------------------- /qb-phone/client/notification.lua: -------------------------------------------------------------------------------- 1 | local Result = nil 2 | local test = false 3 | 4 | -- NUI Callbacks 5 | 6 | RegisterNUICallback('AcceptNotification', function() 7 | Result = true 8 | Wait(100) 9 | test = false 10 | return Result 11 | end) 12 | 13 | RegisterNUICallback('DenyNotification', function() 14 | Result = false 15 | Wait(100) 16 | test = false 17 | return Result 18 | end) 19 | 20 | -- Events 21 | 22 | RegisterNetEvent("qb-phone:client:CustomNotification", function(title, text, icon, color, timeout) -- Send a PhoneNotification to the phone from anywhere 23 | SendNUIMessage({ 24 | action = "PhoneNotification", 25 | PhoneNotify = { 26 | title = title, 27 | text = text, 28 | icon = icon, 29 | color = color, 30 | timeout = timeout, 31 | }, 32 | }) 33 | end) 34 | 35 | -- ex. local success = exports['qb-phone']:PhoneNotification("PING", info.Name..' Incoming Ping', 'fas fa-map-pin', '#b3e0f2', "NONE", 'fas fa-check-circle', 'fas fa-times-circle') 36 | 37 | RegisterNetEvent("qb-phone:client:CustomNotification2", function(title, text, icon, color, timeout, accept, deny) -- Send a PhoneNotification to the phone from anywhere 38 | SendNUIMessage({ 39 | action = "PhoneNotificationCustom", 40 | PhoneNotify = { 41 | title = title, 42 | text = text, 43 | icon = icon, 44 | color = color, 45 | timeout = timeout, 46 | accept = accept, 47 | deny = deny, 48 | }, 49 | }) 50 | end) 51 | -- Functions 52 | 53 | local function PhoneNotification(title, text, icon, color, timeout, accept, deny) 54 | Result = nil 55 | test = true 56 | SendNUIMessage({ 57 | action = "PhoneNotificationCustom", 58 | PhoneNotify = { 59 | title = title, 60 | text = text, 61 | icon = icon, 62 | color = color, 63 | timeout = timeout, 64 | accept = accept, 65 | deny = deny, 66 | }, 67 | }) 68 | while test do 69 | Wait(5) 70 | end 71 | Wait(100) 72 | return Result 73 | end exports("PhoneNotification", PhoneNotification) 74 | -------------------------------------------------------------------------------- /qb-phone/Exports.MD: -------------------------------------------------------------------------------- 1 | qb-phone exports 2 | 3 | # Crypto (Server side) 4 | 5 | ``` 6 | 7 | exports['qb-phone']:RemoveCrypto(src, type, amount) 8 | 9 | exports['qb-phone']:hasEnough(src, type, amount) 10 | 11 | exports['qb-phone']:AddCrypto(src, type, amount) 12 | 13 | ``` 14 | 15 | # Employment (Server side) 16 | 17 | ``` 18 | 19 | exports['qb-phone']:hireUser(Job, CID, grade) 20 | 21 | exports['qb-phone']:fireUser(Job, CID) 22 | 23 | ``` 24 | 25 | # Groups (Server Side) 26 | ``` 27 | 28 | exports['qb-phone']:NotifyGroup(group, msg, type) 29 | 30 | exports['qb-phone']:pNotifyGroup(group, header, msg, icon, colour, length) 31 | 32 | exports['qb-phone']:CreateBlipForGroup(groupID, name, data) 33 | 34 | exports['qb-phone']:RemoveBlipForGroup(groupID, name) 35 | 36 | exports['qb-phone']:GetGroupByMembers(src) 37 | 38 | exports['qb-phone']:getGroupMembers(groupID) 39 | 40 | exports['qb-phone']:getGroupSize(groupID) 41 | 42 | exports['qb-phone']:GetGroupLeader(groupID) 43 | 44 | exports['qb-phone']:DestroyGroup(groupID) 45 | 46 | exports['qb-phone']:isGroupLeader(src, groupID) 47 | 48 | -------------------------------------------------- 49 | 50 | exports['qb-phone']:setJobStatus(groupID, status, stages) 51 | 52 | exports['qb-phone']:getJobStatus(groupID) 53 | 54 | exports['qb-phone']:resetJobStatus(groupID) 55 | 56 | -------------------------------------------------- 57 | 58 | exports['qb-phone']:isGroupTemp(groupID) 59 | 60 | exports['qb-phone']:CreateGroup(src, name, password) 61 | 62 | ``` 63 | 64 | # Notifications (Client side) 65 | 66 | ``` 67 | 68 | exports['qb-phone']:PhoneNotification(title, text, icon, color, timeout, accept, deny) 69 | 70 | ``` 71 | 72 | # Twitter (Server side) 73 | 74 | ``` 75 | 76 | local function escape_str(s) 77 | return s 78 | end 79 | 80 | local TweetData = { 81 | firstName = PhoneData.PlayerData.charinfo.firstname, 82 | lastName = PhoneData.PlayerData.charinfo.lastname, 83 | citizenid = PhoneData.PlayerData.citizenid, 84 | message = escape_str(data.Message):gsub("[%<>\"()\'$]",""), 85 | time = data.Date, 86 | tweetId = "TWEET-"..math.random(11111111, 99999999), 87 | type = data.type, 88 | url = URL 89 | } 90 | 91 | exports['qb-phone']:AddNewTweet(TweetData) 92 | 93 | ``` 94 | -------------------------------------------------------------------------------- /qb-phone/client/mail.lua: -------------------------------------------------------------------------------- 1 | -- NUI Callback 2 | 3 | RegisterNUICallback('AcceptMailButton', function(data, cb) 4 | if data.buttonEvent or data.buttonData then 5 | if data.isServer then 6 | TriggerServerEvent(data.buttonEvent, data.buttonData) 7 | else 8 | TriggerEvent(data.buttonEvent, data.buttonData) 9 | end 10 | end 11 | 12 | TriggerServerEvent('qb-phone:server:ClearButtonData', data.mailId) 13 | cb('ok') 14 | end) 15 | 16 | RegisterNUICallback('GetMails', function(_, cb) 17 | cb(PhoneData.Mails) 18 | end) 19 | 20 | RegisterNUICallback('RemoveMail', function(data, cb) 21 | local MailId = data.mailId 22 | TriggerServerEvent('qb-phone:server:RemoveMail', MailId) 23 | cb('ok') 24 | end) 25 | 26 | -- Events 27 | 28 | RegisterNetEvent('qb-phone:client:NewMailNotify', function(MailData) 29 | TriggerEvent('qb-phone:client:CustomNotification', 30 | "Mail", 31 | "New E-Mail from: "..MailData.sender, 32 | "fas fa-envelope", 33 | "ff002f", 34 | 1500 35 | ) 36 | 37 | Config.PhoneApplications['mail'].Alerts = Config.PhoneApplications['mail'].Alerts + 1 38 | end) 39 | 40 | RegisterNetEvent('qb-phone:client:UpdateMails', function(NewMails) 41 | 42 | PhoneData.Mails = {} 43 | 44 | for _, v in pairs(NewMails) do 45 | PhoneData.Mails[#PhoneData.Mails+1] = { 46 | citizenid = v.citizenid, 47 | sender = v.sender, 48 | subject = v.subject, 49 | message = v.message, 50 | read = v.read, 51 | mailid = v.mailId, 52 | date = v.date, 53 | button = type(v.button) == "string" and json.decode(v.button) or v.button 54 | } 55 | end 56 | 57 | PhoneData.Mails = NewMails 58 | 59 | SendNUIMessage({ 60 | action = "UpdateMails", 61 | Mails = NewMails 62 | }) 63 | end) 64 | 65 | RegisterCommand("testmail", function(source) 66 | TriggerServerEvent('qb-phone:server:sendNewMail', { 67 | sender = "MV-SCRIPT", 68 | subject = "Test Mail", 69 | message = "Hello,

The vehicle you need to collect is a
" .. 70 | ".

The approximate position of the vehicle and the scrapyard you need to bring it to are marked on your GPS.", 71 | }) 72 | end, false) -------------------------------------------------------------------------------- /qb-phone/client/invoices.lua: -------------------------------------------------------------------------------- 1 | local function GetInvoiceFromID(id) 2 | for k, v in pairs(PhoneData.Invoices) do 3 | if v.id == id then 4 | return k 5 | end 6 | end 7 | end 8 | 9 | -- NUI Callback 10 | 11 | RegisterNUICallback('GetInvoices', function(_, cb) 12 | cb(PhoneData.Invoices) 13 | end) 14 | 15 | RegisterNUICallback('PayInvoice', function(data, cb) 16 | local senderCitizenId = data.senderCitizenId 17 | local society = data.society 18 | local amount = data.amount 19 | local invoiceId = data.invoiceId 20 | 21 | TriggerServerEvent('qb-phone:server:PayMyInvoice', society, amount, invoiceId, senderCitizenId) 22 | cb("ok") 23 | end) 24 | 25 | RegisterNUICallback('DeclineInvoice', function(data, cb) 26 | local amount = data.amount 27 | local invoiceId = data.invoiceId 28 | TriggerServerEvent('qb-phone:server:DeclineMyInvoice', amount, invoiceId) 29 | cb("ok") 30 | end) 31 | 32 | -- Events 33 | 34 | RegisterNetEvent('qb-phone:client:AcceptorDenyInvoice', function(id, name, job, senderCID, amount, resource) 35 | PhoneData.Invoices[#PhoneData.Invoices+1] = { 36 | id = id, 37 | citizenid = QBCore.Functions.GetPlayerData().citizenid, 38 | sender = name, 39 | society = job, 40 | sendercitizenid = senderCID, 41 | amount = amount 42 | } 43 | 44 | local success = exports['qb-phone']:PhoneNotification("Invoice", 'Invoice of $'..amount.." Sent from "..name, 'fas fa-file-invoice-dollar', '#b3e0f2', "NONE", 'fas fa-check-circle', 'fas fa-times-circle') 45 | if success then 46 | local table = GetInvoiceFromID(id) 47 | if table then 48 | TriggerServerEvent('qb-phone:server:PayMyInvoice', job, amount, id, senderCID, resource) 49 | end 50 | else 51 | local table = GetInvoiceFromID(id) 52 | if table then 53 | TriggerServerEvent('qb-phone:server:DeclineMyInvoice', amount, id, senderCID, resource) 54 | end 55 | end 56 | end) 57 | 58 | RegisterNetEvent('qb-phone:client:RemoveInvoiceFromTable', function(id) 59 | local table = GetInvoiceFromID(id) 60 | if table then 61 | PhoneData.Invoices[table] = nil 62 | 63 | SendNUIMessage({ 64 | action = "refreshInvoice", 65 | invoices = PhoneData.Invoices, 66 | }) 67 | end 68 | end) -------------------------------------------------------------------------------- /qb-phone/client/advertisements.lua: -------------------------------------------------------------------------------- 1 | -- Functions 2 | 3 | local function GetKeyByNumber(Number) 4 | if PhoneData.Chats then 5 | for k, v in pairs(PhoneData.Chats) do 6 | if v.number == Number then 7 | return k 8 | end 9 | end 10 | end 11 | end 12 | 13 | -- NUI Callback 14 | 15 | RegisterNUICallback('PostAdvert', function(data, cb) 16 | local url 17 | 18 | if data.url and string.match(data.url, '[a-z]*://[^ >,;]*') then 19 | url = data.url 20 | end 21 | 22 | TriggerServerEvent('qb-phone:server:AddAdvert', data.message, url) 23 | cb("ok") 24 | end) 25 | 26 | 27 | RegisterNUICallback('FlagAdvert', function(data, cb) 28 | TriggerServerEvent('qb-phone:server:flagAdvert', data.number) 29 | cb("ok") 30 | end) 31 | 32 | RegisterNUICallback("DeleteAdvert", function(_, cb) 33 | TriggerServerEvent("qb-phone:server:DeleteAdvert") 34 | cb("ok") 35 | end) 36 | 37 | RegisterNUICallback('LoadAdverts', function(_, cb) 38 | cb(PhoneData.Adverts) 39 | end) 40 | 41 | RegisterNUICallback('ClearAlerts', function(data, cb) 42 | local chat = data.number 43 | local ChatKey = GetKeyByNumber(chat) 44 | 45 | if PhoneData.Chats[ChatKey].Unread then 46 | local newAlerts = (Config.PhoneApplications['whatsapp'].Alerts - PhoneData.Chats[ChatKey].Unread) 47 | Config.PhoneApplications['whatsapp'].Alerts = newAlerts 48 | 49 | PhoneData.Chats[ChatKey].Unread = 0 50 | 51 | SendNUIMessage({ 52 | action = "RefreshWhatsappAlerts", 53 | Chats = PhoneData.Chats, 54 | }) 55 | SendNUIMessage({ action = "RefreshAppAlerts", AppData = Config.PhoneApplications }) 56 | end 57 | 58 | cb("ok") 59 | end) 60 | 61 | -- Events 62 | 63 | RegisterNetEvent('qb-phone:client:UpdateAdverts', function(Adverts, LastAd, src) 64 | if not FullyLoaded or not Adverts then return end 65 | PhoneData.Adverts = Adverts 66 | 67 | SendNUIMessage({ 68 | action = "RefreshAdverts", 69 | Adverts = PhoneData.Adverts 70 | }) 71 | 72 | if not LastAd or not src then return end 73 | if GetPlayerServerId(cache.ped) == src then return end 74 | 75 | TriggerEvent('qb-phone:client:CustomNotification', 76 | "Advertisement", 77 | "New Ad Posted: "..LastAd, 78 | "fas fa-ad", 79 | "#ff8f1a", 80 | 4500 81 | ) 82 | end) -------------------------------------------------------------------------------- /qb-phone/client/documents.lua: -------------------------------------------------------------------------------- 1 | -- NUI Callback 2 | 3 | -- WORK IN PROGRESS 4 | --[[ 5 | RegisterNUICallback('SetupHousingDocuments', function(_, cb) 6 | QBCore.Functions.TriggerCallback('qb-phone:server:GetHousingLocations', function(houses) 7 | cb(houses) 8 | end) 9 | end) 10 | ]] 11 | 12 | RegisterNUICallback('documents_Save_Note_As', function(data, cb) 13 | TriggerServerEvent('qb-phone:server:documents_Save_Note_As', data) 14 | cb("ok") 15 | end) 16 | 17 | RegisterNUICallback('document_Send_Note', function(data, cb) 18 | if data.Type == 'LocalSend' then 19 | local pID, playerPed, coords = lib.getClosestPlayer(GetEntityCoords(cache.ped), 2.5) 20 | if pID ~= -1 then 21 | local PlayerId = GetPlayerServerId(pID) 22 | TriggerServerEvent("qb-phone:server:sendDocumentLocal", data, PlayerId) 23 | else 24 | TriggerEvent("DoShortHudText", "No one around!", 2) 25 | end 26 | elseif data.Type == 'PermSend' then 27 | TriggerServerEvent('qb-phone:server:sendDocument', data) 28 | end 29 | cb("ok") 30 | end) 31 | 32 | RegisterNetEvent("qb-phone:client:sendingDocumentRequest", function(data, Receiver, Ply, SenderName) 33 | local success = exports['qb-phone']:PhoneNotification("DOCUMENTS", SenderName..' Incoming Document', 'fas fa-folder', '#b3e0f2', "NONE", 'fas fa-check-circle', 'fas fa-times-circle') 34 | if success then 35 | if data.Type == 'PermSend' then 36 | TriggerServerEvent("qb-phone:server:documents_Save_Note_As", data, Receiver, Ply, SenderName) 37 | elseif data.Type == 'LocalSend' then 38 | TriggerEvent('qb-phone:client:CustomNotification', 39 | 'DOCUMENTS', 40 | 'New Document', 41 | 'fas fa-folder', 42 | '#d9d9d9', 43 | 5000 44 | ) 45 | 46 | SendNUIMessage({ 47 | action = "DocumentSent", 48 | DocumentSend = { 49 | title = data.Title, 50 | text = data.Text, 51 | }, 52 | }) 53 | end 54 | end 55 | end) 56 | 57 | RegisterNUICallback('GetNote_for_Documents_app', function(_, cb) 58 | cb(PhoneData.Documents) 59 | end) 60 | 61 | RegisterNetEvent('qb-phone:RefReshNotes_Free_Documents', function(notes) 62 | PhoneData.Documents = notes 63 | SendNUIMessage({ 64 | action = "DocumentRefresh", 65 | }) 66 | end) -------------------------------------------------------------------------------- /qb-phone/server/betting.lua: -------------------------------------------------------------------------------- 1 | local CasinoTable = {} 2 | local BetNumber = 0 3 | 4 | RegisterNetEvent('qb-phone:server:CasinoAddBet', function(data) 5 | BetNumber += 1 6 | CasinoTable[BetNumber] = {['Name'] = data.name, ['chanse'] = data.chanse, ['id'] = BetNumber} 7 | TriggerClientEvent('qb-phone:client:addbetForAll', -1, CasinoTable) 8 | end) 9 | 10 | local CasinoBetList = {} 11 | local casino_status = true 12 | 13 | RegisterNetEvent('qb-phone:server:BettingAddToTable', function(data) 14 | local src = source 15 | local Player = QBCore.Functions.GetPlayer(src) 16 | local amount = tonumber(data.amount) 17 | local CSN = Player.PlayerData.citizenid 18 | if casino_status then 19 | if Player.PlayerData.money.bank >= amount then 20 | if not CasinoBetList[CSN] then 21 | Player.Functions.RemoveMoney('bank', amount, "casino betting") 22 | CasinoBetList[CSN] = {['csn'] = CSN, ['amount'] = amount, ['player'] = data.player, ['chanse'] = data.chanse, ['id'] = data.id} 23 | else 24 | TriggerClientEvent('QBCore:Notify', src, "You are already betting...", "error") 25 | end 26 | else 27 | TriggerClientEvent('QBCore:Notify', src, "You do not have enough money!", "error") 28 | end 29 | else 30 | TriggerClientEvent('QBCore:Notify', src, "Betting is not active...", "error") 31 | end 32 | end) 33 | 34 | RegisterNetEvent('qb-phone:server:DeleteAndClearTable', function() 35 | local src = source 36 | CasinoTable = {} 37 | CasinoBetList = {} 38 | BetNumber = 0 39 | TriggerClientEvent('qb-phone:client:addbetForAll', -1, CasinoTable) 40 | TriggerClientEvent('QBCore:Notify', src, "Done", "primary") 41 | end) 42 | 43 | lib.callback.register('qb-phone:server:CheckHasBetTable', function(_) 44 | return CasinoTable 45 | end) 46 | 47 | 48 | RegisterNetEvent('qb-phone:server:casino_status', function() 49 | casino_status = not casino_status 50 | end) 51 | 52 | lib.callback.register('qb-phone:server:CheckHasBetStatus', function(_) 53 | return casino_status 54 | end) 55 | 56 | RegisterNetEvent('qb-phone:server:WineridCasino', function(data) 57 | local Winer = data.id 58 | for _, v in pairs(CasinoBetList) do 59 | if v.id == Winer then 60 | local OtherPly = QBCore.Functions.GetPlayerByCitizenId(v.csn) 61 | if OtherPly then 62 | local amount = v.amount * v.chanse 63 | OtherPly.Functions.AddMoney('bank', tonumber(amount), "Casino Winner") 64 | end 65 | end 66 | end 67 | end) -------------------------------------------------------------------------------- /qb-phone/client/garage.lua: -------------------------------------------------------------------------------- 1 | -- Functions 2 | 3 | local function findVehFromPlateAndLocate(plate) 4 | local gameVehicles = QBCore.Functions.GetVehicles() 5 | for i = 1, #gameVehicles do 6 | local vehicle = gameVehicles[i] 7 | if DoesEntityExist(vehicle) then 8 | if QBCore.Functions.GetPlate(vehicle) == plate then 9 | local vehCoords = GetEntityCoords(vehicle) 10 | SetNewWaypoint(vehCoords.x, vehCoords.y) 11 | return true 12 | end 13 | end 14 | end 15 | end 16 | 17 | -- NUI Callback 18 | 19 | RegisterNUICallback('SetupGarageVehicles', function(_, cb) 20 | local vehicles = lib.callback.await('qb-phone:server:GetGarageVehicles', false) 21 | cb(vehicles) 22 | cb(PhoneData.GarageVehicles) 23 | end) 24 | 25 | RegisterNUICallback('gps-vehicle-garage', function(data, cb) 26 | local veh = data.veh 27 | if Config.Garage == 'jdev' then 28 | exports['qb-garages']:TrackVehicleByPlate(veh.plate) 29 | TriggerEvent('qb-phone:client:CustomNotification', 30 | "GARAGE", 31 | "GPS Marker Set!", 32 | "fas fa-car", 33 | "#e84118", 34 | 5000 35 | ) 36 | cb("ok") 37 | elseif Config.Garage == 'qbcore' then 38 | --Deprecated 39 | if veh.state == 'In' then 40 | if veh.parkingspot then 41 | SetNewWaypoint(veh.parkingspot.x, veh.parkingspot.y) 42 | QBCore.Functions.Notify("Your vehicle has been marked", "success") 43 | end 44 | elseif veh.state == 'Out' and findVehFromPlateAndLocate(veh.plate) then 45 | QBCore.Functions.Notify("Your vehicle has been marked", "success") 46 | else 47 | QBCore.Functions.Notify("This vehicle cannot be located", "error") 48 | end 49 | cb("ok") 50 | end 51 | end) 52 | 53 | RegisterNUICallback('sellVehicle', function(data, cb) 54 | TriggerServerEvent('qb-phone:server:sendVehicleRequest', data) 55 | cb("ok") 56 | end) 57 | 58 | -- Events 59 | 60 | RegisterNetEvent('qb-phone:client:sendVehicleRequest', function(data, seller) 61 | local success = exports['qb-phone']:PhoneNotification("VEHICLE SALE", 'Purchase '..data.plate..' for $'..data.price, 'fas fa-map-pin', '#b3e0f2', "NONE", 'fas fa-check-circle', 'fas fa-times-circle') 62 | if success then 63 | TriggerServerEvent("qb-phone:server:sellVehicle", data, seller, 'accepted') 64 | else 65 | TriggerServerEvent("qb-phone:server:sellVehicle", data, seller, 'denied') 66 | end 67 | end) 68 | 69 | RegisterNetEvent('qb-phone:client:updateGarages', function() 70 | SendNUIMessage({ 71 | action = "UpdateGarages", 72 | }) 73 | end) 74 | -------------------------------------------------------------------------------- /qb-phone/html/js/lsbn.js: -------------------------------------------------------------------------------- 1 | 2 | LoadLSBNEvent = function() { 3 | var PlayerJob = QB.Phone.Data.PlayerData.job.name; 4 | if (PlayerJob == "reporter"){ 5 | $(".lsbn-send-news-for-chat").css({"display":"block"}); 6 | } else { 7 | $(".lsbn-send-news-for-chat").css({"display":"none"}); 8 | } 9 | 10 | $(".lsbn-list").html(""); 11 | $.post('https://qb-phone/GetLSBNchats', JSON.stringify({})); 12 | } 13 | 14 | $(document).on('click', '.lsbn-send-news-for-chat', function(e){ 15 | e.preventDefault(); 16 | ClearInputNew() 17 | $('#lsbn-box-new-add-text').fadeIn(350); 18 | }); 19 | 20 | $(document).on('click', '#lsbn-submit-to-send-text', function(e){ 21 | e.preventDefault(); 22 | 23 | var Text = $(".lsbn-input-yek").val(); 24 | var Image = $(".lsbn-input-doo").val(); 25 | var date = new Date(); 26 | var Times = date.getDay()+" "+MonthFormatting[date.getMonth()]+" "+date.getHours()+":"+date.getMinutes(); 27 | 28 | if((Text && Image) != ""){ 29 | $.post('https://qb-phone/Send_lsbn_ToChat', JSON.stringify({ 30 | Type: "Image", 31 | Text: Text, 32 | Image: Image, 33 | Time: Times, 34 | })); 35 | ClearInputNew() 36 | $('#lsbn-box-new-add-text').fadeOut(350); 37 | }else if (Text != ""){ 38 | $.post('https://qb-phone/Send_lsbn_ToChat', JSON.stringify({ 39 | Type: "Text", 40 | Text: Text, 41 | Time: Times, 42 | })); 43 | ClearInputNew() 44 | $('#lsbn-box-new-add-text').fadeOut(350); 45 | } 46 | }); 47 | 48 | $(document).ready(function(){ 49 | window.addEventListener('message', function(event) { 50 | switch(event.data.action) { 51 | case "AddNews": 52 | AddNewsLSBN(event.data.data) 53 | break; 54 | } 55 | }) 56 | }); 57 | 58 | 59 | AddNewsLSBN = function(data) { 60 | for (const [k, v] of Object.entries(data)) { 61 | if(v.Type == "Text"){ 62 | var AddOption = '
'+v.Text+ 63 | '
'+v.Time+'
' 64 | '
'; 65 | 66 | $('.lsbn-list').prepend(AddOption); 67 | }else if(v.Type == "Image"){ 68 | var AddOption = '
'+ 69 | ''+ 70 | '
'+v.Text+'
'+ 71 | '
'+v.Time+'
'+ 72 | '
'; 73 | 74 | $('.lsbn-list').prepend(AddOption); 75 | } 76 | } 77 | } 78 | 79 | $(document).on('click','.lsbn-chat-to-image-style', function (){ 80 | let source = $(this).attr('src') 81 | QB.Screen.popUp(source); 82 | }); -------------------------------------------------------------------------------- /qb-phone/html/js/gopro.js: -------------------------------------------------------------------------------- 1 | let cam 2 | 3 | // Functions 4 | 5 | function ConfirmationFrame() { 6 | $('.spinner-input-frame').css("display", "flex"); 7 | setTimeout(function () { 8 | $('.spinner-input-frame').css("display", "none"); 9 | $('.checkmark-input-frame').css("display", "flex"); 10 | setTimeout(function () { 11 | $('.checkmark-input-frame').css("display", "none"); 12 | }, 2000) 13 | }, 1000) 14 | } 15 | 16 | SetupGoPros = function(cams) { 17 | $(".gopro-lists").html(""); 18 | if (JSON.stringify(cams) != "[]"){ 19 | $.each(cams, function(i, cams){ 20 | var Element = '
'+cams.name+'
'; 21 | $(".gopro-lists").append(Element); 22 | }); 23 | }else{ 24 | $(".gopro-lists").html('

Nothing Here!

'); 25 | } 26 | } 27 | 28 | // Search Bar Filter 29 | 30 | $(document).ready(function(){ 31 | $("#gopro-search").on("keyup", function() { 32 | var value = $(this).val().toLowerCase(); 33 | $(".gopro-list").filter(function() { 34 | $(this).toggle($(this).text().toLowerCase().indexOf(value) > -1); 35 | }); 36 | }); 37 | }); 38 | 39 | // On Clicks 40 | 41 | $(document).on('click', '#gopro-view-camera', function(e){ 42 | e.preventDefault(); 43 | cam = $(this).data('id') 44 | $.post("https://qb-phone/gopro-viewcam", JSON.stringify({ 45 | id: cam, 46 | })); 47 | }); 48 | 49 | $(document).on('click', '#gopro-track-camera', function(e){ 50 | e.preventDefault(); 51 | cam = $(this).data('id') 52 | $.post("https://qb-phone/gopro-track", JSON.stringify({ 53 | id: cam, 54 | })); 55 | }); 56 | 57 | $(document).on('click', '#gopro-addto-camera', function(e){ 58 | e.preventDefault(); 59 | ClearInputNew() 60 | cam = $(this).data('id') 61 | $('#gopro-access-menu').fadeIn(350); 62 | }); 63 | 64 | $(document).on('click', '#gopro-send-access', function(e){ 65 | e.preventDefault(); 66 | var stateid = $(".gopro-stateid-access").val(); 67 | if(stateid != ""){ 68 | setTimeout(function(){ 69 | ConfirmationFrame() 70 | }, 150); 71 | $.post("https://qb-phone/gopro-transfer", JSON.stringify({ 72 | id: cam, 73 | stateid: stateid, 74 | })); 75 | } 76 | ClearInputNew() 77 | $('#gopro-access-menu').fadeOut(350); 78 | }); 79 | -------------------------------------------------------------------------------- /qb-phone/html/js/details.js: -------------------------------------------------------------------------------- 1 | function numberWithCommas(num) { 2 | return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ','); 3 | } 4 | 5 | function LoadPlayerMoneys(){ 6 | var PlayerPhoneNumber = QB.Phone.Data.PlayerData.charinfo.phone; 7 | var PlayerBankAcc = QB.Phone.Data.PlayerData.charinfo.account; 8 | var PlayerBankMoney = QB.Phone.Data.PlayerData.money.bank; 9 | var PlayerCashMoney = QB.Phone.Data.PlayerData.money.cash; 10 | var PlayerCasinoMoney = QB.Phone.Data.PlayerData.money.casino; 11 | var PlayerStateID = QB.Phone.Data.PlayerData.citizenid; 12 | 13 | // $(".details-phone").html(formatPhoneNumber(PlayerPhoneNumber)) 14 | // $(".details-bankserial").html(PlayerBankAcc) 15 | // $(".details-bankmoney").html("$"+numberWithCommas(PlayerBankMoney)) 16 | // $(".details-cashmoney").html("$"+numberWithCommas(PlayerCashMoney)) 17 | // $(".details-casinomoney").html("$"+numberWithCommas(PlayerCasinoMoney)) 18 | // $(".details-stateid").html(PlayerStateID) 19 | $(".details-phone").html(formatPhoneNumber(PlayerPhoneNumber)) 20 | $(".details-bankserial").html(PlayerBankAcc) 21 | $(".details-bankmoney").html("$"+(PlayerBankMoney)) 22 | $(".details-cashmoney").html("$"+(PlayerCashMoney)) 23 | $(".details-casinomoney").html("$"+(PlayerCasinoMoney)) 24 | $(".details-stateid").html(PlayerStateID) 25 | 26 | var PlayerLicenses = QB.Phone.Data.PlayerData.metadata.licences; 27 | 28 | $(".details-license-body-main").html(""); 29 | // var AddOption0 = '
Licenses
' 30 | // $('.details-list').append(AddOption0); 31 | for (const [k, v] of Object.entries(PlayerLicenses)) { 32 | if (v){ 33 | var firstLetter = k.substring(0, 1); 34 | var Fulltext = firstLetter.toUpperCase()+k.replace(firstLetter,'')+" License" 35 | 36 | var AddOption = '
'+ 37 | '
'+Fulltext+'
'+ 38 | '
Valid
'+ 39 | '
' 40 | $('.details-license-body-main').append(AddOption); 41 | } 42 | } 43 | } 44 | 45 | 46 | function formatPhoneNumber(phoneNumber) { 47 | // Remove any non-numeric characters from the phone number 48 | var cleaned = ('' + phoneNumber).replace(/\D/g, ''); 49 | 50 | // Check if the number is empty 51 | if (cleaned === '') { 52 | return ''; 53 | } 54 | 55 | // Format the number as (XXX)-XXX-XXXX 56 | var formatted = cleaned.match(/^(\d{3})(\d{3})(\d{4})$/); 57 | 58 | // If the format doesn't match, return the original number 59 | if (formatted === null) { 60 | return phoneNumber; 61 | } 62 | 63 | // Otherwise, return the formatted number 64 | return '(' + formatted[1] + ')-' + formatted[2] + '-' + formatted[3]; 65 | } -------------------------------------------------------------------------------- /qb-phone/server/whatsapp.lua: -------------------------------------------------------------------------------- 1 | RegisterNetEvent('qb-phone:server:UpdateMessages', function(ChatMessages, ChatNumber) 2 | if not ChatNumber or not ChatMessages then return end 3 | 4 | local src = source 5 | local SenderData = QBCore.Functions.GetPlayer(src) 6 | local TargetData = QBCore.Functions.GetPlayerByPhone(ChatNumber) 7 | 8 | if TargetData then 9 | local Chat = MySQL.query.await('SELECT * FROM phone_messages WHERE citizenid = ? AND number = ?', {SenderData.PlayerData.citizenid, ChatNumber}) 10 | if Chat[1] then 11 | MySQL.update('UPDATE phone_messages SET messages = ? WHERE citizenid = ? AND number = ?', {json.encode(ChatMessages), TargetData.PlayerData.citizenid, SenderData.PlayerData.charinfo.phone}) 12 | MySQL.update('UPDATE phone_messages SET messages = ? WHERE citizenid = ? AND number = ?', {json.encode(ChatMessages), SenderData.PlayerData.citizenid, TargetData.PlayerData.charinfo.phone}) 13 | TriggerClientEvent('qb-phone:client:UpdateMessages', TargetData.PlayerData.source, ChatMessages, SenderData.PlayerData.charinfo.phone, false) 14 | else 15 | MySQL.insert('INSERT INTO phone_messages (citizenid, number, messages) VALUES (?, ?, ?)', {TargetData.PlayerData.citizenid, SenderData.PlayerData.charinfo.phone, json.encode(ChatMessages)}) 16 | MySQL.insert('INSERT INTO phone_messages (citizenid, number, messages) VALUES (?, ?, ?)', {SenderData.PlayerData.citizenid, TargetData.PlayerData.charinfo.phone, json.encode(ChatMessages)}) 17 | TriggerClientEvent('qb-phone:client:UpdateMessages', TargetData.PlayerData.source, ChatMessages, SenderData.PlayerData.charinfo.phone, true) 18 | end 19 | else 20 | local query = '%' .. ChatNumber .. '%' 21 | local Player = MySQL.query.await('SELECT * FROM players WHERE charinfo LIKE ?', {query}) 22 | local Chat = MySQL.query.await('SELECT * FROM phone_messages WHERE citizenid = ? AND number = ?', {SenderData.PlayerData.citizenid, ChatNumber}) 23 | if Chat[1] and Player[1] then 24 | MySQL.update('UPDATE phone_messages SET messages = ? WHERE citizenid = ? AND number = ?', {json.encode(ChatMessages), Player[1].citizenid, SenderData.PlayerData.charinfo.phone}) 25 | Player[1].charinfo = json.decode(Player[1].charinfo) 26 | MySQL.update('UPDATE phone_messages SET messages = ? WHERE citizenid = ? AND number = ?', {json.encode(ChatMessages), SenderData.PlayerData.citizenid, Player[1].charinfo.phone}) 27 | elseif Player[1] then 28 | MySQL.insert('INSERT INTO phone_messages (citizenid, number, messages) VALUES (?, ?, ?)', {Player[1].citizenid, SenderData.PlayerData.charinfo.phone, json.encode(ChatMessages)}) 29 | Player[1].charinfo = json.decode(Player[1].charinfo) 30 | MySQL.insert('INSERT INTO phone_messages (citizenid, number, messages) VALUES (?, ?, ?)', {SenderData.PlayerData.citizenid, Player[1].charinfo.phone, json.encode(ChatMessages)}) 31 | end 32 | end 33 | end) -------------------------------------------------------------------------------- /qb-phone/html/css/calculator.css: -------------------------------------------------------------------------------- 1 | .calculator-app { 2 | display: none; 3 | height: 108%; 4 | width: 100%; 5 | background: linear-gradient(158deg, rgba(24,25,46,1) 0%, rgba(15,18,27,1) 32%, rgba(24,25,46,1) 68%, rgba(15,18,27,1) 100%); 6 | overflow: hidden; 7 | } 8 | 9 | .calculator-header { 10 | position: absolute; 11 | width: 100%; 12 | height: 8vh; 13 | background-color: transparent; 14 | top: 0; 15 | color: white; 16 | font-family: 'Gilroy'; 17 | font-size: 1.8vh; 18 | } 19 | 20 | .calculator-header > p { 21 | line-height: 12vh; 22 | text-indent: 2vh; 23 | } 24 | 25 | 26 | .calculator-list { 27 | position: absolute; 28 | background-color: transparent; 29 | width: 100%; 30 | height: 85%; 31 | 32 | margin: 0 auto; 33 | left: 0; 34 | right: 0; 35 | bottom: 0; 36 | 37 | border-radius: .5vh; 38 | 39 | overflow-y: scroll; 40 | } 41 | 42 | .calculator-list::-webkit-scrollbar { 43 | display: none; 44 | } 45 | 46 | 47 | 48 | form{ 49 | width: 92%; 50 | position: relative; 51 | top: 45%; 52 | left: 5%; 53 | transform: translate(-1%, -50%); 54 | } 55 | input[name="display"]{ 56 | background: rgb(39, 39, 39); 57 | color: #fff; 58 | font-size: 4.5vh; 59 | height: 10vh; 60 | text-align: left; 61 | margin: 4vh 0.5vh; 62 | width: calc(100% - 10px); 63 | border: none; 64 | padding: 0 1vh; 65 | } 66 | input[type="button"]{ 67 | font-size: 2vh; 68 | float: left; 69 | width: calc(100% / 4 - 0.6vh); 70 | background: #fff; 71 | background-image: linear-gradient(#fff, rgb(189, 189, 189)); 72 | text-align: center; 73 | padding: 1vh; 74 | margin: 0 0 0.45vh 0.45vh; 75 | border: none; 76 | transition: 0.25s; 77 | border-radius: 5px; 78 | } 79 | input[type="button"]:hover{ 80 | background: rgb(121, 121, 121); 81 | background-image: linear-gradient(rgb(121, 121, 121), rgb(87, 87, 87)); 82 | } 83 | input[type="button"]:nth-last-of-type(1){ 84 | background: yellow; 85 | background-image: linear-gradient(yellow, rgb(163, 163, 2)); 86 | width: calc(50% - 0.7vh); 87 | transition: 0.25s; 88 | } 89 | input[type="button"]:nth-last-of-type(1):hover{ 90 | background: rgb(204, 204, 4); 91 | background-image: linear-gradient(rgb(204, 204, 4), rgb(167, 167, 1)); 92 | } 93 | 94 | #minishalhcalc{ 95 | background: rgb(241, 126, 18); 96 | background-image: linear-gradient(rgb(241, 126, 18), rgb(202, 106, 16)); 97 | color: #fff; 98 | transition: 0.25s; 99 | } 100 | #minishalhcalc:hover{ 101 | background: rgb(204, 102, 6); 102 | background-image: linear-gradient(rgb(204, 102, 6), rgb(174, 86, 4)); 103 | } 104 | #shakhescalc{ 105 | background: rgb(191, 191, 191); 106 | background-image: linear-gradient(rgb(191, 191, 191), rgb(153, 153, 153)); 107 | transition: 0.25s; 108 | } 109 | #shakhescalc:hover{ 110 | background: rgb(121, 121, 121); 111 | background-image: linear-gradient(rgb(121, 121, 121), rgb(90, 90, 90)); 112 | } 113 | 114 | .calc-icon{ 115 | margin-left: -0.1vh; 116 | width: 4.8vh; 117 | } -------------------------------------------------------------------------------- /qb-phone/html/css/ping.css: -------------------------------------------------------------------------------- 1 | @import "https://assets.nopixel.net/web/fonts/gilroy/stylesheet.css"; 2 | 3 | .ping-app { 4 | display: none; 5 | height: 108%; 6 | width: 100%; 7 | overflow: hidden; 8 | background: linear-gradient(158deg, rgba(24,25,46,1) 0%, rgba(15,18,27,1) 32%, rgba(24,25,46,1) 68%, rgba(15,18,27,1) 100%); 9 | } 10 | 11 | .ping-header { 12 | position: absolute; 13 | width: 90%; 14 | height: 35%; 15 | top: 8%; 16 | left: 0; 17 | right: 0; 18 | color: white; 19 | font-size: 1.8vh; 20 | margin: 0 auto; 21 | } 22 | 23 | .erpinger { 24 | position: absolute; 25 | width: 175%; 26 | margin: 0 auto; 27 | left: -9.7vh; 28 | right: 6vh; 29 | top: -6.5vh; 30 | } 31 | 32 | .ping-header > p { 33 | line-height: 12vh; 34 | text-indent: 2vh; 35 | margin: 0 0 0 9vh; 36 | } 37 | 38 | .ping-header > span { 39 | position: absolute; 40 | top: 8vh; 41 | left: 9vh; 42 | font-size: 1.2vh; 43 | height: 2vh; 44 | color: white; 45 | } 46 | 47 | .ping-list { 48 | position: absolute; 49 | width: 98%; 50 | height: 100%; 51 | margin: 0 auto; 52 | left: 0; 53 | right: 0; 54 | /* bottom: 3%; */ 55 | border-radius: .5vh; 56 | overflow-y: scroll; 57 | } 58 | 59 | .ping-list::-webkit-scrollbar { 60 | display: none; 61 | } 62 | 63 | 64 | .imagepingapp{ 65 | width: 100%; 66 | height: 100%; 67 | } 68 | 69 | .channel { 70 | position: absolute; 71 | width: 100%; 72 | top: 20%; 73 | font-size: 2vh; 74 | background: none; 75 | -moz-user-select: -moz-none; 76 | -khtml-user-select: none; 77 | -webkit-user-select: none; 78 | -o-user-select: none; 79 | user-select: none; 80 | z-index: 1; 81 | color: whitesmoke; 82 | } 83 | 84 | 85 | .ping-sender-piinger{ 86 | display: block; 87 | height: 4.5vh; 88 | width: 80%; 89 | top: 1.5vh; 90 | text-align: center; 91 | margin-left: 10%; 92 | background: rgb(49,71,94); 93 | border-radius: 4px; 94 | box-shadow: 1px 1px 6px rgb(5, 5, 5); 95 | text-shadow: 1px 1px 3px rgb(5, 5, 5); 96 | transition: 0.3s; 97 | padding: 8px; 98 | } 99 | 100 | .ping-sender-piinger > i{ 101 | margin-right: 2.5vh; 102 | } 103 | 104 | .ping-sender-piinger:hover{ 105 | background: rgb(37, 68, 111); 106 | } 107 | 108 | .ping-menu-text{ 109 | position: relative; 110 | top: 2.2vh; 111 | margin-left: 20%; 112 | margin-bottom: 20%; 113 | width: 55%; 114 | border: none; 115 | background: none; 116 | outline: none; 117 | text-indent: 3vh; 118 | text-align: left; 119 | line-height: 3.0vh; 120 | font-size: 1.45vh; 121 | overflow: hidden; 122 | color: white; 123 | border-bottom: .1vh solid #fff; 124 | transition: 0.25s; 125 | } 126 | 127 | #ping-menu-icon{ 128 | position: relative; 129 | top: 2.2vh; 130 | right: 13.7vh; 131 | font-size: 1.4vh; 132 | color: white; 133 | } 134 | 135 | .ping-menu-title{ 136 | position: relative; 137 | bottom: 0.2vh; 138 | right: 15.4vh; 139 | font-size: 1.1vh; 140 | color: white; 141 | } -------------------------------------------------------------------------------- /qb-phone/html/js/garage.js: -------------------------------------------------------------------------------- 1 | let veh 2 | let plate 3 | 4 | $(document).ready(function(){ 5 | $("#garage-search").on("keyup", function() { 6 | var value = $(this).val().toLowerCase(); 7 | $(".garage-vehicle").filter(function() { 8 | $(this).toggle($(this).text().toLowerCase().indexOf(value) > -1); 9 | }); 10 | }); 11 | }); 12 | 13 | $(document).on('click', '.garage-vehicle', function(e){ 14 | e.preventDefault(); 15 | 16 | $(this).find(".garage-block").toggle(); 17 | var Id = $(this).attr('id'); 18 | var VehData = $("#"+Id).data('VehicleData'); 19 | veh = VehData 20 | }); 21 | 22 | 23 | $(document).on('click', '.box-track', function(e){ 24 | e.preventDefault() 25 | $.post("https://qb-phone/gps-vehicle-garage", JSON.stringify({ 26 | veh: veh, 27 | })); 28 | }); 29 | 30 | $(document).on('click', '.box-sellvehicle', function(e){ 31 | e.preventDefault() 32 | plate = $(this).parent().attr('id'); 33 | $('#garage-sellvehicle-menu').fadeIn(350); 34 | }); 35 | 36 | $(document).on('click', '#garage-sellvehicle', function(e){ 37 | e.preventDefault(); 38 | var stateid = $(".garage-sellvehicle-stateid").val(); 39 | var price = $(".garage-sellvehicle-price").val(); 40 | if(price != "" && stateid != ""){ 41 | $.post("https://qb-phone/sellVehicle", JSON.stringify({ 42 | plate: plate, 43 | id: stateid, 44 | price: price 45 | })); 46 | } 47 | ClearInputNew() 48 | $('#garage-sellvehicle-menu').fadeOut(350); 49 | }); 50 | 51 | SetupGarageVehicles = function(Vehicles) { 52 | $(".garage-vehicles").html(""); 53 | if (Vehicles != null) { 54 | $.each(Vehicles, function(i, vehicle){ 55 | var Element = 56 | '
'+vehicle.fullname+' '+vehicle.plate+' '+vehicle.state+'' + 57 | '
' + 58 | '
'+vehicle.garage+'
' + 59 | '
'+vehicle.plate+'
' + 60 | '
'+vehicle.fuel+'
' + 61 | '
'+vehicle.engine + " %"+'
' + 62 | '
'+vehicle.body+ " %"+'
' + 63 | '
'+vehicle.paymentsleft+' Payments Left
' + 64 | '
TRACKSELL
' + 65 | '
' + 66 | '
'; 67 | 68 | $(".garage-vehicles").append(Element); 69 | $("#vehicle-"+i).data('VehicleData', vehicle); 70 | }); 71 | } 72 | } -------------------------------------------------------------------------------- /qb-phone/html/css/casino.css: -------------------------------------------------------------------------------- 1 | @import "https://assets.nopixel.net/web/fonts/gilroy/stylesheet.css"; 2 | 3 | .casino-app { 4 | display: none; 5 | height: 108%; 6 | width: 100%; 7 | overflow: hidden; 8 | background: linear-gradient(158deg, rgba(24,25,46,1) 0%, rgba(15,18,27,1) 32%, rgba(24,25,46,1) 68%, rgba(15,18,27,1) 100%); 9 | } 10 | 11 | .casino-header { 12 | position: absolute; 13 | width: 90%; 14 | height: 10%; 15 | top: 8%; 16 | left: 0; 17 | right: 0; 18 | color: white; 19 | font-size: 1.8vh; 20 | margin: 0 auto; 21 | } 22 | 23 | .casino-header > p { 24 | line-height: 12vh; 25 | text-indent: 2vh; 26 | margin: 0 0 0 9vh; 27 | } 28 | 29 | .casino-header > span { 30 | position: absolute; 31 | top: 8vh; 32 | left: 9vh; 33 | font-size: 1.2vh; 34 | height: 2vh; 35 | color: white; 36 | } 37 | 38 | .casino-list { 39 | position: absolute; 40 | width: 90%; 41 | height: 80%; 42 | margin: 0 auto; 43 | left: 0; 44 | right: 0; 45 | bottom: 3%; 46 | border-radius: .5vh; 47 | overflow-y: scroll; 48 | } 49 | 50 | .casino-list::-webkit-scrollbar { 51 | display: none; 52 | } 53 | 54 | .casino-dashboard-boss{ 55 | display: none; 56 | position: relative; 57 | left: 80%; 58 | width: 15%; 59 | background: #2c465f; 60 | color: whitesmoke; 61 | text-align: center; 62 | border-radius: 4px; 63 | box-shadow: 0rem 0rem 0.2rem 0.02rem #000000a6; 64 | transition: 0.2s; 65 | } 66 | .casino-dashboard-boss:hover{ 67 | background: #0d1218c0; 68 | } 69 | 70 | .casino-dashboard-btn{ 71 | width: 86%; 72 | margin-left: 6.5%; 73 | margin-bottom: 3%; 74 | color: whitesmoke; 75 | background: #0d1218c0; 76 | text-align: center; 77 | border-radius: 4px; 78 | transition: 0.2s; 79 | } 80 | .casino-dashboard-btn:hover{ 81 | background: #0d1218; 82 | } 83 | 84 | 85 | 86 | .casino-license-body-main{ 87 | display: block; 88 | width: 95%; 89 | margin-left: 1.8%; 90 | padding-left: 2%; 91 | margin-bottom: 2%; 92 | color: whitesmoke; 93 | border-radius: 4px; 94 | background: #2c465f; 95 | transition: 0.2s; 96 | font-size: 130%; 97 | } 98 | .casino-license-body-main:hover{ 99 | background: #0d1218c0; 100 | } 101 | 102 | .casino-license-icon-class{ 103 | display: inline; 104 | text-align: right; 105 | width: 10%; 106 | } 107 | .casino-license-text-class{ 108 | display: inline-block; 109 | width: 85%; 110 | } 111 | 112 | #casino-click-beting{ 113 | color: #8ee074; 114 | transition: 0.2s; 115 | } 116 | #casino-click-beting:hover{ 117 | color: #6cac59; 118 | } 119 | 120 | .casino-info-player{ 121 | width: 86%; 122 | color: whitesmoke; 123 | margin-left: 10%; 124 | margin-bottom: 2%; 125 | } 126 | 127 | #casino-Winer-this{ 128 | background: #8ee074; 129 | transition: 0.2s; 130 | width: 72%; 131 | border-radius: 4px; 132 | color: black; 133 | text-align: center; 134 | } 135 | #casino-Winer-this:hover{ 136 | background: #6cac59; 137 | } 138 | 139 | .casino-text-clear{ 140 | text-align: center; 141 | color: whitesmoke; 142 | } -------------------------------------------------------------------------------- /qb-phone/client/twitter.lua: -------------------------------------------------------------------------------- 1 | -- Functions 2 | 3 | local function escape_str(s) 4 | return s 5 | end 6 | 7 | local function GenerateTweetId() 8 | local tweetId = "TWEET-"..math.random(11111111, 99999999) 9 | return tweetId 10 | end 11 | 12 | -- NUI Callback 13 | 14 | RegisterNUICallback('GetTweets', function(_, cb) 15 | local hasVPN = QBCore.Functions.HasItem(Config.VPNItem) 16 | 17 | cb({ 18 | TweetData = PhoneData.Tweets, 19 | hasVPN = hasVPN, 20 | }) 21 | end) 22 | 23 | RegisterNUICallback('PostNewTweet', function(data, cb) 24 | 25 | local URL 26 | 27 | if data.url ~= "" and string.match(data.url, '[a-z]*://[^ >,;]*') then 28 | URL = data.url 29 | else 30 | URL = "" 31 | end 32 | 33 | local TweetMessage = { 34 | firstName = PhoneData.PlayerData.charinfo.firstname, 35 | lastName = PhoneData.PlayerData.charinfo.lastname, 36 | citizenid = PhoneData.PlayerData.citizenid, 37 | message = escape_str(data.Message):gsub("[%<>\"()\'$]",""), 38 | time = data.Date, 39 | tweetId = GenerateTweetId(), 40 | type = data.type, 41 | url = URL, 42 | showAnonymous = data.anonymous 43 | } 44 | 45 | TriggerServerEvent('qb-phone:server:UpdateTweets', TweetMessage) 46 | cb("ok") 47 | end) 48 | 49 | RegisterNUICallback('DeleteTweet',function(data) 50 | TriggerServerEvent('qb-phone:server:DeleteTweet', data.id) 51 | end) 52 | 53 | RegisterNUICallback('FlagTweet',function(data, cb) 54 | QBCore.Functions.Notify(data.name..' was reported for saying '..data.message, "error") 55 | cb('ok') 56 | end) 57 | 58 | -- Events 59 | 60 | RegisterNetEvent('qb-phone:client:UpdateTweets', function(src, Tweets, delete) 61 | if not PhoneData or not FullyLoaded then return end 62 | PhoneData.Tweets = Tweets 63 | local MyPlayerId = PlayerData.source or -1 64 | 65 | 66 | if delete and src == MyPlayerId then 67 | SendNUIMessage({ 68 | action = "PhoneNotification", 69 | PhoneNotify = { 70 | title = "Twitter", 71 | text = "Tweet deleted!", 72 | icon = "fab fa-twitter", 73 | color = "#1DA1F2", 74 | timeout = 1000, 75 | }, 76 | }) 77 | end 78 | 79 | local hasVPN = QBCore.Functions.HasItem(Config.VPNItem) 80 | 81 | SendNUIMessage({ 82 | action = "UpdateTweets", 83 | Tweets = PhoneData.Tweets, 84 | hasVPN = hasVPN, 85 | }) 86 | 87 | if delete then return end 88 | 89 | local NewTweetData = Tweets[#Tweets] 90 | local newFirst, newLast = NewTweetData.firstName:gsub("[%<>\"()\'$]",""), NewTweetData.lastName:gsub("[%<>\"()\' $]","") 91 | 92 | 93 | if not delete and src == MyPlayerId then return end 94 | 95 | if not delete then 96 | SendNUIMessage({ 97 | action = "PhoneNotification", 98 | PhoneNotify = { 99 | title = "@"..newFirst.." "..newLast, 100 | text = NewTweetData.message:gsub("[%<>\"()\'$]",""), 101 | icon = "fab fa-twitter", 102 | color = "#1DA1F2", 103 | }, 104 | }) 105 | end 106 | end) -------------------------------------------------------------------------------- /qb-phone/html/css/gopro.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css?family=Lato&display=swap'); 2 | 3 | .gopro-icon { 4 | margin-top: .5vh; 5 | width: 3.4vh; 6 | } 7 | 8 | .gopro-app { 9 | display: none; 10 | height: 108%; 11 | width: 100%; 12 | background: linear-gradient(158deg, rgba(24,25,46,1) 0%, rgba(15,18,27,1) 32%, rgba(24,25,46,1) 68%, rgba(15,18,27,1) 100%); 13 | overflow: hidden; 14 | } 15 | 16 | .gopro-app-header { 17 | position: absolute; 18 | height: 9vh; 19 | width: 100%; 20 | text-align: center; 21 | line-height: 13.5vh; 22 | color: white; 23 | font-size: 1.5vh; 24 | } 25 | 26 | .gopro-homescreen { 27 | position: absolute; 28 | height: 108%; 29 | width: 100%; 30 | left: 0vh; 31 | } 32 | 33 | .gopro-lists::-webkit-scrollbar { 34 | display: none; 35 | } 36 | 37 | .gopro-lists { 38 | position: absolute; 39 | width: 90%; 40 | height: 45vh; 41 | margin: 0 auto; 42 | left: 0; 43 | right: 0.0vh; 44 | top: 12vh; 45 | overflow-x: hidden; 46 | overflow-y: scroll; 47 | } 48 | 49 | .gopro-list { 50 | position: relative; 51 | width: 90%; 52 | color: white; 53 | left: 15px; 54 | height: 5.5vh; 55 | margin-bottom: 8px; 56 | background-color: rgb(44, 70, 95); 57 | box-shadow: rgba(0, 0, 0, 0.557) 0rem 0rem 0.1rem 0.01rem; 58 | border-radius: 0.15rem; 59 | border-bottom: 0.1vh solid rgba(245, 245, 245, 0.68); 60 | } 61 | 62 | .gopro-list:hover { 63 | background-color: #15222e; 64 | } 65 | 66 | .gopro-list-icon { 67 | position: absolute; 68 | margin: .7vh; 69 | margin-left: 1.0vh; 70 | text-align: center; 71 | line-height: 3.5vh; 72 | color: white; 73 | font-size: 4.0vh; 74 | } 75 | 76 | .gopro-list-name { 77 | position: absolute; 78 | left: 6.8vh; 79 | color: white; 80 | line-height: 2.7vh; 81 | font-size: 1.35vh; 82 | } 83 | 84 | /* Action Buttons */ 85 | 86 | .gopro-action-buttons { 87 | visibility: hidden; 88 | position: absolute; 89 | height: 108%; 90 | width: 100%; 91 | padding-bottom: 5.1vh; 92 | left: 0; 93 | right: 0; 94 | } 95 | 96 | .gopro-action-buttons > i { 97 | position: relative; 98 | float: left; 99 | margin-left: 1.8vh; 100 | left: 5.5vh; 101 | top: 1.7vh; 102 | font-size: 1.8vh; 103 | color: rgb(255, 255, 255); 104 | text-align: center; 105 | } 106 | 107 | .gopro-action-buttons > i:hover { 108 | color: #2c465f; 109 | } 110 | 111 | .gopro-list:hover .gopro-action-buttons { 112 | background: #0d1218c0; 113 | visibility: visible; 114 | } 115 | 116 | /* Search Bar / Icon */ 117 | 118 | #gopro-search { 119 | display: block; 120 | position: absolute; 121 | background: none; 122 | border: none; 123 | background: none; 124 | top: 6.9vh; 125 | width: 79%; 126 | margin: 0 auto; 127 | left: 0%; 128 | right: 0; 129 | opacity: 1; 130 | height: 2.5vh; 131 | /* border-radius: 1vh; */ 132 | border-bottom: .1vh solid #f5f5f5ad; 133 | /* box-shadow: 0 0 .2vh 0 rgba(0, 0, 0, 0.281); */ 134 | /* font-family: 'Gilroy'; */ 135 | outline: none; 136 | text-indent: 2.5vh; 137 | z-index: 100; 138 | color: whitesmoke; 139 | } 140 | #gopro-search-icon { 141 | position: absolute; 142 | top: 7.5vh; 143 | left: 3.5vh; 144 | font-size: 1.4vh; 145 | color: #FFFFFF; 146 | } -------------------------------------------------------------------------------- /qb-phone/html/css/wenmo.css: -------------------------------------------------------------------------------- 1 | @import "https://assets.nopixel.net/web/fonts/gilroy/stylesheet.css"; 2 | 3 | .wenmo-app { 4 | display: none; 5 | height: 100%; 6 | width: 100%; 7 | overflow: hidden; 8 | background: linear-gradient(158deg, rgba(24,25,46,1) 0%, rgba(15,18,27,1) 32%, rgba(24,25,46,1) 68%, rgba(15,18,27,1) 100%); 9 | } 10 | 11 | .wenmo-header { 12 | position: absolute; 13 | width: 90%; 14 | height: 10%; 15 | left: 6.5%; 16 | right: 0; 17 | color: white; 18 | font-size: 1.8vh; 19 | } 20 | 21 | .wenmo-header > p { 22 | line-height: 12vh; 23 | text-indent: 2vh; 24 | margin: 0 0 0 9vh; 25 | } 26 | 27 | .wenmo-header > span { 28 | position: absolute; 29 | top: 8vh; 30 | left: 9vh; 31 | font-size: 1.2vh; 32 | height: 2vh; 33 | color: white; 34 | } 35 | 36 | .wenmo-list { 37 | position: absolute; 38 | width: 90%; 39 | height: 84%; 40 | margin: 0 auto; 41 | left: 0; 42 | right: 0; 43 | bottom: 3%; 44 | border-radius: .5vh; 45 | overflow-y: scroll; 46 | } 47 | 48 | .wenmo-list::-webkit-scrollbar { 49 | display: none; 50 | } 51 | 52 | 53 | .wenmo-send-money-btn{ 54 | position: absolute; 55 | bottom: 0; 56 | top: 2vh; 57 | right: -1.5vh; 58 | width: 3.5vh; 59 | height: 3.5vh; 60 | margin: 2.2vh; 61 | z-index: 101; 62 | border-radius: 0.5vh; 63 | text-align: center; 64 | transition: .2s; 65 | background: linear-gradient(180deg, rgba(67,120,204,1) 0%, rgba(124,166,241,1) 100%); 66 | } 67 | 68 | .wenmo-send-money-btn:hover{ 69 | color: rgb(187, 187, 187); 70 | } 71 | 72 | .wenmo-send-money-btn > i { 73 | line-height: 3.5vh; 74 | font-size: 2vh; 75 | color: white; 76 | } 77 | 78 | .wenmo-form-style-body{ 79 | margin-bottom: 0.5vh; 80 | padding: 0.8vh 1.5vh; 81 | /* Adjust the padding here */ 82 | border-radius: 0.463vh; 83 | background: rgb(11, 14, 21); 84 | overflow: hidden; 85 | } 86 | 87 | .wenmo-time-class-body{ 88 | display: inline; 89 | float: right; 90 | color: whitesmoke; 91 | } 92 | 93 | .wenmo-input-one{ 94 | display: block; 95 | position: absolute; 96 | background: rgb(11, 14, 21); 97 | border: none; 98 | width: 90%; 99 | margin: 0 auto; 100 | left: -2%; 101 | right: 0; 102 | opacity: 1; 103 | height: auto; 104 | border-radius: 0.5vh; 105 | outline: none; 106 | text-indent: .5vh; 107 | z-index: 100; 108 | color: #FFFFFF; 109 | height: 4vh; 110 | } 111 | .wenmo-input-two{ 112 | display: block; 113 | position: absolute; 114 | background: rgb(11, 14, 21); 115 | border: none; 116 | width: 90%; 117 | margin: 0 auto; 118 | left: -2%; 119 | right: 0; 120 | opacity: 1; 121 | height: auto; 122 | border-radius: 0.5vh; 123 | outline: none; 124 | text-indent: .5vh; 125 | z-index: 100; 126 | color: #FFFFFF; 127 | height: 4vh; 128 | top:8vh; 129 | } 130 | .wenmo-input-three{ 131 | display: block; 132 | position: absolute; 133 | background: rgb(11, 14, 21); 134 | border: none; 135 | width: 90%; 136 | margin: 0 auto; 137 | left: -2%; 138 | right: 0; 139 | opacity: 1; 140 | height: auto; 141 | border-radius: 0.5vh; 142 | outline: none; 143 | text-indent: .5vh; 144 | z-index: 100; 145 | color: #FFFFFF; 146 | height: 4vh; 147 | top:13vh; 148 | } -------------------------------------------------------------------------------- /qb-phone/html/css/mail.css: -------------------------------------------------------------------------------- 1 | @import "https://assets.nopixel.net/web/fonts/gilroy/stylesheet.css"; 2 | 3 | .mail-app { 4 | display: none; 5 | height: 108%; 6 | width: 100%; 7 | background: linear-gradient(158deg, rgba(24,25,46,1) 0%, rgba(15,18,27,1) 32%, rgba(24,25,46,1) 68%, rgba(15,18,27,1) 100%); 8 | overflow: hidden; 9 | } 10 | 11 | .mail-home { 12 | position: relative; 13 | left: 0; 14 | } 15 | 16 | .mail-header { 17 | display: block; 18 | width: 100%; 19 | } 20 | 21 | .mail-list { 22 | position: absolute; 23 | width: 86.0%; 24 | height: 46.5vh; 25 | top: 13vh; 26 | margin: 0 auto; 27 | left: 0; 28 | right: 0; 29 | overflow-y: scroll; 30 | } 31 | 32 | .mail-list::-webkit-scrollbar { 33 | display: none; 34 | } 35 | 36 | .mail { 37 | color: white; 38 | margin-bottom: 0.5vh; 39 | padding: 0.8vh 1.5vh; 40 | /* Adjust the padding here */ 41 | border-radius: 0.463vh; 42 | background: rgb(11, 14, 21); 43 | overflow: hidden; 44 | font-size:1.3vh; 45 | font-family:'Gilroy'; 46 | } 47 | 48 | .mail-sender { 49 | padding-top: 1.8vh; 50 | padding-left: 0.5vh; 51 | font-size: 1.1vh; 52 | color: white; 53 | left: 0.8vh; 54 | } 55 | 56 | .mail-subject { 57 | padding-left: 0.5vh; 58 | font-size: 1.1vh; 59 | color: white; 60 | max-width: 21vh; 61 | width: 21vh; 62 | } 63 | 64 | .mail-message { 65 | padding-left: 0.5vh; 66 | font-size: 1.1vh; 67 | color: white; 68 | max-width: 21vh; 69 | margin-bottom: 7%; 70 | } 71 | 72 | .mail-line { 73 | margin-left: 1.5vh; 74 | margin-right: 1.5vh; 75 | border-bottom: .1vh solid #fff; 76 | } 77 | 78 | .mail-time { 79 | margin-top: 0.7vh; 80 | font-size: 1.15vh; 81 | color: white; 82 | width: 100%; 83 | text-align: center; 84 | } 85 | 86 | #mail-search { 87 | display: block; 88 | position: absolute; 89 | background: rgb(11, 14, 21); 90 | border: 2px solid #34373e; 91 | top: 8vh; 92 | width: 86%; 93 | margin: 0 auto; 94 | left: -2%; 95 | right: 0; 96 | opacity: 1; 97 | height: 4vh; 98 | border-radius: 0.5vh; 99 | outline: none; 100 | text-indent: .8vh; 101 | z-index: 0; 102 | color: #FFFFFF; 103 | } 104 | #mail-search-icon { 105 | float: right; 106 | color: #34373e; 107 | position: absolute; 108 | right: 3.5vh; 109 | top: 8.7vh; 110 | z-index: 1; 111 | background: #1c1f26; 112 | padding: 0.5vh; 113 | border-radius: 0.3vh; 114 | } 115 | 116 | .nomails { 117 | text-align: center; 118 | font-family: 'Gilroy'; 119 | font-size: 1.7vh; 120 | font-weight: bold; 121 | color: #FFFFFF; 122 | line-height: 20vh; 123 | } 124 | 125 | #mail-frown { 126 | position: absolute; 127 | top: 3.5%; 128 | left: 41.5%; 129 | font-size: 275%; 130 | color: #FFFFFF; 131 | } 132 | 133 | .mail-block { 134 | padding: 0 0.3vh; 135 | /*line-height: 5vh;*/ 136 | display: none; 137 | overflow: hidden; 138 | } 139 | 140 | .mail-box { 141 | transition: 0.25s; 142 | border-radius: 0.5vh; 143 | color: white; 144 | font-family: 'Gilroy'; 145 | font-size: 1.1vh; 146 | margin-bottom: 4%; 147 | width:85%; 148 | text-align:center; 149 | } 150 | 151 | .mail-delete{ 152 | background: linear-gradient(0deg, rgb(141, 23, 23) 0%, rgb(155, 19, 19) 50%, rgb(141, 23, 23) 100%); 153 | padding: 4.0%; 154 | } 155 | 156 | .mail-accept{ 157 | background: linear-gradient(0deg, rgba(18,115,92,1) 0%, rgba(15,133,105,1) 50%, rgba(18,115,92,1) 100%); 158 | padding: 4.0%; 159 | } -------------------------------------------------------------------------------- /qb-phone/server/twitter.lua: -------------------------------------------------------------------------------- 1 | Tweets = {} 2 | 3 | -- Events 4 | 5 | CreateThread(function() 6 | local tweetsSelected = MySQL.query.await('SELECT * FROM phone_tweets WHERE `date` > NOW() - INTERVAL ? hour', {Config.TweetDuration}) 7 | Tweets = tweetsSelected 8 | end) 9 | 10 | RegisterNetEvent('qb-phone:server:DeleteTweet', function(tweetId) 11 | local src = source 12 | local CID = QBCore.Functions.GetPlayer(src).PlayerData.citizenid 13 | local delete = false 14 | for i = 1, #Tweets do 15 | if Tweets[i].tweetId == tweetId and Tweets[i].citizenid == CID then 16 | table.remove(Tweets, i) 17 | delete = true 18 | break 19 | end 20 | end 21 | if not delete then return end 22 | TriggerClientEvent('qb-phone:client:UpdateTweets', -1, src, Tweets, true) 23 | end) 24 | 25 | RegisterNetEvent('qb-phone:server:UpdateTweets', function(TweetData) 26 | local src = source 27 | local Player = QBCore.Functions.GetPlayer(src) 28 | local HasVPN = Player.Functions.GetItemByName(Config.VPNItem) 29 | 30 | if (TweetData.showAnonymous and HasVPN) then 31 | TweetData.firstName = "Anonymous" 32 | TweetData.lastName = "" 33 | end 34 | 35 | print(json.encode(TweetData.url)) 36 | MySQL.insert('INSERT INTO phone_tweets (citizenid, firstName, lastName, message, url, tweetid, type) VALUES (?, ?, ?, ?, ?, ?, ?)', { 37 | TweetData.citizenid, 38 | TweetData.firstName:gsub("[%<>\"()\'$]",""), 39 | TweetData.lastName:gsub("[%<>\"()\'$]",""), 40 | TweetData.message:gsub("[%<>\"()\'$]",""), 41 | TweetData.url, 42 | TweetData.tweetId, 43 | TweetData.type, 44 | }, function(id) 45 | if id then 46 | Tweets[#Tweets+1] = { 47 | id = id, 48 | citizenid = TweetData.citizenid, 49 | firstName = TweetData.firstName:gsub("[%<>\"()\'$]",""), 50 | lastName = TweetData.lastName:gsub("[%<>\"()\'$]",""), 51 | message = TweetData.message:gsub("[%<>\"()\'$]",""), 52 | url = TweetData.url, 53 | tweetId =TweetData.tweetId, 54 | type = TweetData.type, 55 | date = os.date('%Y-%m-%d %H:%M:%S') 56 | } 57 | 58 | TriggerClientEvent('qb-phone:client:UpdateTweets', -1, src, Tweets, false) 59 | end 60 | end) 61 | end) 62 | 63 | -- Use this tweet function in different resources I used it in Renewed Fishing script to make the ped tweet close to start of tournaments -- 64 | local function AddNewTweet(TweetData) 65 | local tweetID = TweetData and TweetData.tweetId or "TWEET-"..math.random(11111111, 99999999) 66 | 67 | MySQL.insert('INSERT INTO phone_tweets (citizenid, firstName, lastName, message, url, tweetid, type) VALUES (?, ?, ?, ?, ?, ?, ?)', { 68 | TweetData.citizenid, 69 | TweetData.firstName:gsub("[%<>\"()\'$]",""), 70 | TweetData.lastName:gsub("[%<>\"()\'$]",""), 71 | TweetData.message:gsub("[%<>\"()\'$]",""), 72 | TweetData.url, 73 | tweetID, 74 | TweetData.type or "tweet", 75 | }, function(id) 76 | if id then 77 | Tweets[#Tweets+1] = { 78 | id = id, 79 | citizenid = TweetData.citizenid or "TEMP332", 80 | firstName = TweetData.firstName:gsub("[%<>\"()\'$]",""), 81 | lastName = TweetData.lastName:gsub("[%<>\"()\'$]",""), 82 | message = TweetData.message:gsub("[%<>\"()\'$]",""), 83 | url = TweetData.url or "", 84 | tweetId = tweetID, 85 | type = TweetData.type or "tweet", 86 | date = os.date('%Y-%m-%d %H:%M:%S') 87 | } 88 | 89 | TriggerClientEvent('qb-phone:client:UpdateTweets', -1, 0, Tweets, false) 90 | end 91 | end) 92 | end exports("AddNewTweet", AddNewTweet) -------------------------------------------------------------------------------- /qb-phone/html/js/mail.js: -------------------------------------------------------------------------------- 1 | var OpenedMail = null; 2 | 3 | // Mail APP 4 | 5 | // Search 6 | 7 | $(document).ready(function(){ 8 | $("#mail-search").on("keyup", function() { 9 | var value = $(this).val().toLowerCase(); 10 | $(".mail").filter(function() { 11 | $(this).toggle($(this).text().toLowerCase().indexOf(value) > -1); 12 | }); 13 | }); 14 | }); 15 | 16 | // Functions 17 | 18 | QB.Phone.Functions.SetupMails = function(Mails) { 19 | if (Mails !== null && Mails !== undefined) { 20 | Mails = Mails.reverse(); 21 | if (Mails.length > 0) { 22 | $(".mail-list").html(""); 23 | $.each(Mails, function(i, mail){ 24 | var TimeAgo = moment(mail.date).format('MM/DD/YYYY hh:mm'); 25 | 26 | if (JSON.stringify(mail.button) != "[]"){ 27 | var element = 28 | '
'+ 29 | 'From: '+mail.sender+'' + 30 | '

Subject: '+mail.subject+'

' + 31 | '
' + 32 | '
'+mail.message+'
' + 33 | '
ACCEPTDELETE
' + 34 | '
' + 35 | '
' + 36 | '
'+TimeAgo+'
' + 37 | '
'; 38 | $(".mail-list").append(element); 39 | $("#mail-"+mail.mailid).data('MailData', mail); 40 | }else{ 41 | var element = 42 | '
'+ 43 | 'From: '+mail.sender+'' + 44 | '

Subject: '+mail.subject+'

' + 45 | '
' + 46 | '
'+mail.message+'
' + 47 | '
DELETE
' + 48 | '
' + 49 | '
' + 50 | '
'+TimeAgo+'
' + 51 | '
'; 52 | $(".mail-list").append(element); 53 | $("#mail-"+mail.mailid).data('MailData', mail); 54 | } 55 | }); 56 | } else { 57 | $(".mail-list").html('

Nothing Here!

'); 58 | } 59 | 60 | } 61 | } 62 | 63 | // Clicks 64 | 65 | $(document).on('click', '.mail-accept', function(e){ 66 | e.preventDefault(); 67 | var mailId = $(this).parent().parent().parent().data('mailid'); 68 | var MailData = $("#"+OpenedMail).data('MailData'); 69 | $.post('https://qb-phone/AcceptMailButton', JSON.stringify({ 70 | buttonEvent: MailData.button.buttonEvent, 71 | buttonData: MailData.button.buttonData, 72 | isServer: MailData.button.isServer, 73 | mailId: mailId, 74 | })); 75 | }); 76 | 77 | $(document).on('click', '.mail-delete', function(e){ 78 | e.preventDefault(); 79 | var mailId = $(this).parent().parent().parent().data('mailid'); 80 | $.post('https://qb-phone/RemoveMail', JSON.stringify({ 81 | mailId: mailId 82 | })); 83 | }); 84 | 85 | $(document).on('click', '.mail', function(e){ 86 | e.preventDefault(); 87 | $(this).find(".mail-block").toggle(); 88 | OpenedMail = $(this).attr('id'); 89 | }); -------------------------------------------------------------------------------- /qb-phone/html/css/debt.css: -------------------------------------------------------------------------------- 1 | @import "https://assets.nopixel.net/web/fonts/gilroy/stylesheet.css"; 2 | 3 | .debt-app { 4 | display: none; 5 | height: 108%; 6 | width: 100%; 7 | overflow: hidden; 8 | background: linear-gradient(158deg, rgba(24,25,46,1) 0%, rgba(15,18,27,1) 32%, rgba(24,25,46,1) 68%, rgba(15,18,27,1) 100%); 9 | } 10 | 11 | .debts-header { 12 | position: absolute; 13 | width: 100%; 14 | height: 12vh; 15 | top: 0; 16 | color: white; 17 | /* font-family: 'Gilroy'; */ 18 | font-size: 1.8vh; 19 | } 20 | 21 | .debts-list { 22 | position: absolute; 23 | width: 80.0%; 24 | height: 46.5vh; 25 | top: 10.8vh; 26 | margin: 0 auto; 27 | left: 0; 28 | right: 0; 29 | overflow-y: scroll; 30 | } 31 | 32 | .debts-list::-webkit-scrollbar { 33 | display: none; 34 | } 35 | 36 | .debt-list { 37 | padding: 4px; 38 | width: 100%; 39 | background-color: rgb(44, 70, 95); 40 | border-radius: 4px 4px 0px 0px; 41 | border-bottom: .1vh solid #fff; 42 | margin-bottom: 3.5%; 43 | } 44 | 45 | /* ASSET FEES */ 46 | 47 | .debt-icon { 48 | position: relative; 49 | line-height: 6vh; 50 | left: 0vh; 51 | padding-top: 1.1vh; 52 | padding-bottom: 1.1vh; 53 | padding-left: 1.3vh; 54 | padding-right: 2.6vh; 55 | color: white; 56 | font-size: 4.0vh; 57 | transition: .05s linear; 58 | } 59 | 60 | .debt-main-title { 61 | position: absolute; 62 | left: 6.8vh; 63 | color: white; 64 | line-height: 8.5vh; 65 | font-size: 1.2vh; 66 | } 67 | 68 | .debt-main-fee { 69 | position: absolute; 70 | left: 6.8vh; 71 | color: white; 72 | line-height: 3vh; 73 | font-size: 1.2vh; 74 | } 75 | 76 | .debt-remaining-payments { 77 | position: absolute; 78 | right: 1.0vh; 79 | color: white; 80 | line-height: 8.5vh; 81 | font-size: 1.3vh; 82 | } 83 | 84 | /* Click Block CSS */ 85 | 86 | .debt-block { 87 | padding: 0 18px; 88 | /*line-height: 5vh;*/ 89 | display: none; 90 | overflow: hidden; 91 | background-color: rgb(44, 70, 95); 92 | margin-bottom: 1.4vh; 93 | } 94 | 95 | .debt-title { 96 | padding: 3px 18px; 97 | padding-top: 0.5vh; 98 | padding-left: 0vh; 99 | color: white; 100 | font-size: 1.3vh; 101 | border-bottom: .1vh solid #fff; 102 | } 103 | 104 | .debt-title > i { 105 | padding-right: 0.8vh; 106 | font-size: 1.3vh; 107 | color: white; 108 | } 109 | 110 | .debt-extrainfo { 111 | padding: 3px 18px; 112 | padding-top: 0.5vh; 113 | padding-left: 0vh; 114 | color: white; 115 | font-size: 1.3vh; 116 | border-bottom: .1vh solid #fff; 117 | } 118 | 119 | .debt-extrainfo > i { 120 | padding-right: 0.8vh; 121 | font-size: 1.3vh; 122 | color: white; 123 | } 124 | 125 | .debt-due { 126 | padding: 3px 18px; 127 | padding-top: 0.5vh; 128 | padding-left: 0vh; 129 | color: white; 130 | font-size: 1.3vh; 131 | border-bottom: .1vh solid #fff; 132 | margin-bottom: 7%; 133 | } 134 | 135 | .debt-due > i { 136 | padding-right: 0.8vh; 137 | font-size: 1.3vh; 138 | color: white; 139 | } 140 | 141 | .debt-box { 142 | transition: 0.25s; 143 | border-radius: 5px; 144 | color: black; 145 | font-family: 'Gilroy'; 146 | font-size: 1.1vh; 147 | margin-bottom: 4%; 148 | } 149 | 150 | .send-all-box{ 151 | background:#90e278; 152 | padding: 4.0%; 153 | } 154 | 155 | .send-minimum-box{ 156 | background:#f6a167; 157 | padding: 4.0%; 158 | } 159 | 160 | /* SEARCH SHIT */ 161 | 162 | #debt-search { 163 | display: block; 164 | position: absolute; 165 | background: none; 166 | border: none; 167 | background: none; 168 | top: 6.9vh; 169 | width: 77%; 170 | margin: 0 auto; 171 | left: -2%; 172 | right: 0; 173 | opacity: 1; 174 | height: 2.5vh; 175 | border-bottom: .1vh solid #f5f5f5ad; 176 | outline: none; 177 | text-indent: 2.5vh; 178 | z-index: 100; 179 | color: whitesmoke; 180 | } 181 | #debt-search-icon { 182 | position: absolute; 183 | top: 7.5vh; 184 | left: 3.5vh; 185 | font-size: 1.4vh; 186 | color: #FFFFFF; 187 | } -------------------------------------------------------------------------------- /qb-phone/html/js/taxi.js: -------------------------------------------------------------------------------- 1 | // Functions 2 | 3 | function formatPhoneNumber(phoneNumberString) { 4 | var cleaned = ('' + phoneNumberString).replace(/\D/g, ''); 5 | var match = cleaned.match(/^(\d{3})(\d{3})(\d{4})$/); 6 | if (match) { 7 | return '(' + match[1] + ') ' + match[2] + '-' + match[3]; 8 | } 9 | return phoneNumberString; 10 | } 11 | 12 | SetupTaxiDrivers = function(data) { 13 | $(".taxis-list").html(""); 14 | $.each(data, function(job, jobData) { 15 | $(".taxis-list").append(`

Available Drivers

`); 16 | $.each(jobData.Players, function(i, player) { 17 | $(".taxis-list").append(`
${player.Name}
${formatPhoneNumber(player.Phone)}
`); 18 | }); 19 | 20 | if (jobData.Players.length === 0) { 21 | $(".taxis-list").append('

None Available!

'); 22 | } 23 | $(".taxis-list").append("
"); 24 | }); 25 | } 26 | 27 | // On Click 28 | 29 | $(document).on('click', '.taxi-list-call', function(e){ 30 | e.preventDefault(); 31 | var Number = $(this).parent().attr('id'); 32 | if (Number != undefined){ 33 | var InputNum = Number; 34 | 35 | if (InputNum != ""){ 36 | cData = { 37 | number: InputNum, 38 | name: InputNum, 39 | } 40 | $.post('https://qb-phone/CallContact', JSON.stringify({ 41 | ContactData: cData, 42 | Anonymous: QB.Phone.Data.AnonymousCall, 43 | }), function(status){ 44 | if (cData.number !== QB.Phone.Data.PlayerData.charinfo.phone) { 45 | if (status.IsOnline) { 46 | if (status.CanCall) { 47 | if (!status.InCall) { 48 | $('.phone-new-box-body').fadeOut(350); 49 | ClearInputNew() 50 | $(".phone-call-outgoing").css({"display":"none"}); 51 | $(".phone-call-incoming").css({"display":"none"}); 52 | $(".phone-call-ongoing").css({"display":"none"}); 53 | $(".phone-call-outgoing-caller").html(cData.name); 54 | QB.Phone.Functions.HeaderTextColor("white", 400); 55 | QB.Phone.Animations.TopSlideUp('.phone-application-container', 400, -160); 56 | setTimeout(function(){ 57 | $(".phone-app").css({"display":"none"}); 58 | QB.Phone.Animations.TopSlideDown('.phone-application-container', 400, -160); 59 | QB.Phone.Functions.ToggleApp("phone-call", "block"); 60 | $(".phone-currentcall-container").css({"display":"block"}); 61 | $("#incoming-answer").css({"display":"none"}); 62 | }, 450); 63 | 64 | CallData.name = cData.name; 65 | CallData.number = cData.number; 66 | 67 | QB.Phone.Data.currentApplication = "phone-call"; 68 | } else { 69 | QB.Phone.Notifications.Add("fas fa-phone", "Phone", "You're already in a call!"); 70 | } 71 | } else { 72 | QB.Phone.Notifications.Add("fas fa-phone", "Phone", "This person is busy!"); 73 | } 74 | } else { 75 | QB.Phone.Notifications.Add("fas fa-phone", "Phone", "This person is not available!"); 76 | } 77 | } else { 78 | QB.Phone.Notifications.Add("fas fa-phone", "Phone", "You can't call yourself!"); 79 | } 80 | }); 81 | } 82 | } 83 | }) 84 | -------------------------------------------------------------------------------- /qb-phone/client/groups.lua: -------------------------------------------------------------------------------- 1 | local inJob = false 2 | local GroupBlips = {} 3 | 4 | local function FindBlipByName(name) 5 | for i=1, #GroupBlips do 6 | if GroupBlips[i] and GroupBlips[i].name == name then 7 | return i 8 | end 9 | end 10 | end 11 | 12 | RegisterNetEvent("groups:removeBlip", function(name) 13 | local i = FindBlipByName(name) 14 | if i then 15 | local blip = GroupBlips[i]["blip"] 16 | SetBlipRoute(blip, false) 17 | RemoveBlip(blip) 18 | GroupBlips[i] = nil 19 | end 20 | end) 21 | 22 | RegisterNetEvent('groups:phoneNotification', function(data) 23 | SendNUIMessage({ 24 | action = "PhoneNotification", 25 | PhoneNotify = { 26 | title = data.title, 27 | text = data.text, 28 | icon = data.icon, 29 | color = data.color, 30 | timeout = data.timeout, 31 | }, 32 | }) 33 | end) 34 | 35 | RegisterNetEvent("groups:createBlip", function(name, data) 36 | if not data then return print("Invalid Data was passed to the create blip event") end 37 | 38 | if FindBlipByName(name) then 39 | TriggerEvent("groups:removeBlip", name) 40 | end 41 | 42 | local blip 43 | if data.entity then 44 | blip = AddBlipForEntity(data.entity) 45 | elseif data.netId then 46 | blip = AddBlipForEntity(NetworkGetEntityFromNetworkId(data.netId)) 47 | elseif data.radius then 48 | blip = AddBlipForRadius(data.coords.x, data.coords.y, data.coords.z, data.radius) 49 | else 50 | blip = AddBlipForCoord(data.coords) 51 | end 52 | 53 | if not data.color then data.color = 1 end 54 | if not data.alpha then data.alpha = 255 end 55 | 56 | if not data.radius then 57 | if not data.sprite then data.sprite = 1 end 58 | if not data.scale then data.scale = 0.7 end 59 | if not data.label then data.label = "NO LABEL FOUND" end 60 | 61 | SetBlipSprite(blip, data.sprite) 62 | SetBlipScale(blip, data.scale) 63 | BeginTextCommandSetBlipName("STRING") 64 | AddTextComponentSubstringPlayerName(data.label) 65 | EndTextCommandSetBlipName(blip) 66 | end 67 | 68 | SetBlipColour(blip, data.color) 69 | SetBlipAlpha(blip, data.alpha) 70 | 71 | if data.route then 72 | SetBlipRoute(blip, true) 73 | SetBlipRouteColour(blip, data.routeColor) 74 | end 75 | GroupBlips[#GroupBlips+1] = {name = name, blip = blip} 76 | end) 77 | 78 | RegisterNUICallback('GetGroupsApp', function (_, cb) 79 | local getGroups = lib.callback.await('qb-phone:server:getAllGroups', false) 80 | cb(getGroups) 81 | end) 82 | 83 | RegisterNetEvent('qb-phone:client:RefreshGroupsApp', function(Groups, finish) 84 | if finish then inJob = false end 85 | if inJob then return end 86 | SendNUIMessage({ 87 | action = "refreshApp", 88 | data = Groups, 89 | }) 90 | end) 91 | 92 | 93 | RegisterNetEvent('qb-phone:client:AddGroupStage', function(_, stage) 94 | inJob = true 95 | SendNUIMessage({ 96 | action = "addGroupStage", 97 | status = stage 98 | }) 99 | end) 100 | 101 | 102 | RegisterNUICallback('jobcenter_CreateJobGroup', function(data, cb) --employment 103 | TriggerServerEvent('qb-phone:server:jobcenter_CreateJobGroup', data) 104 | cb("ok") 105 | end) 106 | 107 | RegisterNUICallback('jobcenter_JoinTheGroup', function(data, cb) --employment 108 | TriggerServerEvent('qb-phone:server:jobcenter_JoinTheGroup', data) 109 | cb("ok") 110 | end) 111 | 112 | RegisterNUICallback('jobcenter_leave_grouped', function(data, cb) --employment 113 | if not data then return end 114 | local success = exports['qb-phone']:PhoneNotification("Job Center", 'Are you sure you want to leave the group?', 'fas fa-users', '#FFBF00', "NONE", 'fas fa-check-circle', 'fas fa-times-circle') 115 | if success then 116 | TriggerServerEvent('qb-phone:server:jobcenter_leave_grouped', data) 117 | end 118 | cb("ok") 119 | end) 120 | 121 | RegisterNUICallback('jobcenter_DeleteGroup', function(data, cb) --employment 122 | TriggerServerEvent('qb-phone:server:jobcenter_DeleteGroup', data) 123 | cb("ok") 124 | end) 125 | 126 | 127 | RegisterNUICallback('jobcenter_CheckPlayerNames', function(data, cb) --employment 128 | local HasName = lib.callback.await('qb-phone:server:jobcenter_CheckPlayerNames', false, data.id) 129 | cb(HasName) 130 | end) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### README.md for Renewed Phone customized by Wahyu Adi ("4.0 INSPIRED") 2 | 3 | #### GPL v3 Compliant Distribution Notification 4 | 5 | Welcome to the repository for Renewed-Phone customized by Wahyu Adi, originally customized by [FjamZoo](https://github.com/Renewed-Scripts/qb-phone). This document serves as an official notification and overview of the distribution of this software, which includes modifications made by the previous owner from whom I acquired it. The software is governed under the GNU General Public License version 3 (GPLv3), which is dedicated to protecting the freedoms to use, study, modify, and share software. 6 | 7 | #### Background 8 | 9 | The decision to acquire and subsequently distribute this script was informed by the discovery that the original seller was engaging in the practice of reselling free software at a significant markup, with only minimal changes to the user interface. In response to this, and in keeping with the spirit and legal requirements of the GPLv3, I have taken the initiative to ensure that these modifications, along with the original script, are made freely available. This repository embodies a commitment to the open-source community's principles of transparency, collaboration, and the free distribution of software. 10 | 11 | #### Repository Contents 12 | 13 | Contained within this repository is the complete source code of the script as it was received by me, unaltered from its modified state. This includes both the original code and the modifications introduced by the previous owner. 14 | 15 | #### Our Commitment to Open Source 16 | 17 | By making this modified script accessible on GitHub, we are adhering to the stipulations set forth by the GPLv3, thus ensuring that everyone is granted the freedom to use, modify, and distribute the software. This action is a reflection of our dedication to supporting the open-source ecosystem, fostering a culture of free knowledge exchange, and advancing technology in a manner that is inclusive and equitable. 18 | 19 | #### Reason for Distribution 20 | 21 | It is important to highlight that the catalyst for this distribution was the realization that the original seller was capitalizing on the open-source nature of the software by reselling it at a high price with only minimal user interface enhancements. This practice not only contravenes the ethos of the open-source movement but also undermines the fundamental rights afforded by the GPLv3. By making this software freely available, we aim to rectify this situation and ensure that the software remains accessible to all, in line with the original intentions of its licensing. 22 | 23 | #### Access and Use 24 | 25 | We invite all interested parties to explore, utilize, and contribute to this project. In accordance with the GPLv3, you are empowered to: 26 | 27 | - **Run** the software for any purpose. 28 | - **Study** the source code and modify it according to your needs. 29 | - **Distribute** copies of the original or modified software, thus enabling others to benefit from the same freedoms. 30 | 31 | #### Conclusion 32 | 33 | This README stands as a declaration of our compliance with GPLv3 licensing requirements and our unwavering commitment to the principles of open-source software distribution. Through initiatives like this, we collectively contribute towards a technological future that is open, collaborative, and innovative. 34 | 35 | For detailed information on the GNU General Public License version 3 (GPLv3), please visit [GNU's Official Website](https://www.gnu.org/licenses/gpl-3.0.en.html). 36 | 37 | Your contributions, feedback, and participation in this project are warmly welcomed. Together, we can guarantee that the benefits of technology remain freely accessible to everyone. 38 | 39 | # Keep FiveM Free and Open Source 40 | # Obey the GPL 41 | 42 | **Proof of purchase:** 43 | 44 | ![image](https://github.com/jnccloud/Renewed-Phone-Wahyu-Abi/assets/58707473/7229b745-b945-4e30-9745-b391e2c8b9d2) 45 | ![image](https://github.com/jnccloud/Renewed-Phone-Wahyu-Abi/assets/58707473/a60ae863-fb31-48e2-bda8-98d8407f90c3) 46 | ![image](https://github.com/jnccloud/Renewed-Phone-Wahyu-Abi/assets/58707473/ca81545f-2b3f-487a-837b-d7f5677c9d00) 47 | ![ab2](https://github.com/jnccloud/Renewed-Phone-Wahyu-Abi/assets/58707473/f9a7c7cb-5c89-42a1-8708-24c1277fc686) 48 | ![ab3](https://github.com/jnccloud/Renewed-Phone-Wahyu-Abi/assets/58707473/9cdbef1e-1474-46db-92c4-60fef3dd87e4) 49 | ![ab1](https://github.com/jnccloud/Renewed-Phone-Wahyu-Abi/assets/58707473/520b6179-aba5-4039-a7b6-69eb70696983) 50 | 51 | 52 | **CFX, if you ever look at this, here's a prime example of someone selling FiveM content outside of Tebex.** 53 | -------------------------------------------------------------------------------- /qb-phone/html/css/gallery.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css?family=Lato&display=swap'); 2 | 3 | .gallery-app { 4 | display: none; 5 | height: 108%; 6 | width: 100%; 7 | background: linear-gradient(158deg, rgba(24,25,46,1) 0%, rgba(15,18,27,1) 32%, rgba(24,25,46,1) 68%, rgba(15,18,27,1) 100%); 8 | overflow: hidden; 9 | } 10 | 11 | .gallery-app-header { 12 | position: absolute; 13 | height: 9vh; 14 | width: 100%; 15 | text-align: center; 16 | line-height: 12.5vh; 17 | color: white; 18 | font-size: 1.5vh; 19 | } 20 | 21 | .gallery-homescreen { 22 | position: absolute; 23 | height: 108%; 24 | width: 100%; 25 | left: 0vh; 26 | } 27 | 28 | .gallery-detailscreen { 29 | position: absolute; 30 | height: 108%; 31 | width: 100%; 32 | left: -30vh; 33 | } 34 | .gallery-postscreen { 35 | position: absolute; 36 | height: 108%; 37 | width: 100%; 38 | left: -30vh; 39 | } 40 | 41 | .gallery-images { 42 | position: absolute; 43 | width: 85%; 44 | height: 44.5vh; 45 | top: 10.5vh; 46 | margin: 0 auto; 47 | left: 0; 48 | right: 0; 49 | overflow-y: scroll; 50 | } 51 | 52 | .gallery-images::-webkit-scrollbar { 53 | display: none; 54 | } 55 | 56 | .tumbnail{ 57 | width: 100%; 58 | border-radius: 0.3vh; 59 | } 60 | 61 | .gallery-image { 62 | display: inline-block; 63 | width: 50%; 64 | padding: 0.2vh; 65 | height: 7.1vh; 66 | 67 | } 68 | .gallery-details { 69 | position: absolute; 70 | height: 76%; 71 | width: 84%; 72 | margin: 0 auto; 73 | left: 0vh; 74 | right: 0; 75 | top: 11vh; 76 | } 77 | 78 | 79 | 80 | .return-button { 81 | display: flex; 82 | flex-direction: row; 83 | justify-content: space-between; 84 | } 85 | 86 | .return-button > div { 87 | margin: 2px; 88 | width: 100%; 89 | height: 5vh; 90 | background-color: rgb(233, 233, 233); 91 | border-radius: .3vh; 92 | transition: .05s linear; 93 | text-align: center; 94 | line-height: 5vh; 95 | font-size: 1.4vh; 96 | } 97 | 98 | .return-button > div:hover { 99 | background-color: rgb(212, 212, 212); 100 | } 101 | 102 | .make-post-button { 103 | display: flex; 104 | flex-direction: row; 105 | } 106 | 107 | .make-post-button > div { 108 | margin: 2px; 109 | width: 40%; 110 | height: 5vh; 111 | background-color: #8ee074; 112 | border-radius: .3vh; 113 | transition: .05s linear; 114 | text-align: center; 115 | line-height: 5vh; 116 | font-size: 1.4vh; 117 | } 118 | 119 | .make-post-button > div:hover { 120 | background-color: #6cac59; 121 | } 122 | 123 | #delete-button { 124 | margin: 2px; 125 | width: 20%; 126 | height: 5vh; 127 | background-color: #f5a15b; 128 | border-radius: .3vh; 129 | transition: .05s linear; 130 | text-align: center; 131 | line-height: 5vh; 132 | font-size: 1.4vh; 133 | } 134 | #delete-button:hover { 135 | background-color: #c27e47; 136 | } 137 | 138 | #gallery-coppy-button{ 139 | background: rgb(187, 187, 81); 140 | } 141 | #gallery-coppy-button:hover{ 142 | background: rgb(145, 145, 63); 143 | } 144 | 145 | .posts-button { 146 | display: flex; 147 | flex-direction: row; 148 | justify-content: space-between; 149 | } 150 | 151 | #tweet-button { 152 | margin: 2px; 153 | width: 50%; 154 | height: 5vh; 155 | 156 | color: #151515; 157 | border-radius: .3vh; 158 | transition: .2s linear; 159 | text-align: center; 160 | line-height: 5vh; 161 | font-size: 1.4vh; 162 | background-color: #08a0e9; 163 | 164 | } 165 | #tweet-button:hover { 166 | background-color: #0078a3; 167 | } 168 | 169 | #advert-button { 170 | margin: 2px; 171 | width: 50%; 172 | height: 5vh; 173 | color: #fff; 174 | border-radius: .3vh; 175 | transition: .2s linear; 176 | text-align: center; 177 | line-height: 5vh; 178 | font-size: 1.4vh; 179 | background-color: #ff8f1a; 180 | } 181 | #advert-button:hover { 182 | background-color: #bd7528; 183 | } 184 | 185 | 186 | 187 | #new-textarea { 188 | border: none; 189 | height: 15vh; 190 | margin: 0 auto; 191 | left: 0; 192 | right: 0; 193 | background: none; 194 | outline: none; 195 | border: .1vh solid #f5f5f5ad; 196 | color: whitesmoke; 197 | resize: none; 198 | transition: border-bottom 0.1s ease-in-out; 199 | padding: 0.87vh; 200 | font-size: 1.4vh; 201 | top: 12vh; 202 | width: 100%; 203 | border-radius: 4px; 204 | } -------------------------------------------------------------------------------- /qb-phone/server/invoices.lua: -------------------------------------------------------------------------------- 1 | -- Events 2 | 3 | RegisterNetEvent('qb-phone:server:InvoiceHandler') 4 | 5 | -- EVENT HANDLER(S) -- 6 | 7 | -- Has player paid something this -- 8 | --[[AddEventHandler('qb-phone:server:InvoiceHandler', function(paid, amount, source, resource) 9 | 10 | if paid and resource == GetCurrentResourceName() then 11 | if amount >= config.minPayment then 12 | if Config.RenewedBanking then 13 | local cid = Player.PlayerData.citizenid 14 | local name = ("%s %s"):format(Player.PlayerData.charinfo.firstname, Player.PlayerData.charinfo.lastname) 15 | exports['Renewed-Banking']:handleTransaction(cid, "Phone Invoice", amount, "Paid off phone invoice of $"..amount, name, name, "withdraw") 16 | end 17 | -- Do shit 18 | end 19 | end 20 | end)]] 21 | 22 | RegisterNetEvent('qb-phone:server:PayMyInvoice', function(society, amount, invoiceId, sendercitizenid, resource) 23 | local src = source 24 | local Player = QBCore.Functions.GetPlayer(src) 25 | local SenderPly = QBCore.Functions.GetPlayerByCitizenId(sendercitizenid) 26 | if Player.PlayerData.money.bank >= amount then 27 | Player.Functions.RemoveMoney('bank', amount, "Paid Mobile Invoice") 28 | if SenderPly and Config.BillingCommissions and Config.BillingCommissions[society] then 29 | local commission = math.ceil(amount * Config.BillingCommissions[society]) 30 | SenderPly.Functions.AddMoney('bank', commission, "Invoice Paid") 31 | end 32 | 33 | if SenderPly then 34 | TriggerClientEvent('qb-phone:client:CustomNotification', SenderPly.PlayerData.source, 35 | "Invoice Paid off by " .. SenderPly.PlayerData.charinfo.firstname .. ".", 36 | "Recent Invoice of $" .. amount .. " has been paid.", 37 | "fas fa-file-invoice-dollar", 38 | "#1DA1F2", 39 | 7500 40 | ) 41 | end 42 | 43 | TriggerClientEvent('qb-phone:client:RemoveInvoiceFromTable', src, invoiceId) 44 | TriggerEvent("qb-phone:server:InvoiceHandler", true, amount, src, resource) 45 | 46 | exports.oxmysql:execute('DELETE FROM phone_invoices WHERE id = ?', {invoiceId}) 47 | end 48 | end) 49 | 50 | RegisterNetEvent('qb-phone:server:DeclineMyInvoice', function(amount, invoiceId, sendercitizenid, resource) 51 | local Ply = QBCore.Functions.GetPlayer(source) 52 | local SenderPly = QBCore.Functions.GetPlayerByCitizenId(sendercitizenid) 53 | if not Ply then return end 54 | 55 | exports.oxmysql:execute('DELETE FROM phone_invoices WHERE id = ?', {invoiceId}) 56 | if SenderPly then 57 | TriggerClientEvent('qb-phone:client:CustomNotification', SenderPly.PlayerData.source, 58 | "Invoice Declined by " .. SenderPly.PlayerData.charinfo.firstname .. ".", 59 | "Recent invoice of $" .. amount .. " has been declined.", 60 | "fas fa-file-invoice-dollar", 61 | "#1DA1F2", 62 | 7500 63 | ) 64 | end 65 | 66 | TriggerClientEvent('qb-phone:client:RemoveInvoiceFromTable', source, invoiceId) 67 | TriggerEvent("qb-phone:server:InvoiceHandler", false, amount, source, resource) 68 | end) 69 | 70 | 71 | RegisterNetEvent('qb-phone:server:CreateInvoice', function(billed, biller, amount) 72 | local billedID = tonumber(billed) 73 | local cash = tonumber(amount) 74 | local billedCID = QBCore.Functions.GetPlayer(billedID) 75 | local billerInfo = QBCore.Functions.GetPlayer(biller) 76 | 77 | local resource = GetInvokingResource() 78 | 79 | if not billedID or not cash or not billedCID or not billerInfo then return end 80 | MySQL.Async.insert('INSERT INTO phone_invoices (citizenid, amount, society, sender, sendercitizenid) VALUES (?, ?, ?, ?, ?)',{ 81 | billedCID.PlayerData.citizenid, 82 | cash, 83 | billerInfo.PlayerData.job.name, 84 | billerInfo.PlayerData.charinfo.firstname, 85 | billerInfo.PlayerData.citizenid 86 | }, function(id) 87 | if id then 88 | TriggerClientEvent('qb-phone:client:AcceptorDenyInvoice', billedCID.PlayerData.source, id, billerInfo.PlayerData.charinfo.firstname, billerInfo.PlayerData.job.name, billerInfo.PlayerData.citizenid, cash, resource) 89 | end 90 | end) 91 | end) 92 | 93 | lib.callback.register('qb-phone:server:GetInvoices', function(source) 94 | local Player = QBCore.Functions.GetPlayer(source) 95 | local invoices = exports.oxmysql:executeSync('SELECT * FROM phone_invoices WHERE citizenid = ?', {Player.PlayerData.citizenid}) 96 | return invoices 97 | end) 98 | -------------------------------------------------------------------------------- /qb-phone/client/whatsapp.lua: -------------------------------------------------------------------------------- 1 | -- Functions 2 | 3 | local function IsNumberInContacts(num) 4 | for _, v in pairs(PhoneData.Contacts) do 5 | if num == v.number then 6 | return v.name 7 | end 8 | end 9 | end 10 | 11 | local function GetKeyByDate(Number, Date) 12 | if PhoneData.Chats[Number] and PhoneData.Chats[Number].messages then 13 | for key, chat in pairs(PhoneData.Chats[Number].messages) do 14 | if chat.date == Date then 15 | return key 16 | end 17 | end 18 | end 19 | end 20 | 21 | -- NUI Callback 22 | 23 | RegisterNUICallback('GetWhatsappChat', function(data, cb) 24 | if PhoneData.Chats[data.phone] then 25 | cb(PhoneData.Chats[data.phone]) 26 | else 27 | cb(false) 28 | end 29 | end) 30 | 31 | RegisterNUICallback('GetWhatsappChats', function(_, cb) 32 | cb(PhoneData.Chats) 33 | end) 34 | 35 | RegisterNUICallback('SendMessage', function(data, cb) 36 | local ChatMessage = data.ChatMessage 37 | local ChatDate = data.ChatDate 38 | local ChatNumber = data.ChatNumber 39 | local ChatTime = data.ChatTime 40 | local ChatType = data.ChatType 41 | local ChatKey = GetKeyByDate(ChatNumber, ChatDate) 42 | 43 | if PhoneData.Chats[ChatNumber] then 44 | if not PhoneData.Chats[ChatNumber].messages then 45 | PhoneData.Chats[ChatNumber].messages = {} 46 | end 47 | else 48 | PhoneData.Chats[ChatNumber] = { 49 | name = IsNumberInContacts(ChatNumber), 50 | number = ChatNumber, 51 | messages = {}, 52 | } 53 | end 54 | 55 | if not ChatKey or (ChatKey and not PhoneData.Chats[ChatNumber].messages[ChatKey]) then 56 | local temp = #PhoneData.Chats[ChatNumber].messages+1 57 | PhoneData.Chats[ChatNumber].messages[temp] = { 58 | date = ChatDate, 59 | messages = {}, 60 | } 61 | 62 | ChatKey = temp 63 | end 64 | 65 | if ChatMessage then 66 | PhoneData.Chats[ChatNumber].messages[ChatKey].messages[#PhoneData.Chats[ChatNumber].messages[ChatKey].messages+1] = { 67 | message = ChatMessage, 68 | time = ChatTime, 69 | sender = PhoneData.PlayerData.citizenid, 70 | type = ChatType, 71 | data = {}, 72 | } 73 | else 74 | PhoneData.Chats[ChatNumber].messages[ChatKey].messages[#PhoneData.Chats[ChatNumber].messages[ChatKey].messages+1] = { 75 | message = "Photo", 76 | time = ChatTime, 77 | sender = PhoneData.PlayerData.citizenid, 78 | type = ChatType, 79 | data = { 80 | url = data.url 81 | }, 82 | } 83 | end 84 | 85 | TriggerServerEvent('qb-phone:server:UpdateMessages', PhoneData.Chats[ChatNumber].messages, ChatNumber) 86 | SendNUIMessage({ 87 | action = "UpdateChat", 88 | chatData = PhoneData.Chats[ChatNumber], 89 | chatNumber = ChatNumber, 90 | }) 91 | 92 | 93 | cb("ok") 94 | end) 95 | 96 | -- Events 97 | 98 | RegisterNetEvent('qb-phone:client:UpdateMessages', function(ChatMessages, SenderNumber, New) 99 | if not ChatMessages or not SenderNumber then return end 100 | 101 | local NumberKey = type(SenderNumber) ~= "string" and tostring(SenderNumber) or SenderNumber 102 | local name = IsNumberInContacts(SenderNumber) or SenderNumber 103 | 104 | if SenderNumber == PhoneData.PlayerData.charinfo.phone then return end 105 | 106 | if New then 107 | PhoneData.Chats[NumberKey] = { 108 | name = name, 109 | number = SenderNumber, 110 | messages = ChatMessages 111 | } 112 | else 113 | PhoneData.Chats[NumberKey].messages = ChatMessages 114 | end 115 | 116 | SendNUIMessage({ 117 | action = "PhoneNotification", 118 | PhoneNotify = { 119 | title = "Messages", 120 | text = "New Message From: "..name, 121 | icon = "fas fa-comment", 122 | color = "#25D366", 123 | timeout = math.random(4000, 7500), 124 | }, 125 | }) 126 | 127 | if PhoneData.isOpen then 128 | SendNUIMessage({ 129 | action = "UpdateChat", 130 | chatData = PhoneData.Chats[NumberKey], 131 | chatNumber = NumberKey, 132 | }) 133 | else 134 | Config.PhoneApplications['whatsapp'].Alerts = Config.PhoneApplications['whatsapp'].Alerts + 1 135 | end 136 | 137 | if not PhoneData.Chats[NumberKey].Unread then PhoneData.Chats[NumberKey].Unread = 1 else PhoneData.Chats[NumberKey].Unread += 1 end 138 | end) -------------------------------------------------------------------------------- /qb-phone/qb-phone.sql: -------------------------------------------------------------------------------- 1 | 2 | DROP TABLE IF EXISTS `phone_gallery`; 3 | CREATE TABLE IF NOT EXISTS `phone_gallery` ( 4 | `citizenid` varchar(255) NOT NULL, 5 | `image` varchar(255) NOT NULL, 6 | `date` timestamp NULL DEFAULT current_timestamp() 7 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; 8 | 9 | DROP TABLE IF EXISTS `phone_invoices`; 10 | CREATE TABLE IF NOT EXISTS `phone_invoices` ( 11 | `id` int(10) NOT NULL AUTO_INCREMENT, 12 | `citizenid` varchar(50) DEFAULT NULL, 13 | `amount` int(11) NOT NULL DEFAULT 0, 14 | `society` tinytext DEFAULT NULL, 15 | `sender` varchar(50) DEFAULT NULL, 16 | `sendercitizenid` varchar(50) DEFAULT NULL, 17 | `time` int(11) DEFAULT NULL, 18 | PRIMARY KEY (`id`), 19 | KEY `citizenid` (`citizenid`) 20 | ) ENGINE=InnoDB AUTO_INCREMENT=42 DEFAULT CHARSET=utf8; 21 | 22 | DROP TABLE IF EXISTS `phone_messages`; 23 | CREATE TABLE IF NOT EXISTS `phone_messages` ( 24 | `id` int(11) NOT NULL AUTO_INCREMENT, 25 | `citizenid` varchar(50) DEFAULT NULL, 26 | `number` varchar(50) DEFAULT NULL, 27 | `messages` text DEFAULT NULL, 28 | `time` int(11) DEFAULT NULL, 29 | PRIMARY KEY (`id`), 30 | KEY `citizenid` (`citizenid`), 31 | KEY `number` (`number`) 32 | ) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8; 33 | 34 | DROP TABLE IF EXISTS `phone_note`; 35 | CREATE TABLE IF NOT EXISTS `phone_note` ( 36 | `id` int(10) NOT NULL AUTO_INCREMENT, 37 | `citizenid` varchar(50) DEFAULT NULL, 38 | `title` text DEFAULT NULL, 39 | `text` text DEFAULT NULL, 40 | `lastupdate` varchar(50) DEFAULT NULL, 41 | PRIMARY KEY (`id`), 42 | KEY `citizenid` (`citizenid`) 43 | ) ENGINE=InnoDB AUTO_INCREMENT=56 DEFAULT CHARSET=utf8; 44 | 45 | DROP TABLE IF EXISTS `phone_tweets`; 46 | CREATE TABLE IF NOT EXISTS `phone_tweets` ( 47 | `id` int(11) NOT NULL AUTO_INCREMENT, 48 | `citizenid` varchar(50) DEFAULT NULL, 49 | `firstName` varchar(25) DEFAULT NULL, 50 | `lastName` varchar(25) DEFAULT NULL, 51 | `type` varchar(25) DEFAULT NULL, 52 | `message` text DEFAULT NULL, 53 | `url` text DEFAULT NULL, 54 | `tweetId` varchar(25) NOT NULL, 55 | `date` datetime DEFAULT current_timestamp(), 56 | PRIMARY KEY (`id`), 57 | KEY `citizenid` (`citizenid`) 58 | ) ENGINE=InnoDB AUTO_INCREMENT=289 DEFAULT CHARSET=UTF8; 59 | 60 | DROP TABLE IF EXISTS `player_contacts`; 61 | CREATE TABLE IF NOT EXISTS `player_contacts` ( 62 | `id` int(11) NOT NULL AUTO_INCREMENT, 63 | `citizenid` varchar(50) DEFAULT NULL, 64 | `name` varchar(50) DEFAULT NULL, 65 | `number` varchar(50) DEFAULT NULL, 66 | PRIMARY KEY (`id`), 67 | KEY `citizenid` (`citizenid`) 68 | ) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8; 69 | 70 | DROP TABLE IF EXISTS `player_mails`; 71 | CREATE TABLE IF NOT EXISTS `player_mails` ( 72 | `id` int(11) NOT NULL AUTO_INCREMENT, 73 | `citizenid` varchar(50) DEFAULT NULL, 74 | `sender` varchar(50) DEFAULT NULL, 75 | `subject` varchar(50) DEFAULT NULL, 76 | `message` text DEFAULT NULL, 77 | `read` tinyint(4) DEFAULT 0, 78 | `mailid` int(11) DEFAULT NULL, 79 | `date` timestamp NULL DEFAULT current_timestamp(), 80 | `button` text DEFAULT NULL, 81 | PRIMARY KEY (`id`), 82 | KEY `citizenid` (`citizenid`) 83 | ) ENGINE=InnoDB AUTO_INCREMENT=49 DEFAULT CHARSET=utf8; 84 | 85 | 86 | DROP TABLE IF EXISTS `phone_chatrooms`; 87 | CREATE TABLE `phone_chatrooms` ( 88 | `id` INT unsigned NOT NULL AUTO_INCREMENT, 89 | `room_code` VARCHAR(10) NOT NULL UNIQUE, 90 | `room_name` VARCHAR(15) NOT NULL, 91 | `room_owner_id` VARCHAR(20), 92 | `room_owner_name` VARCHAR(60), 93 | `room_members` TEXT DEFAULT '{}', 94 | `room_pin` VARCHAR(50), 95 | `unpaid_balance` DECIMAL(10,2) DEFAULT 0, 96 | `is_pinned` BOOLEAN DEFAULT 0, 97 | `created` DATETIME DEFAULT NOW(), 98 | PRIMARY KEY (`id`) 99 | ); 100 | 101 | INSERT INTO `phone_chatrooms` (`room_code`, `room_name`, `room_owner_id`, `room_owner_name`, `is_pinned`) VALUES 102 | ('411', '411', 'official', 'Government', 1), 103 | ('lounge', 'The Lounge', 'official', 'Government', 1), 104 | ('events', 'Events', 'official', 'Government', 1); 105 | 106 | DROP TABLE IF EXISTS `phone_chatroom_messages`; 107 | CREATE TABLE `phone_chatroom_messages` ( 108 | `id` INT unsigned NOT NULL AUTO_INCREMENT, 109 | `room_id` INT unsigned, 110 | `member_id` VARCHAR(20), 111 | `member_name` VARCHAR(50), 112 | `message` TEXT NOT NULL, 113 | `is_pinned` BOOLEAN DEFAULT FALSE, 114 | `created` DATETIME DEFAULT NOW(), 115 | PRIMARY KEY (`id`) 116 | ); 117 | 118 | DROP TABLE IF EXISTS `player_jobs`; 119 | CREATE TABLE IF NOT EXISTS `player_jobs` ( 120 | `id` int(11) NOT NULL AUTO_INCREMENT, 121 | `jobname` varchar(50) DEFAULT NULL, 122 | `employees` text DEFAULT NULL, 123 | `maxEmployee` tinyint(11) DEFAULT 15, 124 | PRIMARY KEY (`id`) 125 | ) ENGINE=InnoDB AUTO_INCREMENT=106 DEFAULT CHARSET=utf8; -------------------------------------------------------------------------------- /qb-phone/html/css/details.css: -------------------------------------------------------------------------------- 1 | @import "https://assets.nopixel.net/web/fonts/gilroy/stylesheet.css"; 2 | 3 | .details-app { 4 | display: none; 5 | height: 108%; 6 | width: 100%; 7 | overflow: hidden; 8 | background: linear-gradient(158deg, rgba(24,25,46,1) 0%, rgba(15,18,27,1) 32%, rgba(24,25,46,1) 68%, rgba(15,18,27,1) 100%); 9 | -moz-user-select: -moz-text; 10 | -khtml-user-select: text; 11 | -webkit-user-select: text; 12 | -o-user-select: text; 13 | user-select: text; 14 | } 15 | 16 | 17 | 18 | .details-header { 19 | position: absolute; 20 | width: 90%; 21 | height: 20%; 22 | top: 8%; 23 | left: 0; 24 | right: 0; 25 | color: white; 26 | font-size: 1.3vh; 27 | margin: 0 auto; 28 | } 29 | 30 | 31 | .details-header-main { 32 | position: absolute; 33 | width: 90%; 34 | top: 0%; 35 | left: 0; 36 | right: 7%; 37 | color: white; 38 | font-size: 2.4vh; 39 | margin: 0 auto; 40 | font-family: 'Gilroy'; 41 | } 42 | 43 | .details-header-secondary { 44 | position: absolute; 45 | width: 90%; 46 | top: 40%; 47 | left: 0; 48 | right: 7%; 49 | color: white; 50 | font-size: 1.5vh; 51 | margin: 0 auto; 52 | font-family: 'Gilroy'; 53 | } 54 | 55 | .details-header-license { 56 | position: absolute; 57 | width: 90%; 58 | height: 30%; 59 | top: 27vh; 60 | right: 7%; 61 | color: white; 62 | font-size: 1.5vh; 63 | margin: 0 auto; 64 | font-family: 'Gilroy'; 65 | } 66 | 67 | .details-header>p { 68 | line-height: 12vh; 69 | text-indent: 2vh; 70 | margin: 0 0 0 9vh; 71 | font-family: 'Gilroy'; 72 | } 73 | 74 | .details-header>span { 75 | position: absolute; 76 | top: 8vh; 77 | left: 9vh; 78 | font-size: 1.2vh; 79 | height: 2vh; 80 | color: white; 81 | font-family: 'Gilroy'; 82 | } 83 | 84 | .details-list { 85 | margin-bottom: 0.5vh; 86 | padding: 0.8vh 1.5vh; 87 | /* Adjust the padding here */ 88 | border-radius: 0.463vh; 89 | background: rgb(11, 14, 21); 90 | overflow: hidden; 91 | /* Ensures the box expands to contain floated elements */ 92 | } 93 | 94 | .details-list::-webkit-scrollbar { 95 | display: none; 96 | } 97 | 98 | 99 | .details-money-types { 100 | position: absolute; 101 | width: 110%; 102 | top: 17vh; 103 | /* Adjust the percentage to move it down */ 104 | left: 52%; 105 | transform: translate(-50%, -50%); 106 | } 107 | 108 | .details-license-types { 109 | position: absolute; 110 | width: 110%; 111 | height:200%; 112 | top: 42vh; 113 | /* Adjust the percentage to move it down */ 114 | left: 52%; 115 | transform: translate(-50%, -50%); 116 | overflow-y: scroll; 117 | } 118 | 119 | .details-value { 120 | float: right; 121 | clear: right; 122 | font-family: 'Gilroy'; 123 | } 124 | 125 | .details-label { 126 | float: left; 127 | font-family: 'Gilroy'; 128 | } 129 | 130 | .details-box { 131 | margin-bottom: 0.5vh; 132 | padding: 0.8vh 1.5vh; 133 | /* Adjust the padding here */ 134 | border-radius: 0.463vh; 135 | background: rgb(11, 14, 21); 136 | overflow: hidden; 137 | /* Ensures the box expands to contain floated elements */ 138 | } 139 | 140 | 141 | .details-moneys-body-main { 142 | display: block; 143 | width: 100%; 144 | margin-left: 3%; 145 | margin-bottom: 2%; 146 | max-width: 90%; 147 | white-space: nowrap; 148 | overflow: hidden !important; 149 | text-overflow: ellipsis; 150 | } 151 | 152 | .details-icon-class { 153 | display: inline-block; 154 | text-align: center; 155 | width: 10%; 156 | } 157 | 158 | .details-text-class { 159 | display: inline; 160 | width: 90%; 161 | } 162 | 163 | .details-license-body-main { 164 | display: block; 165 | width: 100%; 166 | margin-left: 3%; 167 | margin-bottom: 3vh; 168 | max-width: 90%; 169 | white-space: nowrap; 170 | overflow: hidden !important; 171 | text-overflow: ellipsis; 172 | } 173 | 174 | .details-license-icon-class { 175 | display: inline; 176 | text-align: right; 177 | width: 10%; 178 | } 179 | 180 | .details-license-text-class { 181 | display: inline-block; 182 | width: 85%; 183 | } 184 | 185 | .details-text-license { 186 | width: 100%; 187 | color: whitesmoke; 188 | text-align: center; 189 | } 190 | 191 | .details-section { 192 | margin-bottom: 1.8519vh; 193 | /* Adjust spacing between sections */ 194 | } 195 | 196 | .details-section h2 { 197 | color: white; 198 | font-size: 1.2vh; 199 | /* Adjust font size */ 200 | margin-bottom: 0.9259vh; 201 | font-family: 'Gilroy'; 202 | /* Adjust spacing between header and content */ 203 | } 204 | 205 | .valid-text { 206 | background: #15661b; 207 | border-radius: 0.3vh; 208 | padding: 0.4vh; 209 | font-family: 'Gilroy'; 210 | font-size: 1.3vh; 211 | } -------------------------------------------------------------------------------- /qb-phone/client/racing.lua: -------------------------------------------------------------------------------- 1 | -- NUI Callback 2 | 3 | RegisterNUICallback('GetAvailableRaces', function(_, cb) 4 | QBCore.Functions.TriggerCallback('qb-lapraces:server:GetRaces', function(Races) 5 | cb(Races) 6 | end) 7 | end) 8 | 9 | RegisterNUICallback('JoinRace', function(data, cb) 10 | TriggerServerEvent('qb-lapraces:server:JoinRace', data.RaceData) 11 | cb("ok") 12 | end) 13 | 14 | RegisterNUICallback('LeaveRace', function(data, cb) 15 | TriggerServerEvent('qb-lapraces:server:LeaveRace', data.RaceData) 16 | cb("ok") 17 | end) 18 | 19 | RegisterNUICallback('StartRace', function(data, cb) 20 | TriggerServerEvent('qb-lapraces:server:StartRace', data.RaceData.RaceId) 21 | cb("ok") 22 | end) 23 | 24 | RegisterNUICallback('SetAlertWaypoint', function(data, cb) 25 | local coords = data.alert.coords 26 | QBCore.Functions.Notify('GPS set: '..data.alert.title, "primary") 27 | SetNewWaypoint(coords.x, coords.y) 28 | cb("ok") 29 | end) 30 | 31 | RegisterNUICallback('GetRaces', function(_, cb) 32 | QBCore.Functions.TriggerCallback('qb-lapraces:server:GetListedRaces', function(Races) 33 | cb(Races) 34 | end) 35 | end) 36 | 37 | RegisterNUICallback('GetTrackData', function(data, cb) 38 | QBCore.Functions.TriggerCallback('qb-lapraces:server:GetTrackData', function(TrackData, CreatorData) 39 | TrackData.CreatorData = CreatorData 40 | cb(TrackData) 41 | end, data.RaceId) 42 | end) 43 | 44 | RegisterNUICallback('SetupRace', function(data, cb) 45 | -- local hasDongle = exports.ox_inventory:Search('count', 'phone_dongle') 46 | local hasDongle = QBCore.Functions.HasItem('phone_dongle', 'count') 47 | TriggerServerEvent('qb-lapraces:server:SetupRace', data.RaceId, tonumber(data.AmountOfLaps)) 48 | if hasDongle >= 1 then 49 | SendNUIMessage({ 50 | action = "PhoneNotification", 51 | PhoneNotify = { 52 | title = "FROM THE PM", 53 | text = "New Race Has Started!", 54 | icon = "fas fa-flag-checkered", 55 | color = "#167869" 56 | }, 57 | }) 58 | end 59 | cb("ok") 60 | end) 61 | 62 | RegisterNUICallback('HasCreatedRace', function(_, cb) 63 | QBCore.Functions.TriggerCallback('qb-lapraces:server:HasCreatedRace', function(HasCreated) 64 | cb(HasCreated) 65 | end) 66 | end) 67 | 68 | RegisterNUICallback('IsInRace', function(_, cb) 69 | local InRace = exports['qb-lapraces']:IsInRace() 70 | cb(InRace) 71 | end) 72 | 73 | RegisterNUICallback('IsAuthorizedToCreateRaces', function(data, cb) 74 | QBCore.Functions.TriggerCallback('qb-lapraces:server:IsAuthorizedToCreateRaces', function(IsAuthorized, NameAvailable) 75 | local sendData = { 76 | IsAuthorized = IsAuthorized, 77 | IsBusy = exports['qb-lapraces']:IsInEditor(), 78 | IsNameAvailable = NameAvailable, 79 | } 80 | cb(sendData) 81 | end, data.TrackName) 82 | end) 83 | 84 | RegisterNUICallback('StartTrackEditor', function(data, cb) 85 | TriggerServerEvent('qb-lapraces:server:CreateLapRace', data.TrackName) 86 | cb("ok") 87 | end) 88 | 89 | RegisterNUICallback('GetRacingLeaderboards', function(_, cb) 90 | QBCore.Functions.TriggerCallback('qb-lapraces:server:GetRacingLeaderboards', function(Races) 91 | cb(Races) 92 | end) 93 | end) 94 | 95 | RegisterNUICallback('RaceDistanceCheck', function(data, cb) 96 | QBCore.Functions.TriggerCallback('qb-lapraces:server:GetRacingData', function(RaceData) 97 | local coords = GetEntityCoords(cache.ped) 98 | local checkpointcoords = RaceData.Checkpoints[1].coords 99 | local dist = #(coords - vector3(checkpointcoords.x, checkpointcoords.y, checkpointcoords.z)) 100 | if dist <= 115.0 then 101 | if data.Joined then 102 | TriggerEvent('qb-lapraces:client:WaitingDistanceCheck') 103 | end 104 | cb(true) 105 | else 106 | QBCore.Functions.Notify('You\'re too far away from the race. GPS set.', "error", 5000) 107 | SetNewWaypoint(checkpointcoords.x, checkpointcoords.y) 108 | cb(false) 109 | end 110 | end, data.RaceId) 111 | end) 112 | 113 | RegisterNUICallback('IsBusyCheck', function(data, cb) 114 | if data.check == "editor" then 115 | cb(exports['qb-lapraces']:IsInEditor()) 116 | else 117 | cb(exports['qb-lapraces']:IsInRace()) 118 | end 119 | end) 120 | 121 | RegisterNUICallback('CanRaceSetup', function(_, cb) 122 | QBCore.Functions.TriggerCallback('qb-lapraces:server:CanRaceSetup', function(CanSetup) 123 | cb(CanSetup) 124 | end) 125 | end) 126 | 127 | -- Events 128 | 129 | RegisterNetEvent('qb-phone:client:RaceNotify', function(message) 130 | TriggerEvent('qb-phone:client:CustomNotification', 131 | "Racing", 132 | message, 133 | "fas fa-flag-checkered", 134 | "#353b48", 135 | 3500 136 | ) 137 | end) 138 | 139 | RegisterNetEvent('qb-phone:client:UpdateLapraces', function() 140 | SendNUIMessage({ 141 | action = "UpdateRacingApp", 142 | }) 143 | end) -------------------------------------------------------------------------------- /qb-phone/server/mail.lua: -------------------------------------------------------------------------------- 1 | -- Functions 2 | 3 | local function GenerateMailId() 4 | return math.random(111111, 999999) 5 | end 6 | 7 | 8 | 9 | RegisterNetEvent('qb-phone:server:RemoveMail', function(MailId) 10 | local src = source 11 | local Player = QBCore.Functions.GetPlayer(src) 12 | if not MailId or not Player then return end 13 | 14 | local CID = Player.PlayerData.citizenid 15 | 16 | 17 | MySQL.query('DELETE FROM player_mails WHERE mailid = ? AND citizenid = ?', {MailId, CID}) 18 | SetTimeout(100, function() 19 | local mails = MySQL.query.await('SELECT * FROM player_mails WHERE citizenid = ? ORDER BY `date` ASC', {CID}) 20 | TriggerClientEvent('qb-phone:client:UpdateMails', src, mails) 21 | end) 22 | end) 23 | 24 | 25 | RegisterNetEvent('qb-phone:server:sendNewMail', function(mailData, citizenID) 26 | 27 | if not mailData or not mailData.sender or not mailData.subject or not mailData.message then return end 28 | local Player 29 | 30 | if citizenID then 31 | Player = QBCore.Functions.GetPlayerByCitizenId(citizenID) 32 | else 33 | Player = QBCore.Functions.GetPlayer(source) 34 | end 35 | 36 | if Player then 37 | local CID = Player.PlayerData.citizenid 38 | if mailData.button then 39 | MySQL.insert('INSERT INTO player_mails (`citizenid`, `sender`, `subject`, `message`, `mailid`, `read`, `button`) VALUES (?, ?, ?, ?, ?, ?, ?)', {CID, mailData.sender, mailData.subject, mailData.message, GenerateMailId(), 0, json.encode(mailData.button)}) 40 | else 41 | MySQL.insert('INSERT INTO player_mails (`citizenid`, `sender`, `subject`, `message`, `mailid`, `read`) VALUES (?, ?, ?, ?, ?, ?)', {CID, mailData.sender, mailData.subject, mailData.message, GenerateMailId(), 0}) 42 | end 43 | 44 | TriggerClientEvent('qb-phone:client:NewMailNotify', Player.PlayerData.source, mailData) 45 | 46 | SetTimeout(200, function() 47 | local mails = MySQL.query.await('SELECT * FROM player_mails WHERE citizenid = ? ORDER BY `date` ASC', {CID}) 48 | if mails[1] then 49 | for _, v in pairs(mails) do 50 | if v.button then 51 | v.button = json.decode(v.button) 52 | end 53 | end 54 | end 55 | 56 | TriggerClientEvent('qb-phone:client:UpdateMails', Player.PlayerData.source, mails) 57 | end) 58 | elseif citizenID then 59 | if mailData.button then 60 | MySQL.insert('INSERT INTO player_mails (`citizenid`, `sender`, `subject`, `message`, `mailid`, `read`, `button`) VALUES (?, ?, ?, ?, ?, ?, ?)', {citizenID, mailData.sender, mailData.subject, mailData.message, GenerateMailId(), 0, json.encode(mailData.button)}) 61 | else 62 | MySQL.insert('INSERT INTO player_mails (`citizenid`, `sender`, `subject`, `message`, `mailid`, `read`) VALUES (?, ?, ?, ?, ?, ?)', {citizenID, mailData.sender, mailData.subject, mailData.message, GenerateMailId(), 0}) 63 | end 64 | end 65 | end) 66 | 67 | function sendNewMailToOffline(citizenid, mailData) 68 | local Player = QBCore.Functions.GetPlayerByCitizenId(citizenid) 69 | if Player then 70 | local src = Player.PlayerData.source 71 | if mailData.button == nil then 72 | MySQL.insert('INSERT INTO player_mails (`citizenid`, `sender`, `subject`, `message`, `mailid`, `read`) VALUES (?, ?, ?, ?, ?, ?)', {Player.PlayerData.citizenid, mailData.sender, mailData.subject, mailData.message, GenerateMailId(), 0}) 73 | TriggerClientEvent('qb-phone:client:NewMailNotify', src, mailData) 74 | else 75 | MySQL.insert('INSERT INTO player_mails (`citizenid`, `sender`, `subject`, `message`, `mailid`, `read`, `button`) VALUES (?, ?, ?, ?, ?, ?, ?)', {Player.PlayerData.citizenid, mailData.sender, mailData.subject, mailData.message, GenerateMailId(), 0, json.encode(mailData.button)}) 76 | TriggerClientEvent('qb-phone:client:NewMailNotify', src, mailData) 77 | end 78 | SetTimeout(200, function() 79 | local mails = MySQL.query.await( 80 | 'SELECT * FROM player_mails WHERE citizenid = ? ORDER BY `date` ASC', {Player.PlayerData.citizenid}) 81 | if mails[1] ~= nil then 82 | for k, _ in pairs(mails) do 83 | if mails[k].button ~= nil then 84 | mails[k].button = json.decode(mails[k].button) 85 | end 86 | end 87 | end 88 | 89 | TriggerClientEvent('qb-phone:client:UpdateMails', src, mails) 90 | end) 91 | else 92 | if mailData.button == nil then 93 | MySQL.insert('INSERT INTO player_mails (`citizenid`, `sender`, `subject`, `message`, `mailid`, `read`) VALUES (?, ?, ?, ?, ?, ?)', {citizenid, mailData.sender, mailData.subject, mailData.message, GenerateMailId(), 0}) 94 | else 95 | MySQL.insert('INSERT INTO player_mails (`citizenid`, `sender`, `subject`, `message`, `mailid`, `read`, `button`) VALUES (?, ?, ?, ?, ?, ?, ?)', {citizenid, mailData.sender, mailData.subject, mailData.message, GenerateMailId(), 0, json.encode(mailData.button)}) 96 | end 97 | end 98 | end 99 | exports("sendNewMailToOffline",sendNewMailToOffline) -------------------------------------------------------------------------------- /qb-phone/server/documents.lua: -------------------------------------------------------------------------------- 1 | RegisterNetEvent("qb-phone:server:sendDocument", function(data) 2 | local src = source 3 | local Ply = QBCore.Functions.GetPlayer(src) 4 | local Receiver = QBCore.Functions.GetPlayer(tonumber(data.StateID)) 5 | local SenderName = Ply.PlayerData.charinfo.firstname..' '..Ply.PlayerData.charinfo.lastname 6 | if not Receiver then 7 | TriggerClientEvent('qb-phone:client:CustomNotification', src, 8 | "Documents", 9 | "Invalid State ID", 10 | "fas fa-folder", 11 | "#d9d9d9", 12 | 5000 13 | ) 14 | return 15 | end 16 | 17 | if Ply.PlayerData.citizenid ~= Receiver.PlayerData.citizenid then 18 | TriggerClientEvent('qb-phone:client:CustomNotification', src, 19 | "Documents", 20 | "Document Sent", 21 | "fas fa-folder", 22 | "#d9d9d9", 23 | 5000 24 | ) 25 | TriggerClientEvent("qb-phone:client:sendingDocumentRequest", data.StateID, data, Receiver, Ply, SenderName) 26 | else 27 | TriggerClientEvent('qb-phone:client:CustomNotification', src, 28 | "Documents", 29 | "You can't send a document to yourself!", 30 | "fas fa-folder", 31 | "#d9d9d9", 32 | 5000 33 | ) 34 | end 35 | end) 36 | 37 | RegisterNetEvent("qb-phone:server:sendDocumentLocal", function(data, playerId) 38 | local src = source 39 | local Ply = QBCore.Functions.GetPlayer(src) 40 | local Receiver = QBCore.Functions.GetPlayer(playerId) 41 | local SenderName = Ply.PlayerData.charinfo.firstname..' '..Ply.PlayerData.charinfo.lastname 42 | 43 | TriggerClientEvent('qb-phone:client:CustomNotification', src, 44 | "Documents", 45 | "Document Sent", 46 | "fas fa-folder", 47 | "#d9d9d9", 48 | 5000 49 | ) 50 | TriggerClientEvent("qb-phone:client:sendingDocumentRequest", playerId, data, Receiver, Ply, SenderName) 51 | end) 52 | 53 | local function saveNote(data, CID, src) 54 | if not data or not data.Title or not data.Text or not data.Time or not CID or not src then return end 55 | 56 | exports.oxmysql:insert('INSERT INTO phone_note (citizenid, title, text, lastupdate) VALUES (?, ?, ?, ?)',{CID, data.Title, data.Text, data.Time}) 57 | 58 | TriggerClientEvent('qb-phone:client:CustomNotification', src, 59 | "Documents", 60 | "Created new Document", 61 | "fas fa-folder", 62 | "#d9d9d9", 63 | 5000 64 | ) 65 | end 66 | 67 | local function updateNote(data, ID, src) 68 | if not data or not data.Title or not data.Text or not data.Time or not ID or not src then return end 69 | MySQL.Sync.execute('UPDATE phone_note SET title = @title, text = @text, lastupdate = @lastupdate WHERE id = @id', { 70 | ["@id"] = ID, 71 | ["@title"] = data.Title, 72 | ["@text"] = data.Text, 73 | ["@lastupdate"] = data.Time 74 | }) 75 | 76 | 77 | TriggerClientEvent('qb-phone:client:CustomNotification', src, 78 | "Documents", 79 | "Document Saved", 80 | "fas fa-folder", 81 | "#d9d9d9", 82 | 5000 83 | ) 84 | end 85 | 86 | local function deleteNote(ID, src) 87 | if not ID or not src then return end 88 | 89 | exports.oxmysql:execute('DELETE FROM phone_note WHERE id = ?', {ID}) 90 | TriggerClientEvent('qb-phone:client:CustomNotification', src, 91 | "Documents", 92 | "Document Deleted", 93 | "fas fa-folder", 94 | "#d9d9d9", 95 | 5000 96 | ) 97 | end 98 | 99 | RegisterNetEvent('qb-phone:server:documents_Save_Note_As', function(data, Receiver) 100 | local src = source 101 | local Player = QBCore.Functions.GetPlayer(src) 102 | if not data or not Player then return end 103 | if data.Type ~= 'Delete' then 104 | if not data.Title or not data.Text or not data.Time then return end 105 | end 106 | 107 | local CID = Player.PlayerData.citizenid 108 | local ID 109 | 110 | if data.Type ~= "New" and not data.ID then return else ID = tonumber(data.ID) end 111 | 112 | if data.Type == "New" then 113 | saveNote(data, CID, src) 114 | elseif data.Type == "Update" then 115 | local Note = exports.oxmysql:executeSync('SELECT * FROM phone_note WHERE id = ?', {ID}) 116 | if Note[1] then 117 | updateNote(data, ID, src) 118 | end 119 | elseif data.Type == "Delete" then 120 | deleteNote(ID, src) 121 | elseif data.Type == "PermSend" then 122 | local Note = exports.oxmysql:executeSync('SELECT * FROM phone_note WHERE id = ?', {ID}) 123 | if Note[1] then 124 | Wait(400) 125 | exports.oxmysql:insert('INSERT INTO phone_note (citizenid, title, text, lastupdate) VALUES (?, ?, ?, ?)',{Receiver.PlayerData.citizenid, data.Title, data.Text, data.Time}) 126 | TriggerClientEvent('qb-phone:client:CustomNotification', tonumber(data.StateID), 'DOCUMENTS', 'New Document', 'fas fa-folder', '#d9d9d9', 5000) 127 | end 128 | end 129 | 130 | Wait(250) 131 | local Notes = exports.oxmysql:executeSync('SELECT * FROM phone_note WHERE citizenid = ?', {CID}) 132 | Wait(100) 133 | TriggerClientEvent('qb-phone:RefReshNotes_Free_Documents', src, Notes) 134 | end) 135 | -------------------------------------------------------------------------------- /qb-phone/server/garage.lua: -------------------------------------------------------------------------------- 1 | RegisterNetEvent('qb-phone:server:sendVehicleRequest', function(data) 2 | local src = source 3 | local Player = QBCore.Functions.GetPlayer(src) 4 | local Asshole = tonumber(data.id) 5 | local OtherAsshole = QBCore.Functions.GetPlayer(Asshole) 6 | 7 | if not OtherAsshole then return TriggerClientEvent("QBCore:Notify", src, 'State ID does not exist!', "error") end 8 | if not data.price or not data.plate then return end 9 | if Player.PlayerData.citizenid == OtherAsshole.PlayerData.citizenid then return TriggerClientEvent("QBCore:Notify", src, 'You cannot sell a vehicle to yourself!', "error") end 10 | 11 | TriggerClientEvent('qb-phone:client:sendVehicleRequest', Asshole, data, Player) 12 | end) 13 | 14 | RegisterNetEvent('qb-phone:server:sellVehicle', function(data, Seller, type) 15 | local src = source 16 | local Player = QBCore.Functions.GetPlayer(src) 17 | local SellerData = QBCore.Functions.GetPlayerByCitizenId(Seller.PlayerData.citizenid) 18 | 19 | if type == 'accepted' then 20 | if Player.PlayerData.money.bank and Player.PlayerData.money.bank >= tonumber(data.price) then 21 | Player.Functions.RemoveMoney('bank', data.price, "Bought Used Vehicle") 22 | SellerData.Functions.AddMoney('bank', data.price, "Sold Used Vehicle") 23 | TriggerClientEvent('qb-phone:client:CustomNotification', src, "VEHICLE SALE", "You purchased the vehicle for $"..data.price, "fas fa-chart-line", "#D3B300", 5500) 24 | TriggerClientEvent('qb-phone:client:CustomNotification', Seller.PlayerData.source, "VEHICLE SALE", "Your vehicle was successfully purchased!", "fas fa-chart-line", "#D3B300", 5500) 25 | MySQL.update('UPDATE player_vehicles SET citizenid = ?, garage = ?, state = ? WHERE plate = ?',{Player.PlayerData.citizenid, Config.SellGarage, 1, data.plate}) 26 | -- Update Garages 27 | TriggerClientEvent('qb-phone:client:updateGarages', src) 28 | TriggerClientEvent('qb-phone:client:updateGarages', Seller.PlayerData.source) 29 | else 30 | TriggerClientEvent('qb-phone:client:CustomNotification', src, "VEHICLE SALE", "Insufficient Funds", "fas fa-chart-line", "#D3B300", 5500) 31 | TriggerClientEvent('qb-phone:client:CustomNotification', Seller.PlayerData.source, "VEHICLE SALE", "Your vehicle was not purchased!", "fas fa-chart-line", "#D3B300", 5500) 32 | end 33 | elseif type == 'denied' then 34 | TriggerClientEvent('qb-phone:client:CustomNotification', src, "VEHICLE SALE", "Request denied", "fas fa-chart-line", "#D3B300", 5500) 35 | TriggerClientEvent('qb-phone:client:CustomNotification', Seller.PlayerData.source, "VEHICLE SALE", "Your sale request was denied!", "fas fa-chart-line", "#D3B300", 5500) 36 | end 37 | end) 38 | 39 | local function round(num, numDecimalPlaces) 40 | return tonumber(string.format("%." .. (numDecimalPlaces or 0) .. "f", num)) 41 | end 42 | 43 | lib.callback.register('qb-phone:server:GetGarageVehicles', function(source) 44 | local src = source 45 | local Player = QBCore.Functions.GetPlayer(src) 46 | local Vehicles = {} 47 | local vehdata 48 | local result = exports.oxmysql:executeSync('SELECT * FROM player_vehicles WHERE citizenid = ?', {Player.PlayerData.citizenid}) 49 | if result[1] then 50 | for _, v in pairs(result) do 51 | local VehicleData = QBCore.Shared.Vehicles[v.vehicle] 52 | local VehicleGarage = "None" 53 | local enginePercent = round(v.engine / 10, 0) 54 | local bodyPercent = round(v.body / 10, 0) 55 | -- if v.garage then 56 | -- if Config.Garages[v.garage] then 57 | -- VehicleGarage = Config.Garages[v.garage]["label"] 58 | -- else 59 | -- VehicleGarage = v.garage 60 | -- end 61 | -- end 62 | 63 | local VehicleState = "In" 64 | if v.state == 0 then 65 | VehicleState = "Out" 66 | elseif v.state == 2 then 67 | VehicleState = "Impounded" 68 | end 69 | 70 | if VehicleData["brand"] then 71 | vehdata = { 72 | fullname = VehicleData["brand"] .. " " .. VehicleData["name"], 73 | brand = VehicleData["brand"], 74 | model = VehicleData["name"], 75 | plate = v.plate, 76 | garage = VehicleGarage, 77 | state = VehicleState, 78 | fuel = v.fuel, 79 | engine = enginePercent, 80 | body = bodyPercent, 81 | paymentsleft = v.paymentsleft 82 | } 83 | else 84 | vehdata = { 85 | fullname = VehicleData["name"], 86 | brand = VehicleData["name"], 87 | model = VehicleData["name"], 88 | plate = v.plate, 89 | garage = VehicleGarage, 90 | state = VehicleState, 91 | fuel = v.fuel, 92 | engine = enginePercent, 93 | body = bodyPercent, 94 | paymentsleft = v.paymentsleft 95 | } 96 | end 97 | Vehicles[#Vehicles+1] = vehdata 98 | end 99 | return Vehicles 100 | else 101 | return nil 102 | end 103 | end) 104 | -------------------------------------------------------------------------------- /qb-phone/html/js/gallery.js: -------------------------------------------------------------------------------- 1 | function setUpGalleryData(Images){ 2 | $(".gallery-images").html(""); 3 | if (Images != null) { 4 | $.each(Images, function(i, image){ 5 | var Element = ''; 6 | 7 | $(".gallery-images").append(Element); 8 | $("#image-"+i).data('ImageData', image); 9 | }); 10 | } 11 | } 12 | 13 | $(document).on('click', '.tumbnail', function(e){ 14 | e.preventDefault(); 15 | let source = $(this).attr('src') 16 | $(".gallery-homescreen").animate({ 17 | left: 30+"vh" 18 | }, 200); 19 | $(".gallery-detailscreen").animate({ 20 | left: 0+"vh" 21 | }, 200); 22 | SetupImageDetails(source); 23 | }); 24 | 25 | $(document).on('click', '.image', function(e){ 26 | e.preventDefault(); 27 | let source = $(this).attr('src') 28 | QB.Screen.popUp(source) 29 | }); 30 | 31 | 32 | $(document).on('click', '#delete-button', function(e){ 33 | e.preventDefault(); 34 | let source = $('.image').attr('src') 35 | 36 | setTimeout(() => { 37 | $.post('https://qb-phone/DeleteImage', JSON.stringify({image:source}), function(Hashtags){ 38 | setTimeout(()=>{ 39 | $('#return-button').click() 40 | $.post('https://qb-phone/GetGalleryData', JSON.stringify({}), function(data){ 41 | setTimeout(()=>{ 42 | setUpGalleryData(data); 43 | 44 | },200) 45 | }); 46 | },200) 47 | }) 48 | 49 | }, 200); 50 | }); 51 | 52 | 53 | function SetupImageDetails(Image){ 54 | $('#imagedata').attr("src", Image); 55 | } 56 | let postImageUrl=""; 57 | function SetupPostDetails(){ 58 | } 59 | 60 | 61 | $(document).on('click', '#make-post-button', function(e){ 62 | e.preventDefault(); 63 | let source = $('#imagedata').attr('src') 64 | postImageUrl=source 65 | 66 | $(".gallery-detailscreen").animate({ 67 | left: 30+"vh" 68 | }, 200); 69 | $(".gallery-postscreen").animate({ 70 | left: 0+"vh" 71 | }, 200); 72 | SetupPostDetails(); 73 | }); 74 | 75 | $(document).on('click', '#gallery-coppy-button', function(e){ 76 | e.preventDefault(); 77 | let source = $('#imagedata').attr('src') 78 | copyToClipboard(source) 79 | }); 80 | 81 | const copyToClipboard = str => { 82 | const el = document.createElement('textarea'); 83 | el.value = str; 84 | document.body.appendChild(el); 85 | el.select(); 86 | document.execCommand('copy'); 87 | document.body.removeChild(el); 88 | }; 89 | 90 | $(document).on('click', '#return-button', function(e){ 91 | e.preventDefault(); 92 | 93 | $(".gallery-homescreen").animate({ 94 | left: 00+"vh" 95 | }, 200); 96 | $(".gallery-detailscreen").animate({ 97 | left: -30+"vh" 98 | }, 200); 99 | }); 100 | 101 | $(document).on('click', '#returndetail-button', function(e){ 102 | e.preventDefault(); 103 | returnDetail(); 104 | 105 | }); 106 | 107 | function returnDetail(){ 108 | $(".gallery-detailscreen").animate({ 109 | left: 00+"vh" 110 | }, 200); 111 | $(".gallery-postscreen").animate({ 112 | left: -30+"vh" 113 | }, 200); 114 | } 115 | 116 | 117 | $(document).on('click', '#tweet-button', function(e){ 118 | e.preventDefault(); 119 | var TweetMessage = $("#new-textarea").val(); 120 | var imageURL = postImageUrl 121 | if (TweetMessage != "") { 122 | var CurrentDate = new Date(); 123 | $.post('https://qb-phone/PostNewTweet', JSON.stringify({ 124 | Message: TweetMessage, 125 | Date: CurrentDate, 126 | Picture: QB.Phone.Data.MetaData.profilepicture, 127 | url: imageURL 128 | }), function(Tweets){ 129 | QB.Phone.Notifications.LoadTweets(Tweets); 130 | }); 131 | var TweetMessage = $("#new-textarea").val(' '); 132 | $.post('https://qb-phone/GetHashtags', JSON.stringify({}), function(Hashtags){ 133 | QB.Phone.Notifications.LoadHashtags(Hashtags) 134 | }) 135 | returnDetail() 136 | } else { 137 | QB.Phone.Notifications.Add("fab fa-twitter", "Twitter", "Fill a message!", "#1DA1F2"); 138 | }; 139 | $('#tweet-new-url').val(""); 140 | $("#tweet-new-message").val(""); 141 | }); 142 | 143 | 144 | $(document).on('click', '#advert-button', function(e){ 145 | e.preventDefault(); 146 | var Advert = $("#new-textarea").val(); 147 | let picture = postImageUrl; 148 | 149 | if (Advert !== "") { 150 | $(".advert-home").animate({ 151 | left: 0+"vh" 152 | }); 153 | $(".new-advert").animate({ 154 | left: -30+"vh" 155 | }); 156 | if (!picture){ 157 | $.post('https://qb-phone/PostAdvert', JSON.stringify({ 158 | message: Advert, 159 | url: null 160 | })); 161 | returnDetail() 162 | }else { 163 | $.post('https://qb-phone/PostAdvert', JSON.stringify({ 164 | message: Advert, 165 | url: picture 166 | })); 167 | returnDetail() 168 | } 169 | $("#new-textarea").val(' '); 170 | } else { 171 | QB.Phone.Notifications.Add("fas fa-ad", "Advertisement", "You can\'t post an empty ad!", "#ff8f1a", 2000); 172 | } 173 | }); 174 | 175 | -------------------------------------------------------------------------------- /qb-phone/html/css/jobcenter.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css2?family=Roboto:wght@300&display=swap'); 2 | @import "https://assets.nopixel.net/web/fonts/gilroy/stylesheet.css"; 3 | .job-app { 4 | display: none; 5 | height: 100%; 6 | width: 100%; 7 | overflow: hidden; 8 | background-image: url("../img/backgrounds/bg.png"); 9 | background-position: center; 10 | background-repeat: no-repeat; 11 | background-size: cover; 12 | /* background: linear-gradient(158deg, rgba(24,25,46,1) 0%, rgba(15,18,27,1) 32%, rgba(24,25,46,1) 68%, rgba(15,18,27,1) 100%); */ 13 | } 14 | 15 | .job-header { 16 | position: absolute; 17 | width: 90%; 18 | height: 10%; 19 | /* top: 8%; */ 20 | left: 0; 21 | right: 0; 22 | color: white; 23 | /* font-family: 'Gilroy'; */ 24 | font-size: 1.5vh; 25 | /* margin: 0 auto; */ 26 | } 27 | 28 | .job-header > p { 29 | text-align: center; 30 | line-height: 12vh; 31 | text-indent: 2vh; 32 | font-family: 'Gilroy'; 33 | font-size: 2vh; 34 | /* margin: 0 0 0 9vh; */ 35 | } 36 | 37 | .job-header > span { 38 | position: absolute; 39 | top: 8vh; 40 | left: 5vh; 41 | font-size: 1.2vh; 42 | height: 2vh; 43 | color: white; 44 | } 45 | 46 | .job-list { 47 | position: absolute; 48 | width: 90%; 49 | height: 80%; 50 | margin: 0 auto; 51 | left: 0; 52 | right: 0; 53 | bottom: 3%; 54 | border-radius: .5vh; 55 | overflow-y: scroll; 56 | } 57 | 58 | .job-list::-webkit-scrollbar { 59 | display: none; 60 | } 61 | 62 | .job-class-body-job{ 63 | color: #ffffff; 64 | margin-bottom: 0.5vh; 65 | padding: 1vh 1.5vh; 66 | /* Adjust the padding here */ 67 | border-radius: 0.463vh; 68 | background: rgb(25,103,117); 69 | background: linear-gradient(101deg, rgba(25,103,117,1) 0%, rgba(26,137,149,0.26094187675070024) 85%); 70 | overflow: hidden; 71 | /* box-shadow: 0rem 0rem 0.2rem 0.02rem #000000a6; */ 72 | } 73 | .job-class-body-job:hover{ 74 | background: rgb(28,136,148); 75 | background: radial-gradient(circle, rgba(28,136,148,1) 0%, rgba(8,203,215,1) 100%); 76 | } 77 | 78 | .job-showitems-other{ 79 | margin-left: 35%; 80 | position: absolute; 81 | display: initial; 82 | visibility: hidden; 83 | } 84 | 85 | .job-title { 86 | font-size: 14px; 87 | } 88 | 89 | #job-icon-class2{ 90 | margin-left: 30%; 91 | font-size: 275%; 92 | } 93 | 94 | #job-icon-class{ 95 | float: inline-end; 96 | font-size: 1.8vh; 97 | padding: 0.8vh; 98 | border-radius: 0.3vh; 99 | width: 4vh; 100 | height: auto; 101 | } 102 | #job-icon-left-class{ 103 | text-align: center; 104 | font-size: 1.8vh; 105 | background: #15586D; 106 | padding: 0.8vh; 107 | border-radius: 0.3vh; 108 | width: 4vh; 109 | height: auto; 110 | } 111 | .job-class-body-job:hover .job-showitems-other{ 112 | visibility: visible; 113 | } 114 | 115 | #job-icon-class:hover{ 116 | color: #8ee074; 117 | } 118 | 119 | .jobcenter-input-group-name{ 120 | display: block; 121 | position: absolute; 122 | background: rgb(11, 14, 21); 123 | border: none; 124 | width: 90%; 125 | margin: 0 auto; 126 | left: -2%; 127 | right: 0; 128 | opacity: 1; 129 | height: auto; 130 | border-radius: 0.5vh; 131 | outline: none; 132 | text-indent: .5vh; 133 | z-index: 100; 134 | color: #FFFFFF; 135 | height: 4vh; 136 | top:2vh; 137 | } 138 | 139 | .jobcenter-input-password { 140 | display: block; 141 | position: absolute; 142 | background: rgb(11, 14, 21); 143 | border: none; 144 | width: 90%; 145 | margin: 0 auto; 146 | left: -2%; 147 | right: 0; 148 | opacity: 1; 149 | height: auto; 150 | border-radius: 0.5vh; 151 | outline: none; 152 | text-indent: .5vh; 153 | z-index: 100; 154 | color: #FFFFFF; 155 | height: 4vh; 156 | top:7vh; 157 | } 158 | .jobcenter-input-join-password { 159 | display: block; 160 | position: absolute; 161 | background: rgb(11, 14, 21); 162 | border: none; 163 | width: 90%; 164 | margin: 0 auto; 165 | left: -2%; 166 | right: 0; 167 | opacity: 1; 168 | height: auto; 169 | border-radius: 0.5vh; 170 | outline: none; 171 | text-indent: .5vh; 172 | z-index: 100; 173 | color: #FFFFFF; 174 | height: 4vh; 175 | } 176 | 177 | .jobcenter-input-password2 { 178 | display: block; 179 | position: absolute; 180 | background: rgb(11, 14, 21); 181 | border: none; 182 | width: 90%; 183 | margin: 0 auto; 184 | left: -2%; 185 | right: 0; 186 | opacity: 1; 187 | height: auto; 188 | border-radius: 0.5vh; 189 | outline: none; 190 | text-indent: .5vh; 191 | z-index: 100; 192 | color: #FFFFFF; 193 | height: 4vh; 194 | top:12vh; 195 | } 196 | .groups-menu-body { 197 | display: none; 198 | position: absolute; 199 | height: 40%; 200 | width: 90%; 201 | background: linear-gradient(158deg, rgba(24,25,46,1) 0%, rgba(15,18,27,1) 32%, rgba(24,25,46,1) 68%, rgba(15,18,27,1) 100%); 202 | box-shadow: inset 0px 0px 5px 0px rgba(0, 0, 0, 0.247); 203 | margin: 0 auto; 204 | left: 0; 205 | right: 0; 206 | top: 8.5vh; 207 | border-radius: 0.5vh; 208 | overflow: hidden; 209 | z-index: 700; 210 | border: 1px solid rgba(123,171,248,1); 211 | } 212 | .groups-menu-main { 213 | position: absolute; 214 | transform: translate(-50%, -50%); 215 | top: 1vh; 216 | left: 50%; 217 | padding-top: 10%; 218 | padding-bottom: 5%; 219 | width: 100%; 220 | border-radius: .5vh; 221 | } -------------------------------------------------------------------------------- /qb-phone/client/employment.lua: -------------------------------------------------------------------------------- 1 | -- Use This Callback Whenever You Need To Get A the information -- 2 | local cachedEmployees = {} 3 | local myJobs = {} 4 | 5 | -- NUI Callbacks 6 | 7 | RegisterNUICallback('GetJobs', function(_, cb) 8 | cb(myJobs) 9 | end) 10 | 11 | RegisterNUICallback('dutyStatus', function(_, cb) 12 | cb({ 13 | job = QBCore.Functions.GetPlayerData().job.name, 14 | duty = QBCore.Functions.GetPlayerData().job.onduty 15 | }) 16 | end) 17 | 18 | 19 | RegisterNUICallback('GetEmployees', function(data, cb) 20 | if not data.job then return end 21 | 22 | local employees = cachedEmployees[data.job] or {} 23 | 24 | cb(employees) 25 | end) 26 | 27 | RegisterNUICallback('SendEmployeePayment', function(data, cb) 28 | if not data.job or not data.cid or not data.amount then return end 29 | 30 | TriggerServerEvent('qb-phone:server:SendEmploymentPayment', data.job, data.cid, data.amount) 31 | cb("ok") 32 | end) 33 | 34 | RegisterNUICallback('RemoveEmployee', function(data, cb) 35 | if not data or not data.job or not data.cid then return end 36 | 37 | TriggerServerEvent('qb-phone:server:fireUser', data.job, data.cid) 38 | 39 | cb("ok") 40 | end) 41 | 42 | RegisterNUICallback('ChangeRole', function(data, cb) 43 | if not data then return end 44 | 45 | TriggerServerEvent('qb-phone:server:gradesHandler', data.job, tostring(data.cid), data.grade) 46 | cb("ok") 47 | end) 48 | 49 | RegisterNUICallback('ClockIn', function(data, cb) 50 | if not data or not data.job then return end 51 | 52 | TriggerServerEvent('qb-phone:server:clockOnDuty', data.job) 53 | cb("ok") 54 | end) 55 | 56 | RegisterNUICallback('HireFucker', function(data, cb) 57 | if not data then return end 58 | if not data.job or not data.stateid or not data.grade then return end 59 | 60 | TriggerServerEvent('qb-phone:server:hireUser', data.job, data.stateid, data.grade) 61 | cb("ok") 62 | end) 63 | 64 | RegisterNUICallback('ChargeMF', function(data, cb) 65 | if not data or not data.stateid or not data.amount or not data.job then return end 66 | 67 | TriggerServerEvent('qb-phone:server:ChargeCustomer', data.stateid, data.amount, data.note, data.job) 68 | cb("ok") 69 | end) 70 | 71 | RegisterNetEvent('qb-phone:client:JobsHandler', function(job, employees) 72 | if not job or not employees then return end 73 | if not cachedEmployees[job] then return end 74 | 75 | cachedEmployees[job] = {} 76 | for _, v in pairs(employees) do 77 | cachedEmployees[job][#cachedEmployees[job]+1] = { 78 | cid = v.cid, 79 | name = v.name, 80 | grade = tonumber(v.grade), 81 | } 82 | table.sort(cachedEmployees[job], function(a, b) 83 | return a.grade > b.grade 84 | end) 85 | end 86 | end) 87 | 88 | 89 | RegisterNetEvent('qb-phone:client:MyJobsHandler', function(job, jobTable, employees) 90 | if not QBCore.Shared.Jobs[job] then return end 91 | 92 | myJobs[job] = jobTable 93 | 94 | if employees then 95 | cachedEmployees[job] = {} 96 | for _, v in pairs(employees) do 97 | cachedEmployees[job][#cachedEmployees[job]+1] = { 98 | cid = v.cid, 99 | name = v.name, 100 | grade = tonumber(v.grade), 101 | } 102 | table.sort(cachedEmployees[job], function(a, b) 103 | return a.grade > b.grade 104 | end) 105 | end 106 | else 107 | cachedEmployees[job] = nil 108 | end 109 | end) 110 | 111 | AddEventHandler('onResourceStart', function(resource) 112 | if resource == GetCurrentResourceName() then 113 | Wait(300) 114 | 115 | local employees, myShit = lib.callback.await('qb-phone:server:GetMyJobs', false) 116 | if not employees then print('qb-phone first start might be enabled on the server, disable it!') return end 117 | 118 | for k, _ in pairs(employees) do 119 | for _, v in pairs(employees[k]) do 120 | if not cachedEmployees[k] then cachedEmployees[k] = {} end 121 | cachedEmployees[k][#cachedEmployees[k]+1] = { 122 | cid = v.cid, 123 | name = v.name, 124 | grade = tonumber(v.grade), 125 | } 126 | end 127 | table.sort(cachedEmployees[k], function(a, b) 128 | return a.grade > b.grade 129 | end) 130 | end 131 | 132 | if myShit then 133 | for k, v in pairs(myShit) do 134 | if QBCore.Shared.Jobs[k] and not myJobs[k] then myJobs[k] = v end 135 | end 136 | end 137 | end 138 | end) 139 | 140 | RegisterNetEvent('QBCore:Client:OnPlayerLoaded', function() 141 | local employees, myShit = lib.callback.await('qb-phone:server:GetMyJobs', false) 142 | for k, _ in pairs(employees) do 143 | for _, v in pairs(employees[k]) do 144 | if not cachedEmployees[k] then cachedEmployees[k] = {} end 145 | cachedEmployees[k][#cachedEmployees[k]+1] = { 146 | cid = v.cid, 147 | name = v.name, 148 | grade = tonumber(v.grade), 149 | } 150 | end 151 | table.sort(cachedEmployees[k], function(a, b) 152 | return a.grade > b.grade 153 | end) 154 | end 155 | 156 | 157 | if myShit then 158 | for k, v in pairs(myShit) do 159 | if QBCore.Shared.Jobs[k] and not myJobs[k] then myJobs[k] = v end 160 | end 161 | end 162 | end) 163 | 164 | RegisterNetEvent('QBCore:Client:OnPlayerUnload', function() -- Reset all variables 165 | myJobs = {} 166 | cachedEmployees = {} 167 | end) 168 | -------------------------------------------------------------------------------- /qb-phone/README.md: -------------------------------------------------------------------------------- 1 | # Installation steps 2 | 3 | ## General Setup 4 | General setup is quite easy, delete your OLD qb-phone 5 | if you server havent been running previously then go ahead and run the provided SQL file in your database. 6 | 7 | If your server has been running qb-phone previously please update your sql while being carefull and take a backup so you have no data lost. 8 | 9 | After the SQL setup you can now drop the resource into your server and start it up while you conduct the next steps. 10 | 11 | ## Employment setup 12 | Setting up employment and multijob can be quite tricky so make sure to reread this if you have any issues... 13 | If you already have a multijob system and you do not wish to use this then you can skip this step. 14 | 15 | 16 | 1. Head over to qb-phone/server/employment.lua and change local FirstStart from false to true like shown below 17 | 18 | ```lua 19 | local FirstStart = true 20 | ``` 21 | 22 | 2. Start the script and make sure it's fully done, it can take a while depending on your current playerbase (ensure qb-phone in console or f8) 23 | 24 | 3. Head over to qb-phone/server/employment.lua again and change the FirstStart to false 25 | 26 | Like so: 27 | ```lua 28 | local FirstStart = false 29 | ``` 30 | 31 | 4. Headover to your qb-core/server/commands.lua and find the follow command 'setjob' 32 | 33 | replace the commands with the code below: 34 | ```lua 35 | QBCore.Commands.Add('setjob', 'Set A Players Job (Admin Only)', { { name = 'id', help = 'Player ID' }, { name = 'job', help = 'Job name' }, { name = 'grade', help = 'Grade' } }, true, function(source, args) 36 | local Player = QBCore.Functions.GetPlayer(tonumber(args[1])) 37 | if Player then 38 | local job = tostring(args[2]) 39 | local grade = tonumber(args[3]) 40 | local sgrade = tostring(args[3]) 41 | local jobInfo = QBCore.Shared.Jobs[job] 42 | if jobInfo then 43 | if jobInfo["grades"][sgrade] then 44 | Player.Functions.SetJob(job, grade) 45 | exports['qb-phone']:hireUser(job, Player.PlayerData.citizenid, grade) 46 | else 47 | TriggerClientEvent('QBCore:Notify', source, "Not a valid grade", 'error') 48 | end 49 | else 50 | TriggerClientEvent('QBCore:Notify', source, "Not a valid job", 'error') 51 | end 52 | else 53 | TriggerClientEvent('QBCore:Notify', source, Lang:t('error.not_online'), 'error') 54 | end 55 | end, 'admin') 56 | ``` 57 | 58 | 5. Now below that add the new command called 'removejob' like shown below 59 | 60 | ```lua 61 | QBCore.Commands.Add('removejob', 'Removes A Players Job (Admin Only)', { { name = 'id', help = 'Player ID' }, { name = 'job', help = 'Job name' } }, true, function(source, args) 62 | local Player = QBCore.Functions.GetPlayer(tonumber(args[1])) 63 | if Player then 64 | if Player.PlayerData.job.name == tostring(args[2]) then 65 | Player.Functions.SetJob("unemployed", 0) 66 | end 67 | exports['qb-phone']:fireUser(tostring(args[2]), Player.PlayerData.citizenid) 68 | else 69 | TriggerClientEvent('QBCore:Notify', source, Lang:t('error.not_online'), 'error') 70 | end 71 | end, 'admin') 72 | ``` 73 | 74 | 6. If you use qb-cityhall then u have to Find ApplyJob in qb-cityhall/server/main.lua and replace with this one 75 | 76 | ```lua 77 | RegisterNetEvent('qb-cityhall:server:ApplyJob', function(job, cityhallCoords) 78 | local src = source 79 | local Player = QBCore.Functions.GetPlayer(src) 80 | if not Player then return end 81 | local ped = GetPlayerPed(src) 82 | local pedCoords = GetEntityCoords(ped) 83 | local JobInfo = QBCore.Shared.Jobs[job] 84 | if #(pedCoords - cityhallCoords) >= 20.0 or not availableJobs[job] then 85 | return DropPlayer(source, "Attempted exploit abuse") 86 | end 87 | Player.Functions.SetJob(job, 0) 88 | exports['qb-phone']:hireUser(job, Player.PlayerData.citizenid, 0) 89 | TriggerClientEvent('QBCore:Notify', src, Lang:t('info.new_job', {job = JobInfo.label})) 90 | end) 91 | ``` 92 | 93 | 7. Throw the `dialing.ogg` into your interact-sound/client/html/sounds file, if you don't already have it 94 | 95 | 8. Restart your server fully to get the new commands working and also to get the phone fully working. 96 | 97 | 98 | It should now look like this 99 | 100 | ![QBCore Commands](https://i.gyazo.com/beb2bd18c02088c184e5e381a9f4962a.png) 101 | 102 | 103 | ## Casino Setup 104 | 105 | 1. Head over to your qb-core/config.lua 106 | 2. Replace the following code with below code 107 | ```lua 108 | -- Old 109 | QBConfig.Money.MoneyTypes = { cash = 500, bank = 5000, crypto = 0 } -- type = startamount - Add or remove money types for your server (for ex. blackmoney = 0), remember once added it will not be removed from the database! 110 | QBConfig.Money.DontAllowMinus = { 'cash', 'crypto' } -- Money that is not allowed going in minus 111 | ``` 112 | ```lua 113 | -- NEW 114 | QBConfig.Money.MoneyTypes = { cash = 500, bank = 5000, casino = 0 } -- type = startamount - Add or remove money types for your server (for ex. blackmoney = 0), remember once added it will not be removed from the database! 115 | QBConfig.Money.DontAllowMinus = { 'cash', 'casino' } -- Money that is not allowed going in minus 116 | ``` 117 | 118 | ## Crypto Setup 119 | 120 | 1. Head over to your qb-core/server/Player.lua 121 | 2. Paste the below code into your metadata if you dont know what is metadata it looks something like this: PlayerData.metadata['inside'] 122 | 123 | Code to be pasted 124 | ```lua 125 | PlayerData.metadata['crypto'] = PlayerData.metadata['crypto'] or { 126 | ["shung"] = 0, 127 | ["gne"] = 0, 128 | ["xcoin"] = 0, 129 | ["lme"] = 0 130 | } 131 | ``` 132 | 133 | It should now all look like this: 134 | 135 | ![Metadata Table](https://i.gyazo.com/5422c6ebd1ede57ab523f2e1e07218c4.png) 136 | -------------------------------------------------------------------------------- /qb-phone/html/js/casino.js: -------------------------------------------------------------------------------- 1 | var PlayerNameOf = null 2 | var PlayerChanseOf = null 3 | var PlayerIDOf = null 4 | 5 | function LoadCasinoJob(){ 6 | var PlayerJob = QB.Phone.Data.PlayerData.job.name; 7 | if (PlayerJob == "pilot"){ 8 | $(".casino-dashboard-boss").css({"display":"block"}); 9 | $("#casino-Winer-this").css({"display":"block"}); 10 | } else { 11 | $(".casino-dashboard-boss").css({"display":"none"}); 12 | $("#casino-Winer-this").css({"display":"none"}); 13 | } 14 | 15 | CheckStatus(); 16 | 17 | $.post('https://qb-phone/CheckHasBetTable', JSON.stringify({}), function(HasTable){ 18 | if(JSON.stringify(HasTable) != "[]"){ 19 | AddToChat(HasTable) 20 | }else{ 21 | $(".casino-list").html(""); 22 | var AddOption = '
No Event
'+ 23 | '
'+ 24 | '
'+ 25 | '
'+ 26 | '
' 27 | $('.casino-list').append(AddOption); 28 | } 29 | }); 30 | } 31 | 32 | $(document).on('click', '.casino-dashboard-boss', function(e){ 33 | e.preventDefault(); 34 | ClearInputNew() 35 | $('#casino-dashboard-box').fadeIn(350); 36 | }); 37 | 38 | $(document).on('click', '#casino_create_bet', function(e){ 39 | e.preventDefault(); 40 | ClearInputNew() 41 | $('#casino-dashboard-box').fadeOut(350); 42 | $('#casino-dashboard-box-create-bet').fadeIn(350); 43 | }); 44 | 45 | $(document).on('click', '#casino_delete', function(e){ 46 | e.preventDefault(); 47 | $.post('https://qb-phone/CasinoDeleteTable', JSON.stringify({})); 48 | }); 49 | 50 | $(document).on('click', '#casino_status', function(e){ 51 | e.preventDefault(); 52 | $.post('https://qb-phone/casino_status', JSON.stringify({})); 53 | CheckStatus(); 54 | }); 55 | 56 | $(document).on('click', '#casino-submit-bet', function(e){ 57 | e.preventDefault(); 58 | var InName = $(".casino_input_name").val(); 59 | var InChanse = $(".casino_input_Chanse").val(); 60 | if (InName != "" && InChanse != "" && InChanse >= 1.0){ 61 | $.post('https://qb-phone/CasinoAddBet', JSON.stringify({ 62 | name: InName, 63 | chanse: InChanse, 64 | })); 65 | ClearInputNew(); 66 | } else { 67 | QB.Phone.Notifications.Add("fas fa-exclamation-circle", "System", "Fields are incorrect") 68 | } 69 | }); 70 | 71 | $(document).ready(function(){ 72 | window.addEventListener('message', function(event) { 73 | switch(event.data.action) { 74 | case "BetAddToApp": 75 | AddToChat(event.data.datas) 76 | break; 77 | } 78 | }) 79 | }); 80 | 81 | function AddToChat(data){ 82 | $(".casino-list").html(""); 83 | if(JSON.stringify(data) != "[]"){ 84 | for (const [k, v] of Object.entries(data)) { 85 | var firstLetter = v.Name.substring(0, 1); 86 | var Fulltext = firstLetter.toUpperCase()+(v.Name).replace(firstLetter,'') 87 | 88 | var AddOption = '
'+ 89 | '
'+Fulltext+'
'+ 90 | '
'+ 91 | '
' 92 | $('.casino-list').append(AddOption); 93 | } 94 | }else{ 95 | $(".casino-list").html(""); 96 | var AddOption = '
No Event
'+ 97 | '
'+ 98 | '
'+ 99 | '
'+ 100 | '
' 101 | $('.casino-list').append(AddOption); 102 | } 103 | } 104 | 105 | function CheckStatus(){ 106 | $.post('https://qb-phone/CheckHasBetStatus', JSON.stringify({}), function(HasStatus){ 107 | if (HasStatus){ 108 | $("#casino_status").html("Status: Betting Enabled"); 109 | }else{ 110 | $("#casino_status").html("Status: Betting Disabled"); 111 | } 112 | }); 113 | } 114 | 115 | 116 | $(document).on('click', '#casino-click-beting', function(e){ 117 | e.preventDefault(); 118 | PlayerNameOf = $(this).data('name') 119 | PlayerChanseOf = $(this).data('chanse') 120 | PlayerIDOf = $(this).data('id') 121 | $("#casino-info-player").html(PlayerNameOf); 122 | $("#casino-info-total").html("0 Dollars"); 123 | $("#casino-info-chanse").html("x"+PlayerChanseOf); 124 | $('#casin-bet-boxing-player').fadeIn(350); 125 | }); 126 | 127 | $(".casino-amount-for-bet-player").keyup(function(){ 128 | var input = this.value 129 | var MoneyAmount = input * PlayerChanseOf 130 | 131 | $("#casino-info-total").html(MoneyAmount+" Dollars"); 132 | }); 133 | 134 | $(document).on('click', '#casino-end-task-accept', function(e){ 135 | e.preventDefault(); 136 | var Amount = $(".casino-amount-for-bet-player").val(); 137 | if (Amount != "" && Amount >= 1.0){ 138 | $.post('https://qb-phone/BettingAddToTable', JSON.stringify({ 139 | amount: Amount, 140 | chanse: PlayerChanseOf, 141 | player: PlayerNameOf, 142 | id: PlayerIDOf, 143 | })); 144 | ClearInputNew(); 145 | } else { 146 | QB.Phone.Notifications.Add("fas fa-exclamation-circle", "System", "Fields are incorrect") 147 | } 148 | }); 149 | 150 | $(document).on('click', '#casino-Winer-this', function(e){ 151 | e.preventDefault(); 152 | $.post('https://qb-phone/WineridCasino', JSON.stringify({ 153 | id: PlayerIDOf, 154 | })); 155 | }); -------------------------------------------------------------------------------- /qb-phone/html/js/debt.js: -------------------------------------------------------------------------------- 1 | let debt 2 | 3 | // Search 4 | 5 | $(document).ready(function(){ 6 | $("#debt-search").on("keyup", function() { 7 | var value = $(this).val().toLowerCase(); 8 | $(".debt-list").filter(function() { 9 | $(this).toggle($(this).text().toLowerCase().indexOf(value) > -1); 10 | }); 11 | }); 12 | }); 13 | 14 | // Functions 15 | 16 | var formatter = new Intl.NumberFormat('en-US', { 17 | style: 'currency', 18 | currency: 'USD', 19 | }); 20 | 21 | function ConfirmationFrame() { 22 | $('.spinner-input-frame').css("display", "flex"); 23 | setTimeout(function () { 24 | $('.spinner-input-frame').css("display", "none"); 25 | $('.checkmark-input-frame').css("display", "flex"); 26 | setTimeout(function () { 27 | $('.checkmark-input-frame').css("display", "none"); 28 | }, 2000) 29 | }, 1000) 30 | } 31 | 32 | // Debt Shit 33 | 34 | // Block 35 | $(document).on('click', '.debt-list', function(e){ 36 | e.preventDefault(); 37 | 38 | $(this).find(".debt-block").toggle(); 39 | var Id = $(this).attr('id'); 40 | debt = Id 41 | }); 42 | 43 | // Pay All Tab 44 | $(document).on('click', '.send-all-box', function(e){ 45 | e.preventDefault(); 46 | 47 | var Id = $(this).parent().parent().parent().attr('id'); 48 | debt = Id 49 | setTimeout(function(){ 50 | ConfirmationFrame() 51 | }, 150); 52 | $.post('https://qb-phone/SendAllPayment', JSON.stringify({ 53 | id: Id, 54 | })); 55 | }); 56 | 57 | // Pay Minimum 58 | $(document).on('click', '.send-minimum-box', function(e){ 59 | e.preventDefault(); 60 | 61 | var Id = $(this).parent().parent().parent().attr('id'); 62 | debt = Id 63 | setTimeout(function(){ 64 | ConfirmationFrame() 65 | }, 150); 66 | $.post('https://qb-phone/SendMinimumPayment', JSON.stringify({ 67 | id: Id, 68 | })); 69 | }); 70 | 71 | function LoadDebtJob(data){ 72 | $(".debts-list").html(""); 73 | if(data) { 74 | Object.keys(data).map(function(element, index){ 75 | if (element === 'assets'){ 76 | $(".debts-list").append(`

Asset Fees

`); 77 | }else if (element === 'loan'){ 78 | $(".debts-list").append(`

Loan Payment

`); 79 | }else if (element === 'fine'){ 80 | $(".debts-list").append(`

Bill Payments

`); 81 | } 82 | Object.keys(data[element]).map(function(element2, _){ 83 | if (element === 'assets'){ 84 | $(".debts-list").append('
'+data[element][element2].car+' '+formatter.format(data[element][element2].totalamount)+'' + 85 | '
' + 86 | '
'+data[element][element2].sender+'
' + 87 | '
'+data[element][element2].plate+'
' + 88 | '
in '+data[element][element2].display+'
' + 89 | '
PAY
' + 90 | '
' + 91 | '
'); 92 | 93 | } else if (element === 'loan'){ 94 | $(".debts-list").append('
'+data[element][element2].car+' '+formatter.format(data[element][element2].totalamount)+'' + 95 | '
' + 96 | '
'+data[element][element2].sender+'
' + 97 | '
'+data[element][element2].plate+'
' + 98 | '
in '+data[element][element2].display+'
' + 99 | '
PAY MINIMUMPAY ALL
' + 100 | '
' + 101 | '
'); 102 | } else if (element === 'fine'){ 103 | $(".debts-list").append('
'+data[element][element2].name+' '+formatter.format(data[element][element2].totalamount)+' '+data[element][element2].paybacks+"/"+data[element][element2].totalPays+'' + 104 | '
' + 105 | '
'+data[element][element2].sender+'
' + 106 | '
'+data[element][element2].notes+'
' + 107 | '
in '+data[element][element2].display+'
' + 108 | '
PAY MINIMUMPAY ALL
' + 109 | '
' + 110 | '
'); 111 | } 112 | $("#debt-"+data[element][element2].id).data('debtId', element2); 113 | }) 114 | }) 115 | } 116 | } -------------------------------------------------------------------------------- /qb-phone/server/crypto.lua: -------------------------------------------------------------------------------- 1 | -- exports['qb-phone']:RemoveCrypto(Player, type, amount) 2 | local function RemoveCrypto(src, type, amount) 3 | if not src then return end 4 | local Player = QBCore.Functions.GetPlayer(src) 5 | if not Player or not type or not amount then return end 6 | 7 | local Crypto = Player.PlayerData.metadata.crypto 8 | if not Crypto then return end 9 | amount = tonumber(amount) 10 | if amount < 1 then return false end 11 | 12 | if (Crypto[type] - amount) >= 0 then 13 | Crypto[type] -= amount 14 | Player.Functions.SetMetaData("crypto", Crypto) 15 | TriggerClientEvent('qb-phone:client:UpdateCrypto', src) 16 | return true 17 | else 18 | return false 19 | end 20 | end exports("RemoveCrypto", RemoveCrypto) 21 | 22 | 23 | -- exports['qb-phone']:hasEnough(Player, type, amount) 24 | local function hasEnough(src, type, amount) 25 | if not src then return end 26 | local Player = QBCore.Functions.GetPlayer(src) 27 | 28 | if not Player or not type or not amount then return end 29 | 30 | local Crypto = Player.PlayerData.metadata.crypto 31 | 32 | if not Crypto then return end 33 | if Crypto[type] - tonumber(amount) >= 0 then 34 | return true 35 | else 36 | return false 37 | end 38 | end exports("hasEnough", hasEnough) 39 | 40 | 41 | -- exports['qb-phone']:AddCrypto(Player, type, amount) 42 | local function AddCrypto(src, type, amount) 43 | if not src then return end 44 | local Player = QBCore.Functions.GetPlayer(src) 45 | 46 | if not Player or not type or not amount then return false end 47 | 48 | local Crypto = Player.PlayerData.metadata.crypto 49 | 50 | if not Crypto then return false end 51 | Crypto[type] = Crypto[type] + tonumber(amount) 52 | Player.Functions.SetMetaData("crypto", Crypto) 53 | TriggerClientEvent('qb-phone:client:UpdateCrypto', src) 54 | 55 | return true 56 | end exports("AddCrypto", AddCrypto) 57 | 58 | local function GetConfig(metadata) 59 | for k, v in pairs(Config.CryptoCoins) do 60 | if v.metadata == metadata then 61 | return k 62 | end 63 | end 64 | end 65 | 66 | RegisterNetEvent('qb-phone:server:PurchaseCrypto', function(type, amount) 67 | local src = source 68 | local Player = QBCore.Functions.GetPlayer(src) 69 | if not Player or not Player.PlayerData.metadata.crypto[type] then return end -- if the crypto dosnt exist 70 | local v = Config.CryptoCoins[GetConfig(type)] 71 | local cashAmount = tonumber(amount) * v.value 72 | 73 | if not v.purchase then return end -- Only modders should be only to do this so no need to send a message to client 74 | 75 | local txt = "Purchased " .. amount .. "x " .. v.abbrev 76 | 77 | if Player.PlayerData.money.bank >= cashAmount then 78 | Player.Functions.RemoveMoney('bank', cashAmount, txt) 79 | TriggerClientEvent('qb-phone:client:CustomNotification', src, 80 | "WALLET", 81 | "You Purchased "..amount.." "..type.."!", 82 | "fas fa-chart-line", 83 | "#D3B300", 84 | 7500 85 | ) 86 | 87 | if Config.RenewedBanking then 88 | local cid = Player.PlayerData.citizenid 89 | local name = ("%s %s"):format(Player.PlayerData.charinfo.firstname, Player.PlayerData.charinfo.lastname) 90 | exports['Renewed-Banking']:handleTransaction(cid, "Crypto Purchase", cashAmount, txt, "Los Santos Crypto", name, "withdraw") 91 | end 92 | 93 | AddCrypto(src, type, amount) 94 | else 95 | TriggerClientEvent('qb-phone:client:CustomNotification', src, 96 | "WALLET", 97 | "Not Enough Money", 98 | "fas fa-chart-line", 99 | "#D3B300", 100 | 7500 101 | ) 102 | end 103 | end) 104 | 105 | RegisterNetEvent('qb-phone:server:SellCrypto', function(type, amount) 106 | local src = source 107 | local Player = QBCore.Functions.GetPlayer(src) 108 | if not Player or not Player.PlayerData.metadata.crypto[type] then return end -- if the crypto dosnt exist 109 | local v = Config.CryptoCoins[GetConfig(type)] 110 | local cryptoAmount = tonumber(amount) * v.value 111 | 112 | if not v.sell then return end -- Only modders should be only to do this so no need to send a message to client 113 | 114 | local txt = "Sold " .. amount .. "x " .. v.abbrev 115 | 116 | if not RemoveCrypto(src, type, amount) then return end 117 | 118 | Player.Functions.AddMoney('bank', cryptoAmount, txt) 119 | TriggerClientEvent('qb-phone:client:CustomNotification', src, 120 | "WALLET", 121 | "You Sold "..amount.." "..type.."!", 122 | "fas fa-chart-line", 123 | "#D3B300", 124 | 7500 125 | ) 126 | 127 | if Config.RenewedBanking then 128 | local cid = Player.PlayerData.citizenid 129 | local name = ("%s %s"):format(Player.PlayerData.charinfo.firstname, Player.PlayerData.charinfo.lastname) 130 | exports['Renewed-Banking']:handleTransaction(cid, "Sold Crypto", cryptoAmount, txt, "Los Santos Crypto", name, "deposit") 131 | end 132 | end) 133 | 134 | RegisterNetEvent('qb-phone:server:ExchangeCrypto', function(type, amount, stateid) 135 | local src = source 136 | local Player = QBCore.Functions.GetPlayer(src) 137 | local Receiver = QBCore.Functions.GetPlayer(tonumber(stateid)) 138 | if not Player or not Player.PlayerData.metadata.crypto[type] then return end -- if the crypto dosnt exist 139 | if not Receiver then return TriggerClientEvent("QBCore:Notify", src, 'This state id does not exists!', "error") end 140 | 141 | if Player.PlayerData.citizenid ~= Receiver.PlayerData.citizenid then 142 | if RemoveCrypto(src, type, amount) then 143 | TriggerClientEvent('qb-phone:client:CustomNotification', src, 144 | "WALLET", 145 | "You sent "..amount.." "..type.."!", 146 | "fas fa-chart-line", 147 | "#D3B300", 148 | 7500 149 | ) 150 | 151 | AddCrypto(Receiver.PlayerData.source, type, amount) 152 | TriggerClientEvent('qb-phone:client:CustomNotification', Receiver.PlayerData.source, 153 | "WALLET", 154 | "You received "..amount.." "..type.."!", 155 | "fas fa-chart-line", 156 | "#D3B300", 157 | 7500 158 | ) 159 | else 160 | TriggerClientEvent('qb-phone:client:CustomNotification', src, 161 | "WALLET", 162 | "Cannot transfer crypto!", 163 | "fas fa-chart-line", 164 | "#D3B300", 165 | 7500 166 | ) 167 | 168 | end 169 | else 170 | TriggerClientEvent('qb-phone:client:CustomNotification', src, 171 | "WALLET", 172 | "Cannot send crypto to yourself!", 173 | "fas fa-chart-line", 174 | "#D3B300", 175 | 7500 176 | ) 177 | end 178 | end) 179 | --------------------------------------------------------------------------------