fm.last.irccat.IRCCat.java Source code

Java tutorial

Introduction

Here is the source code for fm.last.irccat.IRCCat.java

Source

/*
 irccat - a development support irc bot
 Copyright (C) 2006-2008 Richard Jones <rj@last.fm>
    
 This program 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; version 2 of the GPL only, not 3 :P
    
 This program 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 this program; if not, write to the Free Software Foundation, Inc.,
 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */
package fm.last.irccat;

import org.apache.commons.configuration.*;
import org.jibble.pircbot.*;
import java.net.*;
import java.io.*;
import java.util.List;
import java.util.Map;
import java.util.HashMap;

public class IRCCat extends PircBot {

    private String nick;
    private String cmdScript;
    private String defaultChannel = null;
    private int maxCmdResponseLines = 26;
    private XMLConfiguration config;

    public static void main(String[] args) throws Exception {
        try {
            if (args.length == 0) {
                System.out.println("first param should be config file");
                System.exit(-1);
            }
            XMLConfiguration c = null;
            try {
                c = new XMLConfiguration(args[0]);
            } catch (ConfigurationException cex) {
                System.err.println("Configuration error, check config file");
                cex.printStackTrace();
                System.exit(1);
            }

            IRCCat bot = new IRCCat(c);

            // listen for stuff and send it to irc:
            ServerSocket serverSocket = null;
            InetAddress inet = null;
            try {
                if (bot.getCatIP() != null)
                    inet = InetAddress.getByName(bot.getCatIP());
            } catch (UnknownHostException ex) {
                System.out.println("Could not resolve config cat.ip, fix your config");
                ex.printStackTrace();
                System.exit(2);
            }

            try {
                serverSocket = new ServerSocket(bot.getCatPort(), 0, inet);
            } catch (IOException e) {
                System.err.println("Could not listen on port: " + bot.getCatPort());
                System.exit(1);
            }

            System.out.println("Listening on " + bot.getCatIP() + " : " + bot.getCatPort());

            while (true) {
                try {
                    Socket clientSocket = serverSocket.accept();
                    // System.out.println("Connection on catport from: "
                    // + clientSocket.getInetAddress().toString());
                    CatHandler handler = new CatHandler(clientSocket, bot);
                    handler.start();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    public IRCCat(XMLConfiguration c) throws Exception {
        this.config = c;
        setEncoding("UTF8");
        cmdScript = config.getString("script.cmdhandler");
        maxCmdResponseLines = config.getInt("script.maxresponselines", 26);
        nick = config.getString("bot.nick");
        setName(nick);
        setLogin(nick);
        setMessageDelay(config.getLong("bot.messagedelay", 1000));
        setFinger(config.getString("bot.finger", "IRCCat - a development support bot, used by Last.fm"));

        try {
            // connect to server
            int tries = 0;
            while (!isConnected()) {
                tries++;
                System.out
                        .println("Connecting to server [try " + tries + "]: " + config.getString("server.address"));
                connect(config.getString("server.address"), config.getInt("server.port", 6667),
                        config.getString("server.password", ""));
                if (tries > 1)
                    Thread.sleep(10000);
            }
        } catch (UnknownHostException uhe) {
            // we get stuck here on java.net.UnknownHostException
            // so just exit and let supervisor restart us
            System.err.println(uhe.toString());
            System.err.println(uhe.getMessage());
            System.exit(-1);
        } catch (Exception e) {
            System.err.println(e.toString());
            System.err.println(e.getMessage());
        }

    }

    public String getCmdScript() {
        return cmdScript;
    }

    public int getCmdMaxResponseLines() {
        return maxCmdResponseLines;
    }

    protected void onDisconnect() {
        while (!isConnected()) {
            try {
                reconnect();
            } catch (Exception ex) {
                try {
                    Thread.sleep(10000);
                } catch (InterruptedException e) {
                    break;
                }
            }
        }
    }

    @SuppressWarnings("unchecked")
    protected void onConnect() {

        // join channels
        List<HierarchicalConfiguration> chans = config.configurationsAt("channels.channel");
        for (HierarchicalConfiguration chan : chans) {
            System.out.println("/join #" + chan.getString("name"));
            joinChannel("#" + chan.getString("name") + " " + chan.getString("password", ""));
            // first one in the list considered default:
            if (defaultChannel == null)
                defaultChannel = "#" + chan.getString("name");
        }
        String nickpass = config.getString("server.identify", "");
        if (nickpass != "")
            identify(nickpass);

        System.out.println("Default channel: " + defaultChannel);
    }

    public int getCatPort() {
        return config.getInt("cat.port", 12345);
    }

    public String getCatIP() {
        return config.getString("cat.ip", "127.0.0.1");
    }

    public String getDefaultChannel() {
        return defaultChannel;
    }

    // PM was sent to us on irc
    public void onPrivateMessage(String sender, String login, String hostname, String message) {
        handleMessage(null, sender, message);
    }

    public void changeTopic(String target, String topic) {
        super.setTopic(target, topic);
    }

    public void sendMsg(String t, String m) {
        m = mIRCify(m);
        super.sendMessage(t, m);
    }

    public String mIRCify(String m) {
        Map<String, String> colorReplacementMap = new HashMap<String, String>();
        colorReplacementMap.put("NORMAL", Colors.NORMAL);
        colorReplacementMap.put("BOLD", Colors.BOLD);
        colorReplacementMap.put("UNDERLINE", Colors.UNDERLINE);
        colorReplacementMap.put("REVERSE", Colors.REVERSE);
        colorReplacementMap.put("WHITE", Colors.WHITE);
        colorReplacementMap.put("BLACK", Colors.BLACK);
        colorReplacementMap.put("DBLUE", Colors.DARK_BLUE);
        colorReplacementMap.put("DGREEN", Colors.DARK_GREEN);
        colorReplacementMap.put("RED", Colors.RED);
        colorReplacementMap.put("BROWN", Colors.BROWN);
        colorReplacementMap.put("PURPLE", Colors.PURPLE);
        colorReplacementMap.put("ORANGE", Colors.OLIVE);
        colorReplacementMap.put("YELLOW", Colors.YELLOW);
        colorReplacementMap.put("GREEN", Colors.GREEN);
        colorReplacementMap.put("TEAL", Colors.TEAL);
        colorReplacementMap.put("CYAN", Colors.CYAN);
        colorReplacementMap.put("BLUE", Colors.BLUE);
        colorReplacementMap.put("PINK", Colors.MAGENTA);
        colorReplacementMap.put("DGRAY", Colors.DARK_GRAY);
        colorReplacementMap.put("GRAY", Colors.LIGHT_GRAY);

        for (Map.Entry<String, String> e : colorReplacementMap.entrySet()) {
            // Support #COLOR or %COLOR
            // either format can be confusing, depending on context.
            m = m.replaceAll("%" + e.getKey(), e.getValue());
            m = m.replaceAll("#" + e.getKey(), e.getValue());
        }
        return m;
    }

    // message sent to our channel
    public void onMessage(String channel_, String sender, String login, String hostname, String message) {
        handleMessage(channel_, sender, message);
    }

    public void onPart(String _channel, String _sender, String _login, String _hostname) {
        if (!_sender.equals(nick))
            return;
        // System.out.println("Exiting due to onPart()");
        // System.exit(-1);
    }

    public void onQuit(String _sourceNick, String _sourceLogin, String _sourceHostname, String _reason) {
        if (!_sourceNick.equals(nick))
            return;
        System.out.println("Exiting due to onQuit()");
        System.exit(-1);
    }

    public void onKick(String channel_, String kickerNick, String kickerLogin, String kickerHostname,
            String recipientNick, String reason) {
        if (!recipientNick.equals(nick))
            return;

        // we were kicked
    }

    // is this nick trusted? (are they in the default channel)
    private boolean isTrusted(String n) {
        //return true
        User[] users = getUsers(getDefaultChannel());
        for (int j = 0; j < users.length; j++)
            if (n.equalsIgnoreCase(users[j].getNick()))
                return true;

        return false;
    }

    public void handleMessage(String channel_, String sender, String message) {
        String cmd;
        String respondTo = channel_ == null ? sender : channel_;

        if (message.startsWith(nick)) {
            // someone said something to us.
            // we don't care.
            return;
        }

        if (message.startsWith("!")) {
            if (!isTrusted(sender)) {
                System.out.println("UNTRUSTED (ignoring): [" + respondTo + "] <" + sender + "> " + message);
                return;
            }
            // irccat builtin command processing:
            String resp = handleBuiltInCommand(message.substring(1).trim(), sender);
            if (!(resp == null || resp.equals("")))
                sendMessage(respondTo, resp);

            System.out.println("Built-in: [" + respondTo + "] <" + sender + "> " + message);
            return;
        }

        if (message.startsWith("?")) {
            // external script command.
            cmd = message.substring(1).trim();
        } else {
            // just a normal message which we ignore
            return;
        }

        if (cmd.trim().length() < 1)
            return;

        // if a PM, you gotta be trusted.
        if (channel_ == null && !isTrusted(sender)) {
            System.out.println("UNTRUSTED (ignoring): [" + respondTo + "] <" + sender + "> " + message);
            return;
        }

        // now "cmd" contains the message, minus the address prefix (eg: ?)
        // hand off msg to thread that executes shell script
        System.out.println("Scripter: [" + respondTo + "] <" + sender + "> " + message);
        Thread t = new Scripter(sender, channel_, respondTo, cmd, this);
        t.run();
    }

    /*
     * Basic built-in command processing allows you to instruct the bot at
     * runtime to join/leave channels etc
     */
    protected String handleBuiltInCommand(String cmd, String sender) {
        String toks[] = cmd.split(" ");
        String method = toks[0];

        // JOIN A CHANNEL
        if (method.equals("join") && toks.length >= 2) {
            if (toks.length == 3)
                joinChannel(toks[1], toks[2]);
            else
                joinChannel(toks[1]);

            sendMessage(toks[1], "<" + sender + "> !" + cmd);
            return "Joining: " + toks[1];
        }

        return "";
    }

    public void catTopic(String stuff, String[] recips) {
        for (int ci = 0; ci < recips.length; ci++) {
            changeTopic(recips[ci], stuff);
        }
    }

    public void catStuff(String stuff, String[] recips) {
        for (int ci = 0; ci < recips.length; ci++) {
            sendMsg(recips[ci], stuff);
        }
    }

}