Bot now supports sending updates to multiple Discord channels simultaneously. Changes: - CHANNEL_ID accepts comma-separated list of channel IDs - Config parses and validates multiple channel IDs - Hourly and market close updates sent to all configured channels - Update .env.example to show multi-channel format - Document multi-channel configuration in README Example: CHANNEL_ID=1442203998932304035,9876543210123456789 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
228 lines
7.0 KiB
Markdown
228 lines
7.0 KiB
Markdown
# Discord Stock Bot
|
|
|
|
A Discord bot that automatically posts hourly stock price updates for PayPal (PYPL) during NYSE market hours. The bot also supports manual queries for any stock ticker via prefix commands.
|
|
|
|
## Features
|
|
|
|
- **Hourly automated updates**: Posts PayPal stock price every hour during market hours (9:30 AM - 4:00 PM ET, Monday-Friday)
|
|
- **Market hours awareness**: Automatically skips updates when NYSE is closed (weekends and holidays)
|
|
- **Manual stock queries**: Query any stock ticker using `!stock TICKER` or `!price TICKER`
|
|
- **Rich embeds**: Color-coded Discord embeds with price changes and market status
|
|
- **API agnostic design**: Abstract stock API layer allows easy switching between data providers
|
|
- **Docker containerized**: Consistent deployment across local and production environments
|
|
|
|
## Commands
|
|
|
|
- `!stock <TICKER>` or `!price <TICKER>` - Get current stock price for any ticker
|
|
- `!market` - Check if NYSE is currently open and view trading hours
|
|
- `!ping` - Check bot responsiveness and latency
|
|
|
|
## Project Structure
|
|
|
|
```
|
|
discord-stock-bot/
|
|
├── bot.py # Main bot application
|
|
├── config.py # Configuration management
|
|
├── market_hours.py # NYSE market hours detection
|
|
├── stock_api/
|
|
│ ├── __init__.py
|
|
│ ├── base.py # Abstract base class for stock APIs
|
|
│ └── yahoo.py # Yahoo Finance implementation
|
|
├── requirements.txt # Python dependencies
|
|
├── Dockerfile # Container definition
|
|
├── docker-compose.yml # Docker Compose configuration
|
|
└── .env # Environment variables (create from .env.example)
|
|
```
|
|
|
|
## Setup Instructions
|
|
|
|
### Prerequisites
|
|
|
|
- Python 3.11+ (for local development)
|
|
- Docker and Docker Compose (for containerized deployment)
|
|
- Discord Bot Token ([Create one here](https://discord.com/developers/applications))
|
|
- Discord Channel ID ([How to get Channel ID](https://support.discord.com/hc/en-us/articles/206346498-Where-can-I-find-my-User-Server-Message-ID))
|
|
|
|
### 1. Create Discord Bot
|
|
|
|
1. Go to [Discord Developer Portal](https://discord.com/developers/applications)
|
|
2. Click "New Application" and give it a name
|
|
3. Navigate to "Bot" section and click "Add Bot"
|
|
4. Under "Privileged Gateway Intents", enable:
|
|
- Message Content Intent
|
|
5. Copy the bot token (you will need this for `.env` file)
|
|
6. Navigate to "OAuth2" > "URL Generator"
|
|
7. Select scopes: `bot`
|
|
8. Select bot permissions: `Send Messages`, `Embed Links`, `Read Messages/View Channels`
|
|
9. Copy the generated URL and use it to invite the bot to your server
|
|
|
|
### 2. Get Channel ID
|
|
|
|
1. Enable Developer Mode in Discord (User Settings > Advanced > Developer Mode)
|
|
2. Right-click the channel where you want price updates
|
|
3. Click "Copy Channel ID"
|
|
|
|
### 3. Configure Environment
|
|
|
|
```bash
|
|
# Navigate to project directory
|
|
cd discord-stock-bot
|
|
|
|
# Copy example environment file
|
|
cp .env.example .env
|
|
|
|
# Edit .env with your values
|
|
# DISCORD_TOKEN=your_actual_bot_token
|
|
# CHANNEL_ID=your_actual_channel_id
|
|
```
|
|
|
|
### 4. Run Locally with Docker
|
|
|
|
```bash
|
|
# Build and start the container
|
|
docker compose up --build
|
|
|
|
# Run in detached mode (background)
|
|
docker compose up -d
|
|
|
|
# View logs
|
|
docker compose logs -f
|
|
|
|
# Stop the bot
|
|
docker compose down
|
|
```
|
|
|
|
### 5. Run Locally without Docker (Development)
|
|
|
|
```bash
|
|
# Create virtual environment
|
|
python -m venv venv
|
|
source venv/bin/activate # On Windows: venv\Scripts\activate
|
|
|
|
# Install dependencies
|
|
pip install -r requirements.txt
|
|
|
|
# Run the bot
|
|
python bot.py
|
|
```
|
|
|
|
## Deployment to Unraid
|
|
|
|
### Method 1: Docker Compose (Recommended)
|
|
|
|
1. Copy the entire `discord-stock-bot` directory to your Unraid server
|
|
2. SSH into your Unraid server
|
|
3. Navigate to the project directory
|
|
4. Create and configure `.env` file
|
|
5. Run: `docker compose up -d`
|
|
|
|
### Method 2: Unraid Docker Template
|
|
|
|
1. Open Unraid web interface
|
|
2. Navigate to Docker tab
|
|
3. Click "Add Container"
|
|
4. Configure with these settings:
|
|
- **Name**: `discord-stock-bot`
|
|
- **Repository**: Build and push your image to Docker Hub first, then use `your-username/discord-stock-bot:latest`
|
|
- **Network Type**: `bridge`
|
|
- **Add Variables**:
|
|
- `DISCORD_TOKEN` = your bot token
|
|
- `CHANNEL_ID` = your channel ID
|
|
- `PRIMARY_TICKER` = PYPL
|
|
- `COMMAND_PREFIX` = !
|
|
- `TZ` = America/New_York
|
|
|
|
### Method 3: Build and Push to Docker Hub
|
|
|
|
```bash
|
|
# Build the image
|
|
docker build -t your-username/discord-stock-bot:latest .
|
|
|
|
# Login to Docker Hub
|
|
docker login
|
|
|
|
# Push to Docker Hub
|
|
docker push your-username/discord-stock-bot:latest
|
|
|
|
# On Unraid, pull and run
|
|
docker pull your-username/discord-stock-bot:latest
|
|
docker run -d --name discord-stock-bot \
|
|
--env-file .env \
|
|
--restart unless-stopped \
|
|
your-username/discord-stock-bot:latest
|
|
```
|
|
|
|
## Configuration Options
|
|
|
|
Environment variables in `.env`:
|
|
|
|
| Variable | Description | Default |
|
|
|----------|-------------|---------|
|
|
| `DISCORD_TOKEN` | Your Discord bot token | Required |
|
|
| `CHANNEL_ID` | Discord channel ID(s) for updates (comma-separated for multiple) | Required |
|
|
| `COMMAND_PREFIX` | Command prefix for bot | `!` |
|
|
| `PRIMARY_TICKER` | Stock ticker for hourly updates | `PYPL` |
|
|
| `UPDATE_INTERVAL_HOURS` | Hours between updates | `1` |
|
|
|
|
**Multi-Channel Support:** To send updates to multiple channels, provide comma-separated channel IDs:
|
|
```
|
|
CHANNEL_ID=1442203998932304035,9876543210123456789
|
|
```
|
|
|
|
## Switching Stock API Providers
|
|
|
|
The bot is designed with an abstract API layer. To switch providers:
|
|
|
|
1. Create a new class in `stock_api/` that inherits from `StockAPIBase`
|
|
2. Implement the required methods: `get_stock_price()` and `is_available()`
|
|
3. Update `bot.py` to use your new provider instead of `YahooFinanceAPI`
|
|
|
|
Example:
|
|
```python
|
|
# In bot.py
|
|
from stock_api import YourNewAPI
|
|
|
|
# In __init__ method
|
|
self.stock_api = YourNewAPI()
|
|
```
|
|
|
|
## Market Hours
|
|
|
|
The bot respects NYSE trading hours:
|
|
- **Trading Days**: Monday - Friday
|
|
- **Trading Hours**: 9:30 AM - 4:00 PM Eastern Time
|
|
- **Holidays**: Major NYSE holidays are observed (New Year's Day, MLK Day, Presidents Day, Good Friday, Memorial Day, Juneteenth, Independence Day, Labor Day, Thanksgiving, Christmas)
|
|
|
|
## Troubleshooting
|
|
|
|
### Bot does not connect
|
|
- Verify `DISCORD_TOKEN` is correct
|
|
- Ensure bot has been invited to your server
|
|
- Check bot has proper permissions in the channel
|
|
|
|
### Bot does not post updates
|
|
- Verify `CHANNEL_ID` is correct
|
|
- Ensure bot has permission to send messages in the channel
|
|
- Check if market is open using `!market` command
|
|
- View logs: `docker compose logs -f`
|
|
|
|
### Stock data not available
|
|
- Yahoo Finance may be experiencing issues
|
|
- Ticker symbol may be invalid
|
|
- Try using `!stock AAPL` to test with a known ticker
|
|
|
|
### Container will not start
|
|
- Verify `.env` file exists and is properly formatted
|
|
- Check Docker logs: `docker compose logs`
|
|
- Ensure no other container is using the same name
|
|
|
|
## License
|
|
|
|
This project is provided as-is for educational and personal use.
|
|
|
|
## Acknowledgments
|
|
|
|
- Stock data provided by Yahoo Finance via `yfinance`
|
|
- Built with `discord.py`
|
|
- Scheduling powered by `APScheduler`
|