Beispiel #1
0
 def __init__(self):
     # commands get checked first - other modules shouldn't be able to override commands from happening
     event_handler.hook('messages:on_handle_messages', self.on_handle_message, 0)
     
     event_handler.hook('commands:do_command', self.do_command)
     
     event_handler.hook('irc:on_whoisaccount', self.on_whoisaccount)
     event_handler.hook('irc:on_endofwhois', self.on_endofwhois)
     
     self.callback_handler = CallbackHandler('commands')
Beispiel #2
0
 def __init__(self):
     event_handler.hook('undo:on_undo', self.on_undo)
     event_handler.hook('undo:on_redo', self.on_redo)
     
     event_handler.hook('db_commands:on_after_add', self.on_after_add)
     event_handler.hook('db_commands:on_before_remove', self.on_before_remove)
     event_handler.hook('db_commands:on_after_remove', self.on_after_remove)
     event_handler.hook('db_commands:on_before_set', self.on_before_set)
     event_handler.hook('db_commands:on_after_set', self.on_after_set)
     
     self.callback_handler = CallbackHandler('alerts')
Beispiel #3
0
 def __init__(self):
     event_handler.hook('irc:on_invite', self.on_invite)
     event_handler.hook('irc:on_kick', self.on_kick)
     event_handler.hook('irc:on_join', self.on_join)
     event_handler.hook('irc:on_namreply', self.on_namreply)
     event_handler.hook('irc:on_channelisfull', self.on_needinvite)
     event_handler.hook('irc:on_inviteonlychan', self.on_needinvite)
     event_handler.hook('irc:on_badchannelkey', self.on_needinvite)
     
     event_handler.hook('send:on_before_send_message', self.on_before_send_message)
     event_handler.hook('bot:on_quit', self.on_quit)
     
     self.callback_handler = CallbackHandler('channels')
Beispiel #4
0
 def __init__(self):
     event_handler.hook('modulehandler:before_init_modules', self.on_before_init_modules)
     event_handler.hook('modulehandler:after_load_modules', self.on_after_load_modules)
     
     event_handler.hook('help:get_command_description', self.get_command_description)
     
     event_handler.hook('commands:get_auth_commands', self.get_auth_commands)
     event_handler.hook('commands:do_auth_command', self.do_auth_command)
     
     event_handler.hook('db_commands:on_after_add', self.on_after_add)
     event_handler.hook('db_commands:on_before_remove', self.on_before_remove)
     event_handler.hook('db_commands:on_after_remove', self.on_after_remove)
     event_handler.hook('db_commands:on_before_set', self.on_before_set)
     event_handler.hook('db_commands:on_after_set', self.on_after_set)
     
     self.callback_handler = CallbackHandler('undo')
Beispiel #5
0
class Undo():
    undo_stack = []
    redo_stack = []
    auth_commands = {
        'undo': 30,
        'redo': 30,
    }
    command_descriptions = {
        'undo': """
            Undoes the last database action (such as add or remove)
            Note: Using "undo, redo, undo" has the same final effect as simply doing "undo" once, as "undo" will also undo a "redo"
            Syntax: undo
        """,
        'redo': """
            redoes the last database action that was undone using "undo" (such as add or remove)
            Note: Using "undo, redo, undo" has the same final effect as simply doing "undo" once, as "undo" will also undo a "redo"
            Syntax: redo
        """,
    }
    
    def __init__(self):
        event_handler.hook('modulehandler:before_init_modules', self.on_before_init_modules)
        event_handler.hook('modulehandler:after_load_modules', self.on_after_load_modules)
        
        event_handler.hook('help:get_command_description', self.get_command_description)
        
        event_handler.hook('commands:get_auth_commands', self.get_auth_commands)
        event_handler.hook('commands:do_auth_command', self.do_auth_command)
        
        event_handler.hook('db_commands:on_after_add', self.on_after_add)
        event_handler.hook('db_commands:on_before_remove', self.on_before_remove)
        event_handler.hook('db_commands:on_after_remove', self.on_after_remove)
        event_handler.hook('db_commands:on_before_set', self.on_before_set)
        event_handler.hook('db_commands:on_after_set', self.on_after_set)
        
        self.callback_handler = CallbackHandler('undo')
    
    def on_before_init_modules(self, module_handler, bot, event_handler, first_time):
        # we're about to be replaced!
        bot.module_parameters['undo:undo_stack'] = self.undo_stack
        bot.module_parameters['undo:redo_stack'] = self.redo_stack
    
    def on_after_load_modules(self, module_handler, bot, event_handler, first_time):
        self.undo_stack = bot.module_parameters.pop('undo:undo_stack', [])
        self.redo_stack = bot.module_parameters.pop('undo:redo_stack', [])
    
    def get_command_description(self, bot, command):
        if command in self.command_descriptions:
            return self.command_descriptions[command]
    
    def get_auth_commands(self, bot):
        return self.auth_commands
    
    def do_auth_command(self, bot, connection, event, command, parameters, reply_target, auth_level):
        if command not in self.auth_commands:
            return False # not for us
        
        if command == 'undo':
            if not self.undo_stack:
                return False
            
            undo = self.undo_stack.pop()
            if undo:
                undo['function'](*undo['parameters'])
                
                self.add_to_stack(bot, self.redo_stack, undo['alt_function'], undo['alt_parameters'], undo['function'], undo['parameters'])
                
                bot.send(connection, reply_target, bot.db.get_random('yes'), event)
                event_handler.fire('undo:on_undo', (bot, connection, event, command, parameters, reply_target, auth_level))
                return True
        
        elif command == 'redo':
            if not self.redo_stack:
                return False
            
            redo = self.redo_stack.pop()
            if redo:
                redo['function'](*redo['parameters'])
                
                self.add_to_stack(bot, self.undo_stack, redo['alt_function'], redo['alt_parameters'], redo['function'], redo['parameters'])
                
                bot.send(connection, reply_target, bot.db.get_random('yes'), event)
                event_handler.fire('undo:on_redo', (bot, connection, event, command, parameters, reply_target, auth_level))
                return True
        
        return False
    
    def on_after_add(self, bot, connection, event, reply_target, auth_level, key, value):
        self.add_to_stack(bot, self.undo_stack, bot.db.delete, (key, value), bot.db.add, (key, value))
    
    def on_before_remove(self, bot, connection, event, reply_target, auth_level, key, value):
        db_key, old_value = bot.db.get_key_value(key, value)
        if old_value:
            self.callback_handler.add(
                'remove|%s|%s' % (key, value),
                self.stack_undo_remove,
                (bot, db_key, old_value, value)
            )
    
    def on_after_remove(self, bot, connection, event, reply_target, auth_level, key, value):
        self.callback_handler.run('remove|%s|%s' % (key, value))
    
    def on_before_set(self, bot, connection, event, reply_target, auth_level, key, values):
        old_values = bot.db.get_all(key)
        if old_values:
            self.callback_handler.add(
                'set|%s|%s' % (key, '|'.join(values)),
                self.stack_undo_set,
                (bot, key, old_values, values)
            )
    
    def on_after_set(self, bot, connection, event, reply_target, auth_level, key, values):
        self.callback_handler.run('set|%s|%s' % (key, '|'.join(values)))
    
    def stack_undo_remove(self, bot, key, old_value, new_value):
        self.add_to_stack(bot, self.undo_stack, bot.db.add, (key, old_value), bot.db.delete, (key, new_value))
    
    def stack_undo_set(self, bot, key, old_values, new_values):
        self.add_to_stack(bot, self.undo_stack, bot.db.set, (key, old_values), bot.db.set, (key, new_values))
    
    def add_to_stack(self, bot, stack, function, parameters, alt_function, alt_parameters):
        if not isinstance(parameters, (tuple, list)):
            parameters = (parameters, )
        
        stack.append({
            'function': function,
            'parameters': parameters,
            'alt_function': alt_function,
            'alt_parameters': alt_parameters,
        })
        
        stack_difference = len(stack) - int(bot.db.get('undo_stack_size', default_value = 10))
        if stack_difference > 0:
            stack = stack[stack_difference:]
Beispiel #6
0
class Alerts():
    def __init__(self):
        event_handler.hook('undo:on_undo', self.on_undo)
        event_handler.hook('undo:on_redo', self.on_redo)
        
        event_handler.hook('db_commands:on_after_add', self.on_after_add)
        event_handler.hook('db_commands:on_before_remove', self.on_before_remove)
        event_handler.hook('db_commands:on_after_remove', self.on_after_remove)
        event_handler.hook('db_commands:on_before_set', self.on_before_set)
        event_handler.hook('db_commands:on_after_set', self.on_after_set)
        
        self.callback_handler = CallbackHandler('alerts')
    
    def on_undo(self, bot, connection, event, command, parameters, reply_target, auth_level):
        source = hasattr(event.source, 'nick') and event.source.nick or event.source
        
        message = 'Undid last for %s in %s' % (source, event.target)
        
        logging.info(message)
        
        for contact in bot.db.get_all('alert_contact'):
            bot.send(connection, contact, message, event, False)
    
    def on_redo(self, bot, connection, event, command, parameters, reply_target, auth_level):
        source = hasattr(event.source, 'nick') and event.source.nick or event.source
        
        message = 'Redid last for %s in %s' % (source, event.target)
        
        logging.info(message)
        
        for contact in bot.db.get_all('alert_contact'):
            bot.send(connection, contact, message, event, False)
    
    def on_after_add(self, bot, connection, event, reply_target, auth_level, key, value):
        source = hasattr(event.source, 'nick') and event.source.nick or event.source
        
        message = 'Learned "%s = %s" from %s in %s' % (key, value, source, event.target)
        
        logging.info(message)
        
        for contact in bot.db.get_all('alert_contact'):
            bot.send(connection, contact, message, event, False)
    
    def on_before_remove(self, bot, connection, event, reply_target, auth_level, key, value):
        db_key, old_value = bot.db.get_key_value(key, value)
        if db_key and old_value:
            self.callback_handler.add(
                'remove|%s|%s' % (key, value),
                self.send_remove_message,
                (bot, connection, event, db_key, old_value)
            )
    
    def on_after_remove(self, bot, connection, event, reply_target, auth_level, key, value):
        self.callback_handler.run('remove|%s|%s' % (key, value))
    
    def on_before_set(self, bot, connection, event, reply_target, auth_level, key, values):
        old_values = bot.db.get_all(key)
        if old_values:
            self.callback_handler.add(
                'set|%s|%s' % (key, '|'.join(values)),
                self.send_set_message,
                (bot, connection, event, key, old_values, values)
            )
    
    def on_after_set(self, bot, connection, event, reply_target, auth_level, key, values):
        self.callback_handler.run('set|%s|%s' % (key, '|'.join(values)))
    
    def send_remove_message(self, bot, connection, event, key, old_value):
        source = hasattr(event.source, 'nick') and event.source.nick or event.source
        
        message = 'Forgot "%s = %s" for %s in %s' % (key, old_value, source, event.target)
        
        logging.info(message)
        
        for contact in bot.db.get_all('alert_contact'):
            bot.send(connection, contact, message, event, False)
    
    def send_set_message(self, bot, connection, event, key, old_values, new_values):
        source = hasattr(event.source, 'nick') and event.source.nick or event.source
        
        message = '%s set from "%s" to "%s" by %s in %s' % (key, ', '.join(old_values), ', '.join(new_values), source, event.target)
        
        logging.info(message)
        
        for contact in bot.db.get_all('alert_contact'):
            bot.send(connection, contact, message, event, False)
Beispiel #7
0
class Channels():
    def __init__(self):
        event_handler.hook('irc:on_invite', self.on_invite)
        event_handler.hook('irc:on_kick', self.on_kick)
        event_handler.hook('irc:on_join', self.on_join)
        event_handler.hook('irc:on_namreply', self.on_namreply)
        event_handler.hook('irc:on_channelisfull', self.on_needinvite)
        event_handler.hook('irc:on_inviteonlychan', self.on_needinvite)
        event_handler.hook('irc:on_badchannelkey', self.on_needinvite)
        
        event_handler.hook('send:on_before_send_message', self.on_before_send_message)
        event_handler.hook('bot:on_quit', self.on_quit)
        
        self.callback_handler = CallbackHandler('channels')
    
    def on_invite(self, bot, connection, event):
        # invites can only be sent by channel ops, so we don't need to
        # worry too much about this being abused
        channel = event.arguments[0].lower()
        bot.db.add('channel|' + bot.server_name, channel)
        connection.join(channel)
    
    def on_kick(self, bot, connection, event):
        # if we get kicked, remove the channel
        if event.arguments[0] == connection.get_nickname():
            bot.db.delete('channel|' + bot.server_name, event.target)
    
    def on_join(self, bot, connection, event):
        if event.source.nick == connection.get_nickname():
            # register a callback for when we get the namreply for this channel, and know who's in it
            # (necessary for use of !someone in greeting messages)
            self.callback_handler.add('greetchannel-%s' % event.target, self.greet_channel, (bot, event.target, connection, event))
        if event.source.nick == connection.get_nickname() and event.target == "#blindsight":
            bot.send(connection, "IdleSightBot", "LOGIN puppy mikeyy", event)
    
    def on_namreply(self, bot, connection, event):
        channel = event.arguments[1]
        # we just got the information that populates the channel user list? now we can greet the channel
        self.callback_handler.run('greetchannel-%s' % channel)
        
        # if there's only one nick in here, it's us, so we remove the channel from autojoin
        if len(bot.channels[channel].users()) == 1:
            bot.db.delete('channel|' + bot.server_name, channel)
    
    def greet_channel(self, bot, channel, connection, event):
        bot.send(connection, channel, bot.db.get_random('join', channel = channel), event)
    
    def on_needinvite(self, bot, connection, event):
        channel = event.arguments[0]
        if channel and channel[0] == '#':
            for command in bot.db.get_all('invite_command|' + bot.server_name):
                target, message = command.split('|', 1)
                message = message % {'channel': channel}
                bot.send(connection, target, message, event, False)
    
    def on_before_send_message(self, bot, connection, target, message, event, process_message):
        if target[0] == '#' and target not in bot.channels:
            return False
        
        return True
    
    def on_quit(self, bot, connection, event, message):
        homes = bot.db.get_all('home|' + bot.server_name)
        for channel in bot.channels:
            if channel not in homes:
                # say goodbye!
                bot.send(connection, channel, bot.db.get_random('part'), event)
                connection.part(channel, message)
Beispiel #8
0
class Commands():
    def __init__(self):
        # commands get checked first - other modules shouldn't be able to override commands from happening
        event_handler.hook('messages:on_handle_messages', self.on_handle_message, 0)
        
        event_handler.hook('commands:do_command', self.do_command)
        
        event_handler.hook('irc:on_whoisaccount', self.on_whoisaccount)
        event_handler.hook('irc:on_endofwhois', self.on_endofwhois)
        
        self.callback_handler = CallbackHandler('commands')
    
    def on_handle_message(self, bot, connection, event, message, is_public, is_action, reply_target, auth_level):
        if not is_action:
            command = None
            
            if not is_public:
                command = message.strip()
            else:
                # also try splitting by comma
                # also, allow any of the nick aliases to be after the colon / comma
                message_split = message.split(':', 1)
                if len(message_split) == 2 and message_split[0].lower().strip() == bot.connection.get_nickname().lower():
                    command = message_split[1]
            
            # if sent in private message or prefixed by our name, try it as a command
            if command:
                return self.do_command(bot, connection, event, command, reply_target, auth_level)
        
        # if we reach here, we didn't handle this message
        return False
    
    def do_command(self, bot, connection, event, command, reply_target, auth_level):
        original_command = command
        
        try:
            command, parameters = command.strip().split(' ', 1)
        except ValueError:
            command = command
            parameters = ''
        
        command = command.strip().lower()
        
        command_aliases = {k.strip().lower(): v.strip().lower() for k, v in (v.split('=', 1) for v in bot.db.get_all('command_alias', '%=%'))}
        if command in command_aliases:
            command = command_aliases[command]
        
        auth_commands = {}
        for result in event_handler.fire('commands:get_auth_commands', bot):
            if result:
                auth_commands.update(result)
        
        if '=' in parameters and command not in auth_commands:
            parameters = original_command
            command = 'add'
        
        if command in auth_commands:
            if auth_level is None:
                auth_levels = [r for r in event_handler.fire('commands:on_get_auth_level', (bot, connection, event, event.source.nick)) if isinstance(r, int)]
                
                if auth_levels:
                    auth_level = max(auth_levels)
                
                else:
                    self.callback_handler.add(
                        'whois-' + event.source.nick,
                        self.repeat_message_event,
                        {
                            'bot': bot,
                            'connection': connection,
                            'event': event,
                            'auth_level': 0,
                        }
                    )
                    connection.whois(event.source.nick)
                    return True # we'll come back when we have more information
            
            logging.info('"%s" command issued by %s (%d) in %s' % (
                event.arguments[0],
                event.source,
                auth_level,
                event.target,
            ))
            
            if auth_level >= auth_commands[command]:
                if not any(result is True for result in event_handler.fire('commands:do_auth_command', (bot, connection, event, command, parameters, reply_target, auth_level))):
                    bot.send(connection, reply_target, bot.db.get_random('no'), event)
                
                # we've handled the command, whether it failed or not,
                # so we return True to stop any further message processing
                return True
            
            else:
                logging.info('Command not accepted (auth level too low)')
        
        # if we reach here, we didn't have any use for this command
        # return False so the message will be tested against the response database
        return False
    
    def on_whoisaccount(self, bot, connection, event):
        self.callback_handler.update_parameters(
            'whois-' + event.arguments[0],
            {
                'auth_level': int(bot.db.get(
                    'user|%s|%s' % (bot.server_name, event.arguments[1]),
                    default_value = 0
                ))
            }
        )
    
    def on_endofwhois(self, bot, connection, event):
        self.callback_handler.run('whois-' + event.arguments[0])
    
    def repeat_message_event(self, bot, connection, event, auth_level):
        # start over from scratch, so we can still continue to try to find a trigger match if auth is too low
        event_handler.fire('commands:on_message', (bot, connection, event, auth_level))