123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408 |
- # █ █ ▀ █▄▀ ▄▀█ █▀█ ▀
- # █▀█ █ █ █ █▀█ █▀▄ █
- # © Copyright 2022
- # https://t.me/hikariatama
- #
- # 🔒 Licensed under the GNU AGPLv3
- # 🌐 https://www.gnu.org/licenses/agpl-3.0.html
- import difflib
- import inspect
- import logging
- from telethon.tl.functions.channels import JoinChannelRequest
- from telethon.tl.types import Message
- from .. import loader, security, utils
- logger = logging.getLogger(__name__)
- @loader.tds
- class HelpMod(loader.Module):
- """Help module, made specifically for Hikka with <3"""
- strings = {
- "name": "Help",
- "bad_module": "<b>🚫 <b>Module</b> <code>{}</code> <b>not found</b>",
- "single_mod_header": "🌑 <b>{}</b>:",
- "single_cmd": "\n▫️ <code>{}{}</code> {}",
- "undoc_cmd": "🦥 No docs",
- "all_header": "🌘 <b>{} mods available, {} hidden:</b>",
- "mod_tmpl": "\n{} <code>{}</code>",
- "first_cmd_tmpl": ": ( {}",
- "cmd_tmpl": " | {}",
- "no_mod": "🚫 <b>Specify module to hide</b>",
- "hidden_shown": "🌘 <b>{} modules hidden, {} modules shown:</b>\n{}\n{}",
- "ihandler": "\n🎹 <code>{}</code> {}",
- "undoc_ihandler": "🦥 No docs",
- "joined": (
- "🌘 <b>Joined the</b> <a href='https://t.me/hikka_talks'>support chat</a>"
- ),
- "join": "🌘 <b>Join the</b> <a href='https://t.me/hikka_talks'>support chat</a>",
- "partial_load": (
- "⚠️ <b>Userbot is not fully loaded, so not all modules are shown</b>"
- ),
- "not_exact": (
- "⚠️ <b>No exact match occured, so the closest result is shown instead</b>"
- ),
- }
- strings_ru = {
- "bad_module": "<b>🚫 <b>Модуль</b> <code>{}</code> <b>не найден</b>",
- "single_mod_header": "🌑 <b>{}</b>:",
- "single_cmd": "\n▫️ <code>{}{}</code> {}",
- "undoc_cmd": "🦥 Нет описания",
- "all_header": "🌘 <b>{} модулей доступно, {} скрыто:</b>",
- "mod_tmpl": "\n{} <code>{}</code>",
- "first_cmd_tmpl": ": ( {}",
- "cmd_tmpl": " | {}",
- "no_mod": "🚫 <b>Укажи модуль(-и), которые нужно скрыть</b>",
- "hidden_shown": "🌘 <b>{} модулей скрыто, {} модулей показано:</b>\n{}\n{}",
- "ihandler": "\n🎹 <code>{}</code> {}",
- "undoc_ihandler": "🦥 Нет описания",
- "joined": (
- "🌘 <b>Вступил в</b> <a href='https://t.me/hikka_talks'>чат помощи</a>"
- ),
- "join": "🌘 <b>Вступи в</b> <a href='https://t.me/hikka_talks'>чат помощи</a>",
- "_cmd_doc_helphide": (
- "<модуль(-и)> - Скрывает модуль(-и) из помощи\n*Разделяй имена модулей"
- " пробелами"
- ),
- "_cmd_doc_help": "[модуль] [-f] - Показывает помощь",
- "_cmd_doc_support": "Вступает в чат помощи Hikka",
- "_cls_doc": "Модуль помощи, сделанный специально для Hikka <3",
- "partial_load": (
- "⚠️ <b>Юзербот еще не загрузился полностью, поэтому показаны не все"
- " модули</b>"
- ),
- "not_exact": (
- "⚠️ <b>Точного совпадения не нашлось, поэтому было выбрано наиболее"
- " подходящее</b>"
- ),
- }
- def __init__(self):
- self.config = loader.ModuleConfig(
- loader.ConfigValue(
- "core_emoji",
- "▪️",
- lambda: "Core module bullet",
- validator=loader.validators.String(length=1),
- ),
- loader.ConfigValue(
- "hikka_emoji",
- "🌘",
- lambda: "Hikka-only module bullet",
- validator=loader.validators.String(length=1),
- ),
- loader.ConfigValue(
- "plain_emoji",
- "▫️",
- lambda: "Plain module bullet",
- validator=loader.validators.String(length=1),
- ),
- loader.ConfigValue(
- "empty_emoji",
- "👁🗨",
- lambda: "Empty modules bullet",
- validator=loader.validators.String(length=1),
- ),
- )
- async def helphidecmd(self, message: Message):
- """<module or modules> - Hide module(-s) from help
- *Split modules by spaces"""
- modules = utils.get_args(message)
- if not modules:
- await utils.answer(message, self.strings("no_mod"))
- return
- mods = [
- i.strings["name"]
- for i in self.allmodules.modules
- if hasattr(i, "strings") and "name" in i.strings
- ]
- modules = list(filter(lambda module: module in mods, modules))
- currently_hidden = self.get("hide", [])
- hidden, shown = [], []
- for module in modules:
- 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"👁🗨 <i>{m}</i>" for m in hidden]),
- "\n".join([f"👁 <i>{m}</i>" for m in shown]),
- ),
- )
- async def modhelp(self, message: Message, args: str):
- exact = True
- try:
- module = next(
- mod
- for mod in self.allmodules.modules
- if mod.strings("name").lower() == args.lower()
- )
- except Exception:
- module = None
- if not module:
- args = args.lower()
- args = args[1:] if args.startswith(self.get_prefix()) else args
- if args in self.allmodules.commands:
- module = self.allmodules.commands[args].__self__
- if not module:
- module_name = next( # skipcq: PTC-W0063
- reversed(
- sorted(
- [module.strings["name"] for module in self.allmodules.modules],
- key=lambda x: difflib.SequenceMatcher(
- None,
- args.lower(),
- x,
- ).ratio(),
- )
- )
- )
- module = next( # skipcq: PTC-W0063
- module
- for module in self.allmodules.modules
- if module.strings["name"] == module_name
- )
- exact = False
- try:
- name = module.strings("name")
- except KeyError:
- name = getattr(module, "name", "ERROR")
- reply = self.strings("single_mod_header").format(utils.escape_html(name))
- if module.__doc__:
- reply += "<i>\nℹ️ " + utils.escape_html(inspect.getdoc(module)) + "\n</i>"
- commands = {
- name: func
- for name, func in module.commands.items()
- if await self.allmodules.check_security(message, func)
- }
- if hasattr(module, "inline_handlers"):
- for name, fun in module.inline_handlers.items():
- reply += self.strings("ihandler").format(
- f"@{self.inline.bot_username} {name}",
- (
- utils.escape_html(inspect.getdoc(fun))
- if fun.__doc__
- else self.strings("undoc_ihandler")
- ),
- )
- for name, fun in commands.items():
- reply += self.strings("single_cmd").format(
- self.get_prefix(),
- name,
- (
- utils.escape_html(inspect.getdoc(fun))
- if fun.__doc__
- else self.strings("undoc_cmd")
- ),
- )
- await utils.answer(
- message, f"{reply}\n\n{'' if exact else self.strings('not_exact')}"
- )
- @loader.unrestricted
- async def helpcmd(self, message: Message):
- """[module] [-f] - Show help"""
- args = utils.get_args_raw(message)
- force = False
- if "-f" in args:
- args = args.replace(" -f", "").replace("-f", "")
- force = True
- if args:
- await self.modhelp(message, args)
- return
- count = 0
- for i in self.allmodules.modules:
- try:
- if i.commands or i.inline_handlers:
- count += 1
- except Exception:
- pass
- hidden = self.get("hide", [])
- reply = self.strings("all_header").format(count, 0 if force else len(hidden))
- shown_warn = False
- plain_ = []
- core_ = []
- inline_ = []
- no_commands_ = []
- for mod in self.allmodules.modules:
- if not hasattr(mod, "commands"):
- logger.debug(f"Module {mod.__class__.__name__} is not inited yet")
- continue
- if mod.strings["name"] in self.get("hide", []) and not force:
- continue
- tmp = ""
- try:
- name = mod.strings["name"]
- except KeyError:
- name = getattr(mod, "name", "ERROR")
- inline = (
- hasattr(mod, "callback_handlers")
- and mod.callback_handlers
- or hasattr(mod, "inline_handlers")
- and mod.inline_handlers
- )
- if not inline:
- for cmd_ in mod.commands.values():
- try:
- inline = "await self.inline.form(" in inspect.getsource(
- cmd_.__code__
- )
- except Exception:
- pass
- core = mod.__origin__ == "<core>"
- if core:
- emoji = self.config["core_emoji"]
- elif inline:
- emoji = self.config["hikka_emoji"]
- else:
- emoji = self.config["plain_emoji"]
- if (
- not getattr(mod, "commands", None)
- and not getattr(mod, "inline_handlers", None)
- and not getattr(mod, "callback_handlers", None)
- ):
- no_commands_ += [
- self.strings("mod_tmpl").format(self.config["empty_emoji"], name)
- ]
- continue
- tmp += self.strings("mod_tmpl").format(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 += self.strings("first_cmd_tmpl").format(cmd)
- first = False
- else:
- tmp += self.strings("cmd_tmpl").format(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 += self.strings("first_cmd_tmpl").format(f"🎹 {cmd}")
- first = False
- else:
- tmp += self.strings("cmd_tmpl").format(f"🎹 {cmd}")
- if commands or icommands:
- tmp += " )"
- if core:
- core_ += [tmp]
- elif inline:
- inline_ += [tmp]
- else:
- plain_ += [tmp]
- elif not shown_warn and (mod.commands or mod.inline_handlers):
- reply = (
- "<i>You have permissions to execute only these"
- f" commands</i>\n{reply}"
- )
- shown_warn = True
- plain_.sort(key=lambda x: x.split()[1])
- core_.sort(key=lambda x: x.split()[1])
- inline_.sort(key=lambda x: x.split()[1])
- no_commands_.sort(key=lambda x: x.split()[1])
- no_commands_ = "".join(no_commands_) if force else ""
- partial_load = (
- ""
- if self.lookup("Loader")._fully_loaded
- else f"\n\n{self.strings('partial_load')}"
- )
- await utils.answer(
- message,
- f"{reply}\n{''.join(core_)}{''.join(plain_)}{''.join(inline_)}{no_commands_}{partial_load}",
- )
- async def supportcmd(self, message):
- """Joins the support Hikka chat"""
- if await self.allmodules.check_security(
- message,
- security.OWNER | security.SUDO,
- ):
- await self._client(JoinChannelRequest("https://t.me/hikka_talks"))
- try:
- await self.inline.form(
- self.strings("joined"),
- reply_markup=[
- [{"text": "👩💼 Chat", "url": "https://t.me/hikka_talks"}]
- ],
- ttl=10,
- message=message,
- )
- except Exception:
- await utils.answer(message, self.strings("joined"))
- else:
- try:
- await self.inline.form(
- self.strings("join"),
- reply_markup=[
- [{"text": "👩💼 Chat", "url": "https://t.me/hikka_talks"}]
- ],
- ttl=10,
- message=message,
- )
- except Exception:
- await utils.answer(message, self.strings("join"))
|