โ† ะะฐะทะฐะด
""" 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)