--- name: sms-message-builder description: Создать или адаптировать конструктор служебных SMS для SMSFlake API с вариантами текста, историей без повторов и безопасными повторными попытками. Применять для уведомлений о статусах заказов и других явно заданных событий. --- # Конструктор служебных SMS Создавай конструктор для заданных событий, а не общую рассылку. Сначала установи реальные названия статусов и обязательные данные события. Для tC8: `order_accepted`, `order_ready_for_pickup`, `order_tracking_assigned`. Присвоенный трек не означает фактическую передачу перевозчику. Для каждого события подготовь 3–5 равнозначных фраз. Номер заказа, трек, адрес и сроки берутся только из события; отсутствие обязательного поля — ошибка. Не добавляй невидимые символы, случайные опечатки или вымышленные сведения. Варианты текста служат понятности уведомлений и не гарантируют доставку. Выбирай случайный неиспользованный вариант. Храни историю идентификаторов вариантов для каждого типа события и канала; после полного цикла сбрасывай использованный набор, исключая немедленный повтор последнего варианта. Не обещай бесконечную уникальность конечного набора. Конструктор должен возвращать текст, ID варианта и новую историю без сетевых запросов. Выбор, обновление истории и сохранение текста в исходящей очереди выполняются вызывающим кодом в одной транзакции с блокировкой истории. История не содержит персональных данных. Повторная попытка использует сохранённый текст и `msg_id`; повторно конструктор не вызывается. Уникальный `msg_id` SMSFlake: 1–16 символов `A-Z a-z 0-9 _ : -`. Проверь UTF-8, обязательные поля, границы длины, полный цикл без повторов, отсутствие соседних повторов на границе циклов и параллельное сохранение истории в интеграции. SMSFlake ограничивает SMS четырьмя частями; для кириллицы считай единицы UTF-16, включая суррогатные пары. Не обрезай существенные данные молча. Для SMSFlake `POST /sms/v1/sms` текст помещается в `message`. Basic Auth: почта аккаунта и API-ключ из защищённого конфига; ключ не записывается в инструкции и логи. Успешный ответ означает постановку в очередь. При `20102` сверь сохранённый ID, не создавай новую SMS автоматически. У автоматической очереди окно 10:00–19:00 по поясу отправителя и случайные интервалы 60–180 секунд. Ручная очередь имеет приоритет и минутный интервал круглосуточно. Сохраняй ограничения тарифа и Android. Подключение нового SMS-канала обрабатывает только события после включения; старые очереди и неудачные уведомления других каналов не воспроизводятся. Эталон SMSFlake: `sdk/php/OrderMessageBuilder.php`; инструкция: `sdk/message-builder.md`. Если этих файлов нет у пользователя, создай реализацию под его язык и постоянное хранилище, сохраняя описанный контракт.