Make some stuff nicer

This commit is contained in:
dave 2016-11-06 23:00:15 +00:00
parent 0d3fbfc91c
commit 19b7a95d76
10 changed files with 206 additions and 203 deletions

View File

@ -1,29 +1,30 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import os
import sys import sys
import logging import logging
from optparse import OptionParser from argparse import ArgumentParser
from pyircbot import PyIRCBot from pyircbot import PyIRCBot
from time import sleep
if __name__ == "__main__": if __name__ == "__main__":
" logging level and facility " " logging level and facility "
logging.basicConfig(level=logging.DEBUG, format="%(asctime)-15s %(levelname)-8s %(filename)s:%(lineno)d %(message)s") logging.basicConfig(level=logging.INFO, format="%(asctime)-15s %(levelname)-8s %(filename)s:%(lineno)d %(message)s")
log = logging.getLogger('main') log = logging.getLogger('main')
" parse command line args " " parse command line args "
parser = OptionParser() parser = ArgumentParser(description="Run pyircbot")
parser.add_option("-c", "--config", action="store", type="string", dest="config", help="Path to config file") parser.add_argument("-c", "--config", help="Path to config file", required=True)
parser.add_argument("--debug", action="store_true", help="Dump raw irc network")
(options, args) = parser.parse_args() args = parser.parse_args()
log.debug(options) if args.debug:
logging.getLogger().setLevel(logging.DEBUG)
log.debug(args)
if not options.config: if not args.config:
log.critical("No bot config file specified (-c). Exiting.") log.critical("No bot config file specified (-c). Exiting.")
sys.exit(0) sys.exit(0)
botconfig = PyIRCBot.load(options.config) botconfig = PyIRCBot.load(args.config)
log.debug(botconfig) log.debug(botconfig)

View File

@ -17,12 +17,18 @@ from inspect import getargspec
from socket import SHUT_RDWR from socket import SHUT_RDWR
from threading import Thread from threading import Thread
from time import sleep, time from time import sleep, time
from collections import namedtuple
try: try:
from cStringIO import StringIO from cStringIO import StringIO
except: except:
from io import BytesIO as StringIO from io import BytesIO as StringIO
IRCEvent = namedtuple("IRCEvent", "args prefix trailing")
UserPrefix = namedtuple("UserPrefix", "nick username hostname")
ServerPrefix = namedtuple("ServerPrefix", "hostname")
class IRCCore(asynchat.async_chat): class IRCCore(asynchat.async_chat):
def __init__(self): def __init__(self):
@ -120,7 +126,7 @@ class IRCCore(asynchat.async_chat):
:param data: the data that was recieved :param data: the data that was recieved
:type data: str""" :type data: str"""
#self.log.debug("<< %(message)s", {"message":repr(data)}) #self.log.info("<< %(message)s", {"message":repr(data)})
self.buffer.write(data) self.buffer.write(data)
def found_terminator(self): def found_terminator(self):
@ -135,11 +141,12 @@ class IRCCore(asynchat.async_chat):
self.log.error("found_terminator(): repr(data): %s" % repr(line)) self.log.error("found_terminator(): repr(data): %s" % repr(line))
self.log.error("found_terminator(): error: %s" % str(ude)) self.log.error("found_terminator(): error: %s" % str(ude))
return return
self.log.debug("< {}".format(line))
self.process_data(line) self.process_data(line)
def handle_close(self): def handle_close(self):
"""Called when the socket is disconnected. Triggers the _DISCONNECT hook""" """Called when the socket is disconnected. Triggers the _DISCONNECT hook"""
self.log.debug("handle_close") self.log.info("handle_close")
self.connected=False self.connected=False
self.close() self.close()
self.fire_hook("_DISCONNECT") self.fire_hook("_DISCONNECT")
@ -157,16 +164,16 @@ class IRCCore(asynchat.async_chat):
if self.server >= len(self.servers): if self.server >= len(self.servers):
self.server=0 self.server=0
serverHostname = self.servers[self.server] serverHostname = self.servers[self.server]
self.log.debug("Connecting to %(server)s:%(port)i", {"server":serverHostname, "port":self.port}) self.log.info("Connecting to %(server)s:%(port)i", {"server":serverHostname, "port":self.port})
socket_type = socket.AF_INET socket_type = socket.AF_INET
if self.ipv6: if self.ipv6:
self.log.info("IPv6 is enabled.") self.log.info("IPv6 is enabled.")
socket_type = socket.AF_INET6 socket_type = socket.AF_INET6
socketInfo = socket.getaddrinfo(serverHostname, self.port, socket_type) socketInfo = socket.getaddrinfo(serverHostname, self.port, socket_type)
self.create_socket(socket_type, socket.SOCK_STREAM) self.create_socket(socket_type, socket.SOCK_STREAM)
self.log.debug("Socket created: %s" % self.socket.fileno()) self.log.info("Socket created: %s" % self.socket.fileno())
self.connect(socketInfo[0][4]) self.connect(socketInfo[0][4])
self.log.debug("Connection established") self.log.info("Connection established")
self._fileno = self.socket.fileno() self._fileno = self.socket.fileno()
self.asynmap[self._fileno] = self # http://willpython.blogspot.com/2010/08/multiple-event-loops-with-asyncore-and.html self.asynmap[self._fileno] = self # http://willpython.blogspot.com/2010/08/multiple-event-loops-with-asyncore-and.html
self.log.info("_connect: Socket map: %s" % str(self.asynmap)) self.log.info("_connect: Socket map: %s" % str(self.asynmap))
@ -174,9 +181,9 @@ class IRCCore(asynchat.async_chat):
def handle_connect(self): def handle_connect(self):
"""When asynchat indicates our socket is connected, fire the _CONNECT hook""" """When asynchat indicates our socket is connected, fire the _CONNECT hook"""
self.connected=True self.connected=True
self.log.debug("handle_connect: connected") self.log.info("handle_connect: connected")
self.fire_hook("_CONNECT") self.fire_hook("_CONNECT")
self.log.debug("handle_connect: complete") self.log.info("handle_connect: complete")
def sendRaw(self, text, prio=2): def sendRaw(self, text, prio=2):
"""Queue messages (raw string) to be sent to the IRC server """Queue messages (raw string) to be sent to the IRC server
@ -325,11 +332,9 @@ class IRCCore(asynchat.async_chat):
:type trailing: str :type trailing: str
:returns: object -- a IRCEvent object with the ``args``, ``prefix``, ``trailing``""" :returns: object -- a IRCEvent object with the ``args``, ``prefix``, ``trailing``"""
return type('IRCEvent', (object,), { return IRCEvent(args,
"args": args, IRCCore.decodePrefix(prefix) if prefix else None,
"prefix": IRCCore.decodePrefix(prefix) if prefix else None, trailing)
"trailing": trailing
})
" Utility methods " " Utility methods "
@staticmethod @staticmethod
@ -340,16 +345,11 @@ class IRCCore(asynchat.async_chat):
:type prefix: str :type prefix: str
:returns: object -- an UserPrefix object with the properties `nick`, `username`, `hostname` or a ServerPrefix object with the property `hostname`""" :returns: object -- an UserPrefix object with the properties `nick`, `username`, `hostname` or a ServerPrefix object with the property `hostname`"""
if "!" in prefix: if "!" in prefix:
ob = type('UserPrefix', (object,), {}) nick, prefix = prefix.split("!")
ob.str = prefix username, hostname = prefix.split("@")
ob.nick, prefix = prefix.split("!") return UserPrefix(nick, username, hostname)
ob.username, ob.hostname = prefix.split("@")
return ob
else: else:
ob = type('ServerPrefix', (object,), {}) return ServerPrefix(prefix)
ob.str = prefix
ob.hostname = prefix
return ob
@staticmethod @staticmethod
def trace(): def trace():
@ -488,15 +488,16 @@ class OutputQueueRunner(Thread):
self.process_queue_item() self.process_queue_item()
lastSend = time() lastSend = time()
except queue.Empty: except queue.Empty:
#self.log.debug("Queue is empty") #self.log.info("Queue is empty")
pass pass
sleep(0.01) sleep(0.01)
def process_queue_item(self): def process_queue_item(self):
"""Remove 1 item from queue and process it""" """Remove 1 item from queue and process it"""
prio,text = self.bot.outputQueue.get(block=True, timeout=10) prio,text = self.bot.outputQueue.get(block=True, timeout=10)
#self.log.debug("%s>> %s" % (prio,text)) #self.log.info("%s>> %s" % (prio,text))
self.bot.outputQueue.task_done() self.bot.outputQueue.task_done()
self.log.debug("> {}".format(text.decode('UTF-8')))
self.bot.send(text) self.bot.send(text)
def clear(self): def clear(self):
@ -507,7 +508,7 @@ class OutputQueueRunner(Thread):
self.bot.outputQueue.get(block=False) self.bot.outputQueue.get(block=False)
except queue.Empty: except queue.Empty:
pass pass
#self.log.debug("output queue cleared") #self.log.info("output queue cleared")
return length return length
def flush(self): def flush(self):
@ -517,4 +518,4 @@ class OutputQueueRunner(Thread):
self.process_queue_item() self.process_queue_item()
except: except:
pass pass
#self.log.debug("output queue flushed") #self.log.info("output queue flushed")

View File

@ -166,9 +166,9 @@ class AttributeStorage(ModuleBase):
if value == None: if value == None:
# delete it # delete it
c = self.db.connection.query("DELETE FROM `values` WHERE `itemid`=%s AND `attributeid`=%s ;", (itemId, attributeId)) c = self.db.connection.query("DELETE FROM `values` WHERE `itemid`=%s AND `attributeid`=%s ;", (itemId, attributeId))
self.log.debug("AttributeStorage: Stored item %s attribute %s value: %s (Deleted)" % (itemId, attributeId, value)) self.log.info("AttributeStorage: Stored item %s attribute %s value: %s (Deleted)" % (itemId, attributeId, value))
else: else:
# add attribute # add attribute
c = self.db.connection.query("REPLACE INTO `values` (`itemid`, `attributeid`, `value`) VALUES (%s, %s, %s);", (itemId, attributeId, value)) c = self.db.connection.query("REPLACE INTO `values` (`itemid`, `attributeid`, `value`) VALUES (%s, %s, %s);", (itemId, attributeId, value))
self.log.debug("AttributeStorage: Stored item %s attribute %s value: %s" % (itemId, attributeId, value)) self.log.info("AttributeStorage: Stored item %s attribute %s value: %s" % (itemId, attributeId, value))
c.close() c.close()

View File

@ -161,9 +161,9 @@ class AttributeStorageLite(ModuleBase):
if value == None: if value == None:
# delete it # delete it
c = self.db.query("DELETE FROM `values` WHERE `itemid`=? AND `attributeid`=? ;", (itemId, attributeId)) c = self.db.query("DELETE FROM `values` WHERE `itemid`=? AND `attributeid`=? ;", (itemId, attributeId))
self.log.debug("Stored item %s attribute %s value: %s (Deleted)" % (itemId, attributeId, value)) self.log.info("Stored item %s attribute %s value: %s (Deleted)" % (itemId, attributeId, value))
else: else:
# add attribute # add attribute
c = self.db.query("REPLACE INTO `values` (`itemid`, `attributeid`, `value`) VALUES (?, ?, ?);", (itemId, attributeId, value)) c = self.db.query("REPLACE INTO `values` (`itemid`, `attributeid`, `value`) VALUES (?, ?, ?);", (itemId, attributeId, value))
self.log.debug("Stored item %s attribute %s value: %s" % (itemId, attributeId, value)) self.log.info("Stored item %s attribute %s value: %s" % (itemId, attributeId, value))
c.close() c.close()

View File

@ -121,13 +121,13 @@ class BitcoinRPC:
def connect(self): def connect(self):
# internal. connect to the service # internal. connect to the service
self.log.debug("CryptoWalletRPC: %s: Connecting to %s:%s" % (self.name, self.host,self.port)) self.log.info("CryptoWalletRPC: %s: Connecting to %s:%s" % (self.name, self.host,self.port))
try: try:
self.con = AuthServiceProxy("http://%s:%s@%s:%s" % (self.username, self.password, self.host, self.port)) self.con = AuthServiceProxy("http://%s:%s@%s:%s" % (self.username, self.password, self.host, self.port))
except Exception as e: except Exception as e:
self.log.debug("CryptoWalletRPC: %s: Could not connect to %s:%s: %s" % (self.name, self.host, self.port, str(e))) self.log.info("CryptoWalletRPC: %s: Could not connect to %s:%s: %s" % (self.name, self.host, self.port, str(e)))
return return
self.log.debug("CryptoWalletRPC: %s: Connected to %s:%s" % (self.name, self.host, self.port)) self.log.info("CryptoWalletRPC: %s: Connected to %s:%s" % (self.name, self.host, self.port))

View File

@ -73,7 +73,7 @@ class DogeController:
def connect(self): def connect(self):
"Connect to RPC endpoint" "Connect to RPC endpoint"
self.log.debug("DogeRPC: Connecting to dogecoind") self.log.info("DogeRPC: Connecting to dogecoind")
self.con = AuthServiceProxy("http://%s:%s@%s:%s" % (self.config["username"], self.config["password"], self.config["host"], self.config["port"])) self.con = AuthServiceProxy("http://%s:%s@%s:%s" % (self.config["username"], self.config["password"], self.config["host"], self.config["port"]))
self.con.getinfo() self.con.getinfo()
self.log.debug("DogeRPC: Connected to %s:%s" % (self.config["host"], self.config["port"])) self.log.info("DogeRPC: Connected to %s:%s" % (self.config["host"], self.config["port"]))

View File

@ -145,7 +145,7 @@ class scrambleGame:
self.nextTimer.start() self.nextTimer.start()
self.guesses=0 self.guesses=0
self.category_count+=1 self.category_count+=1
self.master.log.debug("DogeScramble: category_count is: %s" % (self.category_count)) self.master.log.info("DogeScramble: category_count is: %s" % (self.category_count))
if self.category_count >= self.change_category_after_words: if self.category_count >= self.change_category_after_words:
self.should_change_category = True self.should_change_category = True
else: else:
@ -247,7 +247,7 @@ class scrambleGame:
picked = f.readline().strip().lower() picked = f.readline().strip().lower()
f.close() f.close()
self.master.log.debug("DogeScramble: picked %s for %s" % (picked, self.channel)) self.master.log.info("DogeScramble: picked %s for %s" % (picked, self.channel))
self.lastwords.append(picked) self.lastwords.append(picked)
if len(self.lastwords) > 5: if len(self.lastwords) > 5:
self.lastwords.pop(0) self.lastwords.pop(0)

View File

@ -111,13 +111,13 @@ class LinkTitler(ModuleBase):
def url_headers(self, url): def url_headers(self, url):
"HEAD requests a url to check content type & length, returns something like: {'type': 'image/jpeg', 'size': '90583'}" "HEAD requests a url to check content type & length, returns something like: {'type': 'image/jpeg', 'size': '90583'}"
self.log.debug("url_headers(%s)" % (url,)) self.log.info("url_headers(%s)" % (url,))
resp = head(url=url, allow_redirects=True) resp = head(url=url, allow_redirects=True)
return resp.headers return resp.headers
def url_htmltitle(self, url): def url_htmltitle(self, url):
"Requests page html and returns title in a safe way" "Requests page html and returns title in a safe way"
self.log.debug("url_htmltitle(%s)" % (url,)) self.log.info("url_htmltitle(%s)" % (url,))
resp = get(url=url, stream=True) resp = get(url=url, stream=True)
# Fetch no more than first 10kb # Fetch no more than first 10kb
# if the title isn't seen by then, you're doing it wrong # if the title isn't seen by then, you're doing it wrong

View File

@ -41,6 +41,6 @@ class Triggered(ModuleBase):
def scream(self, channel): def scream(self, channel):
delay = randrange(self.config["mindelay"], self.config["maxdelay"]) delay = randrange(self.config["mindelay"], self.config["maxdelay"])
self.log.debug("Sleeping for %s seconds" % delay) self.log.info("Sleeping for %s seconds" % delay)
sleep(delay) sleep(delay)
self.bot.act_PRIVMSG(channel, choice(self.config["responses"])) self.bot.act_PRIVMSG(channel, choice(self.config["responses"]))

View File

@ -12,8 +12,12 @@ import sys
import traceback import traceback
from pyircbot.rpc import BotRPC from pyircbot.rpc import BotRPC
from pyircbot.irccore import IRCCore from pyircbot.irccore import IRCCore
from collections import namedtuple
import os.path import os.path
ParsedCommand = namedtuple("ParsedCommand", "command args args_str message")
class PyIRCBot: class PyIRCBot:
""":param botconfig: The configuration of this instance of the bot. Passed by main.py. """:param botconfig: The configuration of this instance of the bot. Passed by main.py.
:type botconfig: dict :type botconfig: dict
@ -126,7 +130,7 @@ class PyIRCBot:
:type moduleName: str""" :type moduleName: str"""
" check if already exists " " check if already exists "
if not name in self.modules: if not name in self.modules:
self.log.debug("Importing %s" % name) self.log.info("Importing %s" % name)
" attempt to load " " attempt to load "
try: try:
moduleref = __import__(name) moduleref = __import__(name)
@ -146,7 +150,7 @@ class PyIRCBot:
:param moduleName: Name of the module to import :param moduleName: Name of the module to import
:type moduleName: str""" :type moduleName: str"""
self.log.debug("Deporting %s" % name) self.log.info("Deporting %s" % name)
" unload if necessary " " unload if necessary "
if name in self.moduleInstances: if name in self.moduleInstances:
self.unloadmodule(name) self.unloadmodule(name)
@ -368,13 +372,10 @@ class PyIRCBot:
return False return False
# Verified! Return the set. # Verified! Return the set.
ob = type('ParsedCommand', (object,), {}) return ParsedCommand(command,
ob.command = command args.split(" "),
ob.args = [] if args=="" else args.split(" ") args,
ob.args_str = args message)
ob.message = message
return ob
# return (True, command, args, message)
@staticmethod @staticmethod
def load(filepath): def load(filepath):