Skip to content

Latest commit

 

History

9 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Pelican Beacon

A small Discord bot for a Pelican panel. It keeps one message in a channel, always up to date, listing your servers with their addresses — and lets the people you choose start and stop them from buttons on that message.

┌─────────────────────────────────────────────┐
│ ## 🎮 Game Servers                          │
│ ─────────────────────────────────────────── │
│ 🟢 Satisfactory · play.example.com:25501    │
│    CPU 24% · RAM 3.1/16 GB      [ ⏹ Stop ]  │
│                                             │
│ ⚫ Palworld · play.example.com:25500        │
│                                 [ ▶ Start ] │
│ ─────────────────────────────────────────── │
│ 1/5 online · updated 4 seconds ago          │
│ [ Manage permissions ] [ Permission list ]  │
└─────────────────────────────────────────────┘

What it does

  • One message, not a feed. The panel is edited in place and re-used across restarts, so the channel never fills with status spam.
  • Says only what matters. A status dot, the address you paste into the game, and CPU/RAM for the servers that are actually running. Online servers sort to the top; when there are more servers than fit, the panel pages rather than growing without end.
  • Start/stop that tells you the truth. Actions that cannot work are refused before anything is sent, requests are serialised per server, and the bot watches the server afterwards and reports what actually happened — including the case where it starts, crashes and drops back to offline.
  • Permissions you can edit from Discord. Grants attach to users or roles, can be limited to particular servers, and are stored outside the config file. The admin ids in the config are permanent, so you cannot lock yourself out.

Install as a Pelican egg

  1. In your panel: Admin → Eggs → Import Egg, and upload egg-pelican-beacon.json.

  2. Create a server from the Pelican Beacon egg. It needs no allocation and very little memory (256 MB is plenty).

  3. Fill in the variables:

    Variable What it is
    Discord Bot Token From the Developer Portal → your app → BotReset Token. Admin-only field.
    Panel Client API Key Panel → your account menu → API Credentials → create one. Admin-only field.
    Panel URL e.g. https://panel.example.com
    Status Channel ID Right-click the channel → Copy Channel ID (needs Developer Mode).
    Discord Server ID Optional; makes slash commands appear immediately.
    Admin User IDs Your Discord user id. Comma-separated for several.

    The rest — title, layout, page size, refresh rate, hidden servers — have sensible defaults and can be changed later, either as variables or in config.json on the server.

  4. Start it. The panel appears within a few seconds.

The bot hides the server it is itself running on, so it never lists itself.

Inviting the bot

The bot needs no privileged intents. In the Developer Portal → OAuth2URL Generator, tick bot and applications.commands, and give it View Channel, Send Messages and Read Message History in the channel the panel lives in.

Install anywhere else

git clone https://github.com/valentinps/pelican-beacon.git
cd pelican-beacon
python -m venv .venv && .venv/bin/pip install -r requirements.txt
cp config.example.json config.json && chmod 600 config.json   # then edit it
.venv/bin/python -m beacon config.json

Python 3.11+.

Configuration

Everything lives in config.json. Any value can also be supplied as an environment variable, which always wins — that is how the egg passes secrets without writing them to disk.

Section Key Env Meaning
discord token DISCORD_TOKEN Bot token. Treat as a password.
status_channel_id BEACON_STATUS_CHANNEL_ID Channel the panel lives in
guild_id BEACON_GUILD_ID Your server id (fast command sync)
panel url PANEL_URL Panel base URL
client_api_key PANEL_CLIENT_API_KEY Client API key. Treat as a password.
display title BEACON_TITLE Heading of the panel
title_emoji BEACON_TITLE_EMOJI Emoji before the heading; empty for none
manage_buttons BEACON_MANAGE_BUTTONS Admin buttons under the panel
layout BEACON_LAYOUT sections or compact
public_host BEACON_PUBLIC_HOST Show a domain instead of the IP
show_resources BEACON_SHOW_RESOURCES CPU/RAM line for running servers
shorten_shared_host Print a shared host once, ports per row
hide_servers BEACON_HIDE_SERVERS Names/ids to leave out
hide_servers_without_allocation BEACON_HIDE_UNALLOCATED Skip serverless-looking entries
page_size BEACON_PAGE_SIZE Servers per page (1–8)
refresh_seconds BEACON_REFRESH_SECONDS Poll interval (min 5)
accent_colour BEACON_ACCENT_COLOUR Hex colour of the card's edge
footer_note BEACON_FOOTER_NOTE Extra small line at the bottom
power stop_signal BEACON_STOP_SIGNAL stop (clean) or kill
transition_timeout Seconds to wait for a server to settle
locked_servers BEACON_LOCKED_SERVERS Shown, but never controllable
permissions admin_user_ids BEACON_ADMIN_USER_IDS Permanent admins
operators BEACON_OPERATORS May control every server
server_operators BEACON_SERVER_OPERATORS Per-server access
everyone_can_start BEACON_EVERYONE_CAN_START Anyone may start
everyone_can_stop BEACON_EVERYONE_CAN_STOP Anyone may stop

Keeping the secrets secret

  • Under the egg, the token and API key are panel variables marked admin-only, so they are never written into config.json and are not visible to users who can see the server.
  • If you do put them in config.json, the bot forces the file to mode 600 on startup and warns you if it was readable by anyone else.
  • Both values are stripped from anything the bot logs.

Permissions

Three layers, and a person gets whatever the most generous one gives them.

1. Admins — ids in permissions.admin_user_ids (or the Admin User IDs egg variable). They can do anything and cannot be revoked from Discord, so you can never lock yourself out.

2. Config lists — the quick way to set everything up without touching Discord. Every id here may be a user id or a role id; both are checked, so there is nothing to get wrong.

"permissions": {
  "admin_user_ids": ["475629729995554837"],
  "operators": ["123456789012345678"],          // start + stop, every server
  "server_operators": {                          // per server
    "Satisfactory": ["234567890123456789"],      // a role id works here too
    "Palworld": ["345678901234567890"]
  },
  "everyone_can_start": false,                   // anyone who sees the panel
  "everyone_can_stop": false
}

As egg variables, the same thing:

Variable Example
BEACON_OPERATORS 123456789012345678, 234567890123456789
BEACON_SERVER_OPERATORS Satisfactory=234567890123456789; Palworld=345678901234567890
BEACON_EVERYONE_CAN_START 1
BEACON_EVERYONE_CAN_STOP 0

Layers 1 and 2 are read once at startup, so changing an egg variable or the config file needs a restart. Layer 3 never does.

3. Grants made from Discord, stored in permissions.json. The easiest way is the Manage permissions button under the panel — same screen as:

/permissions setup

Pick a server from the dropdown, pick the members and roles, then press Start + stop, Start only or Remove access. It shows who can already control that server, and adding a second server widens someone's access instead of replacing it. For the typed equivalent:

/permissions grant  target:@Friends  level:operator  servers:Satisfactory, Palworld
/permissions grant  target:@Alice    level:operator  can:"start only"
/permissions revoke target:@Alice
/permissions list

permissions.json is re-read whenever it changes, so editing it by hand in the panel's file manager also takes effect on the next click without a restart.

servers accepts names, short ids or UUIDs. A start-only restriction applies to a person's whole grant rather than per server, so pressing Start + stop for one server lifts it everywhere for them.

Level Can
viewer Nothing beyond seeing the panel, which everyone in the channel can do anyway
operator Start and stop the servers in their scope — optionally only one of the two
admin Everything, plus handing out permissions

Servers listed in power.locked_servers are shown but can never be controlled from Discord, whatever anyone's permissions say.

Commands

Command Who What
/panel refresh admin Redraw the panel now
/panel move admin Move the panel into the current channel
/panel status anyone What the bot can see, and its latency
/permissions setup admin Pick a server, pick who may control it
/permissions list admin Every grant, from all three layers
/permissions grant admin Give a user or role access, by name
/permissions revoke admin Take it away

Day to day nobody needs a command: the buttons do the work.

Troubleshooting

The panel never appears. The bot needs View Channel and Send Messages in that channel; check the console for a permission error, and that the channel id is the channel's, not the server's.

Buttons say "you do not have permission". Only the config admins can act until someone is granted operator with /permissions grant.

A server says "state unknown". The panel answered but wings did not — usually the node is down. The panel keeps trying.

"started but shut itself down again". The process exited on its own; the bot's job ends at reporting it. Open that server's console in the panel.

Layout

beacon/
  panel.py        Pelican client API wrapper
  power.py        start/stop: validation, locking, watching, outcomes
  permissions.py  grants for users and roles, persisted as JSON
  permissions_ui.py  the /permissions setup screen
  render.py       builds the Components V2 card
  bot.py          the bot: update loop, button dispatch, slash commands
  config.py       config file + environment loading

Licence

MIT

About

A tidy Discord status panel and power switch for a Pelican game-server panel

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages