/* * Copyright 2006-2010 Daniel Henninger. All rights reserved. * * This software is published under the terms of the GNU Public License (GPL), * a copy of which is included in this distribution. */ package net.sf.kraken.protocols.irc; import java.lang.ref.WeakReference; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.Enumeration; import java.util.List; import net.sf.kraken.muc.BaseMUCTransport; import net.sf.kraken.muc.MUCTransportRoom; import net.sf.kraken.muc.MUCTransportRoomMember; import net.sf.kraken.muc.MUCTransportSession; import net.sf.kraken.roster.TransportBuddy; import net.sf.kraken.type.PresenceType; import org.apache.log4j.Logger; import org.dom4j.Element; import org.jivesoftware.util.LocaleUtils; import org.jivesoftware.util.NotFoundException; import org.xmpp.packet.Message; import org.xmpp.packet.Presence; import f00f.net.irc.martyr.GenericAutoService; import f00f.net.irc.martyr.InCommand; import f00f.net.irc.martyr.State; import f00f.net.irc.martyr.clientstate.Channel; import f00f.net.irc.martyr.clientstate.Member; import f00f.net.irc.martyr.commands.ChannelModeCommand; import f00f.net.irc.martyr.commands.CtcpMessage; import f00f.net.irc.martyr.commands.CtcpNotice; import f00f.net.irc.martyr.commands.InviteCommand; import f00f.net.irc.martyr.commands.IsonCommand; import f00f.net.irc.martyr.commands.JoinCommand; import f00f.net.irc.martyr.commands.KickCommand; import f00f.net.irc.martyr.commands.MessageCommand; import f00f.net.irc.martyr.commands.ModeCommand; import f00f.net.irc.martyr.commands.NickCommand; import f00f.net.irc.martyr.commands.NoticeCommand; import f00f.net.irc.martyr.commands.PartCommand; import f00f.net.irc.martyr.commands.QuitCommand; import f00f.net.irc.martyr.commands.TopicCommand; import f00f.net.irc.martyr.replies.AwayReply; import f00f.net.irc.martyr.replies.ListEndReply; import f00f.net.irc.martyr.replies.ListReply; import f00f.net.irc.martyr.replies.ListStartReply; import f00f.net.irc.martyr.replies.NamesEndReply; import f00f.net.irc.martyr.replies.NamesReply; import f00f.net.irc.martyr.replies.NowAwayReply; import f00f.net.irc.martyr.replies.TopicInfoReply; import f00f.net.irc.martyr.replies.UnAwayReply; import f00f.net.irc.martyr.util.IRCStringUtils; /** * @author Daniel Henninger */ public class IRCListener extends GenericAutoService { static Logger Log = Logger.getLogger(IRCListener.class); public IRCListener(IRCSession session) { super(session.getConnection()); ircSessionRef = new WeakReference<IRCSession>(session); } WeakReference<IRCSession> ircSessionRef; public IRCSession getSession() { return ircSessionRef.get(); } @Override protected void updateState(State state) { Log.debug("IRC: Received incoming state:"+state); } @Override @SuppressWarnings("unchecked") protected void updateCommand(InCommand inCommand) { Log.debug("IRC: Received incoming command:"+inCommand); if (inCommand instanceof CtcpMessage) { CtcpMessage cm = (CtcpMessage)inCommand; if (cm.getAction().equals("VERSION")) { getSession().getConnection().sendCommand(new CtcpNotice(cm.getSource().getNick(), "VERSION", "IMGateway"+getSession().getTransport().getVersionString()+":Java:-")); } else if (cm.getAction().equals("PING")) { String timestamp = cm.getMessage(); getSession().getConnection().sendCommand(new CtcpNotice(cm.getSource().getNick(), "PING", timestamp)); } else if (cm.getAction().equals("TIME")) { Date current = new Date(); SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss ZZZZZ"); getSession().getConnection().sendCommand(new CtcpNotice(cm.getSource().getNick(), "TIME", format.format(current))); } else if (cm.getAction().equals("ACTION")) { if (cm.isPrivateToUs(getSession().getConnection().getClientState())) { getSession().getTransport().sendMessage( getSession().getJID(), getSession().getTransport().convertIDToJID(cm.getSource().getNick()), "/me "+cm.getMessage() ); } else { getSession().getTransport().sendMessage( getSession().getJID(), getSession().getTransport().getMUCTransport().convertIDToJID(cm.getDest(), cm.getSource().getNick()), "/me "+cm.getMessage(), Message.Type.groupchat ); } } } else if (inCommand instanceof MessageCommand) { MessageCommand mc = (MessageCommand)inCommand; if (mc.isPrivateToUs(getSession().getConnection().getClientState())) { getSession().getTransport().sendMessage( getSession().getJID(), getSession().getTransport().convertIDToJID(mc.getSource().getNick()), IRCStringUtils.stripControlChars(mc.getMessage()) ); } else { getSession().getTransport().sendMessage( getSession().getJID(), getSession().getTransport().getMUCTransport().convertIDToJID(mc.getDest(), mc.getSource().getNick()), IRCStringUtils.stripControlChars(mc.getMessage()), Message.Type.groupchat ); } } else if (inCommand instanceof NoticeCommand) { NoticeCommand nc = (NoticeCommand)inCommand; if (nc.getFrom() != null) { getSession().getTransport().sendMessage( getSession().getJID(), getSession().getTransport().convertIDToJID(nc.getFrom().getNick()), IRCStringUtils.stripControlChars(nc.getNotice()) ); } } else if (inCommand instanceof JoinCommand) { JoinCommand jc = (JoinCommand)inCommand; try { IRCMUCSession mucSession = (IRCMUCSession)getSession().getMUCSessionManager().getSession(jc.getChannel()); mucSession.getContacts().add(jc.getUser().getNick()); Presence p = new Presence(); p.setFrom(getSession().getTransport().getMUCTransport().convertIDToJID(jc.getChannel(), jc.getUser().getNick())); p.setTo(getSession().getJID()); Element elem = p.addChildElement("x", "http://jabber.org/protocol/muc#user"); Element item = elem.addElement("item"); item.addAttribute("affiliation", "member"); item.addAttribute("role", "participant"); getSession().getTransport().sendPacket(p); } catch (NotFoundException e) { Log.debug("Received information for IRC session that doesn't exist."); } } else if (inCommand instanceof PartCommand) { PartCommand pc = (PartCommand)inCommand; try { IRCMUCSession mucSession = (IRCMUCSession)getSession().getMUCSessionManager().getSession(pc.getChannel()); mucSession.getContacts().remove(pc.getUser().getNick()); Presence p = new Presence(); p.setType(Presence.Type.unavailable); p.setFrom(getSession().getTransport().getMUCTransport().convertIDToJID(pc.getChannel(), pc.getUser().getNick())); p.setTo(getSession().getJID()); if (pc.getReason() != null && !pc.getReason().equals("")) { p.setStatus(pc.getReason()); } Element elem = p.addChildElement("x", "http://jabber.org/protocol/muc#user"); Element item = elem.addElement("item"); item.addAttribute("affiliation", "none"); item.addAttribute("role", "none"); getSession().getTransport().sendPacket(p); } catch (NotFoundException e) { Log.debug("Received information for IRC session that doesn't exist."); } } else if (inCommand instanceof QuitCommand) { QuitCommand qc = (QuitCommand)inCommand; for (MUCTransportSession session : getSession().getMUCSessionManager().getSessions()) { if (((IRCMUCSession)session).getContacts().contains(qc.getUser().getNick())) { ((IRCMUCSession)session).getContacts().remove(qc.getUser().getNick()); Presence p = new Presence(); p.setType(Presence.Type.unavailable); p.setFrom(getSession().getTransport().getMUCTransport().convertIDToJID(((IRCMUCSession)session).roomname, qc.getUser().getNick())); p.setTo(getSession().getJID()); if (qc.getReason() != null && !qc.getReason().equals("")) { p.setStatus(qc.getReason()); } Element elem = p.addChildElement("x", "http://jabber.org/protocol/muc#user"); Element item = elem.addElement("item"); item.addAttribute("affiliation", "none"); item.addAttribute("role", "none"); getSession().getTransport().sendPacket(p); } } } else if (inCommand instanceof InviteCommand) { InviteCommand ic = (InviteCommand)inCommand; BaseMUCTransport mucTransport = getSession().getTransport().getMUCTransport(); Message m = new Message(); m.setTo(getSession().getJID()); m.setFrom(mucTransport.convertIDToJID(ic.getChannel(), null)); Element x = m.addChildElement("x", "http://jabber.org/protocol/muc#user"); Element invite = x.addElement("invite"); invite.addAttribute("from", getSession().getTransport().convertIDToJID(ic.getSourceString()).toBareJID()); getSession().getTransport().sendPacket(m); } else if (inCommand instanceof KickCommand) { KickCommand kc = (KickCommand)inCommand; BaseMUCTransport mucTransport = getSession().getTransport().getMUCTransport(); try { IRCMUCSession mucSession = (IRCMUCSession)getSession().getMUCSessionManager().getSession(kc.getChannel()); mucSession.getContacts().add(kc.getKicked().getNick()); Presence p = new Presence(); p.setType(Presence.Type.unavailable); p.setFrom(mucTransport.convertIDToJID(kc.getChannel(), kc.getKicked().getNick())); p.setTo(getSession().getJID()); Element elem = p.addChildElement("x", "http://jabber.org/protocol/muc#user"); Element item = elem.addElement("item"); item.addAttribute("affiliation", "none"); item.addAttribute("role", "none"); Element actor = item.addElement("actor"); actor.addAttribute("jid", getSession().getTransport().convertIDToJID(kc.getKicker().getNick()).toBareJID()); Element reason = item.addElement("reason"); reason.addText(kc.getComment()); Element status = elem.addElement("status"); status.addAttribute("code", "307"); getSession().getTransport().sendPacket(p); } catch (NotFoundException e) { Log.debug("Received information for IRC session that doesn't exist."); } if (kc.kickedUs(getSession().getConnection().getClientState())) { getSession().getMUCSessionManager().removeSession(kc.getChannel()); } } else if (inCommand instanceof ChannelModeCommand) { //ChannelModeCommand cmc = (ChannelModeCommand)inCommand; // TODO: Fix up martyr to handle this then handle it here } else if (inCommand instanceof NickCommand) { //NickCommand nc = (NickCommand)inCommand; // TODO: Map to MUC event (someone's nick just changed) } else if (inCommand instanceof ModeCommand) { //ModeCommand mc = (ModeCommand)inCommand; // TODO: Map to MUC event (your mode just changed) } else if (inCommand instanceof TopicCommand) { TopicCommand tc = (TopicCommand)inCommand; Channel channel = getSession().getConnection().getClientState().getChannel(tc.getChannel()); if (channel != null) { BaseMUCTransport mucTransport = getSession().getTransport().getMUCTransport(); Message m = new Message(); m.setType(Message.Type.groupchat); m.setTo(getSession().getJID()); m.setFrom(mucTransport.convertIDToJID(channel.getName(), channel.getTopicAuthor())); m.setSubject(net.sf.kraken.util.StringUtils.removeInvalidXMLCharacters(channel.getTopic())); mucTransport.sendPacket(m); } } else if (inCommand instanceof TopicInfoReply) { TopicInfoReply tir = (TopicInfoReply)inCommand; Channel channel = getSession().getConnection().getClientState().getChannel(tir.getChannel()); if (channel != null) { BaseMUCTransport mucTransport = getSession().getTransport().getMUCTransport(); Message m = new Message(); m.setType(Message.Type.groupchat); m.setTo(getSession().getJID()); m.setFrom(mucTransport.convertIDToJID(channel.getName(), channel.getTopicAuthor())); m.setSubject(net.sf.kraken.util.StringUtils.removeInvalidXMLCharacters(channel.getTopic())); mucTransport.sendPacket(m); } } else if (inCommand instanceof NamesReply) { NamesReply nr = (NamesReply)inCommand; String channelName = nr.getChannel(); List<MUCTransportRoomMember> members = new ArrayList<MUCTransportRoomMember>(); for (String nick : nr.getNames()) { members.add(new MUCTransportRoomMember(getSession().getTransport().getMUCTransport().convertIDToJID(channelName, nick))); } // This will be ignored if no one asked for it. getSession().getTransport().getMUCTransport().sendRoomMembers(getSession().getJID(), getSession().getTransport().getMUCTransport().convertIDToJID(channelName, null), members); } else if (inCommand instanceof NamesEndReply) { NamesEndReply ner = (NamesEndReply)inCommand; BaseMUCTransport mucTransport = getSession().getTransport().getMUCTransport(); try { IRCMUCSession mucSession = (IRCMUCSession)getSession().getMUCSessionManager().getSession(ner.getChannel()); mucSession.getContacts().clear(); Member myMember = null; Channel channel = getSession().getConnection().getClientState().getChannel(ner.getChannel()); if (channel != null) { Enumeration members = channel.getMembers(); while (members.hasMoreElements()) { Member member = (Member)members.nextElement(); if (member.getNick().getNick().equals(mucSession.getNickname()) || member.getNick().getNick().equals(getSession().getRegistration().getNickname())) { // Aha, this is us, save for the end. myMember = member; continue; } Presence p = new Presence(); p.setTo(getSession().getJID()); if (member.hasOps()) { // Moderator. mucSession.getContacts().add(member.getNick().getNick()); p.setFrom(mucTransport.convertIDToJID(ner.getChannel(), member.getNick().getNick())); Element elem = p.addChildElement("x", "http://jabber.org/protocol/muc#user"); Element item = elem.addElement("item"); item.addAttribute("affiliation", "admin"); item.addAttribute("role", "moderator"); } else { // Regular participant. mucSession.getContacts().add(member.getNick().getNick()); p.setFrom(mucTransport.convertIDToJID(ner.getChannel(), member.getNick().getNick())); Element elem = p.addChildElement("x", "http://jabber.org/protocol/muc#user"); Element item = elem.addElement("item"); item.addAttribute("affiliation", "member"); item.addAttribute("role", "participant"); } mucTransport.sendPacket(p); } } if (myMember != null) { Presence p = new Presence(); p.setTo(getSession().getJID()); p.setFrom(mucTransport.convertIDToJID(ner.getChannel(), mucSession.getNickname())); Element elem = p.addChildElement("x", "http://jabber.org/protocol/muc#user"); Element item = elem.addElement("item"); if (myMember.hasOps()) { item.addAttribute("affiliation", "admin"); item.addAttribute("role", "moderator"); } else { item.addAttribute("affiliation", "member"); item.addAttribute("role", "participant"); } Element status = elem.addElement("status"); status.addAttribute("code", "110"); mucTransport.sendPacket(p); } } catch (NotFoundException e) { Log.debug("Received information for IRC session that doesn't exist."); } } else if (inCommand instanceof ListStartReply) { // Do nothing. } else if (inCommand instanceof ListReply) { ListReply lr = (ListReply)inCommand; String channelName = lr.getChannel(); MUCTransportRoom mucRoom = getSession().getTransport().getMUCTransport().getCachedRoom(channelName); if (mucRoom == null) { mucRoom = new MUCTransportRoom(getSession().getTransport().getMUCTransport().convertIDToJID(channelName, ""), channelName); } mucRoom.setTopic(lr.getTopic()); mucRoom.setOccupant_count(lr.getMemberCount()); getSession().getTransport().getMUCTransport().cacheRoom(mucRoom); // This will be ignored if no one asked for it. getSession().getTransport().getMUCTransport().sendRoomInfo(getSession().getJID(), getSession().getTransport().getMUCTransport().convertIDToJID(mucRoom.getName(), null), mucRoom); } else if (inCommand instanceof ListEndReply) { // This will be ignored if no one asked for it. getSession().getTransport().getMUCTransport().sendRooms(getSession().getJID(), getSession().getTransport().getMUCTransport().getCachedRooms()); } else if (inCommand instanceof IsonCommand) { IsonCommand ic = (IsonCommand)inCommand; List<String> newNicks = new ArrayList<String>(); for (String nick : ic.getNicks()) { newNicks.add(nick.toLowerCase()); } Log.debug("IRC: Got ISON for "+ic.getDest()+" of: "+ic.getNicks()); for (TransportBuddy buddy : getSession().getBuddyManager().getBuddies()) { if (!newNicks.contains(buddy.getName())) { // Previously online nick went offline buddy.setPresence(PresenceType.unavailable); } else { // Previously online nick is still online buddy.setPresence(PresenceType.available); } } } else if (inCommand instanceof UnAwayReply) { getSession().setPresence(PresenceType.available); } else if (inCommand instanceof NowAwayReply) { getSession().setPresence(PresenceType.away); } else if (inCommand instanceof AwayReply) { AwayReply ar = (AwayReply)inCommand; getSession().getTransport().sendMessage( getSession().getJID(), getSession().getTransport().convertIDToJID(ar.getNick()), LocaleUtils.getLocalizedString("gateway.irc.autoreply", "kraken")+" "+ar.getMessage() ); } } }