V
V
VasHan2020-04-20 10:25:39
Python
VasHan, 2020-04-20 10:25:39

How to run telegram bot with webhook on VPS?

Good afternoon!

I want to transfer my telegram bot to webhook, for testing I took the webhook_flask_echo_bot.py example from the pyTelegramBotAPI module.
Rented a VPS, linked to duckdns.org, got a certificate using certbot --nginx, certificate rating A+
Switched the bot to a webhook, being in the directory with the certificate:

https://api.telegram.org/botBOT_TOKEN/setWebhook?url=https://my-host.duckdns.org:8443/BOT_TOKEN/


I run a test bot on the VPS:
import logging
import time
import flask
import telebot

API_TOKEN = 'BOT_TOKEN'

WEBHOOK_HOST = 'my-host.duckdns.org'
WEBHOOK_PORT = 8443  
WEBHOOK_LISTEN = '0.0.0.0'  

WEBHOOK_SSL_CERT = '/etc/letcencrypt/archive/my-host.duckdns.org/fullchain1.pem'  
WEBHOOK_SSL_PRIV = '/etc/letcencrypt/archive/my-host.duckdns.org/privkey1.pem'  

WEBHOOK_URL_BASE = "https://%s:%s" % (WEBHOOK_HOST, WEBHOOK_PORT)
WEBHOOK_URL_PATH = "/%s/" % (API_TOKEN)

logger = telebot.logger
telebot.logger.setLevel(logging.INFO)

bot = telebot.TeleBot(API_TOKEN)

app = flask.Flask(__name__)

# Empty webserver index, return nothing, just http 200
@app.route('/', methods=['GET', 'HEAD'])
def index():
    return ''

Process webhook calls
@app.route(WEBHOOK_URL_PATH, methods=['POST'])
def webhook():
    if flask.request.headers.get('content-type') == 'application/json':
        json_string = flask.request.get_data().decode('utf-8')
        update = telebot.types.Update.de_json(json_string)
        bot.process_new_updates([update])
        return ''
    else:
        flask.abort(403)

# Handle '/start' and '/help'
@bot.message_handler(commands=['help', 'start'])
def send_welcome(message):
    bot.reply_to(message,
                 ("Hi there, I am EchoBot.\n"
                  "I am here to echo your kind words back to you."))

# Handle all other messages
@bot.message_handler(func=lambda message: True, content_types=['text'])
def echo_message(message):
    bot.reply_to(message, message.text)

# Remove webhook, it fails sometimes the set if there is a previous webhook
bot.remove_webhook()

time.sleep(1)

# Set webhook
bot.set_webhook(url=WEBHOOK_URL_BASE + WEBHOOK_URL_PATH,
                certificate=open(WEBHOOK_SSL_CERT, 'r'))

# Start flask server
app.run(host=WEBHOOK_LISTEN,
        port=WEBHOOK_PORT,
        ssl_context=(WEBHOOK_SSL_CERT, WEBHOOK_SSL_PRIV),
        debug=True)


After launch, GET requests are displayed in the logs if you access https://my-host.duckdns.org:8443 through the browser.
But, it does not respond to commands sent to the bot.

When checking the status of the bot, I get:
{
"ok":true,
"result":{"url":"https://my-host.duckdns.org:8443/BOT_TOKEN/",
"has_custom_certificate":true,
"pending_update_count":19,
"last_error_date":1587364313,
"last_error_message":"SSL error {error:1416F086:SSL routines:tls_process_server_certificate:certificate verify failed}",
"max_connections":40}
}


I check through the @CanofWormsBot bot recommended in the documentation.
I get: "This certified certificate is valid"

Tell me, please, what could be the problem?
Is this possible, because the certificate is received on nginx, and the webhook is raised on flask?

Answer the question

In order to leave comments, you need to log in

1 answer(s)
M
Miit, 2020-04-20
@Miit

Telegram does not digest certificates well, especially self-signed ones. You can try feeding the certificate by passing the file as a parameter when installing the webhook. If this does not help, then check your certificate through openssl. The returned code should be 0 if the certificate passed verification

Command example
openssl s_client -connect my-host:duckdns.org:8443

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question