Деплой — это развёртывание программного обеспечения, то есть это все действия, которые делают программную систему готовой к использованию.
Деплой телеграм-бота — это размещение его на сервере или на хостинге.
В этой статье я расскажу, как я настроил хостинг пайтон ботов на обычном хостинге. Итак, стартовые условия:
- хостинг на
Beget - к хостингу привязан домен
- для домена выпущен бесплатный SSL-сертификат Let’s Encrypt

Начинаем установку Flask.
Установка Flask на Beget
Включаем SSH в настройках хостинга (если он выключен).

Подключаемся к хостингу через SSH. Это можно сделать прямо из панели управления хостингом: у Бегет встроен терминал прямо тут — мега-удобная штука.


Я делаю это через программу Putty.

В поле «hostname (or IP address)» вводим:
<логин-к-хостингу>@domain.ru
То есть в моем конкретно случае:
<логин-к-хостингу>@hosting-telegram-bota.ru
Нажимаем Open, вводим пароль от хостинга и заходим на хостинг через SSH:

Затем нам нужно перейти в Docker, выполняем команду:
ssh localhost -p222
Еще раз потребуется ввести пароль от хостинга, и если всё ОК — видим надпись (docker) в скобочках.


Теперь переходим в папку сайта, в моем случае команда выглядит так:
cd hosting-telegram-bota.ru
Вы всегда можете подсмотреть, где сейчас находитесь в помощью команды:
ls -l
Итак, зашли внутрь папки hosting-telegram-bota.ru

Теперь создадим папку .venv командой
mkdir .venv
Обновим pip командой
python3 -m pip install --upgrade pip
Активируем виртуальное окружение. Сначала команда:
pip install pipenv
Затем
pipenv shell
Затем переходим в папку .venv
cd .venv
Выполняем
source bin/activate
Если посмотреть через менеджер файлов — то на хостинге у нас такая картина:

и внутри папки .venv тоже кое-что появилось:

Продолжаем работу в консоли через Putty.
Нужно узнать путь к Python, который мы позже пропишем в настройках Flask. Выполните команду:
which python3
и запишите куда-то путь, который вам покажет.

Например, что-то такое:
/home/h/<логин_к_хостингу>/hosting-telegram-bota.ru/.venv/bin/python3
Установим Flask.
python3 -m pip install flask
Установим библиотеку Requests:
pip install requests
Также на этом этапе возможно вам потребуется установить библиотеки, необходимые для работы вашего бота. Тем более, что бот может быть написан с использованием разных вспомогательных фреймворков — Aiogram, Telebot и т.д.
Выйдем из папки .venv на уровень выше
cd ..
И начнем создавать структуру папок:
.
└── hosting-telegram-bota.ru
├── HelloFlask
│ └── __init__.py
├── .htaccess
├── passenger_wsgi.py
└── tmp
└── .venv
└── Pipfile
└── public_html
Создаем две директории HelloFlask и tmp.
mkdir HelloFlask tmp
Теперь, если посмотреть через File Manager Beget, у нас такая структура папок внутри папки сайта «../hosting-telegram-bota.ru»

Также создаем 2 файла:
touch .htaccess
touch passenger_wsgi.py
Параллельно, если не уверенно себя чувствует с консолью, можно проверять изменения через файловый менеджер хостинга, не забываем кнопку «Обновить», чтобы увидеть изменения.

Здесь же (в менеджере файлов Бегет) я открою файлы на редактирование.

Сначала .htaccess

В файле .htaccess пишем следующие строки, где во второй — путь к нашему Python, который мы узнали ранее через команду which python3
PassengerEnabled On
PassengerPython /home/h/<логин_к_хостингу>/hosting-telegram-bota.ru/.venv/bin/python3
Теперь редактируем файл passenger_wsgi
# -*- coding: utf-8 -*-
import sys, os
# указываем директорию с проектом
sys.path.append('/home/<ваша_буква>/<логин_к_хостингу>/hosting-telegram-bota.ru/HelloFlask')
# указываем директорию с библиотеками, куда поставили Flask
sys.path.append('/home/<ваша_буква>/<логин_к_хостингу>/.local/lib/python3.6/site-packages')
from HelloFlask import app as application
# Когда Flask стартует, он ищет application.
# Если не указать 'as application', сайт не заработает
from werkzeug.debug import DebuggedApplication
# Опционально: подключение модуля отладки
application.wsgi_app = DebuggedApplication(application.wsgi_app, False)
# Опционально: включение модуля отадки
application.debug = False
# Опционально: True/False устанавливается по необходимости в отладке

Также я меняю для обоих файлов права на 644.



Переходим в папку HelloFlask
cd HelloFlask
Создаём там файл __init__.py
touch __init__.py
Открываем его на редактирование и пишем:
from flask import Flask
app = Flask(__name__)
@app.route('/python-bot/')
def hello_world():
return 'Hello Flask!'
if __name__ == '__main__':
app.run()
Обратите внимание, я задал route /python-bot/, который будет использован потом при добавлении вебхука для телеграм-бота.

Сохраняем и также изменяем атрибуты доступа на 644.

Остались последние приготовления перед проверкой — запустилось ли наше Flask-приложение.
Возвращаемся в корневую директорию
cd ..
Выполняем последние команды:
ln -s public_html public
И запуск (ре-старт) Flask:
touch tmp/restart.txt
Эта команда (touch tmp/restart.txt) понадобится нам каждый раз, когда мы будем вносить какие-то изменения, чтобы перезапустить Flask.
Не забывайте выполнять ее, иначе изменения применяться не будут.
Также, не забывайте про права на файлы (chmod 644) и возможные другие проблемы. Важна каждая деталь, например, кодировка файлов.



Теперь проверим — работает ли Flask. Откроем в браузере наш сайт на той странице, адрес которой указали в __init__.py.
Если всё OK, увидим «Hello Flask!»

Запускаем телеграм бота на хостинге
Ок, Flask работает. Теперь заменим код в файле __init__.py на код нашего бота.
Я сделал второго телеграмм бота, чтобы на хостинге у нас работал бот на Python с похожим функционалом, как и тот, что вначале был сделан на PHP.
Вот такой код я помещу в __init__.py
from flask import Flask, render_template
from flask import request
from flask import Response
import requests
TOKEN = "<токен бота>"
app = Flask(__name__, template_folder='../public_html')
def tel_parse_message(message):
print("message-->",message)
try:
chat_id = message['message']['chat']['id']
txt = message['message']['text']
print("chat_id-->", chat_id)
print("txt-->", txt)
return chat_id,txt
except:
print("NO text found-->>")
def tel_send_message(chat_id, text):
url = f'https://api.telegram.org/bot{TOKEN}/sendMessage'
payload = {
'chat_id': chat_id,
'text': text
}
r = requests.post(url,json=payload)
return r
def tel_send_image(chat_id):
url = f'https://api.telegram.org/bot{TOKEN}/sendPhoto'
payload = {
'chat_id': chat_id,
'photo': "https://hosting-telegram-bota.ru/pic/pss-python.jpg",
'caption': "Жми /more"
}
r = requests.post(url, json=payload)
return r
def tel_send_inlineurl(chat_id):
url = f'https://api.telegram.org/bot{TOKEN}/sendMessage'
payload = {
'chat_id': chat_id,
'text': "Добро пожаловать в бота!\nСделано на Python.\nВашему боту нужен хостинг с поддержкой:",
'reply_markup': {
"inline_keyboard": [
[
{"text": "Python", "url": "https://hosting-telegram-bota.ru/python"},
{"text": "Node JS", "url": "https://hosting-telegram-bota.ru/"}
],
[
{"text": "PHP", "url": "https://hosting-telegram-bota.ru/"},
{"text": "PHP - сила!", "url": "https://hosting-telegram-bota.ru/php-bot/PHP_power.jpg"}
]
]
}
}
r = requests.post(url, json=payload)
return r
@ app.route('/python-bot/', methods=['GET', 'POST'])
def index():
if request.method == 'POST':
msg = request.get_json()
try:
chat_id, txt = tel_parse_message(msg)
if txt == "hi":
tel_send_message(chat_id,"Hello, world!")
elif txt == "/start":
tel_send_image(chat_id)
elif txt == "/more":
tel_send_inlineurl(chat_id)
else:
tel_send_message(chat_id, 'from webhook')
except:
print("from index-->")
return Response('ok', status=200)
else:
return '<h1>Это страница-webhook для бота на Python, размещенного на хостинге Beget.</h1>'
@app.route('/', defaults={'path': ''})
@app.route('/<path:path>')
def catch_all(path):
return render_template('home.html')
if __name__ == '__main__':
app.run(threaded=True)
После сохранения нового кода в init.py — не забываем перезапустить Фласк командой (зайдя на хостинг через SSH):
touch tmp/restart.txt
И также активировать webhook для бота, открыв в браузере:
https://api.telegram.org/bot<токен бота>/setWebhook?url=https://hosting-telegram-bota.ru/python-bot/

Проверяем, открыв страницу бота в браузере, и видим ту надпись, которую мы задали для GET-запроса:

Проверяем как работает сам бот @hosting_telegram_bot

Сервер для телеграмм бота Python
Вот так бот на Python может работать на обычном шаред-хостинге. Бесплатного тестового периода в 30 дней вполне хватит, чтобы поиграться-протестировать гипотезу, запустить MVP.
Конечно, боты бывают разной сложности и замысла. Возможно, все-таки понадобится аренда сервера для бота, которые у Beget тоже есть с хорошими конфигурациями.
Список с ценами за VPS/VDS — по ссылке.
А здесь короткое видео, как разместить бота на сервере от Бегет:
Недорогие серверы на Beget.
Перезапуск Flask через терминал Beget
Из панели управления хостингом доступен терминал, что позволяет удобно управлять проектом или перезапускать сервер Flask после внесения правок.
Терминал у Бегет находится слева в виде боковой вкладки:

Удобно, что скопировать команды в терминал можно с помощью обычного CTRL+C => CTRL+V. Также (если вы не знакомы с Linux) — стрелками «вверх-вниз» на клавиатуре можно листать историю команд (чтобы не набирать их заново).
При сворачивании терминал сохраняет историю команд, но если что-то зависло или не реагирует — можно закрыть-открыть новую вкладку:

Вот пример, как я перезапускаю Flask после каких-либо правок в теле страницы — например, в данном случае я добавил новую кнопку:

Если я оказался в неправильной директории и команда touch tmp/restart.txt не сработала — всегда можно посмотреть где мы с помощью команда ls -l

После перехода в папку с сайтом делаем ре-старт Фласка — и теперь все ок. На главной странице добавлена новая кнопка на статью про бота отслеживания подписок на канал:

Полезные ссылки
- Статья на Beget по настройке Python на хостинге
- Код telegram бота на Питоне я подсмотрел здесь
- Кажется, крутой учебник по aiogram
- Еще статья по запуску Flask на Бегете
Бот для сбора статистики — откуда приходят подписчики в канал и для снижения цены привлечения подписчика.
