fmt: Source Formatting
authorBenny Baumann <BenBE@geshi.org>
Tue, 24 Nov 2015 21:54:47 +0000 (22:54 +0100)
committerBenny Baumann <BenBE@geshi.org>
Tue, 24 Nov 2015 22:07:44 +0000 (23:07 +0100)
src/org/cacert/votebot/CAcertVoteAuditor.java
src/org/cacert/votebot/CAcertVoteBot.java
src/org/cacert/votebot/CAcertVoteMechanics.java
src/org/cacert/votebot/IRCBot.java
src/org/cacert/votebot/IRCClient.java

index 9e1a564..95fc87d 100644 (file)
@@ -8,92 +8,102 @@ import java.util.regex.Pattern;
 import org.cacert.votebot.CAcertVoteMechanics.VoteType;
 
 public class CAcertVoteAuditor extends IRCBot {
-       public CAcertVoteAuditor(IRCClient c, String toAudit) {
-               super(c);
-               this.toAudit = toAudit;
-               c.join(voteAuxChn);
-       }
-
-       String voteAuxChn = System.getProperty("auditor.target.voteChn", "vote");
-       String toAudit;
-
-       long warn = Long.parseLong(System.getProperty("voteBot.warnSecs", "90"));
-       long timeout = Long.parseLong(System.getProperty("voteBot.timeoutSecs",
-                       "120"));
-
-       CAcertVoteMechanics mech = new CAcertVoteMechanics();
-
-       String[] capturedResults = new String[VoteType.values().length];
-       int ctr = -1;
-
-       @Override
-       public synchronized void publicMessage(String from, String channel,
-                       String message) {
-               if (channel.equals(voteAuxChn)) {
-                       if (from.equals(toAudit)) {
-                               if (ctr >= 0) {
-                                       capturedResults[ctr++] = message;
-                                       if (ctr == capturedResults.length) {
-                                               String[] reals = mech.closeVote();
-                                               if (Arrays.equals(reals, capturedResults)) {
-                                                       System.out
-                                                                       .println("Audit for vote was successful.");
-                                               } else {
-                                                       System.out
-                                                                       .println("Audit failed! Vote Bot (or Auditor) is probably broken.");
-                                               }
-                                               ctr = -1;
-                                       }
-                                       return;
-                               }
-                               if (message.startsWith("New Vote: ")) {
-                                       System.out.println("detected vote-start");
-                                       Pattern p = Pattern
-                                                       .compile("New Vote: (.*) has started a vote on \"(.*)\"");
-                                       Matcher m = p.matcher(message);
-                                       if (!m.matches()) {
-                                               System.out.println("error: vote-start malformed");
-                                               return;
-                                       }
-                                       mech.callVote(m.group(1), m.group(2));
-                               } else if (message.startsWith("Results: ")) {
-                                       System.out.println("detected vote-end. Reading results");
-                                       ctr = 0;
-                               }
-                       } else {
-                               if (ctr != -1) {
-                                       System.out.println("Vote after end.");
-                                       return;
-                               }
-                               System.out.println("detected vote");
-                               mech.evaluateVote(from, message);
-                               System.out.println("Current state: " + mech.getCurrentResult());
-                       }
-               }
-       }
-       @Override
-       public synchronized void privateMessage(String from, String message) {
-
-       }
-       @Override
-       public synchronized void join(String cleanReferent, String chn) {
-
-       }
-
-       @Override
-       public synchronized void part(String cleanReferent, String chn) {
-
-       }
-
-       public static void main(String[] args) throws IOException,
-                       InterruptedException {
-               IRCClient ic = IRCClient.parseCommandLine(args, "dogcraft_de-Auditor");
-               String targetNick = System.getProperty("auditor.target.nick");
-               if (targetNick == null) {
-                       System.out
-                                       .println("use -Dauditor.target.nick=TargetNick to set a target nick");
-                       System.exit(0);
-               }
-               ic.setBot(new CAcertVoteAuditor(ic, targetNick));
-       }
+
+    public CAcertVoteAuditor(IRCClient c, String toAudit) {
+        super(c);
+        this.toAudit = toAudit;
+        c.join(voteAuxChn);
+    }
+
+    String voteAuxChn = System.getProperty("auditor.target.voteChn", "vote");
+
+    String toAudit;
+
+    long warn = Long.parseLong(System.getProperty("voteBot.warnSecs", "90"));
+
+    long timeout = Long.parseLong(System.getProperty("voteBot.timeoutSecs", "120"));
+
+    CAcertVoteMechanics mech = new CAcertVoteMechanics();
+
+    String[] capturedResults = new String[VoteType.values().length];
+
+    int ctr = -1;
+
+    @Override
+    public synchronized void publicMessage(String from, String channel, String message) {
+        if (channel.equals(voteAuxChn)) {
+            if (from.equals(toAudit)) {
+                if (ctr >= 0) {
+                    capturedResults[ctr++] = message;
+
+                    if (ctr == capturedResults.length) {
+                        String[] reals = mech.closeVote();
+
+                        if (Arrays.equals(reals, capturedResults)) {
+                            System.out.println("Audit for vote was successful.");
+                        } else {
+                            System.out.println("Audit failed! Vote Bot (or Auditor) is probably broken.");
+                        }
+
+                        ctr = -1;
+                    }
+
+                    return;
+                }
+                if (message.startsWith("New Vote: ")) {
+                    System.out.println("detected vote-start");
+
+                    Pattern p = Pattern.compile("New Vote: (.*) has started a vote on \"(.*)\"");
+                    Matcher m = p.matcher(message);
+
+                    if ( !m.matches()) {
+                        System.out.println("error: vote-start malformed");
+                        return;
+                    }
+
+                    mech.callVote(m.group(1), m.group(2));
+                } else if (message.startsWith("Results: ")) {
+                    System.out.println("detected vote-end. Reading results");
+
+                    ctr = 0;
+                }
+            } else {
+                if (ctr != -1) {
+                    System.out.println("Vote after end.");
+                    return;
+                }
+
+                System.out.println("detected vote");
+                mech.evaluateVote(from, message);
+                System.out.println("Current state: " + mech.getCurrentResult());
+            }
+        }
+    }
+
+    @Override
+    public synchronized void privateMessage(String from, String message) {
+
+    }
+
+    @Override
+    public synchronized void join(String cleanReferent, String chn) {
+
+    }
+
+    @Override
+    public synchronized void part(String cleanReferent, String chn) {
+
+    }
+
+    public static void main(String[] args) throws IOException, InterruptedException {
+        IRCClient ic = IRCClient.parseCommandLine(args, "dogcraft_de-Auditor");
+        String targetNick = System.getProperty("auditor.target.nick");
+
+        if (targetNick == null) {
+            System.out.println("use -Dauditor.target.nick=TargetNick to set a target nick");
+            System.exit(0);
+        }
+
+        ic.setBot(new CAcertVoteAuditor(ic, targetNick));
+    }
 }
index 7a66eae..94c2f2d 100644 (file)
@@ -5,82 +5,90 @@ import java.io.IOException;
 import org.cacert.votebot.CAcertVoteMechanics.State;
 
 public class CAcertVoteBot extends IRCBot implements Runnable {
-       public CAcertVoteBot(IRCClient c) {
-               super(c);
-               c.join(meetingChn);
-               c.join(voteAuxChn);
-               new Thread(this).start();
-       }
-
-       String meetingChn = System.getProperty("voteBot.meetingChn", "agm");
-       String voteAuxChn = System.getProperty("voteBot.voteChn", "vote");
-
-       long warn = Long.parseLong(System.getProperty("voteBot.warnSecs", "90"));
-       long timeout = Long.parseLong(System.getProperty("voteBot.timeoutSecs",
-                       "120"));
-
-       CAcertVoteMechanics mech = new CAcertVoteMechanics();
-
-       @Override
-       public synchronized void publicMessage(String from, String channel,
-                       String message) {
-               if (channel.equals(voteAuxChn)) {
-                       sendPublicMessage(voteAuxChn, mech.evaluateVote(from, message));
-               }
-       }
-       @Override
-       public synchronized void privateMessage(String from, String message) {
-               if (message.startsWith("vote ")) {
-                       String response = mech.callVote(from, message.substring(5));
-                       sendPrivateMessage(from, response);
-                       if (response.startsWith("Sorry,")) {
-                               return;
-                       }
-                       anounce("New Vote: " + from + " has started a vote on \""
-                                       + mech.getTopic() + "\"");
-                       sendPublicMessage(meetingChn, "Please cast your vote in #vote");
-                       sendPublicMessage(voteAuxChn, "Please cast your vote in the next "
-                                       + timeout + " seconds.");
-               }
-       }
-       private synchronized void anounce(String msg) {
-               sendPublicMessage(meetingChn, msg);
-               sendPublicMessage(voteAuxChn, msg);
-       }
-       public void run() {
-               try {
-                       while (true) {
-                               while (mech.getState() == State.IDLE) {
-                                       Thread.sleep(1000);
-                               }
-                               Thread.sleep(warn * 1000);
-                               anounce("Voting on " + mech.getTopic() + " will end in "
-                                               + (timeout - warn) + " seconds.");
-                               Thread.sleep((timeout - warn) * 1000);
-                               anounce("Voting on " + mech.getTopic() + " has closed.");
-                               String[] res = mech.closeVote();
-                               anounce("Results: for " + mech.getTopic() + ":");
-                               for (int i = 0; i < res.length; i++) {
-                                       anounce(res[i]);
-                               }
-                       }
-               } catch (InterruptedException e) {
-                       e.printStackTrace();
-               }
-       }
-
-       @Override
-       public synchronized void join(String cleanReferent, String chn) {
-
-       }
-
-       @Override
-       public synchronized void part(String cleanReferent, String chn) {
-
-       }
-       public static void main(String[] args) throws IOException,
-                       InterruptedException {
-               IRCClient ic = IRCClient.parseCommandLine(args, "dogcraft_de");
-               ic.setBot(new CAcertVoteBot(ic));
-       }
+
+    public CAcertVoteBot(IRCClient c) {
+        super(c);
+
+        c.join(meetingChn);
+        c.join(voteAuxChn);
+
+        new Thread(this).start();
+    }
+
+    String meetingChn = System.getProperty("voteBot.meetingChn", "agm");
+
+    String voteAuxChn = System.getProperty("voteBot.voteChn", "vote");
+
+    long warn = Long.parseLong(System.getProperty("voteBot.warnSecs", "90"));
+
+    long timeout = Long.parseLong(System.getProperty("voteBot.timeoutSecs", "120"));
+
+    CAcertVoteMechanics mech = new CAcertVoteMechanics();
+
+    @Override
+    public synchronized void publicMessage(String from, String channel, String message) {
+        if (channel.equals(voteAuxChn)) {
+            sendPublicMessage(voteAuxChn, mech.evaluateVote(from, message));
+        }
+    }
+
+    @Override
+    public synchronized void privateMessage(String from, String message) {
+        if (message.startsWith("vote ")) {
+            String response = mech.callVote(from, message.substring(5));
+            sendPrivateMessage(from, response);
+
+            if (response.startsWith("Sorry,")) {
+                return;
+            }
+
+            anounce("New Vote: " + from + " has started a vote on \"" + mech.getTopic() + "\"");
+            sendPublicMessage(meetingChn, "Please cast your vote in #vote");
+            sendPublicMessage(voteAuxChn, "Please cast your vote in the next " + timeout + " seconds.");
+        }
+    }
+
+    private synchronized void anounce(String msg) {
+        sendPublicMessage(meetingChn, msg);
+        sendPublicMessage(voteAuxChn, msg);
+    }
+
+    public void run() {
+        try {
+            while (true) {
+                while (mech.getState() == State.IDLE) {
+                    Thread.sleep(1000);
+                }
+
+                Thread.sleep(warn * 1000);
+                anounce("Voting on " + mech.getTopic() + " will end in " + (timeout - warn) + " seconds.");
+                Thread.sleep((timeout - warn) * 1000);
+                anounce("Voting on " + mech.getTopic() + " has closed.");
+                String[] res = mech.closeVote();
+                anounce("Results: for " + mech.getTopic() + ":");
+
+                for (int i = 0; i < res.length; i++) {
+                    anounce(res[i]);
+                }
+            }
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+        }
+    }
+
+    @Override
+    public synchronized void join(String cleanReferent, String chn) {
+
+    }
+
+    @Override
+    public synchronized void part(String cleanReferent, String chn) {
+
+    }
+
+    public static void main(String[] args) throws IOException, InterruptedException {
+        IRCClient ic = IRCClient.parseCommandLine(args, "dogcraft_de");
+        ic.setBot(new CAcertVoteBot(ic));
+    }
+
 }
index 926dd85..8f24541 100644 (file)
@@ -5,149 +5,167 @@ import java.util.Map.Entry;
 
 /**
  * Reprenents the voting-automata for voting in IRC chanenls.
- *
  */
 public class CAcertVoteMechanics {
-       public enum VoteType {
-               AYE, NAYE, ABSTAIN
-       }
-       public enum State {
-               RUNNING, IDLE
-       }
-       State state = State.IDLE;
-
-       String voteCaller;
-       String topic;
-
-       private String vote(String voter, String actor, VoteType type) {
-               votes.put(voter, type);
-               if (voter.equals(actor)) {
-                       return "Thanks " + actor + " I count your vote as " + type;
-               } else {
-                       return "Thanks " + actor + " I count your vote for " + voter
-                                       + " as " + type;
-               }
-       }
-       HashMap<String, VoteType> votes = new HashMap<>();
-
-       private String voteError(String actor) {
-               return "Sorry "
-                               + actor
-                               + ", I did not understand your vote, your current vote state remains unchanged!";
-       }
-
-       /**
-        * Adds a vote to the current topic. This interprets proxies.
-        * 
-        * @param actor
-        *            the person that sent this vote
-        * @param txt
-        *            the text that the person sent.
-        * @return A message to
-        * 
-        *         <pre>
-        * actor
-        * </pre>
-        * 
-        *         indicating tha result of his action.
-        */
-       public synchronized String evaluateVote(String actor, String txt) {
-               if (state != State.RUNNING) {
-                       return "Sorry " + actor + ", but currently no vote is running.";
-               }
-
-               String voter = actor;
-               String value = null;
-               if (txt.toLowerCase().matches("^\\s*proxy\\s.*")) {
-                       String[] parts = txt.split("\\s+");
-                       if (parts.length == 3) {
-                               voter = parts[1];
-                               value = parts[2];
-                       }
-               } else {
-                       value = txt.replaceAll("^\\s*|\\s*$", "");
-               }
-               if (value == null) {
-                       return voteError(actor);
-               } else {
-                       value = value.toLowerCase();
-                       switch (value) {
-                               case "aye" :
-                               case "yes" :
-                               case "oui" :
-                               case "ja" : {
-                                       return vote(voter, actor, VoteType.AYE);
-                               }
-                               case "naye" :
-                               case "nay" :
-                               case "no" :
-                               case "non" :
-                               case "nein" : {
-                                       return vote(voter, actor, VoteType.NAYE);
-                               }
-                               case "abstain" :
-                               case "enthaltung" :
-                               case "enthalten" :
-                               case "abs" : {
-                                       return vote(voter, actor, VoteType.ABSTAIN);
-                               }
-                       }
-               }
-               return voteError(actor);
-       }
-       /**
-        * A new vote begins.
-        * 
-        * @param from
-        *            the nick that called the vote
-        * @param topic
-        *            the topic of the vote
-        * @return A response to
-        * 
-        *         <pre>
-        * from
-        * </pre>
-        * 
-        *         indicating success or failure.
-        */
-       public synchronized String callVote(String from, String topic) {
-               if (state != State.IDLE) {
-                       return "Sorry, a vote is already running";
-               }
-               voteCaller = from;
-               this.topic = topic;
-               votes.clear();
-
-               state = State.RUNNING;
-               return "Vote started.";
-       }
-       /**
-        * Ends a vote.
-        * 
-        * @return An array of Strings containing result status messages.
-        */
-       public synchronized String[] closeVote() {
-               int[] res = new int[VoteType.values().length];
-               for (Entry<String, VoteType> i : votes.entrySet()) {
-                       res[i.getValue().ordinal()]++;
-               }
-               String[] results = new String[VoteType.values().length];
-               for (int i = 0; i < res.length; i++) {
-                       results[i] = (VoteType.values()[i] + ": " + res[i]);
-               }
-               votes.clear();
-               voteCaller = null;
-               state = State.IDLE;
-               return results;
-       }
-       public String getTopic() {
-               return topic;
-       }
-       public State getState() {
-               return state;
-       }
-       public String getCurrentResult() {
-               return votes.toString();
-       }
+
+    public enum VoteType {
+        AYE, NAYE, ABSTAIN
+    }
+
+    public enum State {
+        RUNNING, IDLE
+    }
+
+    State state = State.IDLE;
+
+    String voteCaller;
+
+    String topic;
+
+    private String vote(String voter, String actor, VoteType type) {
+        votes.put(voter, type);
+
+        if (voter.equals(actor)) {
+            return "Thanks " + actor + " I count your vote as " + type;
+        } else {
+            return "Thanks " + actor + " I count your vote for " + voter + " as " + type;
+        }
+    }
+
+    HashMap<String, VoteType> votes = new HashMap<>();
+
+    private String voteError(String actor) {
+        return "Sorry " + actor + ", I did not understand your vote, your current vote state remains unchanged!";
+    }
+
+    /**
+     * Adds a vote to the current topic. This interprets proxies.
+     *
+     * @param actor
+     *            the person that sent this vote
+     * @param txt
+     *            the text that the person sent.
+     * @return A message to
+     *
+     *         <pre>
+     * actor
+     * </pre>
+     *
+     *         indicating tha result of his action.
+     */
+    public synchronized String evaluateVote(String actor, String txt) {
+        if (state != State.RUNNING) {
+            return "Sorry " + actor + ", but currently no vote is running.";
+        }
+
+        String voter = actor;
+        String value = null;
+
+        if (txt.toLowerCase().matches("^\\s*proxy\\s.*")) {
+            String[] parts = txt.split("\\s+");
+            if (parts.length == 3) {
+                voter = parts[1];
+                value = parts[2];
+            }
+        } else {
+            value = txt.replaceAll("^\\s*|\\s*$", "");
+        }
+
+        if (value == null) {
+            return voteError(actor);
+        } else {
+            value = value.toLowerCase();
+
+            switch (value) {
+            case "aye":
+            case "yes":
+            case "oui":
+            case "ja": {
+                return vote(voter, actor, VoteType.AYE);
+            }
+            case "naye":
+            case "nay":
+            case "no":
+            case "non":
+            case "nein": {
+                return vote(voter, actor, VoteType.NAYE);
+            }
+            case "abstain":
+            case "enthaltung":
+            case "enthalten":
+            case "abs": {
+                return vote(voter, actor, VoteType.ABSTAIN);
+            }
+            }
+        }
+
+        return voteError(actor);
+    }
+
+    /**
+     * A new vote begins.
+     * 
+     * @param from
+     *            the nick that called the vote
+     * @param topic
+     *            the topic of the vote
+     * @return A response to
+     * 
+     *         <pre>
+     * from
+     * </pre>
+     * 
+     *         indicating success or failure.
+     */
+    public synchronized String callVote(String from, String topic) {
+        if (state != State.IDLE) {
+            return "Sorry, a vote is already running";
+        }
+
+        voteCaller = from;
+        this.topic = topic;
+        votes.clear();
+
+        state = State.RUNNING;
+
+        return "Vote started.";
+    }
+
+    /**
+     * Ends a vote.
+     * 
+     * @return An array of Strings containing result status messages.
+     */
+    public synchronized String[] closeVote() {
+        int[] res = new int[VoteType.values().length];
+
+        for (Entry<String, VoteType> i : votes.entrySet()) {
+            res[i.getValue().ordinal()]++;
+        }
+
+        String[] results = new String[VoteType.values().length];
+
+        for (int i = 0; i < res.length; i++) {
+            results[i] = (VoteType.values()[i] + ": " + res[i]);
+        }
+
+        votes.clear();
+        voteCaller = null;
+        state = State.IDLE;
+
+        return results;
+    }
+
+    public String getTopic() {
+        return topic;
+    }
+
+    public State getState() {
+        return state;
+    }
+
+    public String getCurrentResult() {
+        return votes.toString();
+    }
 
 }
index d5387c5..2fe40ad 100644 (file)
@@ -1,21 +1,28 @@
 package org.cacert.votebot;
 
 public abstract class IRCBot {
-       private IRCClient c;
-
-       public IRCBot(IRCClient c) {
-               this.c = c;
-       }
-       public abstract void publicMessage(String from, String channel,
-                       String message);
-       public abstract void privateMessage(String from, String message);
-
-       public void sendPublicMessage(String channel, String message) {
-               c.send(message, channel);
-       }
-       public void sendPrivateMessage(String to, String message) {
-               c.sendPrivate(message, to);
-       }
-       public abstract void part(String cleanReferent, String chn);
-       public abstract void join(String cleanReferent, String chn);
+
+    private IRCClient c;
+
+    public IRCBot(IRCClient c) {
+        this.c = c;
+    }
+
+    public abstract void publicMessage(String from, String channel,
+            String message);
+
+    public abstract void privateMessage(String from, String message);
+
+    public void sendPublicMessage(String channel, String message) {
+        c.send(message, channel);
+    }
+
+    public void sendPrivateMessage(String to, String message) {
+        c.sendPrivate(message, to);
+    }
+
+    public abstract void part(String cleanReferent, String chn);
+
+    public abstract void join(String cleanReferent, String chn);
+
 }
index 3206fc4..6f1d7a5 100644 (file)
@@ -13,210 +13,252 @@ import java.util.concurrent.Semaphore;
 import javax.net.ssl.SSLSocketFactory;
 
 public class IRCClient {
-       private Semaphore loggedin = new Semaphore(0);
-       private PrintWriter out;
-       private Socket s;
-       private String nick;
-       class ServerReader implements Runnable {
-               private BufferedReader br;
-
-               public ServerReader(BufferedReader br) {
-                       this.br = br;
-                       new Thread(this).start();
-               }
-               @Override
-               public void run() {
-                       String l;
-                       try {
-                               while ((l = br.readLine()) != null) {
-                                       String fullline = l;
-                                       //System.out.println(l);
-                                       if (l.startsWith("PING ")) {
-                                               System.out.println("PONG");
-                                               out.println("PONG " + l.substring(5));
-                                       }
-                                       String referent = "";
-                                       if (l.startsWith(":")) {
-                                               String[] parts = l.split(" ", 2);
-                                               referent = parts[0];
-                                               l = parts[1];
-                                       }
-                                       String[] command = l.split(" ", 3);
-                                       if (command[0].equals("001")) {
-                                               loggedin.release();
-                                       }
-                                       if (command[0].equals("PRIVMSG")) {
-                                               String msg = command[2].substring(1);
-                                               String chnl = command[1];
-                                               if (!chnl.startsWith("#")) {
-                                                       handlePrivMsg(referent, msg);
-                                               } else {
-                                                       handleMsg(referent, chnl, msg);
-                                               }
-                                               log(chnl, fullline);
-                                       } else if (command[0].equals("JOIN")) {
-                                               String chn = command[1].substring(1);
-                                               targetBot.join(cleanReferent(referent),
-                                                               chn.substring(1));
-                                               log(chn, fullline);
-                                       } else if (command[0].equals("PART")) {
-                                               String chn = command[1];
-                                               targetBot.part(cleanReferent(referent), chn);
-                                               log(chn, fullline);
-                                       } else {
-                                               System.out.println("unknown line: ");
-                                               System.out.println(l);
-                                       }
-                               }
-                       } catch (IOException e) {
-                               e.printStackTrace();
-                       }
-
-               }
-               private String cleanReferent(String referent) {
-                       String[] parts = referent.split("!");
-                       if (!parts[0].startsWith(":")) {
-                               System.err.println("invalid public message");
-                               return "unknown";
-                       }
-
-                       return parts[0];
-               }
-               HashMap<String, PrintWriter> logs = new HashMap<String, PrintWriter>();
-
-               private void log(String chn, String l) throws IOException {
-                       if (true) {
-                               return;
-                       }
-                       PrintWriter log = logs.get(chn);
-                       if (log == null) {
-                               log = new PrintWriter(new FileOutputStream("irc/log_" + chn),
-                                               true);
-                               logs.put(chn, log);
-                       }
-                       log.println(l);
-               }
-
-               private void handlePrivMsg(String referent, String msg) {
-                       String[] parts = referent.split("!");
-                       if (!parts[0].startsWith(":")) {
-                               System.err.println("invalid private message");
-                               return;
-                       }
-                       if (targetBot == null) {
-                               System.out.println("dropping message");
-                               return;
-                       }
-                       targetBot.privateMessage(parts[0].substring(1), msg);
-               }
-
-               private void handleMsg(String referent, String chnl, String msg) {
-                       String[] parts = referent.split("!");
-                       if (!parts[0].startsWith(":")) {
-                               System.err.println("invalid public message");
-                               return;
-                       }
-                       if (targetBot == null) {
-                               System.out.println("dropping message");
-                               return;
-                       }
-                       if (!chnl.startsWith("#")) {
-                               System.err.println("invalid public message (chnl)");
-                               return;
-
-                       }
-
-                       targetBot.publicMessage(parts[0].substring(1), chnl.substring(1),
-                                       msg);
-               }
-       }
-       public IRCClient(String nick, String server, int port, boolean ssl)
-                       throws IOException, InterruptedException {
-               this.nick = nick;
-               if (!nick.matches("[a-zA-Z0-9_-]+")) {
-                       throw new Error("malformed");
-               }
-
-               if (ssl) {
-                       s = SSLSocketFactory.getDefault().createSocket(server, port);//default-ssl = 7000
-               } else {
-                       s = new Socket(server, port);// default-plain= 6667
-               }
-               out = new PrintWriter(s.getOutputStream(), true);
-               BufferedReader in = new BufferedReader(new InputStreamReader(
-                               s.getInputStream()));
-               new ServerReader(in);
-               out.println("USER " + nick + " 0 * :unknown");
-               out.println("NICK " + nick);
-               loggedin.acquire();
-
-       }
-       HashSet<String> joined = new HashSet<String>();
-       private IRCBot targetBot;
-       public void join(String channel) {
-               if (!channel.matches("[a-zA-Z0-9_-]+")) {
-                       return;
-               }
-               if (joined.add(channel)) {
-                       out.println("JOIN #" + channel);
-               }
-       }
-       public void leave(String channel) {
-               if (!channel.matches("[a-zA-Z0-9_-]+")) {
-                       return;
-               }
-               if (joined.remove(channel)) {
-                       out.println("PART #" + channel);
-               }
-       }
-
-       public void send(String msg, String channel) {
-               if (!channel.matches("[a-zA-Z0-9_-]+")) {
-                       return;
-               }
-               out.println("PRIVMSG #" + channel + " :" + msg);
-       }
-       public void sendPrivate(String msg, String to) {
-               if (!to.matches("[a-zA-Z0-9_-]+")) {
-                       return;
-               }
-               out.println("PRIVMSG " + to + " :" + msg);
-       }
-
-       public void setBot(IRCBot bot) {
-               this.targetBot = bot;
-
-       }
-       public static IRCClient parseCommandLine(String[] commandLine, String nick)
-                       throws IOException, InterruptedException {
-               String host = null;
-               int port = 7000;
-               boolean ssl = true;
-               for (int i = 0; i < commandLine.length; i++) {
-                       String cmd = commandLine[i];
-                       if (cmd.equals("--no-ssl") || cmd.equals("-u")) {
-                               ssl = false;
-                       } else if (cmd.equals("--ssl") || cmd.equals("-s")) {
-                               ssl = true;
-                       } else if (cmd.equals("--host") || cmd.equals("-h")) {
-                               host = commandLine[++i];
-                       } else if (cmd.equals("--port") || cmd.equals("-p")) {
-                               port = Integer.parseInt(commandLine[++i]);
-                       } else if (cmd.equals("--nick") || cmd.equals("-n")) {
-                               nick = commandLine[++i];
-                       } else if (cmd.equals("--help") || cmd.equals("-h")) {
-                               System.out
-                                               .println("Options: [--no-ssl|-u|--ssl|-s|[--host|-h] <host>|[--port|-p] <port>|[--nick|-n] <nick>]*");
-                               System.out
-                                               .println("Requires the -host argument, --ssl is default, last argument of a kind is significant.");
-                               throw new Error("Operation caneled");
-                       } else {
-                               throw new Error("Invalid option (usage with --help): " + cmd);
-                       }
-               }
-               if (host == null) {
-                       throw new Error("--host <host> is missing");
-               }
-               return new IRCClient(nick, host, port, ssl);
-       }
+
+    private Semaphore loggedin = new Semaphore(0);
+
+    private PrintWriter out;
+
+    private Socket s;
+
+    private String nick;
+
+    class ServerReader implements Runnable {
+
+        private BufferedReader br;
+
+        public ServerReader(BufferedReader br) {
+            this.br = br;
+
+            new Thread(this).start();
+        }
+
+        @Override
+        public void run() {
+            String l;
+
+            try {
+                while ((l = br.readLine()) != null) {
+                    String fullline = l;
+                    // System.out.println(l);
+
+                    if (l.startsWith("PING ")) {
+                        System.out.println("PONG");
+                        out.println("PONG " + l.substring(5));
+                    }
+
+                    String referent = "";
+
+                    if (l.startsWith(":")) {
+                        String[] parts = l.split(" ", 2);
+                        referent = parts[0];
+                        l = parts[1];
+                    }
+
+                    String[] command = l.split(" ", 3);
+
+                    if (command[0].equals("001")) {
+                        loggedin.release();
+                    }
+
+                    if (command[0].equals("PRIVMSG")) {
+                        String msg = command[2].substring(1);
+                        String chnl = command[1];
+
+                        if ( !chnl.startsWith("#")) {
+                            handlePrivMsg(referent, msg);
+                        } else {
+                            handleMsg(referent, chnl, msg);
+                        }
+
+                        log(chnl, fullline);
+                    } else if (command[0].equals("JOIN")) {
+                        String chn = command[1].substring(1);
+                        targetBot.join(cleanReferent(referent), chn.substring(1));
+                        log(chn, fullline);
+                    } else if (command[0].equals("PART")) {
+                        String chn = command[1];
+                        targetBot.part(cleanReferent(referent), chn);
+                        log(chn, fullline);
+                    } else {
+                        System.out.println("unknown line: ");
+                        System.out.println(l);
+                    }
+                }
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+
+        }
+
+        private String cleanReferent(String referent) {
+            String[] parts = referent.split("!");
+
+            if ( !parts[0].startsWith(":")) {
+                System.err.println("invalid public message");
+                return "unknown";
+            }
+
+            return parts[0];
+        }
+
+        HashMap<String, PrintWriter> logs = new HashMap<String, PrintWriter>();
+
+        private void log(String chn, String l) throws IOException {
+            if ( true ) {
+                return;
+            }
+
+            PrintWriter log = logs.get(chn);
+
+            if (log == null) {
+                log = new PrintWriter(new FileOutputStream("irc/log_" + chn), true);
+                logs.put(chn, log);
+            }
+
+            log.println(l);
+        }
+
+        private void handlePrivMsg(String referent, String msg) {
+            String[] parts = referent.split("!");
+
+            if ( !parts[0].startsWith(":")) {
+                System.err.println("invalid private message");
+                return;
+            }
+
+            if (targetBot == null) {
+                System.out.println("dropping message");
+                return;
+            }
+
+            targetBot.privateMessage(parts[0].substring(1), msg);
+        }
+
+        private void handleMsg(String referent, String chnl, String msg) {
+            String[] parts = referent.split("!");
+
+            if ( !parts[0].startsWith(":")) {
+                System.err.println("invalid public message");
+                return;
+            }
+
+            if (targetBot == null) {
+                System.out.println("dropping message");
+                return;
+            }
+
+            if ( !chnl.startsWith("#")) {
+                System.err.println("invalid public message (chnl)");
+                return;
+            }
+
+            targetBot.publicMessage(parts[0].substring(1), chnl.substring(1), msg);
+        }
+
+    }
+
+    public IRCClient(String nick, String server, int port, boolean ssl) throws IOException, InterruptedException {
+        if ( !nick.matches("[a-zA-Z0-9_-]+")) {
+            throw new Error("malformed");
+        }
+
+        if (ssl) {
+            s = SSLSocketFactory.getDefault().createSocket(server, port);//default-ssl = 7000
+            // default-ssl = 7000
+        } else {
+            s = new Socket(server, port);
+            // default-plain = 6667
+        }
+
+        out = new PrintWriter(s.getOutputStream(), true);
+        BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream()));
+
+        new ServerReader(in);
+
+        out.println("USER " + nick + " 0 * :unknown");
+        out.println("NICK " + nick);
+
+        loggedin.acquire();
+    }
+
+    HashSet<String> joined = new HashSet<String>();
+
+    private IRCBot targetBot;
+
+    public void join(String channel) {
+        if ( !channel.matches("[a-zA-Z0-9_-]+")) {
+            return;
+        }
+
+        if (joined.add(channel)) {
+            out.println("JOIN #" + channel);
+        }
+    }
+
+    public void leave(String channel) {
+        if ( !channel.matches("[a-zA-Z0-9_-]+")) {
+            return;
+        }
+
+        if (joined.remove(channel)) {
+            out.println("PART #" + channel);
+        }
+    }
+
+    public void send(String msg, String channel) {
+        if ( !channel.matches("[a-zA-Z0-9_-]+")) {
+            return;
+        }
+
+        out.println("PRIVMSG #" + channel + " :" + msg);
+    }
+
+    public void sendPrivate(String msg, String to) {
+        if ( !to.matches("[a-zA-Z0-9_-]+")) {
+            return;
+        }
+
+        out.println("PRIVMSG " + to + " :" + msg);
+    }
+
+    public void setBot(IRCBot bot) {
+        this.targetBot = bot;
+    }
+
+    public static IRCClient parseCommandLine(String[] commandLine, String nick) throws IOException, InterruptedException {
+        this.nick = nick;
+
+        String host = null;
+        int port = 7000;
+        boolean ssl = true;
+
+        for (int i = 0; i < commandLine.length; i++) {
+            String cmd = commandLine[i];
+
+            if (cmd.equals("--no-ssl") || cmd.equals("-u")) {
+                ssl = false;
+            } else if (cmd.equals("--ssl") || cmd.equals("-s")) {
+                ssl = true;
+            } else if (cmd.equals("--host") || cmd.equals("-h")) {
+                host = commandLine[++i];
+            } else if (cmd.equals("--port") || cmd.equals("-p")) {
+                port = Integer.parseInt(commandLine[++i]);
+            } else if (cmd.equals("--nick") || cmd.equals("-n")) {
+                nick = commandLine[++i];
+            } else if (cmd.equals("--help") || cmd.equals("-h")) {
+                System.out.println("Options: [--no-ssl|-u|--ssl|-s|[--host|-h] <host>|[--port|-p] <port>|[--nick|-n] <nick>]*");
+                System.out.println("Requires the -host argument, --ssl is default, last argument of a kind is significant.");
+                throw new Error("Operation caneled");
+            } else {
+                throw new Error("Invalid option (usage with --help): " + cmd);
+            }
+        }
+
+        if (host == null) {
+            throw new Error("--host <host> is missing");
+        }
+
+        return new IRCClient(nick, host, port, ssl);
+    }
+
 }