Answer the question
In order to leave comments, you need to log in
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()
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)
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')
[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
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
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.
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:
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 questionAsk a Question
731 491 924 answers to any question