ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/i-scream/projects/cms/source/server/uk/org/iscream/cms/server/client/alerters/IRC__Alerter.java
(Generate patch)

Comparing projects/cms/source/server/uk/org/iscream/cms/server/client/alerters/IRC__Alerter.java (file contents):
Revision 1.8 by ajm, Sun Mar 4 02:41:16 2001 UTC vs.
Revision 1.9 by tdb, Sun Mar 4 03:34:50 2001 UTC

# Line 9 | Line 9 | import uk.ac.ukc.iscream.componentmanager.*;
9  
10   import java.io.*;
11   import java.net.*;
12 + import java.util.*;
13  
14   /**
15   * This Alert sends an IRC message.
16   *
17 + * Clean shutdown could be achieved by stopping the run() method in the
18 + * IRCBot inner class.
19 + *
20   * @author  $Author$
21   * @version $Id$
22   */
# Line 25 | Line 29 | public class IRC__Alerter implements PluginAlerter {
29       */
30      public final String REVISION = "$Revision$";
31      
32 +    /**
33 +     * A description of this alerter
34 +     */
35      public final String DESC = "Sends alerts on an IRC channel";
36      
37 +    /**
38 +     * The default reconnect delay in seconds
39 +     */
40 +    public final int DEFAULT_RECONNECT_DELAY = 30;
41 +    
42   //---STATIC METHODS---
43  
44   //---CONSTRUCTORS---
# Line 34 | Line 46 | public class IRC__Alerter implements PluginAlerter {
46      public IRC__Alerter() {
47                          
48          // connect to the IRC server
49 <        _ircbot = null;
50 <        try {
39 <            _ircbot = new IRCBot();
40 <            _ircbot.connect();
41 <            _ircbot.sendNotice("i-scream alerting bot activated");
42 <        } catch(IOException e) {
43 <            _logger.write(toString(), Logger.ERROR, "Error starting IRCBot: "+e);
44 <        }
49 >        _ircbot = new IRCBot();
50 >        _ircbot.start();
51          
52          _logger.write(toString(), Logger.SYSINIT, "IRC Alerter started");
53      }
# Line 49 | Line 55 | public class IRC__Alerter implements PluginAlerter {
55   //---PUBLIC METHODS---
56  
57      public void sendAlert(Alert alert) {
58 <        ConfigurationProxy cp = ConfigurationProxy.getInstance();
59 <        String levelName = cp.getProperty(_name, "Alerter.IRC.level");
60 <        int level = StringUtils.getStringPos(levelName, Alert.alertLevels);
61 <        // only send if it's equal (or above) our level
62 <        if(alert.getLevel() >= level) {
63 <            String alertType = Alert.alertLevels[alert.getLevel()];
64 <            String thresholdType = Alert.thresholdLevels[alert.getThreshold()];
65 <            // sort out the message
66 <            String message = cp.getProperty(_name, "Alerter.IRC.message");
67 <            message = StringUtils.replaceText(message, "%level%", alertType);
68 <            message = StringUtils.replaceText(message, "%threshold%", thresholdType);
69 <            message = StringUtils.replaceText(message, "%source%", alert.getSource());
70 <            message = StringUtils.replaceText(message, "%value%", alert.getValue());
71 <            message = StringUtils.replaceText(message, "%thresholdValue%", alert.getThresholdValue());
72 <            message = StringUtils.replaceText(message, "%attributeName%", alert.getAttributeName());
73 <            message = StringUtils.replaceText(message, "%timeTillNextAlert%",  getTimeString(Long.parseLong(alert.getTimeTillNextAlert())));
74 <            
75 <            // send the message
76 <            _logger.write(toString(), Logger.DEBUG, "Sending " + _name + " at "+ levelName + " level");
77 <            _ircbot.sendMsg(message);
58 >        // only send alerts if we're active
59 >        if(_active) {
60 >            ConfigurationProxy cp = ConfigurationProxy.getInstance();
61 >            String levelName = cp.getProperty(_name, "Alerter.IRC.level");
62 >            int level = StringUtils.getStringPos(levelName, Alert.alertLevels);
63 >            // only send if it's equal (or above) our level
64 >            if(alert.getLevel() >= level) {
65 >                String alertType = Alert.alertLevels[alert.getLevel()];
66 >                String thresholdType = Alert.thresholdLevels[alert.getThreshold()];
67 >                // sort out the message
68 >                String message = cp.getProperty(_name, "Alerter.IRC.message");
69 >                message = StringUtils.replaceText(message, "%level%", alertType);
70 >                message = StringUtils.replaceText(message, "%threshold%", thresholdType);
71 >                message = StringUtils.replaceText(message, "%source%", alert.getSource());
72 >                message = StringUtils.replaceText(message, "%value%", alert.getValue());
73 >                message = StringUtils.replaceText(message, "%thresholdValue%", alert.getThresholdValue());
74 >                message = StringUtils.replaceText(message, "%attributeName%", alert.getAttributeName());
75 >                message = StringUtils.replaceText(message, "%timeTillNextAlert%",  getTimeString(Long.parseLong(alert.getTimeTillNextAlert())));
76 >                
77 >                // send the message
78 >                _logger.write(toString(), Logger.DEBUG, "Sending " + _name + " at "+ levelName + " level");
79 >                _ircbot.sendMsg(message);
80 >                _lastAlert = message;
81 >            }
82          }
83      }
84  
# Line 119 | Line 129 | public class IRC__Alerter implements PluginAlerter {
129      private IRCBot _ircbot;
130      
131      /**
132 +     * Are we "active"
133 +     */
134 +    private boolean _active = false;
135 +    
136 +    /**
137 +     * The last alert that was sent
138 +     */
139 +    private String _lastAlert = "no alerts have been sent";
140 +    
141 +    /**
142       * This is the friendly identifier of the
143       * component this class is running in.
144       * eg, a Filter may be called "filter1",
# Line 153 | Line 173 | public class IRC__Alerter implements PluginAlerter {
173           * present moment it only responds to pings.
174           */
175          public void run() {
176 <            // flag so we can stop the loop
176 >            // so we can stop if required
177              boolean run = true;
178              while(run) {
179 +                // flag so we can stop the loop
180 +                boolean doRead = true;
181 +                // connect to the IRC server
182                  try {
183 <                    // read a command
184 <                    String cmd = _socketIn.readLine();
185 <                    // if it's a PING...
186 <                    if(cmd.startsWith("PING")) {
187 <                        // ...send a PONG
188 <                        _socketOut.println("PONG" + cmd.substring(4));
183 >                    connect();
184 >                    sendNotice(ConfigurationProxy.getInstance().getProperty(_name, "Alerter.IRC.startupNotice"));
185 >                } catch(IOException e) {
186 >                    doRead=false;
187 >                    _logger.write(this.toString(), Logger.ERROR, "Error connecting: "+e);
188 >                }
189 >                while(doRead) {
190 >                    try {
191 >                        // read a command
192 >                        String cmd = _socketIn.readLine();
193 >                        // if we have a null, we've lost contact
194 >                        if(cmd == null) {
195 >                            throw new IOException("End of stream reached");
196 >                        }
197 >                        // let another method deal with the input
198 >                        handleInput(cmd);
199 >                    } catch (IOException e) {
200 >                        // comms failure, maybe our link is dead.
201 >                        _logger.write(this.toString(), Logger.ERROR, "Communication error: "+e);
202 >                        // stop, and loop round for a reconnect.
203 >                        doRead = false;
204                      }
205 +                }
206 +                // make sure we're disconnected
207 +                try {
208 +                    disconnect();
209                  } catch (IOException e) {
210 <                    // comms failure, lets stop
169 <                    _logger.write(this.toString(), Logger.ERROR, "Comms error: "+e);
170 <                    //run = false;
210 >                    _logger.write(this.toString(), Logger.ERROR, "Communication error: "+e);
211                  }
212 +                
213 +                // comms have failed, so wait a while and reconnect
214 +                int delayTime = 0;
215 +                try {
216 +                    delayTime = Integer.parseInt(ConfigurationProxy.getInstance().getProperty(_name, "Alerter.IRC.reconnectDelay"));
217 +                } catch (NumberFormatException e) {
218 +                    delayTime = DEFAULT_RECONNECT_DELAY;
219 +                    _logger.write(this.toString(), Logger.WARNING, "Erronous Alerter.IRC.reconnectDelay value in configuration using default of " + delayTime + " seconds");
220 +                } catch (org.omg.CORBA.MARSHAL e2) {
221 +                    delayTime = DEFAULT_RECONNECT_DELAY;
222 +                    _logger.write(this.toString(), Logger.WARNING, "Alerter.IRC.reconnectDelay value unavailable using default of " + delayTime + " seconds");
223 +                }
224 +                try {
225 +                    Thread.sleep(delayTime * 1000);
226 +                } catch (InterruptedException e) {}
227              }
228 +            // maybe disconnect here ? - shutdown method not implemented yet
229 +            //disconnect();
230          }
231          
232          /**
# Line 182 | Line 239 | public class IRC__Alerter implements PluginAlerter {
239          }
240          
241          /**
242 +         * Sends a message to the channel.
243 +         *
244 +         * @param user The user to send to
245 +         * @param msg The message to send
246 +         */
247 +        public void sendPrivMsg(String user, String msg) {
248 +            _socketOut.println("PRIVMSG "+user+" :"+msg);
249 +        }
250 +        
251 +        /**
252 +         * Sends an action to the channel.
253 +         *
254 +         * @param msg the action message
255 +         */
256 +        public void sendAction(String msg) {
257 +            char esc = 001;
258 +            sendMsg(esc+"ACTION "+msg+esc);
259 +        }
260 +        
261 +        /**
262           * Sends a notice to the channel.
263           *
264           * @param msg The notice to send
# Line 203 | Line 280 | public class IRC__Alerter implements PluginAlerter {
280              _socket = new Socket(server, port);
281              _socketIn = new BufferedReader(new InputStreamReader(_socket.getInputStream()));
282              _socketOut = new PrintWriter(_socket.getOutputStream(), true);
283 <            // send the various log in messages
284 <            _socketOut.println("PASS");
285 <            _socketOut.println("NICK "+cp.getProperty(_name, "Alerter.IRC.nick"));  
286 <            _socketOut.println("USER i-scream 8 * :i-scream alerter bot");
283 >            //_socketOut.println("PASS");
284 >            // send USER details
285 >            String user = cp.getProperty(_name, "Alerter.IRC.user");
286 >            String comment = cp.getProperty(_name, "Alerter.IRC.comment");
287 >            _socketOut.println("USER "+user+" 8 * :"+comment);
288 >            // attempt to get a nick
289 >            String nickList = cp.getProperty(_name, "Alerter.IRC.nickList");
290 >            StringTokenizer st = new StringTokenizer(nickList, ";");
291 >            boolean ok = false;
292 >            // try until we exhaust our list
293 >            while(!ok && st.hasMoreTokens()) {
294 >                String nick = st.nextToken();
295 >                _socketOut.println("NICK "+nick);
296 >                // get a "yes" or "no" response back
297 >                String response = "";
298 >                do {
299 >                    response = _socketIn.readLine();
300 >                    if(response==null) {
301 >                        throw new IOException("Communication error whilst logging in");
302 >                    }
303 >                } while(response.indexOf("001")==-1 && response.indexOf("433")==-1);
304 >                // see if it was a yes
305 >                if(response.indexOf("001")!=-1) {
306 >                    // great, we're logged in !
307 >                    ok = true;
308 >                    // store the name we're using
309 >                    _nickname = nick;
310 >                }
311 >                else {
312 >                    // log we couldn't get the name
313 >                    _logger.write(this.toString(), Logger.WARNING, "Nickname in use: "+nick);
314 >                }
315 >            }
316 >            if(!ok) {
317 >                // oh dear, we couldn't get on.
318 >                throw new IOException("All nicknames in use");
319 >            }
320              // join the channel
321              _channel = cp.getProperty(_name, "Alerter.IRC.channel");
322              _socketOut.println("JOIN "+_channel);
323 <            // start our listening thread
324 <            this.start();
323 >            // allow alerts
324 >            _active = true;
325          }
326          
327          /**
# Line 220 | Line 330 | public class IRC__Alerter implements PluginAlerter {
330           * @throws IOException if the disconnection fails
331           */
332          public void disconnect() throws IOException {
333 +            // stop alerts
334 +            _active = false;
335              // send proper QUIT
336              _socketOut.println("QUIT : iscreamBot component shutting down...");
337              // close the socket
# Line 229 | Line 341 | public class IRC__Alerter implements PluginAlerter {
341          }
342          
343          /**
344 +         * Overrides the {@link java.lang.Object#toString() Object.toString()}
345 +         * method to provide clean logging (every class should have this).
346 +         *
347 +         * This uses the uk.ac.ukc.iscream.util.NameFormat class
348 +         * to format the toString()
349 +         *
350 +         * @return the name of this class and its CVS revision
351 +         */
352 +        public String toString() {
353 +            return FormatName.getName(
354 +                _name,
355 +                getClass().getName(),
356 +                REVISION);
357 +        }
358 +        
359 +        /**
360 +         * Deals with incoming lines from the server.
361 +         *
362 +         * @param line the line to deal with
363 +         */
364 +        private void handleInput(String line) {
365 +            ConfigurationProxy cp = ConfigurationProxy.getInstance();
366 +            // if it's a PING...
367 +            if(line.startsWith("PING")) {
368 +                // ...send a PONG
369 +                _socketOut.println("PONG" + line.substring(4));
370 +            }
371 +            // see if it's for us
372 +            else if(getMsg(line).startsWith(_nickname)) {
373 +                // we have a message for us
374 +                String message = getMsg(line).substring(_nickname.length());
375 +                if(message.indexOf(cp.getProperty(_name, "Alerter.IRC.stopCommand"))!=-1) {
376 +                    _active = false;
377 +                    sendMsg(getMsgSender(line)+", alerts have been stopped");
378 +                }
379 +                else if(message.indexOf(cp.getProperty(_name, "Alerter.IRC.startCommand"))!=-1) {
380 +                    _active = true;
381 +                    sendMsg(getMsgSender(line)+", alerts have been activated");
382 +                }
383 +                else if(message.indexOf(cp.getProperty(_name, "Alerter.IRC.lastAlertCommand"))!=-1) {
384 +                    sendMsg(getMsgSender(line)+", last alert was: "+_lastAlert);
385 +                }
386 +                else if(message.indexOf(cp.getProperty(_name, "Alerter.IRC.joinCommand"))!=-1) {
387 +                    String joinCmd = cp.getProperty(_name, "Alerter.IRC.joinCommand");
388 +                    String newChan = message.substring(message.indexOf(joinCmd) + joinCmd.length() + 1);
389 +                    int endOfChan = newChan.indexOf(" ");
390 +                    if(endOfChan == -1) {
391 +                        endOfChan = newChan.length();
392 +                    }
393 +                    newChan = newChan.substring(0, endOfChan);
394 +                    sendMsg(getMsgSender(line)+", okay, I'm off to "+newChan);
395 +                    _socketOut.println("PART "+_channel);
396 +                    _socketOut.println("JOIN "+newChan);
397 +                    _channel = newChan;
398 +                }
399 +                else if(message.indexOf(cp.getProperty(_name, "Alerter.IRC.helpCommand"))!=-1) {
400 +                    sendPrivMsg(getMsgSender(line), "I am the i-scream alerting bot revision "+REVISION.substring(11, REVISION.length() -2));
401 +                    sendPrivMsg(getMsgSender(line), "I understand the following commands;");
402 +                    sendPrivMsg(getMsgSender(line), cp.getProperty(_name, "Alerter.IRC.stopCommand"));
403 +                    sendPrivMsg(getMsgSender(line), cp.getProperty(_name, "Alerter.IRC.startCommand"));
404 +                    sendPrivMsg(getMsgSender(line), cp.getProperty(_name, "Alerter.IRC.lastAlertCommand"));
405 +                }
406 +                else if(message.indexOf("do a jibble dance")!=-1) {
407 +                    // little joke :)
408 +                    sendAction("jives to the funky beat shouting \"ii--screeeaaammm\"");
409 +                }
410 +                else {
411 +                    sendMsg(getMsgSender(line)+", "+cp.getProperty(_name, "Alerter.IRC.rejectMessage"));
412 +                }
413 +            }
414 +            else if(line.indexOf(_nickname)!=-1 && line.indexOf(_channel)!=-1 && line.indexOf("KICK")!=-1) {
415 +                sendPrivMsg(getMsgSender(line), "That wasn't a nice thing to do...");
416 +                _channel = cp.getProperty(_name, "Alerter.IRC.channel");
417 +                _socketOut.println("JOIN "+_channel);
418 +            }
419 +        }
420 +        
421 +        /**
422 +         * Strips the header from a message line
423 +         *
424 +         * @param line the line to strip
425 +         * @return the message from the line
426 +         */
427 +        private String getMsg(String line) {
428 +            String result = "";
429 +            if(line.indexOf("PRIVMSG")!=-1) {
430 +                int firstColon = line.indexOf(":");
431 +                if(firstColon != -1) {
432 +                    int secondColon = line.indexOf(":", firstColon+1);
433 +                    if(secondColon != -1) {
434 +                        result = line.substring(secondColon+1);
435 +                    }
436 +                }
437 +            }
438 +            return result;
439 +        }
440 +        
441 +        /**
442 +         * Finds out the sender of the message
443 +         *
444 +         * @param line the line to look for a sender in
445 +         * @return the sender
446 +         */
447 +        private String getMsgSender(String line) {
448 +            String result = "";
449 +            int colon = line.indexOf(":");
450 +            int excl = line.indexOf("!");
451 +            if(colon!=-1 && excl!=-1) {
452 +                result = line.substring(colon+1, excl);
453 +            }
454 +            return result;
455 +        }
456 +        
457 +        /**
458           * The socket connected to the server
459           */
460          private Socket _socket;
# Line 248 | Line 474 | public class IRC__Alerter implements PluginAlerter {
474           * this can't be dynamic :)
475           */
476          private String _channel;
477 +        
478 +        /**
479 +         * A reminder of our current nickname...
480 +         */
481 +        private String _nickname;
482 +        
483      }
484  
485   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines