diff --git a/AI/talk_handler.py b/AI/talk_handler.py index 216a2f2..d501e33 100644 --- a/AI/talk_handler.py +++ b/AI/talk_handler.py @@ -88,12 +88,13 @@ PHOTO_EMPTY_RESPONSE_TEXT = "Дед щурился-щурился, а фотка PHOTO_ERROR_RESPONSE_TEXT = "Тьфу ты, фотку не разобрал, железка опять пердит." PHOTO_SYSTEM_PROMPT = ( - "Ты смотришь каждую новую фотографию в Telegram-чате и отвечаешь как очень злой старый дед. " - "Тон: ворчливый, колкий, немного токсичный, но не бессвязный. " - "Сначала коротко скажи, что вообще происходит на фото, потом добавь своё едкое мнение. " + "Ты смотришь каждую новую фотографию в Telegram-чате и отвечаешь как очень злой старый дед, " + "которого всё бесит и который никого не собирается гладить по голове. " + "Тон: желчный, ворчливый, ядовитый, токсичный, но связный и наблюдательный. " + "Сначала коротко скажи, что вообще происходит на фото, потом добавь своё едкое дедовское мнение. " "Пиши 1–3 предложения, без списков и без длинной простыни. " "Если фото мутное, тёмное или непонятное, так и скажи прямо, не выдумывай детали. " - "Не изображай помощника и не извиняйся." + "Не изображай помощника, не извиняйся и не сюсюкай." ) QUESTION_PREFIXES = ( @@ -648,16 +649,26 @@ async def handle_chat_message(message: Message, *, store_message: bool = True, a return True -async def _download_photo_data_url(message: Message) -> str: - if not message.photo: - raise ValueError("Message has no photo") - telegram_file = await message.bot.get_file(message.photo[-1].file_id) +async def _download_image_data_url(message: Message) -> str: + telegram_file = None + mime_type = "image/jpeg" + + if message.photo: + telegram_file = await message.bot.get_file(message.photo[-1].file_id) + guessed_mime_type = mimetypes.guess_type(telegram_file.file_path or "")[0] + if guessed_mime_type and guessed_mime_type.startswith("image/"): + mime_type = guessed_mime_type + elif message.document and (message.document.mime_type or "").startswith("image/"): + telegram_file = await message.bot.get_file(message.document.file_id) + mime_type = message.document.mime_type or mime_type + else: + raise ValueError("Message has no supported image") + buffer = BytesIO() await message.bot.download_file(telegram_file.file_path, destination=buffer) image_bytes = buffer.getvalue() if not image_bytes: raise RuntimeError("Downloaded photo is empty") - mime_type = mimetypes.guess_type(telegram_file.file_path or "")[0] or "image/jpeg" if not mime_type.startswith("image/"): mime_type = "image/jpeg" encoded = base64.b64encode(image_bytes).decode("ascii") @@ -665,7 +676,8 @@ async def _download_photo_data_url(message: Message) -> str: async def handle_photo_message(message: Message) -> bool: - if not message.photo or not message.from_user or message.from_user.is_bot: + is_image_document = bool(message.document and (message.document.mime_type or "").startswith("image/")) + if not (message.photo or is_image_document) or not message.from_user or message.from_user.is_bot: return False if message.caption and message.caption.startswith("/"): return False @@ -674,12 +686,21 @@ async def handle_photo_message(message: Message) -> bool: user_name = message.from_user.first_name or "кент" caption = _clean_text(message.caption or "") + logger.info( + "Received image message for analysis. chat_id=%s user=%s has_photo=%s has_image_document=%s caption=%s", + chat_id, + user_name, + bool(message.photo), + is_image_document, + bool(caption), + ) + await asyncio.to_thread(push_message, chat_id, "user", user_name, _photo_memory_text(caption)) async with _reply_lock: try: await message.bot.send_chat_action(chat_id=chat_id, action="typing") - image_data_url = await _download_photo_data_url(message) + image_data_url = await _download_image_data_url(message) prompt_text = ( f"{user_name} скинул фото в чат. " "Опиши, что на нём происходит, и вкинь своё злое дедовское мнение."