Spaces:
Runtime error
Runtime error
| # handlers.py | |
| import os | |
| import asyncio | |
| import logging | |
| from typing import List | |
| from hydrogram import Client, filters | |
| from hydrogram.types import Message | |
| from hydrogram.errors import FloodWait, RPCError | |
| from hydrogram.handlers import MessageHandler # Explicit import for add_handler | |
| from config import Config | |
| from utils import is_admin | |
| from processing import process_images_sync | |
| from main import executor # Import executor from main.py | |
| logger = logging.getLogger(__name__) | |
| async def handle_photo_message_impl(client: Client, message: Message): | |
| user = message.from_user | |
| user_id = user.id | |
| user_info = f"user_id={user_id}" + (f", username={user.username}" if user.username else "") | |
| caption = message.caption if message.caption else "" | |
| message_id = message.id | |
| chat_id = message.chat.id | |
| logger.info(f"ADMIN ACTION (Bot): Received photo with caption from {user_info} (msg_id={message_id}).") | |
| temp_user_image_path = os.path.join(Config.OUTPUT_DIR, f"bot_user_{user_id}_{message_id}.jpg") | |
| file_downloaded = False | |
| processing_status_message = None | |
| try: | |
| if not message.photo: return | |
| download_start_time = asyncio.get_running_loop().time() | |
| logger.info(f"Attempting download photo (file_id: {message.photo.file_id})...") | |
| downloaded_path = await client.download_media(message.photo.file_id, file_name=temp_user_image_path) | |
| if downloaded_path and os.path.exists(downloaded_path): | |
| download_time = asyncio.get_running_loop().time() - download_start_time | |
| logger.info(f"Photo downloaded to '{downloaded_path}' in {download_time:.2f}s.") | |
| temp_user_image_path = downloaded_path | |
| file_downloaded = True | |
| else: | |
| logger.error(f"Download failed or file not found: '{temp_user_image_path}'. Path: {downloaded_path}") | |
| await message.reply_text("β Internal error after download attempt.") | |
| return | |
| except FloodWait as e: | |
| logger.warning(f"Flood wait: {e.value}s during download (msg_id={message_id}).") | |
| await asyncio.sleep(e.value + 2) | |
| await message.reply_text(f"β³ Telegram limits hit. Wait {e.value}s & try again.") | |
| return | |
| except RPCError as e: | |
| logger.error(f"RPC error downloading photo (msg_id={message_id}): {e}", exc_info=True) | |
| await message.reply_text("β Telegram API error downloading image.") | |
| return | |
| except Exception as e: | |
| logger.error(f"Unexpected error downloading photo (msg_id={message_id}): {e}", exc_info=True) | |
| await message.reply_text("β Unexpected error downloading image.") | |
| return | |
| try: | |
| processing_status_message = await message.reply_text("β³ Processing your image...", quote=True) | |
| except Exception as e: logger.warning(f"Could not send 'Processing...' message: {e}") | |
| message_to_delete_id = processing_status_message.id if processing_status_message else None | |
| loop = asyncio.get_running_loop() | |
| generated_images: List[str] = [] | |
| processing_failed = False | |
| try: | |
| logger.info(f"Submitting image processing for '{os.path.basename(temp_user_image_path)}'") | |
| generated_images = await loop.run_in_executor( | |
| executor, process_images_sync, temp_user_image_path, caption | |
| ) | |
| except Exception as e: | |
| processing_failed = True | |
| logger.error(f"Error during image processing executor call: {e}", exc_info=True) | |
| error_message = "β Unexpected error during processing." | |
| if message_to_delete_id: | |
| try: await client.edit_message_text(chat_id, message_to_delete_id, error_message) | |
| except Exception as edit_e: logger.warning(f"Could not edit status msg: {edit_e}") | |
| message_to_delete_id = None | |
| else: await message.reply_text(error_message) | |
| if message_to_delete_id: | |
| try: await client.delete_messages(chat_id, message_to_delete_id) | |
| except Exception as del_e: logger.warning(f"Could not delete status msg: {del_e}") | |
| if not processing_failed: | |
| if not generated_images: | |
| await message.reply_text("π No styled images generated. Check templates?") | |
| else: | |
| logger.info(f"Sending {len(generated_images)} images for message {message_id}.") | |
| for i, img_path in enumerate(generated_images): | |
| if not os.path.exists(img_path): continue | |
| caption_text = f"Style {i+1}" if len(generated_images) > 1 else "πΌοΈ Styled image:" | |
| try: | |
| await message.reply_photo(photo=img_path, caption=caption_text, quote=True) | |
| except Exception as e: logger.error(f"Error sending photo '{os.path.basename(img_path)}': {e}", exc_info=True) | |
| finally: | |
| try: | |
| if os.path.exists(img_path): os.remove(img_path) | |
| except OSError as e: logger.error(f"Error deleting file '{img_path}': {e}") | |
| try: | |
| if file_downloaded and os.path.exists(temp_user_image_path): | |
| os.remove(temp_user_image_path) | |
| except OSError as e: logger.error(f"Error cleaning user image '{temp_user_image_path}': {e}") | |
| def register_handlers(app: Client): | |
| admin_photo_filter = filters.photo & filters.caption & filters.private & is_admin | |
| app.add_handler(MessageHandler(handle_photo_message_impl, filters=admin_photo_filter)) | |
| logger.info("Registered admin photo handler for bot.") | |