Чат-бот приложения через 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 зависимости:

sudo dpkg --add-architecture i386
sudo aptitude update


Прием сообщений на стороне сервера:

preg_match('#RECEIVED|SENT#Uis')

— работает не совсем правильно, так как реагирует на все сообщения
— да и вообще лучше не использовать такую конструкцию, так как часть сообщений исчезает в недрах dbus, а php до них не добирается, то есть скрипт за цикл работы while() очень часто не успевает получить все сообщения или не получает сообщения вообще. Методом проб и ошибок был найден способ 100% отлавливающий все сообщения и даже после простоя скрипта или его перезагрузки, вот он:

$oSkype->Invoke('SEARCH MISSEDMESSAGES')

Подробнее
class phpSkype {

    private static $iLastId;

    public static function notify($sNotify) {
        //....
        //....
        //....

        /* Message serving 4 */
        if (preg_match('/^CHATMESSAGES/', $sNotify)) {
            $sNotify = str_replace('CHATMESSAGES ', '', $sNotify);

            if ($sNotify != '') {
                $aMessages = explode(', ', $sNotify);
                if (sizeof($aMessages)) {
                    foreach ($aMessages as $iMessageId) {
                        $sAuthRaw = $oSkype->Invoke('GET CHATMESSAGE ' . $iMessageId . ' FROM_HANDLE');
                        $sMessageRaw = $oSkype->Invoke('GET CHATMESSAGE ' . $iMessageId . ' BODY');
                        $aMessage = explode('BODY ', $sMessageRaw);
                        $aUsernameSkype = explode('FROM_HANDLE ', $sAuthRaw);

                        $aChatHash = explode('CHATNAME ', $oSkype->Invoke('GET CHATMESSAGE ' . $iMessageId . ' CHATNAME'));
                        verifyUserSkypeChatId($aUsernameSkype[1], $aChatHash[1]);

                        if (self::$iLastId < $iMessageId) {
                            self::$iLastId = $iMessageId;
                            addLog($aUsernameSkype[1], $aMessage[1]);
                            self::received($aUsernameSkype[1], trim(strtolower($aMessage[1])), $iMessageId);
                        } else {
                            $oSkype->Invoke('SET CHATMESSAGE ' . $iMessageId . ' SEEN');
                        }
                    }
                }
            }
        }

        //....
        //....
        //....
    }

    public static function received($sUid, $sMessage, $iLastMsgId) {
        $oSkype = Zend_Registry::get('$oSkype');

        // Mark received message as read
        $oSkype->Invoke('SET CHATMESSAGE ' . $iLastMsgId . ' SEEN');

        /* Prepare */
        $sChatIdRaw = $oSkype->Invoke('GET CHATMESSAGE ' . $iLastMsgId . ' CHATNAME');
        $aChatId = explode('CHATNAME ', $sChatIdRaw); 

        $sMembers = $oSkype->Invoke("GET CHAT " . $aChatId[1] . " ACTIVEMEMBERS");
        $sMembers = str_replace('CHAT ' . $aChatId[1] . ' ACTIVEMEMBERS ', '', $sMembers);
        $aMembers = explode(' ', $sMembers);
        if (sizeof($aMembers) > 2) {
            $oSkype->Invoke("ALTER CHAT " . $aChatId[1] . " CLEARRECENTMESSAGES");
            $oSkype->Invoke("ALTER CHAT " . $aChatId[1] . " DISBAND");
            $oSkype->Invoke("ALTER CHAT " . $aChatId[1] . " LEAVE");
            return false;
        }

        //....
        //....
        //....
    }

}

$oDbus->registerObject('/com/Skype/Client', 'com.Skype.API.Client', 'phpSkype');

$bSMLastUpdate = 0;
while (true) {
    $s = $oDbus->waitLoop(1);

    /* Get new skype messages */
    global $bSMLastUpdate;
    if (time() - $bSMLastUpdate >= $aConfig['skype_get_new_message']) {
        $bSMLastUpdate = time();

        $oSkype->Invoke('SET USERSTATUS ONLINE');
        $oSkype->Invoke('SEARCH MISSEDMESSAGES');
    }
}


Который в dbus шлет все не обработанные сообщения (на которых не стоит флаг SEEN):
$oSkype->Invoke('SET CHATMESSAGE ' . $iMessageId . ' SEEN');

и в основном цикле их отлавливаем с помощью:
preg_match('/^CHATMESSAGES/', $sNotify)

То же самое сделано и для авторизаций от пользователей боту (будущий пользователь может зарегистрироваться просто послав авторизацию в skype), а именно:
$oSkype->Invoke("SEARCH USERSWAITINGMYAUTHORIZATION")

а не ждать:
preg_match('/^USER ([a-zA-Z0-9_\.]+) RECEIVEDAUTHREQUEST (.)+/', $sNotify, $aMatches)

которое тоже иногда давало осечку. С этим связан еще один нюанс, если нам надо знать, что пользователь удалил бота из листа контактов, то инициируется:
/* Client unlink */
if (preg_match('/BUDDYSTATUS 2/', $sNotify)) {
   //...
}

Но надо быть внимательным и отслеживать ситуацию, когда аналогичная проблема возникает при отправке пользователю авторизации от бота:
$oSkype->Invoke("SET USER [USER_NAME] BUDDYSTATUS 2 [AUTH_MESSAGE]");

Но я так и не смог решить проблему того что боты skype уходят в away после того как пользователи ОС лочаться после бездействия. Хотя в настройках skype стоит away_mode=off и эта строка не помогает:
$oSkype->Invoke('SET USERSTATUS ONLINE');

Только после этого, skype стал работать стабильно.

И вот приступил я к настройке на … freebsd тогда еще 9.х, как и все мои разработки, ох и нравилась мне эта система, боролся я с ней долго, но так и не завел skype через dbus, уперся я тогда в сессии х-менеджера и dbus и их несоответствие и:
найти в /root/.dbus/session-bus/
id сессии dbus и добавить в окружение 
например export DBUS_SESSION_BUS_ADDRESS=8c9916eb531f5f9a0458961c000033bc-1

не всегда помогало, пришлось все ставить на linux, как было указано в статье на Хабре, я выбрал debian. Хотя backend web и остался на freebsd и общались они между собой через memcache. Да, да, знатный «велосипед», но об этом ниже.
Код чат ботов был связан с кодом веба, хотелось его сделать поскорее и поэтому вместо того чтобы взять хорошие решения по «Очередям Сообщений», которые я ранее не использовал, и не особо разбирался, я начал лепить свою очередь из php+memcache со своей логикой lock'ов для того чтобы сделать регистрацию, и рассылку авторизаций и сообщений в im клиенты операторов асинхронными. Это была ужасная «машина» в которой можно было сломать глаза – но она работала и работает до сих пор, насколько я знаю. Представьте себе: 6 ботов/ОС пользователей, 6 поднятых виртуальных рабочих столов отдельно на каждого пользователя debian, 6 vnc окон, в каждом из них по 4 скрипта (skype и jabber бот, воркеры мною написанной очереди). Каждая перезагрузка сервера превращалась в кропотливую работу, зайти в систему шестью юзерами, открыть для каждого vnc, открыть терминал и там запустить 4 php скрипта. Боты то и дело вылетали с какими-то странными ошибками, в частности JAXL, при использовании VNC падал с:
Interrupted system call в jaxl_loop.php

лечилось это изменением/удалением полей в месте инициализации «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», и отправить сообщение).

Пока я пилил и тестировал, коллега с работы, который посмотрел мои наработки, предложил:
А давай еще и viber!

И я снова обратился к своему незаменимому помощнику – google. Там не оказалось ничего об открытых api, но я нашел варианты использования whatsapp и прикрутил его к сервису (взял на github код библиотеки «WhatsProt»). Но стоп, ведь whatsapp в основном для не русскоговорящих, надо делать переводы и для ботов, и на сайте. Почитал «На какие языки переводить проект в первую очередь?» и выбрал английский, русский, китайский упрощенный, немецкий и испанский, от китайского потом отказался, из моих знакомых никто в нем не понимал, чтобы внести изменения художественного характера.
Взял ZF 2.x за основу для веб. Планировал реализовать все приложения как единый бот, а потом каждое приложение — как отдельный бот. Первая схема была очень нестабильной (так как я все еще опирался на memcache в качестве никак недокументированного кеша и в качестве «очереди сообщений»), и я от нее отказался, но потом вернулся частично. А вторая уже после 8 ботов начала захламлять мой контакт лист в skype и jabber, а также отъедала ресурсы на моей локальной виртуальной машине с невероятной скоростью, особенно сам skype, так как для каждого бота приходилось запускать отдельного пользователя со своим рабочим столом и своим skype (хотя и есть возможность запускать несколько разных skype в одном окружении, и привязываться к api каждого по id dbus сессий — но я пока не пробовал), и я отказался от этой схемы, позже я объединил их, теперь каждый бот реализует несколько приложений, сгруппированных по смыслу. Начинал я с такого набора приложений:
  • Базовый (различные операции и статистика по юзеру)
  • Калькулятор
  • Погода
  • Игра с механикой «Башня Ханоя» (я ее пока не выпустил в prod, так как пока не придумал как обрисовывать пирамидки ASCII art'ом без расползания, в skype шрифт играет со мной в игры)
  • Волшебный шар 8
  • Возможность послать сообщение (даже не зарегистрированному) пользователю из любого клиента в любой из трех доступных (из самих ботов и с web сайта без авторизации)
  • Курсы валют
    1. Курс конверсии
    2. Мировой источник
    3. Европейский Центробанк
    4. OCBC Банк (Сингапур)
    5. Центробанк России
    6. Национальный Банк Украины
    7. Национальный Банк Беларуси
    8. Банк Китая
    9. Банк Канады
    10. Курсы Bitcoin

За ноябрь и декабрь и январь я написал почти стабильную версию и, что самое главное, годную для теста на моих знакомых.
Но тут на глаза мне попалась статья «Google отказывается от поддержки XMPP», и я немного расстроился. Но через некоторое время, после статьи «Без паники! Про то, что сделал Google с XMPP», я понял, что все просто хорошо и сам постоянно использую google xmpp. Пришло время выливать все на хостинг. Моя тестовая ВМ на 7 ботов (по три скрипта на каждого бота/приложение (skype-jabber-whatsapp) и 3 воркера для каждого приложения: user worker, api worker (я написал все взаимодействие с бд через api – только зачем, до сих пор не понимаю, зато модульно и с одной точкой входа для web и ботов вышло, проще стало тестировать), и spam worker, все воркеры работали через зайцаMQ) потребляла 3,5ГБ RAM, а у всех хостеров были тарифы 2 и 4 ГБ со стоимостью в 2 раза больше за 4Гб, что мне не подходило, так все это из своего кармана и сервис бесплатен, написал в «цифровой океан» (о котором тоже прочитал на Хабре) о просьбе под нужды такого то сервиса дать ВМ с другим количеством оперативной памяти, но с более слабым процессором, он был не критичен. Мне отказали. Ожидаемо. Нашел сравнение хостеров на «comparevps» и за деньги те же что и для 2Гб, взял систему с 4Гб, хотя опыт реальный работы с этим хостером оказался чуть хуже ожидаемого, все стоит своих денег (в этом случае к сожалению). И написал две пошаговые инструкции по установке freebsd и debian сервера до этапа полностью работающего сервиса, чтобы быстро завести купленные VPS.

Но брать два сервера (freebsd для web + debian для чат ботов) было не с руки, я начал ставить все на один. И это был debian, я неприятно удивился что не могу поставить из пакетов последние версии того что мне надо как я мог сделать это на freebsd сборкой и портов. Потом я разобрался, как и что и престал быть хейтером linux и debian в частности, а стал фанатиком в хорошем смысле (теперь у меня в «must have» еще и Red Hat).

Я добавил по «наводке» друзей новые приложения:
  • Мировые часы (смещения, время, закат, восход и часовой пояс)
  • Hash генератор
  • Хабра парсер (бот мне скидывает все ссылки на лучшие за сутки статьи с кратким описанием)
  • Гороскоп (сложность была в том для всех поддерживаемых языков надо было искать оригинальные гороскопы, так как переводить их на лету плохо)

Ботов стало 11, на каждого 6 скриптов (1й –skype, 2й –jabber, 3й – whatsapp и три воркера), системе не хватало и 4Гб. Пришло время для понимания того что надо объединять приложения в тематические боты, как я говорил ранее, сказано – сделано. Появились Base, Office (калькулятор, курсы валют, мировые часы), Lifestyle (погода, гороскоп, 8ка), Developer (habra, hash). Теперь 2.5Гб и все хорошо. Тут я немного устал, читал неспешно «Джаббер переходит на полное шифрование» и решил протестировать свой сервер на xmpp.net и получил оценку A-, что могло не радовать. Кстати я долго не мог заставить свой ejabbered сервер стать публичным (а равно и добавить межсерверное взаимодействие) пока не сделал в DNS это
image

Но у меня все еще не было ssl сертификатов ни для jabber ни для сайта. Два по 60$ мне не улыбалось, и тут я нашел статью «Получаем бесплатный SSL сертификат» и понеслась. Все просто и понятно.

Была постоянно одна проблема, которая меня вконец допекла: я очень устал восстанавливать все сервисы руками, когда сервер по причине хостера падал или после перезагрузки просто стоял болванкой, надо было решить как-то проблему того, что я об этом узнавал только в понедельник, если это происходило в субботу. Я пробовал много разного, в конечном итоге, система после перезагрузки, полностью автоматом логинит всех *nix пользователей (для skype), под ними стартует terminal в графической оболочке, открывает шесть вкладок и в каждом запускает нужный php скрипт чтобы я мог зайти и посмотреть его вывод в любое время (для debug возникающих иногда мелких проблем):
Debian автологин всех юзеров и запуск скриптов в terminal в графическом режиме
>>nano /etc/inittab
8:2345:respawn:/bin/login -f ИМЯ_СЕРВИСА tty8 </dev/tty8 >/dev/tty8 2>&1
9:2345:respawn:/bin/login -f lifestyle tty9 </dev/tty9 >/dev/tty9 2>&1
10:2345:respawn:/bin/login -f developer tty10 </dev/tty10 >/dev/tty10 2>&1
11:2345:respawn:/bin/login -f xmess tty11 </dev/tty11 >/dev/tty11 2>&1
12:2345:respawn:/bin/login -f office tty12 </dev/tty12 >/dev/tty12 2>&1

>>nano /etc/profile
sleep 8
[ `tty` == '/dev/tty8' ] && startx -- :1
sleep 8
[ `tty` == '/dev/tty9' ] && startx -- :2
sleep 8
[ `tty` == '/dev/tty10' ] && startx -- :3
sleep 8
[ `tty` == '/dev/tty11' ] && startx -- :4
sleep 8
[ `tty` == '/dev/tty12' ] && startx -- :5

«sleep» нужен для того чтобы все успело стартовать, включая skype.
А в автозагрузку gnome каждого пользователя ОС (который предназначен для выполнения скриптов бота) добавить skype и скрипты по обслуживанию бота в:
/home/USERNAME/.config/autostart/

[Desktop Entry]
Type=Application
Exec=skype
Hidden=false
X-GNOME-Autostart-enabled=true
Name[en_US]=skype
Name=skype
Comment[en_US]=
Comment=

[Desktop Entry]
Type=Application
Exec=gnome-terminal --tab --title="skype" -e "/usr/local/bin/php /home/ИМЯ_СЕРВИСА/utils/assistant/_skype_assistant/base_assistant.php" --tab --title="jabber" -e "/usr/local/bin/php /home/ИМЯ_СЕРВИСА/utils/assistant/_jabber_assistant/base_assistant.php" --tab --title="whatsapp" -e "/usr/local/bin/php /home/ИМЯ_СЕРВИСА/utils/assistant/_whatsapp_assistant/base_assistant.php" --tab --title="user_op" -e "/usr/local/bin/php /home/ИМЯ_СЕРВИСА/utils/assistant/lib/worker/user_operations_worker.php base_assistant" --tab --title="api" -e "/usr/local/bin/php /home/ИМЯ_СЕРВИСА/utils/assistant/lib/worker/api_worker.php base_assistant" --tab --title="spamer" -e "/usr/local/bin/php /home/ИМЯ_СЕРВИСА/utils/assistant/lib/worker/spamer_worker.php base_assistant"
Hidden=false
X-GNOME-Autostart-enabled=true
Name[en_US]=all_tabs
Name=all_tabs
Comment[en_US]=
Comment=


Для перезагрузки всего бота я использую:
killall -u lifestyle
и в background запускаю
/bin/login -f lifestyle tty9 </dev/tty9 >/dev/tty9 2>&1 &


А чтобы получать 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 аккаунта
/* Request sms code */
$username = "ТЕЛЕФОН";
$token = md5($username);
$nickname = "ИМЯ_СОСБТВЕННОЕ_ЛЮБОЕ";
$w = new WhatsProt($username, $token, $nickname, true);
$w->codeRequest();

Потом
/* Get password */
$username = "ТЕЛЕФОН";
$token = md5($username);
echo $token;
$nickname = "ИМЯ_СОСБТВЕННОЕ_ЛЮБОЕ";
$w = new WhatsProt($username, $token, $nickname, true);
$result = $w->codeRegister("SMS_КОД_ПОЛУЧЕННЫЙ_РАНЕЕ");
$password = $result->pw;
echo "Password is $password";


Но есть проблема, что каждое новое соединение (в моей схеме, один скрипт слушает команды, а другой отправляет ответы, полученные через очередь) обрывает текущее. Пришлось для whatsapp отказаться частично от очередей и сделать автоматический рестарт самого php скрипта.
Вот интересный хинт для jabber бота, чтобы он показывал статус «typing», когда пользователь ему что-нибудь пишет:
JAXL bot typing status
$oJabber->add_cb('on_chat_message', function($oStanza) {
sMessage = trim(strtolower($oStanza->body));
    if (!$sMessage) {
        $oStanza->to = $oStanza->from;
        $oStanza->from = $oJabber->full_jid->to_string();
        $oJabber->send($oStanza);
    }
//….
}


Кстати, для whatsapp и skype ботов, выйти из spamer воркера, когда тот отработает сообщение из очереди в фоне и совершт действие с пользователем, позволила только строка
posix_kill(getmypid(), 9);

а для jabber просто
$oJabber->send_end_stream();

В планах следующие приложения:
  • чат рулетка
  • email на 10 минут
  • мониторинг сервера через im
  • приложение для интернет магазинов чтобы со стороны продавца все skype и/или jabber были одним для клиента и наоборот

Да и много других приложений вертится в голове, только не хватает теперь на все сразу времени. Даже не столько времени, сколько понимания того, какая ЦА (целевая аудитория) у этого сервиса.

Для того, кто задумает написать что-то похожее и не знает с чего начать, весь код был взят по приведенным выше ссылкам и из примеров использования к проектам на github. Единственное что я там не нашел это то, что я упомянул выше и то, как получать сообщения пользователя из xml для whatsapp бота и не реагировать на «typing» статус, когда юзер набирает сообщение:
whatsapp get user message
$oWa->pollMessages();
    $mData = $oWa->getMessages();
    if (!empty($mData)) {
        if ('message' === $mData[count($mData) - 1]->getTag()) {
            if ('notify' === $mData[count($mData) - 1]->getChildren()[0]->getTag()) {
                $oDbAdapter->getConnection();
                received($oWa->parseJID($mData[count($mData) - 1]->getAttributes()['from']), $mData[count($mData) - 1]->getChildren()[2]->getData());//$sUid, $sMessage
                $oDbAdapter->closeConnection();
            }
        }
    }


Вывод: при помощи в основном только Хабрахабра простой «тестировщик» сделал то, что ему нравилось, спасибо! И стал чуточку счастливее.

PS 1: Когда я заканчивал описывать процесс кропотливой работы над своим сервисом, я увидел на Хабре и не мог не прочитать вот эту статью «Джон Резиг: Пишите код каждый день». В ней четко и просто сформулировано все то, что я никак не мог оформить в своей голове. Я действовал точно также при написании своего сервиса, стал писать код каждый день. И это очень оправдало себя, так как ушла ненужная тревога о том, что я не успеваю сделать достаточно.

Бонус: Free Object Motion Tracking Plugin at Final Cut Pro X, Adobe Premier and DaVinci Resolve.
AdBlock has stolen the banner, but banners are not teeth — they will be back

More
Ads

Comments 8

    0
    >> в skype шрифт играет со мной в игры
    Попробуйте «рисовать» смайлами — у них фиксированная ширина.
      0
      Действительно, о них я что-то не подумал.
      +4
      Наверное, статья могла бы быть очень интересной и полезной. Но читать ее практически невозможно — все в кучу, никакой структуры. Жаль.
        +1
        Увы так и есть, уже после публикации дал почитать статью бывшей журналистке, она сказала, что «как у Достоевского». Трудно читаемо, вообщем. Но теперь я знаю над чем еще поработать.
        0
        А ссылку на сервис так и не приведёте?
          +1
          Я не могу привести ссылку, но скажу, что в google по названию топика можно добраться до него в 1-2 клика.
            0
            Спасибо, нашёл:)
          0
          >$mData[count($mData) — 1]

          На мой взгляд читабельнее и удобнее

          >$last = array_pop($mData);

          И дальше работать с $last.

          Only users with full accounts can post comments. Log in, please.