package com.esri.geoevent.solutions.transport.irc; import java.nio.BufferOverflowException; import java.nio.ByteBuffer; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import com.esri.geoevent.solutions.transport.irc.jerklib.ConnectionManager; import com.esri.geoevent.solutions.transport.irc.jerklib.Profile; import com.esri.geoevent.solutions.transport.irc.jerklib.Session; import com.esri.geoevent.solutions.transport.irc.jerklib.events.IRCEvent; import com.esri.geoevent.solutions.transport.irc.jerklib.events.JoinCompleteEvent; import com.esri.geoevent.solutions.transport.irc.jerklib.events.MessageEvent; import com.esri.geoevent.solutions.transport.irc.jerklib.events.IRCEvent.Type; import com.esri.geoevent.solutions.transport.irc.jerklib.listeners.IRCEventListener; import com.esri.ges.core.component.ComponentException; import com.esri.ges.core.component.RunningException; import com.esri.ges.core.component.RunningState; import com.esri.ges.transport.InboundTransportBase; import com.esri.ges.transport.TransportDefinition; public class IrcInboundTransport extends InboundTransportBase implements IRCEventListener { private static final Log log = LogFactory.getLog(IrcInboundTransport.class); private String[] channelList ={"#pircbot"}; private String nickName = "EsriGEP"; private String serverName = "irc.freenode.net"; private ConnectionManager manager; private ByteBuffer byteBuffer = ByteBuffer.allocate(512+256); // max message is 512 unknown max nick size but we will clip to 256 @Override public boolean isClusterable() { return false; } public IrcInboundTransport(TransportDefinition definition) throws ComponentException { super(definition); } public void applyProperties() { if (getProperty("channelList").isValid()) { String value = (String) getProperty("channelList").getValue(); if( value.length() > 0 ) { channelList = value.split(","); } } if (getProperty("nickName").isValid()) { String value = (String) getProperty("nickName").getValue(); if( value.length() > 0 ) { nickName = value; } } if (getProperty("serverName").isValid()) { String value = (String) getProperty("serverName").getValue(); if( value.length() > 0 ) { serverName = value; } } } @Override public void afterPropertiesSet() { super.afterPropertiesSet(); applyProperties(); } public void receiveEvent(IRCEvent e) { if (e.getType() == Type.CONNECT_COMPLETE) { for (int i=0;i< channelList.length; i++) { e.getSession().join(channelList[i]); } } else if (e.getType() == Type.CHANNEL_MESSAGE) { // got a standard message send it and the nickname that posted it try { MessageEvent me = (MessageEvent) e; String channel = me.getChannel().getName().substring(0, Math.min(me.getChannel().getName().length(), 50)); String text = me.getMessage(); String nick = me.getNick().substring(0, Math.min(me.getNick().length(), 50)); // kind of a hack but I want to make sure the message does not contain Pipe characters which would mess up downstream parsers text = text.replaceAll("\\|", "!"); String message = channel + "|" + nick + "|" + text+"\n"; byteBuffer.put(message.getBytes()); byteBuffer.flip(); byteListener.receive(byteBuffer, channel); byteBuffer.compact(); log.debug(me.getChannel().getName() + ":" + message); } catch (BufferOverflowException boe) { log.error("Buffer overflow. Flushing the buffer and continuing.", boe); byteBuffer.clear(); } catch (Exception ex) { log.error("Unexpected error, stopping the Transport.", ex); stop(); } } else if (e.getType() == Type.JOIN_COMPLETE) { JoinCompleteEvent jce = (JoinCompleteEvent) e; /* say hello */ jce.getChannel().say("Hello. "+ nickName + " bot is now listining on this channel."); setRunningState(RunningState.STARTED); } else if (e.getType() == Type.KICK_EVENT) { log.error("KICKed out of Chatroom. Stopping Transport"); setErrorMessage("KICKed out of Chatroom. Stopping Transport"); stop(); } else if (e.getType() == Type.CONNECTION_LOST) { log.error("Lost Connection. Stopping"); setErrorMessage("Lost Connection. Stopping"); stop(); } else if (e.getType() == Type.ERROR) { log.error("Error returned (possibly Host not found). Stopping"); stop(); } // else // { // log.debug("Lost Connection. Stopping"); // } } @Override public synchronized void stop() { super.stop(); setRunningState(RunningState.STOPPED); if (manager != null) { manager.quit(); } } @SuppressWarnings("incomplete-switch") public void start() throws RunningException { switch (getRunningState()) { case STARTING: case STARTED: case STOPPING: return; } setRunningState(RunningState.STARTING); applyProperties(); /* * ConnectionManager takes a Profile to use for new connections. */ manager = new ConnectionManager(new Profile(nickName)); /* * One instance of ConnectionManager can connect to many IRC networks. * ConnectionManager#requestConnection(String) will return a Session object. * The Session is the main way users will interact with this library and IRC * networks */ Session session = manager.requestConnection(serverName); /* * JerkLib fires IRCEvents to notify users of the lib of incoming events * from a connected IRC server. */ session.addIRCEventListener(this); } }