Advertisement
shakawkaw

xmpp

Mar 28th, 2017
127
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 11.05 KB | None | 0 0
  1. <?
  2. error_reporting(E_ALL & ~E_NOTICE);
  3. set_time_limit(0); // убираем ограничения на время исполнения, чтобы крутилось вечно
  4. $fullPath='/var/www/html/xmpp/'; // полный путь в файловой системе к папке с прогой
  5. require_once($fullPath.'include/ipworks_xmpp.php'); // подключаем файл с классом от производителя модуля
  6. $sleepTime=1; // время остановки в секундах после прохода вечного цикла
  7. $msg_file_name=$fullPath.'messages.txt'; // задаём путь к файлу-буферу, т.к. обрабатываем вывод раз в
  8.  
  9.  
  10.  
  11. class MyXMPP extends IPWorks_XMPP { // создаём новый класс с наследованием методов и свойств класса IPWorks_XMPP от производителя модуля
  12. /*  
  13.     функции обработки событий
  14.     для ActiveX, из которого сделан модуль для 1С, описаны тут http://cdn.nsoftware.com/help/IP9/acx/XMPP.htm#Events
  15.     я же пользуюсь отсюда, но там всё одинаково http://cdn.nsoftware.com/help/IP9/php/XMPP.htm#Events
  16. */
  17.     function fireConnectionStatus($param) {
  18.     // событие состояния соединения, тут оно не обрабатывается, но в случае использования в продакшене в этом месте надо вызывать пересоздание соединения, если оно разорвалось
  19.         print_r($param); // печать параметров события в стандартный вывод
  20.         return $param; // возврат функции
  21.     }
  22.     function fireIQ($param) {
  23.     /*
  24.         событие IQ сообщений (системных), например, чтобы серверу узнать что клиент всё ещё на связи, он его периодически пингует, если клиент отвечает в пределах таймаута (в нашем случае 360 сек), то поддерживается он-лайн статус соединения, выглядит это примерно так:
  25.            
  26.             -------------------- fireIQ ---------------------------
  27.             Array
  28.             (
  29.                 [iq] => <iq type="get" id="362-24749" from="qip.cons23.ru" to="ipworksphp1@qip.cons23.ru/IP*Works! XMPP Agent"><ping xmlns="urn:xmpp:ping"/></iq>
  30.                 [id] => 362-24749
  31.                 [from] => qip.cons23.ru
  32.                 [iqtype] => get
  33.                 [ignore] => 0
  34.             )
  35.             -------------------- fireIQ end------------------------
  36.             -------------------- firePITrail ---------------------------
  37.             Array
  38.             (
  39.                 [direction] => 0
  40.                 [pi] => <iq from='ipworksphp1@qip.cons23.ru/IP*Works! XMPP Agent' to='qip.cons23.ru' id='362-24749' type='result'/>
  41.             )
  42.             -------------------- firePITrail end------------------------
  43.        
  44.     */
  45.         print_r($param); // печать параметров события в стандартный вывод
  46.         return $param; // возврат функции
  47.     }
  48.     function firePITrail($param) {
  49.     // событие для всех сообщений протокола, имеет два параметра: направление (0 - от клиента к серверу, 1 - от сервера клиенту, 2 - информационное) и само сообщение
  50.         global $msg_file_name; // делаем переменную глобальной, чтобы использовать внутри функции
  51.         if ($param['direction']==1) { // смотрим сообщения полученные с сервера
  52.             if (preg_match('/body/si', $param['pi'])) { // смотрим сообщения, у которых есть тело (регулярка проверяет наличие тега <body>)
  53.                 preg_match("/^.+id=\"(.*?)\".*type=\"(.*?)\".*from=\"(.*?)\".*<body>(.*?)<\/body>.*<thread>(.*?)<\/thread>.+$/si", $param['pi'], $output_array);
  54.                 /* разбираем сообщение на запчасти с помощью регулярного выражения, оригинальные сообщения выглядят примерно так:
  55.                     <message to="ipworksphp1@qip.cons23.ru/IP*Works! XMPP Agent" id="YeCon-5376" type="chat" from="pestretsov.aa@qip.cons23.ru/Spark"><body>Тело сообщения</body><thread>qAh2Hi</thread><x xmlns="jabber:x:event"><offline/><composing/></x><active xmlns="http://jabber.org/protocol/chatstates"/></message>
  56.                 */
  57.                 if (count($output_array)==6 && $output_array[2]=='chat' && preg_match("/^[a-zA-Z]{1,20}\.[a-zA-Z]{2}@qip\.cons23\.ru(|\/.+)$/si", $output_array[3])) { // проверяем что сообщение запарсилось и у нас на выходе массив на 6 элементов, чтобы два раза не вставать смотрим ещё чтобы тип сообщения был chat, а отправитель укладывался в наш паттерн (имел имя пользователя как у нас в домене, домен чтобы был тоже наш)
  58.                     $mID=$output_array[1]; // ID сообщения
  59.                     $mType=$output_array[2]; // Тип сообщения
  60.                     $mFrom=$output_array[3]; // Отправитель сообщени
  61.                     $mBody=$output_array[4]; // Тело сообщения
  62.                     $mThread=$output_array[5]; // ID разговора
  63.                    
  64.                     $mTypes=array_flip(array("normal", "chat", "groupchat", "headline", "error")); // создаём массив строковых типов сообщений (мы там вверху в регулярке фильтруем только chat, но можно отвечать на любые) и переворачиваем массив, т.е. если на создании он у нас 4=>error, то теперь будет error=>4
  65.                     $mType=$mTypes[$mType]; // меняем наше текстовое название типа сообщения на цифровое
  66.                    
  67.                     $order   = array("\r\n", "\n", "\r"); // т.к. в сообщениях может встречаться символ перевода строки, а я собираюсь хранить сообщение в строку, то от этих символов надо избавиться, тут задаётся массив таких символов
  68.                     $replace = '<br />'; // это на что я их буду менять, в данном случае тег перевода строки из html
  69.                     $mBody=str_replace($order, $replace, $mBody); // заменем подстроки $order на $replace
  70.  
  71.                     file_put_contents($msg_file_name, $mFrom.'|||'.$mType.'|||'.$mBody.'|||'.$mID.'|||'.$mThread."\n", FILE_APPEND | LOCK_EX); // пишем строку в файл, разделитель у нас ||| так что если попадёт сообщение с такой подстрокой, то получим косяк
  72.                 }
  73.             }
  74.         }
  75.         print_r($param); // печать параметров события в стандартный вывод
  76.         return $param; // возврат функции
  77.     }
  78. }
  79.  
  80. $xmpp = new MyXMPP(); // создаём объект из класса выше
  81.  
  82. $xmpp->setPresence(1); // параметр что мы будем показывать себя как он-лайн пользователя
  83. $xmpp->setTimeout(0); // ставим вечный таймаут
  84. $xmpp->doConfig('codepage=65001'); // кодировка UTF8
  85. $xmpp->doConfig('ParseHTML=true'); // эта опция нужна если мы будем отправлять HTML сообщения, то наш класс их распарсим и отправит текстовую часть как текст для совместимости
  86. $xmpp->setIMServer('qip.cons23.ru'); // сервер
  87. $xmpp->setAuthMethods('SASL/PLAIN'); // тип авторизации
  88.  
  89. try {
  90.     $xmpp->doConnect("IPworksphp1", "IPworksphp1");  // соединяемся с именеи и паролем
  91. } catch (Exception $e) {
  92.     file_put_contents($fullPath.'send_connection.log', $e->getMessage(), FILE_APPEND | LOCK_EX); // если ошибка подключения, то пишем её в файл
  93. }
  94.  
  95.  
  96.  
  97. while (true) { // заводим вечный цикл
  98.     $xmpp->doEvents(); // обрабатываем события из внутренней очереди, например, отвечаем серверу на пинги, в модуле уже это встроено, поэтому на такие события не надо писать пользовательской функции
  99.    
  100.     if (is_file($msg_file_name) && filesize($msg_file_name)>12) { // смотрим существует ли наш файл-буфер исходящих сообщений
  101.         $sendArray=file($msg_file_name); // читаем файл в массив (каждая строчка - элемент)
  102.         unlink($msg_file_name); // удаляем наш файл-буфер
  103.        
  104.         $replace = "\r\n"; // задаём символы перевода строки для обратного преобразования
  105.         $order = '<br />'; // задаём символы перевода строки для обратного преобразования
  106.        
  107.         foreach ($sendArray as $line) { // проходимся по каждому элементу массива сообщений
  108.             $sendVars=explode ('|||', $line); // переводим нашу строку с разделителями обратно в массив
  109.             $mID=$sendVars[3]; // ID сообщения
  110.             $mType=$sendVars[1]; // Тип сообщения
  111.             $mFrom=$sendVars[0]; // Отправитель сообщени
  112.             $mBody=$sendVars[2]; // Тело сообщения
  113.             $mThread=$sendVars[4]; // ID разговора
  114.  
  115.             $mBody=str_replace($order, $replace, $mBody); // заменем подстроки $order на $replace
  116.            
  117.             $xmpp->setMessageText($mBody); // задаём текст сообщения
  118.             $xmpp->setMessageType($mType); // задаём тип сообщения
  119.             $xmpp->setMessageThread($mThread); // задаём ID разговора
  120.             try {
  121.                 $xmpp->doSendMessage($mFrom); // отправляем сообщение пользователю
  122.             } catch (Exception $e) {
  123.                 file_put_contents($fullPath.'send_error.log', $e->getMessage(), FILE_APPEND | LOCK_EX); // если что-то пошло не так пишем ошибку в лог
  124.             }
  125.         }
  126.     }
  127.     sleep($sleepTime); // на завершении прохода цикла приостанавливаем выполнение на $sleepTime секунд, т.к. на полной скорости нам работать не нужно
  128. }
  129.  
  130.  
  131. $xmpp->doDisconnect(); // тут отключаемся, но это можно не делать, т.к. при нормальном выполнении до сюда всё равно не дойдёт, а на непойманном исключении программа просто завершится и всё равно до сюда не дойдёт
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement