Browse Source

Support highlights as command triggers too

dave/xdcc
dave 4 years ago
parent
commit
f7990667eb
  1. 33
      pyircbot/common.py
  2. 2
      pyircbot/irccore.py
  3. 21
      pyircbot/modulebase.py
  4. 1
      pyircbot/modules/CryptoWallet.py
  5. 14
      pyircbot/modules/LMGTFY.py
  6. 2
      run-tests.sh
  7. 3
      tests/lib.py
  8. 5
      tests/modules/test_lmgtfy.py

33
pyircbot/common.py

@ -74,26 +74,36 @@ class TouchReload(Thread):
sleep(self.sleep)
def messageHasCommand(command, message, requireArgs=False):
"""Check if a message has a command with or without args in it
def messageHasCommand(command, message, requireArgs=False, withHighlight=False):
"""
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.
:type command: str or list
:param message: the message string to look in, like "!ban Lil_Mac"
:type message: str
:param requireArgs: if true, only validate if the command use has any amount of trailing text
:type requireArgs: bool"""
:param requireArgs: only match if trailing data is passed with the command used. False-like values disable This
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:
command = [command]
for item in command:
cmd = messageHasCommandSingle(item, message, requireArgs)
cmd = messageHasCommandSingle(item, message, requireArgs, withHighlight)
if cmd:
return cmd
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
messageBeginning = message[0:len(command)]
if messageBeginning != command:
@ -108,13 +118,16 @@ def messageHasCommandSingle(command, message, requireArgs=False):
args = ""
if argsStart > 0:
args = message[argsStart + 1:].strip()
if requireArgs and args == '':
return False
args_list = args.split()
if requireArgs:
if args == '':
return False
elif type(requireArgs) is int and len(args_list) != requireArgs:
return False
# Verified! Return the set.
return ParsedCommand(command,
args.split(" ") if args else [],
args_list,
args,
message)

2
pyircbot/irccore.py

@ -58,6 +58,8 @@ class IRCCore(object):
self.bind_addr = None
"""Optionally bind to a specific address. This should be a (host, port) tuple."""
self.nick = None
# Set up hooks for modules
self.initHooks()

21
pyircbot/modulebase.py

@ -197,10 +197,13 @@ class command(hook):
:param keywords: commands to listen for
:type keywords: str
:param require_args: only match if trailing data is passed with the command used
:type require_args: bool
:param require_args: only match if trailing data is passed with the command used. False-like values disable This
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
:type allow_private: bool
:param allow_highlight: treat 'Nick[:,] command args' the same as '.command args'
"""
prefix = "."
@ -208,12 +211,12 @@ class command(hook):
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")
self.keywords = keywords
self.require_args = require_args
self.allow_private = allow_private
self.parsed_cmd = None
self.allow_highlight = allow_highlight
def validate(self, msg, bot):
"""
@ -224,19 +227,23 @@ class command(hook):
:param bot: reference to main pyircbot
:type bot: pyircbot.pyircbot.PyIRCBot
"""
bot_nick = bot.get_nick()
if not super().validate(msg, bot):
return False
if msg.args[0][0] != "#" and not self.allow_private:
return False
for keyword in self.keywords:
single = self._validate_one(msg, keyword)
single = self._validate_prefixedcommand(msg, keyword, bot_nick)
if single:
print(single)
return single
return False
def _validate_one(self, msg, keyword):
def _validate_prefixedcommand(self, msg, keyword, nick):
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):

1
pyircbot/modules/CryptoWallet.py

@ -9,7 +9,6 @@
from pyircbot.modulebase import ModuleBase, command
from pyircbot.modules.ModInfo import info
from pyircbot.common import messageHasCommand
from decimal import Decimal
import time
import hashlib

14
pyircbot/modules/LMGTFY.py

@ -18,16 +18,8 @@ class LMGTFY(ModuleBase):
@info("lmgtfy <term> display a condescending internet query", cmds=["lmgtfy"])
@command("lmgtfy", require_args=True)
def handleMessage(self, msg, cmd):
message = msg.trailing.split(" ")[1:]
link = self.createLink(message)
self.bot.act_PRIVMSG(msg.args[0], "%s: %s" % (msg.prefix.nick, link))
link = self.createLink(cmd.args_str)
self.bot.act_PRIVMSG(msg.args[0], "{}: {}".format(msg.prefix.nick, link))
def createLink(self, message):
finalUrl = BASE_URL
for word in message:
finalUrl += urllib.parse.quote(word)
if word != message[-1]:
finalUrl += "+"
return finalUrl
return BASE_URL + "+".join([urllib.parse.quote(word) for word in message.split()])

2
run-tests.sh

@ -3,4 +3,4 @@
export PYTHONUNBUFFERED=1
export PYTHONPATH=.
py.test --fulltrace --cov=pyircbot --cov-report html -n 4 tests/
py.test --fulltrace --cov=pyircbot --cov-report html -n 4 tests/ $@

3
tests/lib.py

@ -50,6 +50,9 @@ class FakeBaseBot(PrimitiveBot):
super().unloadmodule(module_name)
self._modules.remove(module_name)
def get_nick(self):
return "testbot"
@pytest.fixture
def fakebot(tmpdir):

5
tests/modules/test_lmgtfy.py

@ -14,3 +14,8 @@ def googbot(fakebot):
def test_lmgtfy_basic(googbot):
googbot.feed_line(".lmgtfy 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…
Cancel
Save