A
A
Alexander2018-03-22 15:41:42
Nginx
Alexander, 2018-03-22 15:41:42

How to make nginx+gunicorn+telebot (telegram webhooks) work?

Hello!
Given :
1. A bot written in flask+python3+telebot.
2. Droplet on DigitalOcean
I want to run a bot on webhooks. Ideally, I would like to run two or more bots on one droplet.
Locally, with the help of long polling, the bot works. On the droplet, he also worked with self-signed certificates just on flaks. I would like to use Nginx and Gunicorn, as it looks like the right solution (doesn't it?)
Problem :
In telebot's logs, I see that the webhook is installed, installed where it should be. Nginx is running, gunicorn is spinning, but the bot is not responding. What's wrong? Maybe somewhere in the root something is wrong?
I followed this https://www.digitalocean.com/community/tutorials/h... and a bit of thishttps://groosha.gitbooks.io/telegram-bot-lessons/c... I am attaching the sources below.
run.py

from test_bot import app

if __name__ == '__main__':
    app.run()

test_bot/__init__.py
import flask
import telebot
import config

app = flask.Flask(__name__)
app.config.from_object(config.DefaultConfig)
from . import bot_core

@app.route('/bot', 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_core.bot.process_new_updates([update])
        return ''
    else:
        flask.abort(403)

test_bot/bot_core.py
import telebot

bot = telebot.TeleBot(app.config['BOT_API_TOKEN'])

# Handle '/start'
@bot.message_handler(commands=['start'])
def start_message(message):
    bot.send_message(message.chat.id, 'Hello!')
# Remove webhook, it fails sometimes the set if there is a previous webhook
bot.remove_webhook()
sleep(1)
# Set webhook
bot.set_webhook('https://droplet_ip/bot')

/etc/systemd/system/test_bot.service
[Unit]
Description=Gunicorn instance to serve test_bot
After=network.target

[Service]
User=netolyrg
Group=www-data
WorkingDirectory=/home/netolyrg/test_bot
Environment="PATH=/home/netolyrg/test_bot/flask_venv/bin"
ExecStart=/home/netolyrg/bmstubot_test/test_bot/bin/gunicorn --workers 1 --bind unix:test_bot.sock -m 007 run:app

[Install]
WantedBy=multi-user.target

/etc/nginx/sites-available/test_bot
server {
    server_name droplet_ip;

    listen 443 ssl;

    access_log /home/netolyrg/logs/access.log;
    error_log  /home/netolyrg/logs/error.log;

    ssl_certificate /etc/nginx/ssl/nginx.crt;
    ssl_certificate_key /etc/nginx/ssl/nginx.key;

    location /bot {
        include proxy_params;
        proxy_pass http://unix:/home/netolyrg/test_bot/test_bot.sock;
        proxy_set_header   Host $host;
        proxy_set_header   X-Real-IP $remote_addr;
        proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header   X-Forwarded-Host $server_name;
    }
}

Answer the question

In order to leave comments, you need to log in

2 answer(s)
A
Alexander, 2018-03-23
@netolyrg

Yes, I found a bug.
I read https://core.telegram.org/bots/webhooks and realized that with a self-signed certificate, you need to bot.set_webhook('https://droplet_ip/bot')specify the path to the .pem public key.

V
vreitech, 2018-03-22
@fzfx

what about the rights to the unix socket? ls -la /home/netolyrg/test_bot/test_bot.sock
in general, offhand everything looks fine, but the problem is that I'm not a real welder. The only thing I don't know is what exactly you do bot_core.bot.process_new_updates([update]).
as an example, I can throw the bot code on D for comparison:

spoiler
import vibe.vibe;
import vibe.stream.tls;
import vibe.data.json;
import std.string;
import std.typecons;

immutable string botName = "somebotname";
immutable string tgWebhookUrl = "/urlforwebhook";
immutable string tApiUrl = "https://api.telegram.org/bot123456789:TOKENISHERE";

void main()
{
        auto settings = new HTTPServerSettings;
  // на каком порту слушать вебхуки, проксируемые сюда nginx'ом
        settings.port = 8080;
  // на каких интерфейсах хоста слушать вебхуки
        settings.bindAddresses = ["::1", "127.0.0.1"];

        auto router = new URLRouter;
  // установка обработчика вебхуков
        router.post(tgWebhookUrl, &tgWebhookDispatcher);

        listenHTTP(settings, router);
        runApplication();
}

// обработчик вебхуков
void tgWebhookDispatcher(HTTPServerRequest req, HTTPServerResponse res)
{
        res.contentType("application/json");
        string resJson;
  // проверка на то, что пришедшее сообщение является replay'ем
        if("reply_to_message" in req.json["message"]) {
    // проверка на то, что в пришедшем сообщении команда для бота
                if("entities" in req.json["message"] &&
                "type" in req.json["message"]["entities"][0] &&
                req.json["message"]["entities"][0]["type"].get!string == "bot_command")
                {
      // диспетчеризация команд для бота и ответ на них
                        switch(req.json["message"]["text"].get!string)
                        {
                                case "/[email protected]" ~ botName:
                                resJson = q"[{"method":"sendMessage","chat_id":]"
                                ~ to!string(req.json["message"]["chat"]["id"])
                                ~ q"[,"text":"Answer1"}]";
                                break;
                                case "/[email protected]" ~ botName:
                                resJson = q"[{"method":"sendMessage","chat_id":]"
                                ~ to!string(req.json["message"]["chat"]["id"])
                                ~ q"[,"text":"Answer2"}]";
                                break;
                                default:
                                break;
                        }
                }
        }
        res.writeBody(resJson);
}

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question