Simple question (I hope)

Hi All,

I just started using Smack library and I’‘m well impressed with it, however there is a simple problem I can’'t figure out.

Can anybody post a sample code, on how to listen for chat messages from other users and respond to them?

Thanks and regards.

Ven,

This example shows how to create a chat with a user and send a message.

// User1 creates a chat with user2
    Chat chat1 = conn1.createChat("user@host.com");     // User1 creates a message to send to user2
    Message msg = chat1.createMessage();
    msg.setSubject("Any subject you want");
    msg.setBody("Hey John, this is my new green!!!!");     // Send the chat message
    try {
        chat1.sendMessage(msg);
    } catch (Exception e) {
        e.printStackTrace();
    }

In this other example you can see how to listen for messages of the chat and how to respond.

// Create a listener for the chat that will respond with the same message     // to the other chat participant
    PacketListener packetListener = new PacketListener() {
        public void processPacket(Packet packet) {
            Message message = (Message) packet;
            System.out.println("Message received: " + message.getBody());
            // Send a response
            try {
                chat2.sendMessage("You said: " + message.getBody());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    };
    chat2.addMessageListener(packetListener);

– Gato

Hi Gato,

Thanks for the reply.

I managed to listen for packets using addPacketListener, however there is a chiken egg problem that I’'m having.

Here is a snippet of the code:

public class JabberBot implements PacketFilter, PacketListener {

public boolean accept(Packet packet)

{

try{

Message msg = (Message)packet;

return msg.getType() == Message.Type.CHAT;

}

catch(Exception e)

{

e.printStackTrace();

return false;

}

}

java.lang.ClassCastException: org.jivesoftware.smack.packet.RosterPacket

at jabbot.JabberBot.accept(JabberBot.java:21)

at org.jivesoftware.smack.PacketCollector.processPacket(PacketCollector.java:205)

at org.jivesoftware.smack.PacketReader.processPacket(PacketReader.java:345)

at org.jivesoftware.smack.PacketReader.parsePackets(PacketReader.java:277)

at org.jivesoftware.smack.PacketReader.access$000(PacketReader.java:77)

at org.jivesoftware.smack.PacketReader$1.run(PacketReader.java:103)

I understand that the Roster packet is being casted to a Message and the exception is being thrown, but how would you check the type of the packet?

Thanks and regards.

Ven,

It seems that you are adding JabberBot as a PacketListener directly to the connection. That’'s why JabberBot is receiving packets other than the Message type. If you take a look at my example you will see that you must add the listener to the chat.

If you add the listener to the chat then you won’'t have to filter messages of type chat since the chat class already does this. Therefore, JabberBot does not need to implement the PacketFilter interface.

Regards,

– Gato

Gato,

You are correct, however when you create a chat object you have to specify a recipient. The application I’'m creating is an IM bot (as you figured) so it will need to be able to respond to chat sessions from any user, and not initiate one.

Or, am I missing something here?

Regards.

Ven,

I think that you have two options here.

Option 1: “Create a Chat instance for each chat”

In this option you have to detect when someone starts a new chat and create a Chat instance using the Chat(connection,participant,chatID) constructor. Once you have created a new Chat instance you will want to add a listener that will be notified of any new messages in the chat.

Option 2: “Directly listen to all the Messages”

In this option you will have to add a listener directly to the connection using #addPacketListener(PacketListener, PacketFilter) where PacketListener could be your bot and the PacketFilter could be a PacketTypeFilter on the class Message. Since the messages that you will receive could be part of a chat you will need to set the Type and Thread to the response.

I will probably choose the second option since you won’‘t be creating Chat instances all the time and therefore you won’'t have to take care of when to release the Chat instances (that is figure out when a Chat has finished). IMHO, the second option is more efficient than the first option.

Regards,

– Gato

Option 2: "Directly listen to all the

Messages"

In this option you will have to add a listener

directly to the connection using

#addPacketListener(PacketListener, PacketFilter)

where PacketListener could be your bot and the

PacketFilter could be a PacketTypeFilter on the class

Message. Since the messages that you will receive

could be part of a chat you will need to set the Type

and Thread to the response.

I will probably choose the second option since you

won’'t be creating Chat instances all the time and

therefore you won’'t have to take care of when to

release the Chat instances (that is figure out when a

Chat has finished). IMHO, the second option is more

efficient than the first option.

Regards,

– Gato

Gato,

Now we are getting at the core question; how would I go about doing that?

A skeleton code would be greatly appreciated.

Thanks and regards.

Ven,

The code would basically look like the following:

// Create a packet listener. It''s defined here as an anonymous inner
// class. However, it could be a full class if you have a lot of logic.
PacketListener myListener = new PacketListener() {
    public void processPacket(Packet packet) {
        Message message = (Message)packet;
        // do stuff with message here...
    }
};
// Add the listener to the connection and ask to be notified of all messages.
con.addPacketListener(myListener, new PacketTypeFilter(Message.class));

Regards,

Matt