Refactors hooks registration

This commit is contained in:
nemunaire 2015-11-02 20:19:12 +01:00
commit f39a0eac56
40 changed files with 202 additions and 168 deletions

View file

@ -14,29 +14,54 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from nemubot.hooks.abstract import Abstract
from nemubot.hooks.command import Command
from nemubot.hooks.message import Message
last_registered = []
class hook:
last_registered = []
def hook(store, *args, **kargs):
"""Function used as a decorator for module loading"""
def sec(call):
last_registered.append((store, Message(call, *args, **kargs)))
return call
return sec
def _add(store, h, *args, **kwargs):
"""Function used as a decorator for module loading"""
def sec(call):
hook.last_registered.append((store, h(call, *args, **kwargs)))
return call
return sec
def add(store, *args, **kwargs):
return hook._add(store, Abstract, *args, **kwargs)
def ask(*args, store="in_DirectAsk", **kwargs):
return hook._add(store, Message, *args, **kwargs)
def command(*args, store="in_Command", **kwargs):
return hook._add(store, Command, *args, **kwargs)
def message(*args, store="in_Text", **kwargs):
return hook._add(store, Message, *args, **kwargs)
def post(*args, store="post", **kwargs):
return hook._add(store, Abstract, *args, **kwargs)
def pre(*args, store="pre", **kwargs):
return hook._add(store, Abstract, *args, **kwargs)
def reload():
global Message
import imp
import nemubot.hooks.abstract
imp.reload(nemubot.hooks.abstract)
import nemubot.hooks.command
imp.reload(nemubot.hooks.command)
import nemubot.hooks.message
imp.reload(nemubot.hooks.message)
Message = nemubot.hooks.message.Message
import nemubot.hooks.keywords
imp.reload(nemubot.hooks.keywords)

View file

@ -87,6 +87,10 @@ class Abstract:
return False
def __str__(self):
return ""
def can_write(self, receivers=list(), server=None):
return True

65
nemubot/hooks/command.py Normal file
View file

@ -0,0 +1,65 @@
# Nemubot is a smart and modulable IM bot.
# Copyright (C) 2012-2015 Mercier Pierre-Olivier
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import re
from nemubot.hooks.message import Message
from nemubot.hooks.keywords import NoKeyword
from nemubot.hooks.keywords.abstract import Abstract as AbstractKeywords
from nemubot.hooks.keywords.dict import Dict as DictKeywords
import nemubot.message
class Command(Message):
"""Class storing hook information, specialized for Command messages"""
def __init__(self, call, name=None, help_usage=dict(), keywords=NoKeyword(),
**kargs):
super().__init__(call=call, **kargs)
if isinstance(keywords, dict):
keywords = DictKeywords(keywords)
assert type(help_usage) is dict, help_usage
assert isinstance(keywords, AbstractKeywords), keywords
self.name = str(name) if name is not None else None
self.help_usage = help_usage
self.keywords = keywords
def __str__(self):
return "\x03\x02%s\x03\x02%s%s" % (
self.name if self.name is not None else "\x03\x1f" + self.regexp + "\x03\x1f" if self.regexp is not None else "",
" (restricted to %:%s)" % ((",".join(self.servers) if self.server else "*") + (",".join(self.channels) if self.channels else "*")) if len(self.channels) or len(self.servers) else "",
": %s" % self.help if self.help is not None else ""
)
def check(self, msg):
return self.keywords.check(msg.kwargs) and super().check(msg)
def match(self, msg):
if not isinstance(msg, nemubot.message.command.Command):
return False
else:
return (
(self.name is None or msg.cmd == self.name) and
(self.regexp is None or re.match(self.regexp, msg.cmd))
)

View file

@ -17,9 +17,6 @@
import re
from nemubot.hooks.abstract import Abstract
from nemubot.hooks.keywords import NoKeyword
from nemubot.hooks.keywords.abstract import Abstract as AbstractKeywords
from nemubot.hooks.keywords.dict import Dict as DictKeywords
import nemubot.message
@ -27,64 +24,26 @@ class Message(Abstract):
"""Class storing hook information, specialized for a generic Message"""
def __init__(self, call, name=None, regexp=None, channels=list(),
server=None, help=None, help_usage=dict(), keywords=NoKeyword(),
**kargs):
Abstract.__init__(self, call=call, **kargs)
if isinstance(keywords, dict):
keywords = DictKeywords(keywords)
def __init__(self, call, regexp=None, help=None, **kwargs):
super().__init__(call=call, **kwargs)
assert regexp is None or type(regexp) is str, regexp
assert channels is None or type(channels) is list, channels
assert server is None or type(server) is str, server
assert type(help_usage) is dict, help_usage
assert isinstance(keywords, AbstractKeywords), keywords
self.name = str(name) if name is not None else None
self.regexp = regexp
self.server = server
self.channels = channels
self.help = help
self.help_usage = help_usage
self.keywords = keywords
def __str__(self):
return "\x03\x02%s\x03\x02%s%s" % (
self.name if self.name is not None else "\x03\x1f" + self.regexp + "\x03\x1f" if self.regexp is not None else "",
" (restricted to %:%s)" % ((",".join(self.servers) if self.server else "*") + (",".join(self.channels) if self.channels else "*")) if len(self.channels) or len(self.server) else "",
": %s" % self.help if self.help is not None else ""
)
# TODO: find a way to name the feature (like command: help)
return self.help if self.help is not None else super().__str__()
def check(self, msg):
return not hasattr(msg, "kwargs") or self.keywords.check(msg.kwargs)
return super().check(msg)
def match(self, msg, server=None):
if not isinstance(msg, nemubot.message.abstract.Abstract):
return True
elif isinstance(msg, nemubot.message.Command):
return self.is_matching(msg.cmd, msg.to, server)
elif isinstance(msg, nemubot.message.Text):
return self.is_matching(msg.message, msg.to, server)
else:
def match(self, msg):
if not isinstance(msg, nemubot.message.text.Text):
return False
def is_matching(self, strcmp, receivers=list(), server=None):
"""Test if the current hook correspond to the message"""
if ((server is None or self.server is None or self.server == server)
and ((self.name is None or strcmp == self.name) and (
self.regexp is None or re.match(self.regexp, strcmp)))):
if receivers and self.channels:
for receiver in receivers:
if receiver in self.channels:
return True
else:
return True
return False
else:
return self.regexp is None or re.match(self.regexp, msg.message)