=============== LIBRARY RULES =============== From library maintainers: - Answer only from the published Murphy's Telegram & Mail documentation, in the user's language. Cite a relevant clickable Markdown source link under https://docs.murphy-workshop.com/murphy-s-telegram-mail/. - This is a public RedM plugin. Do not substitute FiveM, another Murphy plugin, or undocumented framework APIs. Do not mention or speculate about unpublished products. - Never invent commands, exports, event names, configuration keys, default values or compatibility. If the documentation does not establish an answer, say so and link to the closest relevant reference. - Ask for the installed framework and plugin version when they affect behavior. A public release note establishes that release, not a guarantee about files actually installed on the user's server. - Keep answers concise and focused. Give only the requested code. Preserve existing configuration entries and label excerpts. Do not use emojis or long dashes. Remove display line numbers from copied code. - Distinguish client and server context, online server player IDs and persistent character identifiers. Do not interchange commands, events and exports without explicit documentation. - Do not promise data preservation, backups, refunds or offline behavior unless the relevant documentation establishes it. Do not recommend deleting data or blindly replacing a full core file. - Store screenshots show one demonstration setup. Do not infer fixed rewards, version, framework, controls or guarantees from a picture. Do not claim that an in-game test was performed. - Never claim access to purchases, accounts, licenses or server actions. For account or order questions only, link to https://murphy-workshop.com/portal or https://murphy-workshop.com/support. - Published reference: Non. L'intégration appelante doit gérer paiement et retrait des objets; pas de débit automatique par ces exports. Ressource murphy_post. - Published reference: Oui, courrier stocké en base et disponible à sa prochaine visite au bureau de poste. Utiliser les identifiants documentés, sans supposer un ID serveur en ligne pour la cible hors ligne. ### Add resource to server.cfg Source: https://docs.murphy-workshop.com/murphy-s-telegram-mail/getting-started/installation Ensure the required dependencies and the resource itself are started in your server.cfg file. ```text ensure oxmysql ensure murphy_interact ensure murphy_post ``` -------------------------------- ### BLN HUD Integration Configuration Source: https://docs.murphy-workshop.com/murphy-s-telegram-mail/advanced/external-api Example configuration for BLN HUD to read the unread message count from the player statebag. ```lua -- BLN HUD config Config.Telegram = { animateMessagesCount = true, getUnreadMessagesCount = function() return LocalPlayer.state.telegramUnreadMessages or 0 end, } ``` -------------------------------- ### Handle Payment Before Sending Telegram Source: https://docs.murphy-workshop.com/murphy-s-telegram-mail/advanced/external-api Example of how to manually charge the sender before calling the SendTelegram export and issuing a refund if the operation fails. ```lua if ChargeMoney(source, 10) then local result = exports.murphy_post:SendTelegram(senderData, recipientData, telegramData) if not result.ok then RefundMoney(source, 10) -- refund on failure end end ``` -------------------------------- ### Define job-locked letter template Source: https://docs.murphy-workshop.com/murphy-s-telegram-mail/advanced/templates-stationery Example of a template restricted to players with the 'sheriff' or 'marshal' job. ```lua { id = 'sheriff', label = 'Sheriff Department', jobs = { 'sheriff', 'marshal' }, backgroundImage = 'letter_sheriff.png', headerImage = 'header_sheriff.png', stampImage = 'stamp_sheriff.png', headerText = "SHERIFF'S OFFICE", footerText = 'Official document - Sheriff Department', }, ``` -------------------------------- ### Define job-locked telegram template Source: https://docs.murphy-workshop.com/murphy-s-telegram-mail/advanced/templates-stationery An example of a template restricted to specific jobs, using custom header and footer text. ```lua { id = 'government', label = 'Government', jobs = { 'mayor', 'councillor' }, backgroundImage = 'telegram_government.png', borderImage = 'border_telegram_government.png', headerText = 'GOVERNMENT TELEGRAPHIC SERVICE', footerText = 'Official telegram - Government', }, ``` -------------------------------- ### Remove Inventory Items Before Sending Letter Source: https://docs.murphy-workshop.com/murphy-s-telegram-mail/advanced/external-api Example of manually removing items from the sender's inventory before calling the SendLetter export with a packageType. ```lua if RemoveItem(source, 'bread', 5) then exports.murphy_post:SendLetter(senderData, recipientData, { object = 'Supplies', body = 'Here is some bread for your journey.', packageType = 'bread', amount = 5 }) end ``` -------------------------------- ### General Configuration Source: https://docs.murphy-workshop.com/murphy-s-telegram-mail/getting-started/configuration Defines core settings such as development mode, framework selection, and cosmetic date offsets. ```lua Config.DevMode = false -- Enable debug logging in server console Config.framework = "REDEMRP2k23" -- "REDEMRP2k23", "rsg-core", or "vorp" Config.YearsDelay = -125 -- Years offset for document dates (cosmetic) ``` -------------------------------- ### Adapter File Structure Source: https://docs.murphy-workshop.com/murphy-s-telegram-mail/advanced/multi-framework-support The directory layout for server and client-side adapter files that isolate framework-specific implementations. ```text server/adapters/ REDEMRP2k23Adapter.lua RSGAdapter.lua VORPAdapter.lua client/adapters/ REDEMRP2k23Adapter.lua RSGAdapter.lua VORPAdapter.lua ``` -------------------------------- ### Configure framework in config.lua Source: https://docs.murphy-workshop.com/murphy-s-telegram-mail/getting-started/installation Set the framework type in config/config.lua to match your server environment. ```lua Config.framework = "REDEMRP2k23" -- Options: "REDEMRP2k23", "rsg-core", "vorp" ``` -------------------------------- ### Server-side Pricing Configuration Source: https://docs.murphy-workshop.com/murphy-s-telegram-mail/getting-started/configuration Defines the authoritative base prices used by the server. These should match the corresponding NUI base prices. ```lua Config.Prices = { telegramBase = 1.0, -- Must match telegramBasePrice letterBase = 2.0, -- Must match letterBasePrice } ``` -------------------------------- ### Configure Framework in config.lua Source: https://docs.murphy-workshop.com/murphy-s-telegram-mail/advanced/multi-framework-support Set the active framework by updating the Config.framework value in the configuration file. ```lua Config.framework = "REDEMRP2k23" -- or "rsg-core" or "vorp" ``` -------------------------------- ### NUI Pricing Configuration Source: https://docs.murphy-workshop.com/murphy-s-telegram-mail/getting-started/configuration Sets the pricing values displayed in the user interface. These values are validated server-side. ```lua Config.NUI = { -- Telegram telegramBasePrice = 1, -- Base cost to send a telegram telegramPriceChar = 0.03, -- Additional cost per character (body) telegramPaidCharObject = true, -- Charge per character for subject field telegramPaidCharSign = true, -- Charge per character for signature field -- Letter letterBasePrice = 2.0, -- Base cost to send a letter letterPriceChar = 0.0, -- Additional cost per character (body), 0 = free letterPricePerItem = 0.5, -- Additional cost per item in package letterPaidCharObject = false, -- Charge per character for subject field letterPaidCharSign = false, -- Charge per character for signature field } ``` -------------------------------- ### Configure Player Mailbox Settings Source: https://docs.murphy-workshop.com/murphy-s-telegram-mail/advanced/player-home-mailboxes Set the spawn distance, mailbox functionality, and Discord webhook notifications in config/config.lua. ```lua -- Prop spawn/despawn distance (in game units) Config.PlayerMailboxStreamDistance = 50.0 -- Allow sending mail from home mailbox (true) or receive only (false) Config.PlayerMailboxSendEnabled = false -- Discord webhook notification when a mailbox is registered (leave empty to disable) Config.DiscordWebhook = 'https://discord.com/api/webhooks/...' Config.DiscordWebhookName = 'Murphy Post' ``` -------------------------------- ### Configure Package Constraints Source: https://docs.murphy-workshop.com/murphy-s-telegram-mail/getting-started/configuration Defines the maximum weight and allowed item types for letter packages. ```lua Config.Package = { maxWeight = 10.0, -- Maximum total weight (kg) for a letter package allowedTypes = { 'item_standard' }, -- Item types allowed in packages } ``` -------------------------------- ### Register a player mailbox in a housing resource Source: https://docs.murphy-workshop.com/murphy-s-telegram-mail/advanced/player-home-mailboxes Use the RegisterPlayerMailbox export to create a mailbox at specific coordinates when a player purchases a property. ```lua -- server-side, in your housing resource local result = exports.murphy_post:RegisterPlayerMailbox({ coords = property.mailboxCoords, heading = property.mailboxHeading, propModel = 'p_mailbox01x', ownerIdentifier = tostring(player.charIdentifier), label = property.name .. ' Mailbox', externalId = 'property_' .. property.id, }) ``` -------------------------------- ### Configure UI language Source: https://docs.murphy-workshop.com/murphy-s-telegram-mail/getting-started/configuration Sets the language for the UI. Supported values are 'en' or 'fr'. ```lua Config.NUI = { lang = 'fr', -- UI language: 'en' or 'fr' } ``` -------------------------------- ### Configure Auto-cleanup and Expiration Source: https://docs.murphy-workshop.com/murphy-s-telegram-mail/getting-started/configuration Settings for the automatic removal of old documents and inbox entries based on age. ```lua Config.Expiration = { enabled = true, -- Enable automatic cleanup of old documents archiveDays = 30, -- Delete documents older than N days inboxDays = 14, -- Delete inbox entries older than N days checkIntervalMinutes = 60, -- How often the cleanup runs (minutes) } ``` -------------------------------- ### Create post_player_mailboxes table Source: https://docs.murphy-workshop.com/murphy-s-telegram-mail/advanced/player-home-mailboxes The post_player_mailboxes table is automatically created on the first startup. This SQL schema defines the structure for storing mailbox data, including owner identifiers and coordinates. ```sql CREATE TABLE IF NOT EXISTS `post_player_mailboxes` ( `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, `external_id` VARCHAR(64) NULL, `owner_identifier` VARCHAR(64) NOT NULL, `label` VARCHAR(128) NULL, `coord_x` FLOAT NOT NULL, `coord_y` FLOAT NOT NULL, `coord_z` FLOAT NOT NULL, `heading` FLOAT NOT NULL DEFAULT 0.0, `prop_model` VARCHAR(64) NOT NULL DEFAULT 'p_mailbox01x', `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `uniq_external` (`external_id`), INDEX `idx_owner` (`owner_identifier`) ); ``` -------------------------------- ### Configure UI behavior Source: https://docs.murphy-workshop.com/murphy-s-telegram-mail/getting-started/configuration Defines the internal UI state and the polling interval for checking new mail. ```lua Config.UI = { isOpen = false, -- Internal state (do not change) inboxPollSeconds = 30, -- How often the client checks for new mail } ``` -------------------------------- ### Configure Config.Items Source: https://docs.murphy-workshop.com/murphy-s-telegram-mail/getting-started/configuration Defines the inventory item names for letters and telegrams. These values must match the items registered in your framework's item registry. ```lua Config.Items = { letterItem = 'post_letter', -- Inventory item name for letters telegramItem = 'post_telegram', -- Inventory item name for telegrams } ``` -------------------------------- ### Register items for REDEMRP Source: https://docs.murphy-workshop.com/murphy-s-telegram-mail/getting-started/installation SQL command to insert post items into the REDEMRP inventory items table. ```sql INSERT INTO items (item, label, `limit`, `type`, weight) VALUES ('post_letter', 'Letter', 50, 'item_standard', 100), ('post_telegram', 'Telegram', 50, 'item_standard', 100); ``` -------------------------------- ### Configure Rate Limiting Source: https://docs.murphy-workshop.com/murphy-s-telegram-mail/getting-started/configuration Sets the cooldown period in seconds between sends per player. Set to 0 to disable. ```lua Config.RateLimit = { cooldownSeconds = 30, -- Minimum seconds between sends per player (0 = disabled) } ``` -------------------------------- ### Register items for RSG-Core Source: https://docs.murphy-workshop.com/murphy-s-telegram-mail/getting-started/installation Lua configuration entries to add to rsg-core/shared/items.lua. ```lua post_letter = { name = 'post_letter', label = 'Letter', weight = 100, type = 'item', image = 'post_letter.png', unique = false, useable = true, shouldClose = true, description = 'A sealed letter' }, post_telegram = { name = 'post_telegram', label = 'Telegram', weight = 100, type = 'item', image = 'post_telegram.png', unique = false, useable = true, shouldClose = true, description = 'A telegram' }, ``` -------------------------------- ### exports.murphy_post:SendLetter Source: https://docs.murphy-workshop.com/murphy-s-telegram-mail/advanced/external-api Sends a letter to a player, optionally including an item package. ```APIDOC ## exports.murphy_post:SendLetter(sender, recipient, content, options) ### Description Sends a letter to a player. This method supports attaching item packages to the letter. ### Parameters - **sender** (table) - Required - Contains sender details: `identifier`, `firstname`, `lastname`. - **recipient** (table) - Required - Contains recipient details: `firstName`, `lastName`. - **content** (table) - Required - Contains message details: `object`, `body`, `signature`, `packageType`, `amount`. - **options** (table) - Optional - Contains delivery settings: `delay` (in seconds). ``` -------------------------------- ### Register a Player Mailbox Source: https://docs.murphy-workshop.com/murphy-s-telegram-mail/advanced/player-home-mailboxes Use the RegisterPlayerMailbox export to spawn a mailbox prop at specific coordinates for a designated owner. ```lua local result = exports.murphy_post:RegisterPlayerMailbox({ coords = { x = 100.0, y = 200.0, z = 50.0 }, -- Required: world position heading = 90.0, -- Optional: prop heading (default 0) propModel = 'p_mailbox01x', -- Optional: RedM prop model (default 'p_mailbox01x') ownerIdentifier = '32', -- Required: character identifier (charidentifier for VORP) label = "John's Mailbox", -- Optional: display name externalId = 'housing_plot_42', -- Optional: your own unique key for later removal }) -- result = { ok = true, id = 1 } -- success (id = database ID) -- result = { ok = false, error = '...' } -- failure ``` -------------------------------- ### Customize inventory item names Source: https://docs.murphy-workshop.com/murphy-s-telegram-mail/getting-started/installation Update the inventory item keys in config/config.lua if your database uses different names. ```lua Config.Items = { letterItem = 'post_letter', -- change if your items table uses a different name telegramItem = 'post_telegram', } ``` -------------------------------- ### Configure Config.Fonts Source: https://docs.murphy-workshop.com/murphy-s-telegram-mail/getting-started/configuration Defines the list of fonts available for document rendering. Telegrams use a random font from this list, while letters allow the player to choose. ```lua Config.Fonts = { 'BethEllen', -- Handwriting, irregular 'Caveat', -- Handwriting, casual 'DancingScript', -- Cursive, elegant 'MarckScript', -- Handwriting, relaxed 'TypeRa', -- Typewriter monospace } ``` -------------------------------- ### Configure Inbox Statebag Sync Source: https://docs.murphy-workshop.com/murphy-s-telegram-mail/advanced/external-api Enable or disable statebag synchronization and define the key used for the player statebag in config/config.lua. ```lua -- config/config.lua Config.InboxStateBag = { enabled = true, -- set to false to disable the sync key = 'telegramUnreadMessages', -- statebag key (BLN HUD default) } ``` -------------------------------- ### RegisterPlayerMailbox Source: https://docs.murphy-workshop.com/murphy-s-telegram-mail/advanced/player-home-mailboxes Registers a new mailbox in the world, spawning a prop and creating an interaction point. ```APIDOC ## RegisterPlayerMailbox ### Description Registers a new mailbox. A prop is spawned client-side and an interaction point is created automatically. ### Parameters - **coords** ({x, y, z}) - Required - World position for the prop - **heading** (number) - Optional - Prop heading in degrees (default: 0) - **propModel** (string) - Optional - RedM prop model name (default: 'p_mailbox01x') - **ownerIdentifier** (string/number) - Required - Character identifier of the mailbox owner - **label** (string) - Optional - Display name shown in the interaction - **externalId** (string) - Optional - Your own unique identifier for later retrieval/removal ### Response - **ok** (boolean) - Success status - **id** (number) - Database ID on success - **error** (string) - Error message on failure ``` -------------------------------- ### Define Mailboxes Source: https://docs.murphy-workshop.com/murphy-s-telegram-mail/getting-started/configuration Configures job-based mailboxes that restrict access to specific player roles. ```lua Config.Mailboxes = { { id = 'sheriff_rhodes', -- Unique identifier (used in recipientData) label = 'Sheriff Rhodes Mailbox', -- Display name jobs = { 'sheriff', 'marshal' }, -- Jobs that can access this mailbox }, -- Add more mailboxes here... } ``` -------------------------------- ### Define Config.TelegramTemplates structure Source: https://docs.murphy-workshop.com/murphy-s-telegram-mail/advanced/templates-stationery The base configuration structure for defining telegram templates, including identifiers, labels, job restrictions, and asset paths. ```lua Config.TelegramTemplates = { { id = 'default', label = 'Standard Telegram', jobs = {}, backgroundImage = 'telegram_default.png', -- Full background texture borderImage = 'border_telegram_default.png', -- Decorative frame overlay headerText = nil, -- Overrides telegram title (default: "TELEGRAPHIC SERVICE TO THE WHOLE WORLD") footerText = nil, -- Overrides footer text }, } ``` -------------------------------- ### SQL Schema for post_inbox Source: https://docs.murphy-workshop.com/murphy-s-telegram-mail/advanced/database Defines the delivery queue table, tracking document availability and status for characters. ```sql CREATE TABLE IF NOT EXISTS `post_inbox` ( `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, `identifier` VARCHAR(64) NOT NULL, `document_id` INT UNSIGNED NOT NULL, `status` ENUM('scheduled','pending','delivered') NOT NULL DEFAULT 'scheduled', `scheduled_at` DATETIME NULL, `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, `delivered_at` DATETIME NULL, PRIMARY KEY (`id`), INDEX `idx_ident_status` (`identifier`, `status`), INDEX `idx_ident_status_avail` (`identifier`, `status`, `document_id`), INDEX `idx_doc` (`document_id`), CONSTRAINT `fk_inbox_document` FOREIGN KEY (`document_id`) REFERENCES `post_documents`(`id`) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; ``` -------------------------------- ### Send Telegram and Letter via Exports Source: https://docs.murphy-workshop.com/murphy-s-telegram-mail/advanced/external-api Recommended method for sending telegrams and letters using the exports interface. ```lua local result = exports.murphy_post:SendTelegram(senderData, recipientData, telegramData, options) local result = exports.murphy_post:SendLetter(senderData, recipientData, letterData, options) ``` -------------------------------- ### Configure Delivery Delays Source: https://docs.murphy-workshop.com/murphy-s-telegram-mail/getting-started/configuration Sets the delay in seconds before telegrams and letters become available. Documents are initially scheduled and promoted to pending after this delay. ```lua Config.Delays = { telegramSeconds = 3, -- Seconds before a telegram becomes available letterSeconds = 10, -- Seconds before a letter becomes available } ``` -------------------------------- ### Register items for VORP Source: https://docs.murphy-workshop.com/murphy-s-telegram-mail/getting-started/installation SQL command to insert post items into the VORP items database table. ```sql INSERT INTO items (item, label, `limit`, `type`, usable, can_remove, weight) VALUES ('post_letter', 'Letter', 50, 'item_standard', 1, 1, 100), ('post_telegram', 'Telegram', 50, 'item_standard', 1, 1, 100); ``` -------------------------------- ### Send a letter with an item package Source: https://docs.murphy-workshop.com/murphy-s-telegram-mail/advanced/external-api Sends a letter that includes an attached item package, with a specified delay before it becomes available. ```lua local result = exports.murphy_post:SendLetter( { identifier = 'quest_system', firstname = 'Quest', lastname = 'Master' }, { firstName = 'Arthur', lastName = 'Morgan' }, { object = 'Quest Reward', body = 'Congratulations on completing the quest! Your reward is attached.', signature = 'The Quest Master', packageType = 'gold_bar', amount = 2 }, { delay = 300 } -- available in 5 minutes ) ``` -------------------------------- ### RegisterPlayerMailbox Source: https://docs.murphy-workshop.com/murphy-s-telegram-mail/advanced/player-home-mailboxes Registers a new player mailbox in the database, making it available for interaction. ```APIDOC ## RegisterPlayerMailbox ### Description Registers a new mailbox at a specific location associated with a player identifier. ### Parameters - **coords** (vector3) - Required - The coordinates for the mailbox. - **heading** (float) - Required - The heading for the mailbox prop. - **propModel** (string) - Required - The model name of the mailbox prop. - **ownerIdentifier** (string) - Required - The character identifier of the owner. - **label** (string) - Required - The display label for the mailbox. - **externalId** (string) - Required - A unique identifier for the mailbox (e.g., property ID). ### Example ```lua exports.murphy_post:RegisterPlayerMailbox({ coords = property.mailboxCoords, heading = property.mailboxHeading, propModel = 'p_mailbox01x', ownerIdentifier = tostring(player.charIdentifier), label = property.name .. ' Mailbox', externalId = 'property_' .. property.id, }) ``` ``` -------------------------------- ### SQL Query: View recent documents Source: https://docs.murphy-workshop.com/murphy-s-telegram-mail/advanced/database Retrieves the 20 most recently created documents. ```sql SELECT id, type, sender_firstname, sender_lastname, receiver_firstname, receiver_lastname, object, created_at FROM post_documents ORDER BY id DESC LIMIT 20; ``` -------------------------------- ### SQL Query: Count documents per type Source: https://docs.murphy-workshop.com/murphy-s-telegram-mail/advanced/database Aggregates the total number of documents grouped by their type. ```sql SELECT type, COUNT(*) as total FROM post_documents GROUP BY type; ``` -------------------------------- ### SQL Schema for post_contacts Source: https://docs.murphy-workshop.com/murphy-s-telegram-mail/advanced/database Defines the table for storing persistent favorite contacts per character. ```sql CREATE TABLE IF NOT EXISTS `post_contacts` ( `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, `owner_identifier` VARCHAR(64) NOT NULL, `first_name` VARCHAR(64) NOT NULL, `last_name` VARCHAR(64) NOT NULL, `is_favorite` TINYINT(1) NOT NULL DEFAULT 0, `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `uniq_owner_name` (`owner_identifier`, `first_name`, `last_name`), INDEX `idx_owner_fav` (`owner_identifier`, `is_favorite`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; ``` -------------------------------- ### SQL Query: View pending inbox entries Source: https://docs.murphy-workshop.com/murphy-s-telegram-mail/advanced/database Joins the inbox and documents tables to list all pending mail. ```sql SELECT i.id, i.identifier, i.status, d.type, d.object, d.sender_firstname, d.sender_lastname FROM post_inbox i JOIN post_documents d ON d.id = i.document_id WHERE i.status = 'pending' ORDER BY i.id DESC; ``` -------------------------------- ### Retrieve Registered Mailboxes Source: https://docs.murphy-workshop.com/murphy-s-telegram-mail/advanced/player-home-mailboxes Fetch a list of all registered mailboxes or filter them by a specific owner identifier. ```lua -- All mailboxes: local all = exports.murphy_post:GetPlayerMailboxes() -- Only for a specific owner: local mine = exports.murphy_post:GetPlayerMailboxes('32') -- Returns: { -- { id = 1, externalId = 'housing_plot_42', ownerIdentifier = '32', -- label = "John's Mailbox", coords = {x=100, y=200, z=50}, -- heading = 90.0, propModel = 'p_mailbox01x' }, -- ... -- } ``` -------------------------------- ### Telegram visual layout diagram Source: https://docs.murphy-workshop.com/murphy-s-telegram-mail/advanced/templates-stationery A visual representation of the telegram layout, showing the placement of header text, footer text, and image overlays. ```text +========================================+ | +----------------------------------+ | | | -- TELEGRAM TITLE -- | | <- headerText (centered, uppercase) | | disclaimer text... | | | | ============================ | | | | Shipper / Receiver / Box | | | | ============================ | | | | Object: ... | | | | Body: ... | | | | | | | | [Send] | | | | Footer text... | | <- footerText | +----------------------------------+ | +========================================+ ^ borderImage (frame overlay) ^ backgroundImage (behind everything) ``` -------------------------------- ### SQL Schema for post_documents Source: https://docs.murphy-workshop.com/murphy-s-telegram-mail/advanced/database Defines the structure for storing letters and telegrams, including sender and receiver details, content, and timestamps. ```sql CREATE TABLE IF NOT EXISTS `post_documents` ( `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, `type` ENUM('letter','telegram') NOT NULL, `sender_identifier` VARCHAR(64) NOT NULL, `sender_firstname` VARCHAR(64) NOT NULL, `sender_lastname` VARCHAR(64) NOT NULL, `sender_office_id` VARCHAR(64) NULL, `destination_mailbox_id` VARCHAR(64) NULL, `receiver_firstname` VARCHAR(64) NULL, `receiver_lastname` VARCHAR(64) NULL, `package_type` VARCHAR(64) NULL, `package_meta` TEXT NULL, `amount` INT NULL, `object` VARCHAR(128) NOT NULL, `body` TEXT NOT NULL, `signature` VARCHAR(64) NOT NULL, `created_at` DATETIME NOT NULL, `available_at` DATETIME NULL, `template_id` VARCHAR(32) NULL, `font_id` VARCHAR(32) NULL, PRIMARY KEY (`id`), INDEX `idx_sender` (`sender_identifier`), INDEX `idx_receiver_name` (`receiver_firstname`, `receiver_lastname`), INDEX `idx_sender_office` (`sender_office_id`), INDEX `idx_dest_mailbox` (`destination_mailbox_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; ``` -------------------------------- ### Configure LetterTemplates structure Source: https://docs.murphy-workshop.com/murphy-s-telegram-mail/advanced/templates-stationery Defines the structure for letter templates, including unique IDs, labels, job restrictions, and image paths relative to the ui/templates/ directory. ```lua Config.LetterTemplates = { { id = 'default', -- Unique ID (stored in DB per document) label = 'Standard Paper', -- Display name in stationery dropdown jobs = {}, -- Empty = available to everyone -- Images (paths relative to ui/templates/) backgroundImage = 'letter_default.png', -- Full page background texture headerImage = 'header_default.png', -- Wide banner at the top stampImage = nil, -- Small square image, bottom-right (optional) -- Text overrides (nil = use default i18n strings) headerText = nil, -- Bold title above body area footerText = nil, -- Text at the bottom of the letter }, } ``` -------------------------------- ### Monitor Statebag Changes Source: https://docs.murphy-workshop.com/murphy-s-telegram-mail/advanced/external-api Use AddStateBagChangeHandler to trigger logic whenever the unread message count changes. ```lua AddStateBagChangeHandler('telegramUnreadMessages', ('player:%s'):format(GetPlayerServerId(PlayerId())), function(_, _, value) print('You now have ' .. tostring(value) .. ' letters waiting at the post office.') end) ``` -------------------------------- ### Send a newsletter to all online players Source: https://docs.murphy-workshop.com/murphy-s-telegram-mail/advanced/external-api Iterates through all currently online players and sends a telegram to each one individually. ```lua local players = GetPlayers() for _, playerId in ipairs(players) do local pid = tonumber(playerId) local firstname = GetCharFirstname(pid) local lastname = GetCharLastname(pid) if firstname and lastname then exports.murphy_post:SendTelegram( { identifier = 'admin', firstname = 'Server', lastname = 'Admin' }, { firstName = firstname, lastName = lastname }, { object = 'Server Announcement', body = 'Important news...', signature = 'Staff Team' }, { delay = 0 } ) end end ``` -------------------------------- ### RecipientData Option B: Send to a Job Mailbox Source: https://docs.murphy-workshop.com/murphy-s-telegram-mail/advanced/external-api RecipientData structure for sending to a specific job mailbox ID. ```lua { mailboxId = "sheriff_rhodes" } ``` -------------------------------- ### RecipientData Option A: Send to a Person Source: https://docs.murphy-workshop.com/murphy-s-telegram-mail/advanced/external-api RecipientData structure for sending to a specific person by name. ```lua { firstName = "John", lastName = "Marston" } ``` -------------------------------- ### Item Metadata Convention Source: https://docs.murphy-workshop.com/murphy-s-telegram-mail/advanced/database The structure of metadata applied to items when delivered to a player's inventory. ```lua { document_id = 123, -- FK to post_documents.id description = "Subject - SenderFirst SenderLast", -- Display text in inventory opened = false -- Flipped to true on first use } ``` -------------------------------- ### SQL Query: Find mail for a specific character Source: https://docs.murphy-workshop.com/murphy-s-telegram-mail/advanced/database Retrieves all mail associated with a specific character identifier, ordered by creation date. ```sql SELECT d.* FROM post_inbox i JOIN post_documents d ON d.id = i.document_id WHERE i.identifier = 'CHARACTER_ID_HERE' ORDER BY i.created_at DESC; ``` -------------------------------- ### GetPlayerMailboxes Source: https://docs.murphy-workshop.com/murphy-s-telegram-mail/advanced/player-home-mailboxes Retrieves a list of all registered mailboxes, with an optional filter by owner identifier. ```APIDOC ## GetPlayerMailboxes ### Description Returns a list of registered mailboxes. Optionally filter by owner. ### Parameters - **ownerIdentifier** (string) - Optional - Filter mailboxes by a specific owner identifier. ### Response - **Array** (object) - A list of mailbox objects containing id, externalId, ownerIdentifier, label, coords, heading, and propModel. ``` -------------------------------- ### Define Post Offices Source: https://docs.murphy-workshop.com/murphy-s-telegram-mail/getting-started/configuration Configures NPC locations where players can send and receive mail, including coordinates, ped models, and ambient speech settings. ```lua Config.PostOffices = { { id = 'rhodes', -- Unique identifier label = 'Rhodes Post Office', -- Display name coords = vec3(1226.776611, -1295.083984, 76.905350),-- NPC position heading = 46.0, -- NPC facing direction pnj = 'u_m_m_rhdtrainstationworker_01', -- Ped model outfit = 0, -- Ped outfit variation speechDict = "0406_U_M_M_RHDTRAINSTATIONWORKER_01", -- Ambient speech dict speech = { -- Ambient speech lines "CHAT_SHOPKEEPER_GOSSIP", "CHAT_LOCAL_AREA", "HOWS_IT_GOING", } }, -- Add more post offices here... } ``` -------------------------------- ### Letter template layout diagram Source: https://docs.murphy-workshop.com/murphy-s-telegram-mail/advanced/templates-stationery Visual representation of the letter template layout, showing the placement of header images, header text, stamps, and footer text. ```text +----------------------------+ | | | [ headerImage ] | <- Wide banner, always shown | | | Receiver: John Doe | | Box Office / Package | | ----------------------- | | SHERIFF'S OFFICE | <- headerText (optional, bold, centered) | Object: ... | | Body: ... | | | | [STAMP]| <- stampImage (optional, bottom-right) | ====================== | | [Send] | | Official document - ... | <- footerText +----------------------------+ ``` -------------------------------- ### Send a simple telegram to a player Source: https://docs.murphy-workshop.com/murphy-s-telegram-mail/advanced/external-api Sends a standard telegram to a specific player using their first and last name. ```lua local result = exports.murphy_post:SendTelegram( { identifier = 'bank_system', firstname = 'Bank', lastname = 'of Lemoyne' }, { firstName = 'John', lastName = 'Marston' }, { object = 'Weekly Statement', body = string.format('Dear client,\n\nYour weekly interest has been applied.\nNew balance: $%.2f', newBalance), signature = 'The Management' }, { delay = 0 } ) ``` -------------------------------- ### Configure Character Limits Source: https://docs.murphy-workshop.com/murphy-s-telegram-mail/getting-started/configuration Defines the maximum character lengths for telegrams, letters, and recipient names. ```lua Config.NUI = { telegramMaxChar = 120, -- Max body length for telegrams telegramMaxCharObject = 64, -- Max subject length telegramMaxCharSign = 32, -- Max signature length letterMaxChar = 10000, -- Max body length for letters letterMaxCharObject = 64, -- Max subject length letterMaxCharSign = 32, -- Max signature length nameMaxChar = 16, -- Max recipient name length } ``` -------------------------------- ### Send Telegram and Letter via Events Source: https://docs.murphy-workshop.com/murphy-s-telegram-mail/advanced/external-api Alternative method for sending telegrams and letters using TriggerEvent with a callback function. ```lua TriggerEvent('murphy_post:sendTelegramExternal', senderData, recipientData, telegramData, options, function(result) -- handle result end) TriggerEvent('murphy_post:sendLetterExternal', senderData, recipientData, letterData, options, function(result) -- handle result end) ``` -------------------------------- ### exports.murphy_post:SendTelegram Source: https://docs.murphy-workshop.com/murphy-s-telegram-mail/advanced/external-api Sends a telegram using the exported function. ```APIDOC ## exports.murphy_post:SendTelegram ### Description Sends a telegram message to a specified recipient. ### Parameters - **senderData** (table) - Optional - Sender information including identifier, names, and office ID. - **recipientData** (table) - Required - Recipient information (either name or mailboxId). - **telegramData** (table) - Required - Telegram content including subject, body, and optional metadata. - **options** (table) - Optional - Delivery options such as delay. ``` -------------------------------- ### Send a scheduled reminder Source: https://docs.murphy-workshop.com/murphy-s-telegram-mail/advanced/external-api Sends a telegram with a delay, useful for scheduling reminders or future notifications. ```lua exports.murphy_post:SendTelegram( { identifier = 'reminder', firstname = 'Reminder', lastname = 'System' }, { firstName = 'John', lastName = 'Marston' }, { object = 'Appointment Reminder', body = 'Your appointment is in 1 hour.', signature = 'Auto-Reminder' }, { delay = 3600 } -- delivered in 1 hour ) ``` -------------------------------- ### API Return Value Structure Source: https://docs.murphy-workshop.com/murphy-s-telegram-mail/advanced/external-api The structure of the table returned by API calls, indicating success or failure and providing relevant IDs or error messages. ```lua { ok = true, -- boolean: success or failure id = 123, -- number: created document ID (if ok = true) error = "..." -- string: error code (if ok = false) } ``` -------------------------------- ### exports.murphy_post:SendLetter Source: https://docs.murphy-workshop.com/murphy-s-telegram-mail/advanced/external-api Sends a letter using the exported function. ```APIDOC ## exports.murphy_post:SendLetter ### Description Sends a physical letter, optionally including a package. ### Parameters - **senderData** (table) - Optional - Sender information. - **recipientData** (table) - Required - Recipient information. - **letterData** (table) - Required - Letter content including subject, body, and optional package details. - **options** (table) - Optional - Delivery options. ``` -------------------------------- ### TriggerEvent('murphy_post:sendTelegramExternal') Source: https://docs.murphy-workshop.com/murphy-s-telegram-mail/advanced/external-api Triggers a telegram send via event. ```APIDOC ## TriggerEvent('murphy_post:sendTelegramExternal') ### Description Triggers the telegram sending process externally via event system. ``` -------------------------------- ### Telegram Pricing Formula Source: https://docs.murphy-workshop.com/murphy-s-telegram-mail/getting-started/features-overview The formula used to calculate the cost of a telegram based on base price and character count. ```text cost = telegramBasePrice + (telegramPriceChar x characterCount) ``` -------------------------------- ### Notification Configuration Source: https://docs.murphy-workshop.com/murphy-s-telegram-mail/getting-started/configuration Controls whether recipients receive notifications for incoming letters or telegrams. Notifications only trigger if the recipient is online. ```lua Config.LetterNotification = true -- Notify recipient when a letter arrives Config.TelegramNotification = true -- Notify recipient when a telegram arrives ``` -------------------------------- ### exports.murphy_post:SendLetter Source: https://docs.murphy-workshop.com/murphy-s-telegram-mail/advanced/external-api Sends a letter to a recipient. If a packageType is provided, the sender must manually remove the items from their inventory before calling this export. ```APIDOC ## exports.murphy_post:SendLetter ### Description Sends a letter to a recipient. If the recipient is online, they receive an in-game notification; otherwise, the mail is stored in the database for their next visit to a post office. ### Important Notes - **Inventory**: Items are not automatically removed from the sender's inventory when using `packageType`. - **Notifications**: Recipients receive notifications if enabled in the configuration. ``` -------------------------------- ### exports.murphy_post:SendTelegram Source: https://docs.murphy-workshop.com/murphy-s-telegram-mail/advanced/external-api Sends a telegram to a specific player or mailbox. Supports scheduling via a delay parameter. ```APIDOC ## exports.murphy_post:SendTelegram(sender, recipient, content, options) ### Description Sends a telegram message to a specified recipient. The sender and recipient can be identified by system identifiers or specific player names/mailbox IDs. ### Parameters - **sender** (table) - Required - Contains sender details: `identifier`, `firstname`, `lastname`. - **recipient** (table) - Required - Contains recipient details: `firstName`, `lastName` or `mailboxId`. - **content** (table) - Required - Contains message details: `object`, `body`, `signature`. - **options** (table) - Optional - Contains delivery settings: `delay` (in seconds). ``` -------------------------------- ### Send a telegram to a job mailbox Source: https://docs.murphy-workshop.com/murphy-s-telegram-mail/advanced/external-api Sends a telegram to a specific job mailbox identified by mailboxId, defaulting to System Admin sender. ```lua local result = exports.murphy_post:SendTelegram( {}, -- defaults to System Admin { mailboxId = 'sheriff_rhodes' }, { object = 'Crime Report', body = 'A robbery was reported near the Valentine train station.', signature = 'Anonymous Citizen' } ) ``` -------------------------------- ### Unregister a player mailbox Source: https://docs.murphy-workshop.com/murphy-s-telegram-mail/advanced/player-home-mailboxes Use the UnregisterPlayerMailbox export to remove a mailbox from the system when a player sells or loses their property. ```lua exports.murphy_post:UnregisterPlayerMailbox('property_' .. property.id) ``` -------------------------------- ### Unregister a Player Mailbox Source: https://docs.murphy-workshop.com/murphy-s-telegram-mail/advanced/player-home-mailboxes Remove a mailbox prop and its interaction point using either the database ID or the external ID. ```lua -- By database ID: local result = exports.murphy_post:UnregisterPlayerMailbox(1) -- By external ID: local result = exports.murphy_post:UnregisterPlayerMailbox('housing_plot_42') -- result = { ok = true } -- result = { ok = false, error = 'mailbox_not_found' } ``` -------------------------------- ### Letter Pricing Formula Source: https://docs.murphy-workshop.com/murphy-s-telegram-mail/getting-started/features-overview The formula used to calculate the cost of a letter based on base price and the number of items attached. ```text cost = letterBasePrice + (letterPricePerItem x itemCount) ``` -------------------------------- ### Read Unread Message Count Source: https://docs.murphy-workshop.com/murphy-s-telegram-mail/advanced/external-api Access the current unread message count directly from the player statebag in any client-side script. ```lua local count = LocalPlayer.state.telegramUnreadMessages or 0 ``` -------------------------------- ### TriggerEvent('murphy_post:sendLetterExternal') Source: https://docs.murphy-workshop.com/murphy-s-telegram-mail/advanced/external-api Triggers a letter send via event. ```APIDOC ## TriggerEvent('murphy_post:sendLetterExternal') ### Description Triggers the letter sending process externally via event system. ``` -------------------------------- ### UnregisterPlayerMailbox Source: https://docs.murphy-workshop.com/murphy-s-telegram-mail/advanced/player-home-mailboxes Removes a mailbox by its database ID or external ID, despawning the prop and removing the interaction. ```APIDOC ## UnregisterPlayerMailbox ### Description Removes a mailbox. The prop is despawned and the interaction removed for all players. ### Parameters - **identifier** (number/string) - Required - The database ID or externalId of the mailbox to remove. ### Response - **ok** (boolean) - Success status - **error** (string) - Error message on failure ``` -------------------------------- ### exports.murphy_post:SendTelegram Source: https://docs.murphy-workshop.com/murphy-s-telegram-mail/advanced/external-api Sends a telegram to a recipient. Note that this function does not automatically handle payments or inventory removal. ```APIDOC ## exports.murphy_post:SendTelegram ### Description Sends a telegram to a specified recipient. The function returns a table indicating success or failure. ### Return Value - **ok** (boolean) - Success or failure status - **id** (number) - Created document ID (if ok is true) - **error** (string) - Error code (if ok is false) ### Error Codes - **recipient_not_found**: First/last name doesn't match any character - **missing_mailbox**: Mailbox routing requested but no mailboxId provided - **db_insert_failed**: Database insert error ``` -------------------------------- ### UnregisterPlayerMailbox Source: https://docs.murphy-workshop.com/murphy-s-telegram-mail/advanced/player-home-mailboxes Removes a registered mailbox from the system using its external ID. ```APIDOC ## UnregisterPlayerMailbox ### Description Unregisters an existing mailbox using the external ID provided during registration. ### Parameters - **externalId** (string) - Required - The unique identifier used when registering the mailbox. ### Example ```lua exports.murphy_post:UnregisterPlayerMailbox('property_' .. property.id) ``` ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.