Еще пара слов о переходе на Jabber или ICQ бот

26-02-2009

Сам, как приверженец свободных технологий, я давненько завел себе jabber аккаунт, но он долго пустовал, т.к. никто из асечного контактлиста не поддавался на уговоры перейти на jabber. Тут, в свете недавних проблем с AOL и нескольких хабратопиков о XMPP клиентах и способах переманивания людей на них, меня постигла идея поставить на мой UIN бота. Пускай он умеет немного говорить и отсылать всех разговорчивых в нужном направлении. Поискав на тему предмета разговора в интернете, ничего стоящего не удалось найти. Зато наткнулся на страницу с набором классов на PHP, реализующих минимальную функциональность ICQ протокола.
Недолго думая, скачал и попробовал на деле. Работает!!!
и спустя 30 минут написал следующее:


icqbot.php

 

Copy Source | Copy HTML
  1. #!/usr/bin/php
  2. include('icq.php');
  3.  
  4. //подключение zendloader
  5. require 'Zend/Loader.php';
  6. Zend_Loader::registerAutoload();
  7.  
  8. //чтение конфига
  9. $config = new Zend_Config_Xml('config.xml',NULL,true);
  10.  
  11. //подключение к БД
  12. $db = Zend_Db::factory($config->dbadapter,$config->db->toarray());
  13. $db->query('SET CHARACTER SET "'.$config->dbcharset.'"');
  14.  
  15. //аськоклиент
  16. $icq = new WebIcqLite();
  17.  
  18. log_write("ICQ Bot started");
  19.  
  20. //коннектимся
  21. if (!$icq->connect($config->icq->login,$config->icq->password))
  22. {
  23. log_write($icq->error);
  24. exit();
  25. }
  26.  
  27. log_write("Connected ok");
  28.  
  29. while($icq->is_connected())
  30. {
  31. //читаем входящее сообщение
  32. $msg = $icq->read_message();
  33. if($msg)
  34. {
  35. //список админских комманд
  36. if ($msg['message']=="icqbotoff")
  37. {
  38. $icq->disconnect();
  39. log_write("Exit by admin's command.");
  40. exit();
  41. }
  42.  
  43. log_write(" Message '".$msg['message']."' from ".$msg['from']);
  44.  
  45. //режем все лишние символы
  46. $msg['message'] = str_replace(array('(',')','/',':','.',',','?','!','@','#','$','%','^','&','*','-','_','=','+','~','`',';','|','\\','\'','"'),'',$msg['message']);
  47.  
  48. //ищем ответ
  49. $ans = $db->select()->from('messages')->where('q LIKE ?',trim($msg['message']))->where('LENGTH(a)>0')->order('RAND()')->query()->fetch();
  50.  
  51. if ($ans)
  52. {
  53. //точное совпадение
  54. log_write(" Message '".$ans['a']."' sent to ".$msg['from']);
  55. }
  56. else
  57. {
  58. //нет совпадений. ищем полнотекстово.
  59. $db->insert('messages',array('q'=>$msg['message'],'a'=>'','from'=>$msg['from']));
  60. $query = "SELECT *, MATCH q AGAINST ('".$msg['message']."') as relev FROM messages WHERE LENGTH(a)>0 ORDER BY relev DESC LIMIT 1";
  61. $ans = $db->query($query)->fetch();
  62. if ($ans['relev']>0)
  63. {
  64. //нашли ответ
  65. log_write("Message (fulltext search) '".$ans['a']."' sent to ".$msg['from']);
  66. }
  67. else
  68. {
  69. //нет совпадений. выдаем сообщение по умолчанию.
  70. $ans = $db->select()->from('messages')->where('q LIKE ?','default')->query()->fetch();
  71. log_write("Message 'DEFAULT' sent to ".$msg['from']);
  72. }
  73. }
  74. $icq->send_message($msg['from'], $ans['a']);//собственно отправка сообщения получателю
  75. }
  76. //спим секунду
  77. flush();
  78. sleep(1);
  79. }
  80.  
  81. //уходим
  82. log_write("Disconnected by unknown reason.");
  83. $icq->disconnect();
  84.  
  85.  
  86.  
  87.  
  88. //----------------------------------------------------------------------------------------//
  89. //вспомогательные функции//
  90.  
  91. function log_write($str)
  92. {
  93. echo date('Y.m.d H.i.s',time())." ".$str."\n";
  94. }



config.xml

Copy Source | Copy HTML
  1. xml version="1.0" encoding="UTF-8"?>
  2. <configdata>
  3. <debug>0debug>
  4. <db>
  5. <host>localhosthost>
  6. <username>rootusername>
  7. <password>dbpasspassword>
  8. <dbname>icqbotdbname>db>
  9. <dbcharset>CP1251dbcharset>
  10. <dbadapter>Pdo_Mysqldbadapter>
  11. <icq>
  12. <login>UINlogin>
  13. <password>PASSWORDpassword>
  14. icq>



dump.sql

Copy Source | Copy HTML
  1. CREATE TABLE IF NOT EXISTS `messages` (
  2. `id` int(11) NOT NULL auto_increment,
  3. `q` text NOT NULL,
  4. `a` text NOT NULL,
  5. `from` varchar(16) NOT NULL,
  6. PRIMARY KEY (`id`),
  7. FULLTEXT KEY `q` (`q`)
  8. ) ENGINE=MyISAM DEFAULT CHARSET=cp1251 AUTO_INCREMENT=43 ;
  9.  
  10. INSERT INTO `messages` (`id`, `q`, `a`, `from`) VALUES
  11. (1, 'default', 'В данный момент вы говорите с роботом.
  12. Если вы хотите говорить с моим хозяином, вам необходимо зарегистрироваться на одном из Jabber серверов, т.к. в ICQ он больше не появится.
  13. Чтобы узнать подробности о Jabber-е, введите 1.
  14. Чтобы узнать Jabber адрес хозяина, напишите, сколько будет 2плюспять.
  15. Чтобы узнать почтовый адрес хозяина, введите цифры от 1 до 7 без пробелов.', ''),
  16. (2, '1234567', 'My@mail.ri', ''),
  17. (3, '7', 'My@jabber.ru', ''),
  18. (4, '1', 'Один из популярных Jabber серверов - jabber.ru
  19. http://www.jabber.ru/node/247 - это адрес страницы с инструкцией по регистрации подключению к нему.
  20. Чтобы узнать Jabber адрес хозяина, напишите, сколько будет дваплюс5.', ''),
  21. (5, 'привет', 'Привет )', ''),
  22. (6, 'как дела', 'Нормально )', '');



И не забыть положить в папочку с ботом ZendFramework

Не буду что-то комментировать, т.к. все достаточно тривиально.
Отмечу лишь то, что не ставил задачу сделать что-то серьезное, а только отсылалку по адресу (хотя уже набрал достаточно диалогов и бот с некоторыми знакомыми уже говорил цепочками сообщений в 5-10 штук без вываливания дефолтного сообщения). Бот не работает с сообщениями в формате RTF, но в классе реализована эта возможность(можно доделать). Можно было конечно прикрутить и беседу с отдельными UIN в отдельные потоки. Но это дело другое. Главное идея )
Сие творение уже 4 дня в полете. Людей по 1-2 человека в день в jabber контактлисте прибавляется.
Вот такое вот чудо получилось.

Вернуться в блог

Оставить комментарий