https://habrahabr.ru/post/348332/- Программирование
- Node.JS
- JavaScript
- Ajax
- API
После нескольких писем, отправленных с сайта себе на почту, понял что это достаточно неудобно, не современно (возможно), как минимум не прикольно. Задался целью отказаться от использования smtp для формы в пользу api Телеграма.
Так как мое приложение работает на ноде, подумал почему бы не прокачать форму. Общая логика до боли проста. При отправке формы делается запрос к api приложения, где хранится токен бота, обрабатываются данные и далее делается запрос к api телеграмма, который отправляет сообщение в чат.
Но давайте обо всем по порядку.
Для начала, естественно, необходимо создать бота, который будет получать данные из формы и отправлять вам. По сути, он является всего лишь
посредником между вами и api телеграмма.
Итак, стучимся к родителю всех ботов, а именно к
@BotFather и просим его создать нам одного (вводим
/newbot). Вводим имя, ник и
получаем токен бота. Как раз он нам и нужен. Заметьте, что ник бота должен быть <
your>_bot или <
Your>Bot.
Создали, хорошо, но надо оживить его. Ищем его в поиске по нику и пишем
/start. Все, теперь можем обращаться к нему через api.
Далее необходимо создать группу, куда бот будет кидать сообщения, не забываем
добавить его в чат.
Вводим
/join @
ник_бота в созданном чате, потому что бывает, что не добавляется в логи запись о приглашении бота в группу.
Идем в браузер и в адресной строке вводим:
https://api.telegram.org/botXXXXXXXXXXXXXXXXXXXXXXX/getUpdates
где
XXXXXXXXXXXXXXXXXXXXXXX — токен бота, который любезно дал вам
@BotFather.
Если все прошло успешно, то получим примерно такую простыню из букв, где необходимо найти объект
«chat»:{«id:XXXXXXXXXX…}. Обычно id группового чата начинается с минуса.

Отлично, получили
токен бота и
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 вложенность элементов определяется отступами, как в питоне, так что учитывайте это.
Добавляем стили и вот такая форма у меня получилась.
Сообщение будет отправляться без перезагрузки страницы, поэтому вешаем обработчик на форму, собираем данные, преобразуем в 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()), чтобы не вылезала ошибка.
Теперь можно наконец отправить это всё на сервер телеграмма. Делаем
запрос (нажимаем кнопку 'Отправить') и вуаля, сообщение отправлено.
Не забываем обработать ответ, а то мало ли что.
После всех манипуляций, ответ приходит на фронт и уведомляет прошло все норм или не очень.
Из-за того, что для примера не использовал сборщик, а библиотечка всплывашки рассчитана на модульную сборку, пришлось немного поколхозить при ее вызове на фронте.
Если посмотреть в логи приложения на сервере, можно увидеть примерно следующее:
Поздравляю! Теперь вы знаете как отправлять сообщения с вашего сайта в Telegram.
Я описал только общую концепцию данного процесса, поэтому настоятельно рекомендую ознакомится с исходным кодом данного примера.