package irc.account; import gui.forms.GUIMain; import irc.IRCBot; import irc.IRCViewer; import lib.pircbot.PircBot; import lib.pircbot.PircBotConnection; import util.settings.Settings; import java.util.ArrayList; import java.util.Timer; import java.util.TimerTask; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedQueue; /** * Created by Nick on 6/12/2014. */ public class AccountManager extends Thread { private ConcurrentLinkedQueue<Task> tasks; private ConcurrentHashMap<String, ReconnectThread> reconnectThreads; private Account userAccount, botAccount; private PircBot viewer, bot; public AccountManager() { reconnectThreads = new ConcurrentHashMap<>(); tasks = new ConcurrentLinkedQueue<>(); userAccount = null; botAccount = null; viewer = null; bot = null; } public void setBotAccount(Account botAccount) { this.botAccount = botAccount; } public void setUserAccount(Account userAccount) { this.userAccount = userAccount; } public Account getBotAccount() { return botAccount; } public Account getUserAccount() { return userAccount; } public synchronized void addTask(Task t) { if (reconnectThreads != null) { if (t.type == Task.Type.CONNECT || t.type == Task.Type.JOIN_CHANNEL || t.type == Task.Type.LEAVE_CHANNEL) { if (t.doer != null && t.doer.getConnection() != null && t.doer.getConnection().getName() != null) { ReconnectThread rt = reconnectThreads.get(t.doer.getConnection().getName()); if (rt != null) { if (t.type != Task.Type.CONNECT) {//since the reconnect thread already handles this... rt.addTask(t); } return; } } } } tasks.add(t); } public synchronized void setViewer(PircBot viewer1) { viewer = viewer1; } public synchronized PircBot getBot() { return bot; } public synchronized PircBot getViewer() { return viewer; } public synchronized void setBot(PircBot bot1) { bot = bot1; } @Override public void run() {//handle connection status while (!GUIMain.shutDown) { Task t = tasks.poll(); if (t != null) { switch (t.type) { case CREATE_BOT_ACCOUNT: GUIMain.bot = new IRCBot(); PircBot bot = new PircBot(GUIMain.bot); bot.setNick(getBotAccount().getName()); bot.setPassword(getBotAccount().getOAuth().getKey()); bot.setMessageDelay(1500); setBot(bot); addTask(new Task(getBot(), Task.Type.CONNECT, "Loaded Bot: " + getBotAccount().getName() + "!")); break; case CREATE_VIEWER_ACCOUNT: GUIMain.viewer = new IRCViewer(); PircBot viewer = new PircBot(GUIMain.viewer); viewer.setVerbose(true);//TODO remove this viewer.setNick(getUserAccount().getName()); viewer.setPassword(getUserAccount().getOAuth().getKey()); setViewer(viewer); addTask(new Task(getViewer(), Task.Type.CONNECT, "Loaded User: " + getUserAccount().getName() + "!")); break; case DISCONNECT: if (t.doer != null) { if (t.doer.getConnection() != null) { ReconnectThread potential = reconnectThreads.get(t.doer.getConnection().getName()); if (potential != null) { potential.t.cancel(); reconnectThreads.remove(t.doer.getNick()); } } t.doer.disconnect(); t.doer.dispose(); } break; case JOIN_CHANNEL: if (t.doer != null) { if (t.doer.isConnected()) { String channel = (String) t.message; if (!channel.startsWith("#")) channel = "#" + channel; t.doer.joinChannel(channel); } else { createReconnectThread(t.doer.getConnection()); addTask(t);//loops back around, adds to the reconnect thread } } break; case CONNECT: if (t.doer.connect()) { GUIMain.log(t.message); } else { if (!t.doer.isConnected()) { createReconnectThread(t.doer.getConnection()); } } break; case LEAVE_CHANNEL: if (t.doer != null) { if (t.doer.isConnected()) { String chaan = (String) t.message; if (!chaan.startsWith("#")) chaan = "#" + chaan; t.doer.partChannel(chaan); } else { createReconnectThread(t.doer.getConnection()); addTask(t);//loops back around, adds to the reconnect thread } } break; default: break; } } } } public void createReconnectThread(PircBotConnection connection) { try { if (!Settings.autoReconnectAccounts.getValue()) { GUIMain.logCurrent("Auto-reconnects disabled, please check Preferences -> Auto-Reconnect!"); return; } if (connection == null) return; if (reconnectThreads.containsKey(connection.getName())) return; ReconnectThread rt = new ReconnectThread(connection); rt.start(); reconnectThreads.put(connection.getName(), rt); GUIMain.logCurrent("Attempting to reconnect the account: " + connection.getBot().getNick() + " ..."); } catch (Exception e) { GUIMain.log(e); } } private class ReconnectThread { private PircBotConnection connection; private ArrayList<Task> cachedTasks; private Timer t; ReconnectThread(PircBotConnection toReconnect) { connection = toReconnect; cachedTasks = new ArrayList<>(); t = new Timer(); } public void start() { TimerTask task = new TimerTask() { @Override public void run() { if (connection.connect()) { reconnectThreads.remove(connection.getName()); cachedTasks.forEach(Settings.accountManager::addTask); GUIMain.logCurrent("Successfully reconnected the account: " + connection.getBot().getNick() + " !"); t.cancel(); } } }; t.scheduleAtFixedRate(task, 10000L, 10000L); } public void addTask(Task t) { cachedTasks.add(t); } } }