In this blog post, we will write a sample XMPP bot (echobot) using Jaxl 2.0. In turn we will introduce ourselves to some of the basic functionality we can do using Jaxl e.g. fetching roster list, subscribing and unsubscribing to a user presence, etc. We will also focus on how to use XMPP extensions (XEP’s) inside our echobot code. Specifically, we will make use of XEP-0085 (chat state notification), XEP-0203 (delayed delivery) and XEP-0092 (software version) in our sample echobot application.
Echobot source code:
This sample echobot application comes packaged with Jaxl 2.0. If you have already read Installation, Usage guide and Running example apps, you might have even run this sample application.
Alternately, browse and download the sample source code from github echobot app files
Coding with Jaxl 2.0:
Every XMPP application developed using Jaxl 2.0, MUST have a jaxl.ini
environment setup file inside your project directory. For example, packaged echobot sample application contains jaxl.ini which setup necessary Jaxl environment for our echobot application.
If you are developing an application from scratch, copy sample packaged jaxl.ini
into your project folder:
cp /usr/share/php/jaxl/env/jaxl.ini /my/app/directory/jaxl.ini
and update JAXL_BASE_PATH
and JAXL_APP_BASE_PATH
with Jaxl installation path and your application directory path respectively.
Before we go on to write our echobot application code logic, lets see how an XMPP application code written using Jaxl 2.0 will generally look like:
<?php // Initialize Jaxl Library (#1) $jaxl = new JAXL(); // Include required XEP's (#2) jaxl_require(array( 'JAXL0085', // Chat State Notification 'JAXL0092', // Software Version 'JAXL0203' // Delayed Delivery ), $jaxl); // Sample Echobot class (#3) class echobot { function startStream() {} function doAuth($mechanism) {} function postAuth() {} function getMessage($payloads) {} function getPresence($payloads) {} } $echobot = new echobot(); // Add callbacks on various xmpp events (#4) JAXLPlugin::add('jaxl_post_connect', array($echobot, 'startStream')); JAXLPlugin::add('jaxl_get_auth_mech', array($echobot, 'doAuth')); JAXLPlugin::add('jaxl_post_auth', array($echobot, 'postAuth')); JAXLPlugin::add('jaxl_get_message', array($echobot, 'getMessage')); JAXLPlugin::add('jaxl_get_presence', array($echobot, 'getPresence')); ?>
Lets break down the above applications code structure (note the #1, #2, #3, #4 markers in the above code)
- #1 – Create a new Jaxl instance inside your application. By doing so Jaxl core functionality and other utilities are made available inside your application code. You can also pass parameters while initializing Jaxl instance
$jaxl = new JAXL(array( 'user' => 'username', 'pass' => 'password', 'host' => 'talk.google.com', 'domain' => 'gmail.com', 'port' => 5222 ));
Passed parameters will overwrite the values specified inside
jaxl.ini
file - #2 – Include required XMPP extensions (XEP’s) inside your application code. jaxl_require is a special method which makes sure that no Jaxl core class loads twice inside a running Jaxl instance.To include an implemented XEP inside your application code simply use:
jaxl_require('JAXL0203', $jaxl);
where 0203 is the XEP number for Delayed Delivery extension, which will help our echobot know if an incoming message is an offline message. If you wish to include more than one XEP inside your application code, simply pass the list of XEP’s as an array:
jaxl_require(array( 'JAXL0085', 'JAXL0092', 'JAXL0203' ), $jaxl);
where 0085 is xep number for Chat state notification extension and 0092 is the xep number for Software Version extension.
Since version 2.1.0,
jaxl_require
MANDOTORY accepts Jaxl instance which require core classes, in this case$jaxl
. It helps Jaxl core to keep a track of required core classes for every Jaxl instances in a multiple-instance application. - #3 – Now that we have Jaxl core and required XEP’s in our application environment, it’s time to write our application code logic. Application code MUST have methods which are called back by the Jaxl core when specific xmpp events occur during your application run time. Optionally, Jaxl core can pass parameters to these methods during callbacks.
- #4 – In the final step, we will register callbacks for necessary xmpp events using
JAXLPlugin
classadd()
method inside our application logic. Syntax:JAXLPlugin::add($hook, $callback);
In this example, we want to receive callbacks in our application code for following available hooks and events:
- jaxl_post_connect: After Jaxl has opened stream socket to the jabber server
- jaxl_get_auth_mech: When Jaxl have information about supported auth mechanisms by the jabber server
- jaxl_post_auth: After Jaxl finish authenticating the bot with the jabber server
- jaxl_get_message: When a new message stanza is received by Jaxl
- jaxl_get_presence: When a new presence stanza is received by Jaxl
Writing application logic:
Till now we have the registered callbacks for various xmpp events, it’s time to catch these callbacks inside our echobot class and implement the required functionality of our application. Below is an explanation for some of the important pieces inside echobot class:
- startStream() method is called when
jaxl_post_connect
event occurs. For our application we will simply send XMPP start stream by calling$jaxl->startStream()
- doAuth($mechanism) method is called when
jaxl_get_auth_mech
event occurs in Jaxl core. Jaxl core passes list of supported auth mechanism by the jabber server. Proceed with a preferred auth type by calling$jaxl->auth()
method - postAuth() is called after Jaxl library has finished authenticating our application bot with the jabber server
- getMessage($payloads) gets all new messages as they are received by Jaxl core
- getPresence($payloads) gets all new presence as they are received by Jaxl core
Running Echobot:
Enter your application directory (/usr/share/php/jaxl/echobot
). It MUST contain jaxl.ini
, open and edit connecting echobot username, password and jabber host. Then from command line run echobot as follows:
[email protected]:/usr/share/pear/jaxl/app/echobot# jaxl echobot.php == 5617 == [[2010-08-03 10:37:21]] Socket opened to the jabber host jaxl.im:5222 ... == 5617 == [[2010-08-03 10:37:22]] Performing Auth type: DIGEST-MD5 == 5617 == [[2010-08-03 10:37:28]] Auth completed...
Pingback: Releasing Jaxl 2.0 – Object oriented XMPP framework in PHP | Abhi's Weblog
Pingback: Jaxl 2.0 – Installation, Usage guide and Example apps | Abhi's Weblog
Pingback: Tweets that mention Writing a command line XMPP bot (echobot) using Jaxl 2.0 | Abhi's Weblog -- Topsy.com
Hi,
I tried running the downloaded echobot in ubuntu 10.04 on PHP 5.3.2-1ubuntu4.2 with Suhosin-Patch (cli) (built: May 13 2010 20:01:00)
Once I start the echobot, It just keep waiting after opening the socket successfully. something like
PHP Deprecated: Comments starting with ‘#’ are deprecated in /etc/php5/cli/conf.d/mhash.ini on line 1 in Unknown on line 0
PHP Warning: PHP Startup: Unable to load dynamic library ‘/usr/lib/php5/20090626+lfs/mhash.so’ – /usr/lib/php5/20090626+lfs/mhash.so: cannot open shared object file: No such file or directory in Unknown on line 0
== 14323 == [[2010-08-08 22:06:37]] Socket opened to the jabber host talk.google.com:5223 …
It keeps waiting. When I check the log in /var/log/jaxl.log It contains something like
== 14027 == [[2010-08-08 21:30:36]] Jaxl stream not connected to jabber host, unable to send xmpp payload…
== 14069 == [[2010-08-08 21:50:01]] [[XMPPSend]] 183
== 14309 == [[2010-08-08 22:02:48]] [[XMPPSend]] 177
== 14323 == [[2010-08-08 22:06:37]] [[XMPPSend]] 177
Can you throw some light, what I’m missing out…
Regards,
Arun
Hi Arun,
Initial few error like PHP Deprecated and PHP Warning have to do with you PHP installation. Probably you have enabled mhash PHP extension but PHP is unable to find mhash.so.
Also I can see you are trying to connect to port 5223, it should ideally be 5222. Kindly try out with port 5222 and lemme know.
Hi Abhi,
Thanks for your reply. Now that I corrected the port. But now I’m getting something like
== 16233 == [[2010-08-09 08:01:39]] Socket opened to the jabber host talk.google.com:5222 …
== 16233 == [[2010-08-09 08:01:42]] Performing Auth type: PLAIN
PHP Warning: SimpleXMLElement::__construct(): Entity: line 1: parser error : Extra content at the end of the document in /usr/share/php/jaxl/core/jaxl.parser.php on line 126
PHP Warning: SimpleXMLElement::__construct(): </stre in /usr/share/php/jaxl/core/jaxl.parser.php on line 126
PHP Warning: SimpleXMLElement::__construct(): ^ in /usr/share/php/jaxl/core/jaxl.parser.php on line 126
Help me out again…
Hi Arun,
This is probably because you have wrong credentials (username/password) combination inside jaxl.ini file.
While connecting with google talk servers, if you provide wrong credentials, google talk servers respond back with something like $xml = “……</stream:stream>” which causes an invalid xml type detection.
This shall be fixed in future releases, but as of now kindly make sure you have the right username password combination while connecting with gtalk servers.
Lemme know how it goes.
Hi Abihv,
Thanks for your reply again. I’m sure the password is correct. But I tried with one more account ‘[email protected]’. It works cool..!
My original account is still not working. Any guess in this direction…
Thanks, Regards,
Arun
I am not too sure. Try to connect to your original account using gmail integrated chat or desktop gtalk client, and then back again with Jaxl library. Hope this take us to a solution 🙂
Hard luck again.. I’m able to login from my web interface… still no success with my original account… thanks a lot for your time that too in Monday morning.. 🙂
Hi Abhinav,
Got it… It’s expecting goolemail.com instead of gmail.com as a part of my original user id…!
Regards,
Arun
Hi Abhinav,
I was trying to make Jaxl to work on my CentOS 5.5 box, but for some reason it stucks after “Socket opened to the jabber host”… Has you mentioned above, I already checked my user/pass credentials, but nothing changes.
My Jabber server is Openfire. Jaxl 1.0.2 is working fine up to now, using the same credencials… Do you have any idea of what are causing this?
By the way, it would be interesting to have version dependencies like PHP minimal versions, which PHP libs must be installed, etc…
By the way, GREAT WORK on Jaxl… really amazing job. Thanks a lot!
Hi Daniel,
Jaxl have following pre-requisites:
– PHP5
– fsockopen/curl/json support
– OpenSSL enabled for TLS encryption
Generally these dependencies are checked by Jaxl on startup and logs appropriate info inside jaxl.log. Jaxl library will undergo a lot of useful core changes from version 2.1.2 (currently in dev branch). Though core has been upgraded in a way that application codes have minimalistic changes to make (if at all). See CHANGELOG for list of changes in upcoming version.
I personally haven’t runned Jaxl against an openfire server yet (but will do soon if you are unable to proceed further). To debug further can you tail your open fire server log to see what happens when Jaxl client tries to connect with it?
Hey Abhinav,
I just did some tests here… but nothing is logged on Openfire debug log… Jaxl just get stuck on “Socket opened to the jabber host” and nothing happens after.
On jaxl.log I have this:
Jaxl stream not connected to jabber host, unable to send xmpp payload…
== 19265 == [[2010-11-18 10:20:34]] [[XMPPSend]] 183
wordpress escaped… after the last line of previous comment we have this:
‘#/stream:stream#’
You read # as
Looks like I found the problem… CentOS 5.5 have PHP 5.1.6… When running from Ubuntu PHP 5.3.3 Jaxl works like a charm… So, I guess thats it.
Thanks Abhinav.
Regards.
Hi Daniel,
I have test Jaxl on following environment: PHP 5.2.10-2ubuntu6.4 with Suhosin-Patch 0.9.7 (cli). However I am sure Jaxl should would else where too after a few tweaks.
Will it be possible for you to submit a patch if you can find out the fix. Else sometime later i will try to setup CentOS 5.5 with PHP 5.1.6.
Yeap… I’ll make some tests and report to you asap.
I guess that the main problem is on SSL support… lets see… I’ll keep you updated.
Tks.
Hi Abhinav,
Today I was able to do some hacking and find out the problem… Maybe you could help… In xmpp.get.php, function proceed, the array[‘xmlns’] is null, so doesnt satisfy IF command… So I commented IF line and than it hungs again on function challenge cause of a null arr[‘xmlns’].
Seems like the xml is not being correctly handled… I’ll try to find the object that’s causing the problem.
Ok, now for sure I could assure that the problem is on JAXLXml function on jaxl.parser.php. For some reason its returnig a null array, and thats why I’m having problems on CentOS 5.5 PHP 5.1.6. Do you have any hints for me, so I can debug better where in parse function is the problem?
Thanks in advance.
Hi Daniel,
Probably can be a bug inside
JAXLXml::parse
method which actually takes care of specified xml xpaths by various xep’s + core files. I will be in a better situation to assist you further if you can send mejaxl.log
file and also the exact line insidexmpp.get.php
where you face this problem….Also tonight i m going to do some experiments with Openfire + Jaxl and see how it goes, will keep you updated if i find anything.
Hi Abhinav,
The problem starts at line 125 (proceed function)on xmpp.get.php, where an if checks the array, but it is null, probably because its not being handled correctly by JAXLXml::parse as you told before.
Hi Daniel,
I am off on vacation till 25th dec. before i return back to my work place…. I have little access to internet or even a laptop to work with…. Will get back to this issue once i m back and will keep u updated….
Hi Daniel, I finally did some tests with Openfire 3.6.4 + Windows XP box with latest version of Jaxl library downloaded from github. I can see everything going smooth with openfire. Will soon get the tests done against a CENT OS box and post my updates here.
Hi Daniel, Finally i installed a CentOS image with PHP 5.1.6 and indeed Jaxl hangs after receiving <proceed xmlns=”…”> from the xmpp server. I am onto it and shall checkin the code with appropriate fix. To further track this issue i have opened a bug here: http://code.google.com/p/jaxl/issues/detail?id=25
Hi Daniel, The issue has been fixed and pushed to master repo @github. Kindly test, verify the changes and let me know if the problem still persists. https://github.com/abhinavsingh/JAXL/commit/2978d2110526e08d76ce353f21742ccff5f4c1d5
Thanks for your feedback Abhinav. If I can help in something else, please let me know.
Ok, tested and fixed… Thanks A LOT!!! but I’m facing with these 3 warnings…
PHP Notice: Undefined index: ping in /home/zabbix/jaxl2.1.2/xep/jaxl.0199.php on line 64
PHP Notice: Undefined index: time in /home/zabbix/jaxl2.1.2/xep/jaxl.0202.php on line 67
PHP Notice: Undefined index: offline in /home/zabbix/jaxl2.1.2/app/teste.php on line 68
Hi Daniel,
These warnings are probably happening because you must be using XEP 0199, 0202 inside your application.
Not everytime they get a $payload[‘ping’] variable from JAXLXml parser and hence the PHP Notice. You can set appropriate error_reporting() level to ignore these.
Great Abhinav… Thanks!! Keep the good work, Jaxl is really amazing.
Hello,
Sir How can I pass arguments ?
Like
jaxl echobot.php username password
I tried to use $argv[] but console returned this error
“invalid number of parameters passed …”
Hi Chetan,
Kindly download and use v 2.1.2-rc1 which should remove this error for you.
Hi Abhinav, already test your v2.1.2… Is this just can run on localhost? Can’t run on web hosting? I’m using PHP5 too and test your code more than 5 hours just now and nothing I got for possible run FB Chat… 🙁
I think your guide not complete or not update. Hope you can make a new post and telling how to & step by step about new version…
I already test your old version too, and seriously I got nothing here… And I don’t know this is the truth code can use FB Chat or not… Still try and try but now very stuck just focus on your code…
Hi Abhinav, how can i do to know if one user has logged on from another client (talk, messengerfx, ebuddy etc) at the same time with the same account? it’s this possible?
juanlopez -> gtalk
juanlopez -> gmail (chat active)
juanlopez -> an instance of JAXL
I need to known if this user has a multiple chat active.
Tanks for your help!! =)
JAXL 2.1.2 works perfec!!!
Can i know how to setup Jaxl with openfire
Hi Abhinav,
ofter executing the echobot.php i got the following error in jaxl.log file please help me
[1:3560:0] 2012-07-17 13:32:31 – [[XMPP]]
Socket opened to the jabber host talk.google.com:5222 …
[1:3560:0] 2012-07-17 13:32:31 – [[XMPPSend]] 177
[1:3560:0] 2012-07-17 13:32:31 – [[XMPPGet]] 4096
[1:3560:0] 2012-07-17 13:32:31 – [[XMPPGet]] 4096
X-GOOGLE-TOKENX-OAUTH2
[1:3560:0] 2012-07-17 13:32:31 – [[XMPPGet]] OpenSSL extension required to proceed with TLS encryption
https://github.com/abhinavsingh/JAXL from logs i can see you are still using Jaxl v2.x.
Please start using v3.x is you don’t have any dependency upon the previous version.
Hi Abhinav
Thanks for fast reply
As per mentioned i followed the above link and downloaded the v3.x, when i opened the example files in zend editor it showes the errors please help me with updated example files
i got the error at the following code in some of the files in example folder
$client->add_cb(‘on_auth_success’, function() {
global $client;
_debug(“got on_auth_success cb, jid “.$client->full_jid->to_string());
$client->set_status(“available!”, “dnd”, 10);
});
you need to specify and give details of what error you really got
Hi Abhinav,
i got contact list from the account
i got the contact list as below, please help me what’s error in first line and how to develop the chat list like as gmail
OSType: Windows, Unable to register shutdown functions, try moving to a linux box OpenSSL: Enabled for CLI Starting TLS Encryption… Attempting PLAIN Authentication… Starting Session… Requesting Feature List… Requesting Roster List… Setting Status… Array ( [0] => [email protected] [1] => [email protected] [2] => [email protected] ) Done
Hi Abhinav,
OSType: Windows, Unable to register shutdown functions, try moving to a linux box OpenSSL
Hi Abhinav,
ofter executing the script i got the following message in log file but i did not receive any message please help me
2012-07-19 09:46:59
Initializing class variables
2012-07-19 09:46:59
Trying to connect at talk.google.com:5222
2012-07-19 09:46:59
Connection made successfully at talk.google.com:5222
2012-07-19 09:47:00
Starting TLS Encryption…
2012-07-19 09:47:02
Already connected, sending start stream again at talk.google.com:5222
2012-07-19 09:47:03
Authenticating…
2012-07-19 09:47:04
Authentication Successful
2012-07-19 09:47:05
Binding to the server stream
Hi Abhinav,
i got the information as following but i did not receive any message, please help me
1343042242 [INFO]: Connecting to tcp://talk.google.com:5222
1343042243 [INFO]: Starting TLS encryption
1343042243 [INFO]: Attempting Auth…
1343042243 [INFO]: Auth success!
1343042244 [INFO]: Bound to [email protected]/xmpphpA8781BCF
1343042244 [INFO]: Session started
Session Start
Presence: [email protected]/Talk.v1044F691B34 [available]
Presence: [email protected]/gmail.993F350F [available]
Presence: [email protected]/gmail.83603998 [available]
Presence: [email protected]/Talk.v104FB5AFB4C [available] Life isn’t a matter of milestones but of moments.
Presence: [email protected]/gmail.9D20AD8D [away]
Presence: [email protected]/Smack99CB5EFD [available]
Announcing Jaxl v3.x – asynchronous, non-blocking I/O, event based PHP client/server library – http://abhinavsingh.com/blog/2012/07/announcing-jaxl-v3-x-asynchronous-non-blocking-io-event-based-php-clientserver-library/