Telegram Bot на Python. Часть 2. PyCharm. Python3. Пишем код.

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

Часть 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

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

В этой статье мы реали­зуем прос­той, но край­не полез­ный про­ект на 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.

Эхо-бот

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

import telebot # Создаем экземпляр ботаbot = telebot.TeleBot('Здесь впиши токен, полученный от @botfather') # Функция, обрабатывающая команду /start@bot.message_handler(commands=["start"])def start(m, res=False): bot.send_message(m.chat.id, на связи. Напиши мне что-нибудь )') # Получение сообщений от юзера@bot.message_handler(content_types=["text"])def handle_text(message): bot.send_message(message.chat.id, 'Вы написали: ' + message.text) # Запускаем ботаbot.polling(none_stop=True, interval=0)

За­пус­кай скрипт и ищи в поис­ке Telegram сво­его бота по адре­су, который ты при­думал ранее. Запус­каем бота кноп­кой «Запус­тить» (Start) или коман­дой / start и можем убе­дить­ся в том, что он работа­ет и воз­вра­щает сооб­щения.

При­мер работы эхо‑бота

Wikipedia-бот

Да­вай научим нашего бота не прос­то отсы­лать сооб­щения обратно, а чему‑нибудь поин­терес­нее. Нап­ример, по вве­ден­ному сло­ву давать статью на Википе­дии. Здесь нам поможет модуль Wikipedia:

pip install wikipedia

Го­товим код.

import telebot, wikipedia, re # Создаем экземпляр ботаbot = telebot.TeleBot('Здесь впиши токен, полученный от @botfather') # Устанавливаем русский язык в Wikipediawikipedia.set_lang("ru") # Чистим текст статьи в Wikipedia и ограничиваем его тысячей символовdef getwiki(s): try: ny = wikipedia.page(s) # Получаем первую тысячу символов wikitext=ny.content[:1000] # Разделяем по точкам wikimas=wikitext.split('.') # Отбрасываем всЕ после последней точки wikimas = wikimas[:-1] # Создаем пустую переменную для текста wikitext2 = '' # Проходимся по строкам, где нет знаков «равно» (то есть все, кроме заголовков) for x in wikimas: if not('==' in x): # Если в строке осталось больше трех символов, добавляем ее к нашей переменной и возвращаем утерянные при разделении строк точки на место if(len((x.strip()))>3): wikitext2=wikitext2+x+'.' else: break # Теперь при помощи регулярных выражений убираем разметку wikitext2=re.sub('([^()]*)', '', wikitext2) wikitext2=re.sub('([^()]*)', '', wikitext2) wikitext2=re.sub('{[^{}]*}', '', wikitext2) # Возвращаем текстовую строку return wikitext2 # Обрабатываем исключение, которое мог вернуть модуль wikipedia при запросе except Exception as e: return энциклопедии нет информации об этом' # Функция, обрабатывающая команду /start@bot.message_handler(commands=["start"])def start(m, res=False): bot.send_message(m.chat.id, 'Отправьте мне любое слово, и я найду его значение на Wikipedia') # Получение сообщений от юзера@bot.message_handler(content_types=["text"])def handle_text(message): bot.send_message(message.chat.id, getwiki(message.text)) # Запускаем ботаbot.polling(none_stop=True, interval=0)

При­мер работы Wikipedia-бота

Другие статьи в выпуске:

Xakep #272. Приручаем WinAFL

  • Содержание выпуска
  • Подписка на «Хакер»-70%

www

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

Бот с двумя виртуальными кнопками

Во мно­гих Telegram-ботах для выбора каких‑то дей­ствий исполь­зуют­ся так называ­емые вир­туаль­ные кноп­ки. Давай поп­робу­ем сде­лать себе такие же!

Пред­положим, что у нас есть два фай­ла facts. txt и thinks. txt, которые содер­жат спи­сок инте­рес­ных фак­тов и поговор­ки. На каж­дой стро­ке фай­лов находит­ся по одно­му фак­ту или поговор­ке.

Сде­лаем бота, в котором будут две кноп­ки: «Фак­ты» и «Поговор­ки». Если нажать любую, бот отпра­вит поль­зовате­лю соот­ветс­тву­ющее сооб­щение.

info

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

import telebotimport randomfrom telebot import types # Загружаем список интересных фактовf = open('data/facts.txt', 'r', encoding='UTF-8')facts = f.read().split('n')f.close() # Загружаем список поговорокf = open('data/thinks.txt', 'r', encoding='UTF-8')thinks = f.read().split('n')f.close() # Создаем ботаbot = telebot.TeleBot('Здесь твой токен, полученный от @botfather') # Команда start@bot.message_handler(commands=["start"])def start(m, res=False): # Добавляем две кнопки markup=types.ReplyKeyboardMarkup(resize_keyboard=True) item1=types.KeyboardButton("Факт") item2=types.KeyboardButton("Поговорка") markup.add(item1) markup.add(item2) bot.send_message(m.chat.id, 'Нажми: nФакт для получения интересного фактаnПоговорка для получения мудрой цитаты ', reply_markup=markup) # Получение сообщений от юзера@bot.message_handler(content_types=["text"])def handle_text(message): # Если юзер прислал 1, выдаем ему случайный факт if message.text.strip() == 'Факт' : answer = random.choice(facts) # Если юзер прислал 2, выдаем умную мысль elif message.text.strip() == 'Поговорка': answer = random.choice(thinks) # Отсылаем юзеру сообщение в его чат bot.send_message(message.chat.id, answer) # Запускаем ботаbot.polling(none_stop=True, interval=0)

При­мер работы бота, зна­юще­го фак­ты и поговор­ки

Бот, ведущий Telegram-канал с анекдотами

Пре­дыду­щие боты посыла­ли юзе­ру сооб­щения тог­да, ког­да получа­ли от него коман­ды или фра­зы. Но что, если нам нужен бот, который будет пери­оди­чес­ки и в авто­мати­чес­ком режиме пос­тить что‑то в наш канал?

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

Файл с анек­дотами дол­жен лежать в пап­ке data рядом со скрип­том бота.

import telebotimport time # Токен, который выдает @botfatherbot = telebot.TeleBot('Здесь твой токен, полученный от @botfather')# Адрес телеграм-канала, начинается с @CHANNEL_NAME = '@адрес_твоего_канала' # Загружаем список шутокf = open('data/fun.txt', 'r', encoding='UTF-8')jokes = f.read().split('n')f.close() # Пока не закончатся шутки, посылаем их в каналfor joke in jokes: bot.send_message(CHANNEL_NAME, joke) # Делаем паузу в один час time.sleep(3600) bot.send_message(CHANNEL_NAME, "Анекдоты закончились :-(")

При­мер работы бота, ведуще­го канал с анек­дотами

Чат-бот «Маша»

Те­перь давай сде­лаем прос­тей­шего чат‑бота, который будет бол­тать с поль­зовате­лем. Для это­го мы под­готовим файл boltun. txt, содер­жащий стро­ки с воп­росами (в начале таких строк пос­тавим мет­ку u:) и отве­тами на них в сле­дующей стро­ке.

u: как зовутМаша меня зовут!u: сколько тебе летМне уже 18, честно-честно!

Файл boltun. txt помес­тим в пап­ку data рядом со скрип­том бота. Для поис­ка похожих воп­росов исполь­зуем модуль fuzzywuzzy, который поз­воля­ет срав­нивать, нас­коль­ко похожи меж­ду собой две стро­ки. Естес­твен­но, спер­ва этот модуль нуж­но уста­новить:

pip install fuzzywuzzypip install python-Levenshtein

Ни­же при­веден исходный код бота. Пос­ле его запус­ка напиши боту «При­вет» и поп­робуй с ним пооб­щать­ся. Естес­твен­но, это не искусс­твен­ный интеллект и набор его отве­тов огра­ничен фра­зами из фай­ла boltun. txt.

import telebotimport osfrom fuzzywuzzy import fuzz # Создаем бота, пишем свой токенbot = telebot.TeleBot('Здесь твой токен, полученный от @botfather') # Загружаем список фраз и ответов в массивmas=[]if os.path.exists('data/boltun.txt'): f=open('data/boltun.txt', 'r', encoding='UTF-8') for x in f: if(len(x.strip()) > 2): mas.append(x.strip().lower()) f.close() # С помощью fuzzywuzzy вычисляем наиболее похожую фразу и выдаем в качестве ответа следующий элемент спискаdef answer(text): try: text=text.lower().strip() if os.path.exists('data/boltun.txt'): a = 0 n = 0 nn = 0 for q in mas: if('u: ' in q): # С помощью fuzzywuzzy получаем, насколько похожи две строки aa=(fuzz.token_sort_ratio(q.replace('u: ',''), text)) if(aa > a and aa!= a): a = aa nn = n n = n + 1 s = mas[nn + 1] return s else: return 'Ошибка' except: return 'Ошибка' # Команда «Старт»@bot.message_handler(commands=["start"])def start(m, res=False): bot.send_message(m.chat.id, на связи. Напиши мне Привет )') # Получение сообщений от юзера@bot.message_handler(content_types=["text"])def handle_text(message): # Запись логов f=open('data/' + str(message.chat.id) + '_log.txt', 'a', encoding='UTF-8') s=answer(message.text) f.write('u: ' + message.text + 'n' + s +'n') f.close() # Отправка ответа bot.send_message(message.chat.id, s) # Запускаем ботаbot.polling(none_stop=True, interval=0)

При­мер работы чат‑бота

Выводы

Мы написа­ли пять прос­тых ботов, на при­мере которых научи­лись при­нимать и отправ­лять сооб­щения, делать кноп­ки и понимать неточ­ные зап­росы.

В сле­дующей статье мы рас­смот­рим работу с Telegram-ботами более под­робно: научим­ся делать ботов, работа­ющих через веб‑хуки, при­нимать опла­ту от поль­зовате­лей и вза­имо­дей­ство­вать с базой дан­ных SQLite.

Так­же при­зываю тебя не откла­дывать и записы­вать­ся на курс «Python для нович­ков», где мы от прос­тей­ших понятий перей­дем к соз­данию пер­вых инте­рес­ных про­ектов. Стар­туем уже сов­сем ско­ро!

Курс по Python

Курс «Python с нуля» нап­равлен на изу­чение основ и базовых кон­цепций прог­рамми­рова­ния. Пос­ле него ты смо­жешь лег­ко углу­бить­ся в любую из ИТ‑сфер: веб‑раз­работ­ку, ана­лиз дан­ных, безопас­ность при­ложе­ний и так далее. Про­дол­житель­ность кур­са — два кален­дарных месяца. Уро­ки будут про­водить­ся два раза в неделю (втор­ник и чет­верг, ори­енти­ровоч­но в 17:00 по Мос­кве), каж­дый по одно­му ака­деми­чес­кому часу. Пери­оди­чес­ки будут выдавать­ся домаш­ние задания.

За­писать­ся на курс

← Ранее Интерпол сообщил об аресте 1000 человек, связанных с киберпреступностью Далее → HTB Intelligence. Пентестим Active Directory от MSA до KDC Интенсив «Научитесь собирать информацию с сайтов с помощью парсера на Python» tproger.ru События и курсы на tproger.ru

Ну вот и всё, простенький бот в Телеграмме на языке Python готов.

Docker

Сейчас мало кто не слышал про Docker, но если вдруг не слышали — вот хорошая статья. Для нашего проекта потребуется самый простой Dockerfile:

FROM python:3.8  # set work directory  WORKDIR /usr/src/app/  # copy project  COPY . /usr/src/app/  # install dependencies  RUN pip install --user aiogram  # run app  CMD ["python", "bot.py"]

Каталог проекта должны при этом содержать следующие файлы:

  • bot.py;
  • Dockerfile.

Для локальных тестов достаточно установить Docker (linux, mac, windows), после чего в папке проекта собрать и запустить контейнер с помощью команд:

docker build -t my_app  docker run -d my_app  

my_app — это просто название нашего контейнера, вместо которого можно использовать другое имя.

-d — специальный флаг, который запускает контейнер в фоне и позволяет дальше работать в терминале. Это называется detached mode.

Деплой на AWS

Прежде всего нам понадобится аккаунт на Docker Hub. Это аналог GitHub, только не с исходниками кода, а с уже созданными контейнерами. Работа с Docker Hub выглядит достаточно просто:

  1. Локально или с помощью пайплайнов собрали контейнер.
  2. Загрузили его на докер хаб.
  3. В любом удобном месте скачали его. Это может быть локальная машина, VPS сервер или облачный провайдер по типу AWS.
  4. Запустили.

Пройдёмся по этим шагам. Везде, где указано , надо вставлять свой юзернейм, использованный при регистрации на докерхабе. Если это ваша первая публикация на докерхаб, для начала потребуется залогиниться с помощью docker login.

Билдим контейнер:

docker build -t /my_app

Загружаем его на докерхаб:

docker push /my_app

Для проверки успешности загрузки можете запустить контейнер из Docker Hub с помощью команды:

docker run -d /my_app

Далее загрузим наш контейнер в AWS Elastic Beanstalk. Для этого потребуется аккаунт на AWS. Если его нет, необходимо зарегистрироваться. Вас попросят ввести данные карты для верификации, но переживать не стоит, ведь мы воспользуемся бесплатным годовым триалом. Чтобы поиграться, этого более чем достаточно, а вот если вы захотите вывести проект в продакшен, следует перейти на VPS — это даст больше контроля и гибкости.

  • Переходим в Elastic Beanstalk, на вкладку Applications, и создаём новое приложение:
  • Называем приложение, теги оставляем пустыми:
  • Создаём для приложения environment:
  • Выбираем Worker environment:
  • В качестве платформы выбираем Docker:
  • В пункте Application code нужно загрузить JSON-файл с конфигурацией Docker-образа. Сам файл:
Dockerrun.aws.json  {   "AWSEBDockerrunVersion": "1",   "Image": {     "Name": "/my_app",     "Update": "true"   },  "Ports": [   {     "ContainerPort": 5000,     "HostPort": 8000   }  ]  }  
  • Создаём окружение:
  • AWS начинает создавать окружение, просто ждём завершения процесса:
  • Если всё прошло успешно, вы увидите индикатор успешного запуска приложения:

Проверяем работу нашего Telegram bot:

Успех!

Заключение

Поздравляем! Теперь вы знаете, как писать роботов для Telegram на Python.

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

Кстати, в телеграмме есть аж целых два типа клавиатур:

  1. Классическая RelpyKeyboardMarkup, у которой кнопки располагаются под полем ввода сообщения:
  2. Более современная InlineKeyboardMarkup, которая привязывается к конкретному сообщению:

Но и это полностью рабочий Телеграм-бот на Python: дополните словарём, и получите полноценную беседу. Также можете опробовать функциональность нашего Telegram-бота.

В «настоящих проектах» не обойтись без базы данных. Тут на помощь приходит docker-compose, который позволяет объединить несколько контейнеров в один сервис. Таким образом, например, можно создать приложение и положить его в контейнер, а базу данных, как отдельный сервис, поместить в другой контейнер, и с помощью docker-compose наладить между ними связь.

Также для более серьёзной разработки лучше использовать выделенный виртуальный сервер (VPS): он даёт гораздо больше гибкости и свободы, чем тот же AWS. А самое главное, он более приближён к «боевой» разработке. Схема работы тут будет даже проще, чем с AWS: вам просто нужно установить Docker, спуллить образ с Docker Hub и запустить его.

28 июля 2017

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

Без бота это выглядело бы так:

  1. Вы открываете в веб-браузере YouTube.
  2. Ищете видео, которым хотите поделиться.
  3. Выбираете общий доступ.
  4. Возвращаетесь в мессенджер и, наконец, делитесь ссылкой.

Конечно, большинство из нас привыкло к вышеуказанному алгоритму, и это неплохо работает. Однако…

С ботом:

  1. Вы находитесь в мессенджере.
  2. Вводите @vid, а затем видео, которым хотите поделиться.

И это всего лишь одна из возможностей ботов. Разработчики Telegram проделали отличную работу и позволили пользователям создавать своих собственных ботов. Отвечая на вопрос, почему это может быть интересно, я могу сказать, что это самый простой способ получить представление об API.

Прежде всего, зарегистрируйтесь. Рекомендую использовать веб-клиент. Откройте кроссплатформенный мессенджер, найдите @BotFather и запустите чат. Отправьте в сообщении /newbot и следуйте инструкциям. После завершения начальных шагов вы получите:

– токен; – API URL; – ссылку на документацию.

На момент создания бот 100% пассивен. Вам нужно инициализировать разговор. Для этого откройте поиск и введите имя своего бота, а после начните разговор, нажав /start. Введите что-то вроде «Hello». Это сообщение важно, поскольку это первое обновление, которое получит ваш бот.

Если это первый опыт, откройте новую вкладку в своем браузере и используйте /getUpdates” target=”_blank” rel=”noopener noreferrer”>URL-адрес: так вы отправите запрос на сервер Telegram. Пришедший ответ будет в формате JSON и чем-то напоминающим словарь Python. Вы должны увидеть что-то вроде этого:

{"ok":true,"result":[{"update_id":523349956,  "message":{"message_id":51,"from":{"id":303262877,"first_name":"YourName"},"chat":{"id":303262877,"first_name":"YourName","type":"private"},"date":1486829360,"text":"Hello"}}]}

Если вы откроете документацию и заглянете на раздел /sendMessage, то заметите, что требуется 2 дополнительных параметра: chat_id и text. В строке поиска браузера можно использовать ? для первого параметра и & для остальных. Отправка сообщения будет выглядеть следующим образом:

/sendMessage?chat_id=303262877&text=test

Для ответа от бота замените chat_id на значение, которое получите с вызовом /getUpdates.  У нас это 303262877. Текстовый параметр зависит от вас. Запрос должен выглядеть так:

https://api.telegram.org/bot/sendMessage?chat_id=303262877&text=Hello

Если ваша операционная система – Windows, но еще не установлен Python, скачайте его здесь. Без разницы, будет это версия 2.x или 3.x. Для примера мы будем использовать Python 3.x. На macOS и Linux обе версии уже установлены (либо минимум Python 2.x), поэтому нет необходимости дополнительно скачивать что-либо.

Следующий шаг – установка системы управления пакетами pip. Для Python 2.7.9 и выше, а также Python 3.4 и выше они уже предустановленны (равно как и для операционных систем macOS/Linux). Если нужно, вы всегда можете проверить это, используя в терминале команду pip –version. При отсутствии данной системы установите ее с помощью команды:

$ sudo apt-get install python-pip.

Интересная штука: разные версии Python работают с разными pip. Для обладателей macOS подойдет эта инструкция. Если же у вас ОС Windows, загрузите get-pip.py, откройте cmd, перейдите к скачанным файлам (директория) и выполните следующее:

$ python get-pip.py

Это было самое сложное. Осталось воспользоваться pip и установить пакет requests:

$ pip install requests

Дополнительно можно скачать PyCharm, хотя этот шаг и не относится к обязательным.

Если принцип API понятен, и у вас есть все необходимые инструменты, давайте создадим скрипт Python, который будет проверять наличие обновлений и отвечать на них желаемым текстом.

Прежде всего, наш Telegram бот должен проверять наличие обновлений. Сообщение можно рассматривать как самое последнее из них. Так или иначе, getUpdates вернет все обновления за последние 24 часа. Давайте создадим небольшой скрипт, чтобы получить последнее обновление:

import requests    url = "https://api.telegram.org/bot/"      def get_updates_json(request):        response = requests.get(request + 'getUpdates')      return response.json()      def last_update(data):        results = data['result']      total_updates = len(results) - 1      return results[total_updates]

Словарь обновлений состоит из двух элементов – «ok» и «results». Нам нужен второй, который представляет собой список всех обновлений за последние 24 часа. Здесь вы можете посмотреть дополнительную информацию о библиотеке запросов. Основная идея заключается в том, что всякий раз, когда вам нужно получать, обновлять или удалять информацию на сервере, вы отправляете запрос и принимаете ответ.

Следующий шаг – добавление еще 2-х функций. Первая получит chat_id от обновления, а вторая отправит сообщение:

def get_chat_id(update):        chat_id = update['message']['chat']['id']      return chat_id    def send_mess(chat, text):        params = {'chat_id': chat, 'text': text}      response = requests.post(url + 'sendMessage', data=params)      return response    chat_id = get_chat_id(last_update(get_updates_json(url)))    send_mess(chat_id, 'Your message goes here')

Помните, как мы привязывали параметры с помощью ? и &? Вы можете сделать то же самое, добавив dict в качестве второго необязательного параметра для запросов get/post.

Telegram скрипт готов

Однако он еще далек от идеала. Главный недостаток заключается в том, что вам нужно запускать скрипт каждый раз, когда вы хотите обменяться сообщениями с ботом. Давайте исправим это. Чтобы заставить нашего бота слушать сервер для получения обновлений, необходимо запустить главный цикл. Добавьте from time import sleep после import requests и замените 2 последние строки на:

def main():        update_id = last_update(get_updates_json(url))['update_id']      while True:          if update_id == last_update(get_updates_json(url))['update_id']:             send_mess(get_chat_id(last_update(get_updates_json(url))), 'test')             update_id += 1      sleep(1)           if __name__ == '__main__':        main()

Хотя мы добавили «тайм-аут» в 1 секунду, приведенный выше пример должен использоваться только в целях тестирования, поскольку он использует частые опросы. Это не очень хорошо для серверов Telegram. Есть еще два способа получить обновления через API – вебхуки и длинные опросы. Но так как мы проверяем обновления с использованием метода getUpdates, запросы будут частыми.

Поскольку мы использовали основной цикл, следует переключиться на длинные опросы. Изменим первую функцию, добавив параметр timeout. Тайм-аут сам по себе не сделает проверку скрипта для обновления реже. Кроме того, тайм-аут будет работать только в том случае, если последние обновления отсутствуют. Для отметки просмотренных обновлений нужно добавить параметр offset:

def get_updates_json(request):        params = {'timeout': 100, 'offset': None}      response = requests.get(request + 'getUpdates', data=params)      return response.json()

Теперь бот должен работать нормально, но немного изменим код

Неплохо было бы инкапсулировать использованные функции в класс. Модифицированная версия скрипта будет выглядеть таким образом:

import requests    import datetime    class BotHandler:        def __init__(self, token):          self.token = token          self.api_url = "https://api.telegram.org/bot{}/".format(token)        def get_updates(self, timeout=30):          method = 'getUpdates'          params = {'timeout': timeout}          resp = requests.get(self.api_url + method, params)          result_json = resp.json()['result']          return result_json        def send_message(self, chat_id, text):          params = {'chat_id': chat_id, 'text': text}          method = 'sendMessage'          resp = requests.post(self.api_url + method, params)          return resp        def get_last_update(self):          get_result = self.get_updates()            if len(get_result) > 0:              last_update = get_result[-1]          else:              last_update = get_result[len(get_result)]            return last_update

Ну и последний штрих – объявить переменные и научить нашего бота некоторым манерам. Идея состоит в том, чтобы сделать Telegram бота, который будет приветствовать вас раз в день. В зависимости от времени суток сообщение должно быть разным. Если вы хотите попробовать этот скрипт, добавьте строку import datetime после import requests , а также дополните скрипт данным кодом:

greet_bot = BotHandler(token)    greetings = ('hello', 'hi', 'greetings', 'sup')    now = datetime.datetime.now()      def main():        new_offset = None      today = now.day      hour = now.hour        while True:          greet_bot.get_updates(new_offset)            last_update = greet_bot.get_last_update()            last_update_id = last_update['update_id']          last_chat_text = last_update['message']['text']          last_chat_id = last_update['message']['chat']['id']          last_chat_name = last_update['message']['chat']['first_name']            if last_chat_text.lower() in greetings and today == now.day and 6 <= hour < 12:              greet_bot.send_message(last_chat_id, 'Good Morning  {}'.format(last_chat_name))              today += 1            elif last_chat_text.lower() in greetings and today == now.day and 12 <= hour < 17:              greet_bot.send_message(last_chat_id, 'Good Afternoon {}'.format(last_chat_name))              today += 1            elif last_chat_text.lower() in greetings and today == now.day and 17 <= hour < 23:              greet_bot.send_message(last_chat_id, 'Good Evening  {}'.format(last_chat_name))              today += 1            new_offset = last_update_id + 1    if __name__ == '__main__':        try:          main()      except KeyboardInterrupt:          exit()</pre> Теперь у вас есть тысячи различных способов улучшать своего бота! Можно добавить дополнительные кнопки или даже настроить отправку медиафайлов. Последний шаг – это как вишенка на торте, которая позволит сделать из вашего Telegram бота настоящего помощника: его необходимо развернуть на сервере. Скорее всего, у вас нет собственного сервера, и уж вряд ли вы захотите покупать для этого дорогостоящую аппаратуру. К счастью, существует множество облачных сервисов, на которых можно бесплатно разместить приложение. Давайте развернем небольшой скрипт на Heroku. Прежде всего, вам нужна учетная запись на GitHub. Переходите на главную страницу и регистрируйтесь: это обязательный шаг для любого, кто действительно заинтересован в программировании. Помимо учетной записи GitHub, вам также необходимо установить Git. Если у вас Linux, выполните следующую команду: $ sudo apt-get install git-all

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

Устанавливаем virtualenv, используя команду:

$ pip install virtualenv

Теперь вам нужно немного упорядочить свои файлы. Создайте новую папку, откройте терминал/cmd и перейдите в нее. Для инициализации в созданной папке virtualenv введите:

$ virtualenv my_env

Название не имеет особого значения, однако лучше делать его максимально понятным. Перейдите в папку my_env. Следующий шаг – клонировать ваш репозиторий Git. Введите следующую команду:

$ git clone https://github.com/yourprofilename/yourreponame

Поместите свой скрипт в папку и вернитесь в my_env, чтобы запустить virtualenv.

Windows:

$ scriptsactivate.bat

Linux/macOS:

$ source bin/activate

При успешном запуске virtualenv командная строка должна начинаться с (my_env). Установите модуль requests, перейдя в папку репозитория:

$ pip install requests

Для создания зависимостей Heroku введите:

$ pip freeze > requirements.txt

Создайте файл Procfile. В нем вы найдете инструкции для работы со своим скриптом. Имя должно быть Procfile или Procfile.windows, если это Windows. Не стоит включать в название .txt, .py или любые другие расширения. Содержимое файла должно быть следующим (измените my_bot на название вашего скрипта):

web: python my_bot.py

Добавьте файл __init__.py в свою папку. Файл может быть пустым, но он должен находиться там. Введите такую команду:

$ git init  $ git add .  $ git commit -m ‘short message that describe changes to commit’  $ git push -u https://github.com/yourusername/nameofrepo

А теперь развернем нашего Telegram бота на Heroku. Потренируемся делать это через консоль. При возникновении проблем, обратитесь к руководству. Для Windows и macOS нужно установить интерфейс командной строки, используя этот гайд. Для Ubuntu используем команды:

$ sudo add-apt-repository "deb https://cliassets.heroku.com/branches/stable/apt ./"  $ curl -L https://cli-assets.heroku.com/apt/release.key |  $ sudo apt-key add -  $ sudo apt-get update  $ sudo apt-get install heroku

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

$ heroku login  $ heroku create  $ git push heroku master  $ heroku ps:scale web=1  $ heroku open

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

$ heroku logs --trail

Коды ошибок можно посмотреть здесь.

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

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

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

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

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

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

pip install pytelegrambotapi python3 

image

Скриншот из терминала с запущенным интерпретатором 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

image

Бот работает

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

Урок №2 →

Оцените статью
Рейтинг автора
4,8
Материал подготовил
Егор Новиков
Наш эксперт
Написано статей
127
А как считаете Вы?
Напишите в комментариях, что вы думаете – согласны
ли со статьей или есть что добавить?
Добавить комментарий