def __init__(self, config): self.channels = [c.split(' ', 1) for c in config['channels']] self.nickname = config['nickname'] self.password = config.get('password', None) self.history = {} acl_fname = config.get('acl', None) if acl_fname: # Bubble up an IOError if they passed a bad file with open(acl_fname, 'r') as acl_fd: self.acl = ACL(acl_fd.read()) else: self.acl = AllowAllACL() self.loader = PluginLoader(config) if 'db' in config: log.info('Loading db from config: %s', config['db']) db_engine = sqlalchemy.create_engine(config['db']) else: log.info('Using in-memory db') db_engine = sqlalchemy.create_engine('sqlite:///:memory:') DBSession = orm.sessionmaker(db_engine) session = DBSession() self.loader.db = DB(db_engine, session) self.loader.loadAll()
def registerPlugin(self, plugin): """Registers a plugin.""" plugin_types = { 'presence': IPresencePlugin, 'chat': IChatPlugin, 'population': IPopulationPlugin, 'base_plugin': IPlugin, } # Everything is, at least, a base plugin. valid_types = ['baseplugin'] # Loop through the types of plugins and check for implentation of each. for t, interface in plugin_types.iteritems(): try: verified_plugin = verify_plugin(interface, plugin) # If the above succeeded, then `plugin` implementes `interface`. self.plugins[t].append(verified_plugin) self.plugins[t].sort() valid_types.append(t) except DoesNotImplement: # This means this plugin does not declare to be a `t`. pass except PluginException: log.error('Plugin %s claims to be a %s, but is not!', plugin.name, t) plugin.setup(self) log.info('registered plugin %s as %s', plugin.name, valid_types)
def registerPlugin(self, plugin): """Registers a plugin.""" plugin_types = { 'presence': IPresencePlugin, 'chat': IChatPlugin, 'population': IPopulationPlugin, 'base_plugin': IPlugin, } # Everything is, at least, a base plugin. valid_types = ['baseplugin'] # Loop through the types of plugins and check for implentation of each. for t, interface in plugin_types.iteritems(): try: verified_plugin = verify_plugin(interface, plugin) # If the above succeeded, then `plugin` implementes `interface`. self.plugins[t].append(verified_plugin) self.plugins[t].sort() valid_types.append(t) except DoesNotImplement: # This means this plugin does not declare to be a `t`. pass except PluginException: log.error('Plugin "%s" claims to be a %s, but is not!', plugin.name, t) plugin.setup(self) log.info('registered plugin %s as %s', plugin.name, valid_types)
def loadAll(self): plugins_to_load = set() # Gather plugins for plugin in iter_entry_points(group='hamperbot.plugins', name=None): if plugin.name in self.config['plugins']: plugins_to_load.add(plugin.load()) # Sort by priority, highest first plugins_to_load = sorted(plugins_to_load, key=lambda p: -p.priority) # Check dependencies and load plugins. for plugin_class in plugins_to_load: plugin_obj = plugin_class() if not self.dependencies_satisfied(plugin_obj): log.warning('Dependency not satisfied for {0}. Not loading.' .format(plugin_class.__name__)) continue log.info('Loading plugin {0}.'.format(plugin_class.__name__)) plugin_obj.setup(self) self.plugins.append(plugin_obj) # Check for missing plugins plugin_names = {x.name for x in self.plugins} for pattern in self.config['plugins']: if pattern not in plugin_names: log.warning('Sorry, I couldn\'t find a plugin named "%s"', pattern)
def registerPlugin(self, plugin): """Registers a plugin.""" plugin_types = { 'presence': IPresencePlugin, 'chat': IChatPlugin, 'population': IPopulationPlugin, 'base_plugin': BaseInterface, } # Everything is, at least, a base plugin. valid_types = ['baseplugin'] # Loop through the types of plugins and check for implentation of each. claimed_compliances = list(implementedBy(type(plugin))) # Can we use this as a map instead? for t, interface in plugin_types.iteritems(): if interface in claimed_compliances: try: verifyObject(interface, plugin) # If the above succeeded, then `plugin` implementes `interface`. self.plugins[t].append(plugin) self.plugins[t].sort() valid_types.append(t) except DoesNotImplement: log.error('Plugin %s claims to be a %s, but is not!', plugin.name, t) plugin.setup(self) log.info('registered plugin %s as %s', plugin.name, valid_types)
def loadAll(self): plugins_to_load = set() # Gather plugins for plugin in iter_entry_points(group='hamperbot.plugins', name=None): if plugin.name in self.config['plugins']: plugins_to_load.add(plugin.load()) # Sort by priority, highest first plugins_to_load = sorted(plugins_to_load, key=lambda p: -p.priority) # Check dependencies and load plugins. for plugin_class in plugins_to_load: plugin_obj = plugin_class() if not self.dependencies_satisfied(plugin_obj): log.warning('Dependency not satisfied for {0}. Not loading.' .format(plugin_class.__name__)) continue log.info('Loading plugin {0}.'.format(plugin_class.__name__)) plugin_obj.setup(self) self.plugins.append(plugin_obj) # Check for missing plugins plugin_names = {x.name for x in self.plugins} # Don't allow karma and karma_adv to be loaded at once if ('karma' in self.config['plugins'] and 'karma_adv' in self.config['plugins']): quit( "Unable to load both karma and karma_adv at the same time") for pattern in self.config['plugins']: if pattern not in plugin_names: log.warning('Sorry, I couldn\'t find a plugin named "%s"', pattern)
def signedOn(self): """Called after successfully signing on to the server.""" log.info("Signed on as %s.", self.nickname) if not self.password: # We aren't wating for auth, join all the channels self.joinChannels() else: self.msg("NickServ", "IDENTIFY %s" % self.password)
def process_action(self, raw_user, channel, raw_message): """Called when a message is received from a channel or user.""" log.info("%s %s %s", channel, raw_user, raw_message) if not raw_user: # ignore server messages return # This monster of a regex extracts msg and target from a message, where # the target may not be there, and the target is a valid irc name. # Valid ways to target someone are "<nick>: ..." and "<nick>, ..." target, message = re.match( r'^(?:([a-z_\-\[\]\\^{}|`]' # First letter can't be a number '[a-z0-9_\-\[\]\\^{}|`]*)' # The rest can be many things '[:,] )? *(.*)$', # The actual message raw_message, re.I).groups() pm = channel == self.nickname if pm: directed = True if target: if target.lower() == self.nickname.lower(): directed = True else: directed = False message = '{0}: {1}'.format(target, message) else: directed = False if message.startswith('!'): message = message[1:] directed = True if directed: message = message.rstrip() try: user, mask = raw_user.split('!', 1) except ValueError: user = raw_user mask = '' comm = { 'raw_message': raw_message, 'message': message, 'raw_user': raw_user, 'user': user, 'mask': mask, 'target': target, 'channel': channel, 'directed': directed, 'pm': pm, } self.dispatch('chat', 'message', comm) self.factory.history.setdefault( channel, deque(maxlen=100)).append(comm)
def process_action(self, raw_user, channel, raw_message): """Called when a message is received from a channel or user.""" log.info("%s %s %s", channel, raw_user, raw_message) if not raw_user: # ignore server messages return # This monster of a regex extracts msg and target from a message, where # the target may not be there, and the target is a valid irc name. # Valid ways to target someone are "<nick>: ..." and "<nick>, ..." target, message = re.match( r'^(?:([a-z_\-\[\]\\^{}|`]' # First letter can't be a number '[a-z0-9_\-\[\]\\^{}|`]*)' # The rest can be many things '[:,] )? *(.*)$', # The actual message raw_message, re.I).groups() pm = channel == self.nickname if target: if target.lower() == self.nickname.lower(): directed = True else: directed = False message = '{0}: {1}'.format(target, message) else: directed = False if message.startswith('!'): message = message[1:] directed = True if directed: message = message.rstrip() try: user, mask = raw_user.split('!', 1) except ValueError: user = raw_user mask = '' comm = { 'raw_message': raw_message, 'message': message, 'raw_user': raw_user, 'user': user, 'mask': mask, 'target': target, 'channel': channel, 'directed': directed, 'pm': pm, } self.dispatch('chat', 'message', comm) if not channel in self.factory.history: self.factory.history[channel] = deque(maxlen=100) self.factory.history[channel].append(comm)
def noticed(self, user, channel, message): log.info("NOTICE %s %s %s" % (user, channel, message)) # mozilla's nickserv responds as [email protected] if (self.password and channel == self.nickname and user.startswith('NickServ')): if ("Password accepted" in message or "You are now identified" in message): self.joinChannels() elif "Password incorrect" in message: log.info("NickServ AUTH FAILED!!!!!!!") reactor.stop()
def signedOn(self): """Called after successfully signing on to the server.""" log.info("Signed on as %s.", self.nickname) self.dispatch('presence', 'signedOn') for c in self.factory.channels: self.join(c)
def removePlugin(self, plugin): log.info("Unloading %r" % plugin) for plugin_type, plugins in self.factory.plugins.items(): if plugin in plugins: log.debug('plugin is a %s', plugin_type) plugins.remove(plugin)
def clientConnectionLost(self, connector, reason): log.info('Lost connection (%s).', (reason)) # Reconnect connector.connect()
def clientConnectionFailed(self, connector, reason): log.info('Could not connect: %s', (reason, ))
def joined(self, channel): """Called after successfully joining a channel.""" log.info("Joined %s.", channel) # ask for the current list of users in the channel self.dispatch('presence', 'joined', channel)
def left(self, channel): """Called after leaving a channel.""" log.info("Left %s.", channel) self.dispatch('presence', 'left', channel)
def clientConnectionFailed(self, connector, reason): log.info('Could not connect: %s', (reason,))