def __init__ (self, config): # Create logger self.logger = logging.getLogger(__name__) # Load the database try: # Create logger self.db_logger = logging.getLogger(__name__+".database") # Get the database address and port from the config, # or use the mongodb defaults address = config.pop('db_address', 'localhost') port = config.pop('db_port', 27017) # The database connection self.connection = Connection(address, port) self.database = self.connection[config.pop('db_name', 'tactics')] # The main quote collection self.phrases = Phrases(self.database, config) # The users collection # self.users = Users(self.connection['users']) except Exception as e: self.logger.error("Database could not be loaded: {}".format(e.message)) traceback.print_exc() exit() # Call __init__ on the Aleph superclass EventInterface.__init__(self, config) # Commands self.commands = OrderedDict() # Add phrase types to command list for link_name in static.links: link_regex = "^{}$".format(static.links[link_name][0]) self.commands[link_regex] = self.add_phrase_command(link_name) # Load static commands self.commands.update({ "^delete #(?P<id>\d+)$": self.delete_phrase, }) self.logger.debug("Loaded static commands") # Load dynamic commands import commands self.commands_module = commands self.commands.update(self.commands_module.dynamic_commands) self.logger.debug("Loaded dynamic commands")
class Tactics (EventInterface): def __init__ (self, config): # Create logger self.logger = logging.getLogger(__name__) # Load the database try: # Create logger self.db_logger = logging.getLogger(__name__+".database") # Get the database address and port from the config, # or use the mongodb defaults address = config.pop('db_address', 'localhost') port = config.pop('db_port', 27017) # The database connection self.connection = Connection(address, port) self.database = self.connection[config.pop('db_name', 'tactics')] # The main quote collection self.phrases = Phrases(self.database, config) # The users collection # self.users = Users(self.connection['users']) except Exception as e: self.logger.error("Database could not be loaded: {}".format(e.message)) traceback.print_exc() exit() # Call __init__ on the Aleph superclass EventInterface.__init__(self, config) # Commands self.commands = OrderedDict() # Add phrase types to command list for link_name in static.links: link_regex = "^{}$".format(static.links[link_name][0]) self.commands[link_regex] = self.add_phrase_command(link_name) # Load static commands self.commands.update({ "^delete #(?P<id>\d+)$": self.delete_phrase, }) self.logger.debug("Loaded static commands") # Load dynamic commands import commands self.commands_module = commands self.commands.update(self.commands_module.dynamic_commands) self.logger.debug("Loaded dynamic commands") """ Dynamic commands """ def reload_commands (self): """ Reloads commands from the dynamic commands list """ # Remove old commands for key in self.commands_module.dynamic_commands: del self.commands[key] # Reload the commands module and load it reload(self.commands_module) self.commands.update(self.commands_module.dynamic_commands) self.logger.debug("Reloaded dynamic commands") def show_commands (self): """ Returns a string of the loaded commands """ string = "" for command in self.commands: string += "\n\t\t" + command return string """ Input """ def on_privmsg (self, message): """ Respond to messages """ if message.pm or message.to_me: return self.respond(message) # Look for related phrases try: return self.find_related_phrase(message) except NoPhraseFound: pass def respond (self, message): """ Respond to direct messages """ command = self.is_command(message.text) if command: try: return self.run_command(command, message) except ReplyException as error: self.logger.warning(error.message) return message.reply(error.message) # Message has not parsed return message.reply("Message does not parse.") def is_command(self, text): """ Check if a message matches any of the commands """ command = filter(lambda c: match(c,text), self.commands) # Return first matching command, or False if there are no matching commands return command[0] if command else False def run_command (self, c, message): """ Run the given command, calling it if it is a function, or replying with it as a string """ command = self.commands[c] self.logger.debug(c) if hasattr(command, '__call__'): # Search the regex for arguments, and pass them as kwargs kwargs = search(c, message.text).groupdict() command(self, message, **kwargs) else: message.reply(str(command)) """ Phrases - Adding """ def add_phrase_command (self, link_name): """ Returns a lambda function for adding links of a set type Used for creating commands with the static link data """ return lambda self, message, **kwargs: self.add_phrase(message, link_name, **kwargs) def add_phrase (self, message, link_name, **phrase): """ If the phrase has been matched by a link type, try and add it """ id = self.phrases.create(phrase, link_name, { 'author-nick': str(message.source['nick']), 'author-host': str(message.source), }) # Notify self.logger.info('Iserted phrase: "{}" [#{:>06}]'.format(self.phrases.format(phrase), id)) message.reply('Phrase "{}" added to my collection [#{:>06}].'.format(self.phrases.format(phrase), id)) def delete_phrase (self, _, message, id): """ Try and remove a phrase from the database """ self.phrases.delete(int(id)) message.reply("Phrase #{:>06} deleted.".format(id)) """ Phrases - fetching """ def find_related_phrase (self, message): """ Finds a random phrase related to the given text Throws a NoPhraseFound exception if it cannot find a related phrase """ debug_msg = "Attempting to find phrase for text '{}'... ".format(message.text) # Remove trailing spaces and full stops from message text, then split into words words = message.text.strip(' .').split(' ') # Find the subject with the most phrases best_count, best_subject = 0, None best_phrases = None for subject in words: phrases = self.phrases.get_phrases_by_subject(subject) if phrases.count() > best_count: best_count, best_subject = phrases.count(), subject best_phrases = phrases # Finish if no phrases found if not best_subject: self.logger.debug(debug_msg + "No phrases found") return None # Select a random phrase from the list r = randint(0,best_count-1) self.logger.debug(debug_msg + "Using phrase {} of {}".format(r+1, best_phrases.count())) # Record it as the last used phrase self.phrases.last = best_phrases[r] # Return the phrase return message.msg(self.format(message, best_phrases[r])) def format (self, message, phrase): """ Formats a phrase with variables from the message and bot """ text = self.phrases.format(phrase) text = text.format(**{ 'nick': message.source.name() }) return text