Как написать телеграмм бота на python
Перейти к содержимому

Как написать телеграмм бота на python

  • автор:

Питоном по телеграму! Пишем пять простых Telegram-ботов на Python

В этой статье мы реали­зуем прос­той, но край­не полез­ный про­ект на Python — бота для Telegram. Боты — это неболь­шие скрип­ты, которые могут вза­имо­дей­ство­вать с API, что­бы получать сооб­щения от поль­зовате­ля и отправ­лять информа­цию в раз­ные чаты и каналы.

Python для новичков

Ес­ли ты сов­сем не ори­енти­руешь­ся в Python, то отличным началом будет проч­тение трех ввод­ных ста­тей, которые я пуб­ликовал в «Хакере» этим летом, либо посеще­ние кур­са «Python для нович­ков», который я нач­ну вес­ти для читате­лей «Хакера» уже сов­сем ско­ро — 30 нояб­ря.

  • Python с абсо­лют­ного нуля. Учим­ся кодить без скуч­ных кни­жек
  • Python с абсо­лют­ного нуля. Учим­ся работать со стро­ками, фай­лами и интерне­том
  • Python с абсо­лют­ного нуля. Работа­ем с ОС, изу­чаем регуляр­ные выраже­ния и фун­кции

Что­бы соз­дать бота, нам нуж­но дать ему наз­вание, адрес и получить токен — стро­ку, которая будет однознач­но иден­тифици­ровать нашего бота для сер­веров Telegram. Зай­дем в Telegram под сво­им акка­унтом и откро­ем «отца всех ботов», BotFather.

Жмем кноп­ку «Запус­тить» (или отпра­вим / start ), в ответ BotFather приш­лет нам спи­сок дос­тупных команд:

  • / newbot — соз­дать нового бота;
  • / mybots — редак­тировать ваших ботов;
  • / setname — сме­нить имя бота;
  • / setdescription — изме­нить опи­сание бота;
  • / setabouttext — изме­нить информа­цию о боте;
  • / setuserpic — изме­нить фото ава­тар­ки бота;
  • / setcommands — изме­нить спи­сок команд бота;
  • / deletebot — уда­лить бота.

От­пра­вим бате‑боту коман­ду / newbot , что­бы соз­дать нового бота. В ответ он поп­росит ввес­ти имя будуще­го бота, его мож­но писать на рус­ском. Пос­ле вво­да име­ни нуж­но будет отпра­вить адрес бота, при­чем он дол­жен закан­чивать­ся на сло­во bot. Нап­ример, xakepbot или xakep_bot . Если адрес будет уже кем‑то занят, BotFather нач­нет изви­нять­ся и про­сить при­думать что‑нибудь дру­гое.

Ког­да мы наконец най­дем сво­бод­ный и кра­сивый адрес для нашего бота, в ответ получим сооб­щение, в котором пос­ле фра­зы Use this token to access the HTTP API будет написа­на стро­ка из букв и цифр — это и есть необ­ходимый нам токен. Сох­раним ее где‑нибудь на сво­ем компь­юте­ре, что­бы потом исполь­зовать в скрип­те бота.

Для вза­имо­дей­ствия с Telegram API есть нес­коль­ко готовых модулей. Самый прос­той из них — Telebot. Что­бы уста­новить его, набери

pip install pytelegrambotapi

В Linux, воз­можно, понадо­бит­ся написать pip3 вмес­то pip , что­бы ука­зать, что мы хотим работать с треть­ей вер­сией Python.

Эхо-бот

Для начала реали­зуем так называ­емо­го эхо‑бота. Он будет получать от поль­зовате­ля тек­сто­вое сооб­щение и воз­вра­щать его.

Простой Telegram-бот на Python за 30 минут

На Хабре, да и не только, про ботов рассказано уже так много, что даже слишком. Но заинтересовавшись пару недель назад данной темой, найти нормальный материал у меня так и не вышло: все статьи были либо для совсем чайников и ограничивались отправкой сообщения в ответ на сообщение пользователя, либо были неактуальны. Это и подтолкнуло меня на написание статьи, которая бы объяснила такому же новичку, как я, как написать и запустить более-менее осмысленного бота (с возможностью расширения функциональности).

Часть 1: Регистрация бота

Самая простая и описанная часть. Очень коротко: нужно найти бота @BotFather, написать ему /start, или /newbot, заполнить поля, которые он спросит (название бота и его короткое имя), и получить сообщение с токеном бота и ссылкой на документацию. Токен нужно сохранить, желательно надёжно, так как это единственный ключ для авторизации бота и взаимодействия с ним.

Часть 2: Подготовка к написанию кода

Как уже было сказано в заголовке, писать бота мы будем на Python’е. В данной статье будет описана работа с библиотекой PyTelegramBotAPI (Telebot). Если у вас не установлен Python, то сперва нужно сделать это: в терминале Linux нужно ввести

sudo apt-get install python python-pip

Если же вы пользуетесь Windows, то нужно скачать Python с официального сайта .

После, в терминале Linux, или командной строке Windows вводим

pip install pytelegrambotapi

Теперь все готово для написания кода.

Часть 3: Получаем сообщения и говорим «Привет»

Небольшое отступление. Телеграмм умеет сообщать боту о действиях пользователя двумя способами: через ответ на запрос сервера (Long Poll), и через Webhook, когда сервер Телеграмма сам присылает сообщение о том, что кто-то написал боту. Второй способ явно выглядит лучше, но требует выделенного IP-адреса, и установленного SSL на сервере. В этой статье я хочу рассказать о написании бота, а не настройке сервера, поэтому пользоваться мы будем Long Poll’ом.

Открывайте ваш любимый текстовый редактор, и давайте писать код бота!

Первое, что нужно сделать это импортировать нашу библиотеку и подключить токен бота:

import telebot; bot = telebot.TeleBot('%ваш токен%');

Теперь объявим метод для получения текстовых сообщений:

@bot.message_handler(content_types=['text']) def get_text_messages(message):

В этом участке кода мы объявили слушателя для текстовых сообщений и метод их обработки. Поле content_types может принимать разные значения, и не только одно, например

@bot.message_handler(content_types=['text', 'document', 'audio'])

Будет реагировать на текстовые сообщения, документы и аудио. Более подробно можно почитать в официальной документации

Теперь добавим в наш метод немного функционала: если пользователь напишет нам «Привет», то скажем ему «Привет, чем я могу помочь?», а если нам напишут команду «/help», то скажем пользователю написать «Привет»:

if message.text == "Привет": bot.send_message(message.from_user.id, "Привет, чем я могу тебе помочь?") elif message.text == "/help": bot.send_message(message.from_user.id, "Напиши привет") else: bot.send_message(message.from_user.id, "Я тебя не понимаю. Напиши /help.")

Данный участок кода не требует комментариев, как мне кажется. Теперь нужно добавить в наш код только одну строчку (вне всех методов).

bot.polling(none_stop=True, interval=0)

Теперь наш бот будет постоянно спрашивать у сервера Телеграмма «Мне кто-нибудь написал?», и если мы напишем нашему боту, то Телеграмм передаст ему наше сообщение. Сохраняем весь файл, и пишем в консоли

python bot.py

Где bot.py – имя нашего файла.

Теперь можно написать боту и посмотреть на результат:

image

Часть 4: Кнопки и ветки сообщений

Отправлять сообщения это несомненно весело, но ещё веселее вести с пользователем диалог: задавать ему вопросы и получать на них ответы. Допустим, теперь наш бот будет спрашивать у пользователя по очереди его имя, фамилию и возраст. Для этого мы будем использовать метод register_next_step_handler бота:

name = ''; surname = ''; age = 0; @bot.message_handler(content_types=['text']) def start(message): if message.text == '/reg': bot.send_message(message.from_user.id, "Как тебя зовут?"); bot.register_next_step_handler(message, get_name); #следующий шаг – функция get_name else: bot.send_message(message.from_user.id, 'Напиши /reg'); def get_name(message): #получаем фамилию global name; name = message.text; bot.send_message(message.from_user.id, 'Какая у тебя фамилия?'); bot.register_next_step_handler(message, get_surnme); def get_surname(message): global surname; surname = message.text; bot.send_message('Сколько тебе лет?'); bot.register_next_step_handler(message, get_age); def get_age(message): global age; while age == 0: #проверяем что возраст изменился try: age = int(message.text) #проверяем, что возраст введен корректно except Exception: bot.send_message(message.from_user.id, 'Цифрами, пожалуйста'); bot.send_message(message.from_user.id, 'Тебе '+str(age)+' лет, тебя зовут '+name+' '+surname+'?') 

И так, данные пользователя мы записали. В этом примере показан очень упрощённый пример, по хорошему, хранить промежуточные данные и состояния пользователя нужно в БД, но мы сегодня работаем с ботом, а не с базами данных. Последний штрих – запросим у пользователей подтверждение того, что все введено верно, да не просто так, а с кнопками! Для этого немного отредактируем код метода get_age

def get_age(message): global age; while age == 0: #проверяем что возраст изменился try: age = int(message.text) #проверяем, что возраст введен корректно except Exception: bot.send_message(message.from_user.id, 'Цифрами, пожалуйста'); keyboard = types.InlineKeyboardMarkup(); #наша клавиатура key_yes = types.InlineKeyboardButton(text='Да', callback_data='yes'); #кнопка «Да» keyboard.add(key_yes); #добавляем кнопку в клавиатуру key_no= types.InlineKeyboardButton(text='Нет', callback_data='no'); keyboard.add(key_no); question = 'Тебе '+str(age)+' лет, тебя зовут '+name+' '+surname+'?'; bot.send_message(message.from_user.id, text=question, reply_markup=keyboard) 

И теперь наш бот отправляет клавиатуру, но если на нее нажать, то ничего не произойдёт. Потому что мы не написали метод-обработчик. Давайте напишем:

@bot.callback_query_handler(func=lambda call: True) def callback_worker(call): if call.data == "yes": #call.data это callback_data, которую мы указали при объявлении кнопки . #код сохранения данных, или их обработки bot.send_message(call.message.chat.id, 'Запомню : )'); elif call.data == "no": . #переспрашиваем 

Остаётся только дописать в начало файла одну строку:

from telebot import types

Вот и всё, сохраняем и запускаем нашего бота:

Как создать Telegram-бота для мониторинга погоды на Python

В статье делимся пошаговой инструкцией, как написать Telegram-бота для получения данных о погоде и задеплоить его на виртуальный сервер.

Введение

Всем привет! Меня зовут Максим Плачковский, я автор канала PythonToday. Из этой статьи вы узнаете, как написать своего Telegram-бота для получения данных о погоде в любом городе нашей планеты. Мы детально рассмотрим работу с API, парсинг JSON и напишем бота на асинхронной библиотеке aiogram. А после — загрузим его на виртуальный сервер и запустим.

Подготовка API и рабочего окружения

Перед написанием кода нужно получить API-токены для работы с сервисом OpenWeather и Telegram-ботом, а также подготовить рабочее окружение.

Получаем токен OpenWeather

Начнем с самого простого: зарегистрируемся на официальном сайте и в разделе My API keys создадим токен.

После того, как вы создали API-ключ, дайте ему немного «отлежаться» — обычно это занимает 10-15 минут. Спустя это время можно общаться с OpenWeather с помощью сгенерированного токена.

Генерируем токен для Telegram-бота

Ключ для Telegram-бота можно получить у @BotFather, введя /newbot — команду для создания и регистрации нового бота. Во время настройки придумайте боту логин и название — например, Weather Bot. Есть также опциональные настройки: текст приветствия, изображение. Используйте, если хотите получить более уникального бота!

Импортируем необходимые библиотеки

Для работы нам понадобятся модули requests и aiogram — установим их.

pip install requests aiogram

После импортируем модули и классы в файл нашего пет-проекта.

import os import datetime import requests from aiogram import Bot, types from aiogram.dispatcher import Dispatcher from aiogram.utils import executor bot = Bot(token='your_bot_token') dp = Dispatcher(bot)

Создание бота

Первое сообщение

Для начала проверим, что aiogram увидел бота и мы можем с ним взаимодействовать. Создадим простую асинхронную функцию start_command для ответа на команду /start . И добавляем метод start_polling для запуска бота.

import os import datetime import requests from aiogram import Bot, types from aiogram.dispatcher import Dispatcher from aiogram.utils import executor bot = Bot(token='your_bot_token') dp = Dispatcher(bot) @dp.message.handler(commands=["start"]) async def start_command(message: types.Message): await message.reply("Привет! Напиши мне название города и я пришлю сводку погоды") if __name__ == "__main__": # С помощью метода executor.start_polling опрашиваем # Dispatcher: ожидаем команду /start executor.start_polling(dp)

Запускаем скрипт, заходим в Telegram и пишем команду /start — все работает: бот возвращает нужное сообщение.

Обрабатываем входные данные

Теперь добавим функцию, которая будет реагировать на текстовые сообщения с названиями городов. Она должна проверять их на корректность и выводить ошибку, если валидация не была пройдена.

@dp.message_handler() async def get_weather(message: types.Message): pass 

OpenWeather должен принимать название города через API и возвращать данные о погоде. Исходя из документации, кроме названия города запрос должен содержать API-токен.

Усовершенствуем запрос: в параметр q будем передавать город, добавим параметр lang=ru , чтобы API работал с кириллицей. А также используем units=metric для установки метрической системы:

http://api.openweathermap.org/data/2.5/weather?q=москва&lang=ru&units=metric&appid=наш_токен

Теперь добавим блок try-except для обработки пользовательских запросов и создадим переменную для записи результатов OpenWeather, которые возвращает сервис в JSON-формате.

@dp.message_handler() async def get_weather(message: types.Message): try: response = requests.get( f"http://api.openweathermap.org/data/2.5/weather?q=москва&lang=ru&units=metric&appid=your_token" ) data = response.json() except: await message.reply("Проверьте название города!")

Отправим запрос через браузер и посмотрим, какая температура, например, в Бангкоке.

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

Парсим JSON

Приступим к парсингу ответа OpenWeather в формате JSON: заберем данные о городе и температуре, влажности, давлении и скорости ветра.

city = data["name"] cur_temp = data["main"]["temp"] humidity = data["main"]["humidity"] pressure = data["main"]["pressure"] wind = data["wind"]["speed"]

OpenWeather возвращает время рассвета и заката в формате unix timestamp. Извлечем эти данные и преобразуем в секунды.

# получаем время рассвета и преобразуем его в читабельный формат sunrise_timestamp = datetime.datetime.fromtimestamp(data["sys"]["sunrise"]) # то же самое проделаем со временем заката sunset_timestamp = datetime.datetime.fromtimestamp(data["sys"]["sunset"])

Зная время рассвета и заката, мы можем вернуть пользователю продолжительность дня. В результате получается следующее:

@dp.message_handler() async def get_weather(message: types.Message): try: response = requests.get( f"http://api.openweathermap.org/data/2.5/weather?q=москва&lang=ru&units=metric&appid=your_token" ) data = response.json() city = data["name"] cur_temp = data["main"]["temp"] humidity = data["main"]["humidity"] pressure = data["main"]["pressure"] wind = data["wind"]["speed"] sunrise_timestamp = datetime.datetime.fromtimestamp(data["sys"]["sunrise"]) sunset_timestamp = datetime.datetime.fromtimestamp(data["sys"]["sunset"]) # продолжительность дня length_of_the_day = datetime.datetime.fromtimestamp(data["sys"]["sunset"]) - datetime.datetime.fromtimestamp(data["sys"]["sunrise"]) except: await message.reply("Проверьте название города!")

Декорируем сообщения

Разнообразим текст сообщений — будем выводить разные эмодзи в зависимости от погоды.

У словаря, который мы ранее спарсили, есть ключ main — он хранит описание погоды. На его основе мы можем создать свою коллекцию с эмодзи под разные ситуации.

code_to_smile =

Также напишем условие, чтобы в случае специфической погоды, для которой эмодзи не предусмотрен, программа не ломалась, а выводила специальное сообщение.

# получаем значение погоды weather_description = data["weather"][0]["main"] if weather_description in code_to_smile: wd = code_to_smile[weather_description] else: # если эмодзи для погоды нет, выводим другое сообщение wd = "Посмотри в окно, я не понимаю, что там за погода. "

Возвращаем данные пользователю

Данные собрали — время отдать их пользователю. Сформируем строки с датой и временем, погодой, влажностью и другими данными. Главное — учесть формат данных. Например, OpenWeather возвращает значение давления в гектопаскалях. Так, если вы хотите отдавать пользователю данные в миллиметрах ртутного столба, значение нужно разделить на 1.33 и округлить в большую сторону.

await message.reply(f""\n f"Погода в городе: \nТемпература: °C \n" f"Влажность: %\nДавление: мм.рт.ст\nВетер: м/с \n" f"Восход солнца: \nЗакат солнца: \nПродолжительность дня: \n" f"Хорошего дня!" )

Супер — бот работает и возвращает данные в удобочитаемом формате!

Деплой бота

Сейчас синоптик запущен на компьютере. Это неудобно, если вы хотите общаться с ним круглосуточно. Ведь тогда нужно поддерживать бесперебойную работу компьютера и постоянное соединение с интернетом.

Облачные серверы с гибкой производительностью ядра vCPU

Бота лучше перенести в облако. Поскольку затраты процессора на работу с простым Open Weather API минимальны, будет достаточно виртуального сервера с 1 vCPU и 1 ГБ оперативной памяти. С учетом выделенного IP-адреса такая конфигурация выйдет примерно в 30 ₽/день.

Для начала зарегистрируемся в панели управления и создадим новый сервер в разделе Облачная платформа. Затем настроим его.

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

Последним шагом нужно создать .service-файл, который будет автоматически поднимать бота в случае перезагрузки сервера.

Запускаем командой: systemctl enable tg_bot.service

Проверяем статус: systemctl status tg_bot.service

И перезапускаем .service-файл: systemctl restart tg_bot.service

Все готово: бот стабильно работает на сервере и автоматически поднимается в случае перезагрузки.

Заключение

Следуя инструкции, каждый может создать бота для мониторинга погоды. А использование виртуальной машины из линейки Shared Line позволит избежать капитальных затрат. Платите только за потребленные ботом мощности по модели pay-as-you-go, а также экономьте на неполной загрузке ядра.

Автор: Максим Плачковский, создатель канала PythonToday

Зарегистрируйтесь в панели управления

И уже через пару минут сможете арендовать сервер, развернуть базы данных или обеспечить быструю доставку контента.

Читайте также:

Инструкция

Как автоматизировать подготовку к собеседованиям с помощью Telegram-бота

29 сентября 2023

Инструкция

Как реализовать очередь в Redis

14 сентября 2023

Инструкция

Как генерировать истории с помощью ChatGPT и Telegram

Введение, простой echo-бот

Приветствую тебя, читатель! Telegram Bot API – это мощный инструмент для вообще чего угодно. Автоматизация действий, работа с пользователями, онлайн-магазины, игры и много чего ещё. В этом учебнике мы научимся писать ботов для Telegram на языке Python.

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

Язык программирования будет Python 3, но это не означает, что любители PHP, Ruby и т.д. в пролёте; все основные принципы совпадают. Я не буду особо останавливаться на описании самого языка, желающие могут ознакомиться с документацией по Python здесь.

Подготовка к запуску

Взаимодействие ботов с людьми основано на HTTP-запросах. Чтобы не мучаться с обработкой «сырых» данных, воспользуемся библиотекой pyTelegramBotAPI, которая берет на себя все нюансы отправки и получения запросов, позволяя сконцентрироваться непосредственно на логике. Установка библиотеки предельно простая:

pip install pytelegrambotapi python3 

Скриншот из терминала с запущенным интерпретатором Python

Обратите внимание: библиотека называется pyTelegramBotAPI , а не telebot . Последнюю ставить не нужно!

Теперь можно выйти из режима Python-консоли (Ctrl+Z или Ctrl+D, или exit() )

Пишем простого echo-бота

Ну, довольно слов, перейдем к делу. В качестве практики к первому уроку, напишем бота, повторяющего присланное текстовое сообщение. Создадим каталог, а внутри него 2 файла: bot.py и config.py . Я рекомендую выносить различные константы и настройки в файл config.py , дабы не загромождать другие. В файл config.py впишем:

# Токен ненастоящий :) Подставьте свой token = '1234567890:AAE_abCDEFghijKLmNOpqRsTuVWxyz' 

Теперь надо научить бота реагировать на сообщения. Напишем обработчик, который будет реагировать на все текстовые сообщения.

@bot.message_handler(content_types=["text"]) def repeat_all_messages(message): # Название функции не играет никакой роли bot.send_message(message.chat.id, message.text) 

У читателя возникнет вопрос: зачем там символ “@”? Что это вообще за message_handler ? Дело в том, что после приёма сообщения от Telegram его надо обработать по-разному в зависимости от того, что это за сообщение: текст “привет” или текст “пока”, может быть, вообще стикер или музыка. Первое, что придёт в голову – написать множество конструкций if-then-else , но такой подход некрасивый и позволяет быстро запутаться.
Для решения этой проблемы автор библиотеки pyTelegramBotAPI реализовал механизм хэндлеров, которые используют питоновские декораторы (пока просто запомним это слово). В хэндлере описывается, в каком случае необходимо выполнять ту или иную функцию. Например, хэндлер @bot.message_handler(content_types=[«text»]) выполнит нижестоящую функцию, если от Telegram придёт текстовое сообщение, а хэндлер @bot.message_handler(commands=[«start»]) сработает при получении команды /start.

Теперь запустим бесконечный цикл получения новых записей со стороны Telegram:

if __name__ == '__main__': bot.infinity_polling() 

Функция infinity_polling запускает т.н. Long Polling, бот должен стараться не прекращать работу при возникновении каких-либо ошибок. При этом, само собой, за ботом нужно следить, ибо сервера Telegram периодически перестают отвечать на запросы или делают это с большой задержкой приводя к ошибкам 5xx)

Итак, полный код файла bot.py выглядит следующим образом:

import config import telebot bot = telebot.TeleBot(config.token) @bot.message_handler(content_types=["text"]) def repeat_all_messages(message): # Название функции не играет никакой роли bot.send_message(message.chat.id, message.text) if __name__ == '__main__': bot.infinity_polling() 

Готово! Осталось запустить бота: python3 bot.py

Бот работает

На этом первый урок окончен.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *