def disconnect(): """Part from IRC channel and disconnect from host""" try: B.write('DISCONNECT\r\n') B.close() except: e = traceback.format_exc() debug(e, log_only=True)
def title_echo(r, line, bot, chan): """Echo the title of a url via MC""" def write_url(title, url): """Write a URL to the database""" conn = sqlite3.connect(DB_FILE) c = conn.cursor() t = (title, url) c.execute('INSERT INTO url_history VALUES (?, ?)', t) conn.commit() conn.close() # get url and build opener with custom user-agent and cookies enabled url = r.group(5).split()[0] cookie_jar = http.cookiejar.CookieJar() opener = urllib.request.build_opener( urllib.request.HTTPCookieProcessor(cookie_jar)) opener.addheaders = [('User-agent', USER_AGENT)] # open the url but only read a maximum of 2**20 bytes in case someone is # screwing with us try: f = opener.open(str(url)) html = f.read(1048576) # only read the first 2**20 bytes except: e = traceback.format_exc() debug(e, log_only=True) write_url(None, url) return # uncompress if the data is gzipped try: encoding = f.info()['content-encoding'] except KeyError: encoding = None if encoding and encoding == 'gzip': html = io.BytesIO(html) gz = gzip.GzipFile(fileobj=html, mode='rb') html = gz.read() gz.close f.close() # decode the html and search for the title element html = html.decode('utf-8', errors='replace') title = re.search(r'<title.*?>(.*?)</title>', html, re.DOTALL | re.IGNORECASE) if title: title = title.group(1).strip() title = title.replace('\n', '').replace('\r', '') title = ' '.join([w for w in title.split(' ') if w != '']) title = htmlp.HTMLParser().unescape(title) else: write_url(None, url) return # if we are here then there's a title so echo it to the channel bot.write('PRIVMSG {chan} :Title: {msg}\r\n'.format(chan=chan, msg=title)) write_url(title, url)
def title_echo(r, line, bot, chan): """Echo the title of a url via MC""" def write_url(title, url): """Write a URL to the database""" conn = sqlite3.connect(DB_FILE) c = conn.cursor() t = (title, url) c.execute("INSERT INTO url_history VALUES (?, ?)", t) conn.commit() conn.close() # get url and build opener with custom user-agent and cookies enabled url = r.group(5).split()[0] cookie_jar = http.cookiejar.CookieJar() opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(cookie_jar)) opener.addheaders = [("User-agent", USER_AGENT)] # open the url but only read a maximum of 2**20 bytes in case someone is # screwing with us try: f = opener.open(str(url)) html = f.read(1048576) # only read the first 2**20 bytes except: e = traceback.format_exc() debug(e, log_only=True) write_url(None, url) return # uncompress if the data is gzipped try: encoding = f.info()["content-encoding"] except KeyError: encoding = None if encoding and encoding == "gzip": html = io.BytesIO(html) gz = gzip.GzipFile(fileobj=html, mode="rb") html = gz.read() gz.close f.close() # decode the html and search for the title element html = html.decode("utf-8", errors="replace") title = re.search(r"<title.*?>(.*?)</title>", html, re.DOTALL | re.IGNORECASE) if title: title = title.group(1).strip() title = title.replace("\n", "").replace("\r", "") title = " ".join([w for w in title.split(" ") if w != ""]) title = htmlp.HTMLParser().unescape(title) else: write_url(None, url) return # if we are here then there's a title so echo it to the channel bot.write("PRIVMSG {chan} :Title: {msg}\r\n".format(chan=chan, msg=title)) write_url(title, url)
def pinger(host): """Ping the IRC server at the given interval until a keyboard interrupt""" # multiprocessing not threading. while True: try: time.sleep(PING_INTERVAL) B.write('PING {}\r\n'.format(host)) except KeyboardInterrupt: break except: e = traceback.format_exc() debug(e) break
def connect(host, port, chan): """Connect to IRC host, on port, and join chan""" debug('Connecting to server {}:{} and joining {}'.format(host, port, chan)) global B global IRC_PARSER global CUST_PARSER B = Bot(host, int(port), debug=DEBUG) IRC_PARSER = Parser(B, chan, IRC_DEFINITIONS) CUST_PARSER = Parser(B, chan, CUST_DEFINITIONS) B.write('NICK {}\r\n'.format(USERNAME)) B.write('USER {} {} {} :{}\r\n'.format(USERNAME, HOSTNAME, SERVERNAME, REALNAME)) # TODO: Figure out a safe solution for this time.sleep(3) B.write('JOIN {}\r\n'.format(chan))
def recover(args): """Recover from a fatal error""" retry = RETRY_INTERVAL while True: try: disconnect() time.sleep(retry) connect(*args) Process(target=pinger, args=(SERVER, )).start() break except KeyboardInterrupt: break except: e = traceback.format_exc() debug(e) retry *= 2
def recover(args): """Recover from a fatal error""" retry = RETRY_INTERVAL while True: try: disconnect() time.sleep(retry) connect(*args) Process(target=pinger, args=(SERVER,)).start() break except KeyboardInterrupt: break except: e = traceback.format_exc() debug(e) retry *= 2
def connect(host, port, chan): """Connect to IRC host, on port, and join chan""" debug('Connecting to server {}:{} and joining {}'.format( host, port, chan)) global B global IRC_PARSER global CUST_PARSER B = Bot(host, int(port), debug=DEBUG) IRC_PARSER = Parser(B, chan, IRC_DEFINITIONS) CUST_PARSER = Parser(B, chan, CUST_DEFINITIONS) B.write('NICK {}\r\n'.format(USERNAME)) B.write('USER {} {} {} :{}\r\n'.format( USERNAME, HOSTNAME, SERVERNAME, REALNAME)) # TODO: Figure out a safe solution for this time.sleep(3) B.write('JOIN {}\r\n'.format(chan))
Process(target=irc_parse, args=(line, )).start() Process(target=cust_parse, args=(line, )).start() if __name__ == '__main__': # Connect to the server argc = len(sys.argv) args = None if argc == 4: args = (sys.argv[1], sys.argv[2], sys.argv[3]) elif argc == 3: args = (sys.argv[1], sys.argv[2], CHANNEL) elif argc == 2: if sys.argv[1] in ('-help', '--help'): debug('Usage:\n\n$ botbot\n$ botbot <host>\n$ botbot <host>' + ' <port>\n$ botbot <host> <port> <channel>', prefix=False) sys.exit(1) else: args = (sys.argv[1], PORT, CHANNEL) elif argc == 1: args = (SERVER, PORT, CHANNEL) connect(*args) debug('welcome') # Create a process to ping the server every so often. This allows us to # stay connected to the server even if the socket receives no pings. This # arises if the client side network is cleaning up tcp connections before # the server can ping the client. Process(target=pinger, args=(SERVER, )).start()
for line in lines: Process(target=irc_parse, args=(line,)).start() Process(target=cust_parse, args=(line,)).start() if __name__ == '__main__': # Connect to the server argc = len(sys.argv) args = None if argc == 4: args = (sys.argv[1], sys.argv[2], sys.argv[3]) elif argc == 3: args = (sys.argv[1], sys.argv[2], CHANNEL) elif argc == 2: if sys.argv[1] in ('-help', '--help'): debug('Usage:\n\n$ botbot\n$ botbot <host>\n$ botbot <host>' + ' <port>\n$ botbot <host> <port> <channel>', prefix=False) sys.exit(1) else: args = (sys.argv[1], PORT, CHANNEL) elif argc == 1: args = (SERVER, PORT, CHANNEL) connect(*args) debug('welcome') # Create a process to ping the server every so often. This allows us to # stay connected to the server even if the socket receives no pings. This # arises if the client side network is cleaning up tcp connections before # the server can ping the client. Process(target=pinger, args=(SERVER,)).start() # Loop until keyboard interrupt