Documentation 9.6.24
Discord integration
Use only the integration controls available in your installed panel and package.
Webhook setup#
Create a webhook in the intended Discord channel and save it in the relevant integration settings. Treat the webhook URL and bot token as secrets. Send a controlled test message before enabling notifications.
Permissions and troubleshooting#
Grant only the Discord permissions the integration needs. If messages fail, check the saved channel, token and provider response. Rotate a leaked webhook or bot token; do not paste it into logs or support screenshots.
Keep webhook, bot and login credentials separate#
Settings → Integrations contains separate fields for a Discord webhook URL, bot token and OAuth client credentials. The webhook identifies the notification destination, the bot token identifies the bot, and OAuth credentials belong to the login integration. Copying a value between these fields does not turn one workflow into another.
Decide which result you need first: a channel notification, an action supported by the installed bot, or Discord login. Configure and verify that workflow independently. A working webhook does not establish that bot commands are ready or that OAuth login is configured.
Treat the bot token, client secret and webhook URL as confidential. A community invite link is different and may be shared on your website; never put a secret webhook URL into the website’s Discord invite field. Review the permissions of teammates who can change integration settings.
Configure a controlled notification destination#
Select a channel restricted to the intended staff before enabling notifications. Review the destination before sending player or enforcement information, rather than publishing it broadly and adjusting access afterwards.
- Follow Discord’s official webhook guide to create an address for your own channel. Use only the address you created.
- Save its full value in the panel’s Discord webhook field. Check for whitespace, a truncated URL or an old value belonging to another channel.
- Use a test feature if the installed integration provides one; otherwise observe a safe, ordinary notification event. Do not ban a player or initiate a real payment as a test.
- Check the intended channel, message time and content. If no message appears, identify the failing workflow instead of generating the same event repeatedly.
Verify bot and OAuth settings independently#
When a bot is installed, grant only the permissions its used functions require. Filling the token field alone does not establish that its runtime or every command is configured. Follow the functions actually available in your installed package.
For OAuth, put the client ID and client secret in their respective fields. Match the redirect address to the installed login integration instead of inventing a callback path. Keep an existing administrator session available and check the login result in a separate browser session.
When reporting a failure, specify the workflow, error time and error text with secrets removed. Describe webhook, bot and login failures separately so support can identify the relevant channel, identity or login configuration without receiving your credentials.
Respond to an exposed credential#
If a token or webhook URL appeared in a screenshot or public file, removing the post alone is insufficient. Replace the affected value with the provider, update the panel and review other installations that used the old value.
- Save the replacement in the correct field and remove old public screenshots or posts.
- Verify an ordinary notification or login workflow again.
- Hide confidential fields in any new screenshots sent to support.
- Review channel access and team permissions after the replacement.
Trace a missing notification from event to channel#
When a Discord message is missing, first confirm that the expected event actually occurred and that the integration used by that event is configured. A saved webhook address alone cannot prove that every event produces a notification. Record the server or site involved and the event time before changing credentials.
If the ordinary event is visible in the panel but absent from Discord, check the destination channel and the saved webhook address. A deleted webhook, changed channel or copied address with missing characters needs correction at the appropriate stage. Preserve the previous non-secret configuration context so the change remains reviewable.
If a message arrives in an unexpected channel, restrict access there and correct the destination before further testing. Avoid repeatedly generating enforcement events to diagnose delivery. Give support the event category, time and masked error rather than the full webhook address or private player details.
Understand what an integration save preserves#
The bot token and OAuth client secret are confidential password fields. In the current settings implementation, leaving either secret field empty during a save preserves the stored value. An empty field shown on screen therefore does not by itself mean no secret is configured; check the field’s explanation before replacing anything.
When rotating a credential, paste the replacement into its own field and save with an authorized account. The webhook URL and client ID have separate fields and behavior. Do not use a blank save as an assumed way to revoke a bot token or OAuth secret; revoke an exposed credential through Discord.
Keep a note of which credential changed and when, excluding its value. Verify the specific workflow afterwards: channel delivery for a webhook, an available bot function for a bot, or an actual login result for OAuth. One successful workflow does not validate the other two.
Diagnose a Discord login return safely#
Begin a fresh login attempt from the correct website and keep that flow in the same browser session. OAuth uses state to connect the outgoing request with its return. Reopening an old callback address or mixing several login attempts can leave the return unrelated to the current session.
If login returns an invalid-state or similar message, note the error and start again from the normal login entry instead of repeatedly refreshing the callback. Check that browser settings or extensions are not blocking the cookies or navigation needed by that attempt. Keep an existing administrator session available while investigating.
Distinguish the platform’s Discord account login from custom integration credentials saved for a rented site. Confirm which flow is failing before changing a client ID or redirect setting. Do not send a callback URL containing authorization codes, state values, session details or secrets to public support channels.
Review notification content against the team’s needs#
A message arriving verifies delivery; providing clear context to the right people is a separate check. Examine a normal message generated by the installed integration: can you identify its server or website, event time and operation type? Read the existing message format rather than planning around a template editor or filtering option that the panel does not provide.
Restrict channel access to the team needing this information. Hide player identifiers and unnecessary personal details when exporting messages or taking screenshots. Explain that a detection message may not contain the event’s complete context; match its time with the relevant panel record. When several servers share a channel, check that their labels distinguish them sufficiently.
If a message is unclear, record event type, time and sanitized text. Clarify the installed integration’s output with support rather than assuming new features or sanctioning a player for a test. The expected acceptance result is that staff identify the same resource and event without disclosing secrets unnecessarily.
Check account choice and cancelled Discord login#
When reviewing OAuth login, consider a wrong Discord account or cancellation at the permission screen as well as a successful return. The browser may already have another Discord account signed in. Read the identity on the authorization screen and confirm the intended account. This is an identity workflow; changing a webhook destination does not fix it.
If the user cancels or declines, record the outcome and restart from the normal login entry. Do not distribute the previous callback URL; it may contain login-specific values. After a successful return, verify the displayed account and website context. Stop before administering an unexpected account. Creating another account or purchasing a plan does not validate identity matching.
Include the workflow, expected account, outcome and error time in your acceptance note, excluding tokens, client secret, state and authorization codes. Platform account login and a rented site’s custom integration are different. Naming the tested flow helps support investigate without changing unrelated credentials.
Install and verify the bot as a separate service#
The website, webhook and Discord bot are separate components. A working website or webhook does not establish a bot connection. Supply the application Client ID, target Guild ID, bot token and roles/channels belonging to that guild. Never place a token in support messages or a game resource.
Leaving a secret field blank preserves its current value. Saving a new token/API secret requires the site encryption key. Do not paste the displayed mask back as a token.
An installed service with missing IDs, credentials or database configuration is not a verified live bot. Check doctor first and actual Discord online status after activation.
Use a supported Node.js LTS release; the bot requires at least Node 22 LTS. The installed private service uses Node 24.21.0 LTS: /opt/tosun-discord-node/v24.21.0/bin/node. The service example uses the same executable for its ExecStartPre doctor check and ExecStart. Run npm ci and doctor with that runtime on PATH too. A failed doctor check prevents login; do not activate until required credentials are complete.
- Check Client ID and Guild ID in Discord Bot settings. Copy numeric IDs using Discord developer mode rather than names or invite links.
- Grant only the admin, moderator and support roles needed for your team. Administrator in another guild does not authorize actions in this bot’s configured guild.
- Verify the selected panel database and API address. Legacy commands needing game tables require separate framework/inventory support; do not grant global database administration.
- The operator installs independent command and encryption keys for the selected site, then runs its ledger migration. Never distribute the SaaS master key to customer bots. Migrate existing plaintext secrets only after the correct private key is installed.
- Use the locked dependencies with npm ci. npm run doctor checks connection, settings and ledgers without logging into Discord. Resolve missing configuration before activation.
- Restart after changing the token or API connection. After login, verify a harmless status command and correct guild/role. Do not use real player, money or ban operations as installation tests.
Distinguish completed, uncertain and repeated commands#
The bot acknowledges an interaction before database or API work. A timeout does not prove the action failed. Re-delivery of the same interaction is checked against its persistent ledger; sending a new command creates a new interaction.
- Wrong guild or missing role is rejected. Do not grant the entire team Administrator to bypass a configuration problem.
- Replaying a completed interaction does not repeat its mutation. Processing and unknown rows never become retryable merely because they age.
- Before sending a new money, item, ban, resource or server command after an uncertain response, inspect the actual panel result and operation ID. Deleting an unknown row is not a substitute for review.
- Screenshot, live-watch, sync and diag groups are not available through this bot’s secret-only path. Use the relevant panel screen with an authorized session. A listed command does not prove server completion.
- Support records should include only the operation ID, time, command name and a safe result. Never share tokens, signing keys, database passwords or full requests.
Keep Discord secrets separate from AC credentials#
A Discord bot token, webhook URL, OAuth client secret and Tosun panel/license key are different credentials. Do not paste one into another credential’s field. A connected bot does not prove webhook delivery; webhook delivery does not prove command permissions.
Keep bot tokens and bot API/operation secrets in private bot-service configuration or the authorized Discord panel fields. Never place them in shared configs/anticheat_config.lua, NUI, client Lua, public repositories or setup screenshots. The new server-only AC file is not a Discord bot-token field.
AC panel keys and server licenses belong in set settings in server.cfg or configs/anticheat_server.lua. Short-lived screenshot/video tokens authorize scoped evidence uploads only, not bot login, webhooks or package downloads.
Rotate an exposed bot token in the Discord application, a webhook in its channel and a Tosun key in its own authorized screen. Restart the affected service deliberately. Removing a local value does not revoke the remote credential.
- Verify the Discord application, guild, role and channel first. Share identifiers and times, not full tokens.
- Use a harmless status command and a secret-free test-channel notification for acceptance. Do not ban a player or alter their economy.
- For an uncertain operation, inspect the actual panel result and operation record before repeating a money, ban or server command.
Install the bundled Discord bot as a separate service#
The bundled discord-bot application runs on Node.js. Create your own application and bot in Discord Developer Portal. Use your own Application ID, Guild ID, channel IDs and role IDs. Keep the token in a private environment file. Do not add ensure discord-bot to server.cfg.
A rented site database account is restricted to the provider’s localhost by default. Running the bot on a separate FiveM machine does not open that connection. Use a managed service on the site host or a provider-approved private connection for your own site database user. Never use the provider root account or expose MySQL publicly. The bridge does not automatically support every legacy direct-SQL bot command; verify commands that require game tables separately.
As the site owner, save the bot token, Client ID and Guild ID in Site management → Discord bot. Use Download private bot setup and save that file as .env in your own bot folder. Unlike the empty example in the ZIP, it contains keys scoped to the selected site. Do not share it or commit it to source control.
- Install a supported Node.js LTS version at least 22; prepare the example configuration with the bundled setup script.
- Invite the bot with bot and applications.commands scopes. Grant the permissions required by its commands and channels.
- Configure the site database and HTTPS API address. The command signing key is a dedicated private site/bot credential, not a Tosun license or the main SaaS key.
- Run npm run doctor before starting. All required checks must pass. The doctor performs no Discord login or command delivery; verify online status and a permitted role separately.
cd discord-bot
sh setup.sh
# Configure the private .env and site bot settings first.
npm run doctor
npm start