Update main.py

This commit is contained in:
ilyastar9999
2025-12-04 14:26:15 +03:00
parent 154c0cda75
commit b79f525a33

View File

@@ -28,55 +28,71 @@ polling_task = None
async def handle_button_click(callback_data: str, chat_id: int, message_id: int): async def handle_button_click(callback_data: str, chat_id: int, message_id: int):
"""Handle inline button click""" """Handle inline button click"""
print(f"[BUTTON] Received callback: {callback_data} from chat {chat_id}")
if not callback_data.startswith("service_"): if not callback_data.startswith("service_"):
print(f"[BUTTON] Invalid callback prefix: {callback_data}")
return return
# Parse: service_{action}_{id_or_name} # Parse: service_{action}_{id_or_name}
parts = callback_data.split("_", 2) parts = callback_data.split("_", 2)
if len(parts) != 3: if len(parts) != 3:
print(f"[BUTTON] Invalid callback format: {callback_data} (got {len(parts)} parts)")
return return
action = parts[1] # start, stop, restart action = parts[1] # start, stop, restart
identifier = parts[2] # numeric service_id or 'name_{service_name}' identifier = parts[2] # numeric service_id or 'name_{service_name}'
print(f"[BUTTON] Action: {action}, Identifier: {identifier}")
# Determine if identifier is service_id (numeric) or service_name (prefixed with 'name_') # Determine if identifier is service_id (numeric) or service_name (prefixed with 'name_')
if identifier.startswith('name_'): if identifier.startswith('name_'):
# Extract service name from identifier # Extract service name from identifier
service_name = identifier[5:] # Remove 'name_' prefix service_name = identifier[5:] # Remove 'name_' prefix
service_id = None service_id = None
print(f"[BUTTON] Looking up service by name: {service_name}")
# Look up service_id from controller API # Look up service_id from controller API
try: try:
print(f"[BUTTON] Contacting controller at {CONTROLLER_API}/services")
async with aiohttp.ClientSession() as session: async with aiohttp.ClientSession() as session:
headers = {"Authorization": f"Bearer {SECRET_TOKEN}"} headers = {"Authorization": f"Bearer {SECRET_TOKEN}"}
async with session.get(f"{CONTROLLER_API}/services", headers=headers) as resp: async with session.get(f"{CONTROLLER_API}/services", headers=headers) as resp:
print(f"[BUTTON] Controller response: HTTP {resp.status}")
if resp.status == 200: if resp.status == 200:
services = await resp.json() services = await resp.json()
print(f"[BUTTON] Found {len(services)} services: {[s.get('name') for s in services]}")
# Find service by name # Find service by name
for svc in services: for svc in services:
if svc.get('name') == service_name: if svc.get('name') == service_name:
service_id = svc.get('id') service_id = svc.get('id')
print(f"[BUTTON] Matched service '{service_name}' to ID {service_id}")
break break
if not service_id: if not service_id:
error_msg = f"❌ Service '{service_name}' not registered in controller"
print(f"[BUTTON] {error_msg}")
await bot.edit_message_text( await bot.edit_message_text(
chat_id=chat_id, chat_id=chat_id,
message_id=message_id, message_id=message_id,
text=f"❌ Service '{service_name}' not registered in controller" text=error_msg
) )
return return
else: else:
error_msg = f"❌ Failed to fetch services (HTTP {resp.status})"
print(f"[BUTTON] {error_msg}")
await bot.edit_message_text( await bot.edit_message_text(
chat_id=chat_id, chat_id=chat_id,
message_id=message_id, message_id=message_id,
text=f"❌ Failed to fetch services (HTTP {resp.status})" text=error_msg
) )
return return
except Exception as e: except Exception as e:
error_msg = f"❌ Error: {str(e)[:100]}"
print(f"[BUTTON] Exception during service lookup: {str(e)}")
await bot.edit_message_text( await bot.edit_message_text(
chat_id=chat_id, chat_id=chat_id,
message_id=message_id, message_id=message_id,
text=f"❌ Error: {str(e)[:100]}" text=error_msg
) )
await log_message(chat_id, f"Service lookup error", False, str(e)) await log_message(chat_id, f"Service lookup error", False, str(e))
return return
@@ -84,32 +100,47 @@ async def handle_button_click(callback_data: str, chat_id: int, message_id: int)
# Identifier is numeric service_id # Identifier is numeric service_id
try: try:
service_id = int(identifier) service_id = int(identifier)
print(f"[BUTTON] Using numeric service_id: {service_id}")
except ValueError: except ValueError:
print(f"[BUTTON] Failed to parse service_id from: {identifier}")
return return
try: try:
async with aiohttp.ClientSession() as session:
api_url = f"{CONTROLLER_API}/services/{service_id}/action" api_url = f"{CONTROLLER_API}/services/{service_id}/action"
print(f"[BUTTON] Executing {action} on service {service_id} at {api_url}")
async with aiohttp.ClientSession() as session:
headers = {"Authorization": f"Bearer {SECRET_TOKEN}"} headers = {"Authorization": f"Bearer {SECRET_TOKEN}"}
data = {"action": action} data = {"action": action}
print(f"[BUTTON] Sending POST request with data: {data}")
async with session.post(api_url, json=data, headers=headers, timeout=aiohttp.ClientTimeout(total=10)) as resp: async with session.post(api_url, json=data, headers=headers, timeout=aiohttp.ClientTimeout(total=10)) as resp:
response_text = await resp.text()
print(f"[BUTTON] Controller response: HTTP {resp.status}")
print(f"[BUTTON] Response body: {response_text[:200]}")
if resp.status == 200: if resp.status == 200:
success_msg = f"✅ Service action '{action}' executed successfully"
print(f"[BUTTON] Success: {success_msg}")
await bot.edit_message_text( await bot.edit_message_text(
chat_id=chat_id, chat_id=chat_id,
message_id=message_id, message_id=message_id,
text=f"✅ Service action '{action}' executed successfully" text=success_msg
) )
await log_message(chat_id, f"Action: {action} on service {service_id}", True) await log_message(chat_id, f"Action: {action} on service {service_id}", True)
else: else:
error_text = await resp.text() error_msg = f"❌ Failed: {response_text[:100]}"
print(f"[BUTTON] Failed: {error_msg}")
await bot.edit_message_text( await bot.edit_message_text(
chat_id=chat_id, chat_id=chat_id,
message_id=message_id, message_id=message_id,
text=f"❌ Failed: {error_text[:100]}" text=error_msg
) )
await log_message(chat_id, f"Action failed: {action}", False, error_text) await log_message(chat_id, f"Action failed: {action}", False, response_text)
except Exception as e: except Exception as e:
error_msg = f"❌ Exception: {str(e)[:100]}"
print(f"[BUTTON] Exception during action execution: {str(e)}")
print(f"[BUTTON] Full traceback:", exc_info=True)
await log_message(chat_id, f"Action error: {action}", False, str(e)) await log_message(chat_id, f"Action error: {action}", False, str(e))
async def poll_updates(): async def poll_updates():
@@ -117,27 +148,37 @@ async def poll_updates():
global update_offset global update_offset
if not bot: if not bot:
print("[POLLING] Bot not configured, skipping polling")
return return
print("[POLLING] Starting update polling")
while True: while True:
try: try:
updates = await bot.get_updates(offset=update_offset, timeout=30) updates = await bot.get_updates(offset=update_offset, timeout=30)
if updates:
print(f"[POLLING] Received {len(updates)} updates")
for update in updates: for update in updates:
update_offset = update.update_id + 1 update_offset = update.update_id + 1
if update.callback_query: if update.callback_query:
query = update.callback_query query = update.callback_query
print(f"[POLLING] Processing callback query: {query.data}")
await handle_button_click( await handle_button_click(
query.data, query.data,
query.message.chat_id, query.message.chat_id,
query.message.message_id query.message.message_id
) )
await bot.answer_callback_query(query.id) await bot.answer_callback_query(query.id)
print(f"[POLLING] Callback processed successfully")
except asyncio.CancelledError: except asyncio.CancelledError:
print("[POLLING] Polling task cancelled")
break break
except Exception as e: except Exception as e:
print(f"Error in polling: {e}") print(f"[POLLING] Error in polling: {e}")
import traceback
traceback.print_exc()
await asyncio.sleep(5) await asyncio.sleep(5)
class MessageRequest(BaseModel): class MessageRequest(BaseModel):
@@ -182,14 +223,26 @@ async def log_message(chat_id: int, message: str, success: bool, error_message:
@asynccontextmanager @asynccontextmanager
async def lifespan(app: FastAPI): async def lifespan(app: FastAPI):
global db_pool, bot, polling_task global db_pool, bot, polling_task
print("[STARTUP] Initializing Telegram Bot API")
print(f"[STARTUP] DATABASE_URL: {DATABASE_URL}")
print(f"[STARTUP] CONTROLLER_API: {CONTROLLER_API}")
print(f"[STARTUP] TELEGRAM_BOT_TOKEN configured: {bool(TELEGRAM_BOT_TOKEN)}")
print(f"[STARTUP] TELEGRAM_CHAT_ID: {TELEGRAM_CHAT_ID}")
db_pool = await asyncpg.create_pool(DATABASE_URL, min_size=2, max_size=10) db_pool = await asyncpg.create_pool(DATABASE_URL, min_size=2, max_size=10)
print("[STARTUP] Database pool created")
if TELEGRAM_BOT_TOKEN: if TELEGRAM_BOT_TOKEN:
bot = Bot(token=TELEGRAM_BOT_TOKEN) bot = Bot(token=TELEGRAM_BOT_TOKEN)
print("[STARTUP] Telegram Bot initialized")
polling_task = asyncio.create_task(poll_updates()) polling_task = asyncio.create_task(poll_updates())
print("[STARTUP] Polling task created")
else:
print("[STARTUP] WARNING: TELEGRAM_BOT_TOKEN not configured!")
yield yield
print("[SHUTDOWN] Shutting down Telegram Bot API")
if polling_task: if polling_task:
polling_task.cancel() polling_task.cancel()
try: try:
@@ -198,6 +251,7 @@ async def lifespan(app: FastAPI):
pass pass
await db_pool.close() await db_pool.close()
print("[SHUTDOWN] Database pool closed")
app = FastAPI(title="Telegram Bot API", lifespan=lifespan) app = FastAPI(title="Telegram Bot API", lifespan=lifespan)