# █ █ ▀ █▄▀ ▄▀█ █▀█ ▀ ▄▀█ ▀█▀ ▄▀█ █▀▄▀█ ▄▀█ # █▀█ █ █ █ █▀█ █▀▄ █ ▄ █▀█ █ █▀█ █ ▀ █ █▀█ # # © Copyright 2022 # # https://t.me/hikariatama # # 🔒 Licensed under the GNU GPLv3 # 🌐 https://www.gnu.org/licenses/agpl-3.0.html # scope: inline import time import logging from io import BytesIO from .. import loader, utils, main from typing import Union from telethon.tl.types import Message from telethon.errors.rpcerrorlist import ChatSendInlineForbiddenError import aiogram logger = logging.getLogger(__name__) @loader.tds class TestMod(loader.Module): """Perform operations based on userbot self-testing""" strings = { "name": "Tester", "set_loglevel": "🚫 Please specify verbosity as an integer or string", "no_logs": "ℹ️ You don't have any logs at verbosity {}.", "logs_filename": "hikka-logs.txt", "logs_caption": "🏩 Hikka logs with verbosity {}\n\n👩‍🎤 Hikka version: {}.{}.{}\n⏱ Uptime: {}\n{}", "suspend_invalid_time": "🚫 Invalid time to suspend", "suspended": "🥶 Bot suspended for {} seconds", "results_ping": "⏱ Ping: {} ms", "confidential": "⚠️ Log level {} may reveal your confidential info, be careful", "confidential_text": "⚠️ Log level {0} may reveal your confidential info, be careful\nType .logs {0} force_insecure to ignore this warning", "choose_loglevel": "💁‍♂️ Choose log level", } @staticmethod async def dumpcmd(message: Message) -> None: """Use in reply to get a dump of a message""" if not message.is_reply: return await utils.answer( message, "" + utils.escape_html((await message.get_reply_message()).stringify()) + "", ) @staticmethod async def cancel(call: aiogram.types.CallbackQuery) -> None: await call.delete() async def logscmd( self, message: Union[Message, aiogram.types.CallbackQuery], force: bool = False, lvl: Union[int, None] = None, ) -> None: """ - Dumps logs. Loglevels below WARNING may contain personal info.""" if not isinstance(lvl, int): args = utils.get_args_raw(message) try: try: lvl = int(args.split()[0]) except ValueError: lvl = getattr(logging, args.split()[0].upper(), None) except IndexError: lvl = None if not isinstance(lvl, int): if self.inline.init_complete: await self.inline.form( text=self.strings("choose_loglevel"), reply_markup=[ [ { "text": "🚨 Critical", "callback": self.logscmd, "args": (False, 50), }, { "text": "🚫 Error", "callback": self.logscmd, "args": (False, 40), }, ], [ { "text": "⚠️ Warning", "callback": self.logscmd, "args": (False, 30), }, { "text": "ℹ️ Info", "callback": self.logscmd, "args": (False, 20), }, ], [ { "text": "🧑‍💻 Debug", "callback": self.logscmd, "args": (False, 10), }, { "text": "👁 All", "callback": self.logscmd, "args": (False, 0), }, ], [{"text": "🚫 Cancel", "callback": self.cancel}], ], message=message, ) else: await utils.answer(message, self.strings("set_loglevel")) return logs = "\n\n".join( [ ("\n".join(handler.dumps(lvl))) for handler in logging.getLogger().handlers ] ).encode("utf-16") named_lvl = ( lvl if lvl not in logging._levelToName else logging._levelToName[lvl] # skipcq: PYL-W0212 ) if ( lvl < logging.WARNING and not force and ( not isinstance(message, Message) or "force_insecure" not in message.raw_text.lower() ) ): if self.inline.init_complete: try: cfg = { "text": self.strings("confidential").format(named_lvl), "reply_markup": [ [ { "text": "📤 Send anyway", "callback": self.logscmd, "args": [True, lvl], }, {"text": "🚫 Cancel", "callback": self.cancel}, ] ], } if isinstance(message, Message): await self.inline.form(**cfg, message=message) else: await message.edit(**cfg) except ChatSendInlineForbiddenError: await utils.answer( message, self.strings("confidential_text").format(named_lvl) ) else: await utils.answer( message, self.strings("confidential_text").format(named_lvl) ) return if len(logs) <= 2: if isinstance(message, Message): await utils.answer(message, self.strings("no_logs").format(named_lvl)) else: await message.edit(self.strings("no_logs").format(named_lvl)) await message.unload() return logs = BytesIO(logs) logs.name = self.strings("logs_filename") other = (*main.__version__, utils.formatted_uptime(), utils.get_named_platform()) if isinstance(message, Message): await message.delete() await utils.answer( message, logs, caption=self.strings("logs_caption").format(named_lvl, *other) ) else: await message.delete() await self._client.send_file( message.form["chat"], logs, caption=self.strings("logs_caption").format(named_lvl, *other), ) @loader.owner async def suspendcmd(self, message: Message) -> None: """