A Discord bot that sends daily Islamic hadiths and the 99 beautiful names of Allah to configured Discord channels. The bot automatically sends messages at 6:00 PM Toronto time and provides slash commands for interactive hadith and name retrieval.
- Daily Automated Messages: Sends hadiths and Allah's names daily at 6:00 PM Toronto time
- Supabase Database: Stores hadith data and tracks channel states using Supabase
- Slash Commands: Interactive commands for retrieving specific or random hadiths and names
- Multi-Channel Support: Can be configured to send messages to multiple Discord channels
- State Persistence: Tracks progress through hadiths and names for each channel
- Error Handling: Comprehensive logging and error recovery mechanisms
- Discord Bot (
bot.py): Main bot logic with slash commands and scheduled tasks - Database Layer (
db.py): Supabase integration for data storage and retrieval - Utilities (
utils.py): Data models and message formatting functions - Web Server (
server.py): Flask server for health checks and bot hosting - Data Files: Local JSON files containing the 99 names of Allah
bot.py- Main Discord bot applicationserver.py- Flask web server for hosting and health checksdb.py- Database operations and Supabase integrationutils.py- Data models and utility functionstest_setup.py- Setup verification scriptpyproject.toml/uv.lock- Dependencies and lockfile (managed with uv)Makefile- Common dev tasks (make dev/test/lint).env.example- Environment variables templateDockerfile- Container configurationdocker-compose.yml- Multi-container orchestrationProcfile- Heroku deployment configurationdata/99names.json- The 99 beautiful names of Allah
- Python 3.11+
- Discord Bot Token
- Supabase Account and Project
- uv (Python package/dependency manager)
git clone https://github.com/SaiyedRushan/HadithBot.git
cd HadithBotThis project uses uv. With uv installed:
uv syncThis creates a .venv with all dependencies (runtime + dev) from uv.lock.
Run commands with uv run ..., or use the Makefile shortcuts:
make dev # run the bot with autoreload on save
make test # run tests
make lint # static checks (undefined names, bad imports)Create a .env file in the project root:
# Discord Bot Configuration
DISCORD_TOKEN=your_discord_bot_token_here
# Supabase Configuration
SUPABASE_URL=your_supabase_project_url
SUPABASE_KEY=your_supabase_anon_key- Go to Discord Developer Portal
- Create a new application and bot
- Copy the bot token to your
.envfile - Enable the following bot permissions:
- Send Messages
- Use Slash Commands
- Read Message History
- Invite the bot to your Discord server with these permissions
- Create a new project at Supabase
- Set up the following tables in your Supabase database:
CREATE TABLE discord_channel_state (
channel_id TEXT PRIMARY KEY,
channel_name TEXT,
guild_id TEXT,
guild_name TEXT,
last_hadith_no INTEGER NOT NULL DEFAULT 1,
last_name_no INTEGER NOT NULL DEFAULT 1,
last_book_id INTEGER NOT NULL DEFAULT 1,
last_chapter_id INTEGER NOT NULL DEFAULT 1,
active BOOLEAN NOT NULL DEFAULT TRUE,
hadiths_per_day INTEGER NOT NULL DEFAULT 3,
names_per_day INTEGER NOT NULL DEFAULT 3,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);channel_name, guild_name, and guild_id are stored purely for readability
(so you can tell rows apart in the Supabase dashboard) — the bot keys everything
off channel_id. They're refreshed on every save, so renames stay in sync.
CREATE TABLE hadiths (
id SERIAL PRIMARY KEY,
id_in_book INTEGER NOT NULL,
book_id INTEGER NOT NULL,
chapter_id INTEGER NOT NULL,
english_narrator TEXT,
english_text TEXT NOT NULL,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);CREATE TABLE chapters (
id SERIAL PRIMARY KEY,
english TEXT NOT NULL,
arabic TEXT,
book_id INTEGER NOT NULL
);CREATE TABLE books_metadata (
id SERIAL PRIMARY KEY,
english_title TEXT NOT NULL,
arabic_title TEXT
);- Copy your Supabase URL and anon key to the
.envfile
Run the setup test script to verify everything is configured correctly:
python test_setup.pyThis script will check:
- Python version compatibility
- Required dependencies installation
- Environment variables configuration
- Data files existence
- Database connectivity
- Data loading functionality
python bot.pypython server.pyThis starts both the Discord bot and a Flask web server on port 8080 for health checks.
Once the bot is running and added to your Discord server, you can test it using these slash commands:
/bismillah setup channel_id:<channel_id> start_book_id:1 start_chapter_id:1 start_hadith_id:1 start_name:1
Sets up daily messages for a specific channel.
/bismillah random
/bismillah specific book_no:1 chapter_no:1 hadith_no:1
/bismillah random_name
/bismillah specific_name number:1
/bismillah specific_names number:1
/bismillah stop channel_id:<channel_id>
Stops daily messages for a specific channel.
To test the daily message functionality without waiting for 6:00 PM:
- Temporarily modify the schedule in
bot.py:
# Change this line (around line 73):
@tasks.loop(time=time(hour=18, tzinfo=ZoneInfo("America/Toronto")))
# To this for testing (runs every 10 seconds):
@tasks.loop(seconds=10)- Restart the bot and observe the messages being sent every 10 seconds
- Remember to revert this change before deploying to production
Create test files to verify functionality:
# Test database connections
python -c "from db import get_channels; print('Database connection successful:', get_channels())"
# Test data loading
python -c "from utils import *; import json; print('Data files loaded successfully')"Ensure these environment variables are set in your production environment:
DISCORD_TOKEN=your_production_discord_bot_token
SUPABASE_URL=your_production_supabase_url
SUPABASE_KEY=your_production_supabase_key- Install dependencies:
uv sync --frozen --no-dev- Run with Gunicorn:
uv run gunicorn -w 1 -b 0.0.0.0:8080 server:app- Set up process manager (systemd, supervisor, etc.):
# /etc/systemd/system/hadithbot.service
[Unit]
Description=HadithBot Discord Bot
After=network.target
[Service]
Type=simple
User=your_user
WorkingDirectory=/path/to/HadithBot
Environment=PATH=/path/to/HadithBot/.venv/bin
ExecStart=/path/to/HadithBot/.venv/bin/gunicorn -w 1 -b 0.0.0.0:8080 server:app
Restart=always
[Install]
WantedBy=multi-user.targetUsing Docker Compose (Recommended):
# Copy environment file
cp .env.example .env
# Edit .env with your actual values
# Build and run
docker-compose up -d
# View logs
docker-compose logs -f
# Stop
docker-compose downUsing Docker directly:
# Build the image
docker build -t hadithbot .
# Run the container
docker run -d \
--name hadithbot \
-p 8080:8080 \
--env-file .env \
-v $(pwd)/data:/app/data:ro \
hadithbot
# View logs
docker logs -f hadithbotThe project includes a Dockerfile and docker-compose.yml for easy containerized deployment.
Heroku:
The project includes a Procfile for Heroku deployment.
- Deploy:
heroku create your-hadithbot-app
heroku config:set DISCORD_TOKEN=your_token
heroku config:set SUPABASE_URL=your_url
heroku config:set SUPABASE_KEY=your_key
git push heroku mainRailway/Render: Similar process with their respective deployment methods.
The Flask server provides a health check endpoint:
GET http://your-domain:8080/
Response: "Hello. I am alive!"
The bot includes comprehensive logging. Monitor logs for:
- Daily message delivery status
- Database connection issues
- Discord API errors
- Command execution errors
Monitor your Supabase dashboard for:
- API usage
- Database performance
- Error rates
The bot automatically handles daily message scheduling using Discord.py's task loops. No external cron jobs are required.
Daily Schedule: 6:00 PM Toronto Time (America/Toronto timezone)
- Single Instance: The current architecture is designed for single-instance deployment
- Database: Supabase handles scaling automatically
- Rate Limits: Discord API rate limits are handled by the discord.py library
- Memory Usage: Minimal - only loads the 99 names JSON file into memory
-
Bot not responding to commands:
- Verify bot permissions in Discord server
- Check if commands are synced (
await self.tree.sync()in setup_hook) - Ensure bot token is correct
-
Database connection errors:
- Verify Supabase URL and key
- Check Supabase project status
- Ensure tables exist with correct schema
-
Daily messages not sending:
- Check timezone configuration
- Verify channel IDs in database
- Review bot permissions in target channels
-
Import errors:
- Ensure all dependencies are installed
- Check Python version (3.11+ required)
- Verify data files exist in
data/directory
Enable debug logging by modifying the logging level in bot.py:
logging.basicConfig(level=logging.DEBUG)- Fork the repository
- Create a feature branch
- Make your changes
- Test thoroughly
- Submit a pull request
This project is open source. Please ensure compliance with Discord's Terms of Service and API guidelines when using this bot.