The easy Weblog and Wiki Software
[ start | index | login ]
start > SmackBot

SmackBot

Created by senikk. Last edited by senikk, 4 years and 295 days ago. Viewed 2,358 times. #1
[edit] [rdf]
labels
attachments

SmackBot - XMPP Bot using the Smack Library

This bot is currently called SmackBot (I think I'll change it to XMPPBot) The SmackBot is developed using the >>Smack Library Its currently running in my personal SnipSnap at >>http://senikk.com I apriciate suggestions, just post a comment.

Ideas

Todo
  • Add connection listener
  • Improve connection listener add degrading polling interval while trying to reconnect.
    CHANGE This functionality will soon be included in the Smack Library
  • Need to fix the roster handling and groups
  • Add an url to the snip in sendHeadline
Config
app.xmpp.server=
app.xmpp.user=
app.xmpp.password=
app.xmpp.resource=

The Code

package org.snipsnap.notification.xmpp;

// SnipSnap + Radeox import import org.snipsnap.app.Application; import org.snipsnap.config.AppConfiguration; import org.snipsnap.snip.SnipSpace; import org.snipsnap.snip.SnipSpaceFactory; import org.snipsnap.user.UserManager; import org.radeox.util.logging.Logger;

// Smack import import org.jivesoftware.smack.PacketListener; import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.XMPPException; import org.jivesoftware.smack.PacketCollector; import org.jivesoftware.smack.Roster; import org.jivesoftware.smack.ConnectionListener; import org.jivesoftware.smack.filter.PacketFilter; import org.jivesoftware.smack.filter.PacketTypeFilter; import org.jivesoftware.smack.filter.FromContainsFilter; import org.jivesoftware.smack.filter.AndFilter; import org.jivesoftware.smack.packet.Message; import org.jivesoftware.smack.packet.Packet; import org.jivesoftware.smack.packet.Presence;

public class SmackBot { private static SmackBot instance; private XMPPConnection xmpp; private String xmppServer; private String xmppUser; private String xmppPassword; private String xmppResource;

public static synchronized SmackBot getInstance() { if (null == instance) { instance = new SmackBot(); } return instance; }

// // Listeners //

private ConnectionListener conlistener = new ConnectionListener() { public void connectionClosed() { Logger.warn("XMPP Connection Closed"); connect(); }

public void connectionClosedOnError(Exception e) { Logger.warn("XMPP Connection Error: "+e.toString()); connect(); } };

private PacketListener listener = new PacketListener() { public void processPacket(Packet packet) { Message message = (Message)packet; postBlogItem(message.getSubject(),message.getBody()); } };

// // Connect //

private void connect() { try { xmpp = new XMPPConnection(xmppServer);

if(xmpp.isConnected()) { Logger.warn("SmackBot: connected"); xmpp.login(xmppUser,xmppPassword,xmppResource); } else Logger.warn("SmackBot: not connected"); } catch(Exception e) { Logger.warn("SmackBot unable to connect",e); } }

// // The Bot //

public SmackBot() { try { // Read configuration AppConfiguration conf = Application.get().getConfiguration(); xmppServer = conf.getProperty(conf.APP_XMPP_SERVER); xmppUser = conf.getProperty(conf.APP_XMPP_USER); xmppPassword = conf.getProperty(conf.APP_XMPP_PASSWORD); xmppResource = conf.getProperty(conf.APP_XMPP_RESOURCE);

// Login into xmpp server connect();

// Add connection listener xmpp.addConnectionListener(conlistener);

// Add packet filter - needs to be changed PacketFilter postfilter = new AndFilter(new PacketTypeFilter(Message.class),new FromContainsFilter("senikk@jabber.org/Psi")); PacketCollector myCollector = xmpp.createPacketCollector(postfilter); xmpp.addPacketListener(listener,postfilter);

// Add group to Roster Roster roster =xmpp.getRoster(); roster.setSubscriptionMode(Roster.SUBCRIPTION_ACCEPT_ALL); roster.createGroup("registered");

Logger.debug("Registered Groups: "+roster.getGroupCount()+" Entries: "+roster.getEntryCount());

} catch (Exception e) { Logger.warn(e.toString()); } }

public void postBlogItem(String title, String body) { // Get blog instance String user = Application.get().getConfiguration().getAdminLogin(); Application.get().setUser(UserManager.getInstance().load(user)); SnipSpaceFactory.getInstance().post(body,title); }

// // Roster //

public void addToRoster(String jid, String group) { Roster roster = xmpp.getRoster(); String[] groups = {group}; try { roster.createEntry(jid,jid,groups); } catch(XMPPException e) { Logger.warn(e.toString()); } }

// // Presence //

public String onlineStatus(String jid) { Roster roster = xmpp.getRoster(); Presence presence = roster.getPresence(jid); if(presence!=null) return presence.getStatus(); else return ""; }

public String onlineMode(String jid) { Roster roster = xmpp.getRoster(); Presence presence = roster.getPresence(jid); if(presence!=null) return presence.getMode().toString(); else return ""; }

// // Headline //

public void sendHeadline(String user, String message) { try { Logger.debug("Sending '" + message + "' to '" + user + "' ...");

Message msg = new Message(user,Message.Type.HEADLINE); msg.setSubject(Application.get().getConfiguration().getName()); msg.setBody(message); xmpp.sendPacket(msg); Logger.debug("Sent."); } catch (Exception e) { Logger.warn("Unable to send message to " + user, e); } }

}

The Smack Library

A simple example of sending a message to me with smack:

XMPPConnection con = new XMPPConnection("jabber.org");
con.login("user","password");

Chat chat = con.createChat("senikk@jabber.org"); chat.sendMessage("Hey, how's it going?");

Group Chat
When you register yourself at SnipSnap site or maybe when you add yourself a {jabberID} label I think of sending a jabber invite request to this jid telling that there exists a chat room for this site. I don't think the users would like to have such request every time they login and they are not in the chat room, but this could be an option.

With smack you can write such request as:

Packet invite = new Packet() {
  public String toXML() {
    return
      "<message to='senikk@jabber.org/Psi' from='senikk@jabber.org/qexo-weblog'>" +
      "<body>SnipSnap invite you to chat</body>" +
      "<x xmlns='jabber:x:conference' jid='qexo-weblog@conference.jabber.org' />" +
      "</message>";
  }
};
con.sendPacket(invite);

Icons
I read somewhere that someone had made some sort of jabber: url to lets say open the user jabber client chat window. But I don't think it has become a standard yet.

>>draft-ietf-xmpp-uri

Another solution I think of is to use the invite message above to send an invite message when you click on the SnipSnap users jabber icon, this demands that you have to be registered and logged into the SnipSnap site and have the {@jabberID} label in your snip. When the user receive the invite message he/she can initiate the chat with you.

Another possibility I think could be clicking on an "add to your Roster" icon sending a Roster message to your jid with the clicked SnipSnap user jid. Maybe this could be display for the {@jabberID} label in the users snip.

Online Status
By having a jabber bot adding every SnipSnap user with a {@jabberID} label to its Roster, I think it should be easy to extend lets say the {logins} macro to have the possibility to show the correct jabber icon symbol telling if you are online or not.

This makes it also possible I think to send anouncement messages to all registered users.

Affected macros / label
{logins}
{list-of-users}
{@jabberID:senikk@jabber.org}

2 comments (by agni) | post comment

What is SnipSnap?
SnipSnap is a free and easy to install weblog and wiki tool written in Java.

SnipSnap download
Current version: 1.0b3-uttoxeter
Try our >>Web Start Demo!

Resources

5567 Users and 13712 Snips. Installed 5 years and 363 days ago

Logged in Users: (2)
… and 23 Guests.

snipsnap-changed for older changes.

< July 2008 >
SunMonTueWedThuFriSat
12345
6789101112
13141516171819
20212223242526
2728293031

snipsnap
Listed on BlogShares
XHTML 1.0 validated
CSS validated
RSS 2.0 validated
RSS Feed

pico-powered

Powered by SnipSnap 1.0b3-uttoxeter
YourKit >>Java Profiler

Fraunhofer FIRST

snipsnap.org | Copyright 2000-2006 Fraunhofer FIRST