irc.py

changeset 152
1b734faab67a
parent 146
c17b82b1f573
equal deleted inserted replaced
151:e24793fae424 152:1b734faab67a
29 from __future__ import print_function 29 from __future__ import print_function
30 import asyncore 30 import asyncore
31 import socket 31 import socket
32 import sys 32 import sys
33 import re 33 import re
34 import modulecore as ModuleCore
35 import traceback 34 import traceback
36 import time 35 import time
37 import datetime 36 import datetime
37
38 import modulecore
38 from configfile import Config 39 from configfile import Config
39 import bt as Bt 40 import bt as Bt
40 import hgpoll as HgPoll 41 import hgpoll as HgPoll
41 42
42 CLIF_CONNECTED = (1 << 1) 43 CLIF_CONNECTED = (1 << 1)
122 print ("[%s] Connected to [%s] %s:%d" % (get_timestamp(), self.name, self.host, self.port)) 123 print ("[%s] Connected to [%s] %s:%d" % (get_timestamp(), self.name, self.host, self.port))
123 self.register_to_irc() 124 self.register_to_irc()
124 125
125 def write (self, utfdata): 126 def write (self, utfdata):
126 try: 127 try:
127 if sys.version_info < (3, 0): 128 self.send_buffer.append (utfdata)
128 self.send_buffer.append (utfdata.decode("utf-8","ignore").encode("ascii","ignore"))
129 else:
130 self.send_buffer.append (utfdata)
131 except UnicodeEncodeError: 129 except UnicodeEncodeError:
132 pass 130 pass
133 131
134 def handle_close (self): 132 def handle_close (self):
135 print ("[%s] Connection to [%s] %s:%d terminated." % 133 print ("[%s] Connection to [%s] %s:%d terminated." %
148 def send_all_now (self): 146 def send_all_now (self):
149 for line in self.send_buffer: 147 for line in self.send_buffer:
150 if self.verbose: 148 if self.verbose:
151 print ("[%s] [%s] <- %s" % (get_timestamp(), self.name, line)) 149 print ("[%s] [%s] <- %s" % (get_timestamp(), self.name, line))
152 150
153 if sys.version_info >= (3, 0): 151 self.send (bytes (line + '\n', 'UTF-8'))
154 self.send (bytes (line + '\n', 'UTF-8'))
155 else:
156 self.send (line + '\n')
157 time.sleep (0.25) 152 time.sleep (0.25)
158 self.send_buffer = [] 153 self.send_buffer = []
159 154
160 def handle_read (self): 155 def handle_read (self):
161 lines = self.recv (4096).splitlines() 156 lines = self.recv (4096).splitlines()
162 for line in lines: 157 for line in lines:
163 try: 158 line = line.decode ('utf-8', 'ignore')
164 line = line.decode ('utf-8', 'ignore')
165
166 if sys.version_info < (3, 0):
167 line = line.encode ('ascii', 'ignore')
168 except UnicodeDecodeError:
169 continue
170 159
171 if self.verbose: 160 if self.verbose:
172 print ("[%s] [%s] -> %s" % (get_timestamp(), self.name, line)) 161 print ("[%s] [%s] -> %s" % (get_timestamp(), self.name, line))
173 162
174 if line[:len('PING :')] == ('PING :'): 163 if line[:len('PING :')] == ('PING :'):
175 self.write ("PONG :%s" % line[len('PING :'):]) 164 self.write ("PONG :%s" % line[len('PING :'):])
176 self.send_all_now() # pings must be responded to immediately! 165
166 # Pings must be responded to immediately, otherwise command/event/etc processing may
167 # delay the pong sending enough for the bot to be disconnected over a timeout.
168 self.send_all_now()
177 else: 169 else:
178 words = line.split(" ") 170 words = line.split(" ")
179 if len(words) >= 2: 171 if len(words) >= 2:
180 if words[1] == "001": 172 if words[1] == "001":
181 self.flags |= CLIF_CONNECTED 173 self.flags |= CLIF_CONNECTED
236 args = stuff[1:] 228 args = stuff[1:]
237 self.handle_command (sender, user, host, channel, replyto, command, args, message) 229 self.handle_command (sender, user, host, channel, replyto, command, args, message)
238 return 230 return
239 231
240 if channel != self.mynick: 232 if channel != self.mynick:
241 ModuleCore.call_hook (bot=self, hookname='chanmsg', channel=channel, sender=sender, 233 modulecore.call_hook (bot=self, hookname='chanmsg', channel=channel, sender=sender,
242 ident=user, host=host, message=message, replyto=replyto) 234 ident=user, host=host, message=message, replyto=replyto)
243 else: 235 else:
244 ModuleCore.call_hook (bot=self, hookname='querymsg', sender=sender, ident=user, 236 modulecore.call_hook (bot=self, hookname='querymsg', sender=sender, ident=user,
245 host=host, message=message, replyto=replyto) 237 host=host, message=message, replyto=replyto)
246 238
247 ModuleCore.call_hook (bot=self, hookname='privmsg', target=channel, sender=sender, 239 modulecore.call_hook (bot=self, hookname='privmsg', target=channel, sender=sender,
248 ident=user, host=host, message=message, replyto=replyto) 240 ident=user, host=host, message=message, replyto=replyto)
249 241
250 Bt.process_message (self, line, replyto) 242 Bt.process_message (self, line, replyto)
251 243
252 def add_irc_channel (self, channame): 244 def add_irc_channel (self, channame):
274 def handle_command (self, sender, ident, host, target, replyto, command, args, message): 266 def handle_command (self, sender, ident, host, target, replyto, command, args, message):
275 kvargs = {'sender': sender, 'ident': ident, 'host': host, 'target': target, 267 kvargs = {'sender': sender, 'ident': ident, 'host': host, 'target': target,
276 'replyto': replyto, 'cmdname': command, 'message': message} 268 'replyto': replyto, 'cmdname': command, 'message': message}
277 269
278 try: 270 try:
279 ModuleCore.call_command (self, **kvargs) 271 modulecore.call_command (self, **kvargs)
280 return 272 return
281 except ModuleCore.CommandError as e: 273 except modulecore.CommandError as e:
282 lines = str (e).split ('\n') 274 lines = str (e).splitlines()
283 self.privmsg (replyto, 'error: %s' % lines[0]) 275 self.privmsg (replyto, 'error: %s' % lines[0])
284 276
285 for line in lines[1:]: 277 for line in lines[1:]:
286 self.privmsg (replyto, ' ' + line) 278 self.privmsg (replyto, ' ' + line)
287 return 279 return

mercurial