Spaces:
Runtime error
Runtime error
File size: 6,377 Bytes
67cf156 67c785a 67cf156 a156819 67c785a 67cf156 fe216f3 67cf156 67c785a a156819 67cf156 67c785a 67cf156 67c785a 67cf156 67c785a 67cf156 67c785a 67cf156 a156819 67c785a a156819 67cf156 67c785a 7debc6c 67c785a 7debc6c 67c785a 67cf156 67c785a fe216f3 67c785a a156819 67c785a a156819 67c785a a156819 67c785a a156819 67c785a a156819 67c785a a156819 67c785a a156819 67c785a a156819 67c785a a156819 67c785a fe216f3 67c785a fe216f3 67c785a a156819 9a1cb80 c391088 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 |
import logging
import os
from typing import Any
from telegram import Update
from telegram.ext import Application, CommandHandler, ContextTypes
from dotenv import load_dotenv
from src.financial_news_requester import fetch_comp_financial_news
from fastapi import FastAPI, Request
import uvicorn
import httpx
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
load_dotenv()
# Fix 1: Use consistent token name (BOT_TOKEN is standard for HF Spaces)
BOT_TOKEN = os.getenv("BOT_TOKEN") or os.getenv("TELEGRAM_TOKEN")
if not BOT_TOKEN:
logger.error("BOT_TOKEN not found! Please add it in Space Settings > Repository secrets")
raise ValueError("BOT_TOKEN not found in environment variables")
# Fix 2: Correct SPACE_ID format
SPACE_ID = os.environ.get('SPACE_ID', 'researchengineering-news_sentiment_analyzer')
PORT = int(os.environ.get('PORT', 7860))
# Fix 3: Create application GLOBALLY so webhook can access it
application = Application.builder().token(BOT_TOKEN).build()
def format_news_for_telegram(news_json: list[dict[str, Any]]) -> str:
message = ""
for item in news_json:
message += (
f"π° <b>{item.get('headline', 'No headline')}</b>\n"
f"π {item.get('summary', 'No summary')}\n"
f"π·οΈ Source: {item.get('source', 'Unknown')}\n"
f"π <a href=\"{item.get('url', '#')}\">Read more</a>\n\n"
)
return message if message else "No news available."
async def start(update: Update, context: ContextTypes.DEFAULT_TYPE):
await update.message.reply_text("Hello! I'm your Financial News Bot. Use /run to get latest news.")
async def help_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
"""Handle /help command"""
await update.message.reply_text(
"π€ Available commands:\n"
"/start - Start the bot\n"
"/help - Show this help\n"
"/run - Get latest financial news"
)
async def run_crew(update: Update, context: ContextTypes.DEFAULT_TYPE):
await update.message.reply_text("Fetching latest financial news...")
try:
feed = fetch_comp_financial_news()
logger.info(f"Processed: {len(feed)} news items")
formatted_news = format_news_for_telegram(feed)
# Split message if too long (Telegram limit is 4096 characters)
if len(formatted_news) > 4000:
# Split by news items, not by character count
items = formatted_news.split('\n\n')
chunk = ""
for item in items:
if len(chunk) + len(item) + 2 > 4000:
await update.message.reply_text(chunk, parse_mode='HTML')
chunk = ""
chunk += item + "\n\n"
if chunk:
await update.message.reply_text(chunk, parse_mode='HTML')
else:
await update.message.reply_text(formatted_news, parse_mode='HTML')
except Exception as e:
logger.error(f"Error in run_crew: {e}")
await update.message.reply_text(f"Sorry, there was an error fetching news: {str(e)}")
# Add handlers to the global application
application.add_handler(CommandHandler("start", start))
application.add_handler(CommandHandler("help", help_command))
application.add_handler(CommandHandler("run", run_crew))
# Create FastAPI app
app = FastAPI(title="Financial News Bot", description="Telegram bot for financial news")
@app.post(f"/{BOT_TOKEN}")
async def webhook(request: Request):
"""Handle incoming webhook from Telegram"""
try:
# Get the update from Telegram
json_data = await request.json()
update = Update.de_json(json_data, application.bot)
# Process the update
await application.process_update(update)
return {"status": "ok"}
except Exception as e:
logger.error(f"Error processing update: {e}")
return {"status": "error", "message": str(e)}
@app.get("/")
async def root():
"""Health check endpoint"""
return {
"status": "Financial News Bot is running!",
"webhook_url": f"https://{SPACE_ID}.hf.space/{BOT_TOKEN[:10]}...",
"space_id": SPACE_ID,
"available_endpoints": ["/", "/set_webhook", "/webhook_info"]
}
@app.get("/set_webhook")
async def set_webhook():
"""Manually set the webhook (call this once after deployment)"""
try:
webhook_url = f"https://{SPACE_ID}.hf.space/{BOT_TOKEN}"
set_webhook_url = f"https://api.telegram.org/bot{BOT_TOKEN}/setWebhook"
logger.info(f"Setting webhook to: {webhook_url}")
async with httpx.AsyncClient(timeout=30.0) as client:
response = await client.post(set_webhook_url, json={
"url": webhook_url,
"drop_pending_updates": True
})
result = response.json()
if result.get("ok"):
logger.info("Webhook set successfully!")
return {"status": "success", "webhook_url": webhook_url, "result": result}
else:
logger.error(f"Failed to set webhook: {result}")
return {"status": "error", "result": result}
except Exception as e:
logger.error(f"Error setting webhook: {e}")
return {"status": "error", "message": str(e)}
@app.get("/webhook_info")
async def webhook_info():
"""Get current webhook information"""
try:
info_url = f"https://api.telegram.org/bot{BOT_TOKEN}/getWebhookInfo"
async with httpx.AsyncClient(timeout=30.0) as client:
response = await client.get(info_url)
result = response.json()
return result
except Exception as e:
logger.error(f"Error getting webhook info: {e}")
return {"status": "error", "message": str(e)}
@app.get("/health")
async def health():
"""Additional health check"""
return {"status": "healthy", "bot_token_set": bool(BOT_TOKEN)}
if __name__ == "__main__":
logger.info(f"Starting Financial News Bot on port {PORT}")
logger.info(f"Bot token: {BOT_TOKEN[:10]}..." if BOT_TOKEN else "No token set")
logger.info(f"Space ID: {SPACE_ID}")
logger.info(f"Webhook URL will be: https://{SPACE_ID}.hf.space/{BOT_TOKEN[:10]}...")
logger.info("After deployment, visit /set_webhook to configure the webhook")
uvicorn.run(app, host="0.0.0.0", port=PORT)
#application.run_polling() |