Библиотека: maxapi-python 2.3.1
Дата: 2026-07-09
Контекст: Продакшн-использование в коннекторе Bitrix24 Open Line (max-connector), который пересылает медиа между CRM Bitrix и мессенджером MAX.
Краткое описание
maxapi-python 2.3.1 не умеет отправлять и принимать аудиосообщения (войсы) и видеокружки. Сейчас это работает через 10+ monkey-patch'ей во время выполнения. Ниже — список проблем для нативного исправления в библиотеке.
1. UploadPayload — нет поля type
Проблема: UploadPayload содержит только поля count и profile. Сервер MAX в opcode VIDEO_UPLOAD (135) принимает параметр type для выбора типа загрузки:
| type |
Значение |
Примечание |
| 0 |
Обычное видео |
Текущее поведение по умолчанию |
| 1 |
Видеокружок |
VIDEO_MESSAGE |
| 2 |
Аудио |
Голосовое сообщение |
| 3 |
Сторис |
(не тестировалось) |
Запрос: Добавить поле type: int = 0 в UploadPayload и прокидывать его в upload_video() / upload_file().
2. upload_video() — нет параметра type
Проблема: UploadService.upload_video() отправляет VIDEO_UPLOAD без type, сервер всегда обрабатывает как обычное видео (type=0). Видеокружки (type=1) отправить нельзя.
Запрос: Добавить параметр type (или video_type) в upload_video(), чтобы вызов мог указать type=1 для кружков.
3. Загрузка аудио — нет нативной поддержки
Проблема: Нет класса AudioFile и нет способа загрузить аудио как войс. File грузится через FILE_UPLOAD, но MAX ожидает аудио через VIDEO_UPLOAD с type=2. Сервер возвращает audioId + token, а исходящее сообщение требует audio-специфичный payload.
Запрос:
- Добавить класс
AudioFile (аналог File / Video).
- Маршрутизировать аудио через
VIDEO_UPLOAD с type=2.
- Добавить
AttachAudioPayload с полями: _type=AUDIO, audioId, token, duration, wave.
- Зарегистрировать
AttachAudioPayload в SendMessagePayloadMessage.attaches, EditMessagePayload.attachments, ForwardMessagePayloadMessage.attaches через Union.
4. VideoUploadSignal — не принимает audioId
Проблема: При загрузке аудио (type=2) сервер шлёт NOTIF_ATTACH (opcode 136) с audioId вместо videoId. VideoUploadSignal принимает только videoId — событие завершения загрузки молча игнорируется, future никогда не резолвится.
Текущий воркэраунд: Патч validation_alias на AliasChoices("videoId", "audioId").
Запрос: Добавить audioId как принимаемый алиас для video_id в VideoUploadSignal, либо создать отдельную модель AudioUploadSignal.
5. resolve_attach — игнорирует события аудио-загрузки
Проблема: resolve_attach() валидирует VideoUploadSignal (ожидает videoId). Для аудио сервер шлёт audioId — валидация падает, событие игнорируется. Future загрузки никогда не завершается, возникает таймаут.
Запрос: resolve_attach должен обрабатывать audioId-payload'ы и возвращать VIDEO_READY (или новый тип события AUDIO_READY).
6. VideoRequest — поле cache обязательно, но сервер его не присылает
Проблема: client.get_video_by_id() возвращает модель VideoRequest с обязательным полем cache. Сервер иногда возвращает {'MP4_480': 'https://...'} без cache — ValidationError. Воспроизводится при скачивании видеокружков.
Запрос: Сделать cache опциональным в VideoRequest, либо обрабатывать случай, когда сервер возвращает URL напрямую в ключах без обёртки cache.
7. Класс Video — нет поля type для отличия кружка от обычного видео
Проблема: Video не имеет поля type для различения обычного видео и кружка. Сервер использует video_type=1 для кружков в VideoAttachment.
Запрос: Добавить поле video_type (или type) в Video и VideoAttachment со значениями:
0 — обычное видео
1 — видеокружок (VIDEO_MESSAGE)
8. read_message — отметка сообщений прочитанными
Проблема: Нет публичного метода для отметки входящих сообщений как прочитанных. Мы вызываем client.read_message(), который существует, но не задокументирован.
Запрос: Официально expose'нуть и задокументировать read_message(message_id, chat_id) как публичный метод API.
9. Устойчивость сессий — обработка FAIL_LOGOUT_ALL
Проблема: Когда сервер MAX инвалидирует все сессии аккаунта (ошибка login.token / FAIL_LOGOUT_ALL), Client.start() выбрасывает исключение, аккаунт остаётся отключённым. Нет callback'а или события для этого состояния — коннектор не может отличить «временная сетевая ошибка» от «сессия навсегда инвалидирована, нужен re-pairing по SMS».
Запрос: Предоставить структурированное событие или исключение для FAIL_LOGOUT_ALL, чтобы коннекторы могли запустить re-pairing (SMS-флоу) вместо слепых ретраев с мёртвым токеном.
Приоритеты
| # |
Проблема |
Критичность |
Влияние |
| 1 |
UploadPayload без type |
Высокая |
Блокирует отправку аудио+кружков |
| 2 |
upload_video без type |
Высокая |
Блокирует отправку кружков |
| 3 |
Нет загрузки аудио |
Высокая |
Блокирует отправку аудио |
| 4 |
VideoUploadSignal audioId |
Высокая |
Загрузка аудио не завершается |
| 5 |
resolve_attach игнорирует аудио |
Высокая |
Загрузка аудио не завершается |
| 6 |
VideoRequest cache обязательно |
Средняя |
Скачивание кружков падает |
| 7 |
Video без type |
Низкая |
Нельзя отличить кружок/обычное |
| 8 |
read_message не задокументирован |
Низкая |
Нет публичного API для read-receipts |
| 9 |
FAIL_LOGOUT_ALL обработка |
Средняя |
Молчаливая инвалидация сессии |
Окружение
- maxapi-python: 2.3.1
- Python: 3.12
- Сервер MAX: api.oneme.ru
Библиотека: maxapi-python 2.3.1
Дата: 2026-07-09
Контекст: Продакшн-использование в коннекторе Bitrix24 Open Line (max-connector), который пересылает медиа между CRM Bitrix и мессенджером MAX.
Краткое описание
maxapi-python 2.3.1 не умеет отправлять и принимать аудиосообщения (войсы) и видеокружки. Сейчас это работает через 10+ monkey-patch'ей во время выполнения. Ниже — список проблем для нативного исправления в библиотеке.
1.
UploadPayload— нет поляtypeПроблема:
UploadPayloadсодержит только поляcountиprofile. Сервер MAX в opcodeVIDEO_UPLOAD(135) принимает параметрtypeдля выбора типа загрузки:Запрос: Добавить поле
type: int = 0вUploadPayloadи прокидывать его вupload_video()/upload_file().2.
upload_video()— нет параметраtypeПроблема:
UploadService.upload_video()отправляетVIDEO_UPLOADбезtype, сервер всегда обрабатывает как обычное видео (type=0). Видеокружки (type=1) отправить нельзя.Запрос: Добавить параметр
type(илиvideo_type) вupload_video(), чтобы вызов мог указатьtype=1для кружков.3. Загрузка аудио — нет нативной поддержки
Проблема: Нет класса
AudioFileи нет способа загрузить аудио как войс.Fileгрузится черезFILE_UPLOAD, но MAX ожидает аудио черезVIDEO_UPLOADсtype=2. Сервер возвращаетaudioId+token, а исходящее сообщение требует audio-специфичный payload.Запрос:
AudioFile(аналогFile/Video).VIDEO_UPLOADсtype=2.AttachAudioPayloadс полями:_type=AUDIO,audioId,token,duration,wave.AttachAudioPayloadвSendMessagePayloadMessage.attaches,EditMessagePayload.attachments,ForwardMessagePayloadMessage.attachesчерез Union.4.
VideoUploadSignal— не принимаетaudioIdПроблема: При загрузке аудио (type=2) сервер шлёт
NOTIF_ATTACH(opcode 136) сaudioIdвместоvideoId.VideoUploadSignalпринимает толькоvideoId— событие завершения загрузки молча игнорируется, future никогда не резолвится.Текущий воркэраунд: Патч
validation_aliasнаAliasChoices("videoId", "audioId").Запрос: Добавить
audioIdкак принимаемый алиас дляvideo_idвVideoUploadSignal, либо создать отдельную модельAudioUploadSignal.5.
resolve_attach— игнорирует события аудио-загрузкиПроблема:
resolve_attach()валидируетVideoUploadSignal(ожидаетvideoId). Для аудио сервер шлётaudioId— валидация падает, событие игнорируется. Future загрузки никогда не завершается, возникает таймаут.Запрос:
resolve_attachдолжен обрабатыватьaudioId-payload'ы и возвращатьVIDEO_READY(или новый тип событияAUDIO_READY).6.
VideoRequest— полеcacheобязательно, но сервер его не присылаетПроблема:
client.get_video_by_id()возвращает модельVideoRequestс обязательным полемcache. Сервер иногда возвращает{'MP4_480': 'https://...'}безcache—ValidationError. Воспроизводится при скачивании видеокружков.Запрос: Сделать
cacheопциональным вVideoRequest, либо обрабатывать случай, когда сервер возвращает URL напрямую в ключах без обёрткиcache.7. Класс
Video— нет поляtypeдля отличия кружка от обычного видеоПроблема:
Videoне имеет поляtypeдля различения обычного видео и кружка. Сервер используетvideo_type=1для кружков вVideoAttachment.Запрос: Добавить поле
video_type(илиtype) вVideoиVideoAttachmentсо значениями:0— обычное видео1— видеокружок (VIDEO_MESSAGE)8.
read_message— отметка сообщений прочитаннымиПроблема: Нет публичного метода для отметки входящих сообщений как прочитанных. Мы вызываем
client.read_message(), который существует, но не задокументирован.Запрос: Официально expose'нуть и задокументировать
read_message(message_id, chat_id)как публичный метод API.9. Устойчивость сессий — обработка
FAIL_LOGOUT_ALLПроблема: Когда сервер MAX инвалидирует все сессии аккаунта (ошибка
login.token/FAIL_LOGOUT_ALL),Client.start()выбрасывает исключение, аккаунт остаётся отключённым. Нет callback'а или события для этого состояния — коннектор не может отличить «временная сетевая ошибка» от «сессия навсегда инвалидирована, нужен re-pairing по SMS».Запрос: Предоставить структурированное событие или исключение для
FAIL_LOGOUT_ALL, чтобы коннекторы могли запустить re-pairing (SMS-флоу) вместо слепых ретраев с мёртвым токеном.Приоритеты
typeОкружение