Skip to content

Release 0.4.0

Choose a tag to compare

@batarelkin batarelkin released this 13 Sep 04:49
· 11 commits to master since this release

Релиз приводит библиотеку в соответствие с MAX Bot API: с OpenAPI-схемой
0.0.33, по которой построен сайт документации, и с тем, как на деле
отвечает боевой сервер. Добавлены комментарии к постам в каналах, новые
типы событий и живой интеграционный набор тестов.

В релизе есть изменения, ломающие совместимость как по исходному коду,
так и бинарно. Таблица замен — в разделе «Migrating to 0.4.0» README
(«Переход на 0.4.0» в README_RU).

Координаты артефактов: ru.etsft.max:max-bot-api-*:0.4.0.

ЛОМАЮЩИЕ ИЗМЕНЕНИЯ

  • Удалён GET /chats: MaxBotAPI.getChats(), GetChatsQuery и модель
    ChatList. MAX больше не поддерживает этот метод.
  • CommentRemovedUpdate: вместо объекта message событие содержит
    идентификаторы удалённого комментария: messageId, chatId, userId,
    postId. Раньше все четыре терялись.
  • OpenAppButton(text, webApp, contactId, payload): поле url удалено,
    webApp обязателен, contactId передаётся только вместе с ним. Добавлена
    фабрика ofWebApp(text, webApp). Схема допускает кнопку только с
    contact_id, но сервер её отклоняет («Field 'webApp' cannot be null»).
  • MessageButton(text): поле message удалено. Кнопка отправляет в чат
    собственный текст.
  • Message.body() может быть null: так приходит сообщение, которое только
    пересылает другое. Раньше такое сообщение не читалось, а внутри
    message_created превращало событие в UnknownUpdate.
  • ChatPatch.icon — PhotoAttachmentRequestPayload вместо Image: иконку чата
    можно задать внешним URL, токеном или загруженными photos.
  • lastActivityTime() в User, UserWithPhoto, BotInfo и ChatMember —
    Long вместо long: null, если время скрыто настройками приватности
    (раньше читался как 0).
  • VideoAttachmentDetails: поле url удалено, ссылки на варианты видео —
    в urls (новая модель VideoUrls: mp4_1080 … mp4_144, hls). Все поля,
    кроме token, nullable: пока видео обрабатывается, их может не быть.
  • ChatAdminsList содержит список ChatAdmin (userId, permissions, alias)
    вместо userIds — в формате, который принимает POST /chats/{id}/members/admins.
  • ContactAttachment.ContactPayload: tam_info заменён на maxInfo (max_info),
    добавлен hash для проверки HMAC-SHA256(access_token, vcf_info).
  • Новые компоненты record, меняющие их конструкторы:
    MarkupElement — url, userLink, userId (ссылки и упоминания);
    DialogClearedUpdate, DialogUnmutedUpdate, DialogRemovedUpdate,
    BotStoppedUpdate — userLocale; DialogMutedUpdate — mutedUntil и
    userLocale; MessageRemovedUpdate — postId; Subscription — time;
    AudioAttachment — transcription; ChatPatch — description;
    AddMembersResult — message; ChatMember — alias; MessageRecipient —
    postId и userId; UserWithPhoto — firstName и lastName.
  • name и firstName у пользователей теперь nullable: документация называет
    name устаревшим, но её собственный пример GET /me возвращает name без
    first_name.
  • MaxWebhookServer.register() и unregister() выбрасывают
    IllegalStateException, если MAX отвечает HTTP 200 с success=false.
    Раньше отказ игнорировался и в лог писалась успешная регистрация.

НОВОЕ

  • Комментарии к постам в каналах: getComments, getCommentById,
    sendComment, editComment, deleteComment и модели CommentMessage,
    CommentMessageBody, CommentLinkedMessage, NewCommentBody, CommentList,
    SendCommentResult.
  • Типы событий dialog_cleared, dialog_muted, dialog_unmuted,
    dialog_removed, comment_created, comment_edited, comment_removed —
    классы событий и значения UpdateType. Раньше на них нельзя было
    подписаться, а пришедшие события становились UnknownUpdate.
  • PATCH /me/commands — управление командами бота.
  • Кнопка clipboard (ClipboardButton).
  • Параметр disable_link_preview в POST /answers.
  • Webhook: асинхронная обработка по флагу —
    MaxWebhookServer.Builder.dispatchExecutor(...) и в Spring Boot
    max.bot.webhook.async-dispatch=true. Ответ 200 уходит сразу, обработчик
    выполняется после, поэтому долгая обработка не превышает 30 секунд,
    отведённых MAX на ответ. По умолчанию поведение прежнее.
  • ChatPermission снова распознаёт старые названия прав (edit_message,
    delete_message, post_edit_delete_message), которыми MAX всё ещё
    отвечает; canonical() сводит старое название к новому.
  • Живой интеграционный набор max-bot-api-integration-tests: вызывает
    методы MaxBotAPI с настоящим токеном и падает, если ответ не удаётся
    представить моделями. Запускается только вручную:
    ./gradlew :max-bot-api-integration-tests:liveTest.

ИСПРАВЛЕНИЯ

  • Одно некорректное событие больше не срывает разбор всего UpdateList.
    Раньше маркер long polling не продвигался, сервер повторял ту же
    пачку, и бот переставал получать события. Теперь неразборчивые
    события, вложения и кнопки превращаются в UnknownUpdate,
    UnknownAttachment и UnknownButton с исходным JSON, а
    MaxLongPollingConsumer предупреждает после трёх ошибок подряд.
  • Ошибка attachment.not.ready распознаётся: сервер отвечает HTTP 400 с
    кодом через точки, а не 409. Код ошибки теперь виден в сообщении
    MaxApiException.
  • getVideoAttachmentDetails больше не падает на реальных ответах сервера.
  • postAdmins отправляет тело, которое принимает API; раньше запрос всегда
    отклонялся.
  • getChatByLink принимает @name, name, max.ru/name и
    https://max.ru/name.
    Ссылку-приглашение отклоняет сразу, без запроса.
  • GET /subscriptions не падает с NullPointerException, если подписка
    содержит неизвестный библиотеке тип события.
  • Spring-регистратор webhook при success=false пишет в лог ошибку, а не
    сообщение об успешной регистрации.
  • Примеры не падают на постах канала без sender и на сообщениях без body.

УСТАРЕВШЕЕ (@deprecated, будет удалено)

  • POST /chats/{chatId}/members (AddMembersQuery): MAX ограничил метод с
    9 сентября 2026 года и удаляет его 30 сентября 2026 года.
  • Наследие TamTam, которого нет в документации MAX: PATCH /me
    (EditMyInfoQuery, замена — PATCH /me/commands), DELETE /chats/{chatId}
    (боту отказано: нужно владение чатом), GET /chats/{chatLink}, параметр
    user_id в GET /messages, кнопка chat, SenderAction.MARK_SEEN,
    ChatStatus.SUSPENDED, события message_construction_request,
    message_constructed и message_chat_created вместе с их UpdateType,
    Message.constructor.

ДОКУМЕНТАЦИЯ

  • README и README_RU: работа с комментариями и командами бота, таблица
    всех типов событий, срок ответа webhook (30 секунд), политика повторов
    и async-dispatch, лимит MAX в 2 операции в секунду на один чат, раздел
    о переходе на 0.4.0. Исправлен пример MaxWebhookServer, который
    вызывал несуществующий метод api(...).

ПРОВЕРКА

  • ./gradlew build: модульные тесты, Checkstyle, SpotBugs — без ошибок.
  • liveTest против боевого MAX API: 52 теста, 0 падений. Пропуски
    вызваны окружением: webhookRoundTrip — не задан MAX_IT_WEBHOOK_URL
    (в предыдущем прогоне этого дня проходил), deleteChat — MAX отказывает
    боту, getChatByLink — в конфигурации ссылка-приглашение.