1+ import logging
2+ import asyncio
3+ import sys
4+ import os
5+ import html
6+ from telegram import Update
7+ from telegram .ext import ApplicationBuilder , ContextTypes , CommandHandler , MessageHandler , filters
8+
9+ # --- PATH CONFIGURATION ---
10+ # Fixes the 'ModuleNotFoundError' by adding the root project directory
11+ root_path = os .path .abspath (os .path .join (os .path .dirname (__file__ ), ".." ))
12+ if root_path not in sys .path :
13+ sys .path .append (root_path )
14+
15+ from config import Config
16+ from main import run_ficsense_pipeline
17+
18+ # Setup logging
19+ logging .basicConfig (
20+ format = '%(asctime)s - %(name)s - %(levelname)s - %(message)s' ,
21+ level = logging .INFO
22+ )
23+
24+ async def start (update : Update , context : ContextTypes .DEFAULT_TYPE ):
25+ """Handles /start and /restart commands."""
26+ await update .message .reply_html (
27+ "✨ <b>FicSense Antigravity Bot</b> ✨\n \n "
28+ "Ready to find your next read. Send your search as:\n "
29+ "<code>Fandom | Intent</code>\n \n "
30+ "Example: <code>onepiece | time travel ace</code>"
31+ )
32+
33+ async def handle_message (update : Update , context : ContextTypes .DEFAULT_TYPE ):
34+ text = update .message .text
35+
36+ if "|" not in text :
37+ await update .message .reply_html ("❌ <b>Format Error!</b> Please use: <code>Fandom | Intent</code>" )
38+ return
39+
40+ # 1. Parse Inputs
41+ fandom , intent = [x .strip () for x in text .split ("|" )]
42+
43+ await update .message .reply_html (
44+ f"📡 <b>Request Received!</b>\n "
45+ f"🔍 Scoping: <code>{ html .escape (fandom )} </code>\n "
46+ f"🎯 Target: <i>{ html .escape (intent )} </i>\n \n "
47+ f"<i>Launching Chrome on ASUS TUF...</i>"
48+ )
49+
50+ try :
51+ # 2. Run Pipeline (Offloaded to thread to keep bot alive)
52+ loop = asyncio .get_event_loop ()
53+ top_matches = await loop .run_in_executor (None , run_ficsense_pipeline , fandom , intent )
54+
55+ if not top_matches :
56+ await update .message .reply_html ("⚠️ <b>No results found.</b> The scraper might be blocked or no stories matched." )
57+ return
58+
59+ # 3. Build PLAIN TEXT Response (The "Unbreakable" Version)
60+ response = f"🎯 Top { len (top_matches )} Semantic Matches for { fandom .upper ()} \n "
61+ response += "-------------------------------------\n \n "
62+
63+ for i , res in enumerate (top_matches , 1 ):
64+ title = res .get ('title' , 'Unknown Title' )
65+ link = res .get ('link' , 'No Link' )
66+ score = res .get ('score' , 0.0 )
67+ # Truncate synopsis to keep the message clean
68+ synopsis = res .get ('synopsis' , 'No synopsis available.' )[:150 ] + "..."
69+
70+ # Simple string building with NO special formatting
71+ line = f"{ i } . { title } \n "
72+ line += f" 🔗 { link } \n "
73+ line += f" ⭐ Score: { score :.2f} \n "
74+ line += f" 📝 { synopsis } \n \n "
75+
76+ # Telegram message limit check
77+ if len (response + line ) > 4000 :
78+ await update .message .reply_text (response ) # Plain text, no parse_mode
79+ response = ""
80+ response += line
81+
82+ if response .strip ():
83+ # Crucial: We REMOVE parse_mode='HTML' or 'Markdown' here
84+ await update .message .reply_text (response )
85+
86+ except Exception as e :
87+ logging .error (f"Error: { e } " )
88+ # Even the error message should be plain text
89+ await update .message .reply_text (f"❌ System Error: { str (e )} " )
90+
91+ if __name__ == "__main__" :
92+ if not Config .BOT_TOKEN :
93+ print ("🛑 FATAL: No TELEGRAM_BOT_TOKEN found in .env file!" )
94+ else :
95+ # Build the application with increased timeouts for heavy scraping tasks
96+ application = (
97+ ApplicationBuilder ()
98+ .token (Config .BOT_TOKEN )
99+ .read_timeout (300 ) # Wait up to 5 mins for Telegram to read
100+ .write_timeout (300 ) # Wait up to 5 mins for Telegram to send
101+ .connect_timeout (300 )
102+ .pool_timeout (300 )
103+ .build ()
104+ )
105+
106+ # Adding handlers
107+ application .add_handler (CommandHandler (['start' , 'restart' ], start ))
108+ application .add_handler (MessageHandler (filters .TEXT & (~ filters .COMMAND ), handle_message ))
109+
110+ print ("🤖 FicSense Bot is alive with extended timeouts..." )
111+ application .run_polling ()
0 commit comments