Храните условия рядом с карточкой
Сохраните id, название, категорию, допустимый источник, ссылку, статус и дату проверки. Включайте предложение в выдачу, только если программа разрешает Telegram и карточка подходит выбранной задаче. Не подставляйте ссылку из сообщения пользователя. Используйте свой список и проверяйте, что адрес ведёт к ожидаемому домену.
У сценария три шага. Пользователь запускает бота, выбирает категорию, получает одну или две карточки. На карточке поясните, кому подходит предложение и что делать дальше. Если подходящих предложений нет, покажите сообщение и кнопку возврата. Не собирайте номер телефона для простой фильтрации, когда можно обойтись выбором категории.
Отправьте карточку с кнопкой
async function sendOffer(chatId, offer) {
const token = process.env.TELEGRAM_BOT_TOKEN;
const url = new URL(offer.url);
if (!token || url.protocol !== 'https:' || url.hostname !== 'merchant.example') {
throw new Error('Проверьте настройки бота или адрес оффера');
}
const res = await fetch(`https://api.telegram.org/bot${token}/sendMessage`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
chat_id: chatId,
text: `${offer.title}\nПартнёрская ссылка. Условия проверьте на сайте.`,
reply_markup: { inline_keyboard: [[{ text: 'Открыть условия', url: url.href }]] },
}),
});
if (!res.ok || !(await res.json()).ok) throw new Error('Telegram не принял сообщение');
}
Это фрагмент серверного кода. Передайте ID тестового чата из проверенного события бота и разрешённую карточку. Замените домен примера допустимым доменом. Поля sendMessage и клавиатуры описаны в Telegram Bot API. Токен храните вне исходников и журналов. При работе с webhook проверяйте секрет и источник запроса по инструкции Telegram.
Проверьте от выбора до отчёта
В тестовом чате откройте кнопку, проверьте конечный сайт, вернитесь и выберите другую категорию. Отключите оффер в наборе и убедитесь, что бот его больше не показывает. Не считайте отправленное сообщение кликом: для измерения используйте разрешённую метку партнёрской ссылки или собственный способ учёта, который не собирает лишние данные. После обновления каталога повторите проверку устаревших кнопок.
В реестре полезно сохранить версию карточки. Если предложение закрыто, старые сообщения могут остаться у подписчиков. Подготовьте способ обработки устаревшего выбора: не повторяйте отправку карточки, покажите текущие варианты и дайте вернуться в меню. Если выдача стала пустой, это должно выглядеть как понятный ответ, а не как ошибка или обещание результата.
Если отправка не удалась, сохраните только безопасный технический статус без URL запроса, потому что в адресе Bot API находится токен. При повторной доставке одного обновления храните его ID, если приложение запускает обработчик повторно. Так бот не будет присылать одну карточку несколько раз.