package com.juick.components; import com.juick.User; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import rocks.xmpp.addr.Jid; import rocks.xmpp.core.XmppException; import rocks.xmpp.core.stanza.model.IQ; import rocks.xmpp.core.stanza.model.Message; import rocks.xmpp.core.stanza.model.Stanza; import rocks.xmpp.core.stanza.model.client.ClientMessage; import rocks.xmpp.extensions.component.accept.ExternalComponent; import rocks.xmpp.extensions.nick.model.Nickname; import rocks.xmpp.extensions.oob.model.x.OobX; import rocks.xmpp.extensions.ping.PingManager; import rocks.xmpp.extensions.receipts.MessageDeliveryReceiptsManager; import rocks.xmpp.util.XmppUtils; import javax.xml.bind.JAXBException; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamWriter; import java.io.StringWriter; import java.net.URI; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.List; /** * @author ugnich */ public class XMPPConnection implements AutoCloseable { private static final Logger logger = LoggerFactory.getLogger(XMPPConnection.class); private ExternalComponent router; private XMPPServer xmpp; public XMPPConnection(XMPPServer s2s, String componentName, int componentPort, String password) { this.xmpp = s2s; logger.info("stream router start"); router = ExternalComponent.create(componentName, password, xmpp.getSession().getConfiguration(), "localhost", componentPort); PingManager pingManager = router.getManager(PingManager.class); pingManager.setEnabled(true); MessageDeliveryReceiptsManager messageDeliveryReceiptsManager = router.getManager(MessageDeliveryReceiptsManager.class); messageDeliveryReceiptsManager.setEnabled(true); router.addInboundMessageListener(e -> { Message message = e.getMessage(); Jid jid = message.getTo(); if (jid.getDomain().equals(Jid.of(componentName).getDomain())) { com.juick.Message jmsg = message.getExtension(com.juick.Message.class); if (jmsg != null) { if (jid.getLocal().equals("recomm")) { sendJuickRecommendation(jmsg); } else { if (jmsg.getRid() > 0) { sendJuickComment(jmsg); } else if (jmsg.getMid() > 0) { sendJuickMessage(jmsg); } } } } else if (jid.getDomain().endsWith(xmpp.HOSTNAME) && (jid.getDomain().equals(xmpp.HOSTNAME) || jid.getDomain().endsWith("." + xmpp.HOSTNAME))) { if (logger.isInfoEnabled()) { try { logger.info("unhandled message: {}", stanzaToString(message)); } catch (JAXBException | XMLStreamException ex) { logger.error("JAXB exception", ex); } } } else { route(jid.getDomain(), ClientMessage.from(message)); } }); router.addInboundIQListener(e -> { IQ iq = e.getIQ(); Jid jid = iq.getTo(); if (!jid.getDomain().equals(xmpp.HOSTNAME)) { route(jid.getDomain(), iq); } }); try { router.connect(); } catch (XmppException e) { logger.warn("xmpp exception", e); } } String stanzaToString(Stanza stanza) throws XMLStreamException, JAXBException { StringWriter stanzaWriter = new StringWriter(); XMLStreamWriter xmppStreamWriter = XmppUtils.createXmppStreamWriter( router.getConfiguration().getXmlOutputFactory().createXMLStreamWriter(stanzaWriter)); router.createMarshaller().marshal(stanza, xmppStreamWriter); xmppStreamWriter.flush(); xmppStreamWriter.close(); return stanzaWriter.toString(); } void route(String domain, Stanza stanza) { try { String xml = stanzaToString(stanza); logger.info("stream router (out): {}", xml); xmpp.sendOut(domain, xml); } catch (XMLStreamException | JAXBException e) { logger.error("JAXB exception", e); } } public void sendStanza(Stanza xml) { router.send(xml); } public void sendJuickMessage(com.juick.Message jmsg) { List jids = new ArrayList<>(); if (jmsg.FriendsOnly) { jids = xmpp.subscriptionService.getJIDSubscribedToUser(jmsg.getUser().getUid(), jmsg.FriendsOnly); } else { List users = xmpp.subscriptionService.getSubscribedUsers(jmsg.getUser().getUid(), jmsg.getMid()); for (User user : users) { for (String jid : xmpp.userService.getJIDsbyUID(user.getUid())) { jids.add(jid); } } } String txt = "@" + jmsg.getUser().getName() + ":" + jmsg.getTagsString() + "\n"; String attachment = jmsg.getAttachmentURL(); if (attachment != null) { txt += attachment + "\n"; } txt += jmsg.getText() + "\n\n"; txt += "#" + jmsg.getMid() + " http://juick.com/" + jmsg.getMid(); Nickname nick = new Nickname("@" + jmsg.getUser().getName()); Message msg = new Message(); msg.setFrom(xmpp.getJid()); msg.setBody(txt); msg.setType(Message.Type.CHAT); msg.setThread("juick-" + jmsg.getMid()); msg.addExtension(jmsg); msg.addExtension(nick); if (attachment != null) { try { OobX oob = new OobX(new URI(attachment)); msg.addExtension(oob); } catch (URISyntaxException e) { logger.warn("uri exception", e); } } for (String jid : jids) { msg.setTo(Jid.of(jid)); route(msg.getTo().getDomain(), ClientMessage.from(msg)); } } public void sendJuickComment(com.juick.Message jmsg) { List users; String replyQuote; String replyTo; users = xmpp.subscriptionService.getUsersSubscribedToComments(jmsg.getMid(), jmsg.getUser().getUid()); com.juick.Message replyMessage = jmsg.getReplyto() > 0 ? xmpp.messagesService.getReply(jmsg.getMid(), jmsg.getReplyto()) : xmpp.messagesService.getMessage(jmsg.getMid()); replyTo = replyMessage.getUser().getName(); com.juick.Message fullReply = xmpp.messagesService.getReply(jmsg.getMid(), jmsg.getRid()); replyQuote = fullReply.getReplyQuote(); String txt = "Reply by @" + jmsg.getUser().getName() + ":\n" + replyQuote + "\n@" + replyTo + " "; String attachment = jmsg.getAttachmentURL(); if (attachment != null) { txt += attachment + "\n"; } txt += jmsg.getText() + "\n\n" + "#" + jmsg.getMid() + "/" + jmsg.getRid() + " http://juick.com/" + jmsg.getMid() + "#" + jmsg.getRid(); Message msg = new Message(); msg.setFrom(xmpp.getJid()); msg.setBody(txt); msg.setType(Message.Type.CHAT); msg.addExtension(jmsg); for (User user : users) { for (String jid : xmpp.userService.getJIDsbyUID(user.getUid())) { msg.setTo(Jid.of(jid)); route(msg.getTo().getDomain(), ClientMessage.from(msg)); } } } public void sendJuickRecommendation(com.juick.Message recomm) { List users; com.juick.Message jmsg = xmpp.messagesService.getMessage(recomm.getMid()); users = xmpp.subscriptionService.getUsersSubscribedToUserRecommendations(recomm.getUser().getUid(), recomm.getMid(), jmsg.getUser().getUid()); String txt = "Recommended by @" + recomm.getUser().getName() + ":\n"; txt += "@" + jmsg.getUser().getName() + ":" + jmsg.getTagsString() + "\n"; String attachment = jmsg.getAttachmentURL(); if (attachment != null) { txt += attachment + "\n"; } txt += jmsg.getText() + "\n\n"; txt += "#" + jmsg.getMid(); if (jmsg.getReplies() > 0) { if (jmsg.getReplies() % 10 == 1 && jmsg.getReplies() % 100 != 11) { txt += " (" + jmsg.getReplies() + " reply)"; } else { txt += " (" + jmsg.getReplies() + " replies)"; } } txt += " http://juick.com/" + jmsg.getMid(); Nickname nick = new Nickname("@" + jmsg.getUser().getName()); Message msg = new Message(); msg.setFrom(xmpp.getJid()); msg.setBody(txt); msg.setType(Message.Type.CHAT); msg.setThread("juick-" + jmsg.getMid()); msg.addExtension(jmsg); msg.addExtension(nick); if (attachment != null) { try { OobX oob = new OobX(new URI(attachment)); msg.addExtension(oob); } catch (URISyntaxException e) { logger.warn("uri exception", e); } } for (User user : users) { for (String jid : xmpp.userService.getJIDsbyUID(user.getUid())) { msg.setTo(Jid.of(jid)); route(msg.getTo().getDomain(), ClientMessage.from(msg)); } } } @Override public void close() throws Exception { if (router != null) { router.close(); } } }