Чат-бот приложения через skype, jabber и whatsapp
Привет! Хотелось бы рассказать вам историю создания одного незамысловатого развлекательного сервиса чат ботов.
ВступлениеО себе: Хабр читаю давно (лет этак 5), а вот зарегистрировался месяц назад, так как очень хотелось поделиться. Работаю в IT компании инженером по тестированию. Но меня всегда тянуло к разработке. И лет 7 назад занялся freelance параллельно основной работе. Начинал, как и все с малого, разбирался при помощи google. Писал всякие web непотребства. Все это ради достижения неких финансовых целей. Да и вообще вся жизнь состояла из цикла: поиск цели – достижение любыми средствами – удовлетворение – поиск новой цели. Так было и с freelance.
Переломный моментШла зима 2012/2013 года. Работал я на freelance над проектом онлайн-консультанта, и мне надо было сделать интеграцию с jabber и skype, то есть чтобы операторы могли работать с клиентом печатая в свой im клиент, а пользователь сайта получал это все на web. После поиска в google, оказалось, что с jabber все просто, любой xmpp сервер на выбор (я выбрал ejabbered) и библиотечка для работы с ним JAXL (взял на github), тогда еще версии 2.х. А вот со Skype были проблемы: на сайте в разделе Developers предлагался какой-то kit за деньги (и лицензия, запрещающая серверное использование), с ненужными мне активациями и с упоминанием про какой-то api. А хотелось чего-то более простого. И тут я наткнулся на этот api в «Доступ к Skype API используя PHP на *nix системах», сейчас на сайте skype упоминания о работе с api отсутствуют уже, хотя тогда было, и скачал pdf по работе с ним через dbus. Там было все то, что я искал. Возникло сразу несколько проблем, не описанных в прочитанной мною статье, если система x64, то skype требовал некоторые x86 зависимости:
Прием сообщений на стороне сервера:
— работает не совсем правильно, так как реагирует на все сообщения — да и вообще лучше не использовать такую конструкцию, так как часть сообщений исчезает в недрах dbus, а php до них не добирается, то есть скрипт за цикл работы while() очень часто не успевает получить все сообщения или не получает сообщения вообще. Методом проб и ошибок был найден способ 100% отлавливающий все сообщения и даже после простоя скрипта или его перезагрузки, вот он:
Который в dbus шлет все не обработанные сообщения (на которых не стоит флаг SEEN):
и в основном цикле их отлавливаем с помощью:
То же самое сделано и для авторизаций от пользователей боту (будущий пользователь может зарегистрироваться просто послав авторизацию в skype), а именно:
которое тоже иногда давало осечку. С этим связан еще один нюанс, если нам надо знать, что пользователь удалил бота из листа контактов, то инициируется:
Но надо быть внимательным и отслеживать ситуацию, когда аналогичная проблема возникает при отправке пользователю авторизации от бота:
Но я так и не смог решить проблему того что боты skype уходят в away после того как пользователи ОС лочаться после бездействия. Хотя в настройках skype стоит away_mode=off и эта строка не помогает:
Только после этого, skype стал работать стабильно.
И вот приступил я к настройке на … freebsd тогда еще 9.х, как и все мои разработки, ох и нравилась мне эта система, боролся я с ней долго, но так и не завел skype через dbus, уперся я тогда в сессии х-менеджера и dbus и их несоответствие и:
не всегда помогало, пришлось все ставить на linux, как было указано в статье на Хабре, я выбрал debian. Хотя backend web и остался на freebsd и общались они между собой через memcache. Да, да, знатный «велосипед», но об этом ниже. Код чат ботов был связан с кодом веба, хотелось его сделать поскорее и поэтому вместо того чтобы взять хорошие решения по «Очередям Сообщений», которые я ранее не использовал, и не особо разбирался, я начал лепить свою очередь из php+memcache со своей логикой lock'ов для того чтобы сделать регистрацию, и рассылку авторизаций и сообщений в im клиенты операторов асинхронными. Это была ужасная «машина» в которой можно было сломать глаза – но она работала и работает до сих пор, насколько я знаю. Представьте себе: 6 ботов/ОС пользователей, 6 поднятых виртуальных рабочих столов отдельно на каждого пользователя debian, 6 vnc окон, в каждом из них по 4 скрипта (skype и jabber бот, воркеры мною написанной очереди). Каждая перезагрузка сервера превращалась в кропотливую работу, зайти в систему шестью юзерами, открыть для каждого vnc, открыть терминал и там запустить 4 php скрипта. Боты то и дело вылетали с какими-то странными ошибками, в частности JAXL, при использовании VNC падал с:
лечилось это изменением/удалением полей в месте инициализации «new JAXL()», поиск которых в google в рамках очень сжатых сроков, не позволял тщательно решить их.
Ready, steady, goВесной 2013 я решил потешить свой перфекционизм и подумал, что надо бы написать интересное и нужное в плане идеи, да и красивое в плане кода, а не как обычно. И занялся поиском идеи. А она, как оказалась, была у меня под самым носом. Я, например, часто вызываю калькулятор в windows7 или в macos или смотрю погоду в своем телефоне. И почти весь день, пока бодрствую, я провожу за компьютером. Вывод просился сам собой, надо часто используемые операции перенести в постоянно открытые приложения и сократить количество выполняемых операций для существующих задач на компьютере. Бинго. Я судорожно полез в google искать готовые решения, а именно всевозможные приложения, реализованные как чат боты через популярные im протоколы. И на тот момент я ни одного не нашел (плохо искал?). Надо писать свой, он будет бесплатным и самое главное я им сам буду пользоваться. Мне предстояло написать чат ботов, которые по USSD командам могли бы взаимодействовать с юзерами через skype и jabber (позже и whatsapp), только написать получше чем до этого и сделать полностью готовое решение, выбрать доменное имя, логотип, дизайн сайта, сам сайт и все остальное что для этого надо, то есть полный цикл разработки и деплоя в prod.
Задача непростая, да и раньше я никогда так не делал. Но стоит только сделать 1й шаг…. А он уже был сделан. Если честно я сразу подумал, как было бы круто мониторить сервер и иметь эмуляцию ssh консоли в своем skype/jabber/whatsapp для мониторинга сервера (пока эта задача отложена на реализацию, хотя частичные наработки уже есть). И очень хотелось иметь аналог сервиса «email на 10 минут», написав владельцу популярного сервиса об интеграции в мой, я не ждал ничего хорошего, интуиция не подвела, разработчик этой системы вежливо отказался, сказав, что сервис бесплатный, а сам разработчик едва покрывает свое затраченное время рекламой на этом сервисе. А я им так часто пользуюсь. Ну да ладно, я начал мастерить свой велосипед на эту тему, но пока не дописал, так все опробованные идеи сделать быстро – были не очень годными. Не заладилось с freelance (но я не сильно расстроился, цель его и была финансовая, freelance помог ее решить, других целей не было, ах да, я взял себе спорт-байк и вот теперь точно, целей больше не было) и появилось свободное время (хотя я и продолжал постоянно работать в прежней IT компании, но уже на более интересных проектах, но все еще таких далеких от того, что мне нравилось). Два месяца я пилил код, все равно это был какой-то монстр в плане php кода в разрезе чат бота. А вот дизайн сайта до сих пор остался почти не тронутым, я сразу начал делать flat ui – мне казалось за ним успех в ближайшее время. Конец весны я переживаю личные проблемы различного характера, и забываю про этот сервис и к его разработке я возвращаюсь в ноябре 2013 и первое, что я делаю удаляю весь код чат ботов. И начинаю писать его снова и без очереди на memcache.
From the scratchНаписал текстом будущую архитектуру, структуры модулей (web, api, bot). Составил документацию по структуре хранения в memcache — в дальнейшем все это сильно выручало, дабы не держать большие объемы логики в своем «дворце памяти». Начало было в голове такое: Web: freebsd 10 + php 5.x + apache + mysql 5.x + apc , во втором чтении php 5.x стало nginx + php-fpm, и без apc, а с нативным opcache. Chatbot: debian wheezy с gnome + php 5.x + skype + memcache (для кэширования всех результатов ботов, их меню и всевозможных данных приложений) + ejabbered с JAXL 2.x (теперь и 3.x)+ rabbitMQ (о котором тоже прочитал на Хабре) с PhpAmqpLib (замена моему велосипеду с реализацией очереди в memcache взята с github).
Архитектура для каждого приложения: бот-listner для skype, бот-listner для jabber, бот-listner для whatsapp, user worker (rabbitMQ) для обработки add/delete user и add/delete service, api worker (rabbitMQ) для вызова api метдов, spamer worker (rabbitMQ) для рассылки сообщений и трех хелперов (для всех протоколов) — простейшие боты-sender'ы, которые получают команды от user worker и spamer worker, а также вызываются в фоне и после работы закрываются и непосредственно реализуют все активности ботов (отозвать авторизацию, выслать авторизацию с сообщением «X», и отправить сообщение).
Пока я пилил и тестировал, коллега с работы, который посмотрел мои наработки, предложил:
- Базовый (различные операции и статистика по юзеру)
- Калькулятор
- Погода
- Игра с механикой «Башня Ханоя» (я ее пока не выпустил в prod, так как пока не придумал как обрисовывать пирамидки ASCII art'ом без расползания, в skype шрифт играет со мной в игры)
- Возможность послать сообщение (даже не зарегистрированному) пользователю из любого клиента в любой из трех доступных (из самих ботов и с web сайта без авторизации)
- Курсы валют
- Курс конверсии
- Европейский Центробанк
- OCBC Банк (Сингапур)
- Центробанк России
- Национальный Банк Украины
- Национальный Банк Беларуси
- Банк Китая
- Банк Канады
- Курсы Bitcoin
Но брать два сервера (freebsd для web + debian для чат ботов) было не с руки, я начал ставить все на один. И это был debian, я неприятно удивился что не могу поставить из пакетов последние версии того что мне надо как я мог сделать это на freebsd сборкой и портов. Потом я разобрался, как и что и престал быть хейтером linux и debian в частности, а стал фанатиком в хорошем смысле (теперь у меня в «must have» еще и Red Hat).
- Мировые часы (смещения, время, закат, восход и часовой пояс)
- Hash генератор
- Хабра парсер (бот мне скидывает все ссылки на лучшие за сутки статьи с кратким описанием)
- Гороскоп (сложность была в том для всех поддерживаемых языков надо было искать оригинальные гороскопы, так как переводить их на лету плохо)
Но у меня все еще не было ssl сертификатов ни для jabber ни для сайта. Два по 60$ мне не улыбалось, и тут я нашел статью «Получаем бесплатный SSL сертификат» и понеслась. Все просто и понятно.
Была постоянно одна проблема, которая меня вконец допекла: я очень устал восстанавливать все сервисы руками, когда сервер по причине хостера падал или после перезагрузки просто стоял болванкой, надо было решить как-то проблему того, что я об этом узнавал только в понедельник, если это происходило в субботу. Я пробовал много разного, в конечном итоге, система после перезагрузки, полностью автоматом логинит всех *nix пользователей (для skype), под ними стартует terminal в графической оболочке, открывает шесть вкладок и в каждом запускает нужный php скрипт чтобы я мог зайти и посмотреть его вывод в любое время (для debug возникающих иногда мелких проблем):
«sleep» нужен для того чтобы все успело стартовать, включая skype. А в автозагрузку gnome каждого пользователя ОС (который предназначен для выполнения скриптов бота) добавить skype и скрипты по обслуживанию бота в:
Для перезагрузки всего бота я использую:
А чтобы получать email при shutdown и/или startup использовал этот скрипт. Теперь я всегда знал, что происходит с сервером и знал, что он поднимется полностью сам и все боты будут работать, даже после неожиданностей. Плюс к этому настроил бекап бд с ротацией и складированием на почту дампов (они пока небольшие).
Начитался на Хабре про heartbleed, и как, наверное, все, проверил свой сервер – все было ОК, но никак не мог включить TLS 1.2 и все время получал F, заодно и exploit нашел для heartbleed, чтобы протестировать различные сервисы, так как никогда таким не занимался, было занимательно попробовать себя в качестве иженера по безопасности, заодно попробовал «nikto.pl» и вдохновился «nessus» сканерами. Но вернусь к чат ботам, я и libssl переставил и openssl который «g» и проверяя зависимости nginx, постоянно видел, что он склинкован со старой lib, оказалось я просто поставил nginx для squeeze вместо wheezy. Хотя это и было причиной старой libssl слинкованной с nginx из-за которой у меня и не было уязвимости. «Случайность», — скажете вы. «Случайности не случайны», – отвечу я.
Кстати для whatsapp, как я понял свободное получение пароля от аккаунта, прикроют через какое-то время, сейчас его получить очень просто:
Кстати, для whatsapp и skype ботов, выйти из spamer воркера, когда тот отработает сообщение из очереди в фоне и совершт действие с пользователем, позволила только строка
а для jabber просто
- чат рулетка
- email на 10 минут
- мониторинг сервера через im
- приложение для интернет магазинов чтобы со стороны продавца все skype и/или jabber были одним для клиента и наоборот
Для того, кто задумает написать что-то похожее и не знает с чего начать, весь код был взят по приведенным выше ссылкам и из примеров использования к проектам на github. Единственное что я там не нашел это то, что я упомянул выше и то, как получать сообщения пользователя из xml для whatsapp бота и не реагировать на «typing» статус, когда юзер набирает сообщение:
Вывод: при помощи в основном только Хабрахабра простой «тестировщик» сделал то, что ему нравилось, спасибо! И стал чуточку счастливее.
PS 1: Когда я заканчивал описывать процесс кропотливой работы над своим сервисом, я увидел на Хабре и не мог не прочитать вот эту статью «Джон Резиг: Пишите код каждый день». В ней четко и просто сформулировано все то, что я никак не мог оформить в своей голове. Я действовал точно также при написании своего сервиса, стал писать код каждый день. И это очень оправдало себя, так как ушла ненужная тревога о том, что я не успеваю сделать достаточно.