Index: trunk/debs/ircecho/ircecho |
— | — | @@ -9,26 +9,79 @@ |
10 | 10 | import sys |
11 | 11 | import pyinotify |
12 | 12 | import threading |
| 13 | +import random |
| 14 | +import string |
| 15 | +import re |
13 | 16 | from optparse import OptionParser |
14 | 17 | sys.path.append('/usr/ircecho/lib') |
15 | 18 | from ircbot import SingleServerIRCBot |
16 | 19 | |
| 20 | +class EchoNotifier(threading.Thread): |
| 21 | + def __init__(self, notifier): |
| 22 | + threading.Thread.__init__(self) |
| 23 | + self.notifier = notifier |
| 24 | + |
| 25 | + def run(self): |
| 26 | + self.notifier.loop() |
| 27 | + |
17 | 28 | class EchoReader(threading.Thread): |
18 | | - def __init__(self, infile=''): |
| 29 | + def __init__(self, infile='', associatedchannel=''): |
19 | 30 | threading.Thread.__init__(self) |
20 | 31 | self.infile = infile |
| 32 | + self.associatedchannel = associatedchannel |
| 33 | + self.uniques = {';': "UNIQ_" + self.get_unique_string() + "_QINU", |
| 34 | + ':': "UNIQ_" + self.get_unique_string() + "_QINU", |
| 35 | + ',': "UNIQ_" + self.get_unique_string() + "_QINU"} |
21 | 36 | |
| 37 | + def get_unique_string(self): |
| 38 | + unique = '' |
| 39 | + for i in range(15): |
| 40 | + unique = unique + random.choice(string.letters) |
| 41 | + return unique |
| 42 | + |
| 43 | + def escape(self, string): |
| 44 | + escaped_string = re.sub('\\\;', self.uniques[';'], string) |
| 45 | + escaped_string = re.sub('\\\:', self.uniques[':'], escaped_string) |
| 46 | + escaped_string = re.sub('\\\,', self.uniques[','], escaped_string) |
| 47 | + return escaped_string |
| 48 | + |
| 49 | + def unescape(self, string): |
| 50 | + unescaped_string = re.sub(self.uniques[';'], ';', string) |
| 51 | + unescaped_string = re.sub(self.uniques[':'], ':', unescaped_string) |
| 52 | + unescaped_string = re.sub(self.uniques[','], ',', unescaped_string) |
| 53 | + return unescaped_string |
| 54 | + |
22 | 55 | def run(self): |
23 | 56 | if self.infile: |
24 | 57 | print "Using infile" |
25 | | - self.f = open(self.infile) |
26 | | - # Seek to the end of the file |
27 | | - self.f.seek(0,2) |
28 | | - wm = pyinotify.WatchManager() |
29 | | - notifier = pyinotify.Notifier(wm) |
30 | | - mask = pyinotify.IN_MODIFY | pyinotify.IN_CREATE |
31 | | - wdd = wm.watch_transient_file(self.infile, mask, EventHandler) |
32 | | - notifier.loop() |
| 58 | + self.notifiers = [] |
| 59 | + self.associations = {} |
| 60 | + self.files = {} |
| 61 | + infiles = self.escape(self.infile) |
| 62 | + for filechan in infiles.split(';'): |
| 63 | + temparr = filechan.split(':') |
| 64 | + filename = self.unescape(temparr[0]) |
| 65 | + try: |
| 66 | + print "Opening: " + filename |
| 67 | + f = open(filename) |
| 68 | + f.seek(0,2) |
| 69 | + self.files[filename] = f |
| 70 | + except IOError: |
| 71 | + print "Failed to open file: " + filename |
| 72 | + self.files[filename] = None |
| 73 | + pass |
| 74 | + wm = pyinotify.WatchManager() |
| 75 | + mask = pyinotify.IN_MODIFY | pyinotify.IN_CREATE |
| 76 | + wm.watch_transient_file(filename, mask, EventHandler) |
| 77 | + notifier = EchoNotifier(pyinotify.Notifier(wm)) |
| 78 | + self.notifiers.append(notifier) |
| 79 | + # Does this file have channel associations? |
| 80 | + if len(temparr) > 1: |
| 81 | + chans = self.unescape(temparr[1]) |
| 82 | + self.associations[filename] = chans |
| 83 | + for notifier in self.notifiers: |
| 84 | + print "Starting notifier loop" |
| 85 | + notifier.start() |
33 | 86 | else: |
34 | 87 | while True: |
35 | 88 | try: |
— | — | @@ -40,7 +93,18 @@ |
41 | 94 | break; |
42 | 95 | except Exception: |
43 | 96 | pass |
| 97 | + def readfile(self, filename): |
| 98 | + if self.files[filename]: |
| 99 | + return self.files[filename].read() |
| 100 | + else: |
| 101 | + return |
44 | 102 | |
| 103 | + def getchannels(self, filename): |
| 104 | + if filename in self.associations: |
| 105 | + return self.associations[filename] |
| 106 | + else: |
| 107 | + return bot.chans |
| 108 | + |
45 | 109 | class EchoBot(SingleServerIRCBot): |
46 | 110 | def __init__(self, chans, nickname, server): |
47 | 111 | print "*** Connecting to IRC server %s..." % server |
— | — | @@ -57,15 +121,17 @@ |
58 | 122 | |
59 | 123 | class EventHandler(pyinotify.ProcessEvent): |
60 | 124 | def process_IN_MODIFY(self, event): |
61 | | - s = reader.f.read() |
62 | | - bot.connection.privmsg(bot.chans, s) |
| 125 | + s = reader.readfile(event.pathname) |
| 126 | + if s: |
| 127 | + chans = reader.getchannels(event.pathname) |
| 128 | + bot.connection.privmsg(chans, s) |
63 | 129 | |
64 | 130 | def process_IN_CREATE(self, event): |
65 | 131 | try: |
66 | | - print "Reopening file" |
67 | | - reader.f = open(reader.infile) |
| 132 | + print "Reopening file: " + event.pathname |
| 133 | + reader.files[event.pathname] = open(event.pathname) |
68 | 134 | except IOError: |
69 | | - print "Failed to reopen file" |
| 135 | + print "Failed to reopen file: " + event.pathname |
70 | 136 | pass |
71 | 137 | |
72 | 138 | parser = OptionParser(conflict_handler="resolve") |