1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 package com.levelonelabs.aimbot.modules;
34
35 import java.text.SimpleDateFormat;
36 import java.util.ArrayList;
37 import java.util.Calendar;
38 import java.util.Date;
39 import java.util.HashMap;
40 import java.util.Iterator;
41 import java.util.StringTokenizer;
42 import java.util.Timer;
43 import java.util.TimerTask;
44 import java.util.logging.Logger;
45
46 import org.w3c.dom.CDATASection;
47 import org.w3c.dom.Document;
48 import org.w3c.dom.Element;
49
50 import com.levelonelabs.aim.AIMBuddy;
51 import com.levelonelabs.aim.XMLizable;
52 import com.levelonelabs.aimbot.AIMBot;
53 import com.levelonelabs.aimbot.BotModule;
54
55
56 /***
57 * A class to handle scheduling commands to happen at certain times
58 *
59 * @author Steve Zingelewicz
60 * @created May 7th, 2003
61 */
62 public class ScheduleModule extends BotModule implements XMLizable {
63 private static ArrayList services;
64 private static Logger logger = Logger.getLogger(ScheduleModule.class.getName());
65 private static HashMap events = new HashMap();
66 private static Timer timer;
67
68
69 private class SchedulerTask extends TimerTask {
70 AIMBuddy buddy;
71 String cmd;
72 String triggerTime;
73 Date createDate;
74
75
76 SchedulerTask(AIMBuddy _buddy, String _cmd) {
77 buddy = _buddy;
78 cmd = _cmd;
79 createDate = new Date();
80
81
82 }
83
84
85 public void run() {
86 System.err.println("Timeout for: " + buddy.getName() + " cmd:" + cmd);
87 bot.handleMessage(buddy, cmd);
88
89 removeEvent(this);
90 }
91
92
93 public AIMBuddy getBuddy() {
94 return (buddy);
95 }
96
97
98 public String getCommand() {
99 return (cmd);
100 }
101
102
103 public String getCreateDate() {
104 return (createDate.toString());
105 }
106 }
107
108 /***
109 * Initialize the service commands.
110 */
111 static {
112 services = new ArrayList();
113 services.add("schedule");
114 services.add("cancel");
115 services.add("events");
116
117 timer = new Timer();
118 }
119
120
121 /***
122 * Constructor for the ReminderModule object
123 *
124 * @param bot
125 */
126 public ScheduleModule(AIMBot bot) {
127 super(bot);
128 }
129
130
131 /***
132 * Gets the name attribute of the SchedulerModule object
133 *
134 * @return The name value
135 */
136 public String getName() {
137 return "Scheduler Module";
138 }
139
140
141 /***
142 * Gets the services attribute of the SchedulerModule object
143 *
144 * @return The services value
145 */
146 public ArrayList getServices() {
147 return services;
148 }
149
150
151 /***
152 * Describes the usage of the module
153 *
154 * @return the usage of the module
155 */
156 public String help() {
157 StringBuffer sb = new StringBuffer();
158 sb.append("<B>schedule <i>TEXT</i></B> (stores text in the system for retrieval later)\n");
159 sb.append("<B>cancel <i>All or #</i></B> (removes all items or a specific item)\n");
160 sb.append("<B>events</B> (lists all reminders)\n");
161 sb
162 .append("* If the preference \"reminderatsignon\" is set to true, you will automatically get a list when you login to aim.\n");
163
164 return sb.toString();
165 }
166
167
168 /***
169 * Grabs and sends any stored reminders for a buddy
170 *
171 * @param buddy
172 * @return whether any messages where found
173 */
174 public boolean retrieveEvents(AIMBuddy buddy) {
175
176 ArrayList br = (ArrayList) events.get(buddy.getName());
177 if (br != null) {
178 String eventlist = "Events:<BR>";
179
180 if (br.size() != 0) {
181
182 for (int i = 0; i < br.size(); i++) {
183 SchedulerTask st = (SchedulerTask) br.get(i);
184 eventlist += ((i + 1) + ")" + (st.getCommand() + " scheduled " + st.getCreateDate() + "<BR>"));
185 }
186 } else
187 eventlist = "No events scheduled.";
188
189
190 super.sendMessage(buddy, eventlist);
191 return true;
192 }
193 return false;
194 }
195
196
197 /***
198 * Handle a messaging query
199 *
200 * @param buddy
201 * @param query
202 */
203 public void performService(AIMBuddy buddy, String query) {
204 if (query.toLowerCase().startsWith("schedule")) {
205 handleSchedule(buddy, query);
206 } else if (query.toLowerCase().startsWith("cancel")) {
207 handleCancel(buddy, query);
208 } else if (query.toLowerCase().startsWith("events")) {
209 if (!retrieveEvents(buddy)) {
210 sendMessage(buddy, "No events scheduled.");
211 }
212 }
213 }
214
215
216 /***
217 * Schedule time parsing function This function is getting huge and
218 * unwieldy. Once I get it all worked out, I'll figure out how to make it
219 * more manageable.
220 *
221 * @param buddy
222 * @param query
223 */
224 private void handleSchedule(AIMBuddy buddy, String query) {
225 String token;
226 StringTokenizer st = new StringTokenizer(query, " ");
227 int state = 0;
228 int stop = 0;
229 char ch;
230 long period = 60000;
231 String command = "";
232 SimpleDateFormat sdf = new SimpleDateFormat();
233 Date eventDate = null;
234 int sched_type = 0;
235
236 try {
237
238 while (st.hasMoreTokens() && stop == 0) {
239 token = st.nextToken();
240 System.err.println("token: " + token + "state:" + String.valueOf(state));
241
242 switch (state) {
243 case 0 :
244
245
246 if (token.equals("schedule"))
247 state = 1;
248 else
249 state = 99;
250 break;
251 case 1 :
252
253 if (token.equals("at")) {
254 sched_type = 1;
255 state = 2;
256 } else if (token.equals("in")) {
257 sched_type = 2;
258 state = 3;
259 } else if (token.equals("every")) {
260 sched_type = 3;
261 state = 4;
262 } else
263 state = 99;
264 break;
265 case 2 :
266
267
268
269 int at_idx = query.indexOf("at");
270 int delim_idx = query.indexOf("-");
271 if (at_idx != -1 && delim_idx != -1) {
272
273 System.err.println("Schedtoken:" + query.substring(at_idx + 2, delim_idx).trim());
274 try {
275 eventDate = sdf.parse(query.substring(at_idx + 2, delim_idx).trim());
276 state = 51;
277 } catch (Exception e) {
278 System.err.println("Can't parse date & time, trying just time..");
279 state = 99;
280 }
281
282 try {
283
284 sdf = new SimpleDateFormat("h:mm a");
285 eventDate = sdf.parse(query.substring(at_idx + 2, delim_idx).trim());
286 Calendar today = Calendar.getInstance();
287 today.set(Calendar.HOUR, 0);
288 today.set(Calendar.MINUTE, 0);
289 today.set(Calendar.SECOND, 0);
290 Date todaysDate = today.getTime();
291 System.err.println("event date:" + eventDate.toString());
292 System.err.println("today's date:" + todaysDate.toString());
293 System.err.println(eventDate.getTime());
294 System.err.println(todaysDate.getTime());
295
296
297 eventDate.setTime(eventDate.getTime() + todaysDate.getTime() - 18000000);
298 state = 51;
299 } catch (Exception e) {
300 System.err.println("Can't parse date or time, bailing");
301 state = 99;
302 }
303
304 } else
305 state = 99;
306 break;
307 case 3 :
308
309
310
311
312 ch = token.charAt(token.length() - 1);
313 period = Long.parseLong(token.substring(0, token.length() - 1));
314 state = 50;
315
316 if (ch == 's') {
317 period = period * 1000;
318 } else if (ch == 'm') {
319 period = period * 60000;
320 } else if (ch == 'h') {
321 period = period * 3600000;
322 } else if (ch == 'd') {
323 period = period * 86400000;
324 } else
325 state = 99;
326 break;
327 case 4 :
328
329 break;
330 case 50 :
331
332 if (token.equals("-")) {
333 stop = 1;
334 command = query.substring(query.indexOf('-') + 1).trim();
335 } else
336 state = 99;
337 break;
338 case 51 :
339
340 if (token.equals("-")) {
341 stop = 1;
342 command = query.substring(query.indexOf('-') + 1).trim();
343 }
344 break;
345 case 99 :
346
347 stop = 1;
348 break;
349 }
350 }
351
352 if (state == 1)
353
354 {
355 if (!retrieveEvents(buddy)) {
356 sendMessage(buddy, "No events available.");
357 }
358 } else if (state == 50) {
359
360
361 System.err.println("Scheduling " + command + " in " + String.valueOf(period));
362 addEvent(buddy, period, command);
363 sendMessage(buddy, "Event scheduled.");
364 } else if (state == 51) {
365
366
367 System.err.println("Scheduling " + command + " at " + eventDate.toString());
368 addEvent(buddy, eventDate, command);
369 sendMessage(buddy, "Event scheduled.");
370 } else if (state == 99) {
371 sendMessage(buddy, "Unable to understand schedule command");
372 } else
373 sendMessage(buddy, "That schedule command is not implemented yet");
374 } catch (Exception e) {
375 sendMessage(buddy, "Unable to understand schedule command");
376 e.printStackTrace();
377 }
378 }
379
380
381 /***
382 * Forget functionality
383 *
384 * @param buddy
385 * @param query
386 */
387 private void handleCancel(AIMBuddy buddy, String query) {
388
389 StringTokenizer st = new StringTokenizer(query, " ");
390
391
392 if (st.countTokens() != 2) {
393 sendMessage(buddy, "ERROR:\n" + help());
394 return;
395 }
396 st.nextToken();
397 String tok = st.nextToken();
398 if (tok.equalsIgnoreCase("all")) {
399 clearEvents(buddy);
400 sendMessage(buddy, "All events removed.");
401 } else {
402 try {
403 int loc = Integer.parseInt(tok) - 1;
404 if (removeEvent(buddy, loc)) {
405 sendMessage(buddy, "Event cancelled.");
406 } else {
407 sendMessage(buddy, "ERROR: number " + tok + " not valid.");
408 }
409 } catch (Exception e) {
410 e.printStackTrace();
411 sendMessage(buddy, "ERROR: number invalid: " + tok);
412 }
413 }
414 }
415
416
417 /***
418 * Remove Specific Reminder
419 *
420 * @param buddy
421 * buddy
422 * @param i
423 * list item number
424 * @return true if remove took place
425 */
426 public boolean removeEvent(AIMBuddy buddy, int i) {
427 ArrayList br = (ArrayList) events.get(buddy.getName());
428 if ((br != null) && (i >= 0) && (i < br.size())) {
429 br.remove(i);
430 return true;
431 }
432 return false;
433 }
434
435
436 /***
437 * @brief Removes an event given the event's SchedulerTask reference
438 * @param sTask
439 * The reference to the item to remove
440 */
441 void removeEvent(SchedulerTask sTask) {
442
443 ArrayList al;
444 al = (ArrayList) events.get(sTask.buddy.getName());
445 System.err.println("Removing events - " + String.valueOf(al.size()));
446 if (al != null) {
447 for (int i = 0; i < al.size(); i++) {
448
449 if ((SchedulerTask) al.get(i) == sTask) {
450 al.remove(i);
451 System.err.println("Removing " + String.valueOf(i));
452
453 break;
454 }
455 }
456 }
457 }
458
459
460 /***
461 * clear reminders for a buddy
462 *
463 * @param buddy
464 * buddy
465 */
466 public void clearEvents(AIMBuddy buddy) {
467 ArrayList br = (ArrayList) events.get(buddy.getName());
468 if (br != null) {
469 br.clear();
470 }
471 }
472
473
474 /***
475 * Add a reminder for a buddy
476 *
477 * @param buddy
478 * buddy
479 * @param period
480 * Delay for timer
481 */
482 public void addEvent(AIMBuddy buddy, long period, String command) {
483 ArrayList br = (ArrayList) events.get(buddy.getName());
484 if (br == null) {
485 br = new ArrayList();
486 events.put(buddy.getName(), br);
487 }
488
489 SchedulerTask st = new SchedulerTask(buddy, command);
490 timer.schedule(st, period);
491
492 br.add(st);
493 }
494
495
496 /***
497 * Add a reminder for a buddy
498 *
499 * @param buddy
500 * buddy
501 * @param eventDate
502 * Date of scheduled event
503 */
504 public void addEvent(AIMBuddy buddy, Date eventDate, String command) {
505 ArrayList br = (ArrayList) events.get(buddy.getName());
506 if (br == null) {
507 br = new ArrayList();
508 events.put(buddy.getName(), br);
509 }
510
511 SchedulerTask st = new SchedulerTask(buddy, command);
512 timer.schedule(st, eventDate);
513
514 br.add(st);
515 }
516
517
518 /***
519 * @see com.levelonelabs.aim.XMLizable#writeState(Element)
520 */
521 public void writeState(Element emptyStateElement) {
522 Document doc = emptyStateElement.getOwnerDocument();
523 Iterator iter = events.keySet().iterator();
524
525 while (iter.hasNext()) {
526 String name = (String) iter.next();
527 ArrayList br = (ArrayList) events.get(name);
528 if (br.size() > 0) {
529 Element buddyElem = doc.createElement("buddy");
530 buddyElem.setAttribute("name", name);
531 for (int i = 0; i < br.size(); i++) {
532 Element remElem = doc.createElement("event");
533 SchedulerTask st = (SchedulerTask) br.get(i);
534
535 Element buddy = doc.createElement("buddy");
536 CDATASection buddy_data = doc.createCDATASection(st.getBuddy().getName());
537 buddy.appendChild(buddy_data);
538
539 Element cmd = doc.createElement("command");
540 CDATASection cmd_data = doc.createCDATASection(st.getCommand());
541 cmd.appendChild(cmd_data);
542
543 Element createDate = doc.createElement("createDate");
544 CDATASection cd_data = doc.createCDATASection(st.getCreateDate());
545 createDate.appendChild(cd_data);
546
547 remElem.appendChild(buddy);
548 remElem.appendChild(cmd);
549 remElem.appendChild(createDate);
550 buddyElem.appendChild(remElem);
551 }
552 emptyStateElement.appendChild(buddyElem);
553 }
554 }
555 }
556
557
558 /***
559 * @see com.levelonelabs.aim.XMLizable#readState(Element)
560 */
561
562
563
564
565
566
567
568
569 public void readState(Element fullStateElement) {
570
571
572
573
574
575
576
577
578
579
580
581
582
583 }
584 }