Пишем бота обратной связи для Telegram на Python Данил Пистолетов, 10 февраля 202510 февраля 2025 Пишем бота обратной связи для Telegram на Python и Aiogram3, а потом ставим его на VPS, чтобы он работал непрерывно. Выбор в пользу Aiogram3 обусловлен тем, что в настоящий момент это один из лучших вариантов для работы с Telegram, который продолжает обновляться. До этого была распространена вторая версия этого проекта, и при попытке установить третью с помощью команды «pip install aiogram» устанавливалась вторая версия, но сейчас это уже изменено и скачивается именно третья версия. На момент написания этой статьи самой последней версией является aiogram 3.17.0. Боты обратной связи в Telegram являются весьма часто используемым решением в настоящий момент. К нему могут прибегнуть не только какие-либо коммерческие компании, но и обычные пользователи. У этого варианта много преимуществ. Некоторые владельцы конструкторов для ботов предлагают создание бесплатного варианта подобного бота, но взамен предоставляют свою рекламу, что может быть проблематично. В любом случае наличие собственного бота будет более хорошим вариантом. Но он требует затрат на VPS сервер, если вы хотите, чтобы ваш проект работал без перерывов. Можно, конечно, запускать его и на своём компьютере, но это менее удобный вариант. Создание бота в Telegram Первым делом пишем @BotFather и создаём нового бота чтобы получить ключ доступа и, собственно, сам аккаунт бота. Надеюсь, что объяснять столь базовые моменты не нужно. Для его создания достаточно придумать название и указать его адрес (имя пользователя). При желании можно сделать ему аватарку, описание и так далее. Пишем бота обратной связи для Telegram Теперь переходим к наиболее важной части — написании кода для бота. Бот для обратной связи весьма прост и не требует каких-то серьёзных временных затрат. Я буду писать код в PyCharm, а уже потом буду переносить на VPS. Первым делом устанавливаем aiogram с помощью консольной команды «pip install aiogram», ждём некоторое время. Вводим основную часть кода: import asyncio from aiogram import Bot, Dispatcher bot = Bot(token='Сюда вставляем токен') dp = Dispatcher() async def main(): await bot.delete_webhook(drop_pending_updates=True) await dp.start_polling(bot) @dp.message() async def sms(msg): chat_id = msg.chat.id if __name__ == '__main__': asyncio.run(main()) Первой и второй строкой мы импортируем необходимые для работы бота библиотеки. В третьей строке мы вводим токен от бота Bot Father. Далее идут команды для его работы и взаимодействия с сообщениями, последние строки — зацикливание нашего асинхронного чуда. Кусок «chat_id = msg.chat.id» нужен нам для того, чтобы каждый раз не писать «msg.chat.id», а использовать вместо этого «chat_id». Заранее учтём две базовые вещи при использовании таких ботов. Во-первых, нужно как-то читать и отвечать на сообщения. Во-вторых, нужно как-то предотвращать возможный спам. Для подобных действий можно было бы сделать базу данных из двух таблиц (для администрирования и блокировок) на каком-нибудь sqlite, но это не вполне разумный вариант. Основная функция нашего бота — взаимодействие между его автором и пользователем, более ничего не требуется, потому и использовать базу данных было бы излишне. Нам нужно лишь автоматизировать взаимодействие с админом (или админами) и игнорировать спамеров. Вместо того, чтобы создавать лишние нагрузки в виде самого sqlite и библиотек для нашего небольшого скрипта, может остановиться на использовании встроенных в Python решений. После строки «dp = Dispatcher()» вставляем следующее: AdminID = ваш ID banlist = [] Первая строка будет указанием на администратора, вторая представляет из себя список заблокированных пользователей, которых бот будет игнорировать. Если вы не знаете как получить свой ID, напишите в поиске Telegram «Get my ID» или что-то подобное, вам должны попасться боты для получения своего ID. Дополняем наш код: @dp.message() async def sms(msg): chat_id = msg.chat.id if str(chat_id) in banlist: pass Таким образом, если боту напишет человек из списка заблокированных — бот его проигнорирует. Идём дальше: @dp.message() async def sms(msg): chat_id = msg.chat.id if str(chat_id) in banlist: pass else: if chat_id != AdminID: if msg.text == "" or msg.text != "": await bot.send_message(AdminID, f"Текст сообщения: {msg.text}\nID отправителя: {msg.from_user.id}\nLink: <a href=\"tg://user?id={msg.from_user.id}\">{msg.from_user.id}</a>", parse_mode='html') Мы добавили условие что делать в том случае, если пишет пользователь, который не заблокирован. Бот сверяет ID написавшего с ID администратора и, если написал не администратор, сообщение переправляется ему. Помимо самого сообщения, мы получаем информацию об ID отправителя и получаем ссылку на него, что будет очень удобно. Последним штрихом являются админ-команды: if chat_id == AdminID: if msg.text.lower()[:4] == "send": sms = msg.text[5:] sms = sms.split(",") await bot.send_message(chat_id=sms[0], text=sms[1]) await bot.send_message(AdminID, "Отправлено") elif msg.text.lower()[:4] == "ban ": sms = msg.text[4:] banlist.append(sms) await bot.send_message(AdminID, f"Пользователь {sms} заблокирован") await bot.send_message(AdminID, str(banlist)) elif msg.text.lower() == "banlist": await bot.send_message(AdminID, str(banlist)) Первая команда — send. Она используется для отправки сообщения. Вначале пишем ID того, кому хотим написать, потом ставим запятую и пишем текст ответа. Можно поставить какой-нибудь другой разделитель, в ином случае использовать запятые в отправляемом тексте не получится. Вторая команда — ban. После слова «ban» нужно написать ID того, кого нужно заблокировать. Помимо самой блокировки, бот высылает нам список заблокированных. Дополнительно есть команда «banlist», чтобы увидеть заблокированных без блокировки. На этом, собственно, бот готов. Ниже полный код, только AdminID заменён на DanilID. import asyncio from aiogram import Bot, Dispatcher DanilID = Ваш ID bot = Bot(token='Ваш токен') dp = Dispatcher() banlist = [] async def main(): await bot.delete_webhook(drop_pending_updates=True) await dp.start_polling(bot) @dp.message() async def sms(msg): chat_id = msg.chat.id if str(chat_id) in banlist: pass else: if chat_id != DanilID: if msg.text == "" or msg.text != "": await bot.send_message(DanilID, f"Текст сообщения: {msg.text}\nID отправителя: {msg.from_user.id}\nLink: <a href=\"tg://user?id={msg.from_user.id}\">{msg.from_user.id}</a>", parse_mode='html') if chat_id == DanilID: if msg.text.lower()[:4] == "send": sms = msg.text[5:] sms = sms.split(",") await bot.send_message(chat_id=sms[0], text=sms[1]) await bot.send_message(DanilID, "Отправлено") elif msg.text.lower()[:4] == "ban ": sms = msg.text[4:] banlist.append(sms) await bot.send_message(DanilID, f"Пользователь {sms} заблокирован") await bot.send_message(DanilID, str(banlist)) elif msg.text.lower() == "banlist": await bot.send_message(DanilID, str(banlist)) if __name__ == '__main__': asyncio.run(main()) Пример работы на изображении ниже. В процессе написания этой статьи хотел сделать человеческий ответ без всяких send, чтобы просто отвечать на пересланное ботом сообщение. Но как оказалось, такой метод из Telegram убрали, потому чтоб такое сделать нужно заморачиваться и делать какой-то еле работающий костыль. Вместо этого я сделал пересылку сообщения ботом, чтоб можно было открыть профиль, если он не скрыт, и сделал отправку сообщения просто на букву «о» с разделением через «/». Например: «о 111111/текст сообщения». Код ниже. import asyncio from aiogram import Bot, Dispatcher DanilID = Айди bot = Bot(token='Токен') dp = Dispatcher() banlist = [] async def main(): await bot.delete_webhook(drop_pending_updates=True) await dp.start_polling(bot) @dp.message() async def sms(msg): chat_id = msg.chat.id if str(chat_id) in banlist: pass else: if chat_id != DanilID: if msg.text == "" or msg.text != "": await bot.forward_message(DanilID, chat_id, msg.message_id) await bot.send_message(DanilID, f"Текст сообщения: {msg.text}\nID отправителя: {msg.from_user.id}\nLink: <a href=\"tg://user?id={msg.from_user.id}\">{msg.from_user.id}</a>", parse_mode='html') if chat_id == DanilID: if msg.text.lower()[:4] == "ban ": sms = msg.text[4:] banlist.append(sms) await bot.send_message(DanilID, f"Пользователь {sms} заблокирован") await bot.send_message(DanilID, str(banlist)) elif msg.text.lower() == "banlist": await bot.send_message(DanilID, str(banlist)) elif msg.text.lower()[0] == "о": sms = msg.text[2:] sms = sms.split("/") await bot.send_message(chat_id=sms[0], text=sms[1]) await bot.send_message(DanilID, "Отправлено") if __name__ == '__main__': asyncio.run(main()) Ставим бота на VPS Далее нам необходимо поставить бота на сервер для постоянной его работы. Например, на Timeweb самый минимальный облачный сервер стоит 300 рублей в месяц вместе с публичным IP-адресом. На Reg чуть больше — 390, но его по многим причинам использовать не стоит. Лучше выбрать нормальный хостинг вместо Reg. Нужно будет поместить наш файл со скриптом вместе с файлами библиотек. При использовании PyCharm я просто собираю их в папке проекта и к ним вставляю файл Main.py, примерно как на скриншоте ниже. Как только вы собрали эти файлы вместе необходимо переместить их в отдельную папку на вашем сервере. К слову, необходимо установить Python, если его на вашем сервере нет. Обычно он всегда есть, но если нет, то нужно использовать команду «sudo apt install python3 python3-pip» (для Debian). Как только вы убедились в наличии Python3 и перенесли файлы в созданную папку нужно создать демона — процесс, который будет оживлять нашего бота при перезапуске системы и при его выключении по каким-либо причинам. Разместить бота можно по разным адресам. У меня, например, он расположен в папке «/usr/lib/systemd/system». Вам советую расположить его там же. Создаём файл с окончанием «.service». Например: «botik.service». Вставляем в него следующее содержимое: [Unit] Description=tg-bot After=network.target [Service] User=root Group=root Type=simple Restart=always ExecStart=/usr/bin/python3 ваши_папки/main.py [Install] WantedBy=multi-user.target В «ExecStart» необходимо вставить ссылку на сам Python3, а через пробел — на скрипт Main.py. Перезагружаем службы командой «systemctl daemon-reload» и активируем бот командой «systemctl enable botik.service» (или как вы его там назвали). После этого бот должен заработать. Его статус можно проверить командой «systemctl status botik.service». Если каким-то чудом он не заработал, то просмотр статуса поможет узнать причину. Сам же я буду использовать этот проект для бота обратной связи своего Telegram-канала с моей книгой «Злая Россия«, потому уже проверил его работоспособность. Статьи