raw
logotron_genesis.kv     1 #!/usr/bin/python
logotron_genesis.kv 2
logotron_genesis.kv 3 import ConfigParser, sys, logging, socket, time, re, requests, urllib
logotron_genesis.kv 4 from urllib import quote
logotron_genesis.kv 5
logotron_genesis.kv 6 # DBism
logotron_genesis.kv 7 import psycopg2, psycopg2.extras
logotron_genesis.kv 8 import psycopg2.extensions
logotron_genesis.kv 9 psycopg2.extensions.register_type(psycopg2.extensions.UNICODE)
logotron_genesis.kv 10 psycopg2.extensions.register_type(psycopg2.extensions.UNICODEARRAY)
logotron_genesis.kv 11 import time, datetime
logotron_genesis.kv 12 from datetime import datetime
logotron_genesis.kv 13
logotron_genesis.kv 14 ##############################################################################
logotron_genesis.kv 15
logotron_genesis.kv 16 cfg = ConfigParser.ConfigParser()
logotron_genesis.kv 17
logotron_genesis.kv 18 ##############################################################################
logotron_genesis.kv 19
logotron_genesis.kv 20 # Single mandatory arg: config file path
logotron_genesis.kv 21 if len(sys.argv[1:]) != 1:
logotron_genesis.kv 22 # If no args, print usage and exit:
logotron_genesis.kv 23 print sys.argv[0] + " CONFIG"
logotron_genesis.kv 24 exit(0)
logotron_genesis.kv 25
logotron_genesis.kv 26 # Read Config
logotron_genesis.kv 27 cfg.readfp(open(sys.argv[1]))
logotron_genesis.kv 28
logotron_genesis.kv 29 # Get log path
logotron_genesis.kv 30 logpath = cfg.get("bofh", "log")
logotron_genesis.kv 31
logotron_genesis.kv 32 # Get IRCism debug toggle
logotron_genesis.kv 33 irc_dbg = cfg.get("irc", "irc_dbg")
logotron_genesis.kv 34 if irc_dbg == 1:
logotron_genesis.kv 35 log_lvl = logging.DEBUG
logotron_genesis.kv 36 else:
logotron_genesis.kv 37 log_lvl = logging.INFO
logotron_genesis.kv 38
logotron_genesis.kv 39 # Init logo
logotron_genesis.kv 40 logging.basicConfig(filename=logpath, filemode='a', level=log_lvl,
logotron_genesis.kv 41 format='%(asctime)s %(levelname)s %(message)s',
logotron_genesis.kv 42 datefmt='%d-%b-%y %H:%M:%S')
logotron_genesis.kv 43
logotron_genesis.kv 44 # Date format used in log lines
logotron_genesis.kv 45 Date_Short_Format = "%Y-%m-%d"
logotron_genesis.kv 46
logotron_genesis.kv 47 # Date format used in echoes
logotron_genesis.kv 48 Date_Long_Format = "%Y-%m-%d %H:%M:%S"
logotron_genesis.kv 49
logotron_genesis.kv 50 ##############################################################################
logotron_genesis.kv 51 # Get the remaining knob values:
logotron_genesis.kv 52
logotron_genesis.kv 53 try:
logotron_genesis.kv 54 # IRCism:
logotron_genesis.kv 55 Buf_Size = int(cfg.get("tcp", "bufsize"))
logotron_genesis.kv 56 Timeout = int(cfg.get("tcp", "timeout"))
logotron_genesis.kv 57 TX_Delay = float(cfg.get("tcp", "t_delay"))
logotron_genesis.kv 58 Servers = [x.strip() for x in cfg.get("irc", "servers").split(',')]
logotron_genesis.kv 59 Port = int(cfg.get("irc", "port"))
logotron_genesis.kv 60 Nick = cfg.get("irc", "nick")
logotron_genesis.kv 61 Pass = cfg.get("irc", "pass")
logotron_genesis.kv 62 Channels = [x.strip() for x in cfg.get("irc", "chans").split(',')]
logotron_genesis.kv 63 Join_Delay = int(cfg.get("irc", "join_t"))
logotron_genesis.kv 64 Prefix = cfg.get("control", "prefix")
logotron_genesis.kv 65 # DBism:
logotron_genesis.kv 66 DB_Name = cfg.get("db", "db_name")
logotron_genesis.kv 67 DB_User = cfg.get("db", "db_user")
logotron_genesis.kv 68 DB_DEBUG = cfg.get("db", "db_debug")
logotron_genesis.kv 69 # Logism:
logotron_genesis.kv 70 Base_URL = cfg.get("logotron", "base_url")
logotron_genesis.kv 71 Era = int(cfg.get("logotron", "era"))
logotron_genesis.kv 72 NewChan_Idx = int(cfg.get("logotron", "newchan_idx"))
logotron_genesis.kv 73 Src_URL = cfg.get("logotron", "src_url")
logotron_genesis.kv 74
logotron_genesis.kv 75 except Exception as e:
logotron_genesis.kv 76 print "Invalid config: ", e
logotron_genesis.kv 77 exit(1)
logotron_genesis.kv 78
logotron_genesis.kv 79 ##############################################################################
logotron_genesis.kv 80
logotron_genesis.kv 81 # Connect to the given DB
logotron_genesis.kv 82 try:
logotron_genesis.kv 83 db = psycopg2.connect("dbname=%s user=%s" % (DB_Name, DB_User))
logotron_genesis.kv 84 except Exception:
logotron_genesis.kv 85 print "Could not connect to DB!"
logotron_genesis.kv 86 logging.error("Could not connect to DB!")
logotron_genesis.kv 87 exit(1)
logotron_genesis.kv 88 else:
logotron_genesis.kv 89 logging.info("Connected to DB!")
logotron_genesis.kv 90
logotron_genesis.kv 91 ##############################################################################
logotron_genesis.kv 92
logotron_genesis.kv 93 def close_db():
logotron_genesis.kv 94 db.close()
logotron_genesis.kv 95
logotron_genesis.kv 96 def exec_db(query, args=()):
logotron_genesis.kv 97 cur = db.cursor(cursor_factory=psycopg2.extras.RealDictCursor)
logotron_genesis.kv 98 if (DB_DEBUG): logging.debug("query: '{0}'".format(query))
logotron_genesis.kv 99 if (DB_DEBUG): logging.debug("args: '{0}'".format(args))
logotron_genesis.kv 100 cur.execute(query, args)
logotron_genesis.kv 101
logotron_genesis.kv 102 def query_db(query, args=(), one=False):
logotron_genesis.kv 103 cur = db.cursor(cursor_factory=psycopg2.extras.RealDictCursor)
logotron_genesis.kv 104 if (DB_DEBUG): logging.debug("query: '{0}'".format(query))
logotron_genesis.kv 105 cur.execute(query, args)
logotron_genesis.kv 106 rv = cur.fetchone() if one else cur.fetchall()
logotron_genesis.kv 107 if (DB_DEBUG): logging.debug("query res: '{0}'".format(rv))
logotron_genesis.kv 108 return rv
logotron_genesis.kv 109
logotron_genesis.kv 110 def rollback_db():
logotron_genesis.kv 111 cur = db.cursor(cursor_factory=psycopg2.extras.RealDictCursor)
logotron_genesis.kv 112 cur.execute("ROLLBACK")
logotron_genesis.kv 113 db.commit()
logotron_genesis.kv 114
logotron_genesis.kv 115 def commit_db():
logotron_genesis.kv 116 cur = db.cursor(cursor_factory=psycopg2.extras.RealDictCursor)
logotron_genesis.kv 117 db.commit()
logotron_genesis.kv 118
logotron_genesis.kv 119
logotron_genesis.kv 120 ##############################################################################
logotron_genesis.kv 121 # IRCism
logotron_genesis.kv 122 ##############################################################################
logotron_genesis.kv 123
logotron_genesis.kv 124 # Used to compute 'uptime'
logotron_genesis.kv 125 time_last_conn = datetime.now()
logotron_genesis.kv 126
logotron_genesis.kv 127 # Init socket:
logotron_genesis.kv 128 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
logotron_genesis.kv 129
logotron_genesis.kv 130 # Set keepalive:
logotron_genesis.kv 131 sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
logotron_genesis.kv 132
logotron_genesis.kv 133 # Initially we are not connected to anything
logotron_genesis.kv 134 connected = False
logotron_genesis.kv 135
logotron_genesis.kv 136 # Connect to given host:port; return whether connected
logotron_genesis.kv 137 def connect(host, port):
logotron_genesis.kv 138 logging.info("Connecting to %s:%s" % (host, port))
logotron_genesis.kv 139 sock.settimeout(Timeout)
logotron_genesis.kv 140 try:
logotron_genesis.kv 141 sock.connect((host, port))
logotron_genesis.kv 142 except (socket.timeout, socket.error) as e:
logotron_genesis.kv 143 logging.warning(e)
logotron_genesis.kv 144 return False
logotron_genesis.kv 145 except Exception as e:
logotron_genesis.kv 146 logging.exception(e)
logotron_genesis.kv 147 return False
logotron_genesis.kv 148 else:
logotron_genesis.kv 149 logging.info("Connected.")
logotron_genesis.kv 150 return True
logotron_genesis.kv 151
logotron_genesis.kv 152
logotron_genesis.kv 153 # Attempt connect to each of hosts, in order, on port; return whether connected
logotron_genesis.kv 154 def connect_any(hosts, port):
logotron_genesis.kv 155 for host in hosts:
logotron_genesis.kv 156 if connect(host, port):
logotron_genesis.kv 157 return True
logotron_genesis.kv 158 return False
logotron_genesis.kv 159
logotron_genesis.kv 160
logotron_genesis.kv 161 # Transmit IRC message
logotron_genesis.kv 162 def send(message):
logotron_genesis.kv 163 global connected
logotron_genesis.kv 164 if not connected:
logotron_genesis.kv 165 logging.warning("Tried to send while disconnected?")
logotron_genesis.kv 166 return False
logotron_genesis.kv 167 time.sleep(TX_Delay)
logotron_genesis.kv 168 logging.debug("> '%s'" % message)
logotron_genesis.kv 169 message = "%s\r\n" % message
logotron_genesis.kv 170 try:
logotron_genesis.kv 171 sock.send(message.encode("utf-8"))
logotron_genesis.kv 172 except (socket.timeout, socket.error) as e:
logotron_genesis.kv 173 logging.warning("Socket could not send! Disconnecting.")
logotron_genesis.kv 174 connected = False
logotron_genesis.kv 175 return False
logotron_genesis.kv 176 except Exception as e:
logotron_genesis.kv 177 logging.exception(e)
logotron_genesis.kv 178 return False
logotron_genesis.kv 179
logotron_genesis.kv 180
logotron_genesis.kv 181 # Speak given message on a selected channel
logotron_genesis.kv 182 def speak(channel, message):
logotron_genesis.kv 183 send("PRIVMSG #%s :%s" % (channel, message))
logotron_genesis.kv 184 # Now save what the bot spoke:
logotron_genesis.kv 185 save_line(datetime.now(), channel, Nick, False, message)
logotron_genesis.kv 186
logotron_genesis.kv 187
logotron_genesis.kv 188 # Standard incoming IRC line (excludes fleanode liquishit, etc)
logotron_genesis.kv 189 irc_line_re = re.compile("""^:([^!]+)\!\S+\s+PRIVMSG\s+\#(\S+)\s+\:(.*)""")
logotron_genesis.kv 190
logotron_genesis.kv 191 # The '#' prevents interaction via PM, this is not a PM-able bot.
logotron_genesis.kv 192
logotron_genesis.kv 193 # 'Actions'
logotron_genesis.kv 194 irc_act_re = re.compile(""".*ACTION\s+(.*)""")
logotron_genesis.kv 195
logotron_genesis.kv 196
logotron_genesis.kv 197 # A line was received from IRC
logotron_genesis.kv 198 def received_line(line):
logotron_genesis.kv 199 # Process the traditional pingpong
logotron_genesis.kv 200 if line.startswith("PING"):
logotron_genesis.kv 201 send("PONG " + line.split()[1])
logotron_genesis.kv 202 else:
logotron_genesis.kv 203 logging.debug("< '%s'" % line)
logotron_genesis.kv 204 standard_line = re.search(irc_line_re, line)
logotron_genesis.kv 205 if standard_line:
logotron_genesis.kv 206 # Break this line into the standard segments
logotron_genesis.kv 207 (user, chan, text) = [s.strip() for s in standard_line.groups()]
logotron_genesis.kv 208 # Determine whether this line is an 'action' :
logotron_genesis.kv 209 action = False
logotron_genesis.kv 210 act = re.search(irc_act_re, line)
logotron_genesis.kv 211 if act:
logotron_genesis.kv 212 action = True
logotron_genesis.kv 213 text = act.group(1)
logotron_genesis.kv 214 # This line is edible, process it.
logotron_genesis.kv 215 eat_logline(user, chan, text, action)
logotron_genesis.kv 216
logotron_genesis.kv 217
logotron_genesis.kv 218 # IRCate until we get disconnected
logotron_genesis.kv 219 def irc():
logotron_genesis.kv 220 global connected
uptimefix_bye_cac... 221 global time_last_conn
logotron_genesis.kv 222
logotron_genesis.kv 223 # Connect to one among the specified servers, in given priority :
logotron_genesis.kv 224 while not connected:
logotron_genesis.kv 225 connected = connect_any(Servers, Port)
logotron_genesis.kv 226
logotron_genesis.kv 227 # Save time of last successful connect
logotron_genesis.kv 228 time_last_conn = datetime.now()
logotron_genesis.kv 229
logotron_genesis.kv 230 # Auth to server
logotron_genesis.kv 231 send("NICK %s\r\n" % Nick)
logotron_genesis.kv 232 send("USER %s %s %s :%s\r\n" % (Nick, Nick, Nick, Nick))
uniturds_etc.kv 233
uniturds_etc.kv 234 # If this is a production bot, rather than test, there will be a PW:
uniturds_etc.kv 235 if Pass != "":
uniturds_etc.kv 236 send("NICKSERV IDENTIFY %s %s\r\n" % (Nick, Pass))
logotron_genesis.kv 237
logotron_genesis.kv 238 time.sleep(Join_Delay) # wait to join until fleanode eats auth
logotron_genesis.kv 239
logotron_genesis.kv 240 # Join selected channels
logotron_genesis.kv 241 for chan in Channels:
logotron_genesis.kv 242 logging.info("Joining channel '%s'..." % chan)
logotron_genesis.kv 243 send("JOIN #%s\r\n" % chan)
logotron_genesis.kv 244
logotron_genesis.kv 245 while connected:
logotron_genesis.kv 246 try:
logotron_genesis.kv 247 data = sock.recv(Buf_Size)
logotron_genesis.kv 248 except socket.timeout as e:
logotron_genesis.kv 249 logging.debug("Listen timed out")
logotron_genesis.kv 250 continue
logotron_genesis.kv 251 except socket.error as e:
logotron_genesis.kv 252 logging.warning("Listen socket error, disconnecting.")
logotron_genesis.kv 253 connected = False
logotron_genesis.kv 254 continue
logotron_genesis.kv 255 except Exception as e:
logotron_genesis.kv 256 logging.exception(e)
logotron_genesis.kv 257 connected = False
logotron_genesis.kv 258 continue
logotron_genesis.kv 259 else:
logotron_genesis.kv 260 if len(data) == 0:
logotron_genesis.kv 261 logging.warning("Listen socket closed, disconnecting.")
logotron_genesis.kv 262 connected = False
logotron_genesis.kv 263 continue
logotron_genesis.kv 264 try:
uniturds_etc.kv 265 try:
uniturds_etc.kv 266 data = data.strip(b'\r\n').decode("utf-8")
uniturds_etc.kv 267 except UnicodeDecodeError:
uniturds_etc.kv 268 data = data.strip(b'\r\n').decode('latin-1')
logotron_genesis.kv 269 for l in data.splitlines():
logotron_genesis.kv 270 received_line(l)
logotron_genesis.kv 271 continue
logotron_genesis.kv 272 except Exception as e:
logotron_genesis.kv 273 logging.exception(e)
logotron_genesis.kv 274 continue
logotron_genesis.kv 275
logotron_genesis.kv 276 ##############################################################################
logotron_genesis.kv 277
logotron_genesis.kv 278 html_escape_table = {
logotron_genesis.kv 279 "&": "&amp;",
logotron_genesis.kv 280 '"': "&quot;",
logotron_genesis.kv 281 "'": "&apos;",
logotron_genesis.kv 282 ">": "&gt;",
logotron_genesis.kv 283 "<": "&lt;",
logotron_genesis.kv 284 }
logotron_genesis.kv 285
logotron_genesis.kv 286 def html_escape(text):
logotron_genesis.kv 287 res = ("".join(html_escape_table.get(c,c) for c in text))
logotron_genesis.kv 288 return urllib.quote(res.encode('utf-8'))
logotron_genesis.kv 289
logotron_genesis.kv 290
logotron_genesis.kv 291 searcher_re = re.compile("""(\d+) Results""")
logotron_genesis.kv 292
logotron_genesis.kv 293 # Retrieve a search result count using the WWWistic frontend.
logotron_genesis.kv 294 # This way it is not necessary to have query parser in two places.
logotron_genesis.kv 295 # However it is slightly wasteful of CPU (requires actually loading results.)
logotron_genesis.kv 296 def get_search_res(chan, query):
logotron_genesis.kv 297 try:
logotron_genesis.kv 298 esc_q = html_escape(query)
logotron_genesis.kv 299 url = Base_URL + "log-search?q=" + esc_q + "&chan=" + chan
logotron_genesis.kv 300 res = requests.get(url).text
logotron_genesis.kv 301 t = res[res.find('<title>') + 7 : res.find('</title>')].strip()
logotron_genesis.kv 302 found = searcher_re.match(t)
logotron_genesis.kv 303 if found:
logotron_genesis.kv 304 output = "[" + url + "]" + "[" + found.group(1)
logotron_genesis.kv 305 output += """ results for "%s" in #%s]""" % (query, chan)
logotron_genesis.kv 306 return output
logotron_genesis.kv 307 else:
logotron_genesis.kv 308 return """No results found for "%s" in #%s""" % (query, chan)
logotron_genesis.kv 309 except Exception as e:
logotron_genesis.kv 310 logging.exception(e)
logotron_genesis.kv 311 return "No results returned (is logotron WWW up ?)"
logotron_genesis.kv 312
logotron_genesis.kv 313 ##############################################################################
logotron_genesis.kv 314
logotron_genesis.kv 315 # Commands:
logotron_genesis.kv 316
logotron_genesis.kv 317 def cmd_help(arg, user, chan):
logotron_genesis.kv 318 # Speak the 'help' text
logotron_genesis.kv 319 speak(chan, "%s: my valid commands are: %s" %
logotron_genesis.kv 320 (user, ', '.join(Commands.keys())));
logotron_genesis.kv 321
logotron_genesis.kv 322 def cmd_search(arg, user, chan):
logotron_genesis.kv 323 logging.debug("search: '%s'" % arg)
logotron_genesis.kv 324 speak(chan, get_search_res(chan, arg))
logotron_genesis.kv 325
logotron_genesis.kv 326 def cmd_seen(arg, user, chan):
logotron_genesis.kv 327 speak(chan, "%s: this command is not yet implemented." % user);
logotron_genesis.kv 328
logotron_genesis.kv 329 def cmd_src(arg, user, chan):
logotron_genesis.kv 330 speak(chan, "%s: my source code can be seen at: %s" % (user, Src_URL));
logotron_genesis.kv 331
logotron_genesis.kv 332 def cmd_uptime(arg, user, chan):
logotron_genesis.kv 333 uptime_txt = ""
logotron_genesis.kv 334 uptime = (datetime.now() - time_last_conn)
logotron_genesis.kv 335 days = uptime.days
logotron_genesis.kv 336 hours = uptime.seconds/3600
logotron_genesis.kv 337 minutes = (uptime.seconds%3600)/60
logotron_genesis.kv 338 uptime_txt += '%dd ' % days
logotron_genesis.kv 339 uptime_txt += '%dh ' % hours
logotron_genesis.kv 340 uptime_txt += '%dm' % minutes
logotron_genesis.kv 341 # Speak the uptime
logotron_genesis.kv 342 speak(chan, "%s: time since my last reconnect : %s" %
logotron_genesis.kv 343 (user, uptime_txt));
logotron_genesis.kv 344
logotron_genesis.kv 345 Commands = {
logotron_genesis.kv 346 "help" : cmd_help,
logotron_genesis.kv 347 "s" : cmd_search,
logotron_genesis.kv 348 "seen" : cmd_seen,
logotron_genesis.kv 349 "uptime" : cmd_uptime,
logotron_genesis.kv 350 "src" : cmd_src
logotron_genesis.kv 351 }
logotron_genesis.kv 352
logotron_genesis.kv 353 ##############################################################################
logotron_genesis.kv 354
logotron_genesis.kv 355 # Save given line to perma-log
logotron_genesis.kv 356 def save_line(time, chan, speaker, action, payload):
logotron_genesis.kv 357 ## Put in DB:
logotron_genesis.kv 358 try:
logotron_genesis.kv 359 # Get index of THIS new line to be saved
logotron_genesis.kv 360 last_idx = query_db(
logotron_genesis.kv 361 '''select idx from loglines where chan=%s
logotron_genesis.kv 362 and idx = (select max(idx) from loglines where chan=%s) ;''',
logotron_genesis.kv 363 [chan, chan], one=True)
logotron_genesis.kv 364
logotron_genesis.kv 365 # Was this chan unseen previously?
logotron_genesis.kv 366 if last_idx == None:
logotron_genesis.kv 367 cur_idx = NewChan_Idx # Then use the config'd start index
logotron_genesis.kv 368 else:
logotron_genesis.kv 369 cur_idx = last_idx['idx'] + 1 # Otherwise, get the next idx
logotron_genesis.kv 370
logotron_genesis.kv 371 logging.debug("Adding log line with index: %s" % cur_idx)
logotron_genesis.kv 372
logotron_genesis.kv 373 # Set up the insert
logotron_genesis.kv 374 exec_db('''insert into loglines (idx, t, chan, era,
logotron_genesis.kv 375 speaker, self, payload) values (%s, %s, %s, %s, %s, %s, %s) ; ''',
logotron_genesis.kv 376 [cur_idx, time, chan, Era, speaker, action, payload])
logotron_genesis.kv 377
logotron_genesis.kv 378 # Fire
logotron_genesis.kv 379 commit_db()
logotron_genesis.kv 380 except Exception as e:
logotron_genesis.kv 381 rollback_db()
logotron_genesis.kv 382 logging.warning("DB add failed, rolled back.")
logotron_genesis.kv 383 logging.exception(e)
logotron_genesis.kv 384
logotron_genesis.kv 385
logotron_genesis.kv 386 # RE for finding log refs
logotron_genesis.kv 387 logref_re = re.compile(Base_URL + """log\/([^/]+)/([^/]+)#(\d+)""")
logotron_genesis.kv 388
logotron_genesis.kv 389
logotron_genesis.kv 390 # All valid received lines end up here
logotron_genesis.kv 391 def eat_logline(user, chan, text, action):
logotron_genesis.kv 392 # If somehow received line from channel which isn't in the set:
logotron_genesis.kv 393 if chan not in Channels:
logotron_genesis.kv 394 logging.warning(
logotron_genesis.kv 395 "Received martian : '%s' : '%s'" % (chan, text))
logotron_genesis.kv 396 return
logotron_genesis.kv 397
logotron_genesis.kv 398 # First, add the line to the log:
logotron_genesis.kv 399 save_line(datetime.now(), chan, user, action, text)
logotron_genesis.kv 400
logotron_genesis.kv 401 # Then, see if the line was a command for this bot:
logotron_genesis.kv 402 if text.startswith(Prefix):
logotron_genesis.kv 403 cmd = text.partition(Prefix)[2].strip()
logotron_genesis.kv 404 cmd = [x.strip() for x in cmd.split(' ', 1)]
logotron_genesis.kv 405 if len(cmd) == 1:
logotron_genesis.kv 406 arg = ""
logotron_genesis.kv 407 else:
logotron_genesis.kv 408 arg = cmd[1]
logotron_genesis.kv 409 # Dispatch this command...
logotron_genesis.kv 410 command = cmd[0]
logotron_genesis.kv 411 logging.debug("Dispatching command '%s' with arg '%s'.." %
logotron_genesis.kv 412 (command, arg))
logotron_genesis.kv 413 func = Commands.get(command)
logotron_genesis.kv 414 # If this command is undefined:
logotron_genesis.kv 415 if func == None:
logotron_genesis.kv 416 logging.debug("Invalid command: %s" % command)
logotron_genesis.kv 417 # Utter the 'help' text as response to the sad command
logotron_genesis.kv 418 cmd_help("", user, chan)
logotron_genesis.kv 419 else:
logotron_genesis.kv 420 # Is defined command, dispatch it:
logotron_genesis.kv 421 func(arg, user, chan)
logotron_genesis.kv 422 else:
logotron_genesis.kv 423 # Finally, see if contains log refs:
logotron_genesis.kv 424 for ref in re.findall(logref_re, text):
logotron_genesis.kv 425 ref_chan, ref_date, ref_idx = ref
logotron_genesis.kv 426 # Find this line in DB:
logotron_genesis.kv 427 ref_line = query_db(
logotron_genesis.kv 428 '''select t, speaker, payload from loglines
logotron_genesis.kv 429 where chan=%s and idx=%s;''',
logotron_genesis.kv 430 [ref_chan, ref_idx], one=True)
logotron_genesis.kv 431 # If retrieved line is valid, echo it:
logotron_genesis.kv 432 if ref_line != None:
logotron_genesis.kv 433 time_txt = ref_line['t'].strftime(Date_Long_Format)
logotron_genesis.kv 434 my_line = "Logged on %s %s: %s" % (time_txt,
logotron_genesis.kv 435 ref_line['speaker'],
logotron_genesis.kv 436 ref_line['payload'])
logotron_genesis.kv 437 # Speak the line echo into the chan where ref was seen
logotron_genesis.kv 438 speak(chan, my_line)
logotron_genesis.kv 439
logotron_genesis.kv 440 ##############################################################################
logotron_genesis.kv 441
logotron_genesis.kv 442 # IRCate; if disconnected, reconnect
logotron_genesis.kv 443 def run():
logotron_genesis.kv 444 while 1:
logotron_genesis.kv 445 irc()
logotron_genesis.kv 446 logging.warning("Disconnected, will reconnect...")
logotron_genesis.kv 447
logotron_genesis.kv 448 ##############################################################################
logotron_genesis.kv 449
logotron_genesis.kv 450 # Run continuously.
logotron_genesis.kv 451 run()
logotron_genesis.kv 452
logotron_genesis.kv 453 ##############################################################################