Создаем бота в Facebook на Python менее чем за 60 минут
В этой статье научим как создать бота в Facebook при помощи Python, Flask, библиотеки PyMessenger и локального хостинга через ngrok.
Когда мы пользуемся ботами в различных мессенджерах, многие из нас не представляют, насколько легко можно сделать собственного помощника. Например, немного порывшись в документации и зная основы Python, любой может создать своего бота в Facebook за предельно короткое время. В этой статье мы рассмотрим, как менее чем за один час создать простого бота в Facebook Messenger при помощи веб-фреймворка Flask и библиотеки PyMessenger.
Настройка среды разработки
Для создания этого бота убедитесь, что у вас установлены:
При помощи pip в командной строке установите библиотеки Flask и PyMessenger:
pip3 install Flask pip3 install pymessenger
Пишем простое приложение Flask
Используя Flask, мы можем создать терминал вызова — особый способ обращения к веб-ссылке. Например, в случае https://proglib.io/puzzles/ терминалом вызова будет “/puzzles”. Когда пользователь отправляет сообщение, Facebook пересылает данные в терминал вызова, откуда мы отправляем ответ Facebook , чтобы он показал его пользователю.
Для начала создадим простейшее приложение Flask app.py. Если вы ранее не использовали этот веб-фреймворк и хотите лучше понимать что происходит, посмотрите сжатое введение в документацию фреймворка.
from flask import Flask, request app = Flask(__name__) @app.route('/', methods=['GET', 'POST']) def receive_message(): return "Hello World!" if __name__ == '__main__': app.run()
При запуске приведенного кода из командной строки python app.py (или python3 app.py в случае нескольких версий Python) будет выведено сообщение, близкое к следующему:
* Running on http://127.0.0.1:5000/ (Press CTRL C to quit)
Если вы перейдете в браузере по ссылке, полученной от приложения (в приведенном примере http://127.0.0.1:5000/), вы увидите страницу со словами “Hello World!”. То есть с этим минимальным числом строк мы создали простейшее веб-приложение. Для создания бота в Facebook мы возьмем за основу эту простую конструкцию, чтобы получать запросы пользователя и выдавать на них соответствующие ответы.
От простого приложения Flask к созданию бота
В первую очередь необходимо обеспечить обработку двух типов запросов GET и POST, которые вы могли уже заметить в приведенном выше коде. В нашем примере мы будем использовать GET-запросы, когда проверяется маркер бота в Facebook (verify token). Расширяя написанное ранее приложении Flask, добавим в функцию receive_message обработку запроса GET:
if request.method == 'GET': # до того как позволить людям отправлять что-либо боту, Facebook проверяет маркер, # подтверждающий, что все запросы, получаемые ботом, приходят из Facebook token_sent = request.args["hub.verify_token"] return verify_fb_token(token_sent)
Строка “hub.verify_token” соответствует маркеру. Позднее в этой статье мы обсудим, как задать эту переменную.
Если бот не получил запрос GET, он, скорее всего, получит запрос POST, при котором боту в Facebook передается сообщение, отправленное пользователем. Для этого мы дополним условие if блоком else, который будет принимать данные, полученные Facebook от пользователя:
# если запрос не был GET, это был POST-запрос и мы обрабатываем запрос пользователя else: # получаем сообщение, отправленное пользователем боту output = request.get_json() for event in output['entry']: messaging = event['messaging'] for message in messaging: if message.get('message'): #определяем ID, чтобы знать куда отправлять ответ recipient_id = message['sender']['id'] if message['message'].get('text'): response_sent_text = get_message() send_message(recipient_id, response_sent_text) #если пользователь отправил GIF, фото, видео и любой не текстовый объект if message['message'].get('attachments'): response_sent_nontext = get_message() send_message(recipient_id, response_sent_nontext) return "Message Processed"
В начале блока if мы используем функцию проверки маркера (токена). Facebook требует, чтобы ваш бот имел поверочный токен:
def verify_fb_token(token_sent): '''Сверяет токен, отправленный фейсбуком, с имеющимся у вас. При соответствии позволяет осуществить запрос, в обратном случае выдает ошибку.''' if token_sent == VERIFY_TOKEN: return request.args.get("hub.challenge") return 'Invalid verification token'
Теперь, после этих первых шагов, рассмотрим процесс обработки полученного сообщения, генерации и отправки ответа. Как только будет сгенерирован ответ на запрос пользователя, его нужно будет как-то отправить. Для поддержки взаимодействий пользователя и бота в Facebook воспользуемся библиотекой PyMessenger, обеспечивающей простую поддержку POST-запросов с использованием Messenger API:
def send_message(recipient_id, response): '''Отправляет пользователю текстовое сообщение в соответствии с параметром response.''' bot.send_text_message(recipient_id, response) return "success"
В качестве ответов будем отправлять случайные сообщения, подбадривающие нашего собеседника:
import random def get_message(): '''Отправляет случайные сообщения пользователю.''' sample_responses = ["Потрясающе!", "Я вами горжусь!", "Продолжайте в том же духе!", "Лучшее, что я когда-либо видел!"] return random.choice(sample_responses)
Рассмотрев основные фрагменты кода нашего бота в Facebook, соберем их вместе:
import random from flask import Flask, request from pymessenger.bot import Bot app = Flask(__name__) ACCESS_TOKEN = 'YOUR_ACCESS_TOKEN' VERIFY_TOKEN = 'YOUR_VERIFY_TOKEN' bot = Bot(ACCESS_TOKEN) #Получать сообщения, посылаемые фейсбуком нашему боту мы будем в этом терминале вызова @app.route('/', methods=['GET', 'POST']) def receive_message(): if request.method == 'GET': # до того как позволить людям отправлять что-либо боту, Facebook проверяет токен, # подтверждающий, что все запросы, получаемые ботом, приходят из Facebook token_sent = request.args['hub.verify_token'] return verify_fb_token(token_sent) # если запрос не был GET, это был POST-запрос и мы обрабатываем запрос пользователя else: # получаем сообщение, отправленное пользователем для бота в Facebook output = request.get_json() for event in output['entry']: messaging = event['messaging'] for message in messaging: if message.get('message'): #определяем ID, чтобы знать куда отправлять ответ recipient_id = message['sender']['id'] if message['message'].get('text'): response_sent_text = get_message() send_message(recipient_id, response_sent_text) #если пользователь отправил GIF, фото, видео и любой не текстовый объект if message['message'].get('attachments'): response_sent_nontext = get_message() send_message(recipient_id, response_sent_nontext) return "Message Processed" def verify_fb_token(token_sent): '''Сверяет токен, отправленный фейсбуком, с имеющимся у вас. При соответствии позволяет осуществить запрос, в обратном случае выдает ошибку.''' if token_sent == VERIFY_TOKEN: return request.args['hub.challenge'] else: return 'Invalid verification token' def send_message(recipient_id, response): '''Отправляет пользователю текстовое сообщение в соответствии с параметром response.''' bot.send_text_message(recipient_id, response) return 'Success' def get_message(): '''Отправляет случайные сообщения пользователю.''' sample_responses = ["Потрясающе!", "Я вами горжусь!", "Продолжайте в том же духе!", "Лучшее, что я когда-либо видел!"] return random.choice(sample_responses) if __name__ == '__main__': app.run()
Регистрация бота в Facebook for Developers
Итак, мы написали основную часть кода для работы нашего бота. Теперь нам необходимо связать его с Facebook и сделать доступным для работы через интернет. Для этого вам необходимо создать Страницу на Facebook (и аккаунт, если у вас еще его нет). После того как вы создали Страницу, перейдите на Facebook for Developers и создайте аккаунт разработчика.
Следующий шаг после регистрации — назвать ваше приложение (например, MyFirstApp) и указать e-mail:
На следующей странице вы указываете тип вашего приложения (например, “Другое”). После этого вы окажетесь на странице приложения. В меню слева выберите основные настройки: загрузите иконку приложения, определите категорию и др.
Далее необходимо выбрать продукт, для которого мы разрабатываем приложения. Для этого внизу меню нажмите “+Добавить продукт”, выберите на открывшейся странице Messenger и настройте его.
На открывшейся странице перейдите к разделу “Генерирование маркера”. Из выпадающего списка выберите созданную вами страницу и подтвердите разрешение.
При этом в поле справа будет автоматически сгенерирован маркер доступа к приложению (Page Access Token).
Скопируйте сгенерированный маркер и в файле программы app.py присвойте его значение строке ACCESS_TOKEN.
Хостинг для бота в Facebook
Теперь, когда у нас есть и код, и заполнены основные поля, необходимо где-то разместить код. Для этого примера воспользуемся ngrok — простым кроссплатформенным инструментом командной строки, позволяющим создать туннель к localhost, то есть запускать код локально на нашем компьютере, но делать его доступным любому (скачать ngrok можно здесь, простейшие инструкции представлены здесь. Хостинг будет работать пока включен компьютер и на нем запущен ngrok, то есть ngrok предназначен в первую очередь для тестирования и не подразумевает серьезных нагрузок.
Заставим нашего бота работать — вначале в терминале, как делали это ранее, запустим программу app.py. Определите номер порта, идущий в конце ссылки после двоеточия. Открыв второе окно терминала в той же папке, наберите команду “ngrok http” + номер порта. Для приведенного примера “http://127.0.0.1:5000/“ соответствующая комманда будет “ngrok http 5000”. На экране в разделе “Forwarding” скопируйте ссылку, начинающуюся с “https.” Эта ссылка представляет адрес, по которому ваш локальный сервер стал доступен в интернете, то есть она будет служить ссылкой на сервер бота, куда Facebook отправляет сообщения от пользователей.
Если вы попытаетесь обратиться к программе по этой ссылке, в браузере отобразится ошибка, которую мы описали в программе: Invalid verification token. Это соответствует тому, что мы запрограммировали — нам не нужны обращения к программе не из Facebook Messenger. При этом в ngrok вы увидете, что произошло обращение, так как браузер попытался подключиться к программе и загрузить иконку страницы. Изменилось, соответственно, и число подключений.
Обратите внимание, что сервер изменит ссылку при новом запуске ngrok.
Настройка Webhooks
Скопированная ссылка необходима для того, чтобы связать сервер нашего бота с Facebook Messenger. Возвращаемся к Facebook for Developers и настраиваем Webhooks.
При этом вы увидите экран наподобие следующего.
В раздел URL обратного вызова (Callback URL) вставьте скопированную ссылку на наш сервер ngrock. Для того, чтобы защитить ваш бот, Facebook требуется маркер (verify token). Когда пользователь пишет сообщения вашему боту, Facebook посылает эти сообщения вместе с маркером на сервер бота, где созданное вами приложение Flask проверяет соответствие маркера и аутентифицирует присланное сообщение как сообщение из Facebook Messenger. В качестве этой строки может использоваться любая строка. Выберите строку и присвойте это значение в app.py переменной VERIFY_TOKEN (например “TESTINGTOKEN”, но лучше выбрать что-то посложнее). Скопируйте тот же самый маркер (без кавычек) в поле Verify Token окна Webhooks.
В полях подписки можно отметить все боксы. При желании создания ограничений для работы бота, можно подробнее ознакомиться с событиями Webhooks в документации. Наконец, нужно привязать Webhook к Странице бота.
Поздравляем — наш бот готов, осталось лишь его протестировать!
Тестирование бота в Facebook Messenger
Тестирование бота интуитивно понятно — зайдите на Страницу, для которой мы создали бота и напишите сообщение. Если все настроено правильно, бот реагирует на сообщение пользователя одним из заготовленных нами ответов.
Что дальше?
Поздравляем! Вы создали своего первого бота для Facebook Messenger. Теперь его можно сделать более функциональным и полезным: научить отвечать по-разному на сообщения, содержащие определенные слова или заданным образом реагировать на файлы разного формата. Вместо локального запуска бота при помощи ngrok распространенным решением является хостинг на облачной PaaS-платформе, например, Heroku. Знакомство с этими возможностями может пригодиться и в других проектах.