/* CloudBot 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. Foobar 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 Foobar. If not, see <http://www.gnu.org/licenses/>. */ package de.kroesch.clt.net; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; import java.util.ArrayDeque; import java.util.Properties; import java.util.Queue; import javax.management.relation.Role; import org.jibble.pircbot.DccFileTransfer; import org.jibble.pircbot.IrcException; import org.jibble.pircbot.NickAlreadyInUseException; import org.jibble.pircbot.PircBot; import de.kroesch.clt.Environment; import de.kroesch.clt.InternalEnvironment; import de.kroesch.clt.Parser; import de.kroesch.clt.internal.Get; import de.kroesch.clt.internal.Internal; import de.kroesch.clt.security.AuthCommand; import de.kroesch.clt.security.Authority; /** * Implementation of an IRC bot infrastructure. * * The behaviour is as follows: * * * Bot connects to the IRC host specified in ''.console.properties'' * * Bot ignores any messages from users other than botmaster. The latter are executed silently. * * When invited to a private chat, the bot answers to commands, i.e. sends output as message back. * * @author Karsten Kroesch <karsten@kroesch.de> */ public class CloudBot extends PircBot implements InternalEnvironment { private final String BOTMASTER_USER = "botmaster"; private final Properties properties; private final Parser parser; private final Queue<Runnable> commandStack = new ArrayDeque<Runnable>(); private String lastErrorMessage = "OK"; private PrintWriter writer; private StringWriter messageWriter; private Authority authority = new Authority(); public CloudBot() throws NickAlreadyInUseException, IOException, IrcException { parser = new Parser(this); properties = new Properties(); properties.load(new FileReader(".console.properties")); messageWriter = new StringWriter(); writer = new PrintWriter(messageWriter); setVerbose(true); setName(NickNameGenerator.generate()); String botmaster = properties.getProperty("botmaster.host"); System.out.println("Connecting to " + botmaster); connect(botmaster); joinChannel("#botnet"); sendMessage("#botnet", String.format("CloudBot/%s - Up and running", Environment.VERSION)); } /** * Handle private messages. Sends answer output to sender. */ @Override protected void onPrivateMessage(String sender, String login, String hostname, String message) { if (!BOTMASTER_USER.equals(sender)) return; execute(message); writer.flush(); StringBuffer messageBuffer = messageWriter.getBuffer(); if (!"OK".equals(lastErrorMessage)) { messageBuffer.append("? "); messageBuffer.append(lastErrorMessage); } String convertMessage = messageBuffer.toString().replace("\n", " // ") .replace("\t", " "); sendMessage("botmaster", convertMessage); messageBuffer.delete(0, messageBuffer.length()); } /** * Handles incoming messages from botmaster. Does not answer. */ @Override public void onMessage(String channel, String sender, String login, String hostname, String message) { if (!"botmaster".equals(sender)) return; execute(message); writer.flush(); StringBuffer messageBuffer = messageWriter.getBuffer(); messageBuffer.delete(0, messageBuffer.length()); } /* * Common functionality for incoming messages */ private void execute(String message) { Runnable consoleCommand = parser.parseCommand(message); if (!(consoleCommand instanceof Internal)) commandStack.add(consoleCommand); try { if (consoleCommand instanceof AuthCommand) { AuthCommand cmd = (AuthCommand) consoleCommand; if (!authority.authorize(cmd)) throw new SecurityException("Not authorized."); } consoleCommand.run(); lastErrorMessage = "OK"; } catch (Exception ex) { lastErrorMessage = ex.getMessage(); } } /** * Handles file uploads. * * Scripts go to work directory, JARs go to plugins directory. */ @Override protected void onIncomingFileTransfer(DccFileTransfer transfer) { File incoming = transfer.getFile(); File toSave; if (incoming.getName().endsWith(".jar")) { toSave = new File("plugins/" + incoming.getName()); } else { toSave = new File(incoming.getName()); } transfer.receive(toSave, true); } public PrintWriter writer() { return writer; } public String get(String key) { return properties.getProperty(key); } public void set(String key, String value) { properties.setProperty(key, value); } public Queue<Runnable> history() { return commandStack; } public String lastError() { return lastErrorMessage; } public void setLastErrorMessage(String message) { this.lastErrorMessage = message; } public Properties getProperties() { return properties; } public Parser parser() { return parser; } public String expect(String question, String choices) { throw new UnsupportedOperationException("Does not work in Bot mode"); } public static void main(String[] args) throws Exception { CloudBot bot = new CloudBot(); } public Authority authority() { return authority; } }