Repository navigation
v1.1.4
v1.1.4 — Метаданные чатов, телефон из контакта, обновление схемы
Релиз адаптера geekcodev/laravel-max-client поверх ядра geekcodev/max-php-client: ^1.1.8. Предыдущий тег — v1.1.3.
Версия PATCH: только аддитивные изменения и исправления, за исключением двух конструкторов, перечисленных в разделе
«Изменение (BC)».
Новое
- Метаданные чатов в
max_chats: колонкиtitle,description,link,icon_url,
title_checked_at. Заполняются изgetChat()приbot_added/bot_startedи из самого апдейта при
chat_title_changed. Один ответgetChatпишется во все записи чата, поэтому в группе на 50 участников делается один
запрос, а не пятьдесят. Пустой ответ не затирает уже известное значение. MaxChatProfileService:sync(),ensureMetadata(),inheritKnownMetadata(),refresh(),
pendingChatIds(),fetch(),chatTypeFor(),activeChatIds(),forgetChatCache(),
hasKnownTitle(). Настройкиchats.fetch_metadata(MAX_CHATS_FETCH_METADATA, по умолчаниюtrue) и
chats.title_check_interval(MAX_CHATS_TITLE_CHECK_INTERVAL,0— проверять все чаты).MaxContactService: проверка целостности contact-вложения ядром (ContactVerifier) и извлечение телефона
(ContactPhoneExtractor, с v1.1.7). Входящего поляvcf_phoneв апдейтах нет, телефон разбирается изvcf_info.- Телефон в
max_users: полеphone_verified_atи сохранение номера из подтверждённого
request_contact. Отдельного флага включения нет — запись заводится, если её не было, отличающийся номер
перезаписывается (смена номера аккаунта), совпадающий обновляет только отметку проверки. Значение сохраняется как
есть, без канонизации; телефон иvcf_infoв лог не попадают. php artisan max:chats:refresh [--all|--chat=ID]: дозаполнение и перепроверка метаданных чатов.php artisan max:upgrade [--dry-run]: идемпотентная проверка и дополнение схемы реестров для
рассинхронизированных или ранее опубликованных миграций. В штатном обновлении не нужен.- Индекс по
chat_idвmax_chatsотдельной миграцией. - Additive-миграции вместо правки create-миграций:
0001_01_01_000003_add_phone_verified_at_to_max_users_table,
0001_01_01_000004_add_chat_id_index_to_max_chats_table,
0001_01_01_000005_add_chat_metadata_to_max_chats_table. Ранее выполненные create-миграции больше не правятся на
месте. Миграции загружаются провайдером (loadMigrationsFrom), публикация не требуется.
Изменение (BC)
- Ничего не удалено: сверка публичного API с тегом
v1.1.3даёт 0 удалённых методов. - Два конструктора изменились — документированное исключение из правила «в patch-релизе сигнатуры не меняются».
Сохранение прежних сигнатур потребовало бы держать вPersistMaxChatListener
зависимостьApiClient, которая больше не используется, поэтому решено оставить чистые сигнатуры и пометить классы
как внутренние:
| Класс | v1.1.3 | v1.1.4 |
|---|---|---|
Listeners\PersistMaxChatListener |
(Config, ApiClient) |
(Config, MaxChatProfileService) |
Services\MaxUserProfileService |
(ApiClient, Config, Logger) |
(ApiClient, Config, Logger, MaxChatProfileService) |
Оба класса собираются контейнером, и правка в MaxServiceProvider внесена для каждого по-своему:
MaxUserProfileService получает четвёртую зависимость в привязке register(), а
PersistMaxChatListener в привязке не участвует — он регистрируется как класс слушателя в boot(), поэтому
переопределять его нужно подменой привязки на MaxUpdateReceived, а не подменой класса. Кто собирает любой из двух
классов вручную, обязан передавать новый набор зависимостей.
- Поведение
bot_stopped/bot_removedисправлено (см. «Затронутые сценарии»), обратная совместимость не нарушена: для
апдейтов сuserповедение прежнее. Config::usersCapturePhone()не выпускался ни в одном теге, поэтому его удаление вместе с
MAX_USERS_CAPTURE_PHONEне является ломающим изменением.
Исправления
bot_removedбезuserбольше не теряется.bot_added/bot_started/bot_stopped/bot_removed— события о
боте в чате, а не о пользователе, поэтомуuserв них может отсутствовать. Прежде слушатель пропускал такой апдейт,
чат навсегда оставалсяstatus = active,activeChatIds()продолжал его возвращать, аmax:chats:refreshбесконечно
опрашивалgetChat. Теперь приuserId === nullстрока не создаётся (user_idчасть уникального ключа), но
status,last_activity_atиchat_type
обновляются во всех записях с этимchat_id.- Новая запись участника наследует метаданные чата без запроса. Проверка перед запросом отвечала на вопрос «есть ли
хоть одна заполненная строка», а заполнение шло по всем строкам сchat_id, поэтому все участники после первого
оставались без названия. Правило в три состояния: неизвестно нигде →
getChatи запись всем; часть пуста → наследование без запроса; заполнены все → ничего. Существующие значения не
затираются,title_checked_atпереносится вместе с данными. phoneне затирается вupsertUser()иMaxUserProfileService::upsertFromMember()— там перечислены явно
обновляемые поля.
Затронутые сценарии
- Обновление существующей установки: достаточно
php artisan migrate. Аддитивные миграции видны как невыполненные,
данные сохраняются.php artisan max:upgrade— страховка для рассинхронизированной или ранее опубликованной схемы,
идемпотентна. - Новая установка: публиковать миграции не нужно,
loadMigrationsFromподхватывает их из пакета. - Удаление бота из чата: чат переходит в
removedнезависимо от наличияuserв апдейте, и больше не опрашивается
max:chats:refresh. - Группа с несколькими участниками: один запрос
getChatна чат, метаданные у всех записей, включая записи
участников, пришедших позже. - Контакт в сообщении: телефон из подтверждённого
request_contactпопадает вmax_users.phone; неподтверждённое
вложение игнорируется; пересланные контакты приходят файлами и в этот путь не попадают. - Слушатели:
PersistMaxUserPhoneListenerрегистрируется всегда и независимо отchats.enabled. Приложения,
полагавшиеся на отсутствие listeners дляMaxUpdateReceived(например, на ручную постановку в очередь), учитывают это
при обновлении.
Качество
- PHP 8.4,
declare(strict_types=1), PSR-12, PHPStan level max. composer run lint— 0 файлов с правками (62 файла).vendor/bin/phpstan analyse— 0 ошибок.vendor/bin/phpunit— 298 тестов, 732 утверждения, все зелёные.composer run coverage— 98.11% строк (1041/1061), 90.97% методов, порог 95%.composer audit— 0 уязвимостей.- Guard-тесты схемы:
testCreateMigrationsStayFrozen(create-миграции не правятся),
testNewColumnsAreDeclaredInAdditiveMigrationsOnly,testChatIdIndexHasItsOwnMigration, сценарий обновления
установленной версии с сохранением данных и rollback--step 3. - Проверено сравнением публичного API с тегом
v1.1.3: удалённых методов 0.