Support highlights as command triggers too
This commit is contained in:
parent
c3e14a8d0d
commit
f7990667eb
|
@ -74,26 +74,36 @@ class TouchReload(Thread):
|
||||||
sleep(self.sleep)
|
sleep(self.sleep)
|
||||||
|
|
||||||
|
|
||||||
def messageHasCommand(command, message, requireArgs=False):
|
def messageHasCommand(command, message, requireArgs=False, withHighlight=False):
|
||||||
"""Check if a message has a command with or without args in it
|
"""
|
||||||
|
Check if a message has a command with or without args in it
|
||||||
|
|
||||||
:param command: the command string to look for, like !ban. If a list is passed, the first match is returned.
|
:param command: the command string to look for, like !ban. If a list is passed, the first match is returned.
|
||||||
:type command: str or list
|
:type command: str or list
|
||||||
:param message: the message string to look in, like "!ban Lil_Mac"
|
:param message: the message string to look in, like "!ban Lil_Mac"
|
||||||
:type message: str
|
:type message: str
|
||||||
:param requireArgs: if true, only validate if the command use has any amount of trailing text
|
:param requireArgs: only match if trailing data is passed with the command used. False-like values disable This
|
||||||
:type requireArgs: bool"""
|
requirement. True-like values require any number of args greater than one. Int values require a specific number
|
||||||
|
of args
|
||||||
|
:type requireArgs: bool
|
||||||
|
:param withHighlight: if provided, treat 'Nick[:,] command args' the same as '.command args' where Nick is a string
|
||||||
|
provided by withHighlight
|
||||||
|
:type withHighlight: str
|
||||||
|
"""
|
||||||
|
|
||||||
if not type(command) == list:
|
if not type(command) == list:
|
||||||
command = [command]
|
command = [command]
|
||||||
for item in command:
|
for item in command:
|
||||||
cmd = messageHasCommandSingle(item, message, requireArgs)
|
cmd = messageHasCommandSingle(item, message, requireArgs, withHighlight)
|
||||||
if cmd:
|
if cmd:
|
||||||
return cmd
|
return cmd
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def messageHasCommandSingle(command, message, requireArgs=False):
|
def messageHasCommandSingle(command, message, requireArgs=False, withHighlight=False):
|
||||||
|
if withHighlight:
|
||||||
|
if message.startswith(withHighlight + ": ") or message.startswith(withHighlight + ", "):
|
||||||
|
message = "." + message[len(withHighlight) + 2:]
|
||||||
# Check if the message at least starts with the command
|
# Check if the message at least starts with the command
|
||||||
messageBeginning = message[0:len(command)]
|
messageBeginning = message[0:len(command)]
|
||||||
if messageBeginning != command:
|
if messageBeginning != command:
|
||||||
|
@ -108,13 +118,16 @@ def messageHasCommandSingle(command, message, requireArgs=False):
|
||||||
args = ""
|
args = ""
|
||||||
if argsStart > 0:
|
if argsStart > 0:
|
||||||
args = message[argsStart + 1:].strip()
|
args = message[argsStart + 1:].strip()
|
||||||
|
args_list = args.split()
|
||||||
if requireArgs and args == '':
|
if requireArgs:
|
||||||
return False
|
if args == '':
|
||||||
|
return False
|
||||||
|
elif type(requireArgs) is int and len(args_list) != requireArgs:
|
||||||
|
return False
|
||||||
|
|
||||||
# Verified! Return the set.
|
# Verified! Return the set.
|
||||||
return ParsedCommand(command,
|
return ParsedCommand(command,
|
||||||
args.split(" ") if args else [],
|
args_list,
|
||||||
args,
|
args,
|
||||||
message)
|
message)
|
||||||
|
|
||||||
|
|
|
@ -58,6 +58,8 @@ class IRCCore(object):
|
||||||
self.bind_addr = None
|
self.bind_addr = None
|
||||||
"""Optionally bind to a specific address. This should be a (host, port) tuple."""
|
"""Optionally bind to a specific address. This should be a (host, port) tuple."""
|
||||||
|
|
||||||
|
self.nick = None
|
||||||
|
|
||||||
# Set up hooks for modules
|
# Set up hooks for modules
|
||||||
self.initHooks()
|
self.initHooks()
|
||||||
|
|
||||||
|
|
|
@ -197,10 +197,13 @@ class command(hook):
|
||||||
|
|
||||||
:param keywords: commands to listen for
|
:param keywords: commands to listen for
|
||||||
:type keywords: str
|
:type keywords: str
|
||||||
:param require_args: only match if trailing data is passed with the command used
|
:param require_args: only match if trailing data is passed with the command used. False-like values disable This
|
||||||
:type require_args: bool
|
requirement. True-like values require any number of args greater than one. Int values require a specific
|
||||||
|
number of args
|
||||||
|
:type require_args: bool, int
|
||||||
:param allow_private: enable matching in private messages
|
:param allow_private: enable matching in private messages
|
||||||
:type allow_private: bool
|
:type allow_private: bool
|
||||||
|
:param allow_highlight: treat 'Nick[:,] command args' the same as '.command args'
|
||||||
"""
|
"""
|
||||||
|
|
||||||
prefix = "."
|
prefix = "."
|
||||||
|
@ -208,12 +211,12 @@ class command(hook):
|
||||||
Hotkey that must appear before commands
|
Hotkey that must appear before commands
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, *keywords, require_args=False, allow_private=False):
|
def __init__(self, *keywords, require_args=False, allow_private=False, allow_highlight=True):
|
||||||
super().__init__("PRIVMSG")
|
super().__init__("PRIVMSG")
|
||||||
self.keywords = keywords
|
self.keywords = keywords
|
||||||
self.require_args = require_args
|
self.require_args = require_args
|
||||||
self.allow_private = allow_private
|
self.allow_private = allow_private
|
||||||
self.parsed_cmd = None
|
self.allow_highlight = allow_highlight
|
||||||
|
|
||||||
def validate(self, msg, bot):
|
def validate(self, msg, bot):
|
||||||
"""
|
"""
|
||||||
|
@ -224,19 +227,23 @@ class command(hook):
|
||||||
:param bot: reference to main pyircbot
|
:param bot: reference to main pyircbot
|
||||||
:type bot: pyircbot.pyircbot.PyIRCBot
|
:type bot: pyircbot.pyircbot.PyIRCBot
|
||||||
"""
|
"""
|
||||||
|
bot_nick = bot.get_nick()
|
||||||
if not super().validate(msg, bot):
|
if not super().validate(msg, bot):
|
||||||
return False
|
return False
|
||||||
if msg.args[0][0] != "#" and not self.allow_private:
|
if msg.args[0][0] != "#" and not self.allow_private:
|
||||||
return False
|
return False
|
||||||
for keyword in self.keywords:
|
for keyword in self.keywords:
|
||||||
single = self._validate_one(msg, keyword)
|
single = self._validate_prefixedcommand(msg, keyword, bot_nick)
|
||||||
if single:
|
if single:
|
||||||
|
print(single)
|
||||||
return single
|
return single
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def _validate_one(self, msg, keyword):
|
def _validate_prefixedcommand(self, msg, keyword, nick):
|
||||||
with_prefix = "{}{}".format(self.prefix, keyword)
|
with_prefix = "{}{}".format(self.prefix, keyword)
|
||||||
return messageHasCommand(with_prefix, msg.trailing, requireArgs=self.require_args)
|
return messageHasCommand(with_prefix, msg.trailing,
|
||||||
|
requireArgs=self.require_args,
|
||||||
|
withHighlight=nick if self.allow_highlight else False)
|
||||||
|
|
||||||
|
|
||||||
class regex(hook):
|
class regex(hook):
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
|
|
||||||
from pyircbot.modulebase import ModuleBase, command
|
from pyircbot.modulebase import ModuleBase, command
|
||||||
from pyircbot.modules.ModInfo import info
|
from pyircbot.modules.ModInfo import info
|
||||||
from pyircbot.common import messageHasCommand
|
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
import time
|
import time
|
||||||
import hashlib
|
import hashlib
|
||||||
|
|
|
@ -18,16 +18,8 @@ class LMGTFY(ModuleBase):
|
||||||
@info("lmgtfy <term> display a condescending internet query", cmds=["lmgtfy"])
|
@info("lmgtfy <term> display a condescending internet query", cmds=["lmgtfy"])
|
||||||
@command("lmgtfy", require_args=True)
|
@command("lmgtfy", require_args=True)
|
||||||
def handleMessage(self, msg, cmd):
|
def handleMessage(self, msg, cmd):
|
||||||
message = msg.trailing.split(" ")[1:]
|
link = self.createLink(cmd.args_str)
|
||||||
link = self.createLink(message)
|
self.bot.act_PRIVMSG(msg.args[0], "{}: {}".format(msg.prefix.nick, link))
|
||||||
self.bot.act_PRIVMSG(msg.args[0], "%s: %s" % (msg.prefix.nick, link))
|
|
||||||
|
|
||||||
def createLink(self, message):
|
def createLink(self, message):
|
||||||
finalUrl = BASE_URL
|
return BASE_URL + "+".join([urllib.parse.quote(word) for word in message.split()])
|
||||||
|
|
||||||
for word in message:
|
|
||||||
finalUrl += urllib.parse.quote(word)
|
|
||||||
if word != message[-1]:
|
|
||||||
finalUrl += "+"
|
|
||||||
|
|
||||||
return finalUrl
|
|
||||||
|
|
|
@ -3,4 +3,4 @@
|
||||||
export PYTHONUNBUFFERED=1
|
export PYTHONUNBUFFERED=1
|
||||||
export PYTHONPATH=.
|
export PYTHONPATH=.
|
||||||
|
|
||||||
py.test --fulltrace --cov=pyircbot --cov-report html -n 4 tests/
|
py.test --fulltrace --cov=pyircbot --cov-report html -n 4 tests/ $@
|
||||||
|
|
|
@ -50,6 +50,9 @@ class FakeBaseBot(PrimitiveBot):
|
||||||
super().unloadmodule(module_name)
|
super().unloadmodule(module_name)
|
||||||
self._modules.remove(module_name)
|
self._modules.remove(module_name)
|
||||||
|
|
||||||
|
def get_nick(self):
|
||||||
|
return "testbot"
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def fakebot(tmpdir):
|
def fakebot(tmpdir):
|
||||||
|
|
|
@ -14,3 +14,8 @@ def googbot(fakebot):
|
||||||
def test_lmgtfy_basic(googbot):
|
def test_lmgtfy_basic(googbot):
|
||||||
googbot.feed_line(".lmgtfy foobar asdf")
|
googbot.feed_line(".lmgtfy foobar asdf")
|
||||||
googbot.act_PRIVMSG.assert_called_once_with('#test', 'chatter: http://lmgtfy.com/?q=foobar+asdf')
|
googbot.act_PRIVMSG.assert_called_once_with('#test', 'chatter: http://lmgtfy.com/?q=foobar+asdf')
|
||||||
|
|
||||||
|
|
||||||
|
def test_lmgtfy_highlight(googbot):
|
||||||
|
googbot.feed_line("{}: lmgtfy foobar asdf".format(googbot.get_nick()))
|
||||||
|
googbot.act_PRIVMSG.assert_called_once_with('#test', 'chatter: http://lmgtfy.com/?q=foobar+asdf')
|
||||||
|
|
Loading…
Reference in New Issue