📜 ⬆️ ⬇️

Java XMPP bot using Smack API

image

Good day to all!
The theme of writing bots for gabber is quite widespread. But on Habré, I found only one article in which the bot was written for the OpenFire server. And in the first comment it is written that it would be nice to read about writing a universal bot, not tied to the server. So I decided to write this article. Also I will tell you about the bot for Google Talk and one nuance associated with this bot.


Bot for jabber

As in the above article, I have an OpenFire server, so I decided to use their own library (this does not mean that the bot will only work with my server). There are a lot of examples for bot implementation, and the next code is unlikely to be very new.
')
public class Main { public static void main(String[] args) { try { String botNick = "nickname"; String botPassword = "password"; String botDomain = "jabber.org"; String botServer = "jabber.org"; int botPort = 5222; JabberBot bot = new JabberBot(botNick, botPassword, botDomain, botServer, botPort); Thread botThread = new Thread(bot); botThread.start(); } catch(Exception e) { System.out.printLn(e.getMessage()); } } } /** * ,      . *   Runnable,        *   ,   .<hr> * *   smack.jar  smackx.jar:<br> * org.jivesoftware.smack<hr> * * @author esin * */ public class JabberBot implements Runnable { private String nick; private String password; private String domain; private String server; private int port; private ConnectionConfiguration connConfig; private XMPPConnection connection; /** *     ,     - * @param nick -  * @param password -  * @param domain -  * @param server -  * @param port -  */ public JabberBot (String nick, String password, String domain, String server, int port) { this.nick = nick; this.password = password; this.domain = domain; this.server = server; this.port = port; } @Override public void run() { connConfig = new ConnectionConfiguration(server, port, domain); connection = new XMPPConnection(connConfig); try { int priority = 10; SASLAuthentication.supportSASLMechanism("PLAIN", 0); connection.connect(); connection.login(nick, password); Presence presence = new Presence(Presence.Type.available); presence.setStatus(" "); connection.sendPacket(presence); presence.setPriority(priority); PacketFilter filter = new AndFilter(new PacketTypeFilter(Message.class)); PacketListener myListener = new PacketListener() { public void processPacket(Packet packet) { if (packet instanceof Message) { Message message = (Message) packet; //    processMessage(message); } } }; connection.addPacketListener(myListener, filter); //      ,     while(connection.isConnected()) { Thread.sleep(60000); } } catch (Exception e) { System.out.printLn(e.getMessage()); } } /** *   <hr> * @param message   */ private void processMessage(Message message) { String messageBody = message.getBody(); String JID = message.getFrom(); //  .     :) //     - sendMessage(JID, messageBody); } /** *   <hr> * @param to JID ,    <br> * @param message  */ private void sendMessage(String to, String message) { if(!message.equals("")) { ChatManager chatmanager = connection.getChatManager(); Chat newChat = chatmanager.createChat(to, null); try { newChat.sendMessage(message); } catch (XMPPException e) { System.out.printLn(e.getMessage()); } } } } 


That's all. For what I allocated a bot in a separate thread? I understand that to produce threads is not good. But this thread after the initialization of the bot will sleep almost all the time. He will wake only once a minute to check the connection. And even that is unnecessary, but it was impossible to remove, because otherwise, the bot will start and immediately turn off. All processing of incoming messages and sending outgoing is carried out in the streams created by the Smack library.

GoogleTalk bot

The code of this bot is almost no different. There are only a couple of differences:

 public class Main { public static void main(String[] args) { try { String botNick = "nickname"; String botPassword = "password"; String botDomain = "gmail.com"; //        String botServer = "talk.google.com"; int botPort = 5222; GoogleTalkBot bot = new GoogleTalkBot(botNick, botPassword, botDomain, botServer, botPort); Thread botThread = new Thread(bot); botThread.start(); } catch(Exception e) { System.out.printLn(e.getMessage()); } } } /** * ,       . *   Runnable,        *   ,   .<hr> * *   smack.jar  smackx.jar:<br> * org.jivesoftware.smack<hr> * * @author esin * */ public class GoogleTalkBot implements Runnable { private String nick; private String password; private String domain; private String server; private int port; private ConnectionConfiguration connConfig; private XMPPConnection connection; /** *     ,      * @param nick -  * @param password -  * @param domain -  * @param server -  * @param port -  */ public GoogleTalkBot (String nick, String password, String domain, String server, int port) { this.nick = nick; this.password = password; this.domain = domain; this.server = server; this.port = port; } @Override public void run() { connConfig = new ConnectionConfiguration(server, port, domain); connection = new XMPPConnection(connConfig); try { int priority = 10; SASLAuthentication.supportSASLMechanism("PLAIN", 0); connection.connect(); connection.login(nick + "@" + domain, password); //         nickname@gmail.com Presence presence = new Presence(Presence.Type.available); presence.setStatus(" "); connection.sendPacket(presence); presence.setPriority(priority); PacketFilter filter = new AndFilter(new PacketTypeFilter(Message.class)); PacketListener myListener = new PacketListener() { public void processPacket(Packet packet) { if (packet instanceof Message) { Message message = (Message) packet; if(message.getType() == Type.chat) //    ,       { // Process message processMessage(message); } } } }; // Register the listener. connection.addPacketListener(myListener, filter); while(connection.isConnected()) { Thread.sleep(60000); } } catch (Exception e) { System.out.printLn(e.getMessage()); } } /** *   <hr> * @param message -   */ private void processMessage(Message message) { String messageBody = message.getBody(); String JID = message.getFrom(); sendMessage(JID, messageBody); } /** *   <hr> * @param to - JID ,    <br> * @param message -  */ private void sendMessage(String to, String message) { if(!message.equals("")) { ChatManager chatmanager = connection.getChatManager(); Chat newChat = chatmanager.createChat(to, null); try { newChat.sendMessage(message); } catch (XMPPException e) { System.out.printLn(e.getMessage()); } } } } 


In general, everything is almost the same.
Now about the nuance that is associated with the bot for Google current (in the gill this nuance is not). When I tested bots, the text of the echo reply from them was sent as
<who sent>: <what sent>
those. The text clearly indicated the identifier (JID) of the person who sent it. Gill worked perfectly, without any failures. Google talk after exactly 10 messages stopped sending the answer. The fact that this is due to the login in Google, I found out after a lot of torment. Moreover, it does not have to be specified as nickname@gmail.com, just the nickname will suffice. If the login does not write at all or write any other, everything works fine

Source: https://habr.com/ru/post/127535/


All Articles