Add cryptocurrency price command via CoinGecko API

New features:
- !crypto <SYMBOL> command to query cryptocurrency prices
- CoinGeckoAPI integration (free, no API key required)
- Support for 20+ popular cryptocurrencies (BTC, ETH, DOGE, etc.)
- 24-hour price change and volume data
- Colored embeds matching price movement
- Alias: !c for quick crypto queries

Uses CoinGecko's free /simple/price endpoint with 30 calls/min rate limit.

🤖 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-03 22:44:45 -06:00
parent 6a6716c4cc
commit bde07f676f
3 changed files with 190 additions and 0 deletions

76
bot.py
View File

@@ -9,6 +9,7 @@ import pytz
from config import Config
from stock_api import YahooFinanceAPI, FinnhubAPI
from market_hours import MarketHours
from crypto_api import CoinGeckoAPI
# Configure logging
@@ -39,6 +40,7 @@ class StockBot(commands.Bot):
self.target_channel_ids = [int(id) for id in Config.CHANNEL_IDS]
self.primary_ticker = Config.PRIMARY_TICKER
self.startup_announced = False
self.crypto_api = CoinGeckoAPI()
async def setup_hook(self):
"""Initialize the bot and set up scheduled tasks."""
@@ -212,6 +214,57 @@ class StockBot(commands.Bot):
return embed
def create_crypto_embed(self, crypto_data: dict) -> discord.Embed:
"""
Create a formatted Discord embed for cryptocurrency price data.
Args:
crypto_data: Dictionary containing crypto information
Returns:
Discord embed object
"""
symbol = crypto_data['symbol']
current_price = crypto_data['current_price']
change_dollar = crypto_data['change_dollar']
change_percent = crypto_data['change_percent']
# Determine color based on price movement
if change_dollar > 0:
color = discord.Color.green()
change_emoji = "📈"
elif change_dollar < 0:
color = discord.Color.red()
change_emoji = "📉"
else:
color = discord.Color.blue()
change_emoji = "➡️"
# Format change string
change_sign = "+" if change_dollar >= 0 else ""
change_str = f"{change_sign}${change_dollar} ({change_sign}{change_percent}%)"
# Create embed
embed = discord.Embed(
title=f"{change_emoji} {symbol} Price",
description=f"**${current_price:,.2f}**",
color=color,
timestamp=datetime.now(pytz.timezone('America/New_York'))
)
embed.add_field(name="24h Change", value=change_str, inline=True)
embed.add_field(name="Previous Price", value=f"${crypto_data['previous_price']:,.2f}", inline=True)
# Add volume if available
volume = crypto_data.get('volume_24h', 0)
if volume > 0:
volume_str = f"${volume:,.0f}"
embed.add_field(name="24h Volume", value=volume_str, inline=False)
embed.set_footer(text="Data from CoinGecko")
return embed
# Create bot instance
bot = StockBot()
@@ -240,6 +293,29 @@ async def get_stock_price(ctx, ticker: str = None):
await ctx.send(embed=embed)
@bot.command(name='crypto', aliases=['c'])
async def get_crypto_price(ctx, symbol: str = None):
"""
Query cryptocurrency price.
Usage: !crypto BTC or !c ETH
"""
if not symbol:
await ctx.send("Please provide a crypto symbol. Usage: `!crypto BTC`")
return
symbol = symbol.upper()
logger.info(f"Crypto query for {symbol} by {ctx.author}")
crypto_data = bot.crypto_api.get_crypto_price(symbol)
if not crypto_data:
await ctx.send(f"Unable to retrieve data for crypto: {symbol}")
return
embed = bot.create_crypto_embed(crypto_data)
await ctx.send(embed=embed)
@bot.command(name='ping')
async def ping(ctx):
"""Check if bot is responsive."""