def __init__(self, nick=None, name=None, channels=None, password=None, debug=True): Bot.__init__(self, nick, name, channels, password) self.joined = False self.autoTofadeThreshold = 98 self.riddleMaxDist = 2 self.debug = debug self.TGtime = 5 self.lolRateDepth = 8 self.cron = Cron() self.lastTGtofbot = 0 self.memoryDepth = 50 self.last_interaction = int(time.time()) self.plugins = self.load_plugins()
def __init__(self, nick=None, name=None, channels=None, password=None, debug=True): Bot.__init__(self, nick, name, channels, password) self.joined = False self.autoTofadeThreshold = 98 self.riddleMaxDist = 2 self.debug = debug self.TGtime = 5 self.lolRateDepth = 8 self.cron = Cron() self.lastTGtofbot = 0 self.memoryDepth = 20 self.plugins = self.load_plugins()
class Tofbot(Bot): # Those attributes are published and can be changed by irc users # value is a str to object converter. It could do sanitization: # if value is incorrect, raise ValueError _mutable_attributes = {"TGtime": int, "memoryDepth": int} def __init__(self, nick=None, name=None, channels=None, password=None, debug=True): Bot.__init__(self, nick, name, channels, password) self.joined = False self.autoTofadeThreshold = 98 self.riddleMaxDist = 2 self.debug = debug self.TGtime = 5 self.lolRateDepth = 8 self.cron = Cron() self.lastTGtofbot = 0 self.memoryDepth = 50 self.last_interaction = int(time.time()) self.plugins = self.load_plugins() def idle_time(self): return int(time.time() - self.last_interaction) def load_plugins(self): d = os.path.dirname(__file__) plugindir = os.path.join(d, 'plugins') plugin_instances = {} for m in dir(plugins): if isinstance(m, types.ModuleType): continue plugin = getattr(plugins, m) for n in dir(plugin): c = getattr(plugin, n) if type(c) not in [types.ClassType, types.TypeType]: continue name = c.__name__ if name.startswith('Plugin'): instance = c(self) plugin_name = name[6:].lower() plugin_instances[plugin_name] = instance return plugin_instances # line-feed-safe def msg(self, chan, msg): for m in msg.split("\n"): Bot.msg(self, chan, m) def log(self, msg): if self.debug: print(msg) def try_join(self, args): if args[0] in ("End of /MOTD command.", "This server was created ... I don't know"): for chan in self.channels: self.write(('JOIN', chan)) self.joined = True def dispatch(self, origin, args): # Useful: https://www.alien.net.au/irc/irc2numerics.html self.last_interaction = time.time() self.log("o=%s n=%s a=%s" % (origin.sender, origin.nick, args)) sender_nick = origin.nick command_type = args[1] if not self.joined: self.try_join(args) return if command_type == 'JOIN': for p in self.plugins.values(): p.on_join(args[0], sender_nick) elif command_type == 'KICK' and args[3] == self.nick: reason = args[0] chan = args[2] self.write(('JOIN', chan)) for p in self.plugins.values(): p.on_kick(chan, reason) elif command_type == 'PRIVMSG': self.cron.tick() msg_text = args[0] chan = args[2] urls = urls_in(msg_text) # filter empty messages if len(msg_text.strip()) == 0: return # dispatch to plugins for p in self.plugins.values(): p.handle_msg(msg_text, chan, sender_nick) for url in urls: p.on_url(url) # dispatch commands if msg_text.strip().startswith("!"): tokens = msg_text.strip().split(" ") cmd = tokens[0][1:] chan = self.channels[0] if cmd in _simple_dispatch: act = self.find_cmd_action("cmd_" + cmd) act(chan, tokens[1:], sender_nick) elif command_type == 'PING': self.log('PING received in bot.py') elif command_type == 'ERROR': traceback.print_exc(file=sys.stdout) elif command_type == 'PART': chan = args[2] for p in self.plugins.values(): p.on_leave(chan, sender_nick) elif command_type == 'QUIT': for p in self.plugins.values(): p.on_quit(sender_nick) elif command_type == '353': # Reply to NAMES names = set([ n.lstrip('@') for n in args[0].split(' ') if n.lstrip('@') != self.nick ]) # act like if everybody just joined for n in names: for p in self.plugins: if p != "jokes": self.plugins[p].on_join(args[-1], n) else: # Unknown command type self.log('Unknown command type : %s' % command_type) def find_cmd_action(self, cmd_name): targets = self.plugins.values() targets.insert(0, self) for t in targets: if (hasattr(t, cmd_name)): action = getattr(t, cmd_name) return action def nop(self, chan, args): pass return nop def safe_getattr(self, key): if key not in self._mutable_attributes: return None if not hasattr(self, key): return "(None)" else: return str(getattr(self, key)) def safe_setattr(self, key, value): try: converter = self._mutable_attributes.get(key) if converter is None: return False value = converter(value) setattr(self, key, value) return True except ValueError: pass def load(self, filename): try: with open(filename) as f: state = json.load(f) if state['version'] != 1: return False for name, plugin_state in state['plugins'].items(): try: plugin = self.plugins[name] plugin.load(plugin_state) except KeyError: pass except IOError as e: print "Can't load state. Error: ", e def save(self, filename): try: with open(filename, 'w') as f: state = {'version': 1, 'plugins': {}} for name, plugin in self.plugins.items(): plugin_state = plugin.save() state['plugins'][name] = plugin_state json.dump(state, indent=4, fp=f) except IOError as e: print "Can't save state. Error: ", e
class Tofbot(Bot): # Those attributes are published and can be changed by irc users # value is a str to object converter. It could do sanitization: # if value is incorrect, raise ValueError _mutable_attributes = { "TGtime": int, "memoryDepth": int } def __init__(self, nick=None, name=None, channels=None, password=None, debug=True): Bot.__init__(self, nick, name, channels, password) self.joined = False self.autoTofadeThreshold = 98 self.riddleMaxDist = 2 self.debug = debug self.TGtime = 5 self.lolRateDepth = 8 self.cron = Cron() self.lastTGtofbot = 0 self.memoryDepth = 50 self.last_interaction = int(time.time()) self.plugins = self.load_plugins() def idle_time(self): return int(time.time() - self.last_interaction) def load_plugins(self): d = os.path.dirname(__file__) plugindir = os.path.join(d, 'plugins') plugin_instances = {} for m in dir(plugins): if isinstance(m, types.ModuleType): continue plugin = getattr(plugins, m) for n in dir(plugin): c = getattr(plugin, n) if type(c) not in [types.ClassType, types.TypeType]: continue name = c.__name__ if name.startswith('Plugin'): instance = c(self) plugin_name = name[6:].lower() plugin_instances[plugin_name] = instance return plugin_instances # line-feed-safe def msg(self, chan, msg): for m in msg.split("\n"): Bot.msg(self, chan, m) def log(self, msg): if self.debug: print(msg) def try_join(self, args): if args[0] in ("End of /MOTD command.", "This server was created ... I don't know"): for chan in self.channels: self.write(('JOIN', chan)) self.joined = True def dispatch(self, origin, args): # Useful: https://www.alien.net.au/irc/irc2numerics.html self.last_interaction = time.time() self.log("o=%s n=%s a=%s" % (origin.sender, origin.nick, args)) sender_nick = origin.nick command_type = args[1] if not self.joined: self.try_join(args) return if command_type == 'JOIN': for p in self.plugins.values(): p.on_join(args[0], sender_nick) elif command_type == 'KICK' and args[3] == self.nick: reason = args[0] chan = args[2] self.write(('JOIN', chan)) for p in self.plugins.values(): p.on_kick(chan, reason) elif command_type == 'PRIVMSG': self.cron.tick() msg_text = args[0] chan = args[2] urls = urls_in(msg_text) # filter empty messages if len(msg_text.strip()) == 0: return # dispatch to plugins for p in self.plugins.values(): p.handle_msg(msg_text, chan, sender_nick) for url in urls: p.on_url(url) # dispatch commands if msg_text.strip().startswith("!"): tokens = msg_text.strip().split(" ") cmd = tokens[0][1:] chan = self.channels[0] if cmd in _simple_dispatch: act = self.find_cmd_action("cmd_" + cmd) act(chan, tokens[1:], sender_nick) elif command_type == 'PING': self.log('PING received in bot.py') elif command_type == 'ERROR': traceback.print_exc(file=sys.stdout) elif command_type == 'PART': chan = args[2] for p in self.plugins.values(): p.on_leave(chan, sender_nick) elif command_type == 'QUIT': for p in self.plugins.values(): p.on_quit(sender_nick) elif command_type == '353': # Reply to NAMES names = set([n.lstrip('@') for n in args[0].split(' ') if n.lstrip('@') != self.nick]) # act like if everybody just joined for n in names: for p in self.plugins: if p != "jokes": self.plugins[p].on_join(args[-1], n) else: # Unknown command type self.log('Unknown command type : %s' % command_type) def find_cmd_action(self, cmd_name): targets = self.plugins.values() targets.insert(0, self) for t in targets: if (hasattr(t, cmd_name)): action = getattr(t, cmd_name) return action def nop(self, chan, args): pass return nop def safe_getattr(self, key): if key not in self._mutable_attributes: return None if not hasattr(self, key): return "(None)" else: return str(getattr(self, key)) def safe_setattr(self, key, value): try: converter = self._mutable_attributes.get(key) if converter is None: return False value = converter(value) setattr(self, key, value) return True except ValueError: pass def load(self, filename): try: with open(filename) as f: state = json.load(f) if state['version'] != 1: return False for name, plugin_state in state['plugins'].items(): try: plugin = self.plugins[name] plugin.load(plugin_state) except KeyError: pass except IOError as e: print "Can't load state. Error: ", e def save(self, filename): try: with open(filename, 'w') as f: state = {'version': 1, 'plugins': {}} for name, plugin in self.plugins.items(): plugin_state = plugin.save() state['plugins'][name] = plugin_state json.dump(state, indent=4, fp=f) except IOError as e: print "Can't save state. Error: ", e