Bored mail or how to send messages from a site to Telegram via Node.js (Express)

logicSchema

After several letters sent from the site to my e-mail, I realized that it was rather inconvenient, not modern (maybe), at least not cool. I set out to abandon the use of smtp for forms in favor of the Telegram api.

Since my application runs on a node, I thought why not upgrade the form. The general logic is painfully simple. When submitting the form, a request is made to the api of the application, where the bot token is stored, data is processed, and then a request is made to the api telegram, which sends a message to the chat.

But let's talk about everything in order.

To start, of course, you need to create a bot that will receive data from the form and send it to you. In fact, he is just an intermediary between you and the telegram api.

So, we knock on the parent of all bots, namely @BotFather and ask him to create one for us (enter / newbot ). Enter the name, nickname and get the bot token . We just need it. Note that the bot's nickname must be < your > _bot or < Your > Bot.

@BotFather

Created, well, but it is necessary to revive it. We look for it in a search by nickname and write / start . That's it, now we can access it via api.

@BotFather

Next, you need to create a group where the bot will throw messages, do not forget to add it to the chat.

createChat


addMembers


We enter / join @ nick_bot in the created chat, because it happens that the entry about the invitation of the bot to the group is not added to the logs.

We go to the browser and enter in the address bar:

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

where XXXXXXXXXXXXXXXXXXXXXXXX is the bot token that kindly gave you @BotFather .

If everything went well, then we will get something like this sheet of letters where you need to find the “chat” object  : {"id: XXXXXXXXXX ...} . Usually the group chat id starts with a minus.

getUpdates

Well, we got the bot token and chat id where the messages will come.
Now let's get started with the application.

Front


Let's start from the front.

I used the Express wrapper for Node to work , which in turn can render files of various template engines. I decided to use Pug . It is quite easy to learn, so if you first encounter it, there will be no difficulty in getting to know it. For example, I did not use the collectors, so the scripts are connected as usual.
The structure of the application is generated using Express Generator .

Form layout


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")

Do not forget that in Pug the nesting of elements is determined by indentation , as in python, so keep this in mind.

Add styles and this is how I got it.

form

The message will be sent without reloading the page, so we hang up the handler on the form, collect the data, convert it to json and send it asynchronously to ourselves in api + display a message about the status of the request.

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


On the server side, for starters, you need to catch the request from the client side ; for this, in the router, write:

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 = [
    'Name: ' + reqBody.name,
    'Email: ' + 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: 'Произошла ошибка!'});
    }
  });
}

To simplify the request process, the ' request ' package is installed .

npm i request

config / config.json:

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

So what is going on here?


In the request, we passed json, so on the server side we can work with data as with a regular object.

For convenience, we push each value of the object into an array.
The telegram API allows you to transfer data through text in the address bar, so we go through the array and create a long line. In order to pass HTML tags, you must encode the string into a universal identifier ( encodeURI () method ) so that the error does not come out.

Now you can finally send it all to the telegram server. We make a request (click the 'Send' button) and voila, the message has been sent. Do not forget to process the answer , otherwise you never know what.

After all the manipulations, the answer comes to the front and notifies all the rules have passed or not.
Due to the fact that the collector did not use it as an example, and the pop-up library is designed for a modular assembly, I had to take a few steps when calling it at the front.

formSent

message

If you look in the application logs on the server, you can see something like the following:

image

Congratulations! Now you know how to send messages from your site to Telegram.

I described only the general concept of this process, so I strongly recommend that you familiarize yourself with the source code of this example .

Also popular now: