Official Discord bot for the Aether extension ecosystem.
AetherBot connects the Aether GitHub repository and the Aether-Extensions registry to your Discord server. It handles automated release announcements, extension browsing, and cryptographic developer verification — allowing extension authors to prove GitHub repository ownership and receive developer roles.
- Node.js 22+
- A Discord application with a bot token
- A GitHub personal access token (fine-grained, read-only)
- The
data/directory must be writable (SQLite database)
# Clone or copy the project
cd AetherBot
# Install dependencies
npm install
# Copy the example files
cp .env.example .env
cp config.example.json config.jsonEdit .env with your real tokens. Edit config.json with your guild and role IDs.
# Development (with hot reload)
npm run dev
# Build for production
npm run build
# Run production build
npm start- Go to discord.com/developers/applications
- Click New Application and name it
AetherBot - Go to the Bot tab → Click Add Bot
- Under Token, click Reset Token and copy it to your
.envasDISCORD_TOKEN
Under Bot → Privileged Gateway Intents, enable:
- ✅ Server Members Intent — required to fetch member objects for role assignment
Go to OAuth2 → URL Generator and select:
Scopes:
botapplications.commands
Bot Permissions:
- View Channels
- Send Messages
- Embed Links
- Manage Roles
Copy the generated URL and open it in your browser to invite the bot.
This step is critical. The bot can only manage roles that are positioned below its own role in the server's role list.
In Server Settings → Roles, drag the AetherBot role so it is positioned above both:
- Extension Developer
- Verified Extension Developer
If the bot's role is below these roles, role assignment will silently fail.
- Go to github.com/settings/personal-access-tokens
- Choose Fine-grained personal access token
- Set Resource owner to your personal account
- Under Repository access, choose Public Repositories (read-only)
- No additional permissions are required — the bot only reads public data
- Copy the token to your
.envasGITHUB_TOKEN
| Variable | Required | Description |
|---|---|---|
DISCORD_TOKEN |
✅ | Your bot token |
GITHUB_TOKEN |
✅ (recommended) | GitHub fine-grained token |
GITHUB_REPO |
Optional | Aether main repo (default: wayback09/Aether) |
GITHUB_REGISTRY_REPO |
Optional | Extensions registry repo (default: wayback09/Aether-Extensions) |
POLL_INTERVAL_SECONDS |
Optional | How often to poll for releases (default: 300) |
VERIFY_TOKEN_TTL_HOURS |
Optional | Verification token lifetime (default: 24) |
OWNER_USER_IDS |
Optional | Comma-separated Discord user IDs of Aether owners |
{
"ownerUserIds": ["123456789012345678"],
"guilds": {
"YOUR_GUILD_ID": {
"extensionDeveloperRoleId": "ROLE_ID",
"verifiedDeveloperRoleId": "ROLE_ID"
}
}
}Alternatively, configure roles in Discord using /config set-dev-role and /config set-verified-role.
Extension developers can verify their ownership of a GitHub repository to receive Discord roles.
/link-github username:your-github-username
The bot validates that the GitHub account exists.
/verify extension-id:your-extension-id
The bot generates a cryptographic token and displays it once (ephemeral). It will also show the repository URL.
In your extension's GitHub repository (the one listed in the Aether-Extensions registry), create a file called aether-verify.txt at the repository root containing exactly the token shown:
aether-verify.txt
─────────────────
abc123def456...your-64-char-token-here
Push the file to the main or master branch.
Run the same command again:
/verify extension-id:your-extension-id
The bot fetches aether-verify.txt from GitHub, compares it against the stored hash, and grants the appropriate role on success.
/verify-status
Shows your linked GitHub account, verified extensions, pending token status, and current roles.
/unlink
Removes your GitHub link, invalidates all pending tokens, removes verified extension records, and re-evaluates your roles.
| Role | Granted When |
|---|---|
| Extension Developer | GitHub linked + at least 1 verified extension (or in OWNER_USER_IDS) |
| Verified Extension Developer | Owns an extension with trust: "verified" or trust: "official" (or in OWNER_USER_IDS) |
Role state is re-evaluated:
- When verification succeeds
- When the extension registry refreshes (every 10 minutes)
- On bot startup
- When the bot joins a new server
- When you run
/config sync-roles - When you run
/unlink
/announce-channel add channel:#releases
/announce-channel remove channel:#releases
/announce-channel list
/announce-now
Posts the latest Aether release to all configured channels in the current server immediately (admin only).
The poller checks for new releases every 5 minutes by default. Releases are only posted once — the bot remembers announced releases in SQLite and survives restarts.
/extensions
Lists all registry entries with trust badges (🔵 Official, ✅ Verified, 👤 Community). Paginated with buttons if there are many entries.
/extension id:modrinth
Shows full details for a specific extension: name, ID, author, description, trust level, repository, and install URL.
/registry
Displays: number of extensions, cache age, last refresh time, GitHub connectivity status.
All admin commands require Manage Server permission.
| Command | Description |
|---|---|
/config set-dev-role |
Set the Extension Developer role |
/config set-verified-role |
Set the Verified Extension Developer role |
/config show |
Show current configuration |
/config sync-roles |
Re-evaluate all managed roles |
/announce-channel add/remove/list |
Manage announcement channels |
/announce-now |
Post the latest release immediately |
npm run buildCreate /etc/systemd/system/aetherbot.service:
[Unit]
Description=AetherBot Discord Bot
After=network.target
[Service]
Type=simple
User=aetherbot
WorkingDirectory=/opt/aetherbot
ExecStart=/usr/bin/node dist/index.js
Restart=on-failure
RestartSec=5
StandardOutput=journal
StandardError=journal
# Never log these — just in case
Environment=NODE_ENV=production
[Install]
WantedBy=multi-user.targetKeep .env outside the Git repository and on persistent disk:
# On the VPS
cp .env.example .env
nano .env # Fill in real tokensThe .env file is already in .gitignore.
sudo systemctl daemon-reload
sudo systemctl enable aetherbot
sudo systemctl start aetherbot
sudo journalctl -u aetherbot -f # Watch logsThe SQLite database is stored at data/aetherbot.db. Ensure this path is on persistent storage (not a tmpfs) and back it up regularly.
- Verification tokens are never stored in plaintext — only SHA-256 hashes
- Tokens are shown to users exactly once via ephemeral (private) Discord messages
- Tokens expire after 24 hours (configurable)
- Tokens are invalidated after 3 failed verification attempts
- The bot verifies against the registry's
repositoryfield only — users cannot supply an arbitrary repository - The bot never requests Administrator permission
- GitHub tokens and Discord tokens are never logged
Copyright (c) 2026 wayback09. All Rights Reserved.
This software is proprietary. No permission is granted to copy, modify, distribute, or host this software without explicit permission from the author.