Dmitry Beresnev commited on
Commit
67c785a
Β·
1 Parent(s): f74cab2

fix dockerfile and dockerfile

Browse files
Files changed (2) hide show
  1. Dockerfile +11 -7
  2. src/telegram_bot.py +88 -56
Dockerfile CHANGED
@@ -2,12 +2,11 @@ FROM python:3.10-slim
2
 
3
  # Set environment variables
4
  ENV HOME=/app
 
5
 
6
  # Create app directory and set as working dir
7
  WORKDIR $HOME
8
 
9
- ENV PYTHONPATH=$HOME
10
-
11
  RUN apt-get update && apt-get install -y \
12
  build-essential \
13
  curl \
@@ -16,15 +15,20 @@ RUN apt-get update && apt-get install -y \
16
  && rm -rf /var/lib/apt/lists/*
17
 
18
  COPY requirements.txt ./
19
- COPY src/ ./src/
20
 
21
  RUN pip3 install --no-cache-dir -r requirements.txt
22
 
23
- ENV http_proxy ""
24
- ENV https_proxy ""
 
 
25
 
26
  EXPOSE 7860
27
 
28
- HEALTHCHECK CMD curl --fail http://localhost:7860/
 
 
 
29
 
30
- ENTRYPOINT ["uvicorn", "src.telegram_bot:app", "--host", "0.0.0.0", "--port", "7860"]
 
 
2
 
3
  # Set environment variables
4
  ENV HOME=/app
5
+ ENV PYTHONPATH=$HOME
6
 
7
  # Create app directory and set as working dir
8
  WORKDIR $HOME
9
 
 
 
10
  RUN apt-get update && apt-get install -y \
11
  build-essential \
12
  curl \
 
15
  && rm -rf /var/lib/apt/lists/*
16
 
17
  COPY requirements.txt ./
 
18
 
19
  RUN pip3 install --no-cache-dir -r requirements.txt
20
 
21
+ COPY src/ ./src/
22
+
23
+ ENV http_proxy=""
24
+ ENV https_proxy=""
25
 
26
  EXPOSE 7860
27
 
28
+ # Health check for Flask app
29
+ HEALTHCHECK CMD curl --fail http://localhost:7860/ || exit 1
30
+
31
+ # Choose ONE of these based on your file structure:
32
 
33
+ # Option A: If main file is src/telegram_bot.py with Flask app
34
+ ENTRYPOINT ["python", "src/telegram_bot.py"]
src/telegram_bot.py CHANGED
@@ -1,64 +1,92 @@
1
  import logging
2
  import os
3
- import sys
4
  from typing import Any
5
 
6
  from telegram import Update
7
- from telegram.ext import Application, ApplicationBuilder, CommandHandler, ContextTypes
8
  from dotenv import load_dotenv
9
  from src.financial_news_requester import fetch_comp_financial_news
10
  from fastapi import FastAPI, Request
11
  import uvicorn
12
- import asyncio
13
-
14
 
15
  logging.basicConfig(level=logging.INFO)
16
  logger = logging.getLogger(__name__)
17
 
18
-
19
  load_dotenv()
20
 
21
- TELEGRAM_TOKEN = os.getenv("TELEGRAM_TOKEN")
22
- if not TELEGRAM_TOKEN:
23
- logger.error("TELEGRAM_TOKEN not found! Please add it in Space Settings > Repository secrets")
24
- raise ValueError("TELEGRAM_TOKEN not found in environment variables")
25
- SPACE_ID = os.environ.get('SPACE_ID', 'ResearchEngineering/news_sentiment_analyzer')
 
 
 
26
  PORT = int(os.environ.get('PORT', 7860))
27
 
 
 
 
28
 
29
  def format_news_for_telegram(news_json: list[dict[str, Any]]) -> str:
30
  message = ""
31
  for item in news_json:
32
  message += (
33
- f"πŸ“° <b>{item.get('headline')}</b>\n"
34
- f"πŸ“ {item.get('summary')}\n"
35
- f"🏷️ Source: {item.get('source')}\n"
36
- f"πŸ”— <a href=\"{item.get('url')}\">Read more</a>\n\n"
37
  )
38
- return message
39
 
40
 
41
  async def start(update: Update, context: ContextTypes.DEFAULT_TYPE):
42
- await update.message.reply_text("Hello! I'm your Financial Bot.")
 
43
 
44
  async def help_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
45
  """Handle /help command"""
46
- await update.message.reply_text("πŸ€– Available commands:\n/start - Start the bot\n/help - Show this help")
 
 
 
 
 
 
47
 
48
  async def run_crew(update: Update, context: ContextTypes.DEFAULT_TYPE):
49
- await update.message.reply_text("Running ...")
50
  try:
51
  feed = fetch_comp_financial_news()
52
- logging.info(f"processed: {feed} news")
53
- await update.message.reply_text(f"Result:\n{format_news_for_telegram(feed)}", parse_mode='HTML')
 
 
 
 
 
 
 
 
 
 
 
54
  except Exception as e:
55
- await update.message.reply_text(f"Error: {e}")
 
 
56
 
 
 
 
 
57
 
58
- app = FastAPI()
 
59
 
60
 
61
- @app.post(f"/{TELEGRAM_TOKEN}")
62
  async def webhook(request: Request):
63
  """Handle incoming webhook from Telegram"""
64
  try:
@@ -78,27 +106,35 @@ async def webhook(request: Request):
78
  @app.get("/")
79
  async def root():
80
  """Health check endpoint"""
81
- return {"status": "Bot is running!", "webhook_url": f"https://{SPACE_ID}.hf.space/{TELEGRAM_TOKEN}"}
 
 
 
 
 
82
 
83
 
84
  @app.get("/set_webhook")
85
  async def set_webhook():
86
  """Manually set the webhook (call this once after deployment)"""
87
  try:
88
- webhook_url = f"https://{SPACE_ID}.hf.space/{TELEGRAM_TOKEN}"
89
-
90
- # Use a simple HTTP request to set webhook instead of bot.set_webhook()
91
- import httpx
92
 
93
- set_webhook_url = f"https://api.telegram.org/bot{TELEGRAM_TOKEN}/setWebhook"
94
 
95
- async with httpx.AsyncClient() as client:
96
- response = await client.post(set_webhook_url, json={"url": webhook_url})
 
 
 
97
  result = response.json()
98
 
99
  if result.get("ok"):
 
100
  return {"status": "success", "webhook_url": webhook_url, "result": result}
101
  else:
 
102
  return {"status": "error", "result": result}
103
 
104
  except Exception as e:
@@ -106,37 +142,33 @@ async def set_webhook():
106
  return {"status": "error", "message": str(e)}
107
 
108
 
 
 
 
 
 
109
 
110
- def func():
111
- logging.basicConfig(level=logging.INFO)
112
- app = ApplicationBuilder().token(TELEGRAM_TOKEN).build()
113
- app.add_handler(CommandHandler("start", start))
114
- app.add_handler(CommandHandler("run", run_crew))
115
- app.run_polling()
116
 
 
 
 
 
117
 
118
- def test_func():
119
- application = Application.builder().token(TELEGRAM_TOKEN).build()
120
- application.add_handler(CommandHandler("start", start))
121
- PORT = int(os.environ.get('PORT', 8000))
122
 
123
- # Run webhook (better for HF Spaces)
124
- application.run_webhook(
125
- listen="0.0.0.0",
126
- port=PORT,
127
- url_path=TELEGRAM_TOKEN,
128
- webhook_url=f"https://{os.environ.get('SPACE_ID', SPACE_ID)}.hf.space/{TELEGRAM_TOKEN}"
129
- )
130
 
131
 
132
  if __name__ == "__main__":
133
- # Create telegram application WITHOUT initializing
134
- application = Application.builder().token(TELEGRAM_TOKEN).build()
135
- application.add_handler(CommandHandler("start", start))
136
- application.add_handler(CommandHandler("help", help_command))
137
-
138
- logger.info(f"Starting bot on port {PORT}")
139
- logger.info(f"Webhook URL will be: https://{SPACE_ID}.hf.space/{TELEGRAM_TOKEN}")
140
  logger.info("After deployment, visit /set_webhook to configure the webhook")
141
 
142
- uvicorn.run(app, host="0.0.0.0", port=PORT)
 
1
  import logging
2
  import os
 
3
  from typing import Any
4
 
5
  from telegram import Update
6
+ from telegram.ext import Application, CommandHandler, ContextTypes
7
  from dotenv import load_dotenv
8
  from src.financial_news_requester import fetch_comp_financial_news
9
  from fastapi import FastAPI, Request
10
  import uvicorn
11
+ import httpx
 
12
 
13
  logging.basicConfig(level=logging.INFO)
14
  logger = logging.getLogger(__name__)
15
 
 
16
  load_dotenv()
17
 
18
+ # Fix 1: Use consistent token name (BOT_TOKEN is standard for HF Spaces)
19
+ BOT_TOKEN = os.getenv("BOT_TOKEN") or os.getenv("TELEGRAM_TOKEN")
20
+ if not BOT_TOKEN:
21
+ logger.error("BOT_TOKEN not found! Please add it in Space Settings > Repository secrets")
22
+ raise ValueError("BOT_TOKEN not found in environment variables")
23
+
24
+ # Fix 2: Correct SPACE_ID format
25
+ SPACE_ID = os.environ.get('SPACE_ID', 'researchengineering-news_sentiment_analyzer')
26
  PORT = int(os.environ.get('PORT', 7860))
27
 
28
+ # Fix 3: Create application GLOBALLY so webhook can access it
29
+ application = Application.builder().token(BOT_TOKEN).build()
30
+
31
 
32
  def format_news_for_telegram(news_json: list[dict[str, Any]]) -> str:
33
  message = ""
34
  for item in news_json:
35
  message += (
36
+ f"πŸ“° <b>{item.get('headline', 'No headline')}</b>\n"
37
+ f"πŸ“ {item.get('summary', 'No summary')}\n"
38
+ f"🏷️ Source: {item.get('source', 'Unknown')}\n"
39
+ f"πŸ”— <a href=\"{item.get('url', '#')}\">Read more</a>\n\n"
40
  )
41
+ return message if message else "No news available."
42
 
43
 
44
  async def start(update: Update, context: ContextTypes.DEFAULT_TYPE):
45
+ await update.message.reply_text("Hello! I'm your Financial News Bot. Use /run to get latest news.")
46
+
47
 
48
  async def help_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
49
  """Handle /help command"""
50
+ await update.message.reply_text(
51
+ "πŸ€– Available commands:\n"
52
+ "/start - Start the bot\n"
53
+ "/help - Show this help\n"
54
+ "/run - Get latest financial news"
55
+ )
56
+
57
 
58
  async def run_crew(update: Update, context: ContextTypes.DEFAULT_TYPE):
59
+ await update.message.reply_text("Fetching latest financial news...")
60
  try:
61
  feed = fetch_comp_financial_news()
62
+ logger.info(f"Processed: {len(feed)} news items")
63
+
64
+ formatted_news = format_news_for_telegram(feed)
65
+
66
+ # Split message if too long (Telegram limit is 4096 characters)
67
+ if len(formatted_news) > 4000:
68
+ # Send in chunks
69
+ chunks = [formatted_news[i:i + 4000] for i in range(0, len(formatted_news), 4000)]
70
+ for chunk in chunks:
71
+ await update.message.reply_text(chunk, parse_mode='HTML')
72
+ else:
73
+ await update.message.reply_text(formatted_news, parse_mode='HTML')
74
+
75
  except Exception as e:
76
+ logger.error(f"Error in run_crew: {e}")
77
+ await update.message.reply_text(f"Sorry, there was an error fetching news: {str(e)}")
78
+
79
 
80
+ # Add handlers to the global application
81
+ application.add_handler(CommandHandler("start", start))
82
+ application.add_handler(CommandHandler("help", help_command))
83
+ application.add_handler(CommandHandler("run", run_crew))
84
 
85
+ # Create FastAPI app
86
+ app = FastAPI(title="Financial News Bot", description="Telegram bot for financial news")
87
 
88
 
89
+ @app.post(f"/{BOT_TOKEN}")
90
  async def webhook(request: Request):
91
  """Handle incoming webhook from Telegram"""
92
  try:
 
106
  @app.get("/")
107
  async def root():
108
  """Health check endpoint"""
109
+ return {
110
+ "status": "Financial News Bot is running!",
111
+ "webhook_url": f"https://{SPACE_ID}.hf.space/{BOT_TOKEN[:10]}...",
112
+ "space_id": SPACE_ID,
113
+ "available_endpoints": ["/", "/set_webhook", "/webhook_info"]
114
+ }
115
 
116
 
117
  @app.get("/set_webhook")
118
  async def set_webhook():
119
  """Manually set the webhook (call this once after deployment)"""
120
  try:
121
+ webhook_url = f"https://{SPACE_ID}.hf.space/{BOT_TOKEN}"
122
+ set_webhook_url = f"https://api.telegram.org/bot{BOT_TOKEN}/setWebhook"
 
 
123
 
124
+ logger.info(f"Setting webhook to: {webhook_url}")
125
 
126
+ async with httpx.AsyncClient(timeout=30.0) as client:
127
+ response = await client.post(set_webhook_url, json={
128
+ "url": webhook_url,
129
+ "drop_pending_updates": True
130
+ })
131
  result = response.json()
132
 
133
  if result.get("ok"):
134
+ logger.info("Webhook set successfully!")
135
  return {"status": "success", "webhook_url": webhook_url, "result": result}
136
  else:
137
+ logger.error(f"Failed to set webhook: {result}")
138
  return {"status": "error", "result": result}
139
 
140
  except Exception as e:
 
142
  return {"status": "error", "message": str(e)}
143
 
144
 
145
+ @app.get("/webhook_info")
146
+ async def webhook_info():
147
+ """Get current webhook information"""
148
+ try:
149
+ info_url = f"https://api.telegram.org/bot{BOT_TOKEN}/getWebhookInfo"
150
 
151
+ async with httpx.AsyncClient(timeout=30.0) as client:
152
+ response = await client.get(info_url)
153
+ result = response.json()
 
 
 
154
 
155
+ return result
156
+ except Exception as e:
157
+ logger.error(f"Error getting webhook info: {e}")
158
+ return {"status": "error", "message": str(e)}
159
 
 
 
 
 
160
 
161
+ @app.get("/health")
162
+ async def health():
163
+ """Additional health check"""
164
+ return {"status": "healthy", "bot_token_set": bool(BOT_TOKEN)}
 
 
 
165
 
166
 
167
  if __name__ == "__main__":
168
+ logger.info(f"Starting Financial News Bot on port {PORT}")
169
+ logger.info(f"Bot token: {BOT_TOKEN[:10]}..." if BOT_TOKEN else "No token set")
170
+ logger.info(f"Space ID: {SPACE_ID}")
171
+ logger.info(f"Webhook URL will be: https://{SPACE_ID}.hf.space/{BOT_TOKEN[:10]}...")
 
 
 
172
  logger.info("After deployment, visit /set_webhook to configure the webhook")
173
 
174
+ uvicorn.run(app, host="0.0.0.0", port=PORT)