The paid bot is a separate Windows executable that connects your Discord server to your ASA cluster, using the same database the plugin uses.
With the bot running, I get:
Important: the plugin has its own
config.jsonin the plugin folder, and the bot has a separateconfig.jsonin the bot folder. They are not the same file, but they must agree on things like MySQL settings and server keys.
This page explains how to set it up using this exact bot config structure.
Crosschat plugin installed (premium required)
The bot is designed to work with the premium plugin:
config.json must already be pointing to MySQL and working.MySQL/MariaDB database
Ark:SA Permissions plugin (for role sync)
players table (or whatever you configured).PermissionsMySQL block must point to this DB.Discord application and bot token
Windows host for the bot
CrosschatAscendedBot.exe) on a Windows machine.RCON enabled on game servers (for RCON features)
-RCONEnabled-RCONPort=<port>-RconIp=<ip> and/or -ServerIP=<public ip> or -MULTIHOME=<local ip>.-RconIp=-ServerIP=-MULTIHOME=-RconIp= or -MULTIHOME=.config.jsonDownload the bot
Folder layout
Example layout on the bot machine:
C:\CrosschatBot\
CrosschatAscendedBot.exe
config.json
logs\
From now on I’ll walk through this config:
{
"AccountKey": "",
"Debug": false,
"AutoRestartOnCrash": true,
"AutoRestartEveryHours": 6,
"BotToken": "",
"MySQL": { ... },
"PermissionsMySQL": { ... },
"General": { ... },
"PlayerList": { ... },
"BotStatus": { ... },
"AdminPlayerList": { ... },
"Verification": { ... },
"RoleSyncing": [ ... ],
"RconPasswords": { ... },
"Messages": { ... },
"ScheduledTasks": { ... },
"CustomPanels": { ... },
"CustomButtons": { ... },
"ServerNames": { ... }
}
AccountKey"AccountKey": ""
/licenses in DM).Debug"Debug": false
true, the bot logs extra information to help debug issues."AutoRestartOnCrash": true,
"AutoRestartEveryHours": 6,
AutoRestartOnCrash:
true, the bot will try to auto-restart itself after crashes.AutoRestartEveryHours:
-1 to disable scheduled restarts.This is useful for long-running setups to avoid memory leaks or weird Discord library behavior over weeks.
MySQL)"MySQL": {
"Host": "",
"User": "",
"Password": "",
"Database": "",
"Port": 3306
},
config.json:
Host – DB host or IP.User / Password – DB credentials.Database – Crosschat database name.Port – usually 3306.If this is wrong, the bot can’t see chat, players, or map data.
PermissionsMySQL)"PermissionsMySQL": {
"Host": "",
"User": "",
"Password": "",
"Database": "",
"Port": 3306
},
players) with fields containing permission group info for players.General section – core behaviour"General": {
"AutoUnlinkPlayersAfterDaysInactive": 30,
"UnlinkRemovesGame-DiscordRoles": true,
"UnlinkRemovesDiscord-GamePermissions": true,
"UnlinkIfLeavingDiscordServer": true,
"DiscordOwnerId": 1057656944556515368,
"RconResponsesJustYouCanSeeIt": true,
"RconResponseFormat": "Response from `{server}` (Command: {cmd}\n```{response}```",
"IngameChatChannelId": 1057656944556515368,
"PurgeChatOlderThanDays": 7,
"TimeFormat": "%Y-%m-%d %H:%M:%S",
"IngameChatFormat": "[{time}] {platform} **[{map}] {player}{tribename}**: {message}",
"Platforms": { ... },
"PanelEmbed": { ... },
"LinkDiscordButton": { ... },
"GetEosButton": { ... },
"KickmeButton": { ... }
}
AutoUnlinkPlayersAfterDaysInactive:
0 disables this behaviour.UnlinkRemovesGame-DiscordRoles:
true, when unlinking, roles that came from game → Discord sync are removed.UnlinkRemovesDiscord-GamePermissions:
true, unlinking removes game permissions that came from Discord roles.UnlinkIfLeavingDiscordServer:
true, leaving the Discord server automatically unlinks the player and removes synced roles.These are your safety and cleanup rules; tune them to how strict you want to be.
DiscordOwnerId:
RconResponsesJustYouCanSeeIt:
true, RCON command responses are sent as ephemeral messages – only the command invoker can see them.RconResponseFormat:
{server}, {cmd}, {response}.IngameChatChannelId:
PurgeChatOlderThanDays:
TimeFormat:
IngameChatFormat, using C/strftime style (%Y-%m-%d %H:%M:%S, etc).IngameChatFormat:
{time}, {platform}, {map}, {player}, {tribename}, {message}."Platforms": {
"Steam": "Steam",
"Xbox": "Xbox",
"Playstation": "PS"
},
"PS" to "PlayStation" or localize these values.PanelEmbed and the three buttons control the main crosschat control panel:
"PanelEmbed": {
"Color": [0, 255, 0],
"Url": "",
"Title": {
"Text": "Crosschat Ascended Panel",
"Url": "",
"IconUrl": ""
},
"Description": "Click one of the buttons to do something",
"Thumbnail": "",
"Image": "",
"Footer": {
"Text": "CrosschatAscended. Provided by Pelayori",
"IconUrl": ""
},
"CustomButtons": []
},
"LinkDiscordButton": {
"Enabled": true,
"Text": "Link Discord",
"Style": "SUCCESS"
},
"GetEosButton": {
"Enabled": true,
"Text": "Get your EOS ID",
"Style": "PRIMARY"
},
"KickmeButton": {
"Enabled": true,
"Text": "Kick you from the cluster",
"Style": "DANGER"
}
PanelEmbed:
CustomButtons here are IDs from CustomButtons section; if you list them, they appear as extra buttons.LinkDiscordButton:
GetEosButton:
KickmeButton:
All button Style values can be PRIMARY, SECONDARY, SUCCESS, DANGER (and LINK for link-only buttons).
"PlayerList": {
"Enabled": false,
"Color": [0, 255, 0],
"ChannelId": 1202313051366510712,
"RefreshRateSeconds": 10,
"Thumbnail": "",
"Image": "",
"Title": "Cluster. {nmaps} maps, {nplayers} players",
"Server": "{map} - {players} players.",
"Players": "{name} {tribe}",
"SurroundPlayersInCodeBlock": true,
"MarkupString": "md",
"Footer": {
"Text": "Provided by CrosschatAscended.",
"IconUrl": ""
}
},
Enabled is true, the bot periodically posts/updates an embed in ChannelId with:
{nmaps}, {nplayers}).Server template.Players template.SurroundPlayersInCodeBlock + MarkupString control whether players are shown inside a Discord code block (e.g. md, cs, etc).This is aimed at a public “who is online” overview.
"BotStatus": {
"Enabled": true,
"Statuses": [
["PLAYING", "with {players} players"],
["WATCHING", "{maps} maps, {players} players"],
["LISTENING", "to {players} players"]
]
}
Enabled, the bot cycles between these Discord presence statuses.[ "TYPE", "text" ]:
TYPE: PLAYING, WATCHING, or LISTENING.text can use {players} and {maps} placeholders."AdminPlayerList": {
"Enabled": true,
"ChannelId": 1202313051366510712,
"RefreshRateSeconds": 10,
"Color": [0, 255, 0],
"Thumbnail": "",
"Image": "",
"Title": "Cluster. {nmaps} maps, {nplayers} players",
"Server": "{map} - {players} players. Avg fps: {avgfps}. Current fps: {curfps}",
"SurroundPlayersInCodeBlock": true,
"MarkupString": "md",
"Players": "({playtime}s = {play_secs}s {play_mins}m {play_hours}h) {name} {tribe} ({eos}, {playerid}, {tribeid}) - {discordId} - {discordUsername} - {discordMention} - {discordName}",
"Footer": {
"Text": "Provided by CrosschatAscended.",
"IconUrl": ""
}
},
This is like PlayerList, but for staff:
"Verification": {
"RolesToGiveOnVerification": [728358128218931360],
"RenameDiscordMember": true,
"RenameFormat": "{name} {tribe}",
"TribeNameFormat": "[{name}]",
"TruncateNicknameIfTooLong": false,
"RemoveTribeNameFromNicknameIfTooLong": true
},
RolesToGiveOnVerification:
RenameDiscordMember:
true, after verification, the member’s nickname is changed.RenameFormat:
{name} – player name.{tribe} – formatted tribe name (via TribeNameFormat).{eos}, {tribeid}, {playerid} are also available. <PLACEHOLDER: confirm>TribeNameFormat: how tribe is rendered (e.g. [{name}]).TruncateNicknameIfTooLong / RemoveTribeNameFromNicknameIfTooLong:
"RoleSyncing": [
{
"RoleId": 728358128218931360,
"PermissionGroup": "Verified",
"Sync_Discord_To_Game": true,
"Sync_Game_To_Discord": true
}
],
Each entry links one Discord role ↔ one permission group:
RoleId: Discord role ID.PermissionGroup: Ark:SA permission group name.Sync_Discord_To_Game:
true, giving/removing the role in Discord adds/removes that permission group ingame.Sync_Game_To_Discord:
true, adding/removing the permission group in game adds/removes the Discord role.Use multiple entries for VIP, Donator, etc.
Make sure Ark:SA Permissions DB is correct. If the bot can’t find the player or group in the
playerstable, role sync won’t work.
"RconPasswords": {
"Default": "1234",
"Island-1": "1234",
"1.1.1.1:32330": "1234",
"1.1.1.1": "1234"
},
Default – used if nothing more specific matches.Island-1),IP:Port,The exact mapping method is version-dependent, but generally the bot will try to match the most specific entry first.
"Messages": {
"ConnectCode": "Your connect code is: {0}",
"ServerOffline": "Server is offline",
"NotLinked": "You are not linked. Please link your account first.",
"AlreadyLinked": "You are already linked.",
"Kickme": "You have been kicked from the cluster.",
"GetEos": "Your EOS ID is: {0}"
},
{0} is usually replaced by some dynamic value, e.g. connect code or EOS ID."ScheduledTasks": {
"Hearbeat": {
"IntervalSeconds": 60,
"ForMap": "All",
"Action": "HTTP",
"LogChannel": 1057656944556515368,
"ForEachMap": {
"RequireOnlineServer": true,
"Url": "http://localhost:8080/heartbeat",
"Data": "{ "ForServer": "%map%" }",
"Type": "application/json",
"Mode": "GET"
}
},
"BotHearbeat": {
"IntervalSeconds": 60,
"ForMap": "Bot",
"Action": "HTTP",
"LogChannel": 1057656944556515368,
"ForEachMap": {
"RequireOnlineServer": true,
"Url": "http://localhost:8080/heartbeat",
"Data": "{ "ForServer": "%map%" }",
"Type": "application/json",
"Mode": "GET"
}
},
"DestroyWildDinos": {
"IntervalSeconds": 86400,
"ForMap": "All",
"Action": "RCON",
"LogChannel": 1057656944556515368,
"ForEachMap": {
"Command": "DestroyWildDinos"
}
}
},
Each key (Hearbeat, BotHearbeat, DestroyWildDinos) is a task ID.
Common fields:
IntervalSeconds – how often to run.ForMap:
"All" – run once for each map."Online" – only for online maps. <PLACEHOLDER: exact behaviour>"Bot" – special pseudo-map for tasks not tied to any server.Action:
"HTTP" – send HTTP requests."RCON" – run RCON commands.LogChannel – Discord channel ID where results are logged.ForEachMap:
RequireOnlineServer – if true, only run if the server is online (ignored for "Bot").Url, Data, Type, Mode (GET/POST).%map% in Data is replaced by the map name.Command – RCON command to execute, e.g. DestroyWildDinos.You can delete the example tasks if you don’t want them, or change URLs/commands to fit your infrastructure.
This is the most powerful part: Discord panels with custom buttons that can:
"CustomPanels": {
"AdminPanel": {
"Color": [0, 255, 0],
"Url": "",
"Title": {
"Text": "Crosschat Ascended Panel",
"Url": "",
"IconUrl": ""
},
"Description": "Click one of the buttons to do something",
"Thumbnail": "",
"Image": "",
"Footer": {
"Text": "CrosschatAscended. Provided by Pelayori",
"IconUrl": ""
},
"Buttons": ["rconWipeWildDinos"]
},
"PlayerUtilities": {
"Color": [0, 255, 0],
"Url": "",
"Title": {
"Text": "Crosschat Ascended Panel",
"Url": "",
"IconUrl": ""
},
"Description": "Click one of the buttons to do something",
"Thumbnail": "",
"Image": "",
"Footer": {
"Text": "CrosschatAscended. Provided by Pelayori",
"IconUrl": ""
},
"Buttons": ["info", "rconWipeWildDinos"]
}
},
AdminPanel, PlayerUtilities) is an embed definition.Buttons is a list of button IDs that must exist in CustomButtons.You can expose these panels via slash commands, message components, or admin tools. /custompanel
Examples:
info – message action"info": {
"Action": "message",
"Response": "Hello {discordName} with eos id {eos} This is a custom button. ({discordId} - {discordUsername} - {discordMention} - {discordName})\n You can do anything with it. This is our website: https://example.com",
"OnlyUserCanSee": true,
"RequireEOSLinked": true,
"CooldownMinutes": 5,
"Button": {
"Text": "Info",
"Style": "PRIMARY"
},
"RequiresRoles": [728358128218931360]
},
{discordName}, {discordId}, {discordUsername}, {discordMention}, {eos}, etc.OnlyUserCanSee is true.RequireEOSLinked).infoLink – link button"infoLink": {
"Button": {
"Text": "Info",
"Style": "LINK"
},
"Url": "https://example.com"
},
rconDoSomething – RCON button"rconDoSomething": {
"Action": "rcon",
"ExecuteOnMap": "online",
"Command": "DoSomething",
"Response": "Rcon command executed: {response} from {server}. Cmd: {cmd}",
"OnlyUserCanSee": true,
"RequireEOSLinked": true,
"RequireOnline": true,
"Button": {
"Text": "Rcon Do Something",
"Style": "PRIMARY"
},
"RequiresRoles": [728358128218931360]
},
DoSomething via RCON on:
ExecuteOnMap = "online" → the server the player is currently on.RequireOnline ensures the player must be online.{response}, {server}, {cmd} placeholders.rconWipeWildDinos – cluster-wide RCON button"rconWipeWildDinos": {
"Action": "rcon",
"ExecuteOnMap": "all",
"Command": "DestroyWildDinos",
"Response": "Rcon command executed: {response}",
"OnlyUserCanSee": false,
"RequireEOSLinked": false,
"RequireOnline": false,
"Button": {
"Text": "Wipe wild dinos",
"Style": "PRIMARY"
},
"RequiresRoles": [728358128218931360]
},
DestroyWildDinos on all maps.OnlyUserCanSee: false).addPointsSQL, updateLastSeenSQL)Action: "sql" – run SQL queries.{eos_id} and {discord_id}.UseSameDatabaseAsCrosschat:
true, uses MySQL connection.false, uses the Database sub-block.Security note: Be careful with SQL queries – verify they do exactly what you want and don’t expose them to untrusted roles.
httpGetInfo)Action: "http" – make HTTP GET/POST requests.Url can contain {eos_id} and {discord_id}.Response can include {response}.executeSomeBatFile)Action: "windowsScript" – executes a local script:
ScriptToExecute: supports {eos_id} and {discord_id} parameters.ReadOutputFromScript: if true, output is captured and inserted into {response}.Only use this if you understand the security implications (anyone with the appropriate roles can indirectly execute a script on your bot machine).
"ServerNames": {
"ServerKey1": "TheIsland",
"ServerKey2CustomName": "CustomName"
}
-serverkey= in ASA startup) to pretty names.{server} or {map} appear. <PLACEHOLDER: exact fields>With this bot config structure, the typical player linking flow is:
Said button can be obtained using /panel on a discord channel ( admin command )
Bot generates a code and shows it to the player.
In-game, the player uses:
/setdiscord <code>
Plugin and bot talk via the shared DB and verify the code.
On success:
RolesToGiveOnVerification are given.RoleSyncing.Bot won’t start / crashes immediately
BotToken invalid → regenerate in Developer Portal and update.AccountKey missing → fill it in.Role sync doesn’t work
PermissionsMySQL points to wrong DB or DB doesn’t have expected schema.RoleSyncing are wrong or bot lacks Manage Roles.Player lists empty
MySQL settings don’t match plugin’s.Custom buttons do nothing
RequiresRoles) not met.RequireEOSLinked is true but user isn’t linked.If you hit something weird, grab:
config.json (redacted),and I can usually spot misconfigurations quickly.
Last updated: 2025-11-26T08:39:15