Initial commit: Discord stock price bot with hourly PYPL updates

Implemented Discord bot for automated stock price tracking and reporting with the following features:

- Hourly PayPal (PYPL) stock price updates during NYSE market hours
- Custom branding for PYPL as "Steaks Stablecoin Value"
- Manual stock price queries via !stock and !price commands
- Multi-provider stock API support (Yahoo Finance and Finnhub)
- NYSE market hours detection with holiday awareness
- Discord embed formatting with color-coded price changes
- Docker containerization for consistent deployment
- Comprehensive documentation and deployment guides

Technical stack:
- Python 3.9+ with discord.py
- Finnhub API for stock price data
- APScheduler for hourly automated updates
- Docker support for local and Unraid deployment

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Michael Simard
2025-12-02 21:54:11 -06:00
commit 5964cadf94
14 changed files with 946 additions and 0 deletions

49
config.py Normal file
View File

@@ -0,0 +1,49 @@
import os
from dotenv import load_dotenv
load_dotenv()
class Config:
"""Application configuration loaded from environment variables."""
# Discord configuration
DISCORD_TOKEN = os.getenv('DISCORD_TOKEN')
CHANNEL_ID = os.getenv('CHANNEL_ID')
COMMAND_PREFIX = os.getenv('COMMAND_PREFIX', '!')
# Stock configuration
PRIMARY_TICKER = os.getenv('PRIMARY_TICKER', 'PYPL')
STOCK_API_PROVIDER = os.getenv('STOCK_API_PROVIDER', 'finnhub') # 'yahoo' or 'finnhub'
FINNHUB_API_KEY = os.getenv('FINNHUB_API_KEY')
# Scheduling configuration
UPDATE_INTERVAL_HOURS = int(os.getenv('UPDATE_INTERVAL_HOURS', '1'))
@classmethod
def validate(cls) -> bool:
"""
Validate that required configuration values are present.
Returns:
True if configuration is valid, False otherwise
"""
if not cls.DISCORD_TOKEN:
print("ERROR: DISCORD_TOKEN not set in environment")
return False
if not cls.CHANNEL_ID:
print("ERROR: CHANNEL_ID not set in environment")
return False
try:
int(cls.CHANNEL_ID)
except ValueError:
print("ERROR: CHANNEL_ID must be a numeric Discord channel ID")
return False
if cls.STOCK_API_PROVIDER == 'finnhub' and not cls.FINNHUB_API_KEY:
print("ERROR: FINNHUB_API_KEY not set in environment (required when STOCK_API_PROVIDER=finnhub)")
return False
return True