Add basic IRC framework.
authorDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Sun, 7 Apr 2013 19:52:49 +0000 (21:52 +0200)
committerDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Sun, 7 Apr 2013 19:52:49 +0000 (21:52 +0200)
19 files changed:
src/main/java/net/pterodactylus/irc/Connection.java [new file with mode: 0644]
src/main/java/net/pterodactylus/irc/ConnectionBuilder.java [new file with mode: 0644]
src/main/java/net/pterodactylus/irc/Nickname.java [new file with mode: 0644]
src/main/java/net/pterodactylus/irc/NicknameChooser.java [new file with mode: 0644]
src/main/java/net/pterodactylus/irc/event/AbstractChannelEvent.java [new file with mode: 0644]
src/main/java/net/pterodactylus/irc/event/AbstractConnectionEvent.java [new file with mode: 0644]
src/main/java/net/pterodactylus/irc/event/AbstractReplyEvent.java [new file with mode: 0644]
src/main/java/net/pterodactylus/irc/event/ChannelJoined.java [new file with mode: 0644]
src/main/java/net/pterodactylus/irc/event/ChannelNicknames.java [new file with mode: 0644]
src/main/java/net/pterodactylus/irc/event/ChannelNotJoined.java [new file with mode: 0644]
src/main/java/net/pterodactylus/irc/event/ChannelTopic.java [new file with mode: 0644]
src/main/java/net/pterodactylus/irc/event/ConnectionEstablished.java [new file with mode: 0644]
src/main/java/net/pterodactylus/irc/event/ConnectionFailed.java [new file with mode: 0644]
src/main/java/net/pterodactylus/irc/event/MotdReceived.java [new file with mode: 0644]
src/main/java/net/pterodactylus/irc/event/NicknameInUseReceived.java [new file with mode: 0644]
src/main/java/net/pterodactylus/irc/event/NoNicknameGivenReceived.java [new file with mode: 0644]
src/main/java/net/pterodactylus/irc/event/NoticeReceived.java [new file with mode: 0644]
src/main/java/net/pterodactylus/irc/event/UnknownReplyReceived.java [new file with mode: 0644]
src/main/java/net/pterodactylus/irc/util/RandomNickname.java [new file with mode: 0644]

diff --git a/src/main/java/net/pterodactylus/irc/Connection.java b/src/main/java/net/pterodactylus/irc/Connection.java
new file mode 100644 (file)
index 0000000..158a7f1
--- /dev/null
@@ -0,0 +1,530 @@
+/*
+ * XdccDownloader - Connection.java - Copyright © 2013 David Roden
+ *
+ * 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, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+package net.pterodactylus.irc;
+
+import static com.google.common.base.Preconditions.checkState;
+
+import java.io.BufferedReader;
+import java.io.Closeable;
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+import java.net.Socket;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.SynchronousQueue;
+import javax.net.SocketFactory;
+
+import net.pterodactylus.irc.event.ChannelJoined;
+import net.pterodactylus.irc.event.ChannelNicknames;
+import net.pterodactylus.irc.event.ChannelNotJoined;
+import net.pterodactylus.irc.event.ChannelNotJoined.Reason;
+import net.pterodactylus.irc.event.ChannelTopic;
+import net.pterodactylus.irc.event.ConnectionEstablished;
+import net.pterodactylus.irc.event.ConnectionFailed;
+import net.pterodactylus.irc.event.MotdReceived;
+import net.pterodactylus.irc.event.NicknameInUseReceived;
+import net.pterodactylus.irc.event.NoNicknameGivenReceived;
+import net.pterodactylus.irc.event.UnknownReplyReceived;
+import net.pterodactylus.irc.util.RandomNickname;
+
+import com.beust.jcommander.internal.Maps;
+import com.beust.jcommander.internal.Sets;
+import com.google.common.base.Optional;
+import com.google.common.eventbus.EventBus;
+import com.google.common.eventbus.Subscribe;
+import com.google.common.io.Closeables;
+import com.google.common.util.concurrent.AbstractExecutionThreadService;
+import com.google.common.util.concurrent.Service;
+
+/**
+ * A connection to an IRC server.
+ *
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+public class Connection extends AbstractExecutionThreadService implements Service {
+
+       /** The event bus. */
+       private final EventBus eventBus;
+
+       /** The socket factory. */
+       private final SocketFactory socketFactory;
+
+       /** The hostname to connect to. */
+       private final String hostname;
+
+       /** The port to connect to. */
+       private final int port;
+
+       /** The nickname chooser. */
+       private NicknameChooser nicknameChooser = new NicknameChooser() {
+
+               @Override
+               public String getNickname() {
+                       return RandomNickname.get();
+               }
+       };
+
+       /** The nickname. */
+       private String nickname = null;
+
+       /** The username. */
+       private Optional<String> username = Optional.absent();
+
+       /** The real name. */
+       private Optional<String> realName = Optional.absent();
+
+       /** The optional password for the connection. */
+       private Optional<String> password = Optional.absent();
+
+       /** The connection handler. */
+       private ConnectionHandler connectionHandler;
+
+       /**
+        * Creates a new connection.
+        *
+        * @param eventBus
+        *              The event bus
+        * @param socketFactory
+        *              The socket factory
+        * @param hostname
+        *              The hostname of the IRC server
+        * @param port
+        *              The port number of the IRC server
+        */
+       public Connection(EventBus eventBus, SocketFactory socketFactory, String hostname, int port) {
+               this.eventBus = eventBus;
+               this.socketFactory = socketFactory;
+               this.hostname = hostname;
+               this.port = port;
+       }
+
+       //
+       // ACCESSORS
+       //
+
+       /**
+        * Returns the nickname that is currently in use by this connection. The
+        * nickname is only available once the connection has been {@link #start()}ed.
+        *
+        * @return The current nickname
+        */
+       public String nickname() {
+               return nickname;
+       }
+
+       //
+       // MUTATORS
+       //
+
+       /**
+        * Sets the nickname chooser. The nickname chooser is only used during the
+        * creation of the connection.
+        *
+        * @param nicknameChooser
+        *              The nickname chooser
+        * @return This connection
+        */
+       public Connection nicknameChooser(NicknameChooser nicknameChooser) {
+               this.nicknameChooser = nicknameChooser;
+               return this;
+       }
+
+       /**
+        * Sets the username to use.
+        *
+        * @param username
+        *              The username to use
+        * @return
+        */
+       public Connection username(String username) {
+               this.username = Optional.fromNullable(username);
+               return this;
+       }
+
+       /**
+        * Sets the real name to use.
+        *
+        * @param realName
+        *              The real name to use
+        * @return This connection
+        */
+       public Connection realName(String realName) {
+               this.realName = Optional.fromNullable(realName);
+               return this;
+       }
+
+       /**
+        * Sets the optional password for the connection.
+        *
+        * @param password
+        *              The password for the connection
+        * @return This connection
+        */
+       public Connection password(String password) {
+               this.password = Optional.fromNullable(password);
+               return this;
+       }
+
+       //
+       // ACTIONS
+       //
+
+       /**
+        * Joins the given channel.
+        *
+        * @param channel
+        *              The channel to join
+        * @return {@code true} if the channel was joined, {@code false} otherwise
+        */
+       public boolean joinChannel(final String channel) {
+               final SynchronousQueue<Boolean> result = new SynchronousQueue<Boolean>();
+               Object eventHandler = new Object() {
+
+                       @Subscribe
+                       public void channelJoined(ChannelJoined channelJoined) throws InterruptedException {
+                               if (!channelJoined.channel().equalsIgnoreCase(channel)) {
+                                       return;
+                               }
+                               Optional<String> nickname = channelJoined.client().nick();
+                               if (!nickname.isPresent() || (nickname.isPresent() && nickname().equalsIgnoreCase(nickname.get()))) {
+                                       eventBus.unregister(this);
+                                       result.put(true);
+                               }
+                       }
+
+                       @Subscribe
+                       public void channelNotJoined(ChannelNotJoined channelNotJoined) throws InterruptedException {
+                               if (!channelNotJoined.channel().equalsIgnoreCase(channel)) {
+                                       return;
+                               }
+                               eventBus.unregister(this);
+                               result.put(false);
+                       }
+               };
+               eventBus.register(eventHandler);
+               try {
+                       connectionHandler.sendCommand("JOIN", channel);
+                       return result.take();
+               } catch (IOException ioe1) {
+                       eventBus.unregister(eventHandler);
+               } catch (InterruptedException ie1) {
+                       /* TODO - how to handle? */
+               }
+               return false;
+       }
+
+       //
+       // ABSTRACTEXECUTIONTHREADSERVICE METHODS
+       //
+
+       @Override
+       protected void startUp() throws IllegalStateException {
+               checkState(username.isPresent(), "username must be set");
+               checkState(realName.isPresent(), "realName must be set");
+       }
+
+       @Override
+       protected void run() {
+
+               /* connect to remote socket. */
+               try {
+                       Socket socket = socketFactory.createSocket(hostname, port);
+                       connectionHandler = new ConnectionHandler(socket.getInputStream(), socket.getOutputStream());
+
+                       /* register connection. */
+                       if (password.isPresent()) {
+                               connectionHandler.sendCommand("PASSWORD", password.get());
+                       }
+                       connectionHandler.sendCommand("USER", username.get(), "8", "*", realName.get());
+                       nickname = nicknameChooser.getNickname();
+                       connectionHandler.sendCommand("NICK", nickname);
+
+               } catch (IOException ioe1) {
+                       eventBus.post(new ConnectionFailed(this, ioe1));
+                       return;
+               }
+
+               /* now read replies and react. */
+               try {
+                       /* some status variables. */
+                       int oldConnectionStatus = 0;
+                       int connectionStatus = 0;
+                       boolean connected = true;
+                       StringBuilder motd = new StringBuilder();
+                       Set<Nickname> nicks = Sets.newHashSet();
+
+                       /* server modes. */
+                       Map<String, String> nickPrefixes = Maps.newHashMap();
+
+                       while (connected) {
+                               Reply reply = connectionHandler.readReply();
+                               System.err.println("<< " + reply);
+                               String command = reply.command();
+                               List<String> parameters = reply.parameters();
+
+                               /* replies 001-004 don’t hold information but they have to be sent on a successful connection. */
+                               if (command.equals("001")) {
+                                       connectionStatus |= 0x01;
+                               } else if (command.equals("002")) {
+                                       connectionStatus |= 0x02;
+                               } else if (command.equals("003")) {
+                                       connectionStatus |= 0x04;
+                               } else if (command.equals("004")) {
+                                       connectionStatus |= 0x08;
+
+                               /* 005 originally was a bounce message, now used to transmit useful information about the server. */
+                               } else if (command.equals("005")) {
+                                       for (String parameter : parameters) {
+                                               if (parameter.startsWith("PREFIX=")) {
+                                                       int openParen = parameter.indexOf('(');
+                                                       int closeParen = parameter.indexOf(')');
+                                                       if ((openParen != -1) && (closeParen != -1)) {
+                                                               for (int modeCharacterIndex = 1; modeCharacterIndex < (closeParen - openParen); ++modeCharacterIndex) {
+                                                                       char modeCharacter = parameter.charAt(openParen + modeCharacterIndex);
+                                                                       char modeSymbol = parameter.charAt(closeParen + modeCharacterIndex);
+                                                                       nickPrefixes.put(String.valueOf(modeSymbol), String.valueOf(modeCharacter));
+                                                               }
+                                                       }
+                                               }
+                                       }
+
+                               /* 375, 372, and 376 handle the server’s MOTD. */
+                               } else if (command.equals("375")) {
+                                       /* MOTD starts. */
+                                       motd.append(parameters.get(1)).append('\n');
+                               } else if (command.equals("372")) {
+                                       motd.append(parameters.get(1)).append('\n');
+                               } else if (command.equals("376")) {
+                                       motd.append(parameters.get(1)).append('\n');
+                                       eventBus.post(new MotdReceived(this, motd.toString()));
+                                       motd.setLength(0);
+
+                               /* 43x replies are for nick change errors. */
+                               } else if (command.equals("431")) {
+                                       eventBus.post(new NoNicknameGivenReceived(this, reply));
+                               } else if (command.equals("433")) {
+                                       if (connectionStatus == 0) {
+                                               nickname = nicknameChooser.getNickname();
+                                               connectionHandler.sendCommand("NICK", nickname);
+                                       } else {
+                                               eventBus.post(new NicknameInUseReceived(this, reply));
+                                       }
+
+                               /* channel stuff. */
+                               } else if (command.equalsIgnoreCase("JOIN")) {
+                                       eventBus.post(new ChannelJoined(this, parameters.get(0), reply.source().get()));
+                               } else if (command.equals("331")) {
+                                       /* no topic is set. */
+                               } else if (command.equals("332")) {
+                                       eventBus.post(new ChannelTopic(this, parameters.get(1), parameters.get(2)));
+                               } else if (command.equals("353")) {
+                                       String channel = parameters.get(2);
+                                       for (String nickname : parameters.get(3).split(" ")) {
+                                               if (nickPrefixes.containsKey(nickname.substring(0, 1))) {
+                                                       nicks.add(new Nickname(nickname.substring(1), nickname.substring(0, 1)));
+                                               } else {
+                                                       nicks.add(new Nickname(nickname, ""));
+                                               }
+                                       }
+                               } else if (command.equals("366")) {
+                                       eventBus.post(new ChannelNicknames(this, parameters.get(1), nicks));
+                                       System.out.println("Found Nicknames: " + nicks);
+                                       nicks.clear();
+
+                               /* common channel join errors. */
+                               } else if (command.equals("474")) {
+                                       eventBus.post(new ChannelNotJoined(this, parameters.get(1), Reason.banned));
+                               } else if (command.equals("473")) {
+                                       eventBus.post(new ChannelNotJoined(this, parameters.get(1), Reason.inviteOnly));
+                               } else if (command.equals("475")) {
+                                       eventBus.post(new ChannelNotJoined(this, parameters.get(1), Reason.badChannelKey));
+
+                               /* basic connection housekeeping. */
+                               } else if (command.equalsIgnoreCase("PING")) {
+                                       connectionHandler.sendCommand("PONG", getOptional(parameters, 0), getOptional(parameters, 1));
+
+                               /* okay, everything else. */
+                               } else {
+                                       eventBus.post(new UnknownReplyReceived(this, reply));
+                               }
+
+                               if ((connectionStatus == 0x0f) && (connectionStatus != oldConnectionStatus)) {
+                                       /* connection succeeded! */
+                                       eventBus.post(new ConnectionEstablished(this));
+                               }
+                               oldConnectionStatus = connectionStatus;
+                       }
+               } catch (IOException ioe1) {
+                       ioe1.printStackTrace();
+               } finally {
+                       System.out.println("Closing Connection.");
+                       try {
+                               Closeables.close(connectionHandler, true);
+                       } catch (IOException ioe1) {
+                               /* will not be thrown. */
+                       }
+               }
+
+       }
+
+       //
+       // PRIVATE METHODS
+       //
+
+       /**
+        * Returns an item from the list, or {@link Optional#absent()} if the list is
+        * shorter than required for the given index.
+        *
+        * @param list
+        *              The list to get an item from
+        * @param index
+        *              The index of the item
+        * @param <T>
+        *              The type of the list items
+        * @return This list item wrapped in an {@link Optional}, or {@link
+        *         Optional#absent()} if the list is not long enough
+        */
+       private static <T> Optional<T> getOptional(List<T> list, int index) {
+               if (index < list.size()) {
+                       return Optional.fromNullable(list.get(index));
+               }
+               return Optional.absent();
+       }
+
+       /** Handles input and output for the connection. */
+       private class ConnectionHandler implements Closeable {
+
+               /** The output stream of the connection. */
+               private final OutputStream outputStream;
+
+               /** The input stream of the connection. */
+               private final BufferedReader inputStreamReader;
+
+               /**
+                * Creates a new connection handler for the given input stream and output
+                * stream.
+                *
+                * @param inputStream
+                *              The input stream of the connection
+                * @param outputStream
+                *              The output stream of the connection
+                * @throws UnsupportedEncodingException
+                *              if the encoding (currently “UTF-8”) is not valid
+                */
+               private ConnectionHandler(InputStream inputStream, OutputStream outputStream) throws UnsupportedEncodingException {
+                       this.outputStream = outputStream;
+                       inputStreamReader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
+               }
+
+               //
+               // ACTIONS
+               //
+
+               /**
+                * Sends a command with the given parameters, skipping all {@link
+                * Optional#absent()} optionals.
+                *
+                * @param command
+                *              The command to send
+                * @param parameters
+                *              The parameters
+                * @throws IOException
+                *              if an I/O error occurs
+                */
+               public void sendCommand(String command, Optional<String>... parameters) throws IOException {
+                       List<String> setParameters = new ArrayList<String>();
+                       for (Optional<String> maybeSetParameter : parameters) {
+                               if (maybeSetParameter.isPresent()) {
+                                       setParameters.add(maybeSetParameter.get());
+                               }
+                       }
+                       sendCommand(command, setParameters.toArray(new String[0]));
+               }
+
+               /**
+                * Sends a command with the given parameters.
+                *
+                * @param command
+                *              The command to send
+                * @param parameters
+                *              The parameters of the command
+                * @throws IOException
+                *              if an I/O error occurs
+                * @throws IllegalArgumentException
+                *              if any parameter but that last contains a space character
+                */
+               public void sendCommand(String command, String... parameters) throws IOException, IllegalArgumentException {
+                       StringBuilder commandBuilder = new StringBuilder();
+
+                       commandBuilder.append(command);
+                       for (int parameterIndex = 0; parameterIndex < parameters.length; ++parameterIndex) {
+                               String parameter = parameters[parameterIndex];
+                               /* space is only allowed in the last parameter. */
+                               commandBuilder.append(' ');
+                               if (parameter.contains(" ")) {
+                                       if (parameterIndex == (parameters.length - 1)) {
+                                               commandBuilder.append(':');
+                                       } else {
+                                               throw new IllegalArgumentException(String.format("parameter “%s” must not contain space!", parameter));
+                                       }
+                               }
+                               commandBuilder.append(parameter);
+                       }
+
+                       System.out.println(">> " + commandBuilder.toString());
+                       outputStream.write((commandBuilder.toString() + "\r\n").getBytes("UTF-8"));
+                       outputStream.flush();
+               }
+
+               /**
+                * Reads a line of reply from the connection.
+                *
+                * @return The reply
+                * @throws IOException
+                *              if an I/O error occurs
+                * @throws EOFException
+                *              if EOF was reached
+                */
+               public Reply readReply() throws IOException, EOFException {
+                       String line = inputStreamReader.readLine();
+                       if (line == null) {
+                               throw new EOFException();
+                       }
+
+                       return Reply.parseLine(line);
+               }
+
+               //
+               // CLOSEABLE METHODS
+               //
+
+               @Override
+               public void close() throws IOException {
+                       Closeables.close(outputStream, true);
+                       Closeables.close(inputStreamReader, true);
+               }
+
+       }
+
+}
diff --git a/src/main/java/net/pterodactylus/irc/ConnectionBuilder.java b/src/main/java/net/pterodactylus/irc/ConnectionBuilder.java
new file mode 100644 (file)
index 0000000..feefe1f
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * XdccDownloader - ConnectionBuilder.java - Copyright © 2013 David Roden
+ *
+ * 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, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+package net.pterodactylus.irc;
+
+import javax.net.SocketFactory;
+import javax.net.ssl.SSLSocketFactory;
+
+import com.google.common.base.Optional;
+import com.google.common.eventbus.EventBus;
+import com.google.inject.Inject;
+
+/**
+ * Builder for {@link Connection}s.
+ *
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+public class ConnectionBuilder {
+
+       /** The event bus. */
+       private final EventBus eventBus;
+
+       /** The hostname to connect to. */
+       private Optional<String> hostname = Optional.absent();
+
+       /** The port number to connect to. */
+       private int port = 6666;
+
+       /** Whether to use an SSL connection. */
+       private boolean secure = false;
+
+       /**
+        * Creates a new connection builder.
+        *
+        * @param eventBus
+        *              The event bus
+        */
+       @Inject
+       public ConnectionBuilder(EventBus eventBus) {
+               this.eventBus = eventBus;
+       }
+
+       /**
+        * Configures this builder to use the given hostname for the connection.
+        *
+        * @param hostname
+        *              The hostname of the IRC server
+        * @return This builder
+        */
+       public ConnectionBuilder connect(String hostname) {
+               this.hostname = Optional.fromNullable(hostname);
+               return this;
+       }
+
+       /**
+        * Configures this builder to use the given port number for the connection.
+        *
+        * @param port
+        *              The port number of the IRC server
+        * @return This builder
+        */
+       public ConnectionBuilder port(int port) {
+               this.port = port;
+               return this;
+       }
+
+       /**
+        * Configures this builder to use an SSL connection.
+        *
+        * @return This builder
+        */
+       public ConnectionBuilder secure() {
+               this.secure = true;
+               return this;
+       }
+
+       /**
+        * Builds the connection.
+        *
+        * @return The created connection
+        * @throws IllegalStateException
+        *              if the hostname has not been set
+        */
+       public Connection build() throws IllegalStateException {
+               if (!hostname.isPresent()) {
+                       throw new IllegalStateException("hostname must not be empty");
+               }
+
+               SocketFactory socketFactory = secure ? SSLSocketFactory.getDefault() : SocketFactory.getDefault();
+               return new Connection(eventBus, socketFactory, hostname.get(), port);
+       }
+
+}
diff --git a/src/main/java/net/pterodactylus/irc/Nickname.java b/src/main/java/net/pterodactylus/irc/Nickname.java
new file mode 100644 (file)
index 0000000..25f2497
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * XdccDownloader - Nick.java - Copyright © 2013 David Roden
+ *
+ * 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, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+package net.pterodactylus.irc;
+
+/**
+ * Container for a nickname and a prefix. The prefix is a character specific to
+ * an IRC server that denotes some kind of special status of a nickname in a
+ * channel. The most commonly known prefixes are “@” (for operators) and “+”
+ * (for voiced clients) but newer IRCds know other prefixes, such as “!” and
+ * “%”, too.
+ *
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+public class Nickname {
+
+       /** The name. */
+       private final String name;
+
+       /** The prefix. */
+       private final String prefix;
+
+       /**
+        * Creates a new nickname.
+        *
+        * @param name
+        *              The name of the nickname
+        * @param prefix
+        *              The prefix of the nickname
+        */
+       public Nickname(String name, String prefix) {
+               this.name = name;
+               this.prefix = prefix;
+       }
+
+       //
+       // ACCESSORS
+       //
+
+       /**
+        * Returns the name of the nickname.
+        *
+        * @return The name of the nickname
+        */
+       public String name() {
+               return name;
+       }
+
+       /**
+        * Returns the prefix of the nickname.
+        *
+        * @return The prefix of the nickname (or an empty string if this nickname does
+        *         not have a prefix)
+        */
+       public String prefix() {
+               return prefix;
+       }
+
+       //
+       // OBJECT METHODS
+       //
+
+       @Override
+       public String toString() {
+               return prefix + name;
+       }
+
+}
diff --git a/src/main/java/net/pterodactylus/irc/NicknameChooser.java b/src/main/java/net/pterodactylus/irc/NicknameChooser.java
new file mode 100644 (file)
index 0000000..9a9357a
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * XdccDownloader - NicknameChooser.java - Copyright © 2013 David Roden
+ *
+ * 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, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+package net.pterodactylus.irc;
+
+/**
+ * A nickname choose is used to get a new nickname. It is used by the {@link
+ * Connection} to retrieve the initial nickname of the connection, and it’s also
+ * used in case a nick change results in a “nickname already in use” error.
+ *
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+public interface NicknameChooser {
+
+       /**
+        * Returns a nickname to use.
+        *
+        * @return A nickname
+        */
+       public String getNickname();
+
+}
diff --git a/src/main/java/net/pterodactylus/irc/event/AbstractChannelEvent.java b/src/main/java/net/pterodactylus/irc/event/AbstractChannelEvent.java
new file mode 100644 (file)
index 0000000..960e8f6
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * XdccDownloader - ChannelJoined.java - Copyright © 2013 David Roden
+ *
+ * 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, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+package net.pterodactylus.irc.event;
+
+import net.pterodactylus.irc.Connection;
+
+/**
+ * Abstract base class for all events that happen on a channel.
+ *
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+public abstract class AbstractChannelEvent extends AbstractConnectionEvent {
+
+       /** The channel this event occured on. */
+       private final String channel;
+
+       /**
+        * Creates a new abstract channel event.
+        *
+        * @param connection
+        *              The connection this event occured on
+        * @param channel
+        *              The channel this event occured on
+        */
+       protected AbstractChannelEvent(Connection connection, String channel) {
+               super(connection);
+               this.channel = channel;
+       }
+
+       //
+       // ACCESSORS
+       //
+
+       /**
+        * Returns the channel this event occured on.
+        *
+        * @return The channel this event occured on
+        */
+       public String channel() {
+               return channel;
+       }
+
+}
diff --git a/src/main/java/net/pterodactylus/irc/event/AbstractConnectionEvent.java b/src/main/java/net/pterodactylus/irc/event/AbstractConnectionEvent.java
new file mode 100644 (file)
index 0000000..f862487
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * XdccDownloader - AbstractConnectionEvent.java - Copyright © 2013 David Roden
+ *
+ * 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, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+package net.pterodactylus.irc.event;
+
+import net.pterodactylus.irc.Connection;
+
+/**
+ * Abstract base class for all {@link Connection}-related events.
+ *
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+public abstract class AbstractConnectionEvent {
+
+       /** The connection the event occured on. */
+       private final Connection connection;
+
+       /**
+        * Creates a new abstract connection event.
+        *
+        * @param connection
+        *              The connection the event occured on
+        */
+       protected AbstractConnectionEvent(Connection connection) {
+               this.connection = connection;
+       }
+
+       //
+       // ACCESSORS
+       //
+
+       /**
+        * Returns the connection the event occured on.
+        *
+        * @return The connection the event occured on
+        */
+       public Connection connection() {
+               return connection;
+       }
+
+}
diff --git a/src/main/java/net/pterodactylus/irc/event/AbstractReplyEvent.java b/src/main/java/net/pterodactylus/irc/event/AbstractReplyEvent.java
new file mode 100644 (file)
index 0000000..e940c6c
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * XdccDownloader - AbstractReplyEvent.java - Copyright © 2013 David Roden
+ *
+ * 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, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+package net.pterodactylus.irc.event;
+
+import net.pterodactylus.irc.Connection;
+import net.pterodactylus.irc.Reply;
+
+/**
+ * Abstract base class for all events based on {@link Reply}s (and thus very low
+ * level). Examples would be e.g. nick changing messages, mode changes, private
+ * messages, and other single/global events that do not carry state.
+ *
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+public abstract class AbstractReplyEvent extends AbstractConnectionEvent {
+
+       /** The reply that caused this event. */
+       private final Reply reply;
+
+       /**
+        * Creates a new abstract reply event.
+        *
+        * @param connection
+        *              The connection the event occured on
+        * @param reply
+        *              The reply that caused this event
+        */
+       protected AbstractReplyEvent(Connection connection, Reply reply) {
+               super(connection);
+               this.reply = reply;
+       }
+
+       //
+       // ACCESSORS
+       //
+
+       /**
+        * Returns the reply that caused this event.
+        *
+        * @return The reply that caused this event
+        */
+       public Reply reply() {
+               return reply;
+       }
+
+}
diff --git a/src/main/java/net/pterodactylus/irc/event/ChannelJoined.java b/src/main/java/net/pterodactylus/irc/event/ChannelJoined.java
new file mode 100644 (file)
index 0000000..d607ab1
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * XdccDownloader - ChannelJoined.java - Copyright © 2013 David Roden
+ *
+ * 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, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+package net.pterodactylus.irc.event;
+
+import net.pterodactylus.irc.Connection;
+import net.pterodactylus.irc.Source;
+
+/**
+ * Event that notifies a listener that a client has joined a channel.
+ *
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+public class ChannelJoined extends AbstractChannelEvent {
+
+       private final Source client;
+
+       /**
+        * Creates a new channel joined event.
+        *
+        * @param connection
+        *              The connection that joined the channel
+        * @param channel
+        *              The channel that was joined
+        */
+       public ChannelJoined(Connection connection, String channel, Source client) {
+               super(connection, channel);
+               this.client = client;
+       }
+
+       //
+       // ACCESSORS
+       //
+
+       /**
+        * Returns the client that joined the channel.
+        *
+        * @return The client that joined the channel
+        */
+       public Source client() {
+               return client;
+       }
+
+}
diff --git a/src/main/java/net/pterodactylus/irc/event/ChannelNicknames.java b/src/main/java/net/pterodactylus/irc/event/ChannelNicknames.java
new file mode 100644 (file)
index 0000000..5ceaf09
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * XdccDownloader - ChannelNames.java - Copyright © 2013 David Roden
+ *
+ * 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, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+package net.pterodactylus.irc.event;
+
+import java.util.Collection;
+
+import net.pterodactylus.irc.Connection;
+import net.pterodactylus.irc.Nickname;
+
+/**
+ * Notifies a listener that a list of nicknames has been retrieved for a
+ * channel.
+ *
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+public class ChannelNicknames extends AbstractChannelEvent {
+
+       /** The nicknames. */
+       private final Collection<Nickname> nicknames;
+
+       /**
+        * Creates a new channel nicknames event.
+        *
+        * @param connection
+        *              The connection the event occured on
+        * @param channel
+        *              The channel the nicknames are listed for
+        * @param nicknames
+        *              The nicknames
+        */
+       public ChannelNicknames(Connection connection, String channel, Collection<Nickname> nicknames) {
+               super(connection, channel);
+               this.nicknames = nicknames;
+       }
+
+       //
+       // ACCESSORS
+       //
+
+       /**
+        * Returns the nicknames retrieved for the channel.
+        *
+        * @return The nicknames retrieved for the channel
+        */
+       public Collection<Nickname> nicknames() {
+               return nicknames;
+       }
+
+}
diff --git a/src/main/java/net/pterodactylus/irc/event/ChannelNotJoined.java b/src/main/java/net/pterodactylus/irc/event/ChannelNotJoined.java
new file mode 100644 (file)
index 0000000..daaeded
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * XdccDownloader - ChannelNotJoined.java - Copyright © 2013 David Roden
+ *
+ * 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, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+package net.pterodactylus.irc.event;
+
+import net.pterodactylus.irc.Connection;
+
+/**
+ * Notifies a listener that a channel could not be joined.
+ *
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+public class ChannelNotJoined extends AbstractChannelEvent {
+
+       /** The possible reasons for the failure to join a channel. */
+       public enum Reason {
+
+               channelIsFull,
+               inviteOnly,
+               banned,
+               badChannelKey,
+               badChannelMask,
+               noSuchChannel,
+               tooManyChannels,
+               tooManyTargets,
+               unavailable
+
+       }
+
+       /** The reason for the join failure. */
+       private final Reason reason;
+
+       /**
+        * Creates a new channel not joined event.
+        *
+        * @param connection
+        *              The connection this event occured on
+        * @param channel
+        *              The channel that could not be joined
+        * @param reason
+        *              The reason for the failure to join the channel
+        */
+       public ChannelNotJoined(Connection connection, String channel, Reason reason) {
+               super(connection, channel);
+               this.reason = reason;
+       }
+
+       //
+       // ACCESSORS
+       //
+
+       /**
+        * Returns the reason for the failure to join the channel.
+        *
+        * @return The reason for the failure to join the channel
+        */
+       public Reason reason() {
+               return reason;
+       }
+
+}
diff --git a/src/main/java/net/pterodactylus/irc/event/ChannelTopic.java b/src/main/java/net/pterodactylus/irc/event/ChannelTopic.java
new file mode 100644 (file)
index 0000000..6f22461
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * XdccDownloader - ChannelTopic.java - Copyright © 2013 David Roden
+ *
+ * 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, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+package net.pterodactylus.irc.event;
+
+import net.pterodactylus.irc.Connection;
+
+/**
+ * Notifies a listener that a channel topic has been set.
+ *
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+public class ChannelTopic extends AbstractChannelEvent {
+
+       /** The topic that has been set. */
+       private final String topic;
+
+       /**
+        * Creates a new channel topic event.
+        *
+        * @param connection
+        *              The connection the event occured on
+        * @param channel
+        *              The channel the topic was set on
+        * @param topic
+        *              The topic that was set
+        */
+       public ChannelTopic(Connection connection, String channel, String topic) {
+               super(connection, channel);
+               this.topic = topic;
+       }
+
+       //
+       // ACCESSORS
+       //
+
+       /**
+        * Returns the topic that was set.
+        *
+        * @return The topic that was set
+        */
+       public String topic() {
+               return topic;
+       }
+
+}
diff --git a/src/main/java/net/pterodactylus/irc/event/ConnectionEstablished.java b/src/main/java/net/pterodactylus/irc/event/ConnectionEstablished.java
new file mode 100644 (file)
index 0000000..39aad14
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * XdccDownloader - ConnectionEstablished.java - Copyright © 2013 David Roden
+ *
+ * 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, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+package net.pterodactylus.irc.event;
+
+import net.pterodactylus.irc.Connection;
+
+/**
+ * Notifies a listener that a connection to an IRC server was established
+ * successfully.
+ *
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+public class ConnectionEstablished extends AbstractConnectionEvent {
+
+       /**
+        * Creates a new connection established event.
+        *
+        * @param connection
+        *              The connection the event occured on
+        */
+       public ConnectionEstablished(Connection connection) {
+               super(connection);
+       }
+
+}
diff --git a/src/main/java/net/pterodactylus/irc/event/ConnectionFailed.java b/src/main/java/net/pterodactylus/irc/event/ConnectionFailed.java
new file mode 100644 (file)
index 0000000..9bd57ce
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * XdccDownloader - ConnectionFailed.java - Copyright © 2013 David Roden
+ *
+ * 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, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+package net.pterodactylus.irc.event;
+
+import net.pterodactylus.irc.Connection;
+
+/**
+ * Notifies a listener that a connection to an IRC server could not be
+ * established.
+ *
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+public class ConnectionFailed extends AbstractConnectionEvent {
+
+       /** The cause of the connection failure. */
+       private final Throwable cause;
+
+       /**
+        * Creates a new connection failure event.
+        *
+        * @param connection
+        *              The connection the event occured on
+        * @param cause
+        *              The cause of the connection failure
+        */
+       public ConnectionFailed(Connection connection, Throwable cause) {
+               super(connection);
+               this.cause = cause;
+       }
+
+       //
+       // ACCESSORS
+       //
+
+       /**
+        * Returns the cause of the connection failure.
+        *
+        * @return The cause of the connection failure
+        */
+       public Throwable cause() {
+               return cause;
+       }
+
+}
diff --git a/src/main/java/net/pterodactylus/irc/event/MotdReceived.java b/src/main/java/net/pterodactylus/irc/event/MotdReceived.java
new file mode 100644 (file)
index 0000000..1e0a637
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * XdccDownloader - MotdReceived.java - Copyright © 2013 David Roden
+ *
+ * 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, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+package net.pterodactylus.irc.event;
+
+import net.pterodactylus.irc.Connection;
+
+/**
+ * Notifies a listener that a server’s MOTD (message of the day) was received.
+ *
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+public class MotdReceived extends AbstractConnectionEvent {
+
+       /** The MOTD of the server. */
+       private final String motd;
+
+       /**
+        * Creates a new MOTD received event.
+        *
+        * @param connection
+        *              The connection the event occured on
+        * @param motd
+        *              The MOTD of the server
+        */
+       public MotdReceived(Connection connection, String motd) {
+               super(connection);
+               this.motd = motd;
+       }
+
+       //
+       // ACCESSORS
+       //
+
+       /**
+        * Returns the MOTD of the server.
+        *
+        * @return The MOTD of the server
+        */
+       public String motd() {
+               return motd;
+       }
+
+}
diff --git a/src/main/java/net/pterodactylus/irc/event/NicknameInUseReceived.java b/src/main/java/net/pterodactylus/irc/event/NicknameInUseReceived.java
new file mode 100644 (file)
index 0000000..3a76914
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * XdccDownloader - NicknameInUseReceived.java - Copyright © 2013 David Roden
+ *
+ * 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, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+package net.pterodactylus.irc.event;
+
+import net.pterodactylus.irc.Connection;
+import net.pterodactylus.irc.Reply;
+
+/**
+ * Notifies a listener that a nickname is already in use.
+ *
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+public class NicknameInUseReceived extends AbstractReplyEvent {
+
+       /** The nickname that is already in use. */
+       private final String nickname;
+
+       /** The message from the server. */
+       private final String message;
+
+       /**
+        * Creates a new nickname in use event.
+        *
+        * @param connection
+        *              The connection the event occured on
+        * @param reply
+        *              The reply that caused the event
+        */
+       public NicknameInUseReceived(Connection connection, Reply reply) {
+               super(connection, reply);
+               nickname = reply.parameters().get(0);
+               message = reply.parameters().get(1);
+       }
+
+       //
+       // ACCESSORS
+       //
+
+       /**
+        * Returns the nickname that is already in use.
+        *
+        * @return The nickname that is already in use
+        */
+       public String nickname() {
+               return nickname;
+       }
+
+       /**
+        * Returns the message from the IRC server.
+        *
+        * @return The message from the IRC server
+        */
+       public String message() {
+               return message;
+       }
+
+}
diff --git a/src/main/java/net/pterodactylus/irc/event/NoNicknameGivenReceived.java b/src/main/java/net/pterodactylus/irc/event/NoNicknameGivenReceived.java
new file mode 100644 (file)
index 0000000..aba2fb2
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * XdccDownloader - NoNicknameGivenReceived.java - Copyright © 2013 David Roden
+ *
+ * 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, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+package net.pterodactylus.irc.event;
+
+import net.pterodactylus.irc.Connection;
+import net.pterodactylus.irc.Reply;
+
+/**
+ * Notifies a listener that no nickname was given with a “NICK” command.
+ *
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+public class NoNicknameGivenReceived extends AbstractReplyEvent {
+
+       /**
+        * Creates a new no nickname given event.
+        *
+        * @param connection
+        *              The connection the event occured on
+        * @param reply
+        *              The reply that caused the event
+        */
+       public NoNicknameGivenReceived(Connection connection, Reply reply) {
+               super(connection, reply);
+       }
+
+}
diff --git a/src/main/java/net/pterodactylus/irc/event/NoticeReceived.java b/src/main/java/net/pterodactylus/irc/event/NoticeReceived.java
new file mode 100644 (file)
index 0000000..f4b34c8
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * XdccDownloader - NoticeReceived.java - Copyright © 2013 David Roden
+ *
+ * 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, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+package net.pterodactylus.irc.event;
+
+import net.pterodactylus.irc.Connection;
+import net.pterodactylus.irc.Reply;
+
+/**
+ * Notifies a listener that a notice was received.
+ *
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+public class NoticeReceived extends AbstractReplyEvent {
+
+       /** The target of the notice. */
+       private final String target;
+
+       /** The text of the notice. */
+       private final String text;
+
+       /**
+        * Creates a new notice received event.
+        *
+        * @param connection
+        *              The connection the event occured on
+        * @param reply
+        *              The reply that caused the event
+        */
+       public NoticeReceived(Connection connection, Reply reply) {
+               super(connection, reply);
+               this.target = reply.parameters().get(0);
+               this.text = reply.parameters().get(1);
+       }
+
+       //
+       // ACCESSORS
+       //
+
+       /**
+        * Returns the target of the notice.
+        *
+        * @return The target of the notice
+        */
+       public String target() {
+               return target;
+       }
+
+       /**
+        * Returns the text of the notice.
+        *
+        * @return The text of the notice
+        */
+       public String text() {
+               return text;
+       }
+
+}
diff --git a/src/main/java/net/pterodactylus/irc/event/UnknownReplyReceived.java b/src/main/java/net/pterodactylus/irc/event/UnknownReplyReceived.java
new file mode 100644 (file)
index 0000000..040be97
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * XdccDownloader - UnknownReplyReceived.java - Copyright © 2013 David Roden
+ *
+ * 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, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+package net.pterodactylus.irc.event;
+
+import net.pterodactylus.irc.Connection;
+import net.pterodactylus.irc.Reply;
+
+/**
+ * Notifies a listener that a reply was received that was not handled
+ * internally.
+ *
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+public class UnknownReplyReceived extends AbstractReplyEvent {
+
+       /**
+        * Creates a new unknown reply event.
+        *
+        * @param connection
+        *              The connection the event occured on
+        * @param reply
+        *              The reply that caused the event
+        */
+       public UnknownReplyReceived(Connection connection, Reply reply) {
+               super(connection, reply);
+       }
+
+}
diff --git a/src/main/java/net/pterodactylus/irc/util/RandomNickname.java b/src/main/java/net/pterodactylus/irc/util/RandomNickname.java
new file mode 100644 (file)
index 0000000..d678134
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * XdccDownloader - RandomNickname.java - Copyright © 2013 David Roden
+ *
+ * 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, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+package net.pterodactylus.irc.util;
+
+import java.util.Random;
+
+/**
+ * Creates a random nickname.
+ *
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+public class RandomNickname {
+
+       /** A random number generator. */
+       private static final Random random = new Random();
+
+       /**
+        * Creates a new random nickname.
+        *
+        * @return A new random nickname
+        */
+       public static String get() {
+               StringBuilder nickname = new StringBuilder(9);
+
+               for (int index = 0; index < 9; ++index) {
+                       char letter = (char) ('A' + random.nextInt(26 + 26));
+                       if (letter > 'Z') {
+                               letter += 'a' - 'Z' - 1;
+                       }
+                       nickname.append(letter);
+               }
+
+               return nickname.toString();
+       }
+
+}