База знаний

Инструкции и ответы на вопросы о хостинге, работе сайтов и приложений

Как сделать телеграм-бота на хостинге

Создаем телеграм-бота

Более подробно и со скриншотами мы уже описывали регистрацию тг-бота в статье для Спринтбокс. Вспомним основное:

  • Создание любого бота начинается с сообщения отцу ботов в Телеграме — @BotFather (это официальный бот для создания тг-ботов)
  • Создать бота можно командой /newbot
  • Токен бота меняется командой /revoke
  • У @BotFather есть справка по команде /help

Написание бота

Размещать бота в папке сайта или создавать под него новый сайт не обязательно — бот всё равно будет запускаться из консоли и веб-сервер ему не нужен. Это же приводит нас к еще одному ограничению — поддержки webhook для робота на Python нет, работает только polling. На Спринтбокс таких ограничений нет, любой вариант получения сообщений от Telegram API будет работать.

Чтобы не повторять статью Спринтбокс, напишем код бота на основе другой библиотеки — Aiogram — и примера базового бота из официальной документации.

  1. Создадим папку, откуда будет работать бот:
    [username@server ~]$ mkdir ~/tgbot
  2. Подготовим и активируем виртуальное окружение — инструкция тут.
  3. Установим aiogram:
    (bot_venv) [username@server ~]$ pip install aiogram==2.14.3
  4. Начнем писать бота прямо в терминале:
    (bot_venv) [username@server ~]$ vim ~/tgbot/bot.py
    Чтобы перейти в режим редактирования в vim, нажмем кнопку I
    Для сохранения и выхода из vim нужно нажать ESC и после ввести :wq
    Дальнейшие шаги такие же, как в документации Aiogram.
  5. Импортируем все важные модули:
    import logging

    from aiogram import Bot, Dispatcher, executor, types
  6. Настроим логирование и инициализируем бота и диспетчера:
    API_TOKEN = 'ВСТАВЬТЕ СЮДА ТОКЕН БОТА'

    # Configure logging
    logging.basicConfig(level=logging.INFO)

    # Initialize bot and dispatcher
    bot = Bot(token=API_TOKEN)
     dp = Dispatcher(bot)
  7. Настроим обработчик команд /start и /help и ответы бота:
    @dp.message_handler(commands=['start', 'help'])
    async def send_welcome(message: types.Message):
         """     This handler will be called when user sends `/start` or `/help` command     """     await message.reply("Hi!\nI'm EchoBot!\nPowered by aiogram.")

    Если вы хотите обрабатывать все текстовые сообщения в чате, то надо добавить обработчик без фильтров:
    @dp.message_handler()
    async def echo(message: types.Message):
        # old style:
        # await bot.send_message(message.chat.id, message.text)

         await message.answer(message.text)
  8. И последний шаг — добавляем long polling:
    if __name__ == '__main__':
         executor.start_polling(dp, skip_updates=True)


После этого мы получаем Python-скрипт с телеграм-ботом:

Посмотреть код бота целиком

 """
This is a echo bot.
It echoes any incoming text messages.
"""

import logging

from aiogram import Bot, Dispatcher, executor, types

API_TOKEN = 'ВСТАВЬТЕ СЮДА ТОКЕН БОТА'

# Configure logging
logging.basicConfig(level=logging.INFO)

# Initialize bot and dispatcher
bot = Bot(token=API_TOKEN)
dp = Dispatcher(bot)

@dp.message_handler(commands=['start', 'help'])
async def send_welcome(message: types.Message):
"""
This handler will be called when user sends `/start` or `/help` command
"""
    await message.reply("Hi!\nI'm EchoBot!\nPowered by aiogram.")

@dp.message_handler()
async def echo(message: types.Message):
# old style:
# await bot.send_message(message.chat.id, message.text)

    await message.answer(message.text)

if __name__ == '__main__':
     executor.start_polling(dp, skip_updates=True) 


Запуск бота

Бот готов, запустить его можно командой: (bot_venv) [username@server ~]$ python ~/tgbot/bot.py

Но если закрыть соединение по SSH, бот тоже закроется. Чтобы этого не случилось, нужно дополнить код. В самое начало вставляем: import os, sys
activate_this = '/home/username/bot_venv/bin/activate_this.py'
with open(activate_this) as f:
     exec(f.read(), {'__file__': activate_this})

Этот код активирует виртуальное окружение сразу внутри бота, и его не придется запускать отдельно.

Tmux

Теперь можно будет запустить бота в tmux и оставить его работать, даже отключившись от SSH.

Tmux уже установлен на всех серверах виртуального хостинга. Для запуска утилиты достаточно набрать в терминале tmux: [username@server ~]$ tmux

И уже здесь нужно будет запустить бота, как мы делали это раньше: [username@server ~]$ python ~/tgbot/bot.py

Теперь чтобы отключиться от сессии tmux, достаточно будет набрать комбинацию клавиш Ctrl + B, отпустить и нажать D.

Команды:

  • Посмотреть список сессий:
    [username@server ~]$ tmux ls
  • Подключиться к последней активной сессии:
    [username@server ~]$ tmux a
  • Подключиться к определенной сессии:
    [username@server ~]$ tmux a -t 0 Вместо нуля используйте конкретный номер сессии, его можно узнать через tmux ls

Автоматизируем запуск

Один из наших сотрудников написал простой bash-скрипт, который выполняет запуск, перезапуск и остановку.

#!/usr/bin/bash

if [[ "$#" == 0 || "$1" == "--help" || "$1" == "-h" ]]; then
    echo "
Скрипт для мониторинга бота
start — запускает бота
stop — останавливает бота
status — проверяет, запущен ли процесс
restart — перезапускает бота
check_start — запускает бота, если тот не работает

Пример:
bot_control /home/login/tgbot/bot.py check_start
"
    exit 0
fi

[[ ! -f $1 ]] && { echo "Такого файла нет."; exit 1; }

bot_path=$1
bot_runner="/opt/rh/rh-python38/root/usr/bin/python"

function get_pid {
    bot_pid="$(pgrep -alf python | grep ${bot_path} | awk '{print $1}')"
    echo ${bot_pid}
}

function bot_status {
    pid=$(get_pid)
    if [[ -z ${pid} ]]; then echo "Бот не запущен."; exit 0; fi
    echo "$(ps -p ${pid} -o pid,pcpu,command)"
}

function bot_start {
    pid=$(get_pid)
    if [[ ${pid} ]]; then echo "Бот уже запущен."; exit 0; fi
    exec ${bot_runner} ${bot_path} 2>/dev/null &
    echo "Бот запущен."
}

function bot_stop {
    pid=$(get_pid)
    if [[ -z ${pid} ]]; then echo "Бот не запущен."; exit 0; fi
    kill $(get_pid)
    echo "Бот остановлен."
}

function bot_restart {
    pid=$(get_pid)
    if [[ ${pid} ]]; then
        bot_stop
        sleep 3
        bot_start
        exit 0
    else
        echo "Бот выключен. Попробуйте: bot_control ${bot_path} start"
    fi
}

function bot_check_start {
    pid=$(get_pid)
    if [[ -z ${pid} ]]; then echo "Бот не запущен. Запускаю."; bot_start; exit 0; fi
    echo "Бот запущен, всё хорошо."
}

case "$2" in
    start)
    bot_start
    ;;
    stop)
    bot_stop
    ;;
    status)
    bot_status
    ;;
    restart)
    bot_restart
    ;;
    check_start)
    bot_check_start
    ;;
    *)
    echo "Неверная команда."
    ;;
 esac>

Скрипт можно дорабатывать под себя бесконечно, плюс есть другие рабочие аналоги, это лишь пример.

Прямо сейчас скрипт работает только для Python, но интерпретатор можно легко поменять на 21-й и 24-й строках.

Чтобы запустить скрипт, как в примере кода, нужно сделать исполняемым файл под именем bot_control и положить его в папку /home/username/.local/bin/, где username – это логин вашего аккаунта.

Эти команды помогут развернуть скрипт на аккаунте: [username@server ~]$ chmod +x bot_control
[username@server ~]$ mkdir -p ~/.local/bin/
[username@server ~]$ mv bot_control ~/.local/bin/

Была ли эта инструкция полезной?