/* Yaaic - Yet Another Android IRC Client Copyright 2009-2011 Sebastian Kaspari This file is part of Yaaic. Yaaic is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Yaaic is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Yaaic. If not, see . */ package org.yaaic.irc; import java.util.ArrayList; import java.util.Collection; import java.util.Vector; import java.util.regex.Pattern; import org.jibble.pircbot.PircBot; import org.jibble.pircbot.User; import org.yaaic.R; import org.yaaic.Yaaic; import org.yaaic.command.CommandParser; import org.yaaic.model.Broadcast; import org.yaaic.model.Channel; import org.yaaic.model.Conversation; import org.yaaic.model.Message; import org.yaaic.model.Query; import org.yaaic.model.Server; import org.yaaic.model.ServerInfo; import org.yaaic.model.Status; import android.content.Intent; /** * The class that actually handles the connection to an IRC server * * @author Sebastian Kaspari */ public class IRCConnection extends PircBot { private final IRCService service; private final Server server; private ArrayList autojoinChannels; private Pattern mNickMatch; private boolean ignoreMOTD = true; private boolean isQuitting = false; private boolean disposeRequested = false; private final Object isQuittingLock = new Object(); /** * Create a new connection * * @param service * @param serverId */ public IRCConnection(IRCService service, int serverId) { this.server = Yaaic.getInstance().getServerById(serverId); this.service = service; // XXX: Should be configurable via settings this.setAutoNickChange(true); this.setFinger("http://www.youtube.com/watch?v=oHg5SJYRHA0"); this.updateNickMatchPattern(); } /** * Set the nickname of the user * * @param nickname The nickname to use */ public void setNickname(String nickname) { this.setName(nickname); this.updateNickMatchPattern(); } /** * Set the real name of the user * * @param realname The realname to use */ public void setRealName(String realname) { // XXX: Pircbot uses the version for "real name" and "version". // The real "version" value is provided by onVersion() this.setVersion(realname); } /** * Set channels to autojoin after connect * * @param channels */ public void setAutojoinChannels(ArrayList channels) { autojoinChannels = channels; } /** * On version (CTCP version) * * This is a fix for pircbot as pircbot uses the version as "real name" and as "version" */ @Override protected void onVersion(String sourceNick, String sourceLogin, String sourceHostname, String target) { this.sendRawLine( "NOTICE " + sourceNick + " :\u0001VERSION " + "Yaaic - Yet another Android IRC client - http://www.yaaic.org" + "\u0001" ); } /** * Set the ident of the user * * @param ident The ident to use */ public void setIdent(String ident) { this.setLogin(ident); } /** * On connect */ @Override public void onConnect() { server.setStatus(Status.CONNECTED); server.setMayReconnect(true); ignoreMOTD = service.getSettings().isIgnoreMOTDEnabled(); service.sendBroadcast( Broadcast.createServerIntent(Broadcast.SERVER_UPDATE, server.getId()) ); service.notifyConnected(server.getTitle()); Message message = new Message(service.getString(R.string.message_connected, server.getTitle())); message.setColor(Message.COLOR_GREEN); server.getConversation(ServerInfo.DEFAULT_NAME).addMessage(message); Message infoMessage = new Message(service.getString(R.string.message_now_login)); infoMessage.setColor(Message.COLOR_GREY); server.getConversation(ServerInfo.DEFAULT_NAME).addMessage(infoMessage); Intent intent = Broadcast.createConversationIntent( Broadcast.CONVERSATION_MESSAGE, server.getId(), ServerInfo.DEFAULT_NAME ); if (server.getAuthentication().hasNickservCredentials()) { identify(server.getAuthentication().getNickservPassword()); } service.sendBroadcast(intent); } /** * On register */ @Override public void onRegister() { // Call parent method to ensure "register" status is tracked super.onRegister(); // execute commands CommandParser parser = CommandParser.getInstance(); this.updateNickMatchPattern(); for (String command : server.getConnectCommands()) { parser.parse(command, server, server.getConversation(ServerInfo.DEFAULT_NAME), service); } // TODO: Detect "You are now identified for " notices from NickServ and handle // auto joins in onNotice instead if the user has chosen to wait for NickServ // identification before auto joining channels. // delay 1 sec before auto joining channels try { Thread.sleep(1000); } catch(InterruptedException e) { // do nothing } // join channels if (autojoinChannels != null) { for (String channel : autojoinChannels) { // Add support for channel keys joinChannel(channel); } } else { for (String channel : server.getAutoJoinChannels()) { joinChannel(channel); } } Message infoMessage = new Message(service.getString(R.string.message_login_done)); infoMessage.setColor(Message.COLOR_GREY); server.getConversation(ServerInfo.DEFAULT_NAME).addMessage(infoMessage); Intent intent = Broadcast.createConversationIntent( Broadcast.CONVERSATION_MESSAGE, server.getId(), ServerInfo.DEFAULT_NAME ); service.sendBroadcast(intent); } /** * On channel action */ @Override protected void onAction(String sender, String login, String hostname, String target, String action) { Conversation conversation; Message message = new Message(sender + " " + action); message.setIcon(R.drawable.action); String queryNick = target; if (queryNick.equals(this.getNick())) { // We are the target - this is an action in a query queryNick = sender; } conversation = server.getConversation(queryNick); if (conversation == null) { // Open a query if there's none yet conversation = new Query(queryNick); conversation.setHistorySize(service.getSettings().getHistorySize()); server.addConversation(conversation); conversation.addMessage(message); Intent intent = Broadcast.createConversationIntent( Broadcast.CONVERSATION_NEW, server.getId(), queryNick ); service.sendBroadcast(intent); } else { conversation.addMessage(message); Intent intent = Broadcast.createConversationIntent( Broadcast.CONVERSATION_MESSAGE, server.getId(), queryNick ); service.sendBroadcast(intent); } if (sender.equals(this.getNick())) { // Don't notify for something sent in our name return; } boolean mentioned = isMentioned(action); if (mentioned || target.equals(this.getNick())) { if (conversation.getStatus() != Conversation.STATUS_SELECTED || !server.getIsForeground()) { service.addNewMention( server.getId(), conversation, conversation.getName() + ": " + sender + " " + action, service.getSettings().isVibrateHighlightEnabled(), service.getSettings().isSoundHighlightEnabled() ); } } if (mentioned) { // highlight message.setColor(Message.COLOR_RED); conversation.setStatus(Conversation.STATUS_HIGHLIGHT); } } /** * On Channel Info */ @Override protected void onChannelInfo(String channel, int userCount, String topic) { } /** * On Deop */ @Override protected void onDeop(String target, String sourceNick, String sourceLogin, String sourceHostname, String recipient) { Message message = new Message(service.getString(R.string.message_deop, sourceNick, recipient)); message.setIcon(R.drawable.op); message.setColor(Message.COLOR_BLUE); server.getConversation(target).addMessage(message); Intent intent = Broadcast.createConversationIntent( Broadcast.CONVERSATION_MESSAGE, server.getId(), target ); service.sendBroadcast(intent); } /** * On DeVoice */ @Override protected void onDeVoice(String target, String sourceNick, String sourceLogin, String sourceHostname, String recipient) { Message message = new Message(service.getString(R.string.message_devoice, sourceNick, recipient)); message.setColor(Message.COLOR_BLUE); message.setIcon(R.drawable.voice); server.getConversation(target).addMessage(message); Intent intent = Broadcast.createConversationIntent( Broadcast.CONVERSATION_MESSAGE, server.getId(), target ); service.sendBroadcast(intent); } /** * On Invite */ @Override protected void onInvite(String targetNick, String sourceNick, String sourceLogin, String sourceHostname, String target) { if (targetNick.equals(this.getNick())) { // We are invited Message message = new Message(service.getString(R.string.message_invite_you, sourceNick, target)); server.getConversation(server.getSelectedConversation()).addMessage(message); Intent intent = Broadcast.createConversationIntent( Broadcast.CONVERSATION_MESSAGE, server.getId(), server.getSelectedConversation() ); service.sendBroadcast(intent); } else { // Someone is invited Message message = new Message(service.getString(R.string.message_invite_someone, sourceNick, targetNick, target)); server.getConversation(target).addMessage(message); Intent intent = Broadcast.createConversationIntent( Broadcast.CONVERSATION_MESSAGE, server.getId(), target ); service.sendBroadcast(intent); } } /** * On Join */ @Override protected void onJoin(String target, String sender, String login, String hostname) { if (sender.equalsIgnoreCase(getNick()) && server.getConversation(target) == null) { // We joined a new channel Conversation conversation = new Channel(target); conversation.setHistorySize(service.getSettings().getHistorySize()); server.addConversation(conversation); Intent intent = Broadcast.createConversationIntent( Broadcast.CONVERSATION_NEW, server.getId(), target ); service.sendBroadcast(intent); } else if (service.getSettings().showJoinPartAndQuit()) { Message message = new Message( service.getString(R.string.message_join, sender), Message.TYPE_MISC ); message.setIcon(R.drawable.join); message.setColor(Message.COLOR_GREEN); server.getConversation(target).addMessage(message); Intent intent = Broadcast.createConversationIntent( Broadcast.CONVERSATION_MESSAGE, server.getId(), target ); service.sendBroadcast(intent); } } /** * On Kick */ @Override protected void onKick(String target, String kickerNick, String kickerLogin, String kickerHostname, String recipientNick, String reason) { if (recipientNick.equals(getNick())) { // We are kicked server.removeConversation(target); Intent intent = Broadcast.createConversationIntent( Broadcast.CONVERSATION_REMOVE, server.getId(), target ); service.sendBroadcast(intent); } else { Message message = new Message(service.getString(R.string.message_kick, kickerNick, recipientNick)); message.setColor(Message.COLOR_GREEN); server.getConversation(target).addMessage(message); Intent intent = Broadcast.createConversationIntent( Broadcast.CONVERSATION_MESSAGE, server.getId(), target ); service.sendBroadcast(intent); } } /** * On Message */ @Override protected void onMessage(String target, String sender, String login, String hostname, String text) { Message message = new Message(text, sender); Conversation conversation = server.getConversation(target); if (isMentioned(text)) { // highlight message.setColor(Message.COLOR_RED); if (conversation.getStatus() != Conversation.STATUS_SELECTED || !server.getIsForeground()) { service.addNewMention( server.getId(), conversation, target + ": <" + sender + "> " + text, service.getSettings().isVibrateHighlightEnabled(), service.getSettings().isSoundHighlightEnabled() ); } conversation.setStatus(Conversation.STATUS_HIGHLIGHT); } conversation.addMessage(message); Intent intent = Broadcast.createConversationIntent( Broadcast.CONVERSATION_MESSAGE, server.getId(), target ); service.sendBroadcast(intent); } /** * On Mode */ @Override protected void onMode(String target, String sourceNick, String sourceLogin, String sourceHostname, String mode) { // Disabled as it doubles events (e.g. onOp and onMode will be called) /* Message message = new Message(sourceNick + " sets mode " + mode); server.getChannel(target).addMessage(message); Intent intent = new Intent(Broadcast.CHANNEL_MESSAGE); intent.putExtra(Broadcast.EXTRA_SERVER, server.getId()); intent.putExtra(Broadcast.EXTRA_CHANNEL, target); service.sendBroadcast(intent); */ } /** * On Nick Change */ @Override protected void onNickChange(String oldNick, String login, String hostname, String newNick) { if (getNick().equalsIgnoreCase(newNick)) { this.updateNickMatchPattern(); // Send message about own change to server info window Message message = new Message(service.getString(R.string.message_self_rename, newNick)); message.setColor(Message.COLOR_GREEN); server.getConversation(ServerInfo.DEFAULT_NAME).addMessage(message); Intent intent = Broadcast.createConversationIntent( Broadcast.CONVERSATION_MESSAGE, server.getId(), ServerInfo.DEFAULT_NAME ); service.sendBroadcast(intent); } Vector channels = getChannelsByNickname(newNick); for (String target : channels) { Message message = new Message(service.getString(R.string.message_rename, oldNick, newNick)); message.setColor(Message.COLOR_GREEN); server.getConversation(target).addMessage(message); Intent intent = Broadcast.createConversationIntent( Broadcast.CONVERSATION_MESSAGE, server.getId(), target ); service.sendBroadcast(intent); } } /** * On Notice */ @Override protected void onNotice(String sourceNick, String sourceLogin, String sourceHostname, String target, String notice) { // Post notice to currently selected conversation Conversation conversation; if (service.getSettings().showNoticeInServerWindow()) { conversation = server.getConversation(ServerInfo.DEFAULT_NAME); } else { conversation = server.getConversation(server.getSelectedConversation()); if (conversation == null) { // Fallback: Use ServerInfo view conversation = server.getConversation(ServerInfo.DEFAULT_NAME); } } Message message = new Message("-" + sourceNick + "- " + notice); message.setIcon(R.drawable.info); conversation.addMessage(message); Intent intent = Broadcast.createConversationIntent( Broadcast.CONVERSATION_MESSAGE, server.getId(), conversation.getName() ); service.sendBroadcast(intent); } /** * On Op */ @Override protected void onOp(String target, String sourceNick, String sourceLogin, String sourceHostname, String recipient) { Message message = new Message(service.getString(R.string.message_op, sourceNick, recipient)); message.setColor(Message.COLOR_BLUE); message.setIcon(R.drawable.op); server.getConversation(target).addMessage(message); Intent intent = Broadcast.createConversationIntent( Broadcast.CONVERSATION_MESSAGE, server.getId(), target ); service.sendBroadcast(intent); } /** * On Part */ @Override protected void onPart(String target, String sender, String login, String hostname) { if (sender.equals(getNick())) { // We parted a channel server.removeConversation(target); Intent intent = Broadcast.createConversationIntent( Broadcast.CONVERSATION_REMOVE, server.getId(), target ); service.sendBroadcast(intent); } else if (service.getSettings().showJoinPartAndQuit()) { Message message = new Message( service.getString(R.string.message_part, sender), Message.TYPE_MISC ); message.setColor(Message.COLOR_GREEN); message.setIcon(R.drawable.part); server.getConversation(target).addMessage(message); Intent intent = Broadcast.createConversationIntent( Broadcast.CONVERSATION_MESSAGE, server.getId(), target ); service.sendBroadcast(intent); } } /** * On Private Message */ @Override protected void onPrivateMessage(String sender, String login, String hostname, String target, String text) { Message message = new Message("<" + sender + "> " + text); String queryNick = sender; if (queryNick.equals(this.getNick())) { queryNick = target; } Conversation conversation = server.getConversation(queryNick); if (conversation == null) { // Open a query if there's none yet conversation = new Query(queryNick); conversation.setHistorySize(service.getSettings().getHistorySize()); conversation.addMessage(message); server.addConversation(conversation); Intent intent = Broadcast.createConversationIntent( Broadcast.CONVERSATION_NEW, server.getId(), queryNick ); service.sendBroadcast(intent); } else { conversation.addMessage(message); Intent intent = Broadcast.createConversationIntent( Broadcast.CONVERSATION_MESSAGE, server.getId(), queryNick ); service.sendBroadcast(intent); } if (sender.equals(this.getNick())) { // Don't notify for something sent in our name return; } if (conversation.getStatus() != Conversation.STATUS_SELECTED || !server.getIsForeground()) { service.addNewMention( server.getId(), conversation, "<" + sender + "> " + text, service.getSettings().isVibrateHighlightEnabled(), service.getSettings().isSoundHighlightEnabled() ); } if (isMentioned(text)) { message.setColor(Message.COLOR_RED); conversation.setStatus(Conversation.STATUS_HIGHLIGHT); } } /** * On Quit */ @Override protected void onQuit(String sourceNick, String sourceLogin, String sourceHostname, String reason) { if (sourceNick.equals(this.getNick())) { return; } if (service.getSettings().showJoinPartAndQuit()) { Vector channels = getChannelsByNickname(sourceNick); for (String target : channels) { Message message = new Message( service.getString(R.string.message_quit, sourceNick, reason), Message.TYPE_MISC ); message.setColor(Message.COLOR_GREEN); message.setIcon(R.drawable.quit); server.getConversation(target).addMessage(message); Intent intent = Broadcast.createConversationIntent( Broadcast.CONVERSATION_MESSAGE, server.getId(), target ); service.sendBroadcast(intent); } // Look if there's a query to update Conversation conversation = server.getConversation(sourceNick); if (conversation != null) { Message message = new Message( service.getString(R.string.message_quit, sourceNick, reason), Message.TYPE_MISC ); message.setColor(Message.COLOR_GREEN); message.setIcon(R.drawable.quit); conversation.addMessage(message); Intent intent = Broadcast.createConversationIntent( Broadcast.CONVERSATION_MESSAGE, server.getId(), conversation.getName() ); service.sendBroadcast(intent); } } } /** * On Topic */ @Override public void onTopic(String target, String topic, String setBy, long date, boolean changed) { if (changed) { Message message = new Message(service.getString(R.string.message_topic_set, setBy, topic)); message.setColor(Message.COLOR_YELLOW); server.getConversation(target).addMessage(message); } else { Message message = new Message(service.getString(R.string.message_topic, topic)); message.setColor(Message.COLOR_YELLOW); server.getConversation(target).addMessage(message); } // remember channel's topic ((Channel) server.getConversation(target)).setTopic(topic); Intent intent = Broadcast.createConversationIntent( Broadcast.CONVERSATION_MESSAGE, server.getId(), target ); service.sendBroadcast(intent); // update the displayed conversation title if necessary intent = Broadcast.createConversationIntent( Broadcast.CONVERSATION_TOPIC, server.getId(), target ); service.sendBroadcast(intent); } /** * On User List */ @Override protected void onUserList(String channel, User[] users) { // XXX: Store user list somewhere and keep it updated or just broadcast some event? } /** * On Voice */ @Override protected void onVoice(String target, String sourceNick, String sourceLogin, String sourceHostname, String recipient) { Message message = new Message(service.getString(R.string.message_voice, sourceNick, recipient)); message.setIcon(R.drawable.voice); message.setColor(Message.COLOR_BLUE); server.getConversation(target).addMessage(message); Intent intent = Broadcast.createConversationIntent( Broadcast.CONVERSATION_MESSAGE, server.getId(), target ); service.sendBroadcast(intent); } /** * On remove channel key */ @Override protected void onRemoveChannelKey(String target, String sourceNick, String sourceLogin, String sourceHostname, String key) { Message message = new Message(service.getString(R.string.message_remove_channel_key, sourceNick)); message.setColor(Message.COLOR_BLUE); server.getConversation(target).addMessage(message); service.sendBroadcast( Broadcast.createConversationIntent(Broadcast.CONVERSATION_MESSAGE, server.getId(), target) ); } /** * On set channel key */ @Override protected void onSetChannelKey(String target, String sourceNick, String sourceLogin, String sourceHostname, String key) { Message message = new Message(service.getString(R.string.message_set_channel_key, sourceNick, key)); message.setColor(Message.COLOR_BLUE); server.getConversation(target).addMessage(message); service.sendBroadcast( Broadcast.createConversationIntent(Broadcast.CONVERSATION_MESSAGE, server.getId(), target) ); } /** * On set secret */ @Override protected void onSetSecret(String target, String sourceNick, String sourceLogin, String sourceHostname) { Message message = new Message(service.getString(R.string.message_set_channel_secret, sourceNick)); message.setColor(Message.COLOR_BLUE); server.getConversation(target).addMessage(message); service.sendBroadcast( Broadcast.createConversationIntent(Broadcast.CONVERSATION_MESSAGE, server.getId(), target) ); } /** * On remove secret */ @Override protected void onRemoveSecret(String target, String sourceNick, String sourceLogin, String sourceHostname) { Message message = new Message(service.getString(R.string.message_set_channel_public, sourceNick)); message.setColor(Message.COLOR_BLUE); server.getConversation(target).addMessage(message); service.sendBroadcast( Broadcast.createConversationIntent(Broadcast.CONVERSATION_MESSAGE, server.getId(), target) ); } /** * On set channel limit */ @Override protected void onSetChannelLimit(String target, String sourceNick, String sourceLogin, String sourceHostname, int limit) { Message message = new Message(service.getString(R.string.message_set_channel_limit, sourceNick, limit)); message.setColor(Message.COLOR_BLUE); server.getConversation(target).addMessage(message); service.sendBroadcast( Broadcast.createConversationIntent(Broadcast.CONVERSATION_MESSAGE, server.getId(), target) ); } /** * On remove channel limit */ @Override protected void onRemoveChannelLimit(String target, String sourceNick, String sourceLogin, String sourceHostname) { Message message = new Message(service.getString(R.string.message_remove_channel_limit, sourceNick)); message.setColor(Message.COLOR_BLUE); server.getConversation(target).addMessage(message); service.sendBroadcast( Broadcast.createConversationIntent(Broadcast.CONVERSATION_MESSAGE, server.getId(), target) ); } /** * On set channel ban */ @Override protected void onSetChannelBan(String target, String sourceNick, String sourceLogin, String sourceHostname, String hostmask) { Message message = new Message(service.getString(R.string.message_set_ban, sourceNick, hostmask)); message.setColor(Message.COLOR_BLUE); server.getConversation(target).addMessage(message); service.sendBroadcast( Broadcast.createConversationIntent(Broadcast.CONVERSATION_MESSAGE, server.getId(), target) ); } /** * On remove channel ban */ @Override protected void onRemoveChannelBan(String target, String sourceNick, String sourceLogin, String sourceHostname, String hostmask) { Message message = new Message(service.getString(R.string.message_remove_ban, sourceNick, hostmask)); message.setColor(Message.COLOR_BLUE); server.getConversation(target).addMessage(message); service.sendBroadcast( Broadcast.createConversationIntent(Broadcast.CONVERSATION_MESSAGE, server.getId(), target) ); } /** * On set topic protection */ @Override protected void onSetTopicProtection(String target, String sourceNick, String sourceLogin, String sourceHostname) { Message message = new Message(service.getString(R.string.message_set_topic_protection, sourceNick)); message.setColor(Message.COLOR_BLUE); server.getConversation(target).addMessage(message); service.sendBroadcast( Broadcast.createConversationIntent(Broadcast.CONVERSATION_MESSAGE, server.getId(), target) ); } /** * On remove topic protection */ @Override protected void onRemoveTopicProtection(String target, String sourceNick, String sourceLogin, String sourceHostname) { Message message = new Message(service.getString(R.string.message_remove_topic_protection, sourceNick)); message.setColor(Message.COLOR_BLUE); server.getConversation(target).addMessage(message); service.sendBroadcast( Broadcast.createConversationIntent(Broadcast.CONVERSATION_MESSAGE, server.getId(), target) ); } /** * On set no external messages */ @Override protected void onSetNoExternalMessages(String target, String sourceNick, String sourceLogin, String sourceHostname) { Message message = new Message(service.getString(R.string.message_disable_external, sourceNick)); message.setColor(Message.COLOR_BLUE); server.getConversation(target).addMessage(message); service.sendBroadcast( Broadcast.createConversationIntent(Broadcast.CONVERSATION_MESSAGE, server.getId(), target) ); } /** * On remove no external messages */ @Override protected void onRemoveNoExternalMessages(String target, String sourceNick, String sourceLogin, String sourceHostname) { Message message = new Message(service.getString(R.string.message_enable_external, sourceNick)); message.setColor(Message.COLOR_BLUE); server.getConversation(target).addMessage(message); service.sendBroadcast( Broadcast.createConversationIntent(Broadcast.CONVERSATION_MESSAGE, server.getId(), target) ); } /** * On set invite only */ @Override protected void onSetInviteOnly(String target, String sourceNick, String sourceLogin, String sourceHostname) { Message message = new Message(service.getString(R.string.message_set_invite_only, sourceNick)); message.setColor(Message.COLOR_BLUE); server.getConversation(target).addMessage(message); service.sendBroadcast( Broadcast.createConversationIntent(Broadcast.CONVERSATION_MESSAGE, server.getId(), target) ); } /** * On remove invite only */ @Override protected void onRemoveInviteOnly(String target, String sourceNick, String sourceLogin, String sourceHostname) { Message message = new Message(service.getString(R.string.message_remove_invite_only, sourceNick)); message.setColor(Message.COLOR_BLUE); server.getConversation(target).addMessage(message); service.sendBroadcast( Broadcast.createConversationIntent(Broadcast.CONVERSATION_MESSAGE, server.getId(), target) ); } /** * On set moderated */ @Override protected void onSetModerated(String target, String sourceNick, String sourceLogin, String sourceHostname) { Message message = new Message(service.getString(R.string.message_set_moderated, sourceNick)); message.setColor(Message.COLOR_BLUE); server.getConversation(target).addMessage(message); service.sendBroadcast( Broadcast.createConversationIntent(Broadcast.CONVERSATION_MESSAGE, server.getId(), target) ); } /** * On remove moderated */ @Override protected void onRemoveModerated(String target, String sourceNick, String sourceLogin, String sourceHostname) { Message message = new Message(service.getString(R.string.message_remove_moderated, sourceNick)); message.setColor(Message.COLOR_BLUE); server.getConversation(target).addMessage(message); service.sendBroadcast( Broadcast.createConversationIntent(Broadcast.CONVERSATION_MESSAGE, server.getId(), target) ); } /** * On set private */ @Override protected void onSetPrivate(String target, String sourceNick, String sourceLogin, String sourceHostname) { Message message = new Message(service.getString(R.string.message_set_channel_private, sourceNick)); message.setColor(Message.COLOR_BLUE); server.getConversation(target).addMessage(message); service.sendBroadcast( Broadcast.createConversationIntent(Broadcast.CONVERSATION_MESSAGE, server.getId(), target) ); } /** * On remove private */ @Override protected void onRemovePrivate(String target, String sourceNick, String sourceLogin, String sourceHostname) { Message message = new Message(service.getString(R.string.message_set_channel_public, sourceNick)); message.setColor(Message.COLOR_BLUE); server.getConversation(target).addMessage(message); service.sendBroadcast( Broadcast.createConversationIntent(Broadcast.CONVERSATION_MESSAGE, server.getId(), target) ); } /** * On unknown */ @Override protected void onUnknown(String line) { Message message = new Message(line); message.setIcon(R.drawable.action); message.setColor(Message.COLOR_GREY); server.getConversation(ServerInfo.DEFAULT_NAME).addMessage(message); Intent intent = Broadcast.createConversationIntent( Broadcast.CONVERSATION_MESSAGE, server.getId(), ServerInfo.DEFAULT_NAME ); service.sendBroadcast(intent); } /** * On server response */ @Override protected void onServerResponse(int code, String response) { if (code == 4) { // User has registered with the server onRegister(); return; } if ((code == 372 || code == 375) && ignoreMOTD) { return; } if (code == 376 && ignoreMOTD) { ignoreMOTD = false; return; } if (code >= 200 && code < 300) { // Skip 2XX responses return; } if (code == 353 || code == 366 || code == 332 || code == 333) { return; } if (code < 10) { // Skip server info return; } // Currently disabled... to much text Message message = new Message(response); message.setColor(Message.COLOR_GREY); server.getConversation(ServerInfo.DEFAULT_NAME).addMessage(message); Intent intent = Broadcast.createConversationIntent( Broadcast.CONVERSATION_MESSAGE, server.getId(), ServerInfo.DEFAULT_NAME ); service.sendBroadcast(intent); } /** * On disconnect */ @Override public void onDisconnect() { // Call parent method to ensure "register" status is tracked super.onDisconnect(); if (service.getSettings().isReconnectEnabled() && server.getStatus() != Status.DISCONNECTED) { setAutojoinChannels(server.getCurrentChannelNames()); server.setStatus(Status.CONNECTING); service.connect(server); } else { server.setStatus(Status.DISCONNECTED); } service.notifyDisconnected(server.getTitle()); Intent sIntent = Broadcast.createServerIntent(Broadcast.SERVER_UPDATE, server.getId()); service.sendBroadcast(sIntent); Collection conversations = server.getConversations(); for (Conversation conversation : conversations) { Message message = new Message(service.getString(R.string.message_disconnected)); message.setIcon(R.drawable.error); message.setColor(Message.COLOR_RED); server.getConversation(conversation.getName()).addMessage(message); Intent cIntent = Broadcast.createConversationIntent( Broadcast.CONVERSATION_MESSAGE, server.getId(), conversation.getName() ); service.sendBroadcast(cIntent); } synchronized(isQuittingLock) { isQuitting = false; if (disposeRequested) { super.dispose(); } } } /** * Get all channels where the user with the given nickname is online * * @param nickname * @return Array of channel names */ private Vector getChannelsByNickname(String nickname) { Vector channels = new Vector(); String[] channelArray = getChannels(); for (String channel : channelArray) { User[] userArray = getUsers(channel); for (User user : userArray) { if (user.getNick().equals(nickname)) { channels.add(channel); break; } } } return channels; } /** * Get list of users in a channel as array of strings * * @param channel Name of the channel */ public String[] getUsersAsStringArray(String channel) { User[] userArray = getUsers(channel); int mLength = userArray.length; String[] users = new String[mLength]; for (int i = 0; i < mLength; i++) { users[i] = userArray[i].getPrefix() + userArray[i].getNick(); } return users; } /** * Get a user by channel and nickname * * @param channel The channel the user is in * @param nickname The nickname of the user (with or without prefix) * @return the User object or null if user was not found */ public User getUser(String channel, String nickname) { User[] users = getUsers(channel); int mLength = users.length; for (int i = 0; i < mLength; i++) { if (nickname.equals(users[i].getNick())) { return users[i]; } if (nickname.equals(users[i].getPrefix() + users[i].getNick())) { return users[i]; } } return null; } /** * Quits from the IRC server with default reason. */ @Override public void quitServer() { quitServer(service.getSettings().getQuitMessage()); } @Override public void quitServer(final String message) { synchronized(isQuittingLock) { isQuitting = true; } new Thread() { @Override public void run() { superClassQuitServer(message); } }.start(); } private final void superClassQuitServer(String message) { super.quitServer(message); } /** * Check whether the nickname has been mentioned. * * @param text The text to check for the nickname * @return true if nickname was found, otherwise false */ public boolean isMentioned(String text) { return mNickMatch.matcher(text).find(); } /** * Update the nick matching pattern, should be called when the nickname changes. */ private void updateNickMatchPattern() { mNickMatch = Pattern.compile("(?:^|[\\s?!'�:;,.])"+Pattern.quote(getNick())+"(?:[\\s?!'�:;,.]|$)", Pattern.CASE_INSENSITIVE); } @Override public void dispose() { synchronized(isQuittingLock) { if (isQuitting) { disposeRequested = true; } else { super.dispose(); } } } }