Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/open-api-docs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ openapi: 3.0.3
info:
title: The Agent's user-facing API
description: The user-facing parts of The Agent's API service (excluding system-level endpoints, chat completion, maintenance endpoints, etc.)
version: 5.33.0
version: 5.33.1
license:
name: MIT
url: https://opensource.org/licenses/MIT
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "the-agent"
version = "5.33.0"
version = "5.33.1"

[tool.setuptools]
package-dir = {"" = "src"}
Expand Down
15 changes: 10 additions & 5 deletions src/features/chat/telegram/telegram_chat_inbound_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
from util.error_codes import MEDIA_DOWNLOAD_FAILED, PLATFORM_MAPPING_FAILED
from util.errors import ExternalServiceError, InternalError

TELEGRAM_MAX_DOWNLOAD_FILE_SIZE_BYTES = 20 * 1024 * 1024


class TelegramChatInboundService:

Expand Down Expand Up @@ -65,14 +67,14 @@ def ingest_message(self, message: TelegramMessage) -> IngestedChatMessage | None
if mapped_attachments := mapper.map_attachments(message):
if stored_author is None:
raise InternalError("Telegram attachment cannot be stored without a message author", PLATFORM_MAPPING_FAILED)
stored_attachments = [
self.store_attachment(
for attachment in mapped_attachments:
stored_attachment = self.store_attachment(
mapped_data = attachment,
chat_id = stored_chat.chat_id,
uploader_user_id = stored_author.id,
)
for attachment in mapped_attachments
]
if stored_attachment:
stored_attachments.append(stored_attachment)

# finally we map, format, and store the message
mapped_message = mapper.map_message(message)
Expand Down Expand Up @@ -143,9 +145,12 @@ def store_attachment(
mapped_data: ChatAttachmentRemoteData,
chat_id: UUID,
uploader_user_id: UUID,
) -> ChatAttachment:
) -> ChatAttachment | None:
log.t(f" Storing chat message attachment: {mapped_data}")
attachment = from_remote_data_attachment(mapped_data, chat_id, uploader_user_id)
if attachment.size and attachment.size > TELEGRAM_MAX_DOWNLOAD_FILE_SIZE_BYTES:
log.w(" Skipping Telegram attachment '{attachment.external_id}' because it is too large to download: {attachment.size} bytes") # ruff: ignore[line-too-long]
return None
content = self.__di.telegram_bot_api.download_file(attachment.external_id)
if not content:
raise ExternalServiceError(f"Couldn't download Telegram file '{attachment.external_id}'", MEDIA_DOWNLOAD_FAILED)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,14 @@
from features.chat.message.chat_message import ChatMessage
from features.chat.message.chat_message_remote_data import ChatMessageRemoteData
from features.chat.telegram.model.attachment.document import Document
from features.chat.telegram.model.attachment.photo_size import PhotoSize
from features.chat.telegram.model.attachment.video import Video
from features.chat.telegram.model.chat import Chat
from features.chat.telegram.model.message import Message
from features.chat.telegram.model.text_quote import TextQuote
from features.chat.telegram.model.update import Update
from features.chat.telegram.model.user import User as TelegramUser
from features.chat.telegram.telegram_chat_inbound_service import TelegramChatInboundService
from features.chat.telegram.telegram_chat_inbound_service import TELEGRAM_MAX_DOWNLOAD_FILE_SIZE_BYTES, TelegramChatInboundService
from features.chat.telegram.telegram_domain_mapper import TelegramDomainMapper
from features.integrations.integrations import resolve_agent_user
from features.users.user import User
Expand Down Expand Up @@ -219,6 +220,38 @@ def test_ingest_message_with_video_uses_download_path_and_preserves_missing_mime
self.assertIsNone(result.attachments[0].mime_type)
self.mock_di.telegram_bot_api.download_file.assert_called_once_with("video1")

def test_ingest_message_with_oversized_photo_skips_attachment_download(self):
message = Message(
chat = Chat(id = 1, type = "private"),
message_id = 10,
date = int(datetime.now().timestamp()),
caption = "Oversized photo caption",
photo = [
PhotoSize(
file_id = "photo-too-large",
file_unique_id = "unique-photo",
width = 4096,
height = 4096,
file_size = TELEGRAM_MAX_DOWNLOAD_FILE_SIZE_BYTES + 1,
),
],
**{
"from": TelegramUser(
id = 1,
first_name = "New User",
username = "username",
is_bot = False,
),
},
)

result = self.resolver.ingest_message(message)

self.assertEqual(result.raw_message_text, "Oversized photo caption")
self.assertEqual(result.attachments, [])
self.assertEqual(result.message.text, "Oversized photo caption")
self.mock_di.telegram_bot_api.download_file.assert_not_called()

def test_ingest_message_with_reply_uses_local_attachment_id(self):
chat = self.sql.chat_config_repo().save(
ChatConfig(external_id = "1", chat_type = ChatConfigDB.ChatType.telegram),
Expand Down
Loading