Ejemplo n.º 1
0
    def init(self, **kwargs):
        # Default Settings
        prop_defaults = {
            "nick": "pancakesbot",
            "network": "irc.slashnet.org",
            "port": 6667,
            "channels": ["#bots"],
            "plugins": ["admin"],
            "plugins_path": "plugins",
            "command_prefix": "~",
            "storage_path": "storage",
        }
        self.__dict__.update(prop_defaults)
        # Overwrite defaults with kwargs
        if kwargs:
            self.__dict__.update(kwargs)

        self.terminate = False
        self.storage_path = os.path.abspath(self.storage_path)

        # Add a logger
        self.logger = logging.getLogger(__name__)

        # Message Queue used by plugins, as to avoid kicks for flooding.
        self.msg_queue = []
        # Global mesasge queue timer, only activated when there are messages
        # to process.
        self.queue_timer = None

        # Add TCPClient and IRC to the system.
        TCPClient(channel=self.channel).register(self)
        IRC(channel=self.channel).register(self)

        # Creates an instance of UserManager
        self.logger.debug("Initializing user manager.")
        user_db_file = os.path.join(self.storage_path, "users-{}.db".format(self.network))
        if not os.path.exists(self.storage_path):
            os.makedirs(self.storage_path)
        self.user_mngr = UserManager(self, user_db_file)
        self.user_mngr.register(self)

        # Add plugins directory to path
        self.logger.debug("Initializing plugin manager.")
        self.plugins_path = os.path.abspath(self.plugins_path)
        if not os.path.exists(self.plugins_path):
            os.makedirs(self.plugins_path)
        sys.path.append(self.plugins_path)
        # Keeps track of plugins and commands
        self.plugin_mngr = PluginManager(self, self.command_prefix, os.path.basename(self.plugins_path)).register(self)
        for plugin in self.plugins:
            self.plugin_mngr.load(plugin)

        # Send Keepalive PING every 5 minutes
        Timer(300.0, Event.create("keepalive"), persist=True).register(self)
Ejemplo n.º 2
0
class PancakesBot(Component):

    channel = "pancakesbot"

    def init(self, **kwargs):
        # Default Settings
        prop_defaults = {
            "nick": "pancakesbot",
            "network": "irc.slashnet.org",
            "port": 6667,
            "channels": ["#bots"],
            "plugins": ["admin"],
            "plugins_path": "plugins",
            "command_prefix": "~",
            "storage_path": "storage",
        }
        self.__dict__.update(prop_defaults)
        # Overwrite defaults with kwargs
        if kwargs:
            self.__dict__.update(kwargs)

        self.terminate = False
        self.storage_path = os.path.abspath(self.storage_path)

        # Add a logger
        self.logger = logging.getLogger(__name__)

        # Message Queue used by plugins, as to avoid kicks for flooding.
        self.msg_queue = []
        # Global mesasge queue timer, only activated when there are messages
        # to process.
        self.queue_timer = None

        # Add TCPClient and IRC to the system.
        TCPClient(channel=self.channel).register(self)
        IRC(channel=self.channel).register(self)

        # Creates an instance of UserManager
        self.logger.debug("Initializing user manager.")
        user_db_file = os.path.join(self.storage_path, "users-{}.db".format(self.network))
        if not os.path.exists(self.storage_path):
            os.makedirs(self.storage_path)
        self.user_mngr = UserManager(self, user_db_file)
        self.user_mngr.register(self)

        # Add plugins directory to path
        self.logger.debug("Initializing plugin manager.")
        self.plugins_path = os.path.abspath(self.plugins_path)
        if not os.path.exists(self.plugins_path):
            os.makedirs(self.plugins_path)
        sys.path.append(self.plugins_path)
        # Keeps track of plugins and commands
        self.plugin_mngr = PluginManager(self, self.command_prefix, os.path.basename(self.plugins_path)).register(self)
        for plugin in self.plugins:
            self.plugin_mngr.load(plugin)

        # Send Keepalive PING every 5 minutes
        Timer(300.0, Event.create("keepalive"), persist=True).register(self)

    def enqueue_msg(self, target, message):
        if self.queue_timer:
            self.msg_queue.append((target, message))
        else:
            self.fire(PRIVMSG(target, message))
            self.queue_timer = Timer(1.0, Event.create("process_queue"), persist=True).register(self)

    def process_queue(self):
        if self.msg_queue:
            msg = self.msg_queue[0]
            self.fire(PRIVMSG(msg[0], msg[1]))
            self.msg_queue.pop(0)
        if not self.msg_queue:
            self.queue_timer.unregister()
            self.queue_timer = None

    def keepalive(self):
        timestamp = int(time() * 1000)
        self.logger.debug("PING: {}".format(timestamp))
        self.fire(request(Message("PING", "LAG{0}".format(timestamp))))

    @handler("signal", channels="*")
    def signal(self, signo, stack):
        if signo in (SIGINT, SIGTERM):
            self.fire(QUIT("Received SIGTERM, terminating..."))
            self.fire(events.terminate())

    #######################################################
    # Event Handlers                                      #
    # These handle events and fire the pancakesbot events #
    #######################################################

    @handler("privmsg")
    def _on_text(self, user, target, message):
        user += (self.user_mngr.get_user_id(user),)
        if (message.startswith("\x01ACTION ")) and (message[-1] == "\x01"):
            message = message[7:]
            self.logger.debug("ACTION: {}({})@{}: {}".format(user[0], user[3], target, message))
            self.fire(events.on_action(user, target, message), "plugins")
        else:
            self.logger.debug("MSG: {}({})@{}: {}".format(user[0], user[3], target, message))
            self.fire(events.on_text(user, target, message), "plugins")

    @handler("ready")
    def _on_ready(self, component):
        self.logger.info("Ready. " "Connecting to {0.network}:{0.port}".format(self))
        self.fire(connect(self.network, self.port))

    @handler("connected")
    def _on_connected(self, network, port):
        self.logger.info("Connected. Signing in as {0.nick}".format(self))
        self.fire(NICK(self.nick))
        self.fire(USER("pancakes", "pancakes", network, "robot"))
        self.fire(events.on_logon(network, port), "plugins")

    @handler("disconnected")
    def _on_disconnected(self):
        self.logger.info("Disconnected.")
        self.fire(events.on_disconnect(), "plugins")
        if self.terminate:
            raise SystemExit(0)
        else:
            self.logger.info("Reconnecting.")
            self.fire(events.on_reconnect(), "plugins")
            self.fire(connect(self.network, self.port))

    @handler("terminate")
    def _on_terminate(self):
        self.terminate = True
        self.fire(events.on_exit(), "plugins")
        self.logger.info("Terminating.")
        raise SystemExit(0)

    @handler("join")
    def _on_join(self, user, channel):
        # Send a who for channel on join
        if user[0] == self.nick:
            self.fire(WHO(channel))

        user += (self.user_mngr.get_user_id(user),)
        self.fire(events.on_join(user, channel), "plugins")
        self.logger.info("JOIN: {} ({}) to {}".format(user[0], user[3], channel))

    @handler("part")
    def _on_part(self, user, channel, *args):
        if args:
            message = args[0]
        else:
            message = ""
        user += (self.user_mngr.get_user_id(user),)
        self.fire(events.on_part(user, channel, message), "plugins")
        self.logger.debug("PART: {} ({}) from {} ({})".format(user[0], user[3], channel, message))

    @handler("quit")
    def _on_quit(self, user, *args):
        if args:
            message = args[0]
        else:
            message = ""
        user += (self.user_mngr.get_user_id(user),)
        self.fire(events.on_quit(user, message), "plugins")
        self.logger.debug("QUIT: {} ({})".format(user[0], user[3], message))

    @handler("notice")
    def _on_notice(self, user, target, message):
        user += (self.user_mngr.get_user_id(user),)
        self.fire(events.on_notice(user, target, message), "plugins")
        self.logger.debug("NOTICE: {}@{}: {}".format(user[0], target, message))

    @handler("invite")
    def _on_invite(self, nickname, channel):
        user = self.user_mngr.get_full_user(nick=nickname)
        self.fire(events.on_invite(user, channel), "plugins")
        self.logger.info("INVITE: {} ({}) invited us to {}.".format(user[0], user[3], channel))

    @handler("kick")
    def _on_kick(self, user, channel, target, message):
        user += (self.user_mngr.get_user_id(user),)
        target = self.user_mngr.get_full_user(nick=target)
        self.fire(events.on_kick(user, target, channel, message), "plugins")
        self.logger.debug(
            "KICK: {} ({}) kicked {} ({}) from {} ({})".format(user[0], user[3], target[0], target[3], channel, message)
        )

    @handler("mode")
    def _on_mode(self, user, target, mode, *args):
        if mode == "+b":
            user += (self.user_mngr.get_user_id(user),)
            self.fire(events.on_ban(user, args[0], target), "plugins")
            self.logger.debug("BAN: {} banned {} from {}".format(user[0], args[0], target))
        elif mode == "-b":
            user += (self.user_mngr.get_user_id(user),)
            self.fire(events.on_unban(user, args[0], target), "plugins")
            self.logger.debug("UNBAN: {} unbanned {} from {}".format(user[0], args[0], target))
        elif mode == "+v":
            user += (self.user_mngr.get_user_id(user),)
            t_user = self.user_mngr.get_full_user(nick=args[0])
            self.fire(events.on_voice(user, t_user, target), "plugins")
            self.logger.debug("VOICE: {} gave voice " "to {} in {}".format(user[0], t_user[0], target))
        elif mode == "-v":
            user += (self.user_mngr.get_user_id(user),)
            t_user = self.user_mngr.get_full_user(nick=args[0])
            self.fire(events.on_devoice(user, t_user, target), "plugins")
            self.logger.debug("DEVOICE: {} removed voice " "from {} in {}".format(user[0], t_user[0], target))
        elif mode == "+o":
            user += (self.user_mngr.get_user_id(user),)
            t_user = self.user_mngr.get_full_user(nick=args[0])
            self.fire(events.on_op(user, t_user, target), "plugins")
            self.logger.debug("OP: {} gave operator " "to {} in {}".format(user[0], t_user[0], target))
        elif mode == "-o":
            user += (self.user_mngr.get_user_id(user),)
            t_user = self.user_mngr.get_full_user(nick=args[0])
            self.fire(events.on_deop(user, t_user, target), "plugins")
            self.logger.debug("DEOP: {} removed operator " "from {} in {}".format(user[0], t_user[0], target))
        elif mode == "+q":
            user += (self.user_mngr.get_user_id(user),)
            t_user = self.user_mngr.get_full_user(nick=args[0])
            self.fire(events.on_owner(user, t_user, target), "plugins")
            self.logger.debug("OWNER: {} gave owner " "to {} in {}".format(user[0], t_user[0], target))
        elif mode == "-q":
            user += (self.user_mngr.get_user_id(user),)
            t_user = self.user_mngr.get_full_user(nick=args[0])
            self.fire(events.on_deowner(user, t_user, target), "plugins")
            self.logger.debug("DEOWNER: {} removed owner " "from {} in {}".format(user[0], t_user[0], target))
        elif target.startswith("#"):
            user += (self.user_mngr.get_user_id(user),)
            self.fire(events.on_mode(user, mode, target), "plugins")
            self.logger.debug("MODE: {} set {} in {} ({})".format(user[0], mode, target, args))

    @handler("nick")
    def _on_nick(self, user, new_nick):
        self.user_mngr.changed_nick(user, new_nick)
        user += (self.user_mngr.get_user_id(user),)
        self.fire(events.on_nick(user, new_nick), "plugins")
        self.logger.debug("NICK: {} ({}) changed nick to {}".format(user[0], user[3], new_nick))

    @handler("topic")
    def _on_topic(self, user, channel, topic):
        user += (self.user_mngr.get_user_id(user),)
        self.logger.debug('TOPIC: {} ({}) changed topic of {} to "{}"'.format(user[0], user[3], channel, topic))

    @handler("numeric")
    def _on_numeric(self, source, numeric, *args):
        self.logger.debug("NUMERIC: {} - {}".format(numeric, ", ".join(args)))

        if numeric == ERR_NICKNAMEINUSE:
            # Change Nick if in use
            newnick = "{0:s}_".format(args[1])
            self.nick = newnick
            self.fire(NICK(newnick))
        if numeric == RPL_WHOREPLY:
            print(args)
            user = (args[5], args[2], args[3])
            user += (self.user_mngr.get_user_id(user),)
            print(user)
        elif numeric in (RPL_ENDOFMOTD, ERR_NOMOTD):
            self.fire(events.on_connect(self.network, self.port), "plugins")
            for chan in self.channels:
                self.fire(JOIN(chan))

    # Used to test handlers to determine arguments
    @handler("test")
    def _gen_handler(self, *args, **kwargs):
        if args:
            for arg in args:
                self.logger.info("from args: {}".format(arg))
        if kwargs:
            for key, value in kwargs:
                self.logger.info("from kwargs: {} == {}".format(key, value))