[{"data":1,"prerenderedAt":100},["ShallowReactive",2],{"site":3,"config-slug-site":15,"config-product-en-x3d-phone":21,"config-public-x3d-phone":95},{"site":4,"contact":10,"seo":13,"payment":14},{"name":5,"host":6,"default_locale":7,"locales":8},"X3D Developer","fivem.x3d-developer.com","th",[7,9],"en",{"discord_invite":11,"email":12,"line":12},"https:\u002F\u002Fdiscord.gg\u002FNA5kPVynFv","",{"google_site_verification":12,"bing_site_verification":12},{"bank_name":12,"account_name":12,"account_no":12,"promptpay_id":12},{"site":16,"contact":18,"seo":19,"payment":20},{"name":5,"host":6,"default_locale":7,"locales":17},[7,9],{"discord_invite":11,"email":12,"line":12},{"google_site_verification":12,"bing_site_verification":12},{"bank_name":12,"account_name":12,"account_no":12,"promptpay_id":12},{"id":22,"slug":23,"name":24,"summary":25,"price_thb":26,"license_mode":27,"cover_key":28,"cover_url":29,"category_slugs":30,"tags":32,"latest_version":55,"latest_released_at":56,"published_at":57,"has_docs":58,"config":59,"rent_price_satang":60,"description_md":61,"docs_md":62,"seo_title":63,"seo_description":64,"media":65,"versions":81},"879a5a5d-5b22-4fb5-9274-6ac3ee631904","x3d-phone","X3D Phone","Free ESX smartphone: pma-voice calls, SMS with location sharing, mobile banking, a camera with self-hosted photos, Buzz and anonymous Dark Chat.",0,"none","public\u002Fproducts\u002Fx3d-phone\u002Fcover\u002F9e0b9e2f9bc7352d.jpg","\u002Fapi\u002Fv1\u002Fmedia\u002Fpublic\u002Fproducts\u002Fx3d-phone\u002Fcover\u002F9e0b9e2f9bc7352d.jpg",[31],"hud",[33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54],"phone","โทรศัพท์","โทรศัพท์ fivem","esx phone","phone script","sms","pma-voice","dispatch","แจ้งเหตุ","ธนาคารมือถือ","buzz","dark chat","กล้อง","esx","ฟรี","free","เบอร์หน่วยงาน","ออกบิล","แชร์ตำแหน่ง","เรียกหมอ","กล้องโทรศัพท์","ไอเทมโทรศัพท์","1.1.3","2026-10-12T17:18:13.372348Z","2026-09-25T15:32:10.424119Z",true,"public",null,"A free smartphone for ESX. It comes with Phone, Messages, Contacts, Banking, Bills, Buzz, Dark Chat and Settings apps. The UI is built with Nuxt 4 and works with mouse or keyboard. Fits any city style (school \u002F community \u002F RP).\n\n---\n\n## Features\n\n- [+] Easy setup: tune everything in config, or set it from the web builder\n- [+] Real voice calls through pma-voice, mute your mic, 5 ringtones\n- [+] SMS grouped by conversation, share your location and tap to set a GPS waypoint\n- [+] Service numbers for police, EMS and mechanics, sent to the whole job with your spot\n- [+] Dispatch app: call EMS, a medic responds and gets a waypoint set\n- [+] Bill any number; police, EMS and admin bills are locked, only admins can cancel\n- [+] Mobile banking with transfers by phone number, with your own min and max\n- [+] Camera with photos stored on your own server, and an hourly limit per player\n- [+] Server-wide Buzz feed with 5 post card skins that admins can lock\n- [+] Dark Chat: anonymous rooms with nicknames and an optional room password\n- [+] Require a phone item to use it, with your own item name, or switch it off\n- [+] Write your own hooks to other scripts in addons\u002F\n\n---\n\n## What's inside\n\n- **Phone**: keypad and call history, with a badge for missed calls. Voice calls run through **pma-voice**. You can mute your microphone and pick one of five ringtones.\n- **Messages (SMS)**: one conversation per contact, with unread badges. You can **share your location**. The person who gets it taps it to set a GPS waypoint there.\n- **Contacts**: mark favourites. Contact names also show in call history and in chats.\n- **Service numbers**: text the police, EMS or mechanics and every member of that job gets it with your location. Job scripts can add or remove numbers through the `x3d_phone:registerNumber` \u002F `x3d_phone:removeNumber` events.\n- **Dispatch**: a player hits \"call EMS\" and every medic gets the call in their phone with distance and a map blip. Respond sets a waypoint and tells the caller help is coming. Any script can raise a call with one export.\n- **Bills**: bill any phone number, personally or on behalf of a job (police, EMS, mechanic, add your own). The recipient pays or declines in the phone (locked job bills such as police, EMS and admin cannot be declined or cancelled; an admin cancels them from the admin menu) and a double tap never charges twice. Personal bills pay into the biller's bank account; business bills need your own society account wired in `addons\u002Fbilling\u002Fserver.lua`.\n- **Every emoji**: a picker with groups and search, in SMS, Buzz and Dark Chat.\n- **Mobile banking**: balance and history, plus transfers to an online player's phone number. Uses the ESX `bank` account, or plug in your own banking system.\n- **Camera**: take a photo in game and send it by SMS or post, or use it for a contact, your Buzz avatar or your wallpaper. **Photos are stored on your own server.** No image host and no API key.\n- **Buzz**: one feed for the whole server. Post, like and delete your own posts. New posts show up in the in-game chat as a card with **5 skins** (default, Halloween, Christmas, Songkran, Night). Players pick one, or you lock one for the whole server.\n- **Phone item**: by default a `phone` item is required. No phone means no calls in or out, and the server enforces it.\n- **Dark Chat**: anonymous rooms with nicknames and an optional password. Nobody sees the sender's real phone number.\n- **Settings**: wallpaper, ringtone, notification sound, a keyboard-only mode, and **Alt** to switch to game controls without closing the phone.\n\n---\n\n## Copies to Discord\n\nAdd a webhook to `server.cfg` and every photo a player takes is copied to your admin Discord channel, with the player's name and identifier. The photo itself stays on your server, so in-game links never expire. A separate webhook can log SMS, posts and transfers.\n\n---\n\n## Server-side safety\n\n- The server checks every callback again. It never trusts values sent by the client.\n- SMS, posts, likes and calls are rate-limited.\n- Players can only delete their own contacts, posts and history.\n- External image links are accepted only from the hosts in `Config.ImageHosts` (or from any https site if you switch that on).\n- Uploads need a single-use token, are capped per hour, and must be real JPG\u002FPNG files.\n- Webhook URLs never reach players, and Discord posts never ping anyone.\n\n---\n\n## Make it fit your server\n\nEverything that differs between servers lives in `addons\u002F`, one file for each job:\n\n| File | Job |\n|---|---|\n| `addons\u002Fnotify\u002Fclient.lua` | Notifications: uses esx_notify or ox_lib if either is present, otherwise ESX's own. |\n| `addons\u002Fvoice\u002Fclient.lua` | Voice system. The default is pma-voice. |\n| `addons\u002Fbanking\u002Fserver.lua` | Banking. The default is the ESX `bank` account. |\n| `addons\u002Fbilling\u002Fserver.lua` | Billing: charges the payer and pays the biller (a society account must be wired by you). |\n| `addons\u002Fframework\u002Fserver.lua` \u002F `client.lua` | The framework bridge: ESX if present, else standalone. |\n| `addons\u002Fupload\u002Fclient.lua` | Photo storage. The default stores photos on your own server. |\n| `addons\u002Ffilter\u002Fserver.lua` | Blocks banned words before a message is sent. |\n| `addons\u002Flog\u002Fserver.lua` | Logs SMS, posts and Dark Chat messages. Includes a Discord webhook example. |\n\n---\n\n## Requirements\n\n- `oxmysql`\n- `es_extended` (ESX Legacy). Without it the script runs standalone, and you wire banking and billing yourself in `addons\u002F`\n- `pma-voice` (optional: without it, calls still connect but carry no audio)\n- `screenshot-basic` (optional, needed for the camera; a copy is bundled in `optional\u002F`)\n","## Installation\n\n1. Extract the zip and put the `x3d_phone` folder in `resources\u002F`. **Do not rename the folder**: every export and event uses this name.\n2. Run `install.sql` on your server database. It is safe to run again and keeps existing data.\n3. If your server has no `phone` item, run `optional\u002Fphone_item.sql`. With ox_inventory, add the item to `ox_inventory\u002Fdata\u002Fitems.lua` instead; the file has an example.\n4. If your server has no `screenshot-basic`, move `optional\u002Fscreenshot-basic\u002F` into `resources\u002F`. You can skip this; only the camera needs it.\n5. Add these lines to `server.cfg`, in this order:\n\n```\nensure oxmysql\nensure es_extended\nensure pma-voice\nensure screenshot-basic\nensure x3d_phone\n```\n\nPlayers open the phone with **F1**, the `\u002Fopenphone` command, or by using the `phone` item. While the phone is open, **Alt** switches to game controls; press it again to get the cursor back.\n\n## Requirements\n\n| Resource | Required | Used for |\n|---|---|---|\n| `es_extended` | no | ESX Legacy. Without it the script runs standalone and you wire banking and billing yourself in `addons\u002F` (see `Config.Framework`) |\n| `oxmysql` | yes | database |\n| `pma-voice` | no | call audio; without it calls connect but carry no audio |\n| `screenshot-basic` | no | the camera; a copy is bundled in `optional\u002F` |\n| `chat` (FiveM) | no | post cards in chat |\n\nNo image host, no API key, and no other software to install.\n\n---\n\n## All settings: `config\u002Fconfig.lua`\n\n### General\n\n| Setting | Default | Meaning |\n|---|---|---|\n| `Config.Locale` | `'th'` | Language of the phone and its messages: `'th'` or `'en'` |\n| `Config.Framework` | `'auto'` | `'auto'` (ESX if present, else standalone) `\\| 'esx' \\| 'standalone'` |\n| `Config.Debug` | `false` | `true` prints logs to the server console |\n| `Config.OpenKey` | `'F1'` | Key that opens the phone. Players can rebind it in Settings > Key Bindings > FiveM. This value only applies to a player's first join. |\n| `Config.DefaultContacts` | `{}` | Contacts added to every new number, e.g. `{ phone = '911', name = 'Police' }` |\n\n### Phone item\n\n| Setting | Default | Meaning |\n|---|---|---|\n| `Config.UseItem` | `true` | The item must be in the inventory to open the phone, call, answer and get SMS alerts |\n| `Config.PhoneItem` | `'phone'` | Item name. You can use one your server already has, e.g. `'iphone'` |\n\nWith `UseItem` on:\n- No item: the phone does not open, and every server callback refuses. Triggering events by hand does not get past this.\n- A player without the item cannot be called. The caller sees \"unavailable\" and the call is logged as missed.\n- SMS are still stored, but no alert shows until the player has the item.\n- If the item leaves the inventory while the phone is open (dropped or taken), the phone closes and any call ends.\n\n### Calls\n\n| Setting | Default | Meaning |\n|---|---|---|\n| `Config.UseVoice` | `true` | Use pma-voice for call audio |\n| `Config.CallChannelStart` | `1000` | First pma-voice channel used for calls. Change it only if it collides with another script. |\n| `Config.CallTimeout` | `30` | Seconds before an unanswered call ends |\n| `Config.Ringtones` | 5 sounds | Ringtones; each maps to a GTA V sound |\n| `Config.NotificationSounds` | 3 sounds | Message alert sounds |\n| `Config.RingtonePreviewMs` | `3000` | Length of `\u002Ftestringtone` and `\u002Ftestdialtone` |\n\n> `Config.Ringtones`, `Config.NotificationSounds` and `Config.Wallpapers` are what the server checks a player's choice against. You can remove an option in the config. Adding a new option also needs a change to the phone's web UI.\n\n### Messages\n\nEmoji work in every text box (SMS, Buzz, Dark Chat), with a picker holding all 3,600+ emoji in 9 groups plus search. Lengths are counted in real characters, so Thai text and emoji are not over-counted.\n\n| Setting | Default | Meaning |\n|---|---|---|\n| `Config.MaxMessageLength` | `500` | Maximum length of an SMS or a Dark Chat message |\n\n### Buzz and post card skins\n\n| Setting | Default | Meaning |\n|---|---|---|\n| `Config.Buzz.ToChat` | `true` | New posts appear in everyone's in-game chat |\n| `Config.Buzz.Themes` | all 5 | Skins on offer: `default`, `halloween`, `christmas`, `songkran`, `night` |\n| `Config.Buzz.DefaultTheme` | `'default'` | Skin for players who have not picked one |\n| `Config.Buzz.PlayerTheme` | `true` | `true`: players pick their skin in Settings. `false`: everyone uses `DefaultTheme`. |\n\n**Example:** lock the whole server to Halloween for the event:\n\n```lua\nConfig.Buzz = {\n    ToChat = true,\n    Themes = { 'halloween' },\n    DefaultTheme = 'halloween',\n    PlayerTheme = false,\n}\n```\n\nPost cards use FiveM's standard `chat` resource. x3d_phone adds its own styles through `chat_theme` and leaves your chat theme alone. Post text is always escaped, so players cannot inject HTML into chat.\n\n### Service numbers (police \u002F EMS \u002F mechanic) and job scripts\n\n| Setting | Default | Meaning |\n|---|---|---|\n| `Config.Dispatch.Numbers` | police, ambulance, mechanic | Service numbers: `number = { label = 'Shown name', jobs = { 'job' }, coords = true }` |\n| `Config.Dispatch.OnDutyOnly` | `false` | `true` delivers only to players on duty (ESX Legacy `job.onDuty`) |\n\n- Service numbers appear as special contacts for everyone and cannot be edited or deleted.\n- Texting `police` delivers `[Police] ...` to every online player with a job in `jobs` who has a phone. It arrives from the sender's own number with their location, so a tap sets a GPS waypoint and a reply goes straight back to the sender.\n- The location comes from the character's position on the server, so it cannot be faked. One message per service every 20 seconds.\n- If nobody from the service is online, the sender is told.\n\n**Hooking up job scripts:** the `police`, `ambulance` and `mechanic` numbers already ship in the config, and your job scripts can add or remove numbers with these events.\n\n| Event | What it does |\n|---|---|\n| `TriggerEvent('x3d_phone:registerNumber', number, label, isDispatch, hasCoords)` (server) | Adds a service number from a job script (an existing number is left alone) |\n| `TriggerEvent('x3d_phone:removeNumber', number)` (server) | Removes a registered number (numbers in the config stay) |\n| `TriggerServerEvent('x3d_phone:send', number, message, anonymous)` | Scripts that alert the police automatically (robberies etc.) send a message to a service number. With `anonymous = true` the message comes from the service number instead of the player's. |\n\n> Job scripts that call the old `esx_phone:*` event names do not work with x3d_phone; point them at the events above.\n\n#### Dispatch app\n\nResponders (players with a job in `jobs`) get a **Dispatch** app. Each call shows a title, message, distance, age and the caller's number, plus a flashing map blip, a notification and a sound.\n- **Respond** sets a GPS waypoint, tells the caller \"X accepted and is on the way\", and shows the other responders that someone has it.\n- **Close call** removes it from every phone and map. Calls nobody closes expire after `AlertSeconds`.\n- Calls come from texts to a service number, or from other scripts requesting a service.\n\n| Setting | Default | Meaning |\n|---|---|---|\n| `Config.Dispatch.AlertSeconds` | `600` | How long a call stays in the app |\n| `Config.Dispatch.CallNeedsPhone` | `false` | Whether the caller needs the phone item (a \"call EMS\" button while downed should not) |\n| `Numbers.\u003Cnumber>.request` | | Call title when someone requests the service, e.g. `'Person injured, EMS needed'` |\n| `Numbers.\u003Cnumber>.blip` | | `{ sprite, color }` of the responder's map blip |\n\n**Requesting a service from other scripts (e.g. a \"call EMS\" button on the death screen):**\n\n```lua\n-- client\nexports['x3d_phone']:RequestService('ambulance', 'Unconscious in the street')\n-- or\nTriggerServerEvent('x3d_phone:requestService', 'ambulance', 'Unconscious in the street')\n\n-- server (set your own title \u002F coords)\nexports['x3d_phone']:SendAlert('police', { source = src, title = 'Bank robbery', message = 'Pacific Standard' })\nexports['x3d_phone']:SendAlert('police', { coords = vector3(x, y, z), title = 'Alarm triggered' })\n```\n\n`RequestService` reads the location from the caller's character on the server, so it cannot be faked, and a player can call the same service once every 60 seconds.\n\n### Bills app\n\n| Setting | Default | Meaning |\n|---|---|---|\n| `Config.Billing.Enabled` | `true` | Shows the Bills app |\n| `Config.Billing.AllowPersonal` | `true` | Allows personal bills. The money goes to the biller's bank account, even when they are offline. |\n| `Config.Billing.AllowDecline` | `true` | The recipient can decline. With `false` they can only pay (the biller can still cancel). |\n| `Config.Billing.MinAmount` \u002F `MaxAmount` | `1` \u002F `1000000` | Smallest \u002F largest bill |\n| `Config.Billing.MaxOpenPerTarget` | `10` | Most unpaid bills one biller can have open to one number (anti-spam) |\n| `Config.Billing.PayFrom` | `'bank'` | Which account the payer pays from: `'bank'` or `'money'` |\n| `Config.Billing.UsersTable` | `'users'` | ESX players table, used to credit a biller who is offline |\n| `Config.Billing.Jobs` | police, ambulance, mechanic, taxi | Jobs that can bill on behalf of the business: `jobname = { label = 'Shown name', minGrade = 0, locked = true }` · `locked = true` = the biller cannot cancel and the recipient cannot decline; it is paid or an admin cancels it in x3d_adminpanel (default: police, ambulance) |\n| `Config.Billing.Admin` | `{ enabled = true, label = 'แอดมิน', groups = { 'admin', 'superadmin' }, locked = true }` | Admins can bill as \"Admin\" (e.g. fines); the money goes to `Billing.PayAdmin` at the end of `addons\u002Fbilling\u002Fserver.lua`, credited to nobody by default |\n\nLocked bills can only be cancelled in x3d_adminpanel → Phone → Unpaid bills (search by number or description, hold to cancel, with a cancel log).\n\nBusiness bills: by default there is no society account (`Billing.PaySociety` returns `false`), so the payer is not charged and the bill stays unpaid. Wire your server's society account (for example `esx_addonaccount`) in `addons\u002Fbilling\u002Fserver.lua` before you use business bills.\n\n- The recipient gets an alert at once if online. If offline, the bill waits in the app.\n- A bill can be paid once; tapping repeatedly never charges twice.\n- One bill every 5 seconds per player, and descriptions go through `FilterMessage` like other messages.\n\n**Billing from other scripts (server):**\n\n```lua\nlocal ok, idOrError = exports['x3d_phone']:CreateBill(source, '48213', 500, 'Parking fine', 'police')\n-- issuer: 'personal', a job name in Config.Billing.Jobs (the biller must actually have that job) or 'admin' (the biller must be in Config.Billing.Admin.groups)\n```\n\n### Images: camera, uploads and external links\n\n| Setting | Default | Meaning |\n|---|---|---|\n| `Config.Uploads.Enabled` | `true` | Enables the camera and wallpaper uploads from the PC |\n| `Config.Uploads.BaseUrl` | `''` | Can stay empty; see below |\n| `Config.Uploads.MaxBytes` | 3 MB | Maximum size per image (hard ceiling 8 MB) |\n| `Config.Uploads.PerPlayerPerHour` | `30` | Uploads allowed per player per hour |\n| `Config.Uploads.Keep` | `1000` | How many recent images to keep. After that the oldest is overwritten, and its link stops working. |\n| `Config.Uploads.Quality` | `0.85` | JPG quality of camera photos (0–1) |\n| `Config.ImageHosts` | imgur, ibb | External hosts players may paste image links from (chat, posts, wallpaper). `{}` turns external links off. |\n| `Config.AnyImageHost` | `false` | `true` accepts https links from any site |\n\n**Where images are stored:** in `x3d_phone\u002Fdata\u002Fuploads\u002F` on your server. They are served through FXServer's own game port (30120), with no outside service. Worst-case disk use is `Keep × MaxBytes`, about 3 GB by default, but a camera photo is normally under 400 KB.\n\n**`BaseUrl`:** when empty, image links are stored as `\u002Fi\u002F\u003Ctoken>.jpg`. Each player's client adds the address of the server it is connected to, so this works with no setup. Set `BaseUrl` only when:\n- you have an https domain pointing at the server (for example through a reverse proxy), and you want photos to show inside post cards in chat.\n- Example: `BaseUrl = 'https:\u002F\u002Fimg.myserver.com\u002Fx3d_phone'`\n\n**Why `cdn.discordapp.com` is not a default host:** Discord file links expire after about 24 hours when opened outside Discord, so the image would be gone the next day.\n\n> ⚠️ **`AnyImageHost = true`:** the image host sees the IP address of every player who views the image, and you do not control what the image shows. Prefer listing the hosts you trust in `ImageHosts`.\n\n### Mobile banking\n\n| Setting | Default | Meaning |\n|---|---|---|\n| `Config.Banking.Enabled` | `true` | Shows the Banking app |\n| `Config.Banking.MinTransfer` | `1` | Smallest transfer |\n| `Config.Banking.MaxTransfer` | `1000000` | Largest transfer |\n\nTransfers go to the phone number of an online player. They use the ESX `bank` account and are logged in the `x3d_phone_bank_history` table. A transfer cannot start while another one is still running, and a player can transfer once every 3 seconds.\n\n---\n\n## Copies to Discord\n\nAdd these to `server.cfg`. The webhook URLs stay on the server; players never see them.\n\n```\nset x3d_phone_upload_webhook \"https:\u002F\u002Fdiscord.com\u002Fapi\u002Fwebhooks\u002F...\"\nset x3d_phone_log_webhook    \"https:\u002F\u002Fdiscord.com\u002Fapi\u002Fwebhooks\u002F...\"\n```\n\n| Convar | What it sends |\n|---|---|\n| `x3d_phone_upload_webhook` | A copy of every photo a player takes or uploads, with name, server id, identifier and type (messages \u002F twitter \u002F wallpaper) |\n| `x3d_phone_log_webhook` | Logs of SMS, posts, Dark Chat and transfers (optional) |\n\n- Mentions are off in every post, so a player named `@everyone` pings nobody.\n- Posts are queued, one every 1.5 seconds, to stay under Discord's rate limit. When more than 20 are waiting, new ones are skipped.\n- The photo itself stays on your server, so in-game links never expire.\n- Only URLs that look like real Discord webhooks are accepted.\n\n---\n\n## Fitting your server: `addons\u002F`\n\nEdit these files freely. Each one works out of the box.\n\n| File | Functions | Default |\n|---|---|---|\n| `addons\u002Fnotify\u002Fclient.lua` | `Notify(message, kind)` | esx_notify → ox_lib → `ESX.ShowNotification` |\n| `addons\u002Fvoice\u002Fclient.lua` | `Voice.Enabled()`, `Voice.SetCallChannel(ch)`, `Voice.SetMuted(bool)` | pma-voice (mumble-voip example included) |\n| `addons\u002Fupload\u002Fclient.lua` | `Upload.Screenshot(kind, cb)`, `Upload.Target(kind, cb)` | screenshot-basic → stored on your server |\n| `addons\u002Fframework\u002Fserver.lua` \u002F `client.lua` | The framework bridge (`Framework.*`), identical across every X3D product | ESX if present, else standalone |\n| `addons\u002Fbilling\u002Fserver.lua` | `Billing.Charge`, `Billing.Refund`, `Billing.PaySociety`, `Billing.PayPerson`, `Billing.PayAdmin` | Charges \u002F refunds and pays the biller's bank through `Framework.*`; `PaySociety` returns `false`, wire it yourself |\n| `addons\u002Fbanking\u002Fserver.lua` | `Banking.GetBalances`, `Banking.Transfer`, `Banking.History` | ESX `bank` account |\n| `addons\u002Ffilter\u002Fserver.lua` | `FilterMessage(src, kind, message)` | blocks words in `Config.BannedWords` |\n| `addons\u002Flog\u002Fserver.lua` | `PhoneLog(src, kind, data)`, `UploadCopy(p, file)` | Discord webhooks from convars |\n| `addons\u002Flocale\u002Fshared.lua` | `T(th, en)` | follows `Config.Locale` |\n\n**Example:** to use your own banking system, change `Banking.Transfer` to call it and return `true`, or `false, 'error message'`. The server has already checked the amount, the recipient and the rate limit.\n\n**Example:** banned words:\n\n```lua\nConfig.BannedWords = { 'badword1', 'badword2' }\n```\n\n---\n\n## Exports (client)\n\n```lua\nexports['x3d_phone']:OpenPhone()\nexports['x3d_phone']:ClosePhone()\nexports['x3d_phone']:IsPhoneOpen()     --> boolean\nexports['x3d_phone']:GetPhoneNumber()  --> string | nil\nexports['x3d_phone']:IsInCall()        --> boolean\nexports['x3d_phone']:GetCallData()     --> { phoneNumber, displayName, isOutgoing } | nil\n```\n\n## Commands\n\n| Command | What it does |\n|---|---|\n| `\u002Fopenphone` | Open or close the phone |\n| `\u002Ftestringtone` | Play your selected ringtone |\n| `\u002Ftestnotification` | Play your selected alert sound |\n| `\u002Ftestdialtone` | Play the outgoing-call tone |\n\n## Troubleshooting\n\n| Symptom | Cause \u002F fix |\n|---|---|\n| F1 says \"You don't have a phone\" | `Config.UseItem = true` and the item is not in the inventory. Give the `phone` item, or set `UseItem = false`. |\n| No camera button | `screenshot-basic` is not ensured, or `Config.Uploads.Enabled = false` |\n| A photo fails with `upload_failed` | Check the console. If it says `cannot write data\u002Fuploads\u002F`, create the `data\u002Fuploads\u002F` folder in the resource. |\n| Calls connect but carry no audio | pma-voice is not installed, or is ensured after x3d_phone |\n| Posts do not appear in chat | `Config.Buzz.ToChat = false`, or the server does not run FiveM's `chat` resource |\n| A pasted image link will not send | The host is not in `Config.ImageHosts`, or the link does not start with https |\n","Free FiveM ESX Phone Script: Calls, SMS, Buzz","Free FiveM ESX phone: pma-voice calls, SMS with GPS sharing, contacts, Buzz and anonymous Dark Chat. Thai and English, optional phone item.",[66,69,71,73,75,77,79],{"kind":67,"url":68},"image","\u002Fapi\u002Fv1\u002Fmedia\u002Fpublic\u002Fproducts\u002Fx3d-phone\u002Fmedia\u002F8704c36bb000ed04.png",{"kind":67,"url":70},"\u002Fapi\u002Fv1\u002Fmedia\u002Fpublic\u002Fproducts\u002Fx3d-phone\u002Fmedia\u002F8da2ccf3c9cb7166.png",{"kind":67,"url":72},"\u002Fapi\u002Fv1\u002Fmedia\u002Fpublic\u002Fproducts\u002Fx3d-phone\u002Fmedia\u002F463104ac8d020f1b.png",{"kind":67,"url":74},"\u002Fapi\u002Fv1\u002Fmedia\u002Fpublic\u002Fproducts\u002Fx3d-phone\u002Fmedia\u002F49fd564a93b137ce.png",{"kind":67,"url":76},"\u002Fapi\u002Fv1\u002Fmedia\u002Fpublic\u002Fproducts\u002Fx3d-phone\u002Fmedia\u002F60eb9d61acfcc2ed.png",{"kind":67,"url":78},"\u002Fapi\u002Fv1\u002Fmedia\u002Fpublic\u002Fproducts\u002Fx3d-phone\u002Fmedia\u002F7bfa7b032cc0179b.png",{"kind":67,"url":80},"\u002Fapi\u002Fv1\u002Fmedia\u002Fpublic\u002Fproducts\u002Fx3d-phone\u002Fmedia\u002Faea505b6f18ed953.png",[82,84,88,91],{"version":55,"released_at":56,"changelog_md":83},"### Changed\n\n- Store images now carry English captions for the English store page",{"version":85,"released_at":86,"changelog_md":87},"1.1.1","2026-10-12T03:26:38.605628Z","### Changed\n\n- UI font is now Kanit (one family for Thai and English), bundled inside the script; the Thai font now really loads in game (FiveM's browser dropped the old font declaration and fell back to a system font)",{"version":89,"released_at":90,"changelog_md":12},"1.0.1","2026-09-26T12:42:43.462227Z",{"version":92,"released_at":93,"changelog_md":94},"1.0.0","2026-09-25T15:31:53.651524Z","First public release.\r\n\r\n### Added\r\n\r\n- Phone app: keypad, recent calls, missed-call badge, voice calls through pma-voice (mute, ringtone, dial tone).\r\n- Messages: SMS conversations, unread badges, location sharing that sets a GPS waypoint on tap.\r\n- Contacts with favourites and photos.\r\n- Mobile banking: balance, history and transfers to an online player's phone number (ESX `bank` account by default, swappable in `addons\u002Fbanking\u002Fserver.lua`).\r\n- Camera: take a photo in game with screenshot-basic for messages, posts, contacts, Buzz avatar and wallpaper. Photos are stored on your own server (`data\u002Fuploads\u002F`), no image host or API key needed.\r\n- Post card skins in the in-game chat: default, halloween, christmas, songkran, night. Players pick one in Settings, or the server locks one with `Config.Buzz`. Uses FiveM's standard chat through `chat_theme`.\r\n- Phone item required by default (`Config.UseItem = true`, `Config.PhoneItem = 'phone'`): gates opening, calling, answering and SMS alerts on the server; the phone closes when the item leaves the inventory. `optional\u002Fphone_item.sql` adds the item.\r\n- Service numbers (`Config.Dispatch`): texting `police` \u002F `ambulance` \u002F `mechanic` reaches every online member of that job with the sender's server-side location; answers the old `esx_phone` API (`registerNumber`, `removeNumber`, `cancelMessage`, `esx_phone:send`) so esx_policejob \u002F esx_ambulancejob \u002F esx_mechanicjob work unchanged.\r\n- Dispatch app for responders: calls with distance, map blip and sound; Respond sets a waypoint and tells the caller help is coming. Client export `RequestService` \u002F event `x3d_phone:requestService` (e.g. a death-screen \"call EMS\" button) and server export `SendAlert`.\r\n- Bills app: bill any phone number personally or on behalf of a job (`Config.Billing.Jobs`, paid into `society_\u003Cjob>`); the recipient pays or declines in the phone; paying twice is impossible and a failed payout refunds the payer. Server export `CreateBill`.\r\n- Full emoji picker (3,600+ emoji, 9 groups, search) in SMS, Buzz and Dark Chat; text limits count real characters so Thai and emoji are not over-counted.\r\n- Optional Discord copies: every photo is posted to `x3d_phone_upload_webhook`, and SMS \u002F post \u002F Dark Chat \u002F transfer logs to `x3d_phone_log_webhook`. Webhooks stay server-side, mentions are disabled, and posts are queued.\r\n- External image links in messages, posts and wallpaper from `Config.ImageHosts`, or from any https site with `Config.AnyImageHost`.\r\n- `optional\u002Fscreenshot-basic\u002F` bundled (MIT, CitizenFX) for servers that do not have it.\r\n- Alt switches between the phone cursor and game controls while the phone stays open.\r\n- Buzz: server-wide feed, likes, delete own posts, new posts posted to in-game chat (`Config.Buzz.ToChat`).\r\n- Dark Chat: anonymous channels with handles and optional password.\r\n- Settings: wallpapers (preset, photo, upload from PC or image link), ringtones, notification sounds, keyboard-only mode.\r\n- Optional phone item (`Config.UseItem`), Thai \u002F English (`Config.Locale`).\r\n- Editable adapters in `addons\u002F`: notify, voice, banking, upload, message filter, log.",{"slug":23,"version":55,"latest_version":55,"files":96,"options":60},[97],{"path":98,"content":99},"config\u002Fconfig.lua","Config = Config or {}\n\n-- ===== ทั่วไป \u002F General =====\n\n-- ภาษา: 'th' หรือ 'en' \u002F Language: 'th' or 'en'\nConfig.Locale = 'th'\n\n-- พิมพ์ log ลง console ของเซิร์ฟ \u002F Print logs to the server console\nConfig.Debug = false\n\n-- เฟรมเวิร์ก: 'auto' (ใช้ ESX ถ้ามี ไม่มีก็ standalone) · 'esx' · 'standalone' \u002F Framework: 'auto' (ESX if present, else standalone) · 'esx' · 'standalone'\nConfig.Framework = 'auto'\n\n-- ปุ่มเปิดโทรศัพท์ (ผู้เล่นเปลี่ยนเองได้ใน Settings > Key Bindings > FiveM) \u002F Key that opens the phone (players can rebind it in Settings > Key Bindings > FiveM)\nConfig.OpenKey = 'F1'\n\n-- ===== ไอเทมโทรศัพท์ \u002F Phone item =====\n\n-- true = ต้องมีไอเทมโทรศัพท์ในกระเป๋า: เปิดโทรศัพท์ โทร รับสาย รับแจ้งเตือน SMS\n-- (กดใช้ไอเทมก็เปิดได้ · ไม่มีไอเทมในเซิร์ฟ? รัน optional\u002Fphone_item.sql)\n-- true = a phone item is required in the inventory: to open the phone, call, answer and get SMS alerts\n-- (using the item opens it too · no item on your server? run optional\u002Fphone_item.sql)\nConfig.UseItem = true\n-- ชื่อไอเทมโทรศัพท์ \u002F Name of the phone item\nConfig.PhoneItem = 'phone'\n\n-- ===== การโทร \u002F Calls =====\n\n-- โทรด้วยเสียงผ่าน pma-voice (ไม่ได้ลง pma-voice = โทรติดแต่ไม่มีเสียง) \u002F Voice calls through pma-voice (without pma-voice calls connect but carry no audio)\nConfig.UseVoice = true\n-- เลขช่องเสียงแรกที่ใช้กับการโทร เปลี่ยนเมื่อชนกับสคริปต์อื่น \u002F First voice channel number used for calls, change it if it clashes with another script\nConfig.CallChannelStart = 1000\n\n-- วินาทีก่อนสายที่ไม่มีคนรับจะตัดเป็นสายที่ไม่ได้รับ \u002F Seconds before an unanswered call ends as a missed call\nConfig.CallTimeout = 30\n\n-- ===== ข้อความ \u002F Messages =====\n\n-- ความยาวสูงสุดของ SMS \u002F ข้อความ Dark Chat \u002F Longest SMS \u002F Dark Chat message\nConfig.MaxMessageLength = 500\n\n-- ===== Buzz และการ์ดโพสต์ \u002F Buzz and post cards =====\n\n-- Buzz (แอปโซเชียลฟีดทั้งเซิร์ฟ) และการ์ดโพสต์ในแชท \u002F Buzz (the server-wide social feed app) and its post cards in chat\nConfig.Buzz = {\n    -- โพสต์ใหม่เด้งขึ้นแชทในเกมของทุกคน (ใช้ chat มาตรฐานของ FiveM) \u002F New posts pop up in everyone's in-game chat (uses FiveM's standard chat)\n    ToChat = true,\n    -- สกินการ์ดโพสต์ที่เปิดให้ใช้: default, halloween, christmas, songkran, night \u002F Post card skins you allow: default, halloween, christmas, songkran, night\n    Themes = { 'default', 'halloween', 'christmas', 'songkran', 'night' },\n    -- สกินที่ใช้เมื่อผู้เล่นยังไม่ได้เลือก หรือเมื่อ PlayerTheme = false \u002F Skin used when a player has not chosen, or when PlayerTheme = false\n    DefaultTheme = 'default',\n    -- true = ผู้เล่นเลือกสกินเองได้ในแอปตั้งค่า · false = ทุกคนใช้ DefaultTheme (เช่น ช่วงเทศกาล) \u002F true = players pick their own skin in Settings · false = everyone uses DefaultTheme (e.g. during a festival)\n    PlayerTheme = true,\n}\n\n-- ===== รูปจากภายนอก \u002F External images =====\n\n-- ลิงก์รูปจากเว็บอื่นที่ผู้เล่นวางเองได้ (SMS, โพสต์ Buzz, วอลเปเปอร์) (รูปที่ถ่าย\u002Fอัปโหลดในเกมผ่านเสมอ) · ว่าง {} = ปิดลิงก์ภายนอก\n-- ลิงก์ cdn.discordapp.com หมดอายุภายในประมาณ 24 ชม. ถ้าเปิดจากนอก Discord จึงไม่ได้ใส่ไว้\n-- Image hosts players may paste links from (SMS, Buzz posts, wallpapers); photos taken or uploaded in game always pass · empty {} = external links off\n-- cdn.discordapp.com links expire in about 24 h when opened outside Discord, so it is not listed\n-- เช่น \u002F e.g. 'https:\u002F\u002Fi.imgur.com\u002F'\nConfig.ImageHosts = {\n    'https:\u002F\u002Fi.imgur.com\u002F',\n    'https:\u002F\u002Fi.ibb.co\u002F',\n}\n\n-- true = รับลิงก์ https จากเว็บไหนก็ได้\n-- คำเตือน: เจ้าของเว็บรูปจะเห็น IP ของทุกคนที่เปิดดูรูปนั้น และคุมรูปที่ขึ้นไม่ได้\n-- true = accept https links from any site\n-- Warning: the image host sees the IP of everyone who opens the image, and you cannot control what it shows\nConfig.AnyImageHost = false\n\n-- ===== ธนาคารมือถือ \u002F Mobile banking =====\n\n-- ธนาคารมือถือ: ดูยอดเงินและโอนเข้าบัญชีธนาคารของเจ้าของเบอร์ที่ออนไลน์อยู่\n-- ใช้ระบบธนาคารอื่น? แก้ addons\u002Fbanking\u002Fserver.lua\n-- Mobile banking: see the balance and transfer to the bank account of an online number's owner\n-- Using another banking system? Edit addons\u002Fbanking\u002Fserver.lua\nConfig.Banking = {\n    -- แสดงแอปธนาคาร \u002F Show the Banking app\n    Enabled = true,\n    -- ยอดโอนต่ำสุด \u002F Smallest transfer\n    MinTransfer = 1,\n    -- ยอดโอนสูงสุดต่อครั้ง \u002F Largest transfer\n    MaxTransfer = 1000000,\n}\n\n-- ===== เบอร์หน่วยงาน \u002F Service numbers =====\n\n-- เบอร์หน่วยงาน: ส่ง SMS เข้าเบอร์นี้ = ทุกคนที่มีอาชีพนั้น (ออนไลน์ + มีโทรศัพท์) ได้รับพร้อมพิกัดผู้ส่ง ตอบกลับหาผู้ส่งได้เลย\n-- ขึ้นเป็นรายชื่อพิเศษในแอปรายชื่อของทุกคน\n-- (สคริปต์อาชีพเพิ่ม\u002Fลบเบอร์เองได้ผ่าน event x3d_phone:registerNumber \u002F x3d_phone:removeNumber\n--  และ TriggerServerEvent('x3d_phone:send', ...) — ดู docs.th.md \u002F docs.en.md)\n-- Service numbers: a text to one of these reaches everyone with that job (online and with a phone), with the sender's location, and they can reply to the sender\n-- They show up as special contacts for everyone\n-- (job scripts can add \u002F remove numbers through the events x3d_phone:registerNumber \u002F x3d_phone:removeNumber\n--  and TriggerServerEvent('x3d_phone:send', ...) — see docs.th.md \u002F docs.en.md)\nConfig.Dispatch = {\n    -- true = ส่งถึงเฉพาะคนที่เข้าเวรอยู่ (job.onDuty ของ ESX Legacy) \u002F true = deliver only to players on duty (ESX Legacy job.onDuty)\n    OnDutyOnly = false,\n    -- แจ้งเหตุค้างในแอป Dispatch ได้กี่วินาที \u002F How many seconds a call stays in the Dispatch app\n    AlertSeconds = 600,\n    -- true = คนที่กดเรียก (เช่นปุ่มเรียกหมอตอนล้ม) ต้องมีไอเทมโทรศัพท์ด้วย \u002F true = the caller (e.g. a \"call EMS\" button when down) must also have the phone item\n    CallNeedsPhone = false,\n    -- request = หัวข้อแจ้งเหตุเวลามีคนกดเรียก · blip = { sprite, color } จุดบนแผนที่ของเจ้าหน้าที่\n    -- request = the call title when someone presses call · blip = { sprite, color } the responders' map blip\n    -- เช่น \u002F e.g. police = { label = 'ตำรวจ', jobs = { 'police' }, coords = true }\n    Numbers = {\n        police    = { label = 'ตำรวจ', jobs = { 'police' }, coords = true, request = 'ขอความช่วยเหลือจากตำรวจ', blip = { sprite = 60, color = 29 } },\n        ambulance = { label = 'โรงพยาบาล', jobs = { 'ambulance' }, coords = true, request = 'มีผู้บาดเจ็บ ต้องการหมอ', blip = { sprite = 153, color = 1 } },\n        mechanic  = { label = 'ช่างซ่อมรถ', jobs = { 'mechanic' }, coords = true, request = 'ขอช่างซ่อมรถ', blip = { sprite = 446, color = 47 } },\n    },\n}\n\n-- ===== แอปบิล \u002F Bills app =====\n\n-- แอปบิล: ออกบิลให้เบอร์โทร ผู้รับกดจ่ายในโทรศัพท์ \u002F Bills app: bill a phone number, the recipient pays in the phone\nConfig.Billing = {\n    -- แสดงแอปบิล \u002F Show the Bills app\n    Enabled = true,\n    -- ออกบิลส่วนตัวได้ไหม (เงินเข้าบัญชีธนาคารของคนออกบิล) \u002F Allow personal bills (the money goes to the biller's bank account)\n    AllowPersonal = true,\n    -- ผู้รับกดปฏิเสธบิลได้ไหม (false = ต้องจ่ายอย่างเดียว คนออกบิลยกเลิกได้) \u002F Can the recipient decline (false = pay only, the biller can still cancel)\n    AllowDecline = true,\n    -- ยอดบิลต่ำสุด \u002F Smallest bill\n    MinAmount = 1,\n    -- ยอดบิลสูงสุด \u002F Largest bill\n    MaxAmount = 1000000,\n    -- บิลค้างสูงสุดจากคนออกบิลหนึ่งคนถึงเบอร์เดียว (กันสแปม) \u002F Most open bills from one biller to one number (anti-spam)\n    MaxOpenPerTarget = 10,\n    -- จ่ายจากบัญชีไหนของผู้จ่าย: 'bank' หรือ 'money' \u002F Which account the payer pays from: 'bank' or 'money'\n    PayFrom = 'bank',\n    -- ตารางผู้เล่นของ ESX (ใช้ตอนเงินบิลส่วนตัวเข้าบัญชีคนออกบิลที่ออฟไลน์อยู่ โหมด esx เท่านั้น) \u002F ESX players table (used to credit an offline biller for personal bills, esx mode only)\n    UsersTable = 'users',\n    -- อาชีพที่ออกบิลในนามหน่วยงานได้ (ค่าเริ่มต้นไม่มีบัญชีหน่วยงานให้ — Billing.PaySociety คืน false เสมอ\n    -- ผู้จ่ายไม่ถูกหักเงิน บิลค้างเหมือนเดิม — ต่อระบบบัญชีหน่วยงานของคุณเองที่ addons\u002Fbilling\u002Fserver.lua)\n    -- Jobs that can bill on behalf of the business (no society account is provided by default — Billing.PaySociety always returns false,\n    -- so the payer is not charged and the bill stays unpaid — wire your own society account in addons\u002Fbilling\u002Fserver.lua)\n    -- locked = true: บิลในนามหน่วยงานนี้ คนออกบิลยกเลิกไม่ได้ ผู้รับปฏิเสธไม่ได้ ต้องจ่าย หรือให้แอดมินยกเลิกจากแผง x3d_adminpanel\n    -- locked = true: bills in this job's name cannot be cancelled by the biller or declined by the recipient; only an admin can cancel them in x3d_adminpanel\n    -- เช่น \u002F e.g. police = { label = 'ตำรวจ', minGrade = 0, locked = true }\n    Jobs = {\n        police    = { label = 'ตำรวจ', minGrade = 0, locked = true },\n        ambulance = { label = 'โรงพยาบาล', minGrade = 0, locked = true },\n        mechanic  = { label = 'อู่ซ่อมรถ', minGrade = 0 },\n        taxi      = { label = 'แท็กซี่', minGrade = 0 },\n    },\n    -- แอดมินออกบิลในนาม \"แอดมิน\" ได้ (เช่น ค่าปรับ) เงินที่จ่ายส่งไป Billing.PayAdmin ใน addons\u002Fbilling\u002Fserver.lua (ค่าเริ่มต้น: หายไปจากระบบ)\n    -- Admins can bill as \"admin\" (e.g. fines); the payment goes to Billing.PayAdmin in addons\u002Fbilling\u002Fserver.lua (default: removed from the economy)\n    -- groups = กลุ่มที่นับเป็นแอดมิน \u002F groups that count as admin · locked = เหมือนของหน่วยงาน \u002F same as the job flag above\n    Admin = { enabled = true, label = 'แอดมิน', groups = { 'admin', 'superadmin' }, locked = true },\n}\n\n-- ===== กล้องและอัปโหลดรูป \u002F Camera and photo uploads =====\n\n-- กล้องและอัปโหลดรูป: เก็บรูปไว้ในเซิร์ฟเวอร์เอง (โฟลเดอร์ data\u002Fuploads\u002F) ไม่ต้องใช้บริการฝากรูป\n-- กล้องต้องมี screenshot-basic · อัปโหลดจากคอมพิวเตอร์ (วอลเปเปอร์) ใช้ได้เลย\n-- Camera and photo uploads: photos are stored on your own server (the data\u002Fuploads\u002F folder), no image host needed\n-- The camera needs screenshot-basic · uploading from a computer (wallpapers) works as is\nConfig.Uploads = {\n    -- เปิดกล้องและการอัปโหลด \u002F Turn the camera and uploads on\n    Enabled = true,\n    -- ว่าง = ผู้เล่นแต่ละคนเปิดรูปผ่านที่อยู่เซิร์ฟที่ตัวเองต่ออยู่ ไม่ต้องตั้งอะไร\n    -- ตั้งเองเมื่ออยากได้ลิงก์ตายตัว เช่นมีโดเมน https: 'https:\u002F\u002Fimg.myserver.com\u002Fx3d_phone'\n    -- (รูปจะขึ้นในการ์ดทวีตในแชทได้เฉพาะเมื่อ BaseUrl เป็น https)\n    -- Empty = each player opens photos through the server address they connected to, nothing to set\n    -- Set it when you want a fixed link, e.g. with an https domain: 'https:\u002F\u002Fimg.myserver.com\u002Fx3d_phone'\n    -- (photos show in chat post cards only when BaseUrl is https)\n    BaseUrl = '',\n    -- ขนาดไฟล์สูงสุดต่อรูป (ไบต์) \u002F Largest file size per photo (bytes)\n    MaxBytes = 3 * 1024 * 1024,\n    -- ผู้เล่นหนึ่งคนอัปโหลดได้กี่รูปต่อชั่วโมง \u002F How many photos one player can upload per hour\n    PerPlayerPerHour = 30,\n    -- เก็บรูปล่าสุดกี่รูป เกินแล้ววนทับรูปเก่าสุด (ลิงก์รูปเก่านั้นจะเปิดไม่ได้) \u002F How many latest photos to keep; beyond that the oldest is overwritten (its link stops working)\n    Keep = 1000,\n    -- คุณภาพ JPG ตอนถ่ายรูป (0-1) \u002F JPG quality when taking a photo (0-1)\n    Quality = 0.85,\n}\n\n-- ===== วอลเปเปอร์ \u002F Wallpapers =====\n\n-- วอลเปเปอร์ที่ผู้เล่นเลือกได้ (เซิร์ฟเวอร์ใช้ตรวจค่าที่เลือก เพิ่มตัวเลือกใหม่ต้องแก้หน้าเว็บของโทรศัพท์ด้วย) \u002F Wallpapers players can pick (the server validates against this list; adding a new one also needs the phone web UI edited)\n-- เช่น \u002F e.g. { id = 'default', name = 'Default', file = 'default.jpg' }\nConfig.Wallpapers = {\n    { id = 'default', name = 'Default', file = 'default.jpg' },\n    { id = 'gradient-blue', name = 'Blue Gradient', file = 'gradient-blue.jpg' },\n    { id = 'gradient-purple', name = 'Purple Gradient', file = 'gradient-purple.jpg' },\n    { id = 'gradient-sunset', name = 'Sunset', file = 'gradient-sunset.jpg' },\n    { id = 'abstract-1', name = 'Abstract 1', file = 'abstract-1.jpg' },\n    { id = 'abstract-2', name = 'Abstract 2', file = 'abstract-2.jpg' },\n    { id = 'city-night', name = 'City Night', file = 'city-night.jpg' },\n    { id = 'nature-1', name = 'Nature', file = 'nature-1.jpg' },\n}\n\n-- ===== เสียง \u002F Sounds =====\n\n-- เสียงเรียกเข้า: แต่ละตัวชี้ไปที่เสียงในเกม GTA V \u002F Ringtones: each one points to a GTA V in-game sound\n-- เช่น \u002F e.g. { id = 'default', name = 'Default', nativeSound = 'Remote_Ring', nativeSoundset = 'Phone_SoundSet_Default' }\nConfig.Ringtones = {\n    { id = 'default', name = 'Default', nativeSound = 'Remote_Ring', nativeSoundset = 'Phone_SoundSet_Default' },\n    { id = 'classic', name = 'Classic', nativeSound = '5_Second_Timer', nativeSoundset = 'HUD_MINI_GAME_SOUNDSET' },\n    { id = 'modern', name = 'Modern', nativeSound = 'CONFIRM_BEEP', nativeSoundset = 'HUD_FRONTEND_DEFAULT_SOUNDSET' },\n    { id = 'subtle', name = 'Subtle', nativeSound = 'Pre_Release_Tone', nativeSoundset = 'Phone_SoundSet_Default' },\n    { id = 'loud', name = 'Loud', nativeSound = 'Vibrate_Loop', nativeSoundset = 'Phone_SoundSet_Default' },\n}\n\n-- \u002Ftestringtone กับ \u002Ftestdialtone เล่นกี่มิลลิวินาทีก่อนหยุดเอง \u002F How many milliseconds \u002Ftestringtone and \u002Ftestdialtone play before stopping\nConfig.RingtonePreviewMs = 3000\n\n-- เสียงแจ้งเตือนข้อความ \u002F Message notification sounds\n-- เช่น \u002F e.g. { id = 'default', name = 'Default', nativeSound = 'Text_Arrive_Tone', nativeSoundset = 'Phone_SoundSet_Default' }\nConfig.NotificationSounds = {\n    { id = 'default', name = 'Default', nativeSound = 'Text_Arrive_Tone', nativeSoundset = 'Phone_SoundSet_Default' },\n    { id = 'chime', name = 'Chime', nativeSound = 'CHECKPOINT_PERFECT', nativeSoundset = 'HUD_MINI_GAME_SOUNDSET' },\n    { id = 'ding', name = 'Ding', nativeSound = 'SELECT', nativeSoundset = 'HUD_FRONTEND_DEFAULT_SOUNDSET' },\n}\n\n-- ===== รายชื่อเริ่มต้น \u002F Default contacts =====\n\n-- รายชื่อที่ใส่ให้ทุกเบอร์ใหม่อัตโนมัติ \u002F Contacts added automatically to every new number\n-- เช่น \u002F e.g. { phone = '911', name = 'Police' }\nConfig.DefaultContacts = {\n    -- { phone = '911', name = 'Police' },\n}\n",1792316315645]