A high-performance Discord bot that scrapes Pepper.pl for deals, provides automated notifications, and allows users to set up custom price alerts. Built for speed and reliability using asynchronous Python.
This bot serves as a bridge between the Pepper.pl deal platform and Discord. It bypasses the need for RSS feeds by directly scraping the website using optimized HTML parsing. It supports on-demand searching, personal keyword alerts (sent via DM), and automated channel feeds for specific categories (e.g., "GPU < 3000 PLN").
- Deal Searching: Query Pepper.pl directly from Discord (
/pepper [query],/pepperhot). - Personal Alerts (PepperWatch): Users can subscribe to keywords (e.g., "RTX 4070") with optional price caps. The bot checks every 15 minutes and DMs matches.
- Automated Categories: Server admins can set up dedicated channels for specific deal categories (e.g., "gaming", "home-automation") with customizable schedules and filters.
- Flight Deal Digest: Daily automated report of flight deals.
- High-Performance Scraping: Uses
selectolax(C-based HTML parser) and Vue.js hydration data for fast, reliable extraction. - Duplicate Protection: Tracks sent deals in SQLite to prevent spamming the same offer twice.
- Language: Python 3.10+
- Framework: discord.py (Asynchronous interaction-based bot)
- Scraping: selectolax (Ultra-fast HTML parsing),
aiohttp(Async HTTP requests) - Database:
aiosqlite(Async SQLite3 for lightweight, file-based persistence) - Configuration:
python-dotenv
- Python 3.10 or higher
- A Discord Bot Token (from Discord Developer Portal)
- uv (Recommended for 10-100x faster dependency resolution)
-
Clone the repository:
git clone https://github.com/Kehlanii/PepperPLDiscord.git cd PepperPLDiscord -
Fast Setup (Recommended with
uv):# Create venv and install dependencies in one go (extremely fast) uv venv source .venv/bin/activate # or .venv\Scripts\activate on Windows uv pip install -r requirements.txt
Alternative (Traditional pip):
python3 -m venv venv source venv/bin/activate pip install -r requirements.txt -
Configuration: Create a
.envfile in the root directory:touch .env
Add your bot token:
DISCORD_BOT_TOKEN=your_token_here
-
Run the bot:
python bot.py
The bot supports both Slash Commands (modern) and Text Commands (classic, faster).
| Category | Slash Command | Text Command | Example |
|---|---|---|---|
| Alerts | /pepperwatch add |
p watch:query < price |
p watch:Rzym < 600 |
/pepperwatch list |
p alerts or p list |
p alerts |
|
/pepperwatch remove |
p unwatch:query |
p unwatch:Rzym |
|
| Search | /pepper query |
p query |
p rtx 4070 |
/pepperhot |
p hot |
p hot |
|
/pepper_group slug |
p group:slug |
p group:elektronika |
|
| Categories | /category preview |
p preview:slug |
p preview:lego |
/category list |
p cat list |
p cat list |
|
/category add |
p cat add:slug ... |
p cat add:gry daily 09:00 #deals |
|
/category remove |
p cat rm:slug |
p cat rm:gry |
|
/category pause |
p cat pause:slug |
p cat pause:gry |
|
/category resume |
p cat resume:slug |
p cat resume:gry |
|
/category trigger |
p cat run:slug |
p cat run:gry |
|
| Utility | /pepperclean |
p clean [limit] |
p clean 50 |
/flynow |
p fly |
p fly |
| Command | Description | Permissions |
|---|---|---|
/pepper [query] |
Search for deals matching a keyword. | Everyone |
/pepperhot |
Fetch the current hottest deals from the homepage. | Everyone |
/pepper_group [slug] |
Get deals from a specific category (e.g., gry, elektronika). |
Everyone |
/pepperwatch add [query] [max_price] |
Add a personal alert. DMs you when found. | Everyone |
/pepperwatch list |
View your active personal alerts. | Everyone |
/pepperwatch remove [query] |
Remove a personal alert. | Everyone |
/category add [slug] ... |
Setup an automated feed for a category into a channel. | Admin |
/category list |
List all active category feeds on the server. | Everyone |
/category pause/resume |
Temporarily stop/start a category feed. | Admin |
/flynow |
Manually trigger the flight deal report. | Admin |
The bot is structured around a central asynchronous loop with several key components:
Instead of using heavy browser automation (Selenium/Playwright) or slow parsers (BeautifulSoup), this bot uses selectolax.
- Strategy: It attempts to locate the Vue.js hydration data (
data-vue3attribute) injected into the HTML. This contains raw JSON data, which is faster and more reliable to parse than DOM elements. - Fallback: If Vue data is missing, it falls back to CSS selectors to scrape the rendered HTML.
Uses SQLite for persistence. Key tables:
sent_deals: Tracks IDs of deals already posted to prevent duplicates.alerts: Stores user-defined keywords and price limits.alert_history: Prevents a user from being alerted twice for the same deal.category_configs: Stores settings for server-wide automated feeds.
The bot runs background tasks using discord.ext.tasks:
- Alerts Task: Runs every 15 mins. Scrapes search results for every user query and DMs matches.
- Category Task: Runs every minute. Checks if any configured category needs to be scraped based on its schedule (Daily/Weekly/etc).
- Flight Task: Runs daily at 08:00 AM (configurable).
Core settings are defined in utils/config.py.
FLIGHT_SCHEDULE_HOUR: Hour to send flight reports (Default: 8).WATCH_INTERVAL_MINUTES: Frequency of checking user alerts (Default: 15).DEFAULT_SEARCH_LIMIT: Number of results to show in search (Default: 7).
For production, it is recommended to run the bot as a systemd service.
-
Create service file:
/etc/systemd/system/pepperbot.service[Unit] Description=Pepper.pl Discord Bot After=network.target [Service] Type=simple User=your_user WorkingDirectory=/path/to/PepperPLDiscord ExecStart=/path/to/PepperPLDiscord/venv/bin/python bot.py Restart=always RestartSec=10 [Install] WantedBy=multi-user.target
-
Enable and start:
sudo systemctl enable pepperbot sudo systemctl start pepperbot
- Rate Limiting: Aggressive scraping may trigger Cloudflare protection or IP bans from Pepper.pl. The scraper includes basic delays and user-agent rotation logic, but use reasonable intervals.
- Hardcoded Flight Channel: The flight deal channel ID is currently hardcoded in
Config.FLIGHT_CHANNEL_ID. This needs to be changed in code before deployment.