Skip to content

ValidationError: get_chats() падает на закреплённом пересланном сообщении (LinkedMessage.message обязателен при type="forward") #159

@iamptic

Description

@iamptic

Описание

bot.get_chats() (и любой парсинг ответа GET /chats через модель Chats) падает с ValidationError, если хотя бы в одном чате закреплено пересланное сообщение.

Для пересланного закрепа API MAX возвращает pinned_message.link с type: "forward" и без поля message (поле message присутствует только у reply-линков, у forward его в payload нет). Однако в модели LinkedMessage поле message объявлено обязательным:

# maxapi/types/message.py
class LinkedMessage(BaseModel):
    type: MessageLinkType
    sender: User | None = None
    chat_id: int | None = None
    message: MessageBody          # <-- required, падает на type="forward"

Так как Chats валидирует всю страницу атомарно (chats: list[Chat]), один «отравленный» чат рушит весь ответ get_chats() — список чатов становится пустым у бота, даже если он админ во всех чатах. На проде это привело к тому, что у пользователей пропал список их чатов.

Точный текст ошибки

1 validation error for Chats
chats.0.pinned_message.link.message
  Field required [type=missing, input_value={'type': 'forward', 'chat_id': ...}, input_type=dict]
    For further information visit https://errors.pydantic.dev/2.x/v/missing

Минимальный repro

from maxapi.types.chats import Chats

payload = {
  "chats": [
    {
      "chat_id": 70000000000001,
      "type": "chat",
      "status": "active",
      "title": "Test chat",
      "last_event_time": 1700000000000,
      "participants_count": 3,
      "is_public": False,
      "pinned_message": {
        "recipient": {"chat_id": 70000000000001, "chat_type": "chat"},
        "timestamp": 1700000000000,
        "link": {
          "type": "forward",
          "chat_id": 70000000000002
          # поля "message" нет — так приходит для пересланного закрепа
        },
        "body": {"mid": "mid1", "seq": 1, "text": "forwarded"}
      }
    }
  ],
  "marker": None
}

Chats.model_validate(payload)   # -> ValidationError: ...link.message Field required

Затронутые версии

Воспроизводится на 0.9.16 и на актуальной 1.1.0 (проверено в чистом venv, Python 3.12, pydantic 2.x). В обеих LinkedMessage.message остаётся обязательным.

Предлагаемое исправление

Сделать message необязательным, по аналогии с уже исправленным sender (#11):

class LinkedMessage(BaseModel):
    type: MessageLinkType
    sender: User | None = None
    chat_id: int | None = None
    message: MessageBody | None = None   # forward-линк приходит без message

Места, использующие self.link.message.mid (например Message.edit()), стоит защитить проверкой на None.

См. также #11 — там аналогичная проблема с link.sender.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions