Клиент исправил сообщение Telegram: как обновить заметку в CRM
Политика исправлений Telegram-сообщений в CRM: владение полями, конфликт версий, неизвестный исходник и проверка на искусственных данных.
Если клиент исправил сообщение в Telegram, не создавайте из исправления новый лид и не заменяйте всю карточку. Найдите запись исходного сообщения, сравните значимые данные и обновите только те поля, которыми владеет интеграция. Если запись не найдена, версии спорят или менеджер уже изменил целевую заметку, сохраните исправление как отдельную задачу на сверку. Время получения запроса не доказывает, что его текст новее.
Разбор предназначен для разработчика собственной интеграции Telegram Bot API с CRM. Предполагается разрешённое получение обращений, постоянное хранилище и изолированная тестовая среда. Это проектная политика, а не подтверждённая функция 24go.site и не готовая настройка для конкретной CRM. Ниже рассматриваются обычные message и edited_message; события каналов, business-сообщения, guest-форматы и удаление требуют отдельного контракта. Рабочие токены для локальной проверки не нужны.
Исправление сообщения не равно повтору доставки
В объекте Update поле edited_message обозначает новую версию известного боту сообщения, которое отредактировали. Документация предупреждает: событие иногда вызывают изменения полей, недоступных или не используемых ботом. Поэтому сам факт прихода такого обновления не означает, что нужно изменить видимую заметку или повторно квалифицировать клиента.
Повтор одного обновления и исправление исходного сообщения решают разные задачи. Дедупликация по ключу события не должна отбросить другое обновление только потому, что оно относится к прежнему сообщению. И наоборот, новое обновление с тем же содержимым не требует второй заметки. Для повторов доставки и неоднозначного создания записи используйте отдельную схему идемпотентности вебхука. Здесь задача начинается после связи источника с уже существующим объектом CRM.
Сначала согласуйте с владельцем продаж смысл исправления. Замена «нужно пять лицензий» на «нужно три» может уточнять обращение, но сама по себе не разрешает менять утверждённую сумму сделки. Исправление опечатки не должно заново отправлять письмо или открывать задачу менеджеру. Решение о бизнес-действии принадлежит вашему процессу, а не имени поля Telegram.
Дайте исходному сообщению собственный ключ
Храните отдельно ключ события и ключ сообщения. Для события нужен ваш контекст источника и update_id; для обычного сообщения предложен составной ключ из tenant, бота, chat.id и message_id. Tenant здесь обозначает организацию внутри вашей системы, а не поле Telegram. Дополнительные компоненты не дают двум клиентам интегратора случайно разделить одну запись.
В описании Message message_id уникален внутри чата. Одного этого числа для всей базы недостаточно. Имя пользователя, подпись отправителя и текст обращения также не подходят для поиска исходной заметки: они могут совпадать или меняться. Не пытайтесь при отсутствии связи подобрать похожую сделку по нескольким словам и молча записать исправление туда.
Поддерживайте явное соответствие: ключ сообщения → внутренний ID исходной записи → ID целевой заметки CRM. Рядом храните поддерживаемый тип сообщения, версию преобразователя, принятую проекцию и состояние доставки. Проекция означает выбранные данные, из которых вы строите заметку: например, текст с относящейся к нему разметкой либо подпись с её метаданными. Это прикладная схема, которую надо определить и версионировать.
Если идентичность входа не укладывается в поддерживаемую обычную схему, остановите автоматическую замену. Специальные идентификаторы и новые форматы API нельзя принимать только потому, что JSON содержит знакомое поле. Направьте такой вход на отдельную обработку. Эта инструкция не является универсальным декодером всех форматов Telegram.
Сравнивайте содержимое и время источника раздельно
У Message есть необязательное поле edit_date: время последнего редактирования в Unix time. Оно полезно для сравнения редакций одного поддерживаемого сообщения, но не является полной историей правок. Не подменяйте его временем приёма HTTP-запроса или окончания задания: медленный воркер может завершить старую работу после новой.
Предложенная консервативная политика использует несколько исходов. Если выбранные данные совпадают с текущими, видимую заметку менять не надо. Однако более позднее допустимое время источника стоит сохранить как границу уже наблюдавшихся версий. Иначе последующее запоздавшее изменение может выглядеть новым относительно старого маркера. Метаданные наблюдения и содержимое заметки имеют разные причины обновления.
Если содержимое отличается, а время источника строго позже принятого, это кандидат на исправление. Если время раньше, не заменяйте текущую проекцию. Если времена равны, а данные различаются, фиксируйте конфликт вместо выбора по очередности прихода. Такой консервативный режим иногда потребует ручного решения, но не выдаёт предположение за доказанный порядок. При отсутствующем или некорректном edit_date для исправления тоже нужна сверка.
update_id сохраняйте для дедупликации и расследования, но не объявляйте вечным счётчиком редакций сообщения. Документация Update допускает случайный выбор следующего идентификатора после как минимум недели без новых обновлений. Его описание помогает восстанавливать последовательность обновлений, но не заменяет ваш контракт разрешения конфликтов и владения полями. Не придумывайте отсутствующий точный номер правки.
Выберите, кто владеет полями CRM
Перед автоматизацией составьте таблицу владельцев. Для каждого поля укажите источник, разрешённое действие и способ обнаружить изменение оператором. Заметка с исходным текстом, стадия сделки и подтверждённый телефон не должны случайно получить одно общее правило «последнее событие побеждает».
| Целевые данные | Предложенный владелец | Действие при исправлении |
|---|---|---|
| Отдельная заметка-копия обращения | Интеграция при подтверждённом эксклюзивном владении | Заменить только эту заметку после проверки версии |
| Заметка, которую вправе править менеджер | Совместное владение | Сверить целевую версию; при конфликте добавить связанную коррекцию или задачу |
| Стадия и ответственный | Согласованный процесс продаж | Не менять только из-за edited_message |
| Подтверждённые реквизиты контакта | Отдельный процесс проверки | Не переносить автоматически произвольную новую строку |
| История технической обработки | Интеграция | Записать исход и связь с исправлением в рамках срока хранения |
Не превращайте историю в бесконтрольный архив. Сроки хранения исходников и доступ к ним задаются отдельно с учётом ваших оснований обработки данных. Скрытое копирование всех старых текстов в журналы не становится допустимым из-за удобства расследования. Для общей телеметрии обычно достаточно внутренних ключей, исхода и версии адаптера, а не полного обращения.
Что делать, если исправление пришло раньше исходной записи
Неизвестный исходник не доказывает, что клиент отправил новое обращение. Первичное задание могло задержаться, связь с CRM ещё не сохранена, событие могло попасть в систему до начала наблюдения. Сохраните исправление в состоянии ожидания связи и проверьте локальную очередь и журнал соответствий. Не создавайте новый лид по умолчанию.
Назначьте срок и ответственного за такую сверку. После появления исходной записи обработайте сохранённое исправление по тем же правилам версии, а не просто повторите первоначальную команду на запись. Если связь так и не найдена, оператор должен видеть нерешённый исход, а не зелёную отметку синхронизации. Повторяющиеся неизвестные исходники могут указывать на проблему маршрутизации или хранения.
Не обещайте восстановить всю историю сообщений через эту схему. Исправление представляет наблюдаемую версию, а не журнал всех изменений. Отсутствие очередного события не доказывает, что пользователь ничего не исправлял. Равным образом обычное edited_message не является уведомлением об удалении: отсутствие текста в неподдерживаемом формате нельзя превращать в команду стереть заметку.
Применяйте исправление по этапам
- В существующем проверенном приёмнике сохраните обновление и его тип. Аутентификация вебхука и подтверждение после надёжного сохранения остаются обязательными, но здесь не проектируются заново. Диспетчер должен явно различать новое и отредактированное сообщение.
- Найдите исходный ключ и связь с заметкой. Проверьте организацию, бота и чат; не доверяйте переданному клиентом ID чужой сделки. Если исходник неизвестен, создайте задачу сверки без удалённой замены.
- Постройте проекцию поддерживаемого тела вместе с его метаданными. Отсутствующее поле в неподдерживаемом сообщении не означает пустую строку. Сравнивайте и значимые адреса ссылок, если они входят в заметку, а не только видимые подписи.
- В одной локальной транзакции выберите исход по текущей принятой версии и сохраните намерение операции. Нужен атомарный захват или проверка версии записи, иначе два воркера могут одновременно принять несовместимые решения. Отдельная проверка в памяти этого не обеспечивает.
- Для кандидата на доставку примените политику владельца поля и возможности CRM. Непосредственно перед записью повторно проверьте, что операция не устарела локально; используйте документированную условную запись, когда она доступна. Локальная транзакция не блокирует редактирование удалённой заметки менеджером.
- Перечитайте целевую запись и сверьте ожидаемые данные. При таймауте с неизвестным исходом сохраните состояние сверки, не генерируйте новый ключ и не повторяйте замену вслепую. После подтверждения свяжите результат с конкретной версией источника.
Проверьте политику до подключения CRM
Для воспроизводимой локальной проверки достаточно искусственных идентификаторов, текстов и времён. Реализуйте чистую функцию решения без сети: на входе известность исходника, время принятой версии, её проекция, время кандидата и его проекция. Выходы должны различать отсутствие изменения, устаревший вход, кандидат на доставку и необходимость сверки. Отдельно проверяйте обновление временной границы при совпадающем содержимом; решение «не писать заметку» не равно «забыть наблюдение».
| Искусственный сценарий | Ожидаемое решение |
|---|---|
| Известный исходник, новая дата и другой текст | Кандидат на доставку, не новый лид |
| Более старая дата и другой текст | Не заменять текущую версию |
| Одинаковая дата и разные проекции | Сверка конфликта |
| Более новая дата, та же проекция | Не писать заметку, продвинуть границу наблюдения |
| Нет связи с исходником | Ожидание связи, без нового лида |
| Нет допустимого времени правки | Сверка, без автоматической замены |
В тестовой среде сначала создайте одно разрешённое обращение и зафиксируйте ID его заметки. Исправьте текст без изменения смысла, затем измените существенное условие. Убедитесь, что сохраняется связь с тем же источником, не появляется новая сделка, а автоматические действия соответствуют утверждённой политике. После ручной правки менеджером повторите исправление и проверьте конфликт, а не только HTTP-ответ.
Завершайте внедрение точным результатом: какие исходы проверены локально, какие подтверждены чтением CRM и что остаётся на ручной сверке. Отслеживайте возраст нерешённых исправлений и причины конфликтов. Исправленный текст обращения должен быть доступен оператору без молчаливой потери его собственной работы; именно это нужно доказать перед включением автоматической замены.
Источники
- Telegram Bot API: Update: edited_message, особенности update_id и границы событий; проверено в редакционную дату.
- Telegram Bot API: Message: идентичность сообщения, edit_date, текст и подписи; проверено в редакционную дату.