package com.juick.components.s2s; import com.juick.User; import com.juick.components.XMPPServer; import com.juick.server.PMQueries; import com.juick.server.TagQueries; import com.juick.server.UserQueries; import com.juick.xmpp.JID; import com.juick.xmpp.Message; import com.juick.xmpp.Presence; import com.juick.xmpp.extensions.Error; import com.juick.xmpp.extensions.JuickMessage; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * * @author ugnich */ public class JuickBot { XMPPServer xmpp; public JuickBot(XMPPServer xmpp, JID jid) { this.xmpp = xmpp; this.jid = jid; } private final JID jid; private static final String HELPTEXT = "@username text - Send private message\n" + "*tagname Blah-blah-blah - Post a message with tag 'tagname'\n" + "#1234 Blah-blah-blah - Answer to message #1234\n" + "#1234/5 Blah - Answer to reply #1234/5\n" + "! #1234 - Recommend post\n" + "\n" + "# - Show last messages from your feed (## - second page, ...)\n" + "@ - Show recomendations and popular personal blogs\n" + "* - Show your tags\n" + "#1234 - Show message\n" + "#1234+ - Show message with replies\n" + "@username - Show user's info\n" + "@username+ - Show user's info and last 10 messages\n" + "@username *tag - User's messages with this tag\n" + "*tag - Show last 10 messages with this tag\n" + "? blah - Search posts for 'blah'\n" + "? @username blah - Searching among user\'s posts for 'blah'\n" + "D #123 - Delete message\n" + "D #123/45 - Delete reply\n" + "DL - Delete last message/reply\n" + "S - Show your subscriptions\n" + "S #123 - Subscribe to message replies\n" + "S @username - Subscribe to user's blog\n" + "U #123 - Unsubscribe from comments\n" + "U @username - Unsubscribe from user's blog\n" + "BL - Show your blacklist\n" + "BL @username - Add/delete user to/from your blacklist\n" + "BL *tag - Add/delete tag to/from your blacklist\n" + "ON / OFF - Enable/disable subscriptions delivery\n" + "PING - Pong\n" + "\n" + "Read more: http://juick.com/help/"; public boolean incomingPresence(Presence p) throws Exception { final String username = p.to.Username.toLowerCase(); final boolean toJuick = username.equals("juick"); if (p.type == null) { Presence reply = new Presence(); reply.from = new JID(p.to.Username, p.to.Host, null); reply.to = new JID(p.from.Username, p.from.Host, null); reply.type = Presence.Type.unsubscribe; xmpp.sendOut(reply); return true; } else if (p.type.equals(Presence.Type.probe)) { int uid_to = 0; if (!toJuick) { uid_to = UserQueries.getUIDbyName(xmpp.jdbc, username); } if (toJuick || uid_to > 0) { Presence reply = new Presence(); reply.from = p.to; reply.from.Resource = "Juick"; reply.to = p.from; reply.priority = 10; xmpp.sendOut(reply); } else { Presence reply = new Presence(p.to, p.from, Presence.Type.error); reply.id = p.id; reply.addChild(new Error(Error.Type.cancel, "item-not-found")); xmpp.sendOut(reply); return true; } return true; } else if (p.type.equals(Presence.Type.subscribe)) { boolean canSubscribe = false; if (toJuick) { canSubscribe = true; } else { int uid_to = UserQueries.getUIDbyName(xmpp.jdbc, username); if (uid_to > 0) { PMQueries.addPMinRoster(xmpp.jdbc, uid_to, p.from.Bare()); canSubscribe = true; } } if (canSubscribe) { Presence reply = new Presence(p.to, p.from, Presence.Type.subscribed); xmpp.sendOut(reply); reply.from.Resource = "Juick"; reply.priority = 10; reply.type = null; xmpp.sendOut(reply); return true; } else { Presence reply = new Presence(p.to, p.from, Presence.Type.error); reply.id = p.id; reply.addChild(new Error(Error.Type.cancel, "item-not-found")); xmpp.sendOut(reply); return true; } } else if (p.type.equals(Presence.Type.unsubscribe)) { if (!toJuick) { int uid_to = UserQueries.getUIDbyName(xmpp.jdbc, username); if (uid_to > 0) { PMQueries.removePMinRoster(xmpp.jdbc, uid_to, p.from.Bare()); } } Presence reply = new Presence(p.to, p.from, Presence.Type.unsubscribed); xmpp.sendOut(reply); } return false; } public boolean incomingMessage(Message msg) throws Exception { if (msg.body == null || msg.body.isEmpty()) { return true; } String username = msg.to.Username.toLowerCase(); User user_from = null; String signuphash = ""; user_from = UserQueries.getUserByJID(xmpp.jdbc, msg.from.Bare()); if (user_from == null) { signuphash = UserQueries.getSignUpHashByJID(xmpp.jdbc, msg.from.Bare()); } if (user_from == null) { Message reply = new Message(msg.to, msg.from, Message.Type.chat); if (username.equals("juick")) { reply.body = "Для того, чтобы начать пользоваться сервисом, пожалуйста пройдите быструю регистрацию: http://juick.com/signup?type=xmpp&hash=" + signuphash + "\nЕсли у вас уже есть учетная запись на Juick, вы сможете присоединить этот JabberID к ней.\n\nTo start using Juick, please sign up: http://juick.com/signup?type=xmpp&hash=" + signuphash + "\nIf you already have an account on Juick, you will be proposed to attach this JabberID to your existing account."; } else { reply.body = "Внимание, системное сообщение!\nВаш JabberID не обнаружен в списке доверенных. Для того, чтобы отправить сообщение пользователю " + username + "@juick.com, пожалуйста зарегистрируйте свой JabberID в системе: http://juick.com/signup?type=xmpp&hash=" + signuphash + "\nЕсли у вас уже есть учетная запись на Juick, вы сможете присоединить этот JabberID к ней.\n\nWarning, system message!\nYour JabberID is not found in our server's white list. To send a message to " + username + "@juick.com, please sign up: http://juick.com/signup?type=xmpp&hash=" + signuphash + "\nIf you already have an account on Juick, you will be proposed to attach this JabberID to your existing account."; } xmpp.sendOut(reply); return true; } if (username.equals("juick")) { return incomingMessageJuick(user_from, msg); } int uid_to = UserQueries.getUIDbyName(xmpp.jdbc, username); if (uid_to == 0) { Message reply = new Message(msg.to, msg.from, Message.Type.error); reply.id = msg.id; reply.addChild(new Error(Error.Type.cancel, "item-not-found")); xmpp.sendOut(reply); return true; } boolean success = false; if (!UserQueries.isInBLAny(xmpp.jdbc, uid_to, user_from.getUid())) { success = PMQueries.createPM(xmpp.jdbc, user_from.getUid(), uid_to, msg.body); } if (success) { Message m = new Message(); m.from = new JID("juick", "juick.com", null); m.to = new JID(Integer.toString(uid_to), "push.juick.com", null); JuickMessage jmsg = new JuickMessage(); jmsg.setUser(user_from); jmsg.setText(msg.body); m.childs.add(jmsg); xmpp.getRouter().sendStanza(m.toString()); m.to.Host = "ws.juick.com"; xmpp.getRouter().sendStanza(m.toString()); List jids; boolean inroster = false; jids = UserQueries.getJIDsbyUID(xmpp.jdbc, uid_to); for (String jid : jids) { Message mm = new Message(); mm.to = new JID(jid); mm.type = Message.Type.chat; inroster = PMQueries.havePMinRoster(xmpp.jdbc, user_from.getUid(), jid); if (inroster) { mm.from = new JID(jmsg.getUser().getName(), "juick.com", "Juick"); mm.body = msg.body; } else { mm.from = new JID("juick", "juick.com", "Juick"); mm.body = "Private message from @" + jmsg.getUser().getName() + ":\n" + msg.body; } xmpp.sendOut(mm); } } else { Message reply = new Message(msg.to, msg.from, Message.Type.error); reply.id = msg.id; reply.addChild(new Error(Error.Type.cancel, "not-allowed")); xmpp.sendOut(reply); } return false; } private static Pattern regexPM = Pattern.compile("^\\@(\\S+)\\s+([\\s\\S]+)$"); public boolean incomingMessageJuick(User user_from, Message msg) throws Exception { String command = msg.body.trim(); int commandlen = command.length(); // COMPATIBILITY if (commandlen > 7 && command.substring(0, 3).equalsIgnoreCase("PM ")) { command = command.substring(3).trim(); commandlen = command.length(); } if (commandlen == 4) { if (command.equalsIgnoreCase("PING")) { commandPing(msg); return true; } else if (command.equalsIgnoreCase("HELP")) { commandHelp(msg); return true; } } else if (commandlen == 5 && command.equalsIgnoreCase("LOGIN")) { commandLogin(msg, user_from); return true; } else if (command.charAt(0) == '@') { Matcher matchPM = regexPM.matcher(command); if (matchPM.find()) { String user_to = matchPM.group(1); String msgtxt = matchPM.group(2); commandPM(msg, user_from, user_to, msgtxt); return true; } } else if (commandlen == 2 && command.equalsIgnoreCase("BL")) { commandBLShow(msg, user_from); return true; } return false; } private void commandPing(Message m) throws Exception { Presence p = new Presence(jid, m.from); p.priority = 10; xmpp.sendOut(p); Message reply = new Message(jid, m.from, Message.Type.chat); reply.body = "PONG"; xmpp.sendOut(reply); } private void commandHelp(Message m) throws Exception { Message reply = new Message(jid, m.from, Message.Type.chat); reply.body = HELPTEXT; xmpp.sendOut(reply); } private void commandLogin(Message m, User user_from) throws Exception { Message reply = new Message(jid, m.from, Message.Type.chat); reply.body = "http://juick.com/login?" + UserQueries.getHashByUID(xmpp.jdbc, user_from.getUid()); xmpp.sendOut(reply); } private void commandPM(Message m, User user_from, String user_to, String body) throws Exception { int ret = 0; int uid_to = 0; List jids_to = null; boolean haveInRoster = false; if (user_to.indexOf('@') > 0) { uid_to = UserQueries.getUIDbyJID(xmpp.jdbc, user_to); } else { uid_to = UserQueries.getUIDbyName(xmpp.jdbc, user_to); } if (uid_to > 0) { if (!UserQueries.isInBLAny(xmpp.jdbc, uid_to, user_from.getUid())) { if (PMQueries.createPM(xmpp.jdbc, user_from.getUid(), uid_to, body)) { jids_to = UserQueries.getJIDsbyUID(xmpp.jdbc, uid_to); ret = 200; } else { ret = 500; } } else { ret = 403; } } else { ret = 404; } if (ret == 200) { Message msg = new Message(); msg.from = new JID("juick", "juick.com", null); msg.to = new JID(Integer.toString(uid_to), "push.juick.com", null); JuickMessage jmsg = new JuickMessage(); jmsg.setUser(user_from); jmsg.setText(body); msg.childs.add(jmsg); xmpp.getRouter().sendStanza(msg.toString()); msg.to.Host = "ws.juick.com"; xmpp.getRouter().sendStanza(msg.toString()); for (String jid : jids_to) { Message mm = new Message(); mm.to = new JID(jid); mm.type = Message.Type.chat; haveInRoster = PMQueries.havePMinRoster(xmpp.jdbc, user_from.getUid(), jid); if (haveInRoster) { mm.from = new JID(user_from.getName(), "juick.com", "Juick"); mm.body = body; } else { mm.from = new JID("juick", "juick.com", "Juick"); mm.body = "Private message from @" + user_from.getName() + ":\n" + body; } xmpp.sendOut(mm); } } Message reply = new Message(m.to, m.from); if (ret == 200) { reply.type = m.type; reply.body = "Private message sent"; } else { reply.type = Message.Type.error; reply.body = "Error " + ret; } xmpp.sendOut(reply); } private void commandBLShow(Message m, User user_from) throws Exception { List blusers = UserQueries.getUserBLUsers(xmpp.jdbc, user_from.getUid()); List bltags = TagQueries.getUserBLTags(xmpp.jdbc, user_from.getUid()); String txt = ""; if (bltags.size() > 0) { for (String bltag : bltags) { txt += "*" + bltag + "\n"; } if (blusers.size() > 0) { txt += "\n"; } } if (blusers.size() > 0) { for (User bluser : blusers) { txt += "@" + bluser.getName() + "\n"; } } if (txt.isEmpty()) { txt = "You don't have any users or tags in your blacklist."; } Message reply = new Message(jid, m.from, Message.Type.chat); reply.body = txt; xmpp.sendOut(reply); } public JID getJid() { return jid; } }