Хабрахабр

[Из песочницы] Надоевшая почта или как отправлять сообщения с сайта в Telegram через Node.js (Express)

logicSchema

После нескольких писем, отправленных с сайта себе на почту, понял что это достаточно неудобно, не современно (возможно), как минимум не прикольно. Задался целью отказаться от использования smtp для формы в пользу api Телеграма.

Так как мое приложение работает на ноде, подумал почему бы не прокачать форму. Общая логика до боли проста. При отправке формы делается запрос к api приложения, где хранится токен бота, обрабатываются данные и далее делается запрос к api телеграмма, который отправляет сообщение в чат.

Но давайте обо всем по порядку.
Для начала, естественно, необходимо создать бота, который будет получать данные из формы и отправлять вам. По сути, он является всего лишь посредником между вами и api телеграмма.

Итак, стучимся к родителю всех ботов, а именно к @BotFather и просим его создать нам одного (вводим /newbot). Вводим имя, ник и получаем токен бота. Как раз он нам и нужен. Заметьте, что ник бота должен быть <your>_bot или <Your>Bot.

@BotFather

Создали, хорошо, но надо оживить его. Ищем его в поиске по нику и пишем /start. Все, теперь можем обращаться к нему через api.

@BotFather

Далее необходимо создать группу, куда бот будет кидать сообщения, не забываем добавить его в чат.

createChat
addMembers

Вводим /join @ник_бота в созданном чате, потому что бывает, что не добавляется в логи запись о приглашении бота в группу.

Идем в браузер и в адресной строке вводим:

https://api.telegram.org/botXXXXXXXXXXXXXXXXXXXXXXX/getUpdates

где XXXXXXXXXXXXXXXXXXXXXXX — токен бота, который любезно дал вам @BotFather.

Если все прошло успешно, то получим примерно такую простыню из букв, где необходимо найти объект «chat»:{«id:XXXXXXXXXX…}. Обычно id группового чата начинается с минуса.

getUpdates

Отлично, получили токен бота и id чата, куда будут приходить сообщения.
Теперь давайте приступим к приложению.

Front

Начнем сначала с фронта.

Я использовал для работы Node обёртку Express, который в свою очередь умеет рендерить файлы различных шаблонизаторов. Решил воспользоваться Pug. Он достаточно прост в освоении, поэтому если впервые сталкиваетесь с ним, труда познакомится с ним не возникнет. Для примера не стал использовать сборщики, поэтому скрипты подключаются по старинке.
Структура приложения сгенерирована с помощью Express Generator.

Разметка формы

views/layout.pug:

doctype html
html head title= title link(rel="stylesheet", href="https://cdnjs.cloudflare.com/ajax/libs/sweetalert/1.1.3/sweetalert.min.css") link(rel='stylesheet', href='/stylesheets/style.css') body block content

views/index.pug:

extends layout block content .wrapper .wrapper__bg img.wrapper__bg-img(src='/images/bg.jpg' alt='bg') form(action="/telegram", method="post" class="form" id='telegramForm' enctype="application/x-www-form-urlencoded") .form__container .form__blur .form__title .form__title-line h3.form__title-text Связаться со мной .form__title-line .form__inputs input(type="text" name='name' placeholder="Имя" class="form__input" required) input(type="email" name='email' placeholder="Email" class="form__input" required) textarea(name="text" placeholder="Ваше сообщение" class="form__input form__message" required) .form__buttons input(type="submit" class="form__submit" value="Отправить") .form__clean Очистить script(src="https://cdnjs.cloudflare.com/ajax/libs/sweetalert/1.1.3/sweetalert.min.js") script(src="/javascripts/app.js")

Не забываем что в Pug вложенность элементов определяется отступами, как в питоне, так что учитывайте это.

Добавляем стили и вот такая форма у меня получилась.

form

Сообщение будет отправляться без перезагрузки страницы, поэтому вешаем обработчик на форму, собираем данные, преобразуем в json и отправляем их асинхронно себе в api + выводим сообщение о статусе запроса.

public/javascripts/app.js:

const formId = 'telegramForm'
const form = document.getElementById(formId)
//функция для захвата данных из тегов формы и синтеза JSON-обьекта function toJSONString(form) { var obj = {} var elements = form.querySelectorAll('input, select, textarea') for (var i = 0; i < elements.length; ++i) { var element = elements[i] var name = element.name var value = element.value if (name) { obj[ name ] = value } } return JSON.stringify(obj)
}
if (form) { form.addEventListener('submit', event => { event.preventDefault() //получаем данные из формы const json = toJSONString(form) //создаем соединение const formReq = new XMLHttpRequest() formReq.open('POST', '/telegram', true) /////////////////////////////////// /////////////SweetAlert////////// /////////////////////////////////// //обрабатываем ответ сервера formReq.onload = function(oEvent) { if (formReq.status === 200) { swal({ title: 'Успешно отправлено!', icon: 'success', timer: 2000 }) document.querySelector('.sa-success').style.display = 'block' document.querySelector('.sa-button-container').style.opacity = '0' } if (formReq.status !== 200) { swal({ title: 'Произошла ошибка!', icon: 'error', timer: 2000 }) document.querySelector('.sa-error').style.display = 'block' document.querySelector('.sa-button-container').style.opacity = '0' } } //////////////////////////// //////////////////////////// formReq.setRequestHeader('Content-Type', 'application/json') //отправляем formReq.send(json) })
}

Back

На стороне сервера для начала нужно отловить запрос со стороны клиента, для этого в роутере пишем:

routes/index.js:

//Я вынес логику обработки данных в отдельный файл
const ctrlTelegram = require('../api/telegramMsg');
router.post('/telegram', ctrlTelegram.sendMsg);

api/telegramMsg.js:

module.exports.sendMsg = (req, res) => { //токен и id чата берутся из config.json const config = require('../config/config.json'); let http = require('request') let reqBody = req.body //каждый элемент обьекта запихиваем в массив let fields = [ '<b>Name</b>: ' + reqBody.name, '<b>Email</b>: ' + reqBody.email, reqBody.text ] let msg = '' //проходимся по массиву и склеиваем все в одну строку fields.forEach(field => { msg += field + '\n' }); //кодируем результат в текст, понятный адресной строке msg = encodeURI(msg) //делаем запрос http.post(`https://api.telegram.org/bot${config.telegram.token}/sendMessage?chat_id=${config.telegram.chat}&parse_mode=html&text=${msg}`, function (error, response, body) { //не забываем обработать ответ console.log('error:', error); console.log('statusCode:', response && response.statusCode); console.log('body:', body); if(response.statusCode===200){ res.status(200).json({status: 'ok', message: 'Успешно отправлено!'}); } if(response.statusCode!==200){ res.status(400).json({status: 'error', message: 'Произошла ошибка!'}); } }); }

Для упрощения процесса запроса установлен пакет 'request'.

npm i request

config/config.json:

{ "telegram": { "token": "bot_token", "chat": "chat_id" }
}

Итак, что же здесь происходит?

В запросе мы передали json, поэтому на стороне сервера с данными можем работать как с обычным объектом.

Для удобства каждое значение объекта запихиваем в массив.
API телеграмма позволяет передать данные посредством текста в адресной строке, поэтому проходим по массиву и создаём длинную строку. Чтобы можно было передать HTML теги, необходимо закодировать строку в универсальный идентификатор (метод encodeURI()), чтобы не вылезала ошибка.

Теперь можно наконец отправить это всё на сервер телеграмма. Делаем запрос (нажимаем кнопку 'Отправить') и вуаля, сообщение отправлено. Не забываем обработать ответ, а то мало ли что.

После всех манипуляций, ответ приходит на фронт и уведомляет прошло все норм или не очень.
Из-за того, что для примера не использовал сборщик, а библиотечка всплывашки рассчитана на модульную сборку, пришлось немного поколхозить при ее вызове на фронте.

formSent

message

Если посмотреть в логи приложения на сервере, можно увидеть примерно следующее:

image

Поздравляю! Теперь вы знаете как отправлять сообщения с вашего сайта в Telegram.

Я описал только общую концепцию данного процесса, поэтому настоятельно рекомендую ознакомится с исходным кодом данного примера.

Теги
Показать больше

Похожие статьи

Кнопка «Наверх»
Закрыть