Madras1 commited on
Commit
5a85511
ยท
verified ยท
1 Parent(s): 63e0eb9

Upload 7 files

Browse files
Files changed (2) hide show
  1. app.py +80 -57
  2. requirements.txt +2 -0
app.py CHANGED
@@ -1,23 +1,28 @@
1
  """
2
- HuggingFace Spaces Entry Point for Jade Bot
3
  """
4
  import os
5
  import socket
6
  import logging
7
  import asyncio
8
- import gradio as gr
9
  from datetime import datetime
 
 
 
 
 
10
 
11
- # FORCE IPv4 - Fix for HuggingFace Spaces DNS issues
12
  original_getaddrinfo = socket.getaddrinfo
13
- def force_ipv4_getaddrinfo(host, port, family=0, type=0, proto=0, flags=0):
14
  return original_getaddrinfo(host, port, socket.AF_INET, type, proto, flags)
15
- socket.getaddrinfo = force_ipv4_getaddrinfo
16
 
17
  logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO)
18
  logger = logging.getLogger(__name__)
19
 
20
  bot_status = {"started_at": None, "is_running": False, "error": None}
 
21
 
22
 
23
  def get_status():
@@ -28,29 +33,49 @@ def get_status():
28
  return f"## ๐ŸŸข Jade Running!\n- Started: {bot_status.get('started_at')}"
29
 
30
 
31
- def create_gradio_interface():
32
- with gr.Blocks(title="Jade Bot", theme=gr.themes.Soft()) as demo:
33
- gr.Markdown("# ๐ŸŒฟ Jade - 24h Personal Assistant")
34
- status_display = gr.Markdown(get_status)
35
- gr.Button("๐Ÿ”„ Refresh").click(fn=get_status, outputs=status_display)
36
- gr.Markdown("**Usage:** Find your bot on Telegram โ†’ `/start`")
37
- return demo
 
 
 
 
 
 
38
 
39
 
40
- async def run_bot():
41
- global bot_status
 
 
 
 
 
 
42
 
43
  token = os.getenv("TELEGRAM_BOT_TOKEN")
 
 
44
  if not token:
45
  bot_status["error"] = "TELEGRAM_BOT_TOKEN not set!"
46
  return
47
 
48
- logger.info("Waiting for network to stabilize...")
49
- await asyncio.sleep(5)
 
 
 
 
 
 
 
 
50
 
51
  try:
52
- from telegram import Update
53
- from telegram.ext import ApplicationBuilder, ContextTypes, CommandHandler, MessageHandler, filters
54
  from core import TelegramJadeAgent
55
  from tools import ReminderManager
56
 
@@ -67,57 +92,55 @@ async def run_bot():
67
  response = await loop.run_in_executor(None, agent.chat, chat_id, user_text)
68
  await context.bot.send_message(chat_id=chat_id, text=response)
69
 
70
- # Retry loop - create NEW application each attempt
 
 
 
 
 
 
 
 
71
  for attempt in range(5):
72
  try:
73
- logger.info(f"Connecting to Telegram ({attempt + 1}/5)...")
74
-
75
- # Create fresh application each time
76
- application = ApplicationBuilder().token(token).build()
77
- application.add_handler(CommandHandler('start', start))
78
- application.add_handler(MessageHandler(filters.TEXT & (~filters.COMMAND), handle_message))
79
-
80
- await application.initialize()
81
- await application.start()
82
- await application.updater.start_polling(drop_pending_updates=True)
83
-
84
  bot_status["started_at"] = datetime.now().strftime("%H:%M:%S")
85
  bot_status["is_running"] = True
86
- logger.info("โœ… Bot running!")
87
-
88
- # Keep running
89
- while True:
90
- await asyncio.sleep(60)
91
-
92
  except Exception as e:
93
- logger.warning(f"Attempt {attempt + 1} failed: {e}")
94
  if attempt < 4:
95
- await asyncio.sleep(5 * (attempt + 1))
96
  else:
97
  raise
98
-
99
  except Exception as e:
100
- logger.error(f"Bot failed: {e}")
101
  bot_status["error"] = str(e)
102
 
103
 
104
- def main():
105
- required = ["TELEGRAM_BOT_TOKEN", "CHUTES_API_KEY"]
106
- missing = [v for v in required if not os.getenv(v)]
107
- if missing:
108
- bot_status["error"] = f"Missing: {', '.join(missing)}"
109
-
110
- import threading
111
- def run_async():
112
- loop = asyncio.new_event_loop()
113
- asyncio.set_event_loop(loop)
114
- loop.run_until_complete(run_bot())
115
-
116
- threading.Thread(target=run_async, daemon=True).start()
117
- logger.info("Bot thread started")
118
-
119
- create_gradio_interface().launch(server_name="0.0.0.0", server_port=7860)
 
 
 
120
 
121
 
122
  if __name__ == "__main__":
123
- main()
 
1
  """
2
+ HuggingFace Spaces Entry Point for Jade Bot - Using Webhooks
3
  """
4
  import os
5
  import socket
6
  import logging
7
  import asyncio
 
8
  from datetime import datetime
9
+ from fastapi import FastAPI, Request
10
+ from telegram import Update
11
+ from telegram.ext import ApplicationBuilder, ContextTypes, CommandHandler, MessageHandler, filters
12
+ import uvicorn
13
+ import gradio as gr
14
 
15
+ # FORCE IPv4
16
  original_getaddrinfo = socket.getaddrinfo
17
+ def force_ipv4(host, port, family=0, type=0, proto=0, flags=0):
18
  return original_getaddrinfo(host, port, socket.AF_INET, type, proto, flags)
19
+ socket.getaddrinfo = force_ipv4
20
 
21
  logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO)
22
  logger = logging.getLogger(__name__)
23
 
24
  bot_status = {"started_at": None, "is_running": False, "error": None}
25
+ application = None
26
 
27
 
28
  def get_status():
 
33
  return f"## ๐ŸŸข Jade Running!\n- Started: {bot_status.get('started_at')}"
34
 
35
 
36
+ # FastAPI for webhook
37
+ app = FastAPI()
38
+
39
+
40
+ @app.post("/webhook")
41
+ async def webhook(request: Request):
42
+ """Handle incoming Telegram updates via webhook."""
43
+ global application
44
+ if application:
45
+ data = await request.json()
46
+ update = Update.de_json(data, application.bot)
47
+ await application.process_update(update)
48
+ return {"ok": True}
49
 
50
 
51
+ @app.get("/health")
52
+ async def health():
53
+ return {"status": "ok", "bot_running": bot_status["is_running"]}
54
+
55
+
56
+ async def setup_bot():
57
+ """Setup the Telegram bot with webhook."""
58
+ global application, bot_status
59
 
60
  token = os.getenv("TELEGRAM_BOT_TOKEN")
61
+ space_url = os.getenv("SPACE_URL", "") # e.g., https://madras1-jade-assistant.hf.space
62
+
63
  if not token:
64
  bot_status["error"] = "TELEGRAM_BOT_TOKEN not set!"
65
  return
66
 
67
+ if not space_url:
68
+ # Try to construct from SPACE_ID
69
+ space_id = os.getenv("SPACE_ID", "")
70
+ if space_id:
71
+ space_url = f"https://{space_id.replace('/', '-')}.hf.space"
72
+ else:
73
+ bot_status["error"] = "SPACE_URL not set! Add it to secrets."
74
+ return
75
+
76
+ logger.info(f"Space URL: {space_url}")
77
 
78
  try:
 
 
79
  from core import TelegramJadeAgent
80
  from tools import ReminderManager
81
 
 
92
  response = await loop.run_in_executor(None, agent.chat, chat_id, user_text)
93
  await context.bot.send_message(chat_id=chat_id, text=response)
94
 
95
+ # Build application
96
+ application = ApplicationBuilder().token(token).build()
97
+ application.add_handler(CommandHandler('start', start))
98
+ application.add_handler(MessageHandler(filters.TEXT & (~filters.COMMAND), handle_message))
99
+
100
+ await application.initialize()
101
+
102
+ # Set webhook with retries
103
+ webhook_url = f"{space_url}/webhook"
104
  for attempt in range(5):
105
  try:
106
+ logger.info(f"Setting webhook to {webhook_url} (attempt {attempt + 1}/5)...")
107
+ await application.bot.set_webhook(url=webhook_url)
108
+ logger.info("โœ… Webhook set successfully!")
 
 
 
 
 
 
 
 
109
  bot_status["started_at"] = datetime.now().strftime("%H:%M:%S")
110
  bot_status["is_running"] = True
111
+ break
 
 
 
 
 
112
  except Exception as e:
113
+ logger.warning(f"Webhook attempt {attempt + 1} failed: {e}")
114
  if attempt < 4:
115
+ await asyncio.sleep(10)
116
  else:
117
  raise
118
+
119
  except Exception as e:
120
+ logger.error(f"Bot setup failed: {e}")
121
  bot_status["error"] = str(e)
122
 
123
 
124
+ # Gradio interface
125
+ def create_gradio():
126
+ with gr.Blocks(title="Jade Bot") as demo:
127
+ gr.Markdown("# ๐ŸŒฟ Jade - 24h Personal Assistant")
128
+ status = gr.Markdown(get_status)
129
+ gr.Button("๐Ÿ”„ Refresh").click(fn=get_status, outputs=status)
130
+ gr.Markdown("**Usage:** Message your bot on Telegram โ†’ `/start`")
131
+ return demo
132
+
133
+
134
+ # Mount Gradio on FastAPI
135
+ gradio_app = create_gradio()
136
+ app = gr.mount_gradio_app(app, gradio_app, path="/")
137
+
138
+
139
+ @app.on_event("startup")
140
+ async def startup_event():
141
+ logger.info("Starting bot setup...")
142
+ asyncio.create_task(setup_bot())
143
 
144
 
145
  if __name__ == "__main__":
146
+ uvicorn.run(app, host="0.0.0.0", port=7860)
requirements.txt CHANGED
@@ -3,3 +3,5 @@ openai
3
  duckduckgo-search
4
  huggingface_hub>=0.20.0,<0.30.0
5
  gradio>=4.0.0,<5.0.0
 
 
 
3
  duckduckgo-search
4
  huggingface_hub>=0.20.0,<0.30.0
5
  gradio>=4.0.0,<5.0.0
6
+ uvicorn
7
+ fastapi