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.") | |