-- ╔══════════════════════════════════════════════════════════════════════════╗ -- ║ CODEM-PHONE SERVER EXPORTS ║ -- ╚══════════════════════════════════════════════════════════════════════════╝ --[[ GetPhoneNumberByIdentifier ───────────────────────────────────────────────────────────────────────── Retrieves a player's phone number using their identifier. @param identifier (string) Player identifier (license, steam, etc.) @return (string|nil) Phone number or nil if not found Example: local phone = exports['codem-phone']:GetPhoneNumberByIdentifier('license:abc123') ]] function GetPhoneNumberByIdentifier(identifier) if not identifier then return nil end if Config.UniquePhone then local result = MySQL.query.await('SELECT phone_number FROM codem_mphone_last_phone WHERE owner = ?', { identifier }) if result and result[1] and result[1].phone_number then return result[1].phone_number else return nil end else local result = MySQL.query.await('SELECT phone_number FROM codem_mphone_data WHERE owner = ?', { identifier }) if result and result[1] and result[1].phone_number then return result[1].phone_number else return nil end end end exports('GetPhoneNumberByIdentifier', GetPhoneNumberByIdentifier) --[[ SendMessageFromBySource ───────────────────────────────────────────────────────────────────────── Sends a system/custom message to a player's phone. @param senderPhone (string) Sender identifier ("SYSTEM", "BANK", "555-0000") @param source (number) Target player's server ID @param message (string) Message content @return success (boolean) True if sent successfully @return result (any) Message ID on success, error string on failure Examples: exports['codem-phone']:SendMessageFromBySource('SYSTEM', src, 'Welcome!') exports['codem-phone']:SendMessageFromBySource('BANK', src, 'You received $5000') local ok, res = exports['codem-phone']:SendMessageFromBySource('SYSTEM', src, 'Hello') if ok then print('ID: '..res) else print('Error: '..res) end ]] function SendMessageFromBySource(senderPhone, source, message) local PlayerData = GetValidatedPhoneData(source) if not PlayerData.success then return false, 'Invalid player data' end local targetPhone = PlayerData.phoneNumber if message == nil then return false, 'Missing message content' end if #message == 0 then return false, 'Message content cannot be empty' end if not senderPhone or not targetPhone or not message then return false, 'Missing parameters' end local channelId = GetOrCreatePrivateChannel(senderPhone, targetPhone) if not channelId then return false, 'Could not create channel' end local currentTime = os.time() local insertId = MySQL.insert.await( 'INSERT INTO codem_mphone_messages (channel_id, sender_phone, content, type) VALUES (?, ?, ?, ?)', { channelId, senderPhone, message, 'text' } ) if not insertId then return false, 'Could not save message' end MySQL.update.await( 'UPDATE codem_mphone_message_channels SET last_message = ?, last_message_at = NOW() WHERE id = ?', { message, channelId } ) local TargetID = GetSourceFromPhoneNumber(targetPhone) if TargetID then local contactInfo = GetContactInfo(targetPhone, senderPhone) TriggerClientEvent('codem-phone:client:receivemessage', TargetID, { channel_id = channelId, type = 'private', last_message_sender = senderPhone, last_message_at = currentTime, unread_count = 1, contact_info = contactInfo, last_message = message, newmessage = { { content = message, created_at = currentTime, sender_phone = senderPhone, type = 'text', id = insertId, } } }) PhoneNotification({ source = TargetID, appname = 'message', header = contactInfo.name or senderPhone, message = message }) end CheckIsDeletedMessage(channelId, targetPhone) return true, insertId end exports('SendMessageFromBySource', SendMessageFromBySource)