Introduction
The Islamic Community Bot (code name digital-akhi-bot) is a production-grade, open-source Discord bot built specifically for Muslim communities. It combines verified Islamic knowledge retrieval, multilingual AI conversations, and robust community management tooling into a single, secure package.
The bot is fully self-hostable under the AGPL-3.0 License — you own every line that runs on your infrastructure. It is designed to be both community-friendly for non-technical server admins and developer-friendly for contributors who want to extend its capabilities.
Core Capabilities
- Multilingual AI — Understands Standard Arabic, English transliteration, and informal Arabizi (Arabic written in Latin script).
- Verified Islamic Knowledge — Hadiths with grading metadata (Sahih, Hasan, Da'if) and contextual Duas sourced from authenticated databases.
- Dynamic Prayer Times — City-based salah schedule via the open Aladhan API.
- Multi-Provider AI Failover — Automatically switches between Groq, Gemini, Cerebras, SambaNova, Together AI, and OpenRouter so the bot is never "down" due to a single provider outage.
- Invite & Boost Tier Tracking — Automatically upgrades server members based on invite counts or server boost status.
- Zero-Trust Security — Triple-quote prompt sandboxing, per-command permission verification, and encrypted BYOK credential storage.
- Automatic Data Archival — Nightly
zlib-compressed cold storage of interaction logs after a 30-day hot window.
Tech Stack
| Layer | Technology | Version | Purpose |
|---|---|---|---|
| Runtime | Node.js (ESM) | v18+ | JavaScript execution environment |
| Language | TypeScript | ^5.2 | Type-safe source code |
| Discord | discord.js | ^14.13 | Gateway connection & slash commands |
| Primary DB | MongoDB via Mongoose | ^7.6 | Server configs, invite records, user profiles |
| Cache / Rate-Limit | Redis via ioredis | ^5.3 | Sliding-window rate limiting |
| HTTP Client | axios | ^1.6 | AI API & Aladhan API calls |
| Scheduler | node-cron | ^3.0 | Nightly archival & maintenance tasks |
| Dev Compiler | ts-node | ^10.9 | Run TypeScript directly in development |
| Env Config | dotenv | ^16.3 | Load .env variables at runtime |
Core Architecture
The codebase is split into clearly-separated concerns. Understanding this layout is essential before you start modifying or extending the bot.
digital-akhi-bot/
├── index.ts # Bootstrap — creates Client, loads commands, connects DB
├── commands/ # Slash command definitions (auto-loaded at startup)
│ ├── config.ts # Guild admin configuration
│ ├── dua.ts # Contextual supplication retrieval
│ ├── hadith.ts # Verified hadith search
│ ├── prayer.ts # Prayer time lookup via Aladhan API
│ ├── profile.ts # User tier & rate-limit status
│ └── setkey.ts # BYOK API key registration
├── events/ # discord.js Gateway event handlers
│ ├── messageCreate.ts # AI conversation & command routing
│ ├── interactionCreate.ts # Slash command dispatcher
│ ├── guildMemberAdd.ts # Welcome + invite tracking
│ ├── guildMemberRemove.ts # Invite tracker cleanup
│ └── guildUpdate.ts # Boost-level tier upgrades
├── services/ # Stateless background services
│ ├── AIService.ts # Multi-provider failover AI client
│ ├── EncryptionService.ts # AES-256-CBC encrypt/decrypt helpers
│ ├── KeyRingService.ts # Per-user BYOK credential store
│ ├── MaintenanceService.ts # Cron-driven nightly archival
│ ├── SkillLearningService.ts # Dynamic skill loader
│ ├── TaskWorker.ts # Heavy-task queue (ban, kick, etc.)
│ └── TierService.ts # Invite/boost tier resolver
├── models/ # Mongoose schemas (DB shapes)
├── skills/ # Dynamic skill JSON definitions
├── website/ # Static frontend (this documentation)
├── .env.example # Template for environment variables
├── tsconfig.json # TypeScript compiler options
└── package.json # npm scripts & dependency manifest
Service Overview
AIService.ts
Manages a prioritised list of AI providers. On each request it tries providers in order; if one returns an error or rate-limit response, it seamlessly retries the next provider within the same response cycle.
KeyRingService.ts
Reads and writes per-user BYOK credentials from MongoDB. Wraps EncryptionService so keys are never stored in plaintext. Exposes getKey(userId) and setKey(userId, provider, key).
EncryptionService.ts
Thin wrapper around Node.js's built-in crypto module. Implements AES-256-CBC encrypt/decrypt using the ENCRYPTION_KEY environment variable as the symmetric key.
TierService.ts
Resolves a guild member's access tier by querying their invite count and checking whether they have an active server boost. Returns "free" or "premium" and the corresponding rate-limit quota.
MaintenanceService.ts
Registers a node-cron job that runs nightly. Compresses interaction logs older than 30 days with zlib and moves them to a cold-storage collection, keeping MongoDB lean.
TaskWorker.ts
Intercepts AI responses that contain isHeavyTask: true markers (ban, kick, role changes). Executes the moderation action after re-verifying that the calling user holds the appropriate Discord permissions.
Prerequisite — Node.js & TypeScript
You need Node.js v18 or higher. The bot uses ESM ("type": "module" in package.json) and optional chaining features that require a modern Node version.
Check your current version
node --version # must be >= v18.0.0
npm --version # must be >= 8.0.0
Installing Node.js (if not installed)
The recommended way is via the official installer or a version manager:
- Windows / macOS — Download the LTS installer from nodejs.org.
- Linux (via nvm) — Use the Node Version Manager for clean version control:
# Install nvm
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
# Restart your shell, then:
nvm install --lts
nvm use --lts
Verifying TypeScript
TypeScript is bundled as a dev dependency and does not need to be installed globally. However, if you want to run tsc from your terminal directly:
npm install -g typescript
tsc --version # Should print 5.x.x
Note: The npm start script uses ts-node which compiles and runs TypeScript on-the-fly without a separate build step — ideal for development.
Prerequisite — Creating a Discord Application
Before running the bot, you need to create a Discord Application in the Developer Portal and obtain a bot token, application client ID, and invite URL.
-
1
Go to discord.com/developers/applications and sign in with your Discord account.
-
2
Click "New Application" in the top-right corner. Give it a memorable name (e.g., Islamic Bot) and click Create.
-
3
On the General Information page, copy the Application ID. This is your
CLIENT_IDenvironment variable. -
4
Navigate to Bot in the left sidebar. Click "Add a Bot" → "Yes, do it!". Then click "Reset Token" and copy the token. This is your
DISCORD_TOKEN. Never share this token. -
5
Scroll down the Bot page and enable these Privileged Gateway Intents:
- Server Members Intent — required for invite tracking and tier upgrades.
- Message Content Intent — required for the AI to read message text.
-
6
Navigate to OAuth2 → URL Generator. Select Scopes:
botandapplications.commands. Under Bot Permissions select:Administrator(or at minimum: Send Messages, Read Message History, Manage Roles, Kick Members, Ban Members, Manage Guild, View Channels). Copy the generated URL and open it to invite the bot to your server. -
7
Create a dedicated text channel in your server for security alerts. Copy the Channel ID (right-click the channel → Copy Channel ID with Developer Mode enabled). This becomes
SECURITY_ALERT_CHANNEL_ID. -
8
Copy your Server (Guild) ID (right-click the server icon → Copy Server ID). This is
SUPPORT_SERVER_ID— used to restrict certain admin commands to your support guild only.
⚠️ Never commit your DISCORD_TOKEN to version control. If you accidentally expose it, immediately go back to the Bot page and click Reset Token.
Prerequisite — MongoDB Setup
The bot uses MongoDB to persist server configurations, invite records, user profiles, BYOK credentials, and rate-limit data. You can run it locally or use the free MongoDB Atlas cloud service.
Option A — Local MongoDB (Development)
# macOS (Homebrew)
brew tap mongodb/brew
brew install mongodb-community@7.0
brew services start mongodb-community@7.0
# Ubuntu / Debian
curl -fsSL https://www.mongodb.org/static/pgp/server-7.0.asc | sudo gpg -o /usr/share/keyrings/mongodb-server-7.0.gpg --dearmor
echo "deb [ arch=amd64,arm64 signed-by=/usr/share/keyrings/mongodb-server-7.0.gpg ] https://repo.mongodb.org/apt/ubuntu jammy/mongodb-org/7.0 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-7.0.list
sudo apt-get update && sudo apt-get install -y mongodb-org
sudo systemctl start mongod
# Windows
# Download installer from https://www.mongodb.com/try/download/community
Once running, your connection string is:
MONGODB_URI=mongodb://localhost:27017/islamic-bot
Option B — MongoDB Atlas (Production Recommended)
- 1Go to cloud.mongodb.com and create a free account.
- 2Create a new Project, then click Build a Database. Choose the Free (M0) shared cluster.
- 3Create a Database User with a strong password (not your login password). Keep note of username and password.
- 4Under Network Access, add IP
0.0.0.0/0(allows all) for a VPS, or your specific VPS IP for better security. - 5Click Connect → Drivers, select Node.js, and copy the connection string. Replace
<password>with your database user's password.
MONGODB_URI=mongodb+srv://username:password@cluster0.xxxxx.mongodb.net/islamic-bot?retryWrites=true&w=majority
Prerequisite — Redis Setup
Redis is used for the sliding-window rate limiter. Every command execution checks and increments a Redis key before hitting the AI APIs.
Option A — Local Redis (Development)
# macOS (Homebrew)
brew install redis
brew services start redis
# Ubuntu / Debian
sudo apt-get update && sudo apt-get install redis-server
sudo systemctl start redis-server
sudo systemctl enable redis-server
# Windows
# Use Redis for Windows from https://github.com/microsoftarchive/redis/releases
# Or run via Docker:
docker run -d -p 6379:6379 redis:alpine
Verify it's running:
redis-cli ping # Should respond: PONG
REDIS_URL=redis://localhost:6379
Option B — Redis Cloud (Production)
- 1Create a free account at redis.io/try-free.
- 2Create a new database and copy the Public endpoint and Password.
REDIS_URL=redis://:yourpassword@redis-12345.c1.us-east-1-2.ec2.cloud.redislabs.com:12345
Prerequisite — AI API Keys
The bot supports six AI providers through a multi-key rotation format. You only need at least one, but adding multiple providers activates the automatic failover system for maximum uptime. Keys are set as a comma-separated list in the API_KEYS variable.
API_KEYS=groq:gsk_...,gemini:AIza...,cerebras:csk_...
Extremely fast inference. Excellent primary choice. Free tier available with generous limits. Key prefix: gsk_
Google's Gemini models. Free tier via AI Studio. Key prefix: AIza
Ultra-fast chip-native inference. Free tier during beta. Key prefix: csk_
Hardware-accelerated inference. Free API tier. Good as a secondary failover option.
Unified API for 100+ models. Free models available. Also used for BYOK. Key prefix: sk-or-
Recommended minimum configuration: Add at least Groq + Gemini for production reliability. The failover triggers automatically when one provider returns a 429, 500, or network error.
Installation
Once all prerequisites are met, follow these steps to get the bot installed and running on your system.
Step 1 — Clone the Repository
git clone https://github.com/SEJED-DEV/digital-akhi-bot.git
cd digital-akhi-bot
Step 2 — Install npm Dependencies
npm install
This will install all runtime and dev dependencies listed in package.json including discord.js, mongoose, ioredis, ts-node, and more.
Step 3 — Create Your Environment File
cp .env.example .env
Open .env in your editor and fill in every variable. See the full Environment Variables reference below for descriptions of each field.
Step 4 — Verify Connections
Before deploying commands, confirm MongoDB and Redis are reachable. A quick sanity check:
# Test MongoDB connection (requires mongosh installed)
mongosh "$MONGODB_URI" --eval "db.runCommand({ping:1})"
# Test Redis
redis-cli -u "$REDIS_URL" ping
Environment Variables — Full Reference
All configuration is passed through environment variables loaded from your .env file via dotenv. Below is the complete reference table:
| Variable | Required | Default | Description |
|---|---|---|---|
DISCORD_TOKEN | ✅ Yes | — | Your bot's secret token from the Discord Developer Portal. Used to authenticate the WebSocket gateway connection. |
CLIENT_ID | ✅ Yes | — | Your application's Client / Application ID. Required by the deploy-commands.js script to register slash commands globally. |
SUPPORT_SERVER_ID | ✅ Yes | — | The Discord Guild ID of your support / admin server. Certain privilege-escalation commands are restricted to this guild only. |
SECURITY_ALERT_CHANNEL_ID | ✅ Yes | — | Channel ID where the bot posts security events (e.g., failed admin verification, suspected prompt injections). |
MONGODB_URI | ✅ Yes | mongodb://localhost:27017/islamic-bot |
Full MongoDB connection string. Supports both local instances and Atlas cloud clusters. |
REDIS_URL | ✅ Yes | redis://localhost:6379 |
Redis connection URL. Used by the sliding-window rate limiter. Supports password-protected and TLS connections. |
ENCRYPTION_KEY | ✅ Yes | — | A exactly 32 characters random string used as the AES-256 symmetric encryption key for BYOK API keys. Generate with: node -e "console.log(require('crypto').randomBytes(16).toString('hex'))" |
API_KEYS | ✅ Yes (min 1) | — | Comma-separated list of AI provider keys in provider:key format. Supported providers: groq, gemini, cerebras, sambanova, together, openrouter. Example: groq:gsk_abc,gemini:AIza_xyz |
NEXT_PUBLIC_SUPPORT_SERVER_INVITE | ❌ No | — | Invite link for your Cortex HQ / support Discord server. Embedded in bot error messages to direct users for help. |
Generating a Secure ENCRYPTION_KEY
# Option 1 — Node.js one-liner
node -e "console.log(require('crypto').randomBytes(16).toString('hex'))"
# Option 2 — OpenSSL
openssl rand -hex 16
# Option 3 — Python
python3 -c "import secrets; print(secrets.token_hex(16))"
⚠️ The output of the above commands is 32 hex characters = 16 bytes = 128-bit key. AES-256 requires a 32-byte key. The internal implementation interprets the 32-character hex string as a 32-byte buffer. Do not truncate or pad this value.
Deploying Slash Commands to Discord
Discord requires slash commands to be registered explicitly via the REST API before they appear in servers. This is a one-time action (or repeat it after adding new commands).
Step 1 — Build the TypeScript Source
npm run build
This runs tsc and compiles all .ts files in commands/, events/, and services/ into JavaScript in the dist/ directory.
Step 2 — Run the Deployment Script
node dist/deploy-commands.js
# or, using the npm alias:
npm run deploy
This registers all commands globally. Global registration can take up to 1 hour to propagate to all Discord servers. For instant updates during development, the script can be modified to target a specific Guild ID.
Re-run this script any time you add, rename, or modify a slash command's options. Discord will not automatically update the command schema — you must re-register.
Verifying Registration
After deployment, type / in any server where the bot is present. You should see all commands (hadith, dua, prayer, profile, setkey, config) appear in the autocomplete popup within 1 hour.
Running the Bot
Development Mode (ts-node, hot-friendly)
Runs TypeScript directly without a compile step. Best for active development:
npm start
# Equivalent to: ts-node index.ts
You should see output similar to:
Connected to MongoDB
Logged in as IslamicBot#1234!
Production Mode (compiled JavaScript)
For a VPS or cloud server, always run compiled code for better performance:
npm run build
node dist/index.js
Running as a Background Service (Linux — systemd)
Create a systemd service to keep the bot running after server reboots:
sudo nano /etc/systemd/system/islamicbot.service
[Unit]
Description=Islamic Community Discord Bot
After=network.target
[Service]
Type=simple
User=ubuntu
WorkingDirectory=/home/ubuntu/digital-akhi-bot
ExecStart=/usr/bin/node /home/ubuntu/digital-akhi-bot/dist/index.js
Restart=on-failure
RestartSec=10
EnvironmentFile=/home/ubuntu/digital-akhi-bot/.env
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable islamicbot
sudo systemctl start islamicbot
sudo systemctl status islamicbot # Check it's active (running)
Running with Docker (Optional)
# Build image
docker build -t islamic-bot .
# Run with environment file
docker run -d --name islamic-bot --env-file .env islamic-bot
Slash Command Reference
The following commands are registered by default. All commands respect the user's active access tier and rate-limit window.
/hadith
Retrieves a verified Hadith matching the user's query. Response includes the text, source collection, hadith number, and authenticity grading (Sahih, Hasan, Da'if, or Mawdu').
/dua
Returns a contextually appropriate supplication (Dua). The AI interprets the situation described by the user and selects the most relevant Du'a, with Arabic text, transliteration, and translation.
/prayer
Fetches the five daily prayer times for a specified city using the open Aladhan API. Times are calculated for the current day in the city's local timezone.
/profile
Displays the calling user's server profile: current access tier (Free/Premium), number of valid invites, current request usage and quota, and their tier unlock progress.
/setkey
Registers a personal BYOK API key. The key is encrypted at rest using AES-256-CBC before being stored in MongoDB. Once set, the bot uses this key for all of the user's requests.
/config
Server administrator command. Manage settings: welcome, automod, server stats, and shared BYOK. Requires Administrator permission.
/modstats
Displays moderation performance metrics and leaderboards. Tracks warnings, mutes, kicks, and bans globally per guild.
/lock /unlock
Emergency channel controls. Instantly freezes or restores messaging permissions for the @everyone role.
AutoMod System
The AutoModService provides proactive protection against common server threats. It can be configured via /config automod.
Available Modules
- Anti-Spam — Detects message bursts (default: 5 messages in 10s). Offenders are automatically timed out for 10 minutes.
- Anti-Raid — Monitors join velocity (default: 10 joins in 30s). Triggers an alert and can enable emergency lockdowns.
- Word Filter — Customizable list of forbidden words. Uses a normalization engine to detect leetspeak and unicode bypass attempts.
✅ **Normalization:** The filter automatically converts "5pam" to "spam" and ignores special characters to prevent easy bypasses.
Moderator Stats & Performance
Accountability is key to a healthy Ummah. The bot automatically tracks every formal moderation action taken through its commands.
Tracked Actions
- Warn — logged via
/warn. - Mute — logged via
/mute. - Kick/Ban — logged via
/kick,/ban, or AI-triggered heavy tasks.
Use /modstats to view the server leaderboard or /modstats @moderator for a detailed breakdown of a specific team member's performance.
Tier System
The bot operates on a two-tier access model resolved dynamically at the time of each request by TierService.ts:
| Tier | Requirement | Request Quota | Context Window | Support |
|---|---|---|---|---|
| Free | Default for all members | 20 requests / 6 hours | 4,000 words context | Community channels |
| Premium | 30 valid server invites or 2 active Nitro boosts | 50 requests / 6 hours | 32,000 words context | Priority support channel |
| SuperPremium | 50 valid server invites & Support server join | 100 requests / 6 hours | 128,000 words context | Direct developer support |
ℹ️ **BYOK Bonus:** Users who configure their own API key via `/setkey` bypass all rate limits entirely! Their request quota becomes unlimited.
How Tier Resolution Works
- On every command,
TierService.resolveUser(guildId, userId)is called. - It queries the invite tracking collection in MongoDB for the user's invite count.
- It queries the guild's boost count via the Discord API.
- If either threshold is met,
"premium"is returned with a 50-request quota; otherwise"free"with 20. - The quota is checked against the Redis sliding-window key
ratelimit:{userId}before processing the request.
Invite Tracking
The guildMemberAdd event captures who invited a new member by diffing the guild's invite list before and after the join. Invite counts are stored in MongoDB and updated in real-time. The guildMemberRemove event decrements the invite count if the member leaves within the tracking window to prevent gaming the system.
BYOK — Bring Your Own Key
BYOK lets individual users or server administrators bypass the bot's shared AI quota by registering their own API credentials. This is the most powerful feature for heavy users who need unrestricted access.
⚠️ **48-Hour Trial Policy:** New users can use the bot's default API for 48 hours. After this trial period, you MUST add your own API key using `/setkey` to continue using AI features.
How It Works — Step by Step
- 1User runs
/setkey provider: openrouter key: sk-or-xxxx. The key string is sent to the bot via Discord's encrypted interaction payload. - 2
KeyRingService.setKey(userId, provider, rawKey)callsEncryptionService.encrypt(rawKey). This generates a random IV, runs AES-256-CBC with yourENCRYPTION_KEY, and returns a Base64-encoded ciphertext string. - 3The ciphertext (never the plaintext) is written to MongoDB under the user's document. The original raw key is never logged or stored.
- 4On the user's next AI request,
KeyRingService.getKey(userId)is called. It reads the ciphertext from MongoDB, decrypts it in memory usingEncryptionService.decrypt(), and passes the plaintext key to the AI HTTP request. - 5After the HTTP call completes, the decrypted key goes out of scope and is garbage-collected. It is never written to disk, logs, or environment state.
- 6Users with a BYOK key active are exempt from the standard rate-limit quota — their key's own provider limits apply instead.
Removing a BYOK Key
Users can remove their stored key at any time using the command:
/removekey
This permanently deletes the encrypted credential document from MongoDB.
Security Model
The bot is designed with a zero-trust philosophy. Every request is verified independently regardless of who appears to be sending it.
Prompt Sandboxing
All user-provided text is wrapped in a triple-quoted sandboxing template before being forwarded to the AI provider. This prevents users from injecting instructions that try to override the bot's system prompt or extract internal configurations.
System: You are the Islamic Community Bot...
[INSTRUCTIONS]
...
[END INSTRUCTIONS]
User input: """
{user_message}
"""
The AI is instructed to only respond to content within the triple quotes as user context, never as additional instructions. Attempts to escape the sandbox are flagged and sent to the SECURITY_ALERT_CHANNEL_ID.
Heavy Task Interception (isHeavyTask)
When the AI determines a moderation action is warranted (ban, kick, role change), it returns a structured JSON response containing isHeavyTask: true and a payload describing the action. The TaskWorker service intercepts this, re-verifies the requesting user's Discord permissions independently via the Guild API, and only then executes the action. The AI itself cannot trigger moderation — it can only request it.
Admin Command Gating
The /config command and any sub-actions that modify guild settings require the caller to hold the Manage Guild or Administrator Discord permission. This is checked server-side via interaction.memberPermissions, not by the AI.
Support-Server Restriction
Certain developer and maintenance commands are restricted to the guild specified in SUPPORT_SERVER_ID. Attempts to call them from external servers silently fail.
Data Lifecycle & Archival
The MaintenanceService registers a node-cron job that runs once every 24 hours (typically at 02:00 UTC). On each run it:
- Queries the
interaction_logsMongoDB collection for documents older than 30 days. - Serialises each document to JSON, compresses it with Node.js's built-in
zlib.gzip(), and writes the compressed buffer to thecold_storagecollection as a Binary field. - Deletes the original documents from
interaction_logs.
This keeps the hot MongoDB collection small and query-efficient while preserving a compressed historical archive. Cold storage documents can be decompressed on demand with zlib.gunzip().
ℹ️ If you are self-hosting, you may wish to schedule your own MongoDB Atlas backups separately. The built-in archival is for query performance, not a full backup solution.
Contribution Guide
We actively welcome contributions — bug fixes, new commands, performance improvements, and documentation updates are all appreciated.
Setting Up the Development Environment
# 1. Fork the repository on GitHub, then clone your fork:
git clone https://github.com/YOUR_USERNAME/digital-akhi-bot.git
cd digital-akhi-bot
# 2. Add the upstream remote so you can stay up to date:
git remote add upstream https://github.com/SEJED-DEV/digital-akhi-bot.git
# 3. Install dependencies and set up your .env:
npm install
cp .env.example .env
# Fill in .env values...
# 4. Create a feature branch (never commit directly to main):
git checkout -b feature/your-feature-name
Code Style
- All source files use TypeScript. No plain
.jsfiles incommands/,events/, orservices/. - Use ESM imports (
import/export) — norequire(). - Export a named
data(SlashCommandBuilder) andexecutefunction from every command file so the auto-loader can pick it up. - Keep functions small and single-purpose. Extract repeated logic into
services/.
Pull Request Checklist
- ✅ Code compiles without errors (
npm run build). - ✅ Bot starts without errors (
npm start). - ✅ The new feature/fix is documented in the PR description.
- ✅ Any new environment variables are added to
.env.example. - ✅ PR targets the
mainbranch.
# After making your changes, push and open a PR:
git add .
git commit -m "feat: describe your change clearly"
git push origin feature/your-feature-name
Then open a Pull Request on GitHub from your fork's branch to SEJED-DEV/digital-akhi-bot:main.
Adding a New Slash Command
The command loader in index.ts automatically discovers any .ts or .js file in the commands/ directory that exports both a data property and an execute function. Adding a new command is as simple as creating one file.
Template
// commands/mycommand.ts
import { SlashCommandBuilder, ChatInputCommandInteraction } from 'discord.js';
export const data = new SlashCommandBuilder()
.setName('mycommand')
.setDescription('Brief description of what your command does')
.addStringOption(option =>
option
.setName('input')
.setDescription('The user input for your command')
.setRequired(true)
);
export async function execute(interaction: ChatInputCommandInteraction) {
await interaction.deferReply();
const input = interaction.options.getString('input', true);
// Your command logic here...
const result = `You said: ${input}`;
await interaction.editReply({ content: result });
}
After Creating Your Command File
# 1. Rebuild to compile the new file
npm run build
# 2. Re-register slash commands with Discord
npm run deploy
# 3. Restart the bot
npm start
Note: Use deferReply() for any command that makes network calls. Discord requires a response within 3 seconds; deferReply() extends this to 15 minutes while you fetch data.
Troubleshooting
Bot fails to start: "Used disallowed intents"
Cause: The bot requests GuildMembers or MessageContent intents but they are not enabled in the Developer Portal.
Fix: Go to discord.com/developers/applications → Your App → Bot → Privileged Gateway Intents → enable Server Members Intent and Message Content Intent.
Bot starts but slash commands don't appear
Cause: Commands have not been registered yet, or Discord's global propagation delay (up to 1 hour) has not completed.
Fix: Run npm run build && npm run deploy. Wait up to 60 minutes. For instant testing, modify deploy-commands.js to register to a specific Guild ID using rest.put(Routes.applicationGuildCommands(clientId, guildId), ...).
MongooseServerSelectionError: connection refused
Cause: MongoDB is not running or MONGODB_URI is incorrect.
Fix: Start MongoDB locally (brew services start mongodb-community / sudo systemctl start mongod), or verify your Atlas connection string and IP whitelist.
AI requests return "No available providers"
Cause: All keys in API_KEYS are invalid or exhausted.
Fix: Check the API_KEYS format (provider:key,provider:key). Verify each key is valid by testing it directly with the provider's API playground. Add a backup provider.
BYOK key returns "Decryption failed"
Cause: The ENCRYPTION_KEY in your .env was changed after a key was stored, making existing ciphertext undecryptable.
Fix: Never change ENCRYPTION_KEY after keys are stored. If you must change it, have all users re-run /setkey to re-encrypt their credentials with the new key.
Rate limit errors: user gets "You have reached your limit"
Cause: Expected behaviour — the user's 6-hour sliding window is exhausted.
Fix for users: Wait for the window to reset, gain Premium tier (30 invites / 2 boosts), or register a BYOK key with /setkey.
Fix for self-hosters: Adjust the quota constants in services/TierService.ts to suit your server's usage patterns.
TypeScript compile errors after pulling updates
npm install # Install any new dependencies
npm run build # Recompile
Redis connection refused
# Check Redis is running
redis-cli ping # Should return PONG
# If not running:
sudo systemctl start redis-server # Linux
brew services start redis # macOS
Frequently Asked Questions
General
Is this bot free to use?
Yes. The bot itself is 100% free and open-source (AGPL-3.0 License). You can self-host it at no cost beyond your server's infrastructure costs (a small VPS typically costs $4–6/month). The AI providers also have free tiers — Groq and Cerebras both offer generous free limits that comfortably cover a medium-sized Discord server.
Can I use this bot on multiple servers?
Yes. A single bot instance can serve multiple Discord guilds simultaneously. Each guild has its own configuration stored in MongoDB. There is no hard limit on the number of guilds; the limiting factor is your server's CPU, RAM, and AI API quota.
What happens if all my AI providers are down?
The AIService cycles through all configured providers. If every provider returns an error, the bot responds with a graceful "Service temporarily unavailable" message in Discord rather than crashing. The bot itself remains online — only the AI-powered responses are affected. Non-AI commands like /prayer continue to work normally as they use the Aladhan API directly.
Can the bot ban/kick members?
Only in a tightly controlled way. The AI can suggest a moderation action, which is represented as a structured JSON payload with isHeavyTask: true. Before any action is taken, TaskWorker.ts independently verifies that (a) the requesting user actually holds the required Discord permissions, and (b) the target user is not protected (e.g., has a higher role). The AI cannot independently trigger moderation — it can only request it, and the request is always verified by code, not by the AI itself.
Does the bot store my messages?
Interaction logs (which may include message content) are stored in "hot" MongoDB storage for up to 30 days for the purposes of rate-limit tracking and service quality improvement. After 30 days, logs are zlib-compressed and moved to cold storage. They are never sold or shared with third parties. Users may request deletion at any time via the support server. See the full Privacy Policy for details.
Self-Hosting
Do I need Redis? Can I skip it?
Redis is required for the sliding-window rate limiter. If you skip it, the rate-limiting logic will throw errors and the bot will not start correctly. If you are running a very small private server and want to simplify the setup, you could replace the Redis rate limiter with an in-memory Map — but this is not recommended for production because in-memory rate limits reset every time the bot restarts.
How much RAM does the bot need?
A baseline Node.js process with all services loaded typically uses 100–200 MB of RAM at idle. Under active load (many concurrent AI requests), it may peak at 400–600 MB. A VPS with 1 GB RAM is sufficient for a small-to-medium sized community. For large communities (10,000+ members), 2 GB RAM is recommended.
Can I change the AI system prompt?
Yes. The system prompt is constructed inside services/AIService.ts. You can edit the prompt template to customize the bot's persona, language style, and knowledge boundaries. Be careful not to remove the triple-quote sandboxing wrappers around user input — those are a core security control.
Can I disable the invite tier system?
Yes. In services/TierService.ts, change the resolveUser function to always return "premium" (to give all users premium access) or set the invite threshold to 0. Alternatively, set the rate-limit quota to a very high number to effectively disable it.
What if I want to deploy the website separately?
The website/ folder contains pure static HTML/CSS. It can be deployed to any static host: Vercel, Netlify, GitHub Pages, or Cloudflare Pages — all for free. Simply point the hosting service at the website/ directory. No build step is required.
Security
How secure is the BYOK key storage?
Keys are encrypted with AES-256-CBC using a random IV for each encryption operation. This means even two identical keys produce different ciphertexts, preventing ciphertext comparison attacks. The encryption key itself (ENCRYPTION_KEY) only exists in your .env file and is never stored in the database. The threat model assumes MongoDB access does not constitute a full compromise — an attacker who obtains the database dump but not the ENCRYPTION_KEY cannot recover the API keys.
What happens if my Discord token leaks?
Immediately go to the Discord Developer Portal, navigate to your application's Bot page, and click Reset Token. Update the new token in your .env file and restart the bot. The leaked token is immediately invalidated by Discord upon reset. Also check your repository's git history to ensure the token was never committed — if it was, contact Discord support.
Can users bypass the prompt sandbox?
The triple-quote sandboxing significantly raises the bar for prompt injection. Attempts to break out (e.g., closing the triple quotes, injection via Unicode lookalikes) are mitigated by the fact that the entire message is treated as literal user context. Suspicious patterns are logged to your security alert channel. No sandbox is 100% perfect against a sufficiently determined attacker, but this implementation follows industry best practices for conversational AI safety.
License
The Islamic Community Bot is released under the AGPL-3.0 License.
GNU AGPLv3 License
Copyright (c) 2026 Sejed TRABELSSI
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see .
In plain terms: you are free to use, modify, and distribute this project for any purpose — commercial or non-commercial — as long as you retain the copyright notice and license. If you modify the software and make it available to others over a network, you must also make the source code of your modified version available under the same license.