From 88de1be8d21a6ac7e715ad2d4cc3779f56558e51 Mon Sep 17 00:00:00 2001 From: dpedu Date: Sat, 8 Aug 2015 22:50:04 -0700 Subject: [PATCH] Add simplified style hook arguments --- docs/module_guide/_module_guide.rst | 57 ++++++++++++++++++++++------ examples/data/modules/EchoExample.py | 7 +++- pyircbot/irccore.py | 26 ++++++++++++- 3 files changed, 76 insertions(+), 14 deletions(-) diff --git a/docs/module_guide/_module_guide.rst b/docs/module_guide/_module_guide.rst index 4bbb8f1..0c25ad3 100644 --- a/docs/module_guide/_module_guide.rst +++ b/docs/module_guide/_module_guide.rst @@ -45,19 +45,29 @@ Then, a handler for this hook: .. code-block:: python - def echo(self, args, prefix, trailing): + def echo(self, event): -The handler is passed the data sent by the irc server. What these are can vary, -but the format is the same. ``args`` is the list of arguments the IRC server -sent. ``prefix`` is the sender. ``trailing`` is arbitrary data associated with -the event. In the case of PRIVMSG: args has one entry - the channel name or -nick the message was in/from. Prefix is a user's nick string, in the format of: -NickName!username@ip. Trailing is message content. Since the module describe -above echos messages, let's do that: +The handler is passed and IRCEvent object containing the data sent by the irc +server. The values of these are can vary, but the format is alwaysthe same. + +``event.args`` is the list of arguments the IRC server sent. ``event.prefix`` +is the sender, parsed. ``trailing`` is arbitrary data associated +with the event. In the case of PRIVMSG: args has one entry - the channel name +or nick the message was in/from. + +Prefix is an ``UserPrefix`` object with the properties ``event.prefix.nick``, +``event.prefix.username``, ``event.prefix.hostname``, and the original unparsed +prefix, ``event.prefix.str``. + +Prefix may also be a ``ServerPrefix`` object, if the hook is for an IRC method +that interacts with the server directly, such as PING. It would have the +properties ``event.prefix.hostname`` and ``event.prefix.str``. + +Since the module described above echos messages, let's do that: .. code-block:: python - self.bot.act_PRIVMSG(args[0], trailing) + self.bot.act_PRIVMSG(event.args[0], event.trailing) This sends a PRIVMSG to the originating channel or nick, with the same msg content that was received. @@ -88,8 +98,8 @@ EchoExample module print(self.config) self.hooks=[ModuleHook("PRIVMSG", self.echo)] - def echo(self, args, prefix, trailing): - self.bot.act_PRIVMSG(args[0], trailing) + def echo(self, event): + self.bot.act_PRIVMSG(event.args[0], event.trailing) def ondisable(self): print("I'm getting unloaded!") @@ -101,6 +111,31 @@ In usage: 4:40:17 PM test 4:40:17 PM test +New Style Module Hooks +---------------------- + +Instead of receiving the values of the IRC event a module is responding to in +3 separate arguments, hooks can receive them as one object. The hook system +will automatically determine which argument style to use. + +The reason for this change is to eliminate some unnecessary code in modules. +Any module that looks at a user's nick or hostname may find itself doing +something like this in every hook: + +.. code-block:: python + + def saynick(self, args, prefix, trailing): + prefixObj = self.bot.decodePrefix(prefix) + self.bot.act_PRIVMSG(args[0], "Hello, %s. You are connecting from %s" % (prefixObj.nick, prefixObj.hostname)) + +With the new style, one line can be eliminated, as the passed ``IRCEvent`` +event has the prefix already parsed: + +.. code-block:: python + + def saynick(self, event): + self.bot.act_PRIVMSG(event.args[0], "Hello, %s. You are connecting from %s" % (event.prefix.nick, event.prefix.hostname)) + Advanced Usage ============== diff --git a/examples/data/modules/EchoExample.py b/examples/data/modules/EchoExample.py index ebb65cb..17c1c10 100644 --- a/examples/data/modules/EchoExample.py +++ b/examples/data/modules/EchoExample.py @@ -7,8 +7,11 @@ class EchoExample(ModuleBase): print(self.config) self.hooks=[ModuleHook("PRIVMSG", self.echo)] - def echo(self, args, prefix, trailing): - self.bot.act_PRIVMSG(args[0], trailing) + def echo(self, event): + print(event) + print(repr(event)) + print(dir(event)) + self.bot.act_PRIVMSG(event.args[0], event.trailing) def ondisable(self): print("I'm getting unloaded!") \ No newline at end of file diff --git a/pyircbot/irccore.py b/pyircbot/irccore.py index 6a62373..b63e6ff 100644 --- a/pyircbot/irccore.py +++ b/pyircbot/irccore.py @@ -12,6 +12,7 @@ import asyncore import logging import traceback import sys +from inspect import getargspec from socket import SHUT_RDWR try: @@ -225,7 +226,11 @@ class IRCCore(asynchat.async_chat): for hook in self.hookcalls[command]: try: - hook(args, prefix, trailing) + if len(getargspec(hook).args) == 2: + hook(IRCCore.packetAsObject(args, prefix, trailing)) + else: + hook(args, prefix, trailing) + except: self.log.warning("Error processing hook: \n%s"% self.trace()) @@ -259,6 +264,23 @@ class IRCCore(asynchat.async_chat): self.log.warning("Invalid hook - %s" % command) return False + def packetAsObject(args, prefix, trailing): + """Given an irc message's args, prefix, and trailing data return an object with these properties + + :param args: list of args from the IRC packet + :type args: list + :param prefix: prefix object parsed from the IRC packet + :type prefix: ServerPrefix or UserPrefix + :param trailing: trailing data from the IRC packet + :type trailing: str + :returns: object -- a IRCEvent object with the ``args``, ``prefix``, ``trailing``""" + + return type('IRCEvent', (object,), { + "args": args, + "prefix": IRCCore.decodePrefix(prefix), + "trailing": trailing + }) + " Utility methods " @staticmethod def decodePrefix(prefix): @@ -269,11 +291,13 @@ class IRCCore(asynchat.async_chat): :returns: object -- an UserPrefix object with the properties `nick`, `username`, `hostname` or a ServerPrefix object with the property `hostname`""" if "!" in prefix: ob = type('UserPrefix', (object,), {}) + ob.str = prefix ob.nick, prefix = prefix.split("!") ob.username, ob.hostname = prefix.split("@") return ob else: ob = type('ServerPrefix', (object,), {}) + ob.str = prefix ob.hostname = prefix return ob