Categorii: Tot - google - библиотека

realizată de Евгений Щемелинин 6 luni în urmă

122

Настройка и создание Telegram бота с использованием webhook (1)

Для создания и настройки Telegram бота можно использовать различные платформы и сервисы. Одним из популярных вариантов является использование webhook для взаимодействия с ботом. Бесплатные VPS серверы предоставляют хорошие возможности для размещения и тестирования ботов.

Настройка и создание Telegram бота с использованием webhook (1)

Настройка и создание Telegram бота с использованием webhook

Бесплатные VPS серверы для размещения бота

Alibaba cloud

Еще не тестировал vps машины от Alibaba, но хочу это сделать на одном из следующих проектов

3. Есть множество других бесплатных продуктов

2. Бесплатная машина для предприятий на 12 месяцев

Характеристики на 16.03.2021

2 ядра, 2 gb озу, 40 gb ssd

1. Бесплатная машина физ лиц на 12 месяцев

Характеристики на 16.03.2021

1 ядро, 1 gb озу, 40 gb ssd

Google cloud platform (GCP)

1. Частые изменения тарифных планов

3. Множество дополнительных сервисов

2. Есть множество возможностей по масштабированию и администрированию приложений

1. Есть бесплатные тарифные планы

Условия использования бесплатных тарифных планов очень часто меняются. Изначально там давали 300 долларов на 12 месяцев.

И полностью бесплатную машину N1. Сейчас тарифный план может отличаться...

Heroku

2. Есть жалобы на нестабильную работу

1. Много ограничений

2. Он реально бесплатный

1. Интеграция с github

Библиотеки для разработки

go
telegram bot api

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

Совет - читайте код на github. Это позволит быстрее понять, как работать с библиотекой

Документация

Установка go на linux (рекомендую использовать вторую инструкцию)

Способы создания бота

Про сравнение этих способов можно прочитать здесь
webhook

На стороне сервера telegram регистрируется ip адрес бота.

При получении обновлений сервер telegram сам уведомляет бота о наличие новых сообщений.

package main

import (
	"github.com/Syfaro/telegram-bot-api"
	"log"
	"net/http"
)

func main() {
	bot, err := tgbotapi.NewBotAPI("Тут должен быть твой токен, полученный от Bot Father")
	if err != nil {
		log.Fatal(err)
	}

	bot.Debug = true

	log.Printf("Authorized on account %s", bot.Self.UserName)

// Установка вебхука на внешний адрес машины
	_, err = bot.SetWebhook(tgbotapi.NewWebhookWithCert("https://www.google.com:8443/"+bot.Token, "cert.pem"))
	if err != nil {
		log.Fatal(err)
	}

// Получение обнавлений происходит на внутреннем адресе
	updates, _ := bot.ListenForWebhook("/" + bot.Token)
	go http.ListenAndServeTLS("0.0.0.0:8443", "cert.pem", "key.pem", nil)

	for update := range updates {
		log.Printf("%+v\n", update)
	}
}

Достоинста

4. Как следствие этот способ хорошо подходит для production

3. Ssl сертификаты и https обеспечивает безопасное соединение

2. Отсутствие проблем при перезагрузке серверов telegram

1. Оптимальное использование ресурсов

Процесс настройки может показаться сложным, если вы делаете это впервые. Однако все "недостатки" являются лишь пунктами по настройки сервера



3. Нужно связать внешний адрес машины хостящей бота с внутренним адресом приложения. Решается через Nginx и обратный прокси

2. Этот режим работает только с протоколом https. Как следствие нужны ssl сертификаты

1. Нужен статический ip адрес. Как следствие нужен vps сервер

pooling

В этом режиме бот работает в режиме опроса сервера телеграмма.

То есть каждую секунду бот спрашивает: "есть ли для меня обновления?"

Пример

package main

import (
	"log"
	"github.com/Syfaro/telegram-bot-api"
)

func main() {
	bot, err := tgbotapi.NewBotAPI("Тут должен быть твой токен, полученный от Bot Father")
	if err != nil {
		log.Panic(err)
	}

	bot.Debug = true

	log.Printf("Authorized on account %s", bot.Self.UserName)

	u := tgbotapi.NewUpdate(0)
	u.Timeout = 60

	updates, err := bot.GetUpdatesChan(u)

	for update := range updates {
		log.Printf("[%s] %s", update.Message.From.UserName, update.Message.Text)

		msg := tgbotapi.NewMessage(update.Message.Chat.ID, update.Message.Text)
		msg.ReplyToMessageID = update.Message.MessageID

		bot.Send(msg)
	}
}


Достоинства

1. Проще создать, подходит для обучения

Недостатки

3. Как итог данный способ - плохое решение для production

2. При перезагрузке сервера telegram, бот падает

1. Избыточное количество запросов

Примечания по использованию этой интеллект карты

Альтернативная инструкция
Поскольку это карта - инструкция. То для её полного выполнения необходимо читать все вложенные примечания!
Эта интеллект карта является попыткой сохранения знаний. Для которых более типичным форматом хранения был бы doc файл.

Инструкция по созданию telegram-bota с использованием webhook и сервера от GCP

7. Разработка на удаленном сервере при помощи VSC (Дополнительный пункт)
2. При этом удобно фиксировать все изменения кода в своем репозитории github. В таком случае вы получите producrion сервер с возможностью написания кода.
1. Можно установить среду VSC, и расширение remote ssh. Тогда вы сможете из этой среды писать код, который по факту находится на удаленном компьютере
6. Запуск бота

Поскольку это интеллект карта посещена не программированию и настройке окружения на коком-то конкретном языке. То описание процесса установки go и python здесь отсутствует.

3. Проверить работу сервера и бота вы можете при помощи обычного браузера
2. Пример кода на python

import os
import telegram
from telegram.ext import (Updater, CommandHandler, MessageHandler, Filters)

TOKEN = "Ваш токен телеграм бота"
PORT = int(os.environ.get('PORT', '5000'))
SERVER = 'EXTERNAL IP OF VM INSTANCE/'
CERT = '/home/jj/PUBLIC.pem'

def htel(update, context):
  update.message.reply_text('Help is here')

def echo(update,context):
  dom = update.message.text
  update.message.reply_text(dom)

def tbot():
  updater = Updater(TOKEN, use_context=True)
  dp = updater.dispatcher
  dp.add_handler(CommandHandler("help", htel))
  dp.add_handler(MessageHandler(Filters.text, echo))
# Поднятиебота на внутренннем ip
  updater.start_webhook(listen="0.0.0.0", port=5000, url_path=TOKEN)

# Запрос на связь с телеграмом
  updater.bot.setWebhook(SERVER+TOKEN,certificate=open(CERT, 'rb'))
  updater.idle()
tbot()


1. Пример кода на golang

При написании этого кода использовалась библиотека "telegtam bot api" её описание есть во вкладке "библиотеки для разработки".


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

package main

import (
	"github.com/Syfaro/telegram-bot-api"
	"log"
	"net/http"
)

func main() {
	bot, err := tgbotapi.NewBotAPI("Ваш telegram токен")
	if err != nil {
		log.Fatal(err)
	}

	bot.Debug = true

	log.Printf("Authorized on account %s", bot.Self.UserName)

// Запрос на сязь машины с телеграм серверо
	_, err = bot.SetWebhook(tgbotapi.NewWebhookWithCert("https://www.google.com:8443/"+bot.Token, "cert.pem"))
	if err != nil {
		log.Fatal(err)
	}

	updates, _ := bot.ListenForWebhook("/" + bot.Token)
  // поднятие бота на внутреннем адресе
  go http.ListenAndServeTLS("0.0.0.0:5000", "cert.pem", "key.pem", nil)

	for update := range updates {
		log.Printf("%+v\n", update)
	}
}

5. Настройка Nginx

Теперь у нас есть готовая машина с ssl ключами, telegram токен и доступ ко всему этому чуду.


Однако нам остается зарегистрировать на сервере telegram бота, который будет находиться на полученном external ip, и работать через протокол https.


Для подтверждения регистрации нам понадобится полученный токен и ssl сертефикаты подтверждающие безопасность https соединения.


Так же поскольку telegram бот является сервисом, который сидит на внутреннем адресе и порту, а сообщения от telegram приходят на внешний адрес. То для связи их понадобится nginx в режиме обратный прокти

3. Перезагрузка Nginx

Первым делом нужно связать конфигурационные файлы настроек


sudo ln -s /etc/nginx/sites-available/default.txt /etc/nginx/sites-enabled/default


Перезагрузка nginx

sudo systemctl restart nginx && sudo systemctl status nginx

В случае успеха должно вывестись сообщение похожее на приложенную картинку. В противном случае читайте текст ошибки


2. Настройка nginx

Для начала перейдите в папку с конфигурационным файлом nginx

cd /etc/nginx/sites-available/

Посмотрите содержимое папки

ls -la

У вас отобразятся список всех файлов, которые находятся в этой папки. Лично у меня настройки хранятся в файле defaults. Откройте файл с настройками.

sudo nano defaults

Далее в нем в разделе server нужно написать следующую конфигурацию

server {
  listen 80;
  listen 443 ssl;
 # Тут должен быть внешний IP адрес машины, который вы получали в пункте 2.1
  server_name EXTERNAL IP OF VM INSTANCE;
# тут должны быть пути до ваших сертефикатов
  ssl_certificate /home/jj/cert.pem; 
  ssl_certificate_key /home/jj/cert.key;

  location /Ваш_Telegram_токен!! {
    proxy_set_header Host $http_host;
    proxy_redirect off;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Scheme $scheme;
    proxy_pass https://0.0.0.0:5000/Ваш_Telegram_токен!!/;
    }
}

По сути сейчас только что вы связали внешний адрес и порт вашей машины с внутренним адресом приложения!


Самые частые ошибки в этом файле бывают с указанием пути до сертификатов

1. Установка nginx

Первым делом обновите репозитории системы

sudo apt update -y && sudo apt-get update

Далее установите nginx

sudo apt-get install nginx

4. Генерация SSL сертефикатов
2. А бывают еще и сертефикаты выданные удостоверяющем центром=)) Спасибо Рябцу за криптографию
1. Инструкция для создания самоподписанного сертификата находится во вложении

Первым делом используйте команду

openssl req -newkey rsa:2048 -sha256 -nodes -keyout cert.key -x509 -days 3560 -out cert.pem


*.key - приватный сертификат

*.pen - публичный сертификат


Во время генерации вам будут задавать вопросы, нажимаем enter до пункта с Common Name. В него нужно вставить External IP.

Который вы получили в пункте 2.1 при создании машины!

3. Подключение к удаленной машине
2. Работа через descktop приложения вроде Putty. Примечание! Среда разработки VSC позволяет писать код на удаленной машине при помощи ssh!

2. Во вкладке VM Instance кликнике то текущей машине, в появившемся окне выберете Edit и прокрутите страницу до поля ssh keys. В него нужно добавить ваш ключ

1. Для этого потребуется сгенерировать свой ssh ключ

2. Инструкции для windows

Вроде как в windows 10 даже научились в консоль

Создание ключа через desktop приложение Putty

1. Команды на Linux

ssh-keygen

Далее нажимаете несколько раз enter.

Вывести ssh ключ на экран можно при помощи команды

cd ~/.ssh && cat id_rsa.pub


1. Работа в браузере - для этого нужно нажать кнопку ssh/open in browser После чего откроется окно с панелью терминала удаленной машины
2. Настройка GCP
3. Настройка Firewall

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


Краткая справка по портам:

80 - http порт, обычно используется web серверами для отображение страниц.

443 и 8443 - https порты, нужны для связи с telegram серверom


3. Более подробное описание того, что за что отвечает, читайте в заметке

Созданные машины выбирают правила по приоритету.

Чем ниже priorety, тем более важное правило.

Рекомендую ставить 1000


Если в terget указать "All instances in the network", то правила

будут применяться ко всем машинам на GCP


Source IP ranges: - указывает на диапазон адресов, к которым

применяется правило. 0.0.0.0/0 говорит о том, что правило будет

работать со всеми адресами от 0.0.0.0 до 255.255.255.254.


Во вкладке Protocols and ports, нужно в поле tcp вписать 5000, на

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


2. Нажать на вкладку “CREATE FIREWALL RULE”.

1. Открыть вкладку VPC/Firewall rules

2. Изменение IP на статику

2. Изменить тип с “Ephemeral” на “Static”

1. Перейти в раздел VPC -> External IP addresses

1. Создание машины

3. Обязательно! Нужно поставить галочки возле пунктов allow HTTP и allow HTTPS traffic

По итогу получится что-то вроде этого. External ip - это тот адрес, на который telegram сервер будет отправлять обновления

2. Нажать Create Instance, после чего откроется панель настройки характеристик сервера

Возможные проблемы с бесплатной машиной

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


Я бы рекомендовал использовать регион - Китай-Шанхай.


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


Примечание: Изменение изменение региона на Шанхай и увеличение производительности ведет к использованию средств! Но помните, что у вас есть 300$ на 3 месяца.


Бесплатная машина

Если верить интернетам, то машина серии: N1 и типа f1 Micro - является бесплатной.


Из бесплатных регионов доступны:




Однако в любом случае у вас есть как минимум 300$ на 3 месяца, чтобы попробовать другие услуги.

1. Перейти во вкладку Computete Engine -> VM instances

1. Получение токена для бота у BotFather

Проверка состояния бота, через браузер


Проверить установлен ли webhock можно при помощи команды

https://api.telegram.org/botYOUR-TOKEN/getWebhookInfo


Если все работает, то вы получите следующий json

{"ok":true,"result":{"url":"https://35.224.231.90:8443/712308912:DLGSteczdUnPdnNYLzNikaGOhome7l9q3vova/","has_custom_certificate":true,"pending_update_count":0,"max_connections":40}}


Сбросить регистрацию бота на определенном ip

https://api.telegram.org/botYOUR-TOKEN/setWebhook




Регистрация и получение токена бота

  1. Откройте telegram и подключитесь к боту @BotFather
  2. Вводите команду “/newbot”
  3. Введите name и username вашего бота. Username должен оканчиваться словом "bot"
  4. В ответ BotFather пришлет токен вида “1436541093:AAEp-Vsd31oOLWjfDOhcfn8bNx6tmVzj0yt”

Лучше всего сохранитm токен в отдельную переменную. Которую потом следует подставить в функцию регистрации бота в коде:


tgbotapi.NewBotAPI("Тут должен быть твой токен, полученный от Bot Father")