# ÂŠī¸ Dan Gazizullin, 2021-2023
# This file is a part of Hikka Userbot
# đ https://github.com/hikariatama/Hikka
# You can redistribute it and/or modify it under the terms of the GNU AGPLv3
# đ https://www.gnu.org/licenses/agpl-3.0.html
import difflib
import inspect
import logging
from hikkatl.extensions.html import CUSTOM_EMOJIS
from hikkatl.tl.types import Message
from .. import loader, utils
from ..compat.dragon import DRAGON_EMOJI
from ..types import DragonModule
logger = logging.getLogger(__name__)
@loader.tds
class HelpMod(loader.Module):
"""Shows help for modules and commands"""
strings = {"name": "Help"}
def __init__(self):
self.config = loader.ModuleConfig(
loader.ConfigValue(
"core_emoji",
"âĒī¸",
lambda: "Core module bullet",
validator=loader.validators.Emoji(length=1),
),
loader.ConfigValue(
"plain_emoji",
"âĢī¸",
lambda: "Plain module bullet",
validator=loader.validators.Emoji(length=1),
),
loader.ConfigValue(
"empty_emoji",
"đ",
lambda: "Empty modules bullet",
validator=loader.validators.Emoji(length=1),
),
)
@loader.command()
async def helphide(self, message: Message):
if not (modules := utils.get_args(message)):
await utils.answer(message, self.strings("no_mod"))
return
currently_hidden = self.get("hide", [])
hidden, shown = [], []
for module in filter(
lambda module: self.lookup(module, include_dragon=True), modules
):
module = self.lookup(module, include_dragon=True)
module = (
module.name
if isinstance(module, DragonModule)
else module.__class__.__name__
)
if module in currently_hidden:
currently_hidden.remove(module)
shown += [module]
else:
currently_hidden += [module]
hidden += [module]
self.set("hide", currently_hidden)
await utils.answer(
message,
self.strings("hidden_shown").format(
len(hidden),
len(shown),
"\n".join([f"đâđ¨ {m}" for m in hidden]),
"\n".join([f"đ {m}" for m in shown]),
),
)
def find_aliases(self, command: str) -> list:
"""Find aliases for command"""
aliases = []
_command = self.allmodules.commands[command]
if getattr(_command, "alias", None) and not (
aliases := getattr(_command, "aliases", None)
):
aliases = [_command.alias]
return aliases or []
async def modhelp(self, message: Message, args: str):
exact = True
if not (module := self.lookup(args, include_dragon=True)):
if method := self.allmodules.dispatch(
args.lower().strip(self.get_prefix())
)[1]:
module = method.__self__
else:
module = self.lookup(
next(
(
reversed(
sorted(
[
module.strings["name"]
for module in self.allmodules.modules
],
key=lambda x: difflib.SequenceMatcher(
None,
args.lower(),
x,
).ratio(),
)
)
),
None,
)
)
exact = False
is_dragon = isinstance(module, DragonModule)
try:
name = module.strings("name")
except (KeyError, AttributeError):
name = getattr(module, "name", "ERROR")
_name = (
"{} (v{}.{}.{})".format(
utils.escape_html(name),
module.__version__[0],
module.__version__[1],
module.__version__[2],
)
if hasattr(module, "__version__")
else utils.escape_html(name)
)
reply = "{} {}:".format(
(
DRAGON_EMOJI
if is_dragon
else "đ"
),
_name,
)
if module.__doc__:
reply += (
"\nâšī¸ "
+ utils.escape_html(inspect.getdoc(module))
+ "\n"
)
commands = (
module.commands
if is_dragon
else {
name: func
for name, func in module.commands.items()
if await self.allmodules.check_security(message, func)
}
)
if hasattr(module, "inline_handlers") and not is_dragon:
for name, fun in module.inline_handlers.items():
reply += (
"\nđ¤"
" {}
{}".format(
f"@{self.inline.bot_username} {name}",
(
utils.escape_html(inspect.getdoc(fun))
if fun.__doc__
else self.strings("undoc")
),
)
)
for name, fun in commands.items():
reply += (
"\nâĢī¸"
" {}{}
{} {}".format(
utils.escape_html(self.get_prefix("dragon" if is_dragon else None)),
name,
(
" ({})".format(
", ".join(
"{}{}
".format(
utils.escape_html(
self.get_prefix("dragon" if is_dragon else None)
),
alias,
)
for alias in self.find_aliases(name)
)
)
if self.find_aliases(name)
else ""
),
(
utils.escape_html(fun)
if is_dragon
else (
utils.escape_html(inspect.getdoc(fun))
if fun.__doc__
else self.strings("undoc")
)
),
)
)
await utils.answer(
message,
reply
+ (f"\n\n{self.strings('not_exact')}" if not exact else "")
+ (
f"\n\n{self.strings('core_notice')}"
if module.__origin__.startswith("{}".format(self.config["empty_emoji"], name)
]
continue
core = mod.__origin__.startswith("{}".format(
self.config["core_emoji"] if core else self.config["plain_emoji"], name
)
first = True
commands = [
name
for name, func in mod.commands.items()
if await self.allmodules.check_security(message, func) or force
]
for cmd in commands:
if first:
tmp += f": ( {cmd}"
first = False
else:
tmp += f" | {cmd}"
icommands = [
name
for name, func in mod.inline_handlers.items()
if await self.inline.check_inline_security(
func=func,
user=message.sender_id,
)
or force
]
for cmd in icommands:
if first:
tmp += f": ( đ¤ {cmd}"
first = False
else:
tmp += f" | đ¤ {cmd}"
if commands or icommands:
tmp += " )"
if core:
core_ += [tmp]
else:
plain_ += [tmp]
elif not shown_warn and (mod.commands or mod.inline_handlers):
reply = (
"You have permissions to execute only these"
f" commands\n{reply}"
)
shown_warn = True
plain_.sort(key=lambda x: x.split()[1])
core_.sort(key=lambda x: x.split()[1])
no_commands_.sort(key=lambda x: x.split()[1])
dragon_.sort()
await utils.answer(
message,
"{}\n{}{}".format(
reply,
"".join(core_ + plain_ + dragon_ + (no_commands_ if force else [])),
(
""
if self.lookup("Loader").fully_loaded
else f"\n\n{self.strings('partial_load')}"
),
),
)
@loader.command()
async def support(self, message):
if message.out:
await self.request_join("@hikka_talks", self.strings("request_join"))
await utils.answer(
message,
self.strings("support").format(
(
utils.get_platform_emoji()
if self._client.hikka_me.premium and CUSTOM_EMOJIS
else "đ"
)
),
)