import java.io.File;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import org.pircbotx.Colors;
import org.pircbotx.DccChat;
import org.pircbotx.DccManager;
import org.pircbotx.PircBotX;
import org.pircbotx.ShockyBot;
import org.pircbotx.User;
import org.pircbotx.hooks.events.IncomingChatRequestEvent;
import pl.shockah.shocky.Data;
import pl.shockah.shocky.Module;
import pl.shockah.shocky.Shocky;
import pl.shockah.shocky.interfaces.ILogger;
import pl.shockah.shocky.sql.SQL;
public class ModuleDCC extends Module {
public static interface ProgramFactory {
Program start(DccChat chat);
}
public Map<String,ProgramFactory> programs = new HashMap<String,ProgramFactory>();
private List<Session> sessions = new LinkedList<Session>();
@Override
public boolean isListener() {return true;}
@Override
public String name() {return "dcc";}
@Override
public void onEnable(File dir) {
programs.put("logger", new LoggerFactory());
programs.put("sql", new SQLFactory());
}
@Override
public void onDisable() {
synchronized(sessions) {
if (!sessions.isEmpty()) {
Iterator<Session> iter = sessions.iterator();
while(iter.hasNext()) {
DccChat chat = iter.next().chat;
try {chat.close();} catch (IOException e) {}
iter.remove();
}
}
}
programs.clear();
}
public static boolean isController(PircBotX bot, User user) {
if (bot.getInetAddress().isLoopbackAddress()) return true;
if (Shocky.getLogin(user) == null) return false;
return Data.controllers.contains(Shocky.getLogin(user));
}
@Override
public void onIncomingChatRequest(IncomingChatRequestEvent<ShockyBot> event)
throws Exception {
DccChat chat = event.getChat();
if (!isController(event.getBot(),chat.getUser()))
return;
Session session = new Session(event.getBot().getDccManager(),chat);
new Thread(session,"DCC - "+chat.getUser().getNick()).start();
}
public class Session extends Program {
private final DccManager manager;
public Session(DccManager manager, DccChat chat) {
super(chat);
this.manager = manager;
}
@Override
public String name() {return "dcc session";}
@Override
public void run() {
try {
chat.accept();
synchronized(sessions) {
sessions.add(this);
}
super.run();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (manager.getAllChats().contains(chat))
chat.close();
} catch (IOException e) {
}
synchronized(sessions) {
sessions.remove(this);
}
}
}
@Override
public boolean handleLine(String line) throws IOException {
StringTokenizer tokenizer = new StringTokenizer(line);
String cmd = tokenizer.nextToken();
if (cmd.contentEquals("run") && tokenizer.hasMoreTokens()) {
String run = tokenizer.nextToken();
if (programs.containsKey(run)) {
ProgramFactory factory = programs.get(run);
Program program = factory.start(chat);
program.onStart();
program.run();
}
} else if (cmd.contentEquals("help")) {
chat.sendLine("Commands available: run, help");
StringBuilder sb = new StringBuilder("Programs available: ");
List<String> names = new LinkedList<String>(programs.keySet());
Collections.sort(names);
Iterator<String> iter = names.iterator();
int i = 0;
while(iter.hasNext()) {
if (i++ > 0)
sb.append(", ");
sb.append(iter.next());
}
chat.sendLine(sb.toString());
}
return true;
}
}
public static abstract class Program implements Runnable {
public final DccChat chat;
public Program(DccChat chat) {
this.chat = chat;
}
public abstract String name();
public abstract boolean handleLine(String line) throws IOException;
public void onStart() throws IOException {
chat.sendLine("\1ACTION is starting "+name()+'\1');
}
public void onStop() throws IOException {
chat.sendLine("\1ACTION is stopping "+name()+'\1');
}
@Override
public void run() {
try {
String line;
while((line = chat.readLine()) != null) {
if (line.contentEquals("exit"))
break;
if (line.contentEquals("quit"))
break;
if (!handleLine(line))
break;
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {onStop();} catch (IOException e) {}
}
}
}
public static class LoggerFactory implements ProgramFactory {
@Override
public Logger start(DccChat chat) {
return new Logger(chat);
}
}
public static class Logger extends Program implements ILogger {
public String name() {return "logger";}
public Logger(DccChat chat) {
super(chat);
}
@Override
public void onStart() throws IOException {
super.onStart();
ShockyBot.addLogger(this);
}
@Override
public void onStop() throws IOException {
ShockyBot.removeLogger(this);
super.onStop();
}
@Override
public boolean handleLine(String line) throws IOException {
return true;
}
@Override
public void log(String line) throws IOException {
chat.sendLine(line);
}
}
public static class SQLFactory implements ProgramFactory {
@Override
public SQLConsole start(DccChat chat) {
return new SQLConsole(chat);
}
}
public static class SQLConsole extends Program {
private Connection connection;
public String name() {return "sql";}
public SQLConsole(DccChat chat) {
super(chat);
connection = SQL.getSQLConnection();
}
@Override
public boolean handleLine(String line) throws IOException {
try {
handleSQL(line);
} catch (SQLException e) {
chat.sendLine(e.getMessage());
}
return true;
}
private void handleSQL(String line) throws SQLException, IOException {
PreparedStatement statement = null;
ResultSet set = null;
try {
statement = connection.prepareStatement(line);
if (!statement.execute())
{
chat.sendLine("Total rows affected: "+statement.getUpdateCount());
return;
}
ResultSetMetaData metadata = statement.getMetaData();
int columns = metadata.getColumnCount();
StringBuilder sb = new StringBuilder();
sb.append(Colors.UNDERLINE);
for (int i = 1; i <= columns; ++i) {
if (i!=1)
sb.append('|');
sb.append(metadata.getColumnName(i));
}
sb.append(Colors.UNDERLINE);
chat.sendLine(sb.toString());
set = statement.getResultSet();
while(set.next()) {
sb = new StringBuilder();
for (int i = 1; i <= columns; ++i) {
if (i!=1)
sb.append('|');
sb.append(set.getObject(i));
}
chat.sendLine(sb.toString());
}
} finally {
if (set != null && !set.isClosed())
set.close();
if (statement != null && !statement.isClosed())
statement.close();
}
}
}
}