โ ะะฐะทะฐะด"""
AlphaPulse Bot โ Command & Callback Handlers
"""
import logging
from telegram import Update
from telegram.ext import ContextTypes
from ai import AICommentary
from fetcher import ContentFetcher
logger = logging.getLogger(__name__)
class CommandHandlers:
"""All /command and inline button callback handlers."""
def __init__(self, fetcher: ContentFetcher):
self.fetcher = fetcher
# โโ Slash commands โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
async def cmd_price(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
"""/price โ Live BTC + ETH + SOL prices."""
prices = await self.fetcher.fetch_prices()
if not prices:
await update.message.reply_text("โ ๏ธ Could not fetch prices right now. Try again later.")
return
btc_a = 'โฒ' if prices['btc_change'] > 0 else 'โผ'
eth_a = 'โฒ' if prices['eth_change'] > 0 else 'โผ'
sol_a = 'โฒ' if prices.get('sol_change', 0) > 0 else 'โผ'
text = (
f"๐น <b>Live Prices</b>\n\n"
f"โฟ BTC <b>${prices['btc_price']:,.0f}</b> {btc_a} {prices['btc_change']:+.1f}%\n"
f"โ ETH <b>${prices['eth_price']:,.0f}</b> {eth_a} {prices['eth_change']:+.1f}%\n"
f"โ SOL <b>${prices['sol_price']:,.2f}</b> {sol_a} {prices.get('sol_change', 0):+.1f}%\n\n"
f"<i>Source: CoinGecko</i>"
)
await update.message.reply_text(text, parse_mode='HTML')
async def cmd_fear(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
"""/fear โ Current Fear & Greed Index."""
fg = await self.fetcher.fetch_fear_greed()
if not fg:
await update.message.reply_text("โ ๏ธ Could not fetch Fear & Greed index. Try again later.")
return
text = AICommentary.fear_greed_text(fg['value'], fg['classification'])
await update.message.reply_text(
f"๐๏ธ <b>Fear & Greed Index</b>\n\n{text}\n\n<i>Source: alternative.me</i>",
parse_mode='HTML'
)
async def cmd_stats(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
"""/stats โ Top 5 gainers & losers (24h)."""
gainers, losers = await self.fetcher.fetch_top_movers()
if not gainers and not losers:
await update.message.reply_text("โ ๏ธ Could not fetch top movers. Try again later.")
return
lines = ["๐ <b>Top Movers (24h)</b>", ""]
if gainers:
lines.append("๐ข <b>Gainers</b>")
for c in gainers[:5]:
pct = c['price_change_percentage_24h'] or 0
lines.append(f" {c['symbol'].upper()} +{pct:.1f}%")
if losers:
lines += ["", "๐ด <b>Losers</b>"]
for c in losers[:5]:
pct = c['price_change_percentage_24h'] or 0
lines.append(f" {c['symbol'].upper()} {pct:.1f}%")
await update.message.reply_text('\n'.join(lines), parse_mode='HTML')
async def cmd_trending(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
"""/trending โ Today's top trending coins."""
coins = await self.fetcher.fetch_trending()
if not coins:
await update.message.reply_text("โ ๏ธ Could not fetch trending coins. Try again later.")
return
lines = ["๐ฅ <b>Trending Now</b>", ""]
medals = ['๐ฅ', '๐ฅ', '๐ฅ', '4๏ธโฃ', '5๏ธโฃ', '6๏ธโฃ', '7๏ธโฃ']
for i, c in enumerate(coins[:7]):
rank = f"#{c['rank']}" if c['rank'] != '?' else ''
lines.append(f"{medals[i]} <b>{c['symbol']}</b> {c['name']} {rank}")
lines.append("\n<i>Source: CoinGecko</i>")
await update.message.reply_text('\n'.join(lines), parse_mode='HTML')
async def cmd_help(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
"""/help โ Available commands."""
text = (
"๐ค <b>AlphaPulseXP Commands</b>\n\n"
"/price โ Live BTC + ETH prices\n"
"/fear โ Crypto Fear & Greed Index\n"
"/stats โ Top 5 gainers & losers (24h)\n"
"/trending โ Today's trending coins\n"
"/help โ This message\n\n"
"๐ข Channel: @alphapulsexp"
)
await update.message.reply_text(text, parse_mode='HTML')
# โโ Inline button callbacks โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
async def btn_price(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
"""Inline button: ๐ Price."""
query = update.callback_query
prices = await self.fetcher.fetch_prices()
if not prices:
await query.answer("โ ๏ธ Could not fetch prices", show_alert=True)
return
btc_a = 'โฒ' if prices['btc_change'] > 0 else 'โผ'
eth_a = 'โฒ' if prices['eth_change'] > 0 else 'โผ'
sol_a = 'โฒ' if prices.get('sol_change', 0) > 0 else 'โผ'
text = (
f"โฟ BTC ${prices['btc_price']:,.0f} {btc_a}{prices['btc_change']:+.1f}%\n"
f"โ ETH ${prices['eth_price']:,.0f} {eth_a}{prices['eth_change']:+.1f}%\n"
f"โ SOL ${prices['sol_price']:,.2f} {sol_a}{prices.get('sol_change', 0):+.1f}%"
)
await query.answer(text, show_alert=True)
async def btn_fear(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
"""Inline button: ๐ฑ Fear."""
query = update.callback_query
fg = await self.fetcher.fetch_fear_greed()
if not fg:
await query.answer("โ ๏ธ Could not fetch Fear & Greed", show_alert=True)
return
text = AICommentary.fear_greed_text(fg['value'], fg['classification'])
await query.answer(text.replace('\n', ' | '), show_alert=True)
async def btn_trending(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
"""Inline button: ๐ฅ Trending."""
query = update.callback_query
coins = await self.fetcher.fetch_trending()
if not coins:
await query.answer("โ ๏ธ Could not fetch trending coins", show_alert=True)
return
medals = ['๐ฅ', '๐ฅ', '๐ฅ', '4๏ธโฃ', '5๏ธโฃ', '6๏ธโฃ', '7๏ธโฃ']
lines = [f"{medals[i]} {c['symbol']} {c['name']}" for i, c in enumerate(coins[:5])]
await query.answer('\n'.join(lines), show_alert=True)