Not logged in.  Login/Logout/Register | List snippets | | Create snippet | Upload image | Upload data

3038
LINES

< > BotCompany Repo | #1002680 // class PircBot (modified)

JavaX source code - run with: x30.jar

1  
static abstract class PircBot implements ReplyConstants {
2  
    /**
3  
     * The definitive version number of this release of PircBot.
4  
     * (Note: Change this before automatically building releases)
5  
     */
6  
    public static final String VERSION = "1.5.0+";
7  
    
8  
    
9  
    private static final int OP_ADD = 1;
10  
    private static final int OP_REMOVE = 2;
11  
    private static final int VOICE_ADD = 3;
12  
    private static final int VOICE_REMOVE = 4;
13  
    
14  
    
15  
    /**
16  
     * Constructs a PircBot with the default settings.  Your own constructors
17  
     * in classes which extend the PircBot abstract class should be responsible
18  
     * for changing the default settings if required.
19  
     */
20  
    public PircBot() {}
21  
    
22  
    
23  
    /**
24  
     * Attempt to connect to the specified IRC server.
25  
     * The onConnect method is called upon success.
26  
     *
27  
     * @param hostname The hostname of the server to connect to.
28  
     * 
29  
     * @throws IOException if it was not possible to connect to the server.
30  
     * @throws IrcException if the server would not let us join it.
31  
     * @throws NickAlreadyInUseException if our nick is already in use on the server.
32  
     */
33  
    public final synchronized void connect(String hostname) throws IOException, IrcException, NickAlreadyInUseException {
34  
        this.connect(hostname, 6667, null);
35  
    }
36  
37  
38  
    /**
39  
     * Attempt to connect to the specified IRC server and port number.
40  
     * The onConnect method is called upon success.
41  
     *
42  
     * @param hostname The hostname of the server to connect to.
43  
     * @param port The port number to connect to on the server.
44  
     * 
45  
     * @throws IOException if it was not possible to connect to the server.
46  
     * @throws IrcException if the server would not let us join it.
47  
     * @throws NickAlreadyInUseException if our nick is already in use on the server.
48  
     */
49  
    public final synchronized void connect(String hostname, int port) throws IOException, IrcException, NickAlreadyInUseException {
50  
        this.connect(hostname, port, null);
51  
    }
52  
    
53  
    
54  
    /**
55  
     * Attempt to connect to the specified IRC server using the supplied
56  
     * password.
57  
     * The onConnect method is called upon success.
58  
     *
59  
     * @param hostname The hostname of the server to connect to.
60  
     * @param port The port number to connect to on the server.
61  
     * @param password The password to use to join the server.
62  
     *
63  
     * @throws IOException if it was not possible to connect to the server.
64  
     * @throws IrcException if the server would not let us join it.
65  
     * @throws NickAlreadyInUseException if our nick is already in use on the server.
66  
     */
67  
    public final synchronized void connect(String hostname, int port, String password) throws IOException, IrcException, NickAlreadyInUseException {
68  
69  
        _server = hostname;
70  
        _port = port;
71  
        _password = password;
72  
        
73  
        if (isConnected()) {
74  
            throw new IOException("The PircBot is already connected to an IRC server.  Disconnect first.");
75  
        }
76  
        
77  
        // Don't clear the outqueue - there might be something important in it!
78  
        
79  
        // Clear everything we may have know about channels.
80  
        this.removeAllChannels();
81  
        
82  
        // Connect to the server.
83  
        Socket socket =  new Socket(hostname, port);
84  
        this.log("*** Connected to server.");
85  
        
86  
        _inetAddress = socket.getLocalAddress();
87  
        
88  
        InputStreamReader inputStreamReader = null;
89  
        OutputStreamWriter outputStreamWriter = null;
90  
        if (getEncoding() != null) {
91  
            // Assume the specified encoding is valid for this JVM.
92  
            inputStreamReader = new InputStreamReader(socket.getInputStream(), getEncoding());
93  
            outputStreamWriter = new OutputStreamWriter(socket.getOutputStream(), getEncoding());
94  
        }
95  
        else {
96  
            // Otherwise, just use the JVM's default encoding.
97  
            inputStreamReader = new InputStreamReader(socket.getInputStream());
98  
            outputStreamWriter = new OutputStreamWriter(socket.getOutputStream());
99  
        }
100  
101  
        BufferedReader breader = new BufferedReader(inputStreamReader);
102  
        BufferedWriter bwriter = new BufferedWriter(outputStreamWriter);
103  
        
104  
        // Attempt to join the server.
105  
        if (password != null && !password.equals("")) {
106  
            OutputThread.sendRawLine(this, bwriter, "PASS " + password);
107  
        }
108  
        String nick = this.getName();
109  
        OutputThread.sendRawLine(this, bwriter, "NICK " + nick);
110  
        OutputThread.sendRawLine(this, bwriter, "USER " + this.getLogin() + " 8 * :" + this.getVersion());
111  
112  
        _inputThread = new InputThread(this, socket, breader, bwriter);
113  
        
114  
        // Read stuff back from the server to see if we connected.
115  
        String line = null;
116  
        int tries = 1;
117  
        while ((line = breader.readLine()) != null) {
118  
            
119  
            this.handleLine(line);
120  
            
121  
            int firstSpace = line.indexOf(" ");
122  
            int secondSpace = line.indexOf(" ", firstSpace + 1);
123  
            if (secondSpace >= 0) {
124  
                String code = line.substring(firstSpace + 1, secondSpace);
125  
                
126  
                if (code.equals("004")) {
127  
                    // We're connected to the server.
128  
                    break;
129  
                }
130  
                else if (code.equals("433")) {
131  
                    if (_autoNickChange) {
132  
                        tries++;
133  
                        nick = getName() + tries;
134  
                        OutputThread.sendRawLine(this, bwriter, "NICK " + nick);
135  
                    }
136  
                    else {
137  
                        socket.close();
138  
                        _inputThread = null;
139  
                        throw new NickAlreadyInUseException(line);
140  
                    }
141  
                }
142  
                else if (code.equals("439")) {
143  
                    // No action required.
144  
                }
145  
                else if (code.startsWith("5") || code.startsWith("4")) {
146  
                    socket.close();
147  
                    _inputThread = null;
148  
                    throw new IrcException("Could not log into the IRC server: " + line);
149  
                }
150  
            }
151  
            this.setNick(nick);
152  
            
153  
        }
154  
        
155  
        this.log("*** Logged onto server.");
156  
        
157  
        // This makes the socket timeout on read operations after 5 minutes.
158  
        // Maybe in some future version I will let the user change this at runtime.
159  
        socket.setSoTimeout(5 * 60 * 1000);
160  
        
161  
        // Now start the InputThread to read all other lines from the server.
162  
        _inputThread.start();
163  
        
164  
        // Now start the outputThread that will be used to send all messages.
165  
        if (_outputThread == null) {
166  
            _outputThread = new OutputThread(this, _outQueue);
167  
            _outputThread.start();
168  
        }
169  
        
170  
        this.onConnect();
171  
        
172  
    }
173  
    
174  
    
175  
    /**
176  
     * Reconnects to the IRC server that we were previously connected to.
177  
     * If necessary, the appropriate port number and password will be used.
178  
     * This method will throw an IrcException if we have never connected
179  
     * to an IRC server previously.
180  
     * 
181  
     * @since PircBot 0.9.9
182  
     * 
183  
     * @throws IOException if it was not possible to connect to the server.
184  
     * @throws IrcException if the server would not let us join it.
185  
     * @throws NickAlreadyInUseException if our nick is already in use on the server.
186  
     */
187  
    public final synchronized void reconnect() throws IOException, IrcException, NickAlreadyInUseException{
188  
        if (getServer() == null) {
189  
            throw new IrcException("Cannot reconnect to an IRC server because we were never connected to one previously!");
190  
        }
191  
        connect(getServer(), getPort(), getPassword());
192  
    }
193  
194  
195  
    /**
196  
     * This method disconnects from the server cleanly by calling the
197  
     * quitServer() method.  Providing the PircBot was connected to an
198  
     * IRC server, the onDisconnect() will be called as soon as the
199  
     * disconnection is made by the server.
200  
     *
201  
     * @see #quitServer() quitServer
202  
     * @see #quitServer(String) quitServer
203  
     */
204  
    public final synchronized void disconnect() {
205  
        this.quitServer();
206  
    }
207  
    
208  
    
209  
    /**
210  
     * When you connect to a server and your nick is already in use and
211  
     * this is set to true, a new nick will be automatically chosen.
212  
     * This is done by adding numbers to the end of the nick until an
213  
     * available nick is found.
214  
     *
215  
     * @param autoNickChange Set to true if you want automatic nick changes
216  
     *                       during connection.
217  
     */
218  
    public void setAutoNickChange(boolean autoNickChange) {
219  
        _autoNickChange = autoNickChange;
220  
    }
221  
    
222  
    
223  
    /**
224  
     * Starts an ident server (Identification Protocol Server, RFC 1413).
225  
     *  <p>
226  
     * Most IRC servers attempt to contact the ident server on connecting
227  
     * hosts in order to determine the user's identity.  A few IRC servers
228  
     * will not allow you to connect unless this information is provided.
229  
     *  <p>
230  
     * So when a PircBot is run on a machine that does not run an ident server,
231  
     * it may be necessary to call this method to start one up.
232  
     *  <p>
233  
     * Calling this method starts up an ident server which will respond with
234  
     * the login provided by calling getLogin() and then shut down immediately.
235  
     * It will also be shut down if it has not been contacted within 60 seconds
236  
     * of creation.
237  
     *  <p>
238  
     * If you require an ident response, then the correct procedure is to start
239  
     * the ident server and then connect to the IRC server.  The IRC server may
240  
     * then contact the ident server to get the information it needs.
241  
     *  <p>
242  
     * The ident server will fail to start if there is already an ident server
243  
     * running on port 113, or if you are running as an unprivileged user who
244  
     * is unable to create a server socket on that port number.
245  
     *  <p>
246  
     * If it is essential for you to use an ident server when connecting to an
247  
     * IRC server, then make sure that port 113 on your machine is visible to
248  
     * the IRC server so that it may contact the ident server.
249  
     *
250  
     * @since PircBot 0.9c
251  
     */
252  
    public final void startIdentServer() {
253  
        new IdentServer(this, getLogin());
254  
    }
255  
256  
    
257  
    /**
258  
     * Joins a channel.
259  
     * 
260  
     * @param channel The name of the channel to join (eg "#cs").
261  
     */
262  
    public final void joinChannel(String channel) {
263  
        this.sendRawLine("JOIN " + channel);
264  
    }
265  
    
266  
    
267  
    /**
268  
     * Joins a channel with a key.
269  
     * 
270  
     * @param channel The name of the channel to join (eg "#cs").
271  
     * @param key The key that will be used to join the channel.
272  
     */
273  
    public final void joinChannel(String channel, String key) {
274  
        this.joinChannel(channel + " " + key);
275  
    }
276  
    
277  
278  
    /**
279  
     * Parts a channel.
280  
     *
281  
     * @param channel The name of the channel to leave.
282  
     */
283  
    public final void partChannel(String channel) {
284  
        this.sendRawLine("PART " + channel);
285  
    }
286  
    
287  
    
288  
    /**
289  
     * Parts a channel, giving a reason.
290  
     *
291  
     * @param channel The name of the channel to leave.
292  
     * @param reason  The reason for parting the channel.
293  
     */
294  
    public final void partChannel(String channel, String reason) {
295  
        this.sendRawLine("PART " + channel + " :" + reason);
296  
    }
297  
298  
299  
    /**
300  
     * Quits from the IRC server.
301  
     * Providing we are actually connected to an IRC server, the
302  
     * onDisconnect() method will be called as soon as the IRC server
303  
     * disconnects us.
304  
     */
305  
    public final void quitServer() {
306  
        this.quitServer("");
307  
    }
308  
    
309  
    
310  
    /**
311  
     * Quits from the IRC server with a reason.
312  
     * Providing we are actually connected to an IRC server, the
313  
     * onDisconnect() method will be called as soon as the IRC server
314  
     * disconnects us.
315  
     *
316  
     * @param reason The reason for quitting the server.
317  
     */
318  
    public final void quitServer(String reason) {
319  
        this.sendRawLine("QUIT :" + reason);
320  
    }
321  
    
322  
    
323  
    /**
324  
     * Sends a raw line to the IRC server as soon as possible, bypassing the
325  
     * outgoing message queue.
326  
     *
327  
     * @param line The raw line to send to the IRC server.
328  
     */
329  
    public final synchronized void sendRawLine(String line) {
330  
        if (isConnected()) {
331  
            _inputThread.sendRawLine(line);
332  
        }
333  
    }
334  
    
335  
    /**
336  
     * Sends a raw line through the outgoing message queue.
337  
     * 
338  
     * @param line The raw line to send to the IRC server.
339  
     */
340  
    public final synchronized void sendRawLineViaQueue(String line) {
341  
        if (line == null) {
342  
            throw new NullPointerException("Cannot send null messages to server");
343  
        }
344  
        if (isConnected()) {
345  
            _outQueue.add(line);
346  
        }
347  
    }
348  
    
349  
    
350  
    /**
351  
     * Sends a message to a channel or a private message to a user.  These
352  
     * messages are added to the outgoing message queue and sent at the
353  
     * earliest possible opportunity.
354  
     *  <p>
355  
     * Some examples: -
356  
     *  <pre>    // Send the message "Hello!" to the channel #cs.
357  
     *    sendMessage("#cs", "Hello!");
358  
     *    
359  
     *    // Send a private message to Paul that says "Hi".
360  
     *    sendMessage("Paul", "Hi");</pre>
361  
     *  
362  
     * You may optionally apply colours, boldness, underlining, etc to
363  
     * the message by using the <code>Colors</code> class.
364  
     *
365  
     * @param target The name of the channel or user nick to send to.
366  
     * @param message The message to send.
367  
     * 
368  
     * @see Colors
369  
     */
370  
    public final void sendMessage(String target, String message) {
371  
        _outQueue.add("PRIVMSG " + target + " :" + message);
372  
    }
373  
    
374  
    
375  
    /**
376  
     * Sends an action to the channel or to a user.
377  
     *
378  
     * @param target The name of the channel or user nick to send to.
379  
     * @param action The action to send.
380  
     * 
381  
     * @see Colors
382  
     */
383  
    public final void sendAction(String target, String action) {
384  
        sendCTCPCommand(target, "ACTION " + action);
385  
    }
386  
    
387  
    
388  
    /**
389  
     * Sends a notice to the channel or to a user.
390  
     *
391  
     * @param target The name of the channel or user nick to send to.
392  
     * @param notice The notice to send.
393  
     */
394  
    public final void sendNotice(String target, String notice) {
395  
        _outQueue.add("NOTICE " + target + " :" + notice);
396  
    }
397  
    
398  
    
399  
    /**
400  
     * Sends a CTCP command to a channel or user.  (Client to client protocol).
401  
     * Examples of such commands are "PING <number>", "FINGER", "VERSION", etc.
402  
     * For example, if you wish to request the version of a user called "Dave",
403  
     * then you would call <code>sendCTCPCommand("Dave", "VERSION");</code>.
404  
     * The type of response to such commands is largely dependant on the target
405  
     * client software.
406  
     * 
407  
     * @since PircBot 0.9.5
408  
     *
409  
     * @param target The name of the channel or user to send the CTCP message to.
410  
     * @param command The CTCP command to send.
411  
     */
412  
    public final void sendCTCPCommand(String target, String command) {
413  
        _outQueue.add("PRIVMSG " + target + " :\u0001" + command + "\u0001");
414  
    }
415  
    
416  
    
417  
    /**
418  
     * Attempt to change the current nick (nickname) of the bot when it
419  
     * is connected to an IRC server.
420  
     * After confirmation of a successful nick change, the getNick method
421  
     * will return the new nick.
422  
     *
423  
     * @param newNick The new nick to use.
424  
     */
425  
    public final void changeNick(String newNick) {
426  
        this.sendRawLine("NICK " + newNick);
427  
    }
428  
    
429  
    
430  
    /**
431  
     * Identify the bot with NickServ, supplying the appropriate password.
432  
     * Some IRC Networks (such as freenode) require users to <i>register</i> and
433  
     * <i>identify</i> with NickServ before they are able to send private messages
434  
     * to other users, thus reducing the amount of spam.  If you are using
435  
     * an IRC network where this kind of policy is enforced, you will need
436  
     * to make your bot <i>identify</i> itself to NickServ before you can send
437  
     * private messages. Assuming you have already registered your bot's
438  
     * nick with NickServ, this method can be used to <i>identify</i> with
439  
     * the supplied password. It usually makes sense to identify with NickServ
440  
     * immediately after connecting to a server.
441  
     *  <p>
442  
     * This method issues a raw NICKSERV command to the server, and is therefore
443  
     * safer than the alternative approach of sending a private message to
444  
     * NickServ. The latter approach is considered dangerous, as it may cause
445  
     * you to inadvertently transmit your password to an untrusted party if you
446  
     * connect to a network which does not run a NickServ service and where the
447  
     * untrusted party has assumed the nick "NickServ".  However, if your IRC
448  
     * network is only compatible with the private message approach, you may
449  
     * typically identify like so:
450  
     * <pre>sendMessage("NickServ", "identify PASSWORD");</pre>
451  
     * 
452  
     * @param password The password which will be used to identify with NickServ.
453  
     */
454  
    public final void identify(String password) {
455  
        this.sendRawLine("NICKSERV IDENTIFY " + password);
456  
    }                                        
457  
458  
459  
    /**
460  
     * Set the mode of a channel.
461  
     * This method attempts to set the mode of a channel.  This
462  
     * may require the bot to have operator status on the channel.
463  
     * For example, if the bot has operator status, we can grant
464  
     * operator status to "Dave" on the #cs channel
465  
     * by calling setMode("#cs", "+o Dave");
466  
     * An alternative way of doing this would be to use the op method.
467  
     * 
468  
     * @param channel The channel on which to perform the mode change.
469  
     * @param mode    The new mode to apply to the channel.  This may include
470  
     *                zero or more arguments if necessary.
471  
     * 
472  
     * @see #op(String,String) op
473  
     */
474  
    public final void setMode(String channel, String mode) {
475  
        this.sendRawLine("MODE " + channel + " " + mode);
476  
    }
477  
    
478  
    
479  
    /**
480  
     * Sends an invitation to join a channel.  Some channels can be marked
481  
     * as "invite-only", so it may be useful to allow a bot to invite people
482  
     * into it.
483  
     * 
484  
     * @param nick    The nick of the user to invite
485  
     * @param channel The channel you are inviting the user to join.
486  
     * 
487  
     */
488  
    public final void sendInvite(String nick, String channel) {
489  
        this.sendRawLine("INVITE " + nick + " :" + channel);
490  
    }    
491  
492  
493  
    /**
494  
     * Bans a user from a channel.  An example of a valid hostmask is
495  
     * "*!*compu@*.18hp.net".  This may be used in conjunction with the
496  
     * kick method to permanently remove a user from a channel.
497  
     * Successful use of this method may require the bot to have operator
498  
     * status itself.
499  
     * 
500  
     * @param channel The channel to ban the user from.
501  
     * @param hostmask A hostmask representing the user we're banning.
502  
     */
503  
    public final void ban(String channel, String hostmask) {
504  
        this.sendRawLine("MODE " + channel + " +b " + hostmask);
505  
    }
506  
507  
508  
    /**
509  
     * Unbans a user from a channel.  An example of a valid hostmask is
510  
     * "*!*compu@*.18hp.net".
511  
     * Successful use of this method may require the bot to have operator
512  
     * status itself.
513  
     * 
514  
     * @param channel The channel to unban the user from.
515  
     * @param hostmask A hostmask representing the user we're unbanning.
516  
     */
517  
    public final void unBan(String channel, String hostmask) {
518  
        this.sendRawLine("MODE " + channel + " -b " + hostmask);
519  
    }
520  
521  
522  
    /**
523  
     * Grants operator privilidges to a user on a channel.
524  
     * Successful use of this method may require the bot to have operator
525  
     * status itself.
526  
     * 
527  
     * @param channel The channel we're opping the user on.
528  
     * @param nick The nick of the user we are opping.
529  
     */
530  
    public final void op(String channel, String nick) {
531  
        this.setMode(channel, "+o " + nick);
532  
    }
533  
534  
535  
    /**
536  
     * Removes operator privilidges from a user on a channel.
537  
     * Successful use of this method may require the bot to have operator
538  
     * status itself.
539  
     * 
540  
     * @param channel The channel we're deopping the user on.
541  
     * @param nick The nick of the user we are deopping.
542  
     */
543  
    public final void deOp(String channel, String nick) {
544  
        this.setMode(channel, "-o " + nick);
545  
    }
546  
    
547  
    
548  
    /**
549  
     * Grants voice privilidges to a user on a channel.
550  
     * Successful use of this method may require the bot to have operator
551  
     * status itself.
552  
     * 
553  
     * @param channel The channel we're voicing the user on.
554  
     * @param nick The nick of the user we are voicing.
555  
     */
556  
    public final void voice(String channel, String nick) {
557  
        this.setMode(channel, "+v " + nick);
558  
    }
559  
560  
561  
    /**
562  
     * Removes voice privilidges from a user on a channel.
563  
     * Successful use of this method may require the bot to have operator
564  
     * status itself.
565  
     * 
566  
     * @param channel The channel we're devoicing the user on.
567  
     * @param nick The nick of the user we are devoicing.
568  
     */
569  
    public final void deVoice(String channel, String nick) {
570  
        this.setMode(channel, "-v " + nick);
571  
    }
572  
573  
574  
    /**
575  
     * Set the topic for a channel.
576  
     * This method attempts to set the topic of a channel.  This
577  
     * may require the bot to have operator status if the topic
578  
     * is protected.
579  
     * 
580  
     * @param channel The channel on which to perform the mode change.
581  
     * @param topic   The new topic for the channel.
582  
     * 
583  
     */
584  
    public final void setTopic(String channel, String topic) {
585  
        this.sendRawLine("TOPIC " + channel + " :" + topic);
586  
    }
587  
588  
589  
    /**
590  
     * Kicks a user from a channel.
591  
     * This method attempts to kick a user from a channel and
592  
     * may require the bot to have operator status in the channel.
593  
     * 
594  
     * @param channel The channel to kick the user from.
595  
     * @param nick    The nick of the user to kick.
596  
     */
597  
    public final void kick(String channel, String nick) {
598  
        this.kick(channel, nick, "");
599  
    }
600  
601  
602  
    /**
603  
     * Kicks a user from a channel, giving a reason.
604  
     * This method attempts to kick a user from a channel and
605  
     * may require the bot to have operator status in the channel.
606  
     * 
607  
     * @param channel The channel to kick the user from.
608  
     * @param nick    The nick of the user to kick.
609  
     * @param reason  A description of the reason for kicking a user.
610  
     */
611  
    public final void kick(String channel, String nick, String reason) {
612  
        this.sendRawLine("KICK " + channel + " " + nick + " :" + reason);
613  
    }
614  
    
615  
    
616  
    /**
617  
     * Issues a request for a list of all channels on the IRC server.
618  
     * When the PircBot receives information for each channel, it will
619  
     * call the onChannelInfo method, which you will need to override
620  
     * if you want it to do anything useful.
621  
     * 
622  
     * @see #onChannelInfo(String,int,String) onChannelInfo
623  
     */
624  
    public final void listChannels() {
625  
        this.listChannels(null);
626  
    }
627  
    
628  
    
629  
    /**
630  
     * Issues a request for a list of all channels on the IRC server.
631  
     * When the PircBot receives information for each channel, it will
632  
     * call the onChannelInfo method, which you will need to override
633  
     * if you want it to do anything useful.
634  
     *  <p>
635  
     * Some IRC servers support certain parameters for LIST requests.
636  
     * One example is a parameter of ">10" to list only those channels
637  
     * that have more than 10 users in them.  Whether these parameters
638  
     * are supported or not will depend on the IRC server software.
639  
     * 
640  
     * @param parameters The parameters to supply when requesting the
641  
     *                   list.
642  
     * 
643  
     * @see #onChannelInfo(String,int,String) onChannelInfo
644  
     */
645  
    public final void listChannels(String parameters) {
646  
        if (parameters == null) {
647  
            this.sendRawLine("LIST");
648  
        }
649  
        else {
650  
            this.sendRawLine("LIST " + parameters);
651  
        }
652  
    }
653  
    
654  
    
655  
    /**
656  
     * Sends a file to another user.  Resuming is supported.
657  
     * The other user must be able to connect directly to your bot to be
658  
     * able to receive the file.
659  
     *  <p>
660  
     * You may throttle the speed of this file transfer by calling the
661  
     * setPacketDelay method on the DccFileTransfer that is returned.
662  
     *  <p>
663  
     * This method may not be overridden.
664  
     * 
665  
     * @since 0.9c
666  
     * 
667  
     * @param file The file to send.
668  
     * @param nick The user to whom the file is to be sent.
669  
     * @param timeout The number of milliseconds to wait for the recipient to
670  
     *                acccept the file (we recommend about 120000).
671  
     * 
672  
     * @return The DccFileTransfer that can be used to monitor this transfer.
673  
     * 
674  
     * @see DccFileTransfer
675  
     * 
676  
     */
677  
    public final DccFileTransfer dccSendFile(File file, String nick, int timeout) {
678  
        DccFileTransfer transfer = new DccFileTransfer(this, _dccManager, file, nick, timeout);
679  
        transfer.doSend(true);
680  
        return transfer;
681  
    }
682  
    
683  
    
684  
    /**
685  
     * Receives a file that is being sent to us by a DCC SEND request.
686  
     * Please use the onIncomingFileTransfer method to receive files.
687  
     * 
688  
     * @deprecated As of PircBot 1.2.0, use {@link #onIncomingFileTransfer(DccFileTransfer)}
689  
     */
690  
    protected final void dccReceiveFile(File file, long address, int port, int size) {
691  
        throw new RuntimeException("dccReceiveFile is deprecated, please use sendFile");
692  
    }
693  
    
694  
    
695  
    /**
696  
     * Attempts to establish a DCC CHAT session with a client.  This method
697  
     * issues the connection request to the client and then waits for the
698  
     * client to respond.  If the connection is successfully made, then a
699  
     * DccChat object is returned by this method.  If the connection is not
700  
     * made within the time limit specified by the timeout value, then null
701  
     * is returned.
702  
     *  <p>
703  
     * It is <b>strongly recommended</b> that you call this method within a new
704  
     * Thread, as it may take a long time to return.
705  
     *  <p>
706  
     * This method may not be overridden.
707  
     * 
708  
     * @since PircBot 0.9.8
709  
     *
710  
     * @param nick The nick of the user we are trying to establish a chat with.
711  
     * @param timeout The number of milliseconds to wait for the recipient to
712  
     *                accept the chat connection (we recommend about 120000).
713  
     * 
714  
     * @return a DccChat object that can be used to send and recieve lines of
715  
     *         text.  Returns <b>null</b> if the connection could not be made.
716  
     * 
717  
     * @see DccChat
718  
     */
719  
    public final DccChat dccSendChatRequest(String nick, int timeout) {
720  
        DccChat chat = null;
721  
        try {
722  
            ServerSocket ss = null;
723  
            
724  
            int[] ports = getDccPorts();
725  
            if (ports == null) {
726  
                // Use any free port.
727  
                ss = new ServerSocket(0);
728  
            }
729  
            else {
730  
                for (int i = 0; i < ports.length; i++) {
731  
                    try {
732  
                        ss = new ServerSocket(ports[i]);
733  
                        // Found a port number we could use.
734  
                        break;
735  
                    }
736  
                    catch (Exception e) {
737  
                        // Do nothing; go round and try another port.
738  
                    }
739  
                }
740  
                if (ss == null) {
741  
                    // No ports could be used.
742  
                    throw new IOException("All ports returned by getDccPorts() are in use.");
743  
                }
744  
            }
745  
            
746  
            ss.setSoTimeout(timeout);
747  
            int port = ss.getLocalPort();
748  
            
749  
            InetAddress inetAddress = getDccInetAddress();
750  
            if (inetAddress == null) {
751  
                inetAddress = getInetAddress();
752  
            }
753  
            byte[] ip = inetAddress.getAddress();
754  
            long ipNum = ipToLong(ip);
755  
            
756  
            sendCTCPCommand(nick, "DCC CHAT chat " + ipNum + " " + port);
757  
            
758  
            // The client may now connect to us to chat.
759  
            Socket socket = ss.accept();
760  
            
761  
            // Close the server socket now that we've finished with it.
762  
            ss.close();
763  
            
764  
            chat = new DccChat(this, nick, socket);
765  
        }
766  
        catch (Exception e) {
767  
            // Do nothing.
768  
        }
769  
        return chat;
770  
    }
771  
772  
    
773  
    /**
774  
     * Attempts to accept a DCC CHAT request by a client.
775  
     * Please use the onIncomingChatRequest method to receive files.
776  
     * 
777  
     * @deprecated As of PircBot 1.2.0, use {@link #onIncomingChatRequest(DccChat)}
778  
     */
779  
    protected final DccChat dccAcceptChatRequest(String sourceNick, long address, int port) {
780  
        throw new RuntimeException("dccAcceptChatRequest is deprecated, please use onIncomingChatRequest");
781  
    }
782  
783  
784  
    /**
785  
     * Adds a line to the log.  This log is currently output to the standard
786  
     * output and is in the correct format for use by tools such as pisg, the
787  
     * Perl IRC Statistics Generator.  You may override this method if you wish
788  
     * to do something else with log entries.
789  
     * Each line in the log begins with a number which
790  
     * represents the logging time (as the number of milliseconds since the
791  
     * epoch).  This timestamp and the following log entry are separated by
792  
     * a single space character, " ".  Outgoing messages are distinguishable
793  
     * by a log entry that has ">>>" immediately following the space character
794  
     * after the timestamp.  DCC events use "+++" and warnings about unhandled
795  
     * Exceptions and Errors use "###".
796  
     *  <p>
797  
     * This implementation of the method will only cause log entries to be
798  
     * output if the PircBot has had its verbose mode turned on by calling
799  
     * setVerbose(true);
800  
     * 
801  
     * @param line The line to add to the log.
802  
     */
803  
    public void log(String line) {
804  
        if (_verbose) {
805  
            System.out.println(System.currentTimeMillis() + " " + line);
806  
        }
807  
    }
808  
809  
810  
    /**
811  
     * This method handles events when any line of text arrives from the server,
812  
     * then calling the appropriate method in the PircBot.  This method is
813  
     * protected and only called by the InputThread for this instance.
814  
     *  <p>
815  
     * This method may not be overridden!
816  
     * 
817  
     * @param line The raw line of text from the server.
818  
     */
819  
    protected void handleLine(String line) {
820  
        this.log(line);
821  
822  
        // Check for server pings.
823  
        if (line.startsWith("PING ")) {
824  
            // Respond to the ping and return immediately.
825  
            this.onServerPing(line.substring(5));
826  
            return;
827  
        }
828  
829  
        String sourceNick = "";
830  
        String sourceLogin = "";
831  
        String sourceHostname = "";
832  
833  
        StringTokenizer tokenizer = new StringTokenizer(line);
834  
        String senderInfo = tokenizer.nextToken();
835  
        String command = tokenizer.nextToken();
836  
        String target = null;
837  
838  
        int exclamation = senderInfo.indexOf("!");
839  
        int at = senderInfo.indexOf("@");
840  
        if (senderInfo.startsWith(":")) {
841  
            if (exclamation > 0 && at > 0 && exclamation < at) {
842  
                sourceNick = senderInfo.substring(1, exclamation);
843  
                sourceLogin = senderInfo.substring(exclamation + 1, at);
844  
                sourceHostname = senderInfo.substring(at + 1);
845  
            }
846  
            else {
847  
                
848  
                if (tokenizer.hasMoreTokens()) {
849  
                    String token = command;
850  
851  
                    int code = -1;
852  
                    try {
853  
                        code = Integer.parseInt(token);
854  
                    }
855  
                    catch (NumberFormatException e) {
856  
                        // Keep the existing value.
857  
                    }
858  
                    
859  
                    if (code != -1) {
860  
                        String errorStr = token;
861  
                        String response = line.substring(line.indexOf(errorStr, senderInfo.length()) + 4, line.length());
862  
                        this.processServerResponse(code, response);
863  
                        // Return from the method.
864  
                        return;
865  
                    }
866  
                    else {
867  
                        // This is not a server response.
868  
                        // It must be a nick without login and hostname.
869  
                        // (or maybe a NOTICE or suchlike from the server)
870  
                        sourceNick = senderInfo;
871  
                        target = token;
872  
                    }
873  
                }
874  
                else {
875  
                    // We don't know what this line means.
876  
                    this.onUnknown(line);
877  
                    // Return from the method;
878  
                    return;
879  
                }
880  
                
881  
            }
882  
        }
883  
        
884  
        command = command.toUpperCase();
885  
        if (sourceNick.startsWith(":")) {
886  
            sourceNick = sourceNick.substring(1);
887  
        }
888  
        if (target == null) {
889  
            target = tokenizer.nextToken();
890  
        }
891  
        if (target.startsWith(":")) {
892  
            target = target.substring(1);
893  
        }
894  
895  
        // Check for CTCP requests.
896  
        if (command.equals("PRIVMSG") && line.indexOf(":\u0001") > 0 && line.endsWith("\u0001")) {
897  
            String request = line.substring(line.indexOf(":\u0001") + 2, line.length() - 1);
898  
            if (request.equals("VERSION")) {
899  
                // VERSION request
900  
                this.onVersion(sourceNick, sourceLogin, sourceHostname, target);
901  
            }
902  
            else if (request.startsWith("ACTION ")) {
903  
                // ACTION request
904  
                this.onAction(sourceNick, sourceLogin, sourceHostname, target, request.substring(7));
905  
            }
906  
            else if (request.startsWith("PING ")) {
907  
                // PING request
908  
                this.onPing(sourceNick, sourceLogin, sourceHostname, target, request.substring(5));
909  
            }
910  
            else if (request.equals("TIME")) {
911  
                // TIME request
912  
                this.onTime(sourceNick, sourceLogin, sourceHostname, target);
913  
            }
914  
            else if (request.equals("FINGER")) {
915  
                // FINGER request
916  
                this.onFinger(sourceNick, sourceLogin, sourceHostname, target);
917  
            }
918  
            else if ((tokenizer = new StringTokenizer(request)).countTokens() >= 5 && tokenizer.nextToken().equals("DCC")) {
919  
                // This is a DCC request.
920  
                boolean success = _dccManager.processRequest(sourceNick, sourceLogin, sourceHostname, request);
921  
                if (!success) {
922  
                    // The DccManager didn't know what to do with the line.
923  
                    this.onUnknown(line);
924  
                }
925  
            }
926  
            else {            
927  
                // An unknown CTCP message - ignore it.
928  
                this.onUnknown(line);
929  
            }
930  
        }
931  
        else if (command.equals("PRIVMSG") && _channelPrefixes.indexOf(target.charAt(0)) >= 0) {
932  
            // This is a normal message to a channel.
933  
            this.onMessage(target, sourceNick, sourceLogin, sourceHostname, line.substring(line.indexOf(" :") + 2));
934  
        }
935  
        else if (command.equals("PRIVMSG")) {
936  
            // This is a private message to us.
937  
            this.onPrivateMessage(sourceNick, sourceLogin, sourceHostname, line.substring(line.indexOf(" :") + 2));
938  
        }
939  
        else if (command.equals("JOIN")) {
940  
            // Someone is joining a channel.
941  
            String channel = target;
942  
            this.addUser(channel, new User("", sourceNick));
943  
            this.onJoin(channel, sourceNick, sourceLogin, sourceHostname);
944  
        }
945  
        else if (command.equals("PART")) {
946  
            // Someone is parting from a channel.
947  
            this.removeUser(target, sourceNick);
948  
            if (sourceNick.equals(this.getNick())) {
949  
                this.removeChannel(target);
950  
            }
951  
            this.onPart(target, sourceNick, sourceLogin, sourceHostname);
952  
        }
953  
        else if (command.equals("NICK")) {
954  
            // Somebody is changing their nick.
955  
            String newNick = target;
956  
            this.renameUser(sourceNick, newNick);
957  
            if (sourceNick.equals(this.getNick())) {
958  
                // Update our nick if it was us that changed nick.
959  
                this.setNick(newNick);
960  
            }
961  
            this.onNickChange(sourceNick, sourceLogin, sourceHostname, newNick);
962  
        }
963  
        else if (command.equals("NOTICE")) {
964  
            // Someone is sending a notice.
965  
            this.onNotice(sourceNick, sourceLogin, sourceHostname, target, line.substring(line.indexOf(" :") + 2));
966  
        }
967  
        else if (command.equals("QUIT")) {
968  
            // Someone has quit from the IRC server.
969  
            if (sourceNick.equals(this.getNick())) {
970  
                this.removeAllChannels();
971  
            }
972  
            else {
973  
                this.removeUser(sourceNick);
974  
            }
975  
            this.onQuit(sourceNick, sourceLogin, sourceHostname, line.substring(line.indexOf(" :") + 2));
976  
        }
977  
        else if (command.equals("KICK")) {
978  
            // Somebody has been kicked from a channel.
979  
            String recipient = tokenizer.nextToken();
980  
            if (recipient.equals(this.getNick())) {
981  
                this.removeChannel(target);
982  
            }
983  
            this.removeUser(target, recipient);
984  
            this.onKick(target, sourceNick, sourceLogin, sourceHostname, recipient, line.substring(line.indexOf(" :") + 2));
985  
        }
986  
        else if (command.equals("MODE")) {
987  
            // Somebody is changing the mode on a channel or user.
988  
            String mode = line.substring(line.indexOf(target, 2) + target.length() + 1);
989  
            if (mode.startsWith(":")) {
990  
                mode = mode.substring(1);
991  
            }
992  
            this.processMode(target, sourceNick, sourceLogin, sourceHostname, mode);
993  
        }
994  
        else if (command.equals("TOPIC")) {
995  
            // Someone is changing the topic.
996  
            this.onTopic(target, line.substring(line.indexOf(" :") + 2), sourceNick, System.currentTimeMillis(), true);
997  
        }
998  
        else if (command.equals("INVITE")) {
999  
            // Somebody is inviting somebody else into a channel.
1000  
            this.onInvite(target, sourceNick, sourceLogin, sourceHostname, line.substring(line.indexOf(" :") + 2));
1001  
        }
1002  
        else {
1003  
            // If we reach this point, then we've found something that the PircBot
1004  
            // Doesn't currently deal with.
1005  
            this.onUnknown(line);
1006  
        }
1007  
        
1008  
    }
1009  
    
1010  
    
1011  
    /**
1012  
     * This method is called once the PircBot has successfully connected to
1013  
     * the IRC server.
1014  
     *  <p>
1015  
     * The implementation of this method in the PircBot abstract class
1016  
     * performs no actions and may be overridden as required.
1017  
     * 
1018  
     * @since PircBot 0.9.6
1019  
     */
1020  
    protected void onConnect() {}
1021  
    
1022  
    
1023  
    /**
1024  
     * This method carries out the actions to be performed when the PircBot
1025  
     * gets disconnected.  This may happen if the PircBot quits from the
1026  
     * server, or if the connection is unexpectedly lost.
1027  
     *  <p>
1028  
     * Disconnection from the IRC server is detected immediately if either
1029  
     * we or the server close the connection normally. If the connection to
1030  
     * the server is lost, but neither we nor the server have explicitly closed
1031  
     * the connection, then it may take a few minutes to detect (this is
1032  
     * commonly referred to as a "ping timeout").
1033  
     *  <p>
1034  
     * If you wish to get your IRC bot to automatically rejoin a server after
1035  
     * the connection has been lost, then this is probably the ideal method to
1036  
     * override to implement such functionality.
1037  
     *  <p>
1038  
     * The implementation of this method in the PircBot abstract class
1039  
     * performs no actions and may be overridden as required.
1040  
     */
1041  
    protected void onDisconnect() {}
1042  
    
1043  
    
1044  
    /**
1045  
     * This method is called by the PircBot when a numeric response
1046  
     * is received from the IRC server.  We use this method to
1047  
     * allow PircBot to process various responses from the server
1048  
     * before then passing them on to the onServerResponse method.
1049  
     *  <p>
1050  
     * Note that this method is private and should not appear in any
1051  
     * of the javadoc generated documenation.
1052  
     * 
1053  
     * @param code The three-digit numerical code for the response.
1054  
     * @param response The full response from the IRC server.
1055  
     */
1056  
    private final void processServerResponse(int code, String response) {
1057  
        
1058  
        if (code == RPL_LIST) {
1059  
            // This is a bit of information about a channel.
1060  
            int firstSpace = response.indexOf(' ');
1061  
            int secondSpace = response.indexOf(' ', firstSpace + 1);
1062  
            int thirdSpace = response.indexOf(' ', secondSpace + 1);
1063  
            int colon = response.indexOf(':');
1064  
            String channel = response.substring(firstSpace + 1, secondSpace);
1065  
            int userCount = 0;
1066  
            try {
1067  
                userCount = Integer.parseInt(response.substring(secondSpace + 1, thirdSpace));
1068  
            }
1069  
            catch (NumberFormatException e) {
1070  
                // Stick with the value of zero.
1071  
            }
1072  
            String topic = response.substring(colon + 1);
1073  
            this.onChannelInfo(channel, userCount, topic);
1074  
        }
1075  
        else if (code == RPL_TOPIC) {
1076  
            // This is topic information about a channel we've just joined.
1077  
            int firstSpace = response.indexOf(' ');
1078  
            int secondSpace = response.indexOf(' ', firstSpace + 1);
1079  
            int colon = response.indexOf(':');
1080  
            String channel = response.substring(firstSpace + 1, secondSpace);
1081  
            String topic = response.substring(colon + 1);
1082  
            
1083  
            _topics.put(channel, topic);
1084  
            
1085  
            // For backwards compatibility only - this onTopic method is deprecated.
1086  
            this.onTopic(channel, topic);
1087  
        }
1088  
        else if (code == RPL_TOPICINFO) {
1089  
            StringTokenizer tokenizer = new StringTokenizer(response);
1090  
            tokenizer.nextToken();
1091  
            String channel = tokenizer.nextToken();
1092  
            String setBy = tokenizer.nextToken();
1093  
            long date = 0;
1094  
            try {
1095  
                date = Long.parseLong(tokenizer.nextToken()) * 1000;
1096  
            }
1097  
            catch (NumberFormatException e) {
1098  
                // Stick with the default value of zero.
1099  
            }
1100  
            
1101  
            String topic = (String) _topics.get(channel);
1102  
            _topics.remove(channel);
1103  
            
1104  
            this.onTopic(channel, topic, setBy, date, false);
1105  
        }
1106  
        else if (code == RPL_NAMREPLY) {
1107  
            // This is a list of nicks in a channel that we've just joined.
1108  
            int channelEndIndex = response.indexOf(" :");
1109  
            String channel = response.substring(response.lastIndexOf(' ', channelEndIndex - 1) + 1, channelEndIndex);
1110  
            
1111  
            StringTokenizer tokenizer = new StringTokenizer(response.substring(response.indexOf(" :") + 2));
1112  
            while (tokenizer.hasMoreTokens()) {
1113  
                String nick = tokenizer.nextToken();
1114  
                String prefix = "";
1115  
                if (nick.startsWith("@")) {
1116  
                    // User is an operator in this channel.
1117  
                    prefix = "@";
1118  
                }
1119  
                else if (nick.startsWith("+")) {
1120  
                    // User is voiced in this channel.
1121  
                    prefix = "+";
1122  
                }
1123  
                else if (nick.startsWith(".")) {
1124  
                    // Some wibbly status I've never seen before...
1125  
                    prefix = ".";
1126  
                }
1127  
                nick = nick.substring(prefix.length());
1128  
                this.addUser(channel, new User(prefix, nick));
1129  
            }
1130  
        }
1131  
        else if (code == RPL_ENDOFNAMES) {
1132  
            // This is the end of a NAMES list, so we know that we've got
1133  
            // the full list of users in the channel that we just joined. 
1134  
            String channel = response.substring(response.indexOf(' ') + 1, response.indexOf(" :"));
1135  
            User[] users = this.getUsers(channel);
1136  
            this.onUserList(channel, users);
1137  
        }
1138  
        
1139  
        this.onServerResponse(code, response);
1140  
    }
1141  
1142  
1143  
    /**
1144  
     * This method is called when we receive a numeric response from the
1145  
     * IRC server.
1146  
     *  <p> 
1147  
     * Numerics in the range from 001 to 099 are used for client-server
1148  
     * connections only and should never travel between servers.  Replies
1149  
     * generated in response to commands are found in the range from 200
1150  
     * to 399.  Error replies are found in the range from 400 to 599.
1151  
     *  <p>
1152  
     * For example, we can use this method to discover the topic of a
1153  
     * channel when we join it.  If we join the channel #test which
1154  
     * has a topic of &quot;I am King of Test&quot; then the response
1155  
     * will be &quot;<code>PircBot #test :I Am King of Test</code>&quot;
1156  
     * with a code of 332 to signify that this is a topic.
1157  
     * (This is just an example - note that overriding the
1158  
     * <code>onTopic</code> method is an easier way of finding the
1159  
     * topic for a channel). Check the IRC RFC for the full list of other
1160  
     * command response codes.
1161  
     *  <p>
1162  
     * PircBot implements the interface ReplyConstants, which contains
1163  
     * contstants that you may find useful here.
1164  
     *  <p>
1165  
     * The implementation of this method in the PircBot abstract class
1166  
     * performs no actions and may be overridden as required.
1167  
     * 
1168  
     * @param code The three-digit numerical code for the response.
1169  
     * @param response The full response from the IRC server.
1170  
     * 
1171  
     * @see ReplyConstants
1172  
     */
1173  
    protected void onServerResponse(int code, String response) {}
1174  
    
1175  
    
1176  
    /**
1177  
     * This method is called when we receive a user list from the server
1178  
     * after joining a channel.
1179  
     *  <p>
1180  
     * Shortly after joining a channel, the IRC server sends a list of all
1181  
     * users in that channel. The PircBot collects this information and
1182  
     * calls this method as soon as it has the full list.
1183  
     *  <p>
1184  
     * To obtain the nick of each user in the channel, call the getNick()
1185  
     * method on each User object in the array.
1186  
     *  <p>
1187  
     * At a later time, you may call the getUsers method to obtain an
1188  
     * up to date list of the users in the channel.
1189  
     *  <p>
1190  
     * The implementation of this method in the PircBot abstract class
1191  
     * performs no actions and may be overridden as required.
1192  
     * 
1193  
     * @since PircBot 1.0.0
1194  
     * 
1195  
     * @param channel The name of the channel.
1196  
     * @param users An array of User objects belonging to this channel.
1197  
     * 
1198  
     * @see User
1199  
     */
1200  
    protected void onUserList(String channel, User[] users) {}
1201  
    
1202  
    
1203  
    /**
1204  
     * This method is called whenever a message is sent to a channel.
1205  
     *  <p>
1206  
     * The implementation of this method in the PircBot abstract class
1207  
     * performs no actions and may be overridden as required.
1208  
     *
1209  
     * @param channel The channel to which the message was sent.
1210  
     * @param sender The nick of the person who sent the message.
1211  
     * @param login The login of the person who sent the message.
1212  
     * @param hostname The hostname of the person who sent the message.
1213  
     * @param message The actual message sent to the channel.
1214  
     */
1215  
    protected void onMessage(String channel, String sender, String login, String hostname, String message) {}
1216  
1217  
1218  
    /**
1219  
     * This method is called whenever a private message is sent to the PircBot.
1220  
     *  <p>
1221  
     * The implementation of this method in the PircBot abstract class
1222  
     * performs no actions and may be overridden as required.
1223  
     *
1224  
     * @param sender The nick of the person who sent the private message.
1225  
     * @param login The login of the person who sent the private message.
1226  
     * @param hostname The hostname of the person who sent the private message.
1227  
     * @param message The actual message.
1228  
     */
1229  
    protected void onPrivateMessage(String sender, String login, String hostname, String message) {}
1230  
    
1231  
    
1232  
    /**
1233  
     * This method is called whenever an ACTION is sent from a user.  E.g.
1234  
     * such events generated by typing "/me goes shopping" in most IRC clients.
1235  
     *  <p>
1236  
     * The implementation of this method in the PircBot abstract class
1237  
     * performs no actions and may be overridden as required.
1238  
     * 
1239  
     * @param sender The nick of the user that sent the action.
1240  
     * @param login The login of the user that sent the action.
1241  
     * @param hostname The hostname of the user that sent the action.
1242  
     * @param target The target of the action, be it a channel or our nick.
1243  
     * @param action The action carried out by the user.
1244  
     */
1245  
    protected void onAction(String sender, String login, String hostname, String target, String action) {}
1246  
    
1247  
    
1248  
    /**
1249  
     * This method is called whenever we receive a notice.
1250  
     *  <p>
1251  
     * The implementation of this method in the PircBot abstract class
1252  
     * performs no actions and may be overridden as required.
1253  
     * 
1254  
     * @param sourceNick The nick of the user that sent the notice.
1255  
     * @param sourceLogin The login of the user that sent the notice.
1256  
     * @param sourceHostname The hostname of the user that sent the notice.
1257  
     * @param target The target of the notice, be it our nick or a channel name.
1258  
     * @param notice The notice message.
1259  
     */
1260  
    protected void onNotice(String sourceNick, String sourceLogin, String sourceHostname, String target, String notice) {}
1261  
    
1262  
    
1263  
    /**
1264  
     * This method is called whenever someone (possibly us) joins a channel
1265  
     * which we are on.
1266  
     *  <p>
1267  
     * The implementation of this method in the PircBot abstract class
1268  
     * performs no actions and may be overridden as required.
1269  
     *
1270  
     * @param channel The channel which somebody joined.
1271  
     * @param sender The nick of the user who joined the channel.
1272  
     * @param login The login of the user who joined the channel.
1273  
     * @param hostname The hostname of the user who joined the channel.
1274  
     */
1275  
    protected void onJoin(String channel, String sender, String login, String hostname) {}
1276  
    
1277  
    
1278  
    /**
1279  
     * This method is called whenever someone (possibly us) parts a channel
1280  
     * which we are on.
1281  
     *  <p>
1282  
     * The implementation of this method in the PircBot abstract class
1283  
     * performs no actions and may be overridden as required.
1284  
     *
1285  
     * @param channel The channel which somebody parted from.
1286  
     * @param sender The nick of the user who parted from the channel.
1287  
     * @param login The login of the user who parted from the channel.
1288  
     * @param hostname The hostname of the user who parted from the channel.
1289  
     */
1290  
    protected void onPart(String channel, String sender, String login, String hostname) {}
1291  
1292  
1293  
    /**
1294  
     * This method is called whenever someone (possibly us) changes nick on any
1295  
     * of the channels that we are on.
1296  
     *  <p>
1297  
     * The implementation of this method in the PircBot abstract class
1298  
     * performs no actions and may be overridden as required.
1299  
     *
1300  
     * @param oldNick The old nick.
1301  
     * @param login The login of the user.
1302  
     * @param hostname The hostname of the user.
1303  
     * @param newNick The new nick.
1304  
     */
1305  
    protected void onNickChange(String oldNick, String login, String hostname, String newNick) {}
1306  
    
1307  
    
1308  
    /**
1309  
     * This method is called whenever someone (possibly us) is kicked from
1310  
     * any of the channels that we are in.
1311  
     *  <p>
1312  
     * The implementation of this method in the PircBot abstract class
1313  
     * performs no actions and may be overridden as required.
1314  
     * 
1315  
     * @param channel The channel from which the recipient was kicked.
1316  
     * @param kickerNick The nick of the user who performed the kick.
1317  
     * @param kickerLogin The login of the user who performed the kick.
1318  
     * @param kickerHostname The hostname of the user who performed the kick.
1319  
     * @param recipientNick The unfortunate recipient of the kick.
1320  
     * @param reason The reason given by the user who performed the kick.
1321  
     */
1322  
    protected void onKick(String channel, String kickerNick, String kickerLogin, String kickerHostname, String recipientNick, String reason) {}
1323  
    
1324  
    
1325  
    /**
1326  
     * This method is called whenever someone (possibly us) quits from the
1327  
     * server.  We will only observe this if the user was in one of the
1328  
     * channels to which we are connected.
1329  
     *  <p>
1330  
     * The implementation of this method in the PircBot abstract class
1331  
     * performs no actions and may be overridden as required.
1332  
     * 
1333  
     * @param sourceNick The nick of the user that quit from the server.
1334  
     * @param sourceLogin The login of the user that quit from the server.
1335  
     * @param sourceHostname The hostname of the user that quit from the server.
1336  
     * @param reason The reason given for quitting the server.
1337  
     */
1338  
    protected void onQuit(String sourceNick, String sourceLogin, String sourceHostname, String reason) {}
1339  
    
1340  
    
1341  
    /**
1342  
     * This method is called whenever a user sets the topic, or when
1343  
     * PircBot joins a new channel and discovers its topic.
1344  
     *  <p>
1345  
     * The implementation of this method in the PircBot abstract class
1346  
     * performs no actions and may be overridden as required.
1347  
     *
1348  
     * @param channel The channel that the topic belongs to.
1349  
     * @param topic The topic for the channel.
1350  
     * 
1351  
     * @deprecated As of 1.2.0, replaced by {@link #onTopic(String,String,String,long,boolean)}
1352  
     */
1353  
    protected void onTopic(String channel, String topic) {}
1354  
    
1355  
1356  
    /**
1357  
     * This method is called whenever a user sets the topic, or when
1358  
     * PircBot joins a new channel and discovers its topic.
1359  
     *  <p>
1360  
     * The implementation of this method in the PircBot abstract class
1361  
     * performs no actions and may be overridden as required.
1362  
     *
1363  
     * @param channel The channel that the topic belongs to.
1364  
     * @param topic The topic for the channel.
1365  
     * @param setBy The nick of the user that set the topic.
1366  
     * @param date When the topic was set (milliseconds since the epoch).
1367  
     * @param changed True if the topic has just been changed, false if
1368  
     *                the topic was already there.
1369  
     * 
1370  
     */
1371  
    protected void onTopic(String channel, String topic, String setBy, long date, boolean changed) {}
1372  
    
1373  
    
1374  
    /**
1375  
     * After calling the listChannels() method in PircBot, the server
1376  
     * will start to send us information about each channel on the
1377  
     * server.  You may override this method in order to receive the
1378  
     * information about each channel as soon as it is received.
1379  
     *  <p>
1380  
     * Note that certain channels, such as those marked as hidden,
1381  
     * may not appear in channel listings.
1382  
     *  <p>
1383  
     * The implementation of this method in the PircBot abstract class
1384  
     * performs no actions and may be overridden as required.
1385  
     * 
1386  
     * @param channel The name of the channel.
1387  
     * @param userCount The number of users visible in this channel.
1388  
     * @param topic The topic for this channel.
1389  
     * 
1390  
     * @see #listChannels() listChannels
1391  
     */
1392  
    protected void onChannelInfo(String channel, int userCount, String topic) {}
1393  
      
1394  
    
1395  
    /**
1396  
     * Called when the mode of a channel is set.  We process this in
1397  
     * order to call the appropriate onOp, onDeop, etc method before
1398  
     * finally calling the override-able onMode method.
1399  
     *  <p>
1400  
     * Note that this method is private and is not intended to appear
1401  
     * in the javadoc generated documentation.
1402  
     *
1403  
     * @param target The channel or nick that the mode operation applies to.
1404  
     * @param sourceNick The nick of the user that set the mode.
1405  
     * @param sourceLogin The login of the user that set the mode.
1406  
     * @param sourceHostname The hostname of the user that set the mode.
1407  
     * @param mode  The mode that has been set.
1408  
     */
1409  
    private final void processMode(String target, String sourceNick, String sourceLogin, String sourceHostname, String mode) {
1410  
        
1411  
        if (_channelPrefixes.indexOf(target.charAt(0)) >= 0) {
1412  
            // The mode of a channel is being changed.
1413  
            String channel = target;
1414  
            StringTokenizer tok = new StringTokenizer(mode);
1415  
            String[] params = new String[tok.countTokens()];
1416  
     
1417  
            int t = 0;
1418  
            while (tok.hasMoreTokens()) {
1419  
                params[t] = tok.nextToken();
1420  
                t++;
1421  
            }
1422  
            
1423  
            char pn = ' ';
1424  
            int p = 1;
1425  
     
1426  
            // All of this is very large and ugly, but it's the only way of providing
1427  
            // what the users want :-/
1428  
            for (int i = 0; i < params[0].length(); i++) {
1429  
                char atPos = params[0].charAt(i);
1430  
     
1431  
                if (atPos == '+' || atPos == '-') {
1432  
                    pn = atPos;
1433  
                }
1434  
                else if (atPos == 'o') {
1435  
                   if (pn == '+') {
1436  
                       this.updateUser(channel, OP_ADD, params[p]);
1437  
                       onOp(channel, sourceNick, sourceLogin, sourceHostname, params[p]);
1438  
                   }
1439  
                   else {
1440  
                       this.updateUser(channel, OP_REMOVE, params[p]);
1441  
                       onDeop(channel, sourceNick, sourceLogin, sourceHostname, params[p]);
1442  
                   }
1443  
                   p++;
1444  
               }
1445  
               else if (atPos == 'v') {
1446  
                   if (pn == '+') {
1447  
                       this.updateUser(channel, VOICE_ADD, params[p]);
1448  
                       onVoice(channel, sourceNick, sourceLogin, sourceHostname, params[p]);
1449  
                   }
1450  
                   else {
1451  
                       this.updateUser(channel, VOICE_REMOVE, params[p]);
1452  
                       onDeVoice(channel, sourceNick, sourceLogin, sourceHostname, params[p]);
1453  
                   }
1454  
                   p++; 
1455  
                }
1456  
                else if (atPos == 'k') {
1457  
                    if (pn == '+') {
1458  
                        onSetChannelKey(channel, sourceNick, sourceLogin, sourceHostname, params[p]);
1459  
                    }
1460  
                    else {
1461  
                        onRemoveChannelKey(channel, sourceNick, sourceLogin, sourceHostname, params[p]);
1462  
                    }
1463  
                    p++;
1464  
                }
1465  
                else if (atPos == 'l') {
1466  
                    if (pn == '+') {
1467  
                        onSetChannelLimit(channel, sourceNick, sourceLogin, sourceHostname, Integer.parseInt(params[p]));
1468  
                        p++;
1469  
                    }
1470  
                    else {
1471  
                        onRemoveChannelLimit(channel, sourceNick, sourceLogin, sourceHostname);
1472  
                    }
1473  
                }
1474  
                else if (atPos == 'b') {
1475  
                    if (pn == '+') {
1476  
                        onSetChannelBan(channel, sourceNick, sourceLogin, sourceHostname,params[p]);
1477  
                    }
1478  
                    else {
1479  
                        onRemoveChannelBan(channel, sourceNick, sourceLogin, sourceHostname, params[p]);
1480  
                    }
1481  
                    p++;
1482  
                }
1483  
                else if (atPos == 't') {
1484  
                    if (pn == '+') {
1485  
                        onSetTopicProtection(channel, sourceNick, sourceLogin, sourceHostname);
1486  
                    }
1487  
                    else {
1488  
                        onRemoveTopicProtection(channel, sourceNick, sourceLogin, sourceHostname);
1489  
                    }
1490  
                }
1491  
                else if (atPos == 'n') {
1492  
                    if (pn == '+') {
1493  
                        onSetNoExternalMessages(channel, sourceNick, sourceLogin, sourceHostname);
1494  
                    }
1495  
                    else {
1496  
                        onRemoveNoExternalMessages(channel, sourceNick, sourceLogin, sourceHostname);
1497  
                    }
1498  
                }
1499  
                else if (atPos == 'i') {
1500  
                    if (pn == '+') {
1501  
                        onSetInviteOnly(channel, sourceNick, sourceLogin, sourceHostname);
1502  
                    }
1503  
                    else {
1504  
                        onRemoveInviteOnly(channel, sourceNick, sourceLogin, sourceHostname);
1505  
                    }
1506  
                }
1507  
                else if (atPos == 'm') {
1508  
                    if (pn == '+') {
1509  
                        onSetModerated(channel, sourceNick, sourceLogin, sourceHostname);
1510  
                    }
1511  
                    else {
1512  
                        onRemoveModerated(channel, sourceNick, sourceLogin, sourceHostname);
1513  
                    }
1514  
                }
1515  
                else if (atPos == 'p') {
1516  
                    if (pn == '+') {
1517  
                        onSetPrivate(channel, sourceNick, sourceLogin, sourceHostname);
1518  
                    }
1519  
                    else {
1520  
                        onRemovePrivate(channel, sourceNick, sourceLogin, sourceHostname);
1521  
                    }
1522  
                }
1523  
                else if (atPos == 's') {
1524  
                    if (pn == '+') {
1525  
                        onSetSecret(channel, sourceNick, sourceLogin, sourceHostname);
1526  
                    }
1527  
                    else {
1528  
                        onRemoveSecret(channel, sourceNick, sourceLogin, sourceHostname);
1529  
                    }
1530  
                }
1531  
            }
1532  
        
1533  
            this.onMode(channel, sourceNick, sourceLogin, sourceHostname, mode);
1534  
        }
1535  
        else {
1536  
            // The mode of a user is being changed.
1537  
            String nick = target;
1538  
            this.onUserMode(nick, sourceNick, sourceLogin, sourceHostname, mode);
1539  
        }
1540  
    }
1541  
    
1542  
    
1543  
    /**
1544  
     * Called when the mode of a channel is set.
1545  
     *  <p>
1546  
     * You may find it more convenient to decode the meaning of the mode
1547  
     * string by overriding the onOp, onDeOp, onVoice, onDeVoice,
1548  
     * onChannelKey, onDeChannelKey, onChannelLimit, onDeChannelLimit,
1549  
     * onChannelBan or onDeChannelBan methods as appropriate.
1550  
     *  <p>
1551  
     * The implementation of this method in the PircBot abstract class
1552  
     * performs no actions and may be overridden as required.
1553  
     *
1554  
     * @param channel The channel that the mode operation applies to.
1555  
     * @param sourceNick The nick of the user that set the mode.
1556  
     * @param sourceLogin The login of the user that set the mode.
1557  
     * @param sourceHostname The hostname of the user that set the mode.
1558  
     * @param mode The mode that has been set.
1559  
     * 
1560  
     */
1561  
    protected void onMode(String channel, String sourceNick, String sourceLogin, String sourceHostname, String mode) {}
1562  
1563  
    
1564  
    /**
1565  
     * Called when the mode of a user is set.
1566  
     *  <p>
1567  
     * The implementation of this method in the PircBot abstract class
1568  
     * performs no actions and may be overridden as required.
1569  
     * 
1570  
     * @since PircBot 1.2.0
1571  
     * 
1572  
     * @param targetNick The nick that the mode operation applies to.
1573  
     * @param sourceNick The nick of the user that set the mode.
1574  
     * @param sourceLogin The login of the user that set the mode.
1575  
     * @param sourceHostname The hostname of the user that set the mode.
1576  
     * @param mode The mode that has been set.
1577  
     * 
1578  
     */
1579  
    protected void onUserMode(String targetNick, String sourceNick, String sourceLogin, String sourceHostname, String mode) {}
1580  
    
1581  
    
1582  
    
1583  
    /**
1584  
     * Called when a user (possibly us) gets granted operator status for a channel.
1585  
     *  <p>
1586  
     * This is a type of mode change and is also passed to the onMode
1587  
     * method in the PircBot class.
1588  
     *  <p>
1589  
     * The implementation of this method in the PircBot abstract class
1590  
     * performs no actions and may be overridden as required.
1591  
     * 
1592  
     * @since PircBot 0.9.5
1593  
     *
1594  
     * @param channel The channel in which the mode change took place.
1595  
     * @param sourceNick The nick of the user that performed the mode change.
1596  
     * @param sourceLogin The login of the user that performed the mode change.
1597  
     * @param sourceHostname The hostname of the user that performed the mode change.
1598  
     * @param recipient The nick of the user that got 'opped'.
1599  
     */
1600  
    protected void onOp(String channel, String sourceNick, String sourceLogin, String sourceHostname, String recipient) {}
1601  
1602  
1603  
    /**
1604  
     * Called when a user (possibly us) gets operator status taken away.
1605  
     *  <p>
1606  
     * This is a type of mode change and is also passed to the onMode
1607  
     * method in the PircBot class.
1608  
     *  <p>
1609  
     * The implementation of this method in the PircBot abstract class
1610  
     * performs no actions and may be overridden as required.
1611  
     * 
1612  
     * @since PircBot 0.9.5
1613  
     *
1614  
     * @param channel The channel in which the mode change took place.
1615  
     * @param sourceNick The nick of the user that performed the mode change.
1616  
     * @param sourceLogin The login of the user that performed the mode change.
1617  
     * @param sourceHostname The hostname of the user that performed the mode change.
1618  
     * @param recipient The nick of the user that got 'deopped'.
1619  
     */
1620  
    protected void onDeop(String channel, String sourceNick, String sourceLogin, String sourceHostname, String recipient) {}
1621  
1622  
1623  
    /**
1624  
     * Called when a user (possibly us) gets voice status granted in a channel.
1625  
     *  <p>
1626  
     * This is a type of mode change and is also passed to the onMode
1627  
     * method in the PircBot class.
1628  
     *  <p>
1629  
     * The implementation of this method in the PircBot abstract class
1630  
     * performs no actions and may be overridden as required.
1631  
     * 
1632  
     * @since PircBot 0.9.5
1633  
     *
1634  
     * @param channel The channel in which the mode change took place.
1635  
     * @param sourceNick The nick of the user that performed the mode change.
1636  
     * @param sourceLogin The login of the user that performed the mode change.
1637  
     * @param sourceHostname The hostname of the user that performed the mode change.
1638  
     * @param recipient The nick of the user that got 'voiced'.
1639  
     */
1640  
    protected void onVoice(String channel, String sourceNick, String sourceLogin, String sourceHostname, String recipient) {}
1641  
1642  
1643  
    /**
1644  
     * Called when a user (possibly us) gets voice status removed.
1645  
     *  <p>
1646  
     * This is a type of mode change and is also passed to the onMode
1647  
     * method in the PircBot class.
1648  
     *  <p>
1649  
     * The implementation of this method in the PircBot abstract class
1650  
     * performs no actions and may be overridden as required.
1651  
     * 
1652  
     * @since PircBot 0.9.5
1653  
     *
1654  
     * @param channel The channel in which the mode change took place.
1655  
     * @param sourceNick The nick of the user that performed the mode change.
1656  
     * @param sourceLogin The login of the user that performed the mode change.
1657  
     * @param sourceHostname The hostname of the user that performed the mode change.
1658  
     * @param recipient The nick of the user that got 'devoiced'.
1659  
     */
1660  
    protected void onDeVoice(String channel, String sourceNick, String sourceLogin, String sourceHostname, String recipient) {}
1661  
1662  
1663  
    /**
1664  
     * Called when a channel key is set.  When the channel key has been set,
1665  
     * other users may only join that channel if they know the key.  Channel keys
1666  
     * are sometimes referred to as passwords.
1667  
     *  <p>
1668  
     * This is a type of mode change and is also passed to the onMode
1669  
     * method in the PircBot class.
1670  
     *  <p>
1671  
     * The implementation of this method in the PircBot abstract class
1672  
     * performs no actions and may be overridden as required.
1673  
     * 
1674  
     * @since PircBot 0.9.5
1675  
     *
1676  
     * @param channel The channel in which the mode change took place.
1677  
     * @param sourceNick The nick of the user that performed the mode change.
1678  
     * @param sourceLogin The login of the user that performed the mode change.
1679  
     * @param sourceHostname The hostname of the user that performed the mode change.
1680  
     * @param key The new key for the channel.
1681  
     */
1682  
    protected void onSetChannelKey(String channel, String sourceNick, String sourceLogin, String sourceHostname, String key) {}
1683  
1684  
1685  
    /**
1686  
     * Called when a channel key is removed.
1687  
     *  <p>
1688  
     * This is a type of mode change and is also passed to the onMode
1689  
     * method in the PircBot class.
1690  
     *  <p>
1691  
     * The implementation of this method in the PircBot abstract class
1692  
     * performs no actions and may be overridden as required.
1693  
     * 
1694  
     * @since PircBot 0.9.5
1695  
     *
1696  
     * @param channel The channel in which the mode change took place.
1697  
     * @param sourceNick The nick of the user that performed the mode change.
1698  
     * @param sourceLogin The login of the user that performed the mode change.
1699  
     * @param sourceHostname The hostname of the user that performed the mode change.
1700  
     * @param key The key that was in use before the channel key was removed.
1701  
     */
1702  
    protected void onRemoveChannelKey(String channel, String sourceNick, String sourceLogin, String sourceHostname, String key) {}
1703  
1704  
1705  
    /**
1706  
     * Called when a user limit is set for a channel.  The number of users in
1707  
     * the channel cannot exceed this limit.
1708  
     *  <p>
1709  
     * This is a type of mode change and is also passed to the onMode
1710  
     * method in the PircBot class.
1711  
     *  <p>
1712  
     * The implementation of this method in the PircBot abstract class
1713  
     * performs no actions and may be overridden as required.
1714  
     * 
1715  
     * @since PircBot 0.9.5
1716  
     *
1717  
     * @param channel The channel in which the mode change took place.
1718  
     * @param sourceNick The nick of the user that performed the mode change.
1719  
     * @param sourceLogin The login of the user that performed the mode change.
1720  
     * @param sourceHostname The hostname of the user that performed the mode change.
1721  
     * @param limit The maximum number of users that may be in this channel at the same time.
1722  
     */
1723  
    protected void onSetChannelLimit(String channel, String sourceNick, String sourceLogin, String sourceHostname, int limit) {}
1724  
1725  
1726  
    /**
1727  
     * Called when the user limit is removed for a channel.
1728  
     *  <p>
1729  
     * This is a type of mode change and is also passed to the onMode
1730  
     * method in the PircBot class.
1731  
     *  <p>
1732  
     * The implementation of this method in the PircBot abstract class
1733  
     * performs no actions and may be overridden as required.
1734  
     * 
1735  
     * @since PircBot 0.9.5
1736  
     *
1737  
     * @param channel The channel in which the mode change took place.
1738  
     * @param sourceNick The nick of the user that performed the mode change.
1739  
     * @param sourceLogin The login of the user that performed the mode change.
1740  
     * @param sourceHostname The hostname of the user that performed the mode change.
1741  
     */
1742  
    protected void onRemoveChannelLimit(String channel, String sourceNick, String sourceLogin, String sourceHostname) {}
1743  
1744  
1745  
    /**
1746  
     * Called when a user (possibly us) gets banned from a channel.  Being
1747  
     * banned from a channel prevents any user with a matching hostmask from
1748  
     * joining the channel.  For this reason, most bans are usually directly
1749  
     * followed by the user being kicked :-)
1750  
     *  <p>
1751  
     * This is a type of mode change and is also passed to the onMode
1752  
     * method in the PircBot class.
1753  
     *  <p>
1754  
     * The implementation of this method in the PircBot abstract class
1755  
     * performs no actions and may be overridden as required.
1756  
     * 
1757  
     * @since PircBot 0.9.5
1758  
     *
1759  
     * @param channel The channel in which the mode change took place.
1760  
     * @param sourceNick The nick of the user that performed the mode change.
1761  
     * @param sourceLogin The login of the user that performed the mode change.
1762  
     * @param sourceHostname The hostname of the user that performed the mode change.
1763  
     * @param hostmask The hostmask of the user that has been banned.
1764  
     */
1765  
    protected void onSetChannelBan(String channel, String sourceNick, String sourceLogin, String sourceHostname, String hostmask) {}
1766  
1767  
1768  
    /**
1769  
     * Called when a hostmask ban is removed from a channel.
1770  
     *  <p>
1771  
     * This is a type of mode change and is also passed to the onMode
1772  
     * method in the PircBot class.
1773  
     *  <p>
1774  
     * The implementation of this method in the PircBot abstract class
1775  
     * performs no actions and may be overridden as required.
1776  
     * 
1777  
     * @since PircBot 0.9.5
1778  
     *
1779  
     * @param channel The channel in which the mode change took place.
1780  
     * @param sourceNick The nick of the user that performed the mode change.
1781  
     * @param sourceLogin The login of the user that performed the mode change.
1782  
     * @param sourceHostname The hostname of the user that performed the mode change.
1783  
     * @param hostmask
1784  
     */
1785  
    protected void onRemoveChannelBan(String channel, String sourceNick, String sourceLogin, String sourceHostname, String hostmask) {}
1786  
1787  
    
1788  
    /**
1789  
     * Called when topic protection is enabled for a channel.  Topic protection
1790  
     * means that only operators in a channel may change the topic.
1791  
     *  <p>
1792  
     * This is a type of mode change and is also passed to the onMode
1793  
     * method in the PircBot class.
1794  
     *  <p>
1795  
     * The implementation of this method in the PircBot abstract class
1796  
     * performs no actions and may be overridden as required.
1797  
     * 
1798  
     * @since PircBot 0.9.5
1799  
     *
1800  
     * @param channel The channel in which the mode change took place.
1801  
     * @param sourceNick The nick of the user that performed the mode change.
1802  
     * @param sourceLogin The login of the user that performed the mode change.
1803  
     * @param sourceHostname The hostname of the user that performed the mode change.
1804  
     */
1805  
    protected void onSetTopicProtection(String channel, String sourceNick, String sourceLogin, String sourceHostname) {}
1806  
    
1807  
    
1808  
    /**
1809  
     * Called when topic protection is removed for a channel.
1810  
     *  <p>
1811  
     * This is a type of mode change and is also passed to the onMode
1812  
     * method in the PircBot class.
1813  
     *  <p>
1814  
     * The implementation of this method in the PircBot abstract class
1815  
     * performs no actions and may be overridden as required.
1816  
     * 
1817  
     * @since PircBot 0.9.5
1818  
     *
1819  
     * @param channel The channel in which the mode change took place.
1820  
     * @param sourceNick The nick of the user that performed the mode change.
1821  
     * @param sourceLogin The login of the user that performed the mode change.
1822  
     * @param sourceHostname The hostname of the user that performed the mode change.
1823  
     */
1824  
    protected void onRemoveTopicProtection(String channel, String sourceNick, String sourceLogin, String sourceHostname) {}
1825  
    
1826  
    
1827  
    /**
1828  
     * Called when a channel is set to only allow messages from users that
1829  
     * are in the channel.
1830  
     *  <p>
1831  
     * This is a type of mode change and is also passed to the onMode
1832  
     * method in the PircBot class.
1833  
     *  <p>
1834  
     * The implementation of this method in the PircBot abstract class
1835  
     * performs no actions and may be overridden as required.
1836  
     * 
1837  
     * @since PircBot 0.9.5
1838  
     *
1839  
     * @param channel The channel in which the mode change took place.
1840  
     * @param sourceNick The nick of the user that performed the mode change.
1841  
     * @param sourceLogin The login of the user that performed the mode change.
1842  
     * @param sourceHostname The hostname of the user that performed the mode change.
1843  
     */
1844  
    protected void onSetNoExternalMessages(String channel, String sourceNick, String sourceLogin, String sourceHostname) {}
1845  
    
1846  
    
1847  
    /**
1848  
     * Called when a channel is set to allow messages from any user, even
1849  
     * if they are not actually in the channel.
1850  
     *  <p>
1851  
     * This is a type of mode change and is also passed to the onMode
1852  
     * method in the PircBot class.
1853  
     *  <p>
1854  
     * The implementation of this method in the PircBot abstract class
1855  
     * performs no actions and may be overridden as required.
1856  
     * 
1857  
     * @since PircBot 0.9.5
1858  
     *
1859  
     * @param channel The channel in which the mode change took place.
1860  
     * @param sourceNick The nick of the user that performed the mode change.
1861  
     * @param sourceLogin The login of the user that performed the mode change.
1862  
     * @param sourceHostname The hostname of the user that performed the mode change.
1863  
     */
1864  
    protected void onRemoveNoExternalMessages(String channel, String sourceNick, String sourceLogin, String sourceHostname) {}
1865  
    
1866  
    
1867  
    /**
1868  
     * Called when a channel is set to 'invite only' mode.  A user may only
1869  
     * join the channel if they are invited by someone who is already in the
1870  
     * channel.
1871  
     *  <p>
1872  
     * This is a type of mode change and is also passed to the onMode
1873  
     * method in the PircBot class.
1874  
     *  <p>
1875  
     * The implementation of this method in the PircBot abstract class
1876  
     * performs no actions and may be overridden as required.
1877  
     * 
1878  
     * @since PircBot 0.9.5
1879  
     *
1880  
     * @param channel The channel in which the mode change took place.
1881  
     * @param sourceNick The nick of the user that performed the mode change.
1882  
     * @param sourceLogin The login of the user that performed the mode change.
1883  
     * @param sourceHostname The hostname of the user that performed the mode change.
1884  
     */
1885  
    protected void onSetInviteOnly(String channel, String sourceNick, String sourceLogin, String sourceHostname) {}
1886  
    
1887  
    
1888  
    /**
1889  
     * Called when a channel has 'invite only' removed.
1890  
     *  <p>
1891  
     * This is a type of mode change and is also passed to the onMode
1892  
     * method in the PircBot class.
1893  
     *  <p>
1894  
     * The implementation of this method in the PircBot abstract class
1895  
     * performs no actions and may be overridden as required.
1896  
     * 
1897  
     * @since PircBot 0.9.5
1898  
     *
1899  
     * @param channel The channel in which the mode change took place.
1900  
     * @param sourceNick The nick of the user that performed the mode change.
1901  
     * @param sourceLogin The login of the user that performed the mode change.
1902  
     * @param sourceHostname The hostname of the user that performed the mode change.
1903  
     */
1904  
    protected void onRemoveInviteOnly(String channel, String sourceNick, String sourceLogin, String sourceHostname) {}
1905  
    
1906  
    
1907  
    /**
1908  
     * Called when a channel is set to 'moderated' mode.  If a channel is
1909  
     * moderated, then only users who have been 'voiced' or 'opped' may speak
1910  
     * or change their nicks.
1911  
     *  <p>
1912  
     * This is a type of mode change and is also passed to the onMode
1913  
     * method in the PircBot class.
1914  
     *  <p>
1915  
     * The implementation of this method in the PircBot abstract class
1916  
     * performs no actions and may be overridden as required.
1917  
     * 
1918  
     * @since PircBot 0.9.5
1919  
     *
1920  
     * @param channel The channel in which the mode change took place.
1921  
     * @param sourceNick The nick of the user that performed the mode change.
1922  
     * @param sourceLogin The login of the user that performed the mode change.
1923  
     * @param sourceHostname The hostname of the user that performed the mode change.
1924  
     */
1925  
    protected void onSetModerated(String channel, String sourceNick, String sourceLogin, String sourceHostname) {}
1926  
    
1927  
    
1928  
    /**
1929  
     * Called when a channel has moderated mode removed.
1930  
     *  <p>
1931  
     * This is a type of mode change and is also passed to the onMode
1932  
     * method in the PircBot class.
1933  
     *  <p>
1934  
     * The implementation of this method in the PircBot abstract class
1935  
     * performs no actions and may be overridden as required.
1936  
     * 
1937  
     * @since PircBot 0.9.5
1938  
     *
1939  
     * @param channel The channel in which the mode change took place.
1940  
     * @param sourceNick The nick of the user that performed the mode change.
1941  
     * @param sourceLogin The login of the user that performed the mode change.
1942  
     * @param sourceHostname The hostname of the user that performed the mode change.
1943  
     */
1944  
    protected void onRemoveModerated(String channel, String sourceNick, String sourceLogin, String sourceHostname) {}
1945  
    
1946  
    
1947  
    /**
1948  
     * Called when a channel is marked as being in private mode.
1949  
     *  <p>
1950  
     * This is a type of mode change and is also passed to the onMode
1951  
     * method in the PircBot class.
1952  
     *  <p>
1953  
     * The implementation of this method in the PircBot abstract class
1954  
     * performs no actions and may be overridden as required.
1955  
     * 
1956  
     * @since PircBot 0.9.5
1957  
     *
1958  
     * @param channel The channel in which the mode change took place.
1959  
     * @param sourceNick The nick of the user that performed the mode change.
1960  
     * @param sourceLogin The login of the user that performed the mode change.
1961  
     * @param sourceHostname The hostname of the user that performed the mode change.
1962  
     */
1963  
    protected void onSetPrivate(String channel, String sourceNick, String sourceLogin, String sourceHostname) {}
1964  
    
1965  
    
1966  
    /**
1967  
     * Called when a channel is marked as not being in private mode.
1968  
     *  <p>
1969  
     * This is a type of mode change and is also passed to the onMode
1970  
     * method in the PircBot class.
1971  
     *  <p>
1972  
     * The implementation of this method in the PircBot abstract class
1973  
     * performs no actions and may be overridden as required.
1974  
     * 
1975  
     * @since PircBot 0.9.5
1976  
     *
1977  
     * @param channel The channel in which the mode change took place.
1978  
     * @param sourceNick The nick of the user that performed the mode change.
1979  
     * @param sourceLogin The login of the user that performed the mode change.
1980  
     * @param sourceHostname The hostname of the user that performed the mode change.
1981  
     */
1982  
    protected void onRemovePrivate(String channel, String sourceNick, String sourceLogin, String sourceHostname) {}
1983  
    
1984  
    
1985  
    /**
1986  
     * Called when a channel is set to be in 'secret' mode.  Such channels
1987  
     * typically do not appear on a server's channel listing.
1988  
     *  <p>
1989  
     * This is a type of mode change and is also passed to the onMode
1990  
     * method in the PircBot class.
1991  
     *  <p>
1992  
     * The implementation of this method in the PircBot abstract class
1993  
     * performs no actions and may be overridden as required.
1994  
     * 
1995  
     * @since PircBot 0.9.5
1996  
     *
1997  
     * @param channel The channel in which the mode change took place.
1998  
     * @param sourceNick The nick of the user that performed the mode change.
1999  
     * @param sourceLogin The login of the user that performed the mode change.
2000  
     * @param sourceHostname The hostname of the user that performed the mode change.
2001  
     */
2002  
    protected void onSetSecret(String channel, String sourceNick, String sourceLogin, String sourceHostname) {}
2003  
    
2004  
    
2005  
    /**
2006  
     * Called when a channel has 'secret' mode removed.
2007  
     *  <p>
2008  
     * This is a type of mode change and is also passed to the onMode
2009  
     * method in the PircBot class.
2010  
     *  <p>
2011  
     * The implementation of this method in the PircBot abstract class
2012  
     * performs no actions and may be overridden as required.
2013  
     * 
2014  
     * @since PircBot 0.9.5
2015  
     *
2016  
     * @param channel The channel in which the mode change took place.
2017  
     * @param sourceNick The nick of the user that performed the mode change.
2018  
     * @param sourceLogin The login of the user that performed the mode change.
2019  
     * @param sourceHostname The hostname of the user that performed the mode change.
2020  
     */
2021  
    protected void onRemoveSecret(String channel, String sourceNick, String sourceLogin, String sourceHostname) {}
2022  
    
2023  
    
2024  
    /**
2025  
     * Called when we are invited to a channel by a user.
2026  
     *  <p>
2027  
     * The implementation of this method in the PircBot abstract class
2028  
     * performs no actions and may be overridden as required.
2029  
     * 
2030  
     * @since PircBot 0.9.5
2031  
     * 
2032  
     * @param targetNick The nick of the user being invited - should be us!
2033  
     * @param sourceNick The nick of the user that sent the invitation.
2034  
     * @param sourceLogin The login of the user that sent the invitation.
2035  
     * @param sourceHostname The hostname of the user that sent the invitation.
2036  
     * @param channel The channel that we're being invited to.
2037  
     */
2038  
    protected void onInvite(String targetNick, String sourceNick, String sourceLogin, String sourceHostname, String channel)  {}    
2039  
2040  
2041  
    /**
2042  
     * This method used to be called when a DCC SEND request was sent to the PircBot.
2043  
     * Please use the onIncomingFileTransfer method to receive files, as it
2044  
     * has better functionality and supports resuming.
2045  
     * 
2046  
     * @deprecated As of PircBot 1.2.0, use {@link #onIncomingFileTransfer(DccFileTransfer)}
2047  
     */
2048  
    protected void onDccSendRequest(String sourceNick, String sourceLogin, String sourceHostname, String filename, long address, int port, int size) {}
2049  
    
2050  
    
2051  
    /**
2052  
     * This method used to be called when a DCC CHAT request was sent to the PircBot.
2053  
     * Please use the onIncomingChatRequest method to accept chats, as it
2054  
     * has better functionality.
2055  
     * 
2056  
     * @deprecated As of PircBot 1.2.0, use {@link #onIncomingChatRequest(DccChat)}
2057  
     */
2058  
    protected void onDccChatRequest(String sourceNick, String sourceLogin, String sourceHostname, long address, int port) {}
2059  
    
2060  
    
2061  
    /**
2062  
     * This method is called whenever a DCC SEND request is sent to the PircBot.
2063  
     * This means that a client has requested to send a file to us.
2064  
     * This abstract implementation performs no action, which means that all
2065  
     * DCC SEND requests will be ignored by default. If you wish to receive
2066  
     * the file, then you may override this method and call the receive method
2067  
     * on the DccFileTransfer object, which connects to the sender and downloads
2068  
     * the file.
2069  
     *  <p>
2070  
     * Example:
2071  
     * <pre> public void onIncomingFileTransfer(DccFileTransfer transfer) {
2072  
     *     // Use the suggested file name.
2073  
     *     File file = transfer.getFile();
2074  
     *     // Receive the transfer and save it to the file, allowing resuming.
2075  
     *     transfer.receive(file, true);
2076  
     * }</pre>
2077  
     *  <p>
2078  
     * <b>Warning:</b> Receiving an incoming file transfer will cause a file
2079  
     * to be written to disk. Please ensure that you make adequate security
2080  
     * checks so that this file does not overwrite anything important!
2081  
     *  <p>
2082  
     * Each time a file is received, it happens within a new Thread
2083  
     * in order to allow multiple files to be downloaded by the PircBot
2084  
     * at the same time. 
2085  
     *  <p>
2086  
     * If you allow resuming and the file already partly exists, it will
2087  
     * be appended to instead of overwritten.  If resuming is not enabled,
2088  
     * the file will be overwritten if it already exists.
2089  
     *  <p>
2090  
     * You can throttle the speed of the transfer by calling the setPacketDelay
2091  
     * method on the DccFileTransfer object, either before you receive the
2092  
     * file or at any moment during the transfer.
2093  
     *  <p>
2094  
     * The implementation of this method in the PircBot abstract class
2095  
     * performs no actions and may be overridden as required.
2096  
     *
2097  
     * @since PircBot 1.2.0
2098  
     * 
2099  
     * @param transfer The DcccFileTransfer that you may accept.
2100  
     * 
2101  
     * @see DccFileTransfer
2102  
     * 
2103  
     */
2104  
    protected void onIncomingFileTransfer(DccFileTransfer transfer) {}
2105  
    
2106  
    
2107  
    /**
2108  
     * This method gets called when a DccFileTransfer has finished.
2109  
     * If there was a problem, the Exception will say what went wrong.
2110  
     * If the file was sent successfully, the Exception will be null.
2111  
     *  <p>
2112  
     * Both incoming and outgoing file transfers are passed to this method.
2113  
     * You can determine the type by calling the isIncoming or isOutgoing
2114  
     * methods on the DccFileTransfer object.
2115  
     *
2116  
     * @since PircBot 1.2.0
2117  
     * 
2118  
     * @param transfer The DccFileTransfer that has finished.
2119  
     * @param e null if the file was transfered successfully, otherwise this
2120  
     *          will report what went wrong.
2121  
     * 
2122  
     * @see DccFileTransfer
2123  
     * 
2124  
     */
2125  
    protected void onFileTransferFinished(DccFileTransfer transfer, Exception e) {}
2126  
    
2127  
    
2128  
    /**
2129  
     * This method will be called whenever a DCC Chat request is received.
2130  
     * This means that a client has requested to chat to us directly rather
2131  
     * than via the IRC server. This is useful for sending many lines of text
2132  
     * to and from the bot without having to worry about flooding the server
2133  
     * or any operators of the server being able to "spy" on what is being
2134  
     * said. This abstract implementation performs no action, which means
2135  
     * that all DCC CHAT requests will be ignored by default.
2136  
     *  <p>
2137  
     * If you wish to accept the connection, then you may override this
2138  
     * method and call the accept() method on the DccChat object, which
2139  
     * connects to the sender of the chat request and allows lines to be
2140  
     * sent to and from the bot.
2141  
     *  <p>
2142  
     * Your bot must be able to connect directly to the user that sent the
2143  
     * request.
2144  
     *  <p>
2145  
     * Example: 
2146  
     * <pre> public void onIncomingChatRequest(DccChat chat) {
2147  
     *     try {
2148  
     *         // Accept all chat, whoever it's from.
2149  
     *         chat.accept();
2150  
     *         chat.sendLine("Hello");
2151  
     *         String response = chat.readLine();
2152  
     *         chat.close();
2153  
     *     }
2154  
     *     catch (IOException e) {}
2155  
     * }</pre>
2156  
     * 
2157  
     * Each time this method is called, it is called from within a new Thread
2158  
     * so that multiple DCC CHAT sessions can run concurrently.
2159  
     *  <p>
2160  
     * The implementation of this method in the PircBot abstract class
2161  
     * performs no actions and may be overridden as required.
2162  
     *
2163  
     * @since PircBot 1.2.0
2164  
     * 
2165  
     * @param chat A DccChat object that represents the incoming chat request.
2166  
     * 
2167  
     * @see DccChat
2168  
     * 
2169  
     */
2170  
    protected void onIncomingChatRequest(DccChat chat) {}
2171  
    
2172  
    
2173  
    /**
2174  
     * This method is called whenever we receive a VERSION request.
2175  
     * This abstract implementation responds with the PircBot's _version string,
2176  
     * so if you override this method, be sure to either mimic its functionality
2177  
     * or to call super.onVersion(...);
2178  
     * 
2179  
     * @param sourceNick The nick of the user that sent the VERSION request.
2180  
     * @param sourceLogin The login of the user that sent the VERSION request.
2181  
     * @param sourceHostname The hostname of the user that sent the VERSION request.
2182  
     * @param target The target of the VERSION request, be it our nick or a channel name.
2183  
     */
2184  
    protected void onVersion(String sourceNick, String sourceLogin, String sourceHostname, String target) {
2185  
        this.sendRawLine("NOTICE " + sourceNick + " :\u0001VERSION " + _version + "\u0001");
2186  
    }
2187  
    
2188  
    
2189  
    /**
2190  
     * This method is called whenever we receive a PING request from another
2191  
     * user.
2192  
     *  <p>
2193  
     * This abstract implementation responds correctly, so if you override this
2194  
     * method, be sure to either mimic its functionality or to call
2195  
     * super.onPing(...);
2196  
     * 
2197  
     * @param sourceNick The nick of the user that sent the PING request.
2198  
     * @param sourceLogin The login of the user that sent the PING request.
2199  
     * @param sourceHostname The hostname of the user that sent the PING request.
2200  
     * @param target The target of the PING request, be it our nick or a channel name.
2201  
     * @param pingValue The value that was supplied as an argument to the PING command.
2202  
     */
2203  
    protected void onPing(String sourceNick, String sourceLogin, String sourceHostname, String target, String pingValue) {
2204  
        this.sendRawLine("NOTICE " + sourceNick + " :\u0001PING " + pingValue + "\u0001");
2205  
    }
2206  
    
2207  
    
2208  
    /**
2209  
     * The actions to perform when a PING request comes from the server.
2210  
     *  <p>
2211  
     * This sends back a correct response, so if you override this method,
2212  
     * be sure to either mimic its functionality or to call
2213  
     * super.onServerPing(response);
2214  
     *
2215  
     * @param response The response that should be given back in your PONG.
2216  
     */
2217  
    protected void onServerPing(String response) {
2218  
        this.sendRawLine("PONG " + response);
2219  
    }
2220  
    
2221  
    
2222  
    /**
2223  
     * This method is called whenever we receive a TIME request.
2224  
     *  <p>
2225  
     * This abstract implementation responds correctly, so if you override this
2226  
     * method, be sure to either mimic its functionality or to call
2227  
     * super.onTime(...);
2228  
     * 
2229  
     * @param sourceNick The nick of the user that sent the TIME request.
2230  
     * @param sourceLogin The login of the user that sent the TIME request.
2231  
     * @param sourceHostname The hostname of the user that sent the TIME request.
2232  
     * @param target The target of the TIME request, be it our nick or a channel name.
2233  
     */
2234  
    protected void onTime(String sourceNick, String sourceLogin, String sourceHostname, String target) {
2235  
        this.sendRawLine("NOTICE " + sourceNick + " :\u0001TIME " + new Date().toString() + "\u0001");
2236  
    }
2237  
    
2238  
    
2239  
    /**
2240  
     * This method is called whenever we receive a FINGER request.
2241  
     *  <p>
2242  
     * This abstract implementation responds correctly, so if you override this
2243  
     * method, be sure to either mimic its functionality or to call
2244  
     * super.onFinger(...);
2245  
     * 
2246  
     * @param sourceNick The nick of the user that sent the FINGER request.
2247  
     * @param sourceLogin The login of the user that sent the FINGER request.
2248  
     * @param sourceHostname The hostname of the user that sent the FINGER request.
2249  
     * @param target The target of the FINGER request, be it our nick or a channel name.
2250  
     */
2251  
    protected void onFinger(String sourceNick, String sourceLogin, String sourceHostname, String target) {
2252  
        this.sendRawLine("NOTICE " + sourceNick + " :\u0001FINGER " + _finger + "\u0001");
2253  
    }
2254  
    
2255  
    
2256  
    /**
2257  
     * This method is called whenever we receive a line from the server that
2258  
     * the PircBot has not been programmed to recognise.
2259  
     *  <p>
2260  
     * The implementation of this method in the PircBot abstract class
2261  
     * performs no actions and may be overridden as required.
2262  
     * 
2263  
     * @param line The raw line that was received from the server.
2264  
     */
2265  
    protected void onUnknown(String line) {
2266  
        // And then there were none :)
2267  
    }
2268  
        
2269  
    
2270  
    /**
2271  
     * Sets the verbose mode. If verbose mode is set to true, then log entries
2272  
     * will be printed to the standard output. The default value is false and
2273  
     * will result in no output. For general development, we strongly recommend
2274  
     * setting the verbose mode to true.
2275  
     *
2276  
     * @param verbose true if verbose mode is to be used.  Default is false.
2277  
     */
2278  
    public final void setVerbose(boolean verbose) {
2279  
        _verbose = verbose;
2280  
    }
2281  
    
2282  
    
2283  
    /**
2284  
     * Sets the name of the bot, which will be used as its nick when it
2285  
     * tries to join an IRC server.  This should be set before joining
2286  
     * any servers, otherwise the default nick will be used.  You would
2287  
     * typically call this method from the constructor of the class that
2288  
     * extends PircBot.
2289  
     *  <p>
2290  
     * The changeNick method should be used if you wish to change your nick
2291  
     * when you are connected to a server.
2292  
     *
2293  
     * @param name The new name of the Bot.
2294  
     */
2295  
    protected final void setName(String name) {
2296  
        _name = name;
2297  
    }
2298  
    
2299  
    
2300  
    /**
2301  
     * Sets the internal nick of the bot.  This is only to be called by the
2302  
     * PircBot class in response to notification of nick changes that apply
2303  
     * to us.
2304  
     * 
2305  
     * @param nick The new nick.
2306  
     */
2307  
    private final void setNick(String nick) {
2308  
        _nick = nick;
2309  
    }
2310  
    
2311  
    
2312  
    /**
2313  
     * Sets the internal login of the Bot.  This should be set before joining
2314  
     * any servers.
2315  
     *
2316  
     * @param login The new login of the Bot.
2317  
     */
2318  
    protected final void setLogin(String login) {
2319  
        _login = login;
2320  
    }
2321  
    
2322  
2323  
    /**
2324  
     * Sets the internal version of the Bot.  This should be set before joining
2325  
     * any servers.
2326  
     *
2327  
     * @param version The new version of the Bot.
2328  
     */
2329  
    protected final void setVersion(String version) {
2330  
        _version = version;
2331  
    }
2332  
2333  
2334  
    /**
2335  
     * Sets the interal finger message.  This should be set before joining
2336  
     * any servers.
2337  
     *
2338  
     * @param finger The new finger message for the Bot.
2339  
     */
2340  
    protected final void setFinger(String finger) {
2341  
        _finger = finger;
2342  
    }
2343  
    
2344  
    
2345  
    /**
2346  
     * Gets the name of the PircBot. This is the name that will be used as
2347  
     * as a nick when we try to join servers.
2348  
     *
2349  
     * @return The name of the PircBot.
2350  
     */
2351  
    public final String getName() {
2352  
        return _name;
2353  
    }
2354  
    
2355  
    
2356  
    /**
2357  
     * Returns the current nick of the bot. Note that if you have just changed
2358  
     * your nick, this method will still return the old nick until confirmation
2359  
     * of the nick change is received from the server.
2360  
     *  <p>
2361  
     * The nick returned by this method is maintained only by the PircBot
2362  
     * class and is guaranteed to be correct in the context of the IRC server.
2363  
     *
2364  
     * @since PircBot 1.0.0
2365  
     * 
2366  
     * @return The current nick of the bot.
2367  
     */
2368  
    public String getNick() {
2369  
        return _nick;
2370  
    }
2371  
    
2372  
    
2373  
    /**
2374  
     * Gets the internal login of the PircBot.
2375  
     *
2376  
     * @return The login of the PircBot.
2377  
     */
2378  
    public final String getLogin() {
2379  
        return _login;
2380  
    }
2381  
    
2382  
2383  
    /**
2384  
     * Gets the internal version of the PircBot.
2385  
     *
2386  
     * @return The version of the PircBot.
2387  
     */
2388  
    public final String getVersion() {
2389  
        return _version;
2390  
    }
2391  
    
2392  
    
2393  
    /**
2394  
     * Gets the internal finger message of the PircBot.
2395  
     *
2396  
     * @return The finger message of the PircBot.
2397  
     */
2398  
    public final String getFinger() {
2399  
        return _finger;
2400  
    }
2401  
    
2402  
    
2403  
    /**
2404  
     * Returns whether or not the PircBot is currently connected to a server.
2405  
     * The result of this method should only act as a rough guide,
2406  
     * as the result may not be valid by the time you act upon it.
2407  
     *
2408  
     * @return True if and only if the PircBot is currently connected to a server.
2409  
     */
2410  
    public final synchronized boolean isConnected() {
2411  
        return _inputThread != null && _inputThread.isConnected();
2412  
    }
2413  
    
2414  
    
2415  
    /**
2416  
     * Sets the number of milliseconds to delay between consecutive
2417  
     * messages when there are multiple messages waiting in the
2418  
     * outgoing message queue.  This has a default value of 1000ms.
2419  
     * It is a good idea to stick to this default value, as it will
2420  
     * prevent your bot from spamming servers and facing the subsequent
2421  
     * wrath!  However, if you do need to change this delay value (<b>not
2422  
     * recommended</b>), then this is the method to use.
2423  
     *
2424  
     * @param delay The number of milliseconds between each outgoing message.
2425  
     * 
2426  
     */
2427  
    public final void setMessageDelay(long delay) {
2428  
        if (delay < 0) {
2429  
            throw new IllegalArgumentException("Cannot have a negative time.");
2430  
        }
2431  
        _messageDelay = delay;
2432  
    }
2433  
    
2434  
    
2435  
    /**
2436  
     * Returns the number of milliseconds that will be used to separate
2437  
     * consecutive messages to the server from the outgoing message queue.
2438  
     *
2439  
     * @return Number of milliseconds.
2440  
     */
2441  
    public final long getMessageDelay() {
2442  
        return _messageDelay;
2443  
    }
2444  
    
2445  
    
2446  
    /**
2447  
     * Gets the maximum length of any line that is sent via the IRC protocol.
2448  
     * The IRC RFC specifies that line lengths, including the trailing \r\n
2449  
     * must not exceed 512 bytes.  Hence, there is currently no option to
2450  
     * change this value in PircBot.  All lines greater than this length
2451  
     * will be truncated before being sent to the IRC server.
2452  
     * 
2453  
     * @return The maximum line length (currently fixed at 512)
2454  
     */
2455  
    public final int getMaxLineLength() {
2456  
        return InputThread.MAX_LINE_LENGTH;
2457  
    }
2458  
    
2459  
    
2460  
    /**
2461  
     * Gets the number of lines currently waiting in the outgoing message Queue.
2462  
     * If this returns 0, then the Queue is empty and any new message is likely
2463  
     * to be sent to the IRC server immediately.
2464  
     *
2465  
     * @since PircBot 0.9.9
2466  
     * 
2467  
     * @return The number of lines in the outgoing message Queue.
2468  
     */
2469  
    public final int getOutgoingQueueSize() {
2470  
        return _outQueue.size();
2471  
    }
2472  
    
2473  
    
2474  
    /**
2475  
     * Returns the name of the last IRC server the PircBot tried to connect to.
2476  
     * This does not imply that the connection attempt to the server was
2477  
     * successful (we suggest you look at the onConnect method).
2478  
     * A value of null is returned if the PircBot has never tried to connect
2479  
     * to a server.
2480  
     * 
2481  
     * @return The name of the last machine we tried to connect to. Returns
2482  
     *         null if no connection attempts have ever been made.
2483  
     */
2484  
    public final String getServer() {
2485  
        return _server;
2486  
    }
2487  
    
2488  
    
2489  
    /**
2490  
     * Returns the port number of the last IRC server that the PircBot tried
2491  
     * to connect to.
2492  
     * This does not imply that the connection attempt to the server was
2493  
     * successful (we suggest you look at the onConnect method).
2494  
     * A value of -1 is returned if the PircBot has never tried to connect
2495  
     * to a server.
2496  
     * 
2497  
     * @since PircBot 0.9.9
2498  
     * 
2499  
     * @return The port number of the last IRC server we connected to.
2500  
     *         Returns -1 if no connection attempts have ever been made.
2501  
     */
2502  
    public final int getPort() {
2503  
        return _port;
2504  
    }
2505  
    
2506  
    
2507  
    /**
2508  
     * Returns the last password that we used when connecting to an IRC server.
2509  
     * This does not imply that the connection attempt to the server was
2510  
     * successful (we suggest you look at the onConnect method).
2511  
     * A value of null is returned if the PircBot has never tried to connect
2512  
     * to a server using a password.
2513  
     * 
2514  
     * @since PircBot 0.9.9
2515  
     * 
2516  
     * @return The last password that we used when connecting to an IRC server.
2517  
     *         Returns null if we have not previously connected using a password.
2518  
     */
2519  
    public final String getPassword() {
2520  
        return _password;
2521  
    }
2522  
    
2523  
    
2524  
    /**
2525  
     * A convenient method that accepts an IP address represented as a
2526  
     * long and returns an integer array of size 4 representing the same
2527  
     * IP address.
2528  
     * 
2529  
     * @since PircBot 0.9.4
2530  
     *
2531  
     * @param address the long value representing the IP address.
2532  
     * 
2533  
     * @return An int[] of size 4.
2534  
     */
2535  
    public int[] longToIp(long address) {
2536  
        int[] ip = new int[4];
2537  
        for (int i = 3; i >= 0; i--) {
2538  
            ip[i] = (int) (address % 256);
2539  
            address = address / 256;
2540  
        }
2541  
        return ip;
2542  
    }
2543  
2544  
    
2545  
    /**
2546  
     * A convenient method that accepts an IP address represented by a byte[]
2547  
     * of size 4 and returns this as a long representation of the same IP
2548  
     * address.
2549  
     * 
2550  
     * @since PircBot 0.9.4
2551  
     *
2552  
     * @param address the byte[] of size 4 representing the IP address.
2553  
     * 
2554  
     * @return a long representation of the IP address.
2555  
     */
2556  
    public long ipToLong(byte[] address) {
2557  
        if (address.length != 4) {
2558  
            throw new IllegalArgumentException("byte array must be of length 4");
2559  
        }
2560  
        long ipNum = 0;
2561  
        long multiplier = 1;
2562  
        for (int i = 3; i >= 0; i--) {
2563  
            int byteVal = (address[i] + 256) % 256;
2564  
            ipNum += byteVal*multiplier;
2565  
            multiplier *= 256;
2566  
        }
2567  
        return ipNum;
2568  
    }
2569  
    
2570  
    
2571  
    /**
2572  
     * Sets the encoding charset to be used when sending or receiving lines
2573  
     * from the IRC server.  If set to null, then the platform's default
2574  
     * charset is used.  You should only use this method if you are
2575  
     * trying to send text to an IRC server in a different charset, e.g.
2576  
     * "GB2312" for Chinese encoding.  If a PircBot is currently connected
2577  
     * to a server, then it must reconnect before this change takes effect.
2578  
     * 
2579  
     * @since PircBot 1.0.4
2580  
     * 
2581  
     * @param charset The new encoding charset to be used by PircBot.
2582  
     * 
2583  
     * @throws UnsupportedEncodingException If the named charset is not
2584  
     *                                      supported.
2585  
     */
2586  
    public void setEncoding(String charset) throws UnsupportedEncodingException {
2587  
        // Just try to see if the charset is supported first...
2588  
        "".getBytes(charset);
2589  
        
2590  
        _charset = charset;
2591  
    }
2592  
2593  
    
2594  
    /**
2595  
     * Returns the encoding used to send and receive lines from
2596  
     * the IRC server, or null if not set.  Use the setEncoding
2597  
     * method to change the encoding charset.
2598  
     * 
2599  
     * @since PircBot 1.0.4
2600  
     * 
2601  
     * @return The encoding used to send outgoing messages, or
2602  
     *         null if not set.
2603  
     */
2604  
    public String getEncoding() {
2605  
        return _charset;
2606  
    }
2607  
    
2608  
    /**
2609  
     * Returns the InetAddress used by the PircBot.
2610  
     * This can be used to find the I.P. address from which the PircBot is
2611  
     * connected to a server.
2612  
     * 
2613  
     * @since PircBot 1.4.4
2614  
     * 
2615  
     * @return The current local InetAddress, or null if never connected.
2616  
     */
2617  
    public InetAddress getInetAddress() {
2618  
        return _inetAddress;
2619  
    }
2620  
    
2621  
2622  
    /**
2623  
     * Sets the InetAddress to be used when sending DCC chat or file transfers.
2624  
     * This can be very useful when you are running a bot on a machine which
2625  
     * is behind a firewall and you need to tell receiving clients to connect
2626  
     * to a NAT/router, which then forwards the connection.
2627  
     * 
2628  
     * @since PircBot 1.4.4
2629  
     * 
2630  
     * @param dccInetAddress The new InetAddress, or null to use the default.
2631  
     */
2632  
    public void setDccInetAddress(InetAddress dccInetAddress) {
2633  
        _dccInetAddress = dccInetAddress;
2634  
    }
2635  
    
2636  
2637  
    /**
2638  
     * Returns the InetAddress used when sending DCC chat or file transfers.
2639  
     * If this is null, the default InetAddress will be used.
2640  
     * 
2641  
     * @since PircBot 1.4.4
2642  
     * 
2643  
     * @return The current DCC InetAddress, or null if left as default.
2644  
     */
2645  
    public InetAddress getDccInetAddress() {
2646  
        return _dccInetAddress;
2647  
    }
2648  
    
2649  
    
2650  
    /**
2651  
     * Returns the set of port numbers to be used when sending a DCC chat
2652  
     * or file transfer. This is useful when you are behind a firewall and
2653  
     * need to set up port forwarding. The array of port numbers is traversed
2654  
     * in sequence until a free port is found to listen on. A DCC tranfer will
2655  
     * fail if all ports are already in use.
2656  
     * If set to null, <i>any</i> free port number will be used. 
2657  
     * 
2658  
     * @since PircBot 1.4.4
2659  
     * 
2660  
     * @return An array of port numbers that PircBot can use to send DCC
2661  
     *         transfers, or null if any port is allowed.
2662  
     */
2663  
    public int[] getDccPorts() {
2664  
        if (_dccPorts == null || _dccPorts.length == 0) {
2665  
            return null;
2666  
        }
2667  
        // Clone the array to prevent external modification.
2668  
        return (int[]) _dccPorts.clone();
2669  
    }
2670  
    
2671  
    
2672  
    /**
2673  
     * Sets the choice of port numbers that can be used when sending a DCC chat
2674  
     * or file transfer. This is useful when you are behind a firewall and
2675  
     * need to set up port forwarding. The array of port numbers is traversed
2676  
     * in sequence until a free port is found to listen on. A DCC tranfer will
2677  
     * fail if all ports are already in use.
2678  
     * If set to null, <i>any</i> free port number will be used. 
2679  
     * 
2680  
     * @since PircBot 1.4.4
2681  
     * 
2682  
     * @param ports The set of port numbers that PircBot may use for DCC
2683  
     *              transfers, or null to let it use any free port (default).
2684  
     *
2685  
     */
2686  
    public void setDccPorts(int[] ports) {
2687  
        if (ports == null || ports.length == 0) {
2688  
            _dccPorts = null;
2689  
        }
2690  
        else {
2691  
            // Clone the array to prevent external modification.
2692  
            _dccPorts = (int[]) ports.clone();
2693  
        }
2694  
    }    
2695  
    
2696  
    
2697  
    /**
2698  
     * Returns true if and only if the object being compared is the exact
2699  
     * same instance as this PircBot. This may be useful if you are writing
2700  
     * a multiple server IRC bot that uses more than one instance of PircBot.
2701  
     * 
2702  
     * @since PircBot 0.9.9
2703  
     *
2704  
     * @return true if and only if Object o is a PircBot and equal to this.
2705  
     */
2706  
    public boolean equals(Object o) {
2707  
        // This probably has the same effect as Object.equals, but that may change...
2708  
        if (o instanceof PircBot) {
2709  
            PircBot other = (PircBot) o;
2710  
            return other == this;
2711  
        }
2712  
        return false;
2713  
    }
2714  
    
2715  
    
2716  
    /**
2717  
     * Returns the hashCode of this PircBot. This method can be called by hashed
2718  
     * collection classes and is useful for managing multiple instances of
2719  
     * PircBots in such collections.
2720  
     * 
2721  
     * @since PircBot 0.9.9
2722  
     * 
2723  
     * @return the hash code for this instance of PircBot.
2724  
     */
2725  
    public int hashCode() {
2726  
        return super.hashCode();
2727  
    }
2728  
    
2729  
    
2730  
    /**
2731  
     * Returns a String representation of this object.
2732  
     * You may find this useful for debugging purposes, particularly
2733  
     * if you are using more than one PircBot instance to achieve
2734  
     * multiple server connectivity. The format of
2735  
     * this String may change between different versions of PircBot
2736  
     * but is currently something of the form
2737  
     * <code>
2738  
     *   Version{PircBot x.y.z Java IRC Bot - www.jibble.org}
2739  
     *   Connected{true}
2740  
     *   Server{irc.dal.net}
2741  
     *   Port{6667}
2742  
     *   Password{}
2743  
     * </code>
2744  
     * 
2745  
     * @since PircBot 0.9.10
2746  
     * 
2747  
     * @return a String representation of this object.
2748  
     */
2749  
    public String toString() {
2750  
        return "Version{" + _version + "}" +
2751  
                " Connected{" + isConnected() + "}" +
2752  
                " Server{" + _server + "}" +
2753  
                " Port{" + _port + "}" +
2754  
                " Password{" + _password + "}";
2755  
    }
2756  
    
2757  
    
2758  
    /**
2759  
     * Returns an array of all users in the specified channel.
2760  
     *  <p>
2761  
     * There are some important things to note about this method:-
2762  
     * <ul>
2763  
     *  <li>This method may not return a full list of users if you call it
2764  
     *      before the complete nick list has arrived from the IRC server.
2765  
     *  </li>
2766  
     *  <li>If you wish to find out which users are in a channel as soon
2767  
     *      as you join it, then you should override the onUserList method
2768  
     *      instead of calling this method, as the onUserList method is only
2769  
     *      called as soon as the full user list has been received.
2770  
     *  </li>
2771  
     *  <li>This method will return immediately, as it does not require any
2772  
     *      interaction with the IRC server.
2773  
     *  </li>
2774  
     *  <li>The bot must be in a channel to be able to know which users are
2775  
     *      in it.
2776  
     *  </li>
2777  
     * </ul>
2778  
     * 
2779  
     * @since PircBot 1.0.0
2780  
     *
2781  
     * @param channel The name of the channel to list.
2782  
     * 
2783  
     * @return An array of User objects. This array is empty if we are not
2784  
     *         in the channel.
2785  
     * 
2786  
     * @see #onUserList(String,User[]) onUserList
2787  
     */
2788  
    public final User[] getUsers(String channel) {
2789  
        channel = channel.toLowerCase();
2790  
        User[] userArray = new User[0];
2791  
        synchronized (_channels) {
2792  
            Hashtable users = (Hashtable) _channels.get(channel);
2793  
            if (users != null) {
2794  
                userArray = new User[users.size()];
2795  
                Enumeration enumeration = users.elements();
2796  
                for (int i = 0; i < userArray.length; i++) {
2797  
                    User user = (User) enumeration.nextElement();
2798  
                    userArray[i] = user;
2799  
                }
2800  
            }
2801  
        }
2802  
        return userArray;
2803  
    }
2804  
    
2805  
    
2806  
    /**
2807  
     * Returns an array of all channels that we are in.  Note that if you
2808  
     * call this method immediately after joining a new channel, the new
2809  
     * channel may not appear in this array as it is not possible to tell
2810  
     * if the join was successful until a response is received from the
2811  
     * IRC server.
2812  
     * 
2813  
     * @since PircBot 1.0.0
2814  
     * 
2815  
     * @return A String array containing the names of all channels that we
2816  
     *         are in.
2817  
     */
2818  
    public final String[] getChannels() {
2819  
        String[] channels = new String[0];
2820  
        synchronized (_channels) {
2821  
            channels = new String[_channels.size()];
2822  
            Enumeration enumeration = _channels.keys();
2823  
            for (int i = 0; i < channels.length; i++) {
2824  
                channels[i] = (String) enumeration.nextElement();
2825  
            }
2826  
        }
2827  
        return channels;
2828  
    }
2829  
    
2830  
    
2831  
    /**
2832  
     * Disposes of all thread resources used by this PircBot. This may be
2833  
     * useful when writing bots or clients that use multiple servers (and
2834  
     * therefore multiple PircBot instances) or when integrating a PircBot
2835  
     * with an existing program.
2836  
     *  <p>
2837  
     * Each PircBot runs its own threads for dispatching messages from its
2838  
     * outgoing message queue and receiving messages from the server.
2839  
     * Calling dispose() ensures that these threads are
2840  
     * stopped, thus freeing up system resources and allowing the PircBot
2841  
     * object to be garbage collected if there are no other references to
2842  
     * it.
2843  
     *  <p>
2844  
     * Once a PircBot object has been disposed, it should not be used again.
2845  
     * Attempting to use a PircBot that has been disposed may result in
2846  
     * unpredictable behaviour.
2847  
     * 
2848  
     * @since 1.2.2
2849  
     */
2850  
    public synchronized void dispose() {
2851  
        //System.out.println("disposing...");
2852  
        _outputThread.interrupt();
2853  
        _inputThread.dispose();
2854  
    }
2855  
    
2856  
    
2857  
    /**
2858  
     * Add a user to the specified channel in our memory.
2859  
     * Overwrite the existing entry if it exists.
2860  
     */
2861  
    private final void addUser(String channel, User user) {
2862  
        channel = channel.toLowerCase();
2863  
        synchronized (_channels) {
2864  
            Hashtable users = (Hashtable) _channels.get(channel);
2865  
            if (users == null) {
2866  
                users = new Hashtable();
2867  
                _channels.put(channel, users);
2868  
            }
2869  
            users.put(user, user);
2870  
        }
2871  
    }
2872  
    
2873  
    
2874  
    /**
2875  
     * Remove a user from the specified channel in our memory.
2876  
     */
2877  
    private final User removeUser(String channel, String nick) {
2878  
        channel = channel.toLowerCase();
2879  
        User user = new User("", nick);
2880  
        synchronized (_channels) {
2881  
            Hashtable users = (Hashtable) _channels.get(channel);
2882  
            if (users != null) {
2883  
                return (User) users.remove(user);
2884  
            }
2885  
        }
2886  
        return null;
2887  
    }
2888  
    
2889  
    
2890  
    /**
2891  
     * Remove a user from all channels in our memory.
2892  
     */
2893  
    private final void removeUser(String nick) {
2894  
        synchronized (_channels) {
2895  
            Enumeration enumeration = _channels.keys();
2896  
            while (enumeration.hasMoreElements()) {
2897  
                String channel = (String) enumeration.nextElement();
2898  
                this.removeUser(channel, nick);
2899  
            }
2900  
        }
2901  
    }
2902  
    
2903  
    
2904  
    /**
2905  
     * Rename a user if they appear in any of the channels we know about.
2906  
     */
2907  
    private final void renameUser(String oldNick, String newNick) {
2908  
        synchronized (_channels) {
2909  
            Enumeration enumeration = _channels.keys();
2910  
            while (enumeration.hasMoreElements()) {
2911  
                String channel = (String) enumeration.nextElement();
2912  
                User user = this.removeUser(channel, oldNick);
2913  
                if (user != null) {
2914  
                    user = new User(user.getPrefix(), newNick);
2915  
                    this.addUser(channel, user);
2916  
                }
2917  
            }
2918  
        }
2919  
    }
2920  
    
2921  
    
2922  
    /**
2923  
     * Removes an entire channel from our memory of users.
2924  
     */
2925  
    private final void removeChannel(String channel) {
2926  
        channel = channel.toLowerCase();
2927  
        synchronized (_channels) {
2928  
            _channels.remove(channel);
2929  
        }
2930  
    }
2931  
    
2932  
    
2933  
    /**
2934  
     * Removes all channels from our memory of users.
2935  
     */
2936  
    private final void removeAllChannels() {
2937  
        synchronized(_channels) {
2938  
            _channels = new Hashtable();
2939  
        }
2940  
    }
2941  
2942  
2943  
    private final void updateUser(String channel, int userMode, String nick) {
2944  
        channel = channel.toLowerCase();
2945  
        synchronized (_channels) {
2946  
            Hashtable users = (Hashtable) _channels.get(channel);
2947  
            User newUser = null;
2948  
            if (users != null) {
2949  
                Enumeration enumeration = users.elements();
2950  
                while(enumeration.hasMoreElements()) {
2951  
                    User userObj = (User) enumeration.nextElement();
2952  
                    if (userObj.getNick().equalsIgnoreCase(nick)) {
2953  
                        if (userMode == OP_ADD) {
2954  
                            if (userObj.hasVoice()) {
2955  
                                newUser = new User("@+", nick);
2956  
                            }
2957  
                            else {
2958  
                                newUser = new User("@", nick);
2959  
                            }
2960  
                        }
2961  
                        else if (userMode == OP_REMOVE) {
2962  
                            if(userObj.hasVoice()) {
2963  
                                newUser = new User("+", nick);
2964  
                            }
2965  
                            else {
2966  
                                newUser = new User("", nick);
2967  
                            }
2968  
                        }
2969  
                        else if (userMode == VOICE_ADD) {
2970  
                            if(userObj.isOp()) {
2971  
                                newUser = new User("@+", nick);
2972  
                            }
2973  
                            else {
2974  
                                newUser = new User("+", nick);
2975  
                            }
2976  
                        }
2977  
                        else if (userMode == VOICE_REMOVE) {
2978  
                            if(userObj.isOp()) {
2979  
                                newUser = new User("@", nick);
2980  
                            }
2981  
                            else {
2982  
                                newUser = new User("", nick);
2983  
                            }
2984  
                        }
2985  
                    }
2986  
                }
2987  
            }
2988  
            if (newUser != null) {
2989  
                users.put(newUser, newUser);
2990  
            }
2991  
            else {
2992  
                // just in case ...
2993  
                newUser = new User("", nick);
2994  
                users.put(newUser, newUser);
2995  
            }
2996  
        }
2997  
    }
2998  
2999  
3000  
    // Connection stuff.
3001  
    private InputThread _inputThread = null;
3002  
    private OutputThread _outputThread = null;
3003  
    private String _charset = null;
3004  
    private InetAddress _inetAddress = null;
3005  
3006  
    // Details about the last server that we connected to.
3007  
    private String _server = null;
3008  
    private int _port = -1;
3009  
    private String _password = null;
3010  
    
3011  
    // Outgoing message stuff.
3012  
    private Queue _outQueue = new Queue();
3013  
    private long _messageDelay = 1000;
3014  
    
3015  
    // A Hashtable of channels that points to a selfreferential Hashtable of
3016  
    // User objects (used to remember which users are in which channels).
3017  
    private Hashtable _channels = new Hashtable();
3018  
    
3019  
    // A Hashtable to temporarily store channel topics when we join them
3020  
    // until we find out who set that topic.
3021  
    private Hashtable _topics = new Hashtable();
3022  
    
3023  
    // DccManager to process and handle all DCC events.
3024  
    private DccManager _dccManager = new DccManager(this);
3025  
    private int[] _dccPorts = null;
3026  
    private InetAddress _dccInetAddress = null;
3027  
    
3028  
    // Default settings for the PircBot.
3029  
    private boolean _autoNickChange = false;
3030  
    private boolean _verbose = false;
3031  
    private String _name = "PircBot";
3032  
    private String _nick = _name;
3033  
    private String _login = "PircBot";
3034  
    private String _version = "PircBot " + VERSION + " Java IRC Bot - www.jibble.org";
3035  
    private String _finger = "You ought to be arrested for fingering a bot!";
3036  
    
3037  
    private String _channelPrefixes = "#&+!";
3038  
}

download  show line numbers  debug dex  old transpilations   

Travelled to 13 computer(s): aoiabmzegqzx, bhatertpkbcr, cbybwowwnfue, cfunsshuasjs, gwrvuhgaqvyk, ishqpsrjomds, lpdgvwnxivlt, mqqgnosmbjvj, pyentgdyhuwx, pzhvpgtvlbxg, tslmcundralx, tvejysmllsmz, vouqrxazstgt

No comments. add comment

Snippet ID: #1002680
Snippet name: class PircBot (modified)
Eternal ID of this version: #1002680/1
Text MD5: 04daf04aee12daa809c0c5ff0b61e6f7
Author: stefan
Category: javax
Type: JavaX source code
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2016-02-13 02:51:12
Source code size: 122486 bytes / 3038 lines
Pitched / IR pitched: No / No
Views / Downloads: 696 / 832
Referenced in: [show references]