Write a Telegram Bot from scratch

Posted by WebGeek182 on Fri, 10 May 2019 04:54:04 +0200

Telegram offers a wealth of API Let's develop a bot robot very conveniently. At the same time, Community The underlying API has also been encapsulated in various languages, so this paper uses node-telegram-bot-api To implement bot quickly

Note: Due to the domestic network, Telegram bot needs to open the ladder and choose the global agent mode!!!

Create a new Bot

Search on Telegram Client @BotFather Then follow the steps to create your own bot. After successful creation, BotFather will return you a Token:

For example, I created a bot called Hetai 5_bot. Now on the client side, we @hetai 5_bot has any conversation, and the bot will not respond:

We need to write logic locally to respond to user input

Interactive implementation

Create a new project folder mkdir bot, NPM init-y, and install the dependency npm i node-telegram-bot-api

Create a new index.js

const TelegramBot = require('node-telegram-bot-api');

const token = 'Fill in yours. token';
const bot = new TelegramBot(token, {
  polling: true
});



bot.onText(/\/hentai/, function onLoveText(msg) {
  bot.sendMessage(msg.chat.id, 'Are you a hetai?');
});


bot.onText(/\/echo (.+)/, (msg, match) => {

  const chatId = msg.chat.id;
  const resp = match[1];
  bot.sendMessage(chatId, resp);
});

Then node index.js starts the file, so is it successful?

Unfortunately, if you are developing in China, there is no egg use. Although we have opened the ss(ssr) ladder all the way, ss is different from vpn. ss does not represent all the networks of computers even if it has opened the global mode. By default, browsers will automatically go to the ss proxy server, but other software will not go to the ss proxy by default, so we can't connect to Telegram successfully when node index.js starts the program.

So we need to add proxy manually in the code, go to ss proxy server!

npm i socks5-https-client

Modify the code:

const TelegramBot = require('node-telegram-bot-api');
const Agent = require('socks5-https-client/lib/Agent');

const token = 'Fill in yours. token';
const bot = new TelegramBot(token, {
  polling: true,
  request: { // Setting agent
    agentClass: Agent,
    agentOptions: {
      socksPassword: 'Fill in the password when you climb the ladder'
    }
  }
});

// Matching/hentai
bot.onText(/\/hentai/, function onLoveText(msg) {
  bot.sendMessage(msg.chat.id, 'Are you a hetai?');
});


// Match /echo
bot.onText(/\/echo (.+)/, (msg, match) => {

  const chatId = msg.chat.id;
  const resp = match[1];
  bot.sendMessage(chatId, resp);
});

Dialogue with bot again this time, and the dialog function has been realized!

Of course, we can add some functions, such as user input / prpr pr, from the Internet to find a picture to send users
npm i request

const TelegramBot = require('node-telegram-bot-api');
const Agent = require('socks5-https-client/lib/Agent');
const request = require('request');

const token = 'Fill in yours. token';
const bot = new TelegramBot(token, {
  polling: true,
  request: { // Setting agent
    agentClass: Agent,
    agentOptions: {
      socksPassword: 'Fill in the password when you climb the ladder'
    }
  }
});


bot.onText(/\/hentai/, function onLoveText(msg) {
  bot.sendMessage(msg.chat.id, 'Are you a hetai?');
});

bot.onText(/\/prpr/, function onLoveText(msg) {
  const chatId = msg.chat.id;
  request('https://konachan.com/post.json?tags=ass&limit=50', function (error, response, body) {
    if (!error && response.statusCode == 200) {
      const result = JSON.parse(body) || [];
      const index = parseInt(Math.random() * result.length);
      bot.sendPhoto(chatId, result[index].file_url, { caption: 'Hand flushing for a while, hand flushing for a long time, hand flushing for a long time, hand flushing for a long time, hand flushing for a long time, hand flushing for a long time, hand flushing for a long time.' }).catch((err) => {
        bot.sendMessage(chatId, 'Hand punching failure');
      })
    } else {
      bot.sendMessage(chatId, 'Hand punching failure');
    }
  });
});


bot.onText(/\/echo (.+)/, (msg, match) => {

  const chatId = msg.chat.id;
  const resp = match[1];
  bot.sendMessage(chatId, resp);
});

polling VS webhook

How do we develop bot s to know what commands users send?

Telegram bot has two ways to get commands from users. One is polling mode, which is polling. Our bot needs to send requests to the Telegram server at regular intervals to ask what commands the user has recently sent. The advantage of this approach is that it is easy to debug locally, which is what we just used in our code. The disadvantage is that requests are sent on their own initiative at regular intervals, even though no user may have sent commands recently.

Another model is webhook. We need to set a webhook address for bot, such as https://hentai.com/bot123. This way, every time a user enters a command into a bot, Telegram forwards the command to https://hentai.com/bot123, so we need to deploy our BOT at https://hentai.com/bot123. The advantage of this mode is that it can respond to user's commands in time. The disadvantage is that it is difficult to debug locally, and it may need ngrock as an intranet penetration tool. At the same time, when deploying online, we also need to have our own domain name and support https!!!

Online deployment

First of all, we need to have a foreign server: recommend buying VPS on bricklayers or vultr. At the same time, you need some basic knowledge of linux. If you don't know it at all, I recommend that you read an article I wrote before. Basic knowledge of linux deployment written to front-end Xiaobai

I bought vultr's VPS(/mo package) and installed the operating system centos 7 X64.

Because we use foreign servers, the http proxy in the code can be removed:

const TelegramBot = require('node-telegram-bot-api');
const request = require('request');

const token = 'Your token';
const bot = new TelegramBot(token, {
  polling: true
});

bot.onText(/\/hentai/, function onLoveText(msg) {
  bot.sendMessage(msg.chat.id, 'Are you a hetai?');
});

bot.onText(/\/prpr/, function onLoveText(msg) {
  const chatId = msg.chat.id;
  request('https://konachan.com/post.json?tags=ass&limit=50', function (error, response, body) {
    if (!error && response.statusCode == 200) {
      const result = JSON.parse(body) || [];
      const index = parseInt(Math.random() * result.length);
      bot.sendPhoto(chatId, result[index].file_url, { caption: 'Hand flushing for a while, hand flushing for a long time, hand flushing for a long time, hand flushing for a long time, hand flushing for a long time, hand flushing for a long time, hand flushing for a long time.' }).catch((err) => {
        bot.sendMessage(chatId, 'Hand punching failure');
      })
    } else {
      bot.sendMessage(chatId, 'Hand punching failure');
    }
  });
});

bot.onText(/\/echo (.+)/, (msg, match) => {
  const chatId = msg.chat.id;
  const resp = match[1];
  bot.sendMessage(chatId, resp);
});

Install basic components, nvm,node,pm2

yum -y install gcc gcc-c++ autoconf pcre-devel make automake
yum -y install wget httpd-tools vim
curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.34.0/install.sh | bash
nvm install 11.0.0
npm i pm2 -g

After uploading the local project to the server, run PM2 start index. JS -- name box directly.

Domain name support https

As we said earlier, the downside of polling mode is that it wastes resources and fails to respond to user requests in a timely manner.

In webhook mode, deployment is cumbersome. If you don't want to use this method, you can ignore the following

The premise of using webhook is that we have a custom domain name and need to point the domain name to our vps.

pic

As shown in the figure, I point a subdomain name hentai.urusai.site to my current vps IP address.

Install nginx

vim /etc/yum.repos.d/nginx.repo

Write in:

[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/centos/7/$basearch/
gpgcheck=0
enabled=1

:wq!Save exit

yum install nginx

This installs the latest version of nginx

Set firewall rules:

firewall-cmd --add-service=http
firewall-cmd --add-service=https
firewall-cmd --runtime-to-permanent

Modify nginx configuration:

vim /etc/nginx/conf.d/default.conf

Change server_name localhost to the domain name hentai.urusai.site

When finished, open nginx:

nginx -s reload

When the browser enters http://hentai.urusai.site, there should be a nginx welcome page

Now we need to support https:

Install certbot

yum install epel-release
yum install certbot-nginx

Get the SSL certificate

certbot --nginx

After successful completion, we can call https://hentai.urusai.site and request normally!

Setting Certificate Automatic Renewal
Certificates issued by certbot are only valid for three months by default, so we can set an automatic renewal period.
Work at 5:15 a.m.

crontab -e

input

15 5 * * * certbot renew --quiet

nginx configuration webhook

When Telegram bot uses the webhook pattern, we need to modify the existing code:

npm i express body-parser
const TelegramBot = require('node-telegram-bot-api');
const express = require('express');
const bodyParser = require('body-parser');
const request = require('request');

const TOKEN = 'Your token';
const url = 'https://hentai.urusai.site'; //your own domain name
const port = 9000;

const bot = new TelegramBot(TOKEN);
bot.setWebHook(`${url}/bot${TOKEN}`);
const app = express();
app.use(bodyParser.json());

app.get('/', (req, res) => res.send('Hello World!'));

app.post(`/bot${TOKEN}`, (req, res) => {
  bot.processUpdate(req.body);
  res.sendStatus(200);
});

app.listen(port, () => {
  console.log(`Express server is listening on ${port}`);
});


bot.onText(/\/hentai/, function onLoveText(msg) {
  bot.sendMessage(msg.chat.id, 'Are you a hetai?');
});

bot.onText(/\/prpr/, function onLoveText(msg) {
  const chatId = msg.chat.id;
  request('https://konachan.com/post.json?tags=ass&limit=50', function (error, response, body) {
    if (!error && response.statusCode == 200) {
      const result = JSON.parse(body) || [];
      const index = parseInt(Math.random() * result.length);
      bot.sendPhoto(chatId, result[index].file_url, { caption: 'Hand flushing for a while, hand flushing for a long time, hand flushing for a long time, hand flushing for a long time, hand flushing for a long time, hand flushing for a long time, hand flushing for a long time.' }).catch((err) => {
        bot.sendMessage(chatId, 'Hand punching failure');
      })
    } else {
      bot.sendMessage(chatId, 'Hand punching failure');
    }
  });
});


bot.onText(/\/echo (.+)/, (msg, match) => {

  const chatId = msg.chat.id;
  const resp = match[1];
  bot.sendMessage(chatId, resp);
});

Then restart pm2

pm2 restart bot

Modify nginx configuration

vim /etc/nginx/conf.d/default.conf

Forward https://hentai.urusai.site to the server we just started express

location / {
    proxy_pass http://127.0.0.1:9000;
    proxy_http_version 1.1;
    proxy_set_header X_FORWARDED_PROTO https;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $host;
    
}
nginx -s reload

After restarting nginx successfully, access https://hentai.urusai.site/should show the hello world returned by the express server

At the same time, our Telegram bot's webhook mode has been successfully set up.

Visit the bot again, enter / prpr, and you can still run by hand.

bot sends messages on time

In addition to the actions we do when the user enters a command, we can also send messages to specific channels on a regular basis.

For example, we can create a channel and invite bot to be an administrator, and let bot send a weather forecast at 10 o'clock every day, so that all subscribers to this channel can receive messages!

Last

I also did one recently. Telegram Bot For grabbing yande.re The picture above

yande5_bot

Robot bot

Telegram search @yande5_bot or click here yande5_bot

Usage method:

  • / latest 3 Get the latest three pictures
  • / popular 1d(1d/1w/1m/1y) Get a day (day/week/month/year) popular image
  • / random 3 Gets random 3 Pictures
  • / tag bra 3 Gets three pictures labeled bra
  • / help Help Information
  • / about
  • / start starts

dailyYande

Subscription channel

Telegram search @dailyYande or click here dailyYande

Use the @yande5_bot robot to manage @dailyYande channel and send the popular pictures on time every night at 20:00

Topics: node.js Nginx JSON yum npm