Implement command help system
This commit is contained in:
parent
5c8f6b02fd
commit
2f88dc28c6
|
@ -0,0 +1,31 @@
|
||||||
|
:mod:`ModInfo` --- Module command help system
|
||||||
|
=============================================
|
||||||
|
|
||||||
|
Implements global `help` and `helpindex` commands that print help information about all available modules. Modules must
|
||||||
|
import and use a decorator from this module. For example:
|
||||||
|
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from pyircbot.modules.ModInfo import info
|
||||||
|
|
||||||
|
# ...
|
||||||
|
|
||||||
|
@info("help [command] show the manual for all or [commands]", cmds=["help"])
|
||||||
|
@command("help")
|
||||||
|
def cmd_help(self, msg, cmd):
|
||||||
|
# ...
|
||||||
|
|
||||||
|
|
||||||
|
The `info` decorator takes a mandatory string parameter describing the command. The second, optional, list parameter
|
||||||
|
`cmds` is a list of short names thart are aliases for the function that aide in help lookup. In all cases, the cases,
|
||||||
|
commands will be prefixed with the default command prefix (`from pyircbot.modulebase.command.prefix`).
|
||||||
|
|
||||||
|
|
||||||
|
Class Reference
|
||||||
|
---------------
|
||||||
|
|
||||||
|
.. automodule:: pyircbot.modules.ModInfo
|
||||||
|
:members:
|
||||||
|
:undoc-members:
|
||||||
|
:show-inheritance:
|
|
@ -93,7 +93,6 @@ Client sending a message that the bot will relay
|
||||||
|
|
||||||
pyircbot_send default privmsg ["#clonebot", "asdf1234"]
|
pyircbot_send default privmsg ["#clonebot", "asdf1234"]
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
Example Programs
|
Example Programs
|
||||||
----------------
|
----------------
|
||||||
|
|
|
@ -251,9 +251,6 @@ class regex(hook):
|
||||||
def cmd_foobar(self, matches, msg):
|
def cmd_foobar(self, matches, msg):
|
||||||
print("Someone's message was exactly "foobar" ({}) in channel {}".format(msg.message, msg.args[0]))
|
print("Someone's message was exactly "foobar" ({}) in channel {}".format(msg.message, msg.args[0]))
|
||||||
|
|
||||||
This stores a list of IRC actions each function is tagged for in method.__tag_regexes. This attribute is scanned
|
|
||||||
during module init and appropriate hooks are set up.
|
|
||||||
|
|
||||||
:param regexps: expressions to match for
|
:param regexps: expressions to match for
|
||||||
:type keywords: str
|
:type keywords: str
|
||||||
:param allow_private: enable matching in private messages
|
:param allow_private: enable matching in private messages
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
|
|
||||||
from pyircbot.modulebase import ModuleBase, ModuleHook, MissingDependancyException, regex, command
|
from pyircbot.modulebase import ModuleBase, ModuleHook, MissingDependancyException, regex, command
|
||||||
|
from pyircbot.modules.ModInfo import info
|
||||||
import datetime
|
import datetime
|
||||||
import time
|
import time
|
||||||
import math
|
import math
|
||||||
|
@ -79,6 +80,7 @@ class Calc(ModuleBase):
|
||||||
seconds = int(remaining - (minutes * 60))
|
seconds = int(remaining - (minutes * 60))
|
||||||
return "Please wait %s minute(s) and %s second(s)." % (minutes, seconds)
|
return "Please wait %s minute(s) and %s second(s)." % (minutes, seconds)
|
||||||
|
|
||||||
|
@info("quote [key[ =[ value]]] set or update facts", cmds=["quote"])
|
||||||
@regex(r'(?:^\.?(?:calc|quote)(?:\s+?(?:([^=]+)(?:\s?(=)\s?(.+)?)?)?)?)', types=['PRIVMSG'])
|
@regex(r'(?:^\.?(?:calc|quote)(?:\s+?(?:([^=]+)(?:\s?(=)\s?(.+)?)?)?)?)', types=['PRIVMSG'])
|
||||||
def cmd_calc(self, message, match):
|
def cmd_calc(self, message, match):
|
||||||
word, changeit, value = match.groups()
|
word, changeit, value = match.groups()
|
||||||
|
|
|
@ -0,0 +1,81 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
"""
|
||||||
|
.. module::ModInfo
|
||||||
|
:synopsis: Provides manpage-like info for commands
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
from pyircbot.modulebase import ModuleBase, command
|
||||||
|
|
||||||
|
|
||||||
|
class info(object):
|
||||||
|
"""
|
||||||
|
Decorator for tagging module methods with help text
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
from pyircbot.modules.ModInfo import info
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
@info("help [command] show the manual for all or [commands]", cmds=["help", "rtfm"])
|
||||||
|
@command("help")
|
||||||
|
def cmd_help(self, msg, cmd):
|
||||||
|
...
|
||||||
|
|
||||||
|
:param docstring: command help formatted as above
|
||||||
|
:type docstring: str
|
||||||
|
:param cmds: enable command names or aliases this function implements, as a list of strings. E.g. if the "help"
|
||||||
|
command has the alias "rtfm"
|
||||||
|
:type cmds: list
|
||||||
|
"""
|
||||||
|
def __init__(self, docstring, cmds=None):
|
||||||
|
self.docstring = docstring
|
||||||
|
self.commands = cmds or []
|
||||||
|
|
||||||
|
def __call__(self, func):
|
||||||
|
setattr(func, "irchelp", self.docstring)
|
||||||
|
setattr(func, "irchelpc", self.commands)
|
||||||
|
return func
|
||||||
|
|
||||||
|
|
||||||
|
class ModInfo(ModuleBase):
|
||||||
|
|
||||||
|
@info("help [command] show the manual for all or [commands]", cmds=["help"])
|
||||||
|
@command("help")
|
||||||
|
def cmd_help(self, msg, cmd):
|
||||||
|
"""
|
||||||
|
Get help on a command
|
||||||
|
"""
|
||||||
|
if cmd.args:
|
||||||
|
for modname, module, helptext, helpcommands in self.iter_modules():
|
||||||
|
if cmd.args[0] in ["{}{}".format(command.prefix, i) for i in helpcommands]:
|
||||||
|
self.bot.act_PRIVMSG(msg.args[0], "RTFM: {}: {}".format(cmd.args[0], helptext))
|
||||||
|
else:
|
||||||
|
for modname, module, helptext, helpcommands in self.iter_modules():
|
||||||
|
self.bot.act_PRIVMSG(msg.args[0], "{}: {}{}".format(modname, command.prefix, helptext))
|
||||||
|
|
||||||
|
@command("helpindex")
|
||||||
|
def cmd_helpindex(self, msg, cmd):
|
||||||
|
"""
|
||||||
|
Short index of commands
|
||||||
|
"""
|
||||||
|
commands = []
|
||||||
|
for modname, module, helptext, helpcommands in self.iter_modules():
|
||||||
|
commands += ["{}{}".format(command.prefix, i) for i in helpcommands]
|
||||||
|
|
||||||
|
self.bot.act_PRIVMSG(msg.args[0], "{}: commands: {}".format(msg.prefix.nick, ", ".join(commands)))
|
||||||
|
|
||||||
|
def iter_modules(self):
|
||||||
|
"""
|
||||||
|
Iterator that cycles through module methods that are tagged with help information. The iterator yields tuples
|
||||||
|
of:
|
||||||
|
|
||||||
|
(module_name, module_object, helptext, command_list)
|
||||||
|
"""
|
||||||
|
for modname, module in self.bot.moduleInstances.items():
|
||||||
|
for attr_name in dir(module):
|
||||||
|
attr = getattr(module, attr_name)
|
||||||
|
if callable(attr) and hasattr(attr, "irchelp"):
|
||||||
|
yield (modname, module, getattr(attr, "irchelp"), getattr(attr, "irchelpc"), )
|
||||||
|
raise StopIteration()
|
|
@ -7,7 +7,9 @@
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from pyircbot.modulebase import ModuleBase, ModuleHook
|
from pyircbot.modules.ModInfo import info
|
||||||
|
from pyircbot.modulebase import ModuleBase, command, hook
|
||||||
|
from contextlib import closing
|
||||||
import sqlite3
|
import sqlite3
|
||||||
import time
|
import time
|
||||||
|
|
||||||
|
@ -15,7 +17,6 @@ import time
|
||||||
class Seen(ModuleBase):
|
class Seen(ModuleBase):
|
||||||
def __init__(self, bot, moduleName):
|
def __init__(self, bot, moduleName):
|
||||||
ModuleBase.__init__(self, bot, moduleName)
|
ModuleBase.__init__(self, bot, moduleName)
|
||||||
self.hooks = [ModuleHook("PRIVMSG", self.lastSeen)]
|
|
||||||
# if the database doesnt exist, it will be created
|
# if the database doesnt exist, it will be created
|
||||||
sql = self.getSql()
|
sql = self.getSql()
|
||||||
c = sql.cursor()
|
c = sql.cursor()
|
||||||
|
@ -27,31 +28,32 @@ class Seen(ModuleBase):
|
||||||
c.execute("CREATE TABLE `seen` (`nick` VARCHAR(32), `date` INTEGER, PRIMARY KEY(`nick`))")
|
c.execute("CREATE TABLE `seen` (`nick` VARCHAR(32), `date` INTEGER, PRIMARY KEY(`nick`))")
|
||||||
self.x = "asdf"
|
self.x = "asdf"
|
||||||
|
|
||||||
def lastSeen(self, args, prefix, trailing):
|
@hook("PRIVMSG")
|
||||||
|
def recordSeen(self, message, command):
|
||||||
# using a message to update last seen, also, the .seen query
|
# using a message to update last seen, also, the .seen query
|
||||||
prefixObj = self.bot.decodePrefix(prefix)
|
|
||||||
nick = prefixObj.nick
|
|
||||||
sql = self.getSql()
|
|
||||||
c = sql.cursor()
|
|
||||||
# update or add the user's row
|
|
||||||
datest = str(time.time() + (int(self.config["add_hours"]) * 60 * 60))
|
datest = str(time.time() + (int(self.config["add_hours"]) * 60 * 60))
|
||||||
c.execute("REPLACE INTO `seen` (`nick`, `date`) VALUES (?, ?)", (nick.lower(), datest))
|
sql = self.getSql()
|
||||||
# self.log.info("Seen: %s on %s" % (nick.lower(), datest))
|
with closing(sql.cursor()) as c:
|
||||||
sql.commit()
|
# update or add the user's row
|
||||||
if trailing.startswith(".seen"):
|
c.execute("REPLACE INTO `seen` (`nick`, `date`) VALUES (?, ?)", (message.prefix.nick.lower(), datest))
|
||||||
cmdargs = trailing.split(" ")
|
# self.log.info("Seen: %s on %s" % (nick.lower(), datest))
|
||||||
|
sql.commit()
|
||||||
|
|
||||||
|
@info("seen <nick> print last time user was seen", cmds=["seen"])
|
||||||
|
@command("seen", require_args=True)
|
||||||
|
def lastSeen(self, message, command):
|
||||||
|
sql = self.getSql()
|
||||||
|
searchnic = command.args[0].lower()
|
||||||
|
with closing(sql.cursor()) as c:
|
||||||
# query the DB for the user
|
# query the DB for the user
|
||||||
if len(cmdargs) >= 2:
|
c.execute("SELECT * FROM `seen` WHERE `nick`= ? ", [searchnic])
|
||||||
searchnic = cmdargs[1].lower()
|
rows = c.fetchall()
|
||||||
c.execute("SELECT * FROM `seen` WHERE `nick`= ? ", [searchnic])
|
if len(rows) == 1:
|
||||||
rows = c.fetchall()
|
self.bot.act_PRIVMSG(message.args[0], "I last saw %s on %s (%s)." %
|
||||||
if len(rows) == 1:
|
(command.args[0], time.strftime("%m/%d/%y at %I:%M %p",
|
||||||
self.bot.act_PRIVMSG(args[0], "I last saw %s on %s (%s)." %
|
time.localtime(rows[0]['date'])), self.config["timezone"]))
|
||||||
(cmdargs[1], time.strftime("%m/%d/%y at %I:%M %p",
|
else:
|
||||||
time.localtime(rows[0]['date'])), self.config["timezone"]))
|
self.bot.act_PRIVMSG(message.args[0], "Sorry, I haven't seen %s!" % command.args[0])
|
||||||
else:
|
|
||||||
self.bot.act_PRIVMSG(args[0], "Sorry, I haven't seen %s!" % cmdargs[1])
|
|
||||||
c.close()
|
|
||||||
|
|
||||||
def getSql(self):
|
def getSql(self):
|
||||||
# return a SQL reference to the database
|
# return a SQL reference to the database
|
||||||
|
@ -66,9 +68,3 @@ class Seen(ModuleBase):
|
||||||
for idx, col in enumerate(cursor.description):
|
for idx, col in enumerate(cursor.description):
|
||||||
d[col[0]] = row[idx]
|
d[col[0]] = row[idx]
|
||||||
return d
|
return d
|
||||||
|
|
||||||
def test(self, arg):
|
|
||||||
print("TEST: %s" % arg)
|
|
||||||
print("self.x = %s" % self.x)
|
|
||||||
return arg
|
|
||||||
|
|
||||||
|
|
|
@ -369,14 +369,14 @@ class PyIRCBot(object):
|
||||||
argsStart = len(command)
|
argsStart = len(command)
|
||||||
args = ""
|
args = ""
|
||||||
if argsStart > 0:
|
if argsStart > 0:
|
||||||
args = message[argsStart + 1:]
|
args = message[argsStart + 1:].strip()
|
||||||
|
|
||||||
if requireArgs and args.strip() == '':
|
if requireArgs and args == '':
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# Verified! Return the set.
|
# Verified! Return the set.
|
||||||
return ParsedCommand(command,
|
return ParsedCommand(command,
|
||||||
args.split(" "),
|
args.split(" ") if args else [],
|
||||||
args,
|
args,
|
||||||
message)
|
message)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue