forked from zuckerberg/dailybot
		
	
		
			
				
	
	
		
			204 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			204 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| # coding=utf-8
 | |
| 
 | |
| # Help Module for drastikbot modules.
 | |
| #
 | |
| # This module provides help messages for the loaded drastikbot modules.
 | |
| #
 | |
| # Usage
 | |
| # -----
 | |
| # Calling the command without arguments returns a list of all the
 | |
| # loaded modules with help information.  Example: .help
 | |
| #
 | |
| # Giving the name of a module as an argument returns the available
 | |
| # bot_commands of that module.  Example: .help text
 | |
| #
 | |
| # Giving the name of a module followed by one of its bot_commands
 | |
| # returns a help message of that command:  Example: .help text ae
 | |
| #
 | |
| # API
 | |
| # ---
 | |
| # To  provide help  messages through  this module  other modules  must
 | |
| # include  the manual  variable  in  their Module  class.  If no  such
 | |
| # variable is provided the module will be unlisted.
 | |
| 
 | |
| 
 | |
| # Copyright (C) 2021 drastik.org
 | |
| #
 | |
| # This file is part of drastikbot.
 | |
| #
 | |
| # 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, version 3 only.
 | |
| #
 | |
| # 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 <https://www.gnu.org/licenses/>.
 | |
| 
 | |
| 
 | |
| import itertools
 | |
| 
 | |
| 
 | |
| class Module:
 | |
|     def __init__(self):
 | |
|         self.commands = ["help"]
 | |
| 
 | |
| 
 | |
| def get_module_object(i, module_name):
 | |
|     # drastikbot v2.2
 | |
|     if hasattr(i, "mod"):
 | |
|         for mod_object, mod_path in i.mod["modules_d"].values():
 | |
|             if mod_path.stem == module_name:
 | |
|                 return mod_object
 | |
| 
 | |
|     # drastikbot v2.1
 | |
|     if hasattr(i, "modules") and module_name in i.modules:
 | |
|         return i.modules[module_name]
 | |
| 
 | |
|     return None
 | |
| 
 | |
| 
 | |
| def hidden_status(i, module_name: str) -> bool:
 | |
|     """Is ``module'' a hidden module?"""
 | |
| 
 | |
|     module_object = get_module_object(i, module_name)
 | |
|     if module_object is None:
 | |
|         return True  # Module not found
 | |
| 
 | |
|     if not hasattr(module_object, "Module"):
 | |
|         return True  # No Module class, it's hidden
 | |
| 
 | |
|     if hasattr(module_object.Module(), "manual"):
 | |
|         return module_object.Module().manual
 | |
|     elif hasattr(module_object.Module(), "helpmsg"):  # Old method
 | |
|         if "__hidden__" in  module_object.Module().helpmsg:
 | |
|             return "hidden"
 | |
| 
 | |
| 
 | |
| def is_hidden(i, module_name):
 | |
|     return hidden_status(i, module_name) == "hidden"
 | |
| 
 | |
| 
 | |
| def module_checks(i, irc, module):
 | |
|     if module not in i.modules.keys():
 | |
|         irc.notice(i.channel, f"Help: `{module}' is not an imported module.")
 | |
|         return False
 | |
| 
 | |
|     try:
 | |
|         module_bl = irc.var.modules_obj["blacklist"][module]
 | |
|         if module_bl and i.channel in module_bl:
 | |
|             irc.notice(i.channel, f"Help: This module has been disabled.")
 | |
|             return False
 | |
|     except KeyError:
 | |
|         pass  # No blacklist, move on
 | |
| 
 | |
|     try:
 | |
|         module_wl = irc.var.modules_obj["whitelist"][module]
 | |
|         if module_wl and i.channel not in module_wl:
 | |
|             irc.notice(i.channel, f"Help: This module has been disabled.")
 | |
|             return False
 | |
|     except KeyError:
 | |
|         pass  # No whitelist, move on
 | |
| 
 | |
|     module_c = i.modules[module].Module()
 | |
|     if not hasattr(module_c, "manual"):
 | |
|         irc.notice(i.channel, "Help: This module does not have a manual.")
 | |
|         return False
 | |
| 
 | |
|     return True
 | |
| 
 | |
| def module_help(i, irc, module):
 | |
|     if not module_checks(i, irc, module):
 | |
|         return
 | |
| 
 | |
|     module_c = i.modules[module].Module()
 | |
| 
 | |
|     commands = ""
 | |
|     if hasattr(module_c, "commands"):
 | |
|         commands = ", ".join(module_c.commands)
 | |
|         commands = f"Commands: {commands} | "
 | |
| 
 | |
|     info = ""
 | |
|     if "desc" in module_c.manual:
 | |
|         info = module_c.manual["desc"]
 | |
|         info = f"Info: {info}"
 | |
| 
 | |
|     t = f"\x0311{module}\x0F: {commands}{info}"
 | |
|     t += f" | Use: {i.cmd_prefix}help <module> <command> for command info."
 | |
|     irc.notice(i.channel, t)
 | |
| 
 | |
| 
 | |
| def command_help(i, irc, module, command):
 | |
|     if not module_checks(i, irc, module):
 | |
|         return
 | |
| 
 | |
|     module_c = i.modules[module].Module()
 | |
| 
 | |
|     if not hasattr(module_c, "commands"):
 | |
|         irc.notice(i.channel, "Help: This module does not provide commands.")
 | |
|         return
 | |
| 
 | |
|     if "bot_commands" not in module_c.manual:
 | |
|         irc.notice(i.channel, "Help: No manual entry for this command ")
 | |
|         return
 | |
| 
 | |
|     command_manual = module_c.manual["bot_commands"]
 | |
| 
 | |
|     if command not in command_manual:
 | |
|         irc.notice(i.channel, "Help: No manual entry for this command.")
 | |
|         return
 | |
| 
 | |
|     command_entry = command_manual[command]
 | |
| 
 | |
|     t = []
 | |
| 
 | |
|     if "usage" in command_entry:
 | |
|         usage = command_entry["usage"](i.cmd_prefix)
 | |
|         usage = f"Usage: {usage}"
 | |
|         t.append(usage)
 | |
| 
 | |
|     if "info" in command_entry:
 | |
|         info = command_entry["info"]
 | |
|         info = f"Info: {info}"
 | |
|         t.append(info)
 | |
| 
 | |
|     if "alias" in command_entry:
 | |
|         alias = ", ".join(command_entry["alias"])
 | |
|         alias = f"Aliases: {alias}"
 | |
|         t.append(alias)
 | |
| 
 | |
|     t = " | ".join(t)
 | |
|     t = f"{command}: {t}"
 | |
|     irc.notice(i.channel, t)
 | |
| 
 | |
| 
 | |
| def module_list(i, irc):
 | |
|     m1 = filter(lambda x: not is_hidden(i, x) and i.whitelist(x, i.channel) \
 | |
|                           and not i.blacklist(x, i.channel),
 | |
|                set(i.command_dict.values()))
 | |
|     m2 = filter(lambda x: not is_hidden(i, x) and i.whitelist(x, i.channel) \
 | |
|                           and not i.blacklist(x, i.channel) and not x in m1,
 | |
|                i.auto_list)
 | |
|     m = itertools.chain(m1, m2)
 | |
|     t = "Help: " + ", ".join(sorted(m))
 | |
|     t += f" | Use: {i.cmd_prefix}help <module> for module info."
 | |
|     irc.notice(i.channel, t)
 | |
| 
 | |
| 
 | |
| def main(i, irc):
 | |
|     if i.msg_nocmd:
 | |
|         argv = i.msg_nocmd.split()
 | |
|         argc = len(argv)
 | |
|         if argc == 1:
 | |
|             module_help(i, irc, argv[0])
 | |
|         elif argc == 2:
 | |
|             command_help(i, irc, argv[0], argv[1])
 | |
|         else:
 | |
|             m = f"Usage: {i.cmd_prefix}help [module] [command]"
 | |
|             irc.notice(i.channel, m)
 | |
|     else:
 | |
|         module_list(i, irc)
 |