diff --git a/hikka/_internal.py b/hikka/_internal.py index 43cd06c..a5e7068 100644 --- a/hikka/_internal.py +++ b/hikka/_internal.py @@ -1,8 +1,8 @@ import atexit import functools +import logging import os import sys -import logging def get_startup_callback() -> callable: diff --git a/hikka/modules/api_protection.py b/hikka/modules/api_protection.py index b4199f5..cc46173 100644 --- a/hikka/modules/api_protection.py +++ b/hikka/modules/api_protection.py @@ -18,6 +18,7 @@ from telethon.tl.types import Message from .. import loader, utils from ..inline.types import InlineCall +from ..web.debugger import WebDebugger logger = logging.getLogger(__name__) @@ -110,6 +111,8 @@ class APIRatelimiterMod(loader.Module): " anyone." ), "web_pin_btn": "🐞 Show Werkzeug PIN", + "proxied_url": "🌐 Proxied URL", + "local_url": "🏠 Local URL", } strings_ru = { @@ -154,6 +157,8 @@ class APIRatelimiterMod(loader.Module): " никому." ), "web_pin_btn": "🐞 Показать Werkzeug PIN", + "proxied_url": "🌐 Проксированная ссылка", + "local_url": "🏠 Локальная ссылка", } strings_de = { @@ -201,19 +206,21 @@ class APIRatelimiterMod(loader.Module): " anzuzeigen. Gib ihn niemandem." ), "web_pin_btn": "🐞 Werkzeug PIN anzeigen", + "proxied_url": "🌐 Proxied URL", + "local_url": "🏠 Lokale URL", } strings_tr = { "warning": ( - "⚠️" - " Dikkat!\n\nHesabın ayarlarda belirtilmiş istek sınırını aştı." - " Telegram API Flood’unu önlemek için tüm kullanıcı botu {} saniye" - " boyunca durduruldu. Daha fazla bilgi almak için ekteki dosyayı" - " inceleyebilirsiniz. /n/ Ayrıca {prefix}Destek grubundan" - " yardım almanız önerilmektedir. Eğer bu işlemin kasıtlı bir işlem olduğunu" - " düşünüyorsanız, kullanıcı botunuzun açılmasının bekleyin ve bu tarz bir" - " işlem gerçekleştireceğiniz sıradaki sefer" - " {prefix}suspend_api_protect <saniye> kodunu kullanın." + "⚠️ Dikkat!\n\nHesap" + " yapılandırmasında belirtilen sınır değerlerini aştı. Telegram API" + " sızmalarını önlemek için tüm Userbot {} sanie donduruldu. Daha" + " fazla bilgi için aşağıya eklenen dosyaya bakın.\n\nLütfen" + " {prefix}support grubu ile yardım almak için destek" + " olun!\n\nEğer bu, Userbot'un planlanmış davranışı olduğunu" + " düşünüyorsanız, zamanlayıcı bittiğinde ve" + " {prefix}suspend_api_protect <saniye cinsinden süre>" + " gibi kaynak tüketen bir işlemi planladığınızda yeniden deneyin." ), "args_invalid": ( "🚫 Geçersiz" @@ -247,6 +254,8 @@ class APIRatelimiterMod(loader.Module): " tıklayın. Onu kimseye vermeyin." ), "web_pin_btn": "🐞 Werkzeug PIN'ini göster", + "proxied_url": "🌐 Proxied URL", + "local_url": "🏠 Lokal URL", } strings_uz = { @@ -287,6 +296,8 @@ class APIRatelimiterMod(loader.Module): " Uni hech kimga bermang." ), "web_pin_btn": "🐞 Werkzeug PIN-ni ko'rsatish", + "proxied_url": "🌐 Proxied URL", + "local_url": "🏠 Lokal URL", } strings_es = { @@ -334,6 +345,8 @@ class APIRatelimiterMod(loader.Module): " Werkzeug. No se lo des a nadie." ), "web_pin_btn": "🐞 Mostrar el PIN de Werkzeug", + "proxied_url": "🌐 URL de proxy", + "local_url": "🏠 URL local", } strings_kk = { @@ -373,6 +386,8 @@ class APIRatelimiterMod(loader.Module): " басыңыз. Оны кімсіне де бермеңіз." ), "web_pin_btn": "🐞 Werkzeug PIN кодын көрсету", + "proxied_url": "🌐 Прокси URL", + "local_url": "🏠 Жергілікті URL", } _ratelimiter = [] @@ -527,11 +542,11 @@ class APIRatelimiterMod(loader.Module): ) @property - def _pin(self) -> str: - return logging.getLogger().handlers[0].web_debugger.pin + def _debugger(self) -> WebDebugger: + return logging.getLogger().handlers[0].web_debugger async def _show_pin(self, call: InlineCall): - await call.answer(f"Werkzeug PIN: {self._pin}", show_alert=True) + await call.answer(f"Werkzeug PIN: {self._debugger.pin}", show_alert=True) @loader.command( ru_doc="Показать PIN Werkzeug", @@ -541,15 +556,26 @@ class APIRatelimiterMod(loader.Module): es_doc="Mostrar herramienta PIN", kk_doc="PIN құралын көрсету", ) - async def debugpin(self, message: Message): + async def debugger(self, message: Message): """Show the Werkzeug PIN""" await self.inline.form( message=message, text=self.strings("web_pin"), - reply_markup={ - "text": self.strings("web_pin_btn"), - "callback": self._show_pin, - }, + reply_markup=[ + [ + { + "text": self.strings("web_pin_btn"), + "callback": self._show_pin, + } + ], + [ + {"text": self.strings("proxied_url"), "url": self._debugger.url}, + { + "text": self.strings("local_url"), + "url": f"http://127.0.0.1:{self._debugger.port}", + }, + ], + ], ) async def _finish(self, call: InlineCall): diff --git a/hikka/modules/hikka_config.py b/hikka/modules/hikka_config.py index 3d1b730..aaae5b7 100755 --- a/hikka/modules/hikka_config.py +++ b/hikka/modules/hikka_config.py @@ -28,33 +28,35 @@ class HikkaConfigMod(loader.Module): strings = { "name": "HikkaConfig", - "choose_core": "🎚 Choose a category", - "configure": "🎚 Choose a module to configure", - "configure_lib": "🪴 Choose a library to configure", + "choose_core": "⚙️ Choose a category", + "configure": "⚙️ Choose a module to configure", + "configure_lib": "📦 Choose a library to configure", "configuring_mod": ( - "🎚 Choose config option for mod {}\n\nCurrent" + "⚙️ Choose config option for mod {}\n\nCurrent" " options:\n\n{}" ), "configuring_lib": ( - "🪴 Choose config option for library {}\n\nCurrent" + "📦 Choose config option for library {}\n\nCurrent" " options:\n\n{}" ), "configuring_option": ( - "🎚 Configuring option {} of mod" + "⚙️ Configuring option {} of mod" " {}\nℹ️ {}\n\nDefault: {}\n\nCurrent:" " {}\n\n{}" ), "configuring_option_lib": ( - "🪴 Configuring option {} of library" + "📦 Configuring option {} of library" " {}\nℹ️ {}\n\nDefault: {}\n\nCurrent:" " {}\n\n{}" ), "option_saved": ( - "🎚 Option {} of module {}" + "⚙️ Option" + " {} of module {}" " saved!\nCurrent: {}" ), "option_saved_lib": ( - "🪴 Option {} of library {}" + "📦 Option" + " {} of library {}" " saved!\nCurrent: {}" ), "option_reset": ( @@ -85,37 +87,39 @@ class HikkaConfigMod(loader.Module): "hide_value": "🔒 Hide value", "builtin": "🛰 Built-in", "external": "🛸 External", - "libraries": "🪴 Libraries", + "libraries": "📦 Libraries", } strings_ru = { - "choose_core": "🎚 Выбери категорию", - "configure": "🎚 Выбери модуль для настройки", - "configure_lib": "🪴 Выбери библиотеку для настройки", + "choose_core": "⚙️ Выбери категорию", + "configure": "⚙️ Выбери модуль для настройки", + "configure_lib": "📦 Выбери библиотеку для настройки", "configuring_mod": ( - "🎚 Выбери параметр для модуля {}\n\nТекущие" + "⚙️ Выбери параметр для модуля {}\n\nТекущие" " настройки:\n\n{}" ), "configuring_lib": ( - "🪴 Выбери параметр для библиотеки {}\n\nТекущие" + "📦 Выбери параметр для библиотеки {}\n\nТекущие" " настройки:\n\n{}" ), "configuring_option": ( - "🎚 Управление параметром {} модуля" + "⚙️ Управление параметром {} модуля" " {}\nℹ️ {}\n\nСтандартное:" " {}\n\nТекущее: {}\n\n{}" ), "configuring_option_lib": ( - "🪴 Управление параметром {} библиотеки" + "📦 Управление параметром {} библиотеки" " {}\nℹ️ {}\n\nСтандартное:" " {}\n\nТекущее: {}\n\n{}" ), "option_saved": ( - "🎚 Параметр {} модуля {}" + "⚙️ Параметр" + " {} модуля {}" " сохранен!\nТекущее: {}" ), "option_saved_lib": ( - "🪴 Параметр {} библиотеки {}" + "📦 Параметр" + " {} библиотеки {}" " сохранен!\nТекущее: {}" ), "option_reset": ( @@ -149,38 +153,40 @@ class HikkaConfigMod(loader.Module): "hide_value": "🔒 Скрыть значение", "builtin": "🛰 Встроенные", "external": "🛸 Внешние", - "libraries": "🪴 Библиотеки", + "libraries": "📦 Библиотеки", } strings_de = { - "choose_core": "🎚 Wähle eine Kategorie", - "configure": "🎚 Modul zum Konfigurieren auswählen", - "configure_lib": "🪴 Wählen Sie eine zu konfigurierende Bibliothek aus", + "choose_core": "⚙️ Wähle eine Kategorie", + "configure": "⚙️ Modul zum Konfigurieren auswählen", + "configure_lib": "📦 Wählen Sie eine zu konfigurierende Bibliothek aus", "configuring_mod": ( - "🎚 Wählen Sie einen Parameter für das Modul aus" + "⚙️ Wählen Sie einen Parameter für das Modul aus" " {}\n\nAktuell Einstellungen:\n\n{}" ), "configuring_lib": ( - "🪴 Wählen Sie eine Option für die Bibliothek aus" + "📦 Wählen Sie eine Option für die Bibliothek aus" " {}\n\nAktuell Einstellungen:\n\n{}" ), "configuring_option": ( - "🎚 Option {} des Moduls {}" + "⚙️ Option {} des Moduls {}" " konfigurieren\nℹ️ {}\n\nStandard: {}\n\n" "Aktuell: {}\n\n{}" ), "configuring_option_lib": ( - "🪴 Option {} der Bibliothek {}" + "📦 Option {} der Bibliothek {}" " konfigurieren\nℹ️ {}\n\nStandard: {}\n\n" "Aktuell: {}\n\n{}" ), "option_saved": ( - "🎚 Option {} des Moduls {}" - " gespeichert!\nAktuell: {}" + "⚙️ Option" + " {} des Moduls {}" + " gespeichert!\nAktuell: {}" ), "option_saved_lib": ( - "🪴 Option {} der Bibliothek {}" - " gespeichert!\nAktuell: {}" + "📦 Option" + " {} der Bibliothek {}" + " gespeichert!\nAktuell: {}" ), "option_reset": ( "♻️ Option {} des Moduls {}" @@ -213,38 +219,39 @@ class HikkaConfigMod(loader.Module): "hide_value": "🔒 Wert verbergen", "builtin": "🛰 Ingebaut", "external": "🛸 Extern", - "libraries": "🪴 Bibliotheken", + "libraries": "📦 Bibliotheken", } strings_uz = { - "choose_core": "🎚 Kurum tanlang", - "configure": "🎚 Sozlash uchun modulni tanlang", - "configure_lib": "🪴 Sozlash uchun kutubxonani tanlang", + "choose_core": "⚙️ Kurum tanlang", + "configure": "⚙️ Sozlash uchun modulni tanlang", + "configure_lib": "📦 Sozlash uchun kutubxonani tanlang", "configuring_mod": ( - "🎚 Modul uchun parametrni tanlang {}\n\nJoriy" + "⚙️ Modul uchun parametrni tanlang {}\n\nJoriy" " sozlamalar:\n\n{}" ), "configuring_lib": ( - "🪴 Kutubxona uchun variantni tanlang {}\n\nHozirgi" + "📦 Kutubxona uchun variantni tanlang {}\n\nHozirgi" " sozlamalar:\n\n{}" ), "configuring_option": ( - "🎚 Modul {} sozlamasi {}" + "⚙️ Modul {} sozlamasi {}" " konfiguratsiya qilinmoqda\nℹ️ {}\n\nDefault:" " {}\n\nHozirgi: {}\n\n{}" ), "configuring_option_lib": ( - "🪴 Modul {} kutubxonasi sozlamasi" + "📦 Modul {} kutubxonasi sozlamasi" " {} konfiguratsiya qilinmoqda\nℹ️" " {}\n\nDefault: {}\n\nHozirgi: {}\n\n{}" ), "option_saved": ( - "🎚 Modul {} sozlamasi saqlandi!\nHozirgi:" - " {}" + "⚙️ Modul" + " {} sozlamasi saqlandi!\nHozirgi: {}" ), "option_saved_lib": ( - "🪴 Modul {} kutubxonasi sozlamasi" - " saqlandi!\nHozirgi: {}" + "📦 Modul" + " {} kutubxonasi sozlamasi saqlandi!\nHozirgi:" + " {}" ), "option_reset": ( "♻️ Modul {} sozlamasi standart qiymatga" @@ -271,29 +278,30 @@ class HikkaConfigMod(loader.Module): "hide_value": "🔒 Qiymatni yashirish", "builtin": "🛰 Ichki", "external": "🛸 Tashqi", - "libraries": "🪴 Kutubxona", + "libraries": "📦 Kutubxona", "close_btn": "🔻 Yopish", "back_btn": "👈 Orqaga", } strings_tr = { "configuring_option": ( - "🎚 Modül {} seçeneği {}" + "⚙️ Modül {} seçeneği {}" " yapılandırılıyor\nℹ️ {}\n\nVarsayılan: {}\n\n" "Mevcut: {}\n\n{}" ), "configuring_option_lib": ( - "🪴 Modül {} kütüphanesi seçeneği {}" + "📦 Modül {} kütüphanesi seçeneği {}" " yapılandırılıyor\nℹ️ {}\n\nVarsayılan: {}\n\n" "Mevcut: {}\n\n{}" ), "option_saved": ( - "🎚 Modül {} seçeneği kaydedildi!\nMevcut:" - " {}" + "⚙️ Modül" + " {} seçeneği kaydedildi!\nMevcut: {}" ), "option_saved_lib": ( - "🪴 Modül {} kütüphanesi seçeneği" - " kaydedildi!\nMevcut: {}" + "📦 Modül" + " {} kütüphanesi seçeneği kaydedildi!\nMevcut:" + " {}" ), "option_reset": ( "♻️ Modül {} seçeneği varsayılan değere" @@ -318,27 +326,29 @@ class HikkaConfigMod(loader.Module): "hide_value": "🔒 Değeri gizle", "builtin": "🛰 Dahili", "external": "🛸 Harici", - "libraries": "🪴 Kütüphane", + "libraries": "📦 Kütüphane", "back_btn": "👈 Geri", } strings_es = { "configuring_option": ( - "🎚 Configurando la opción {} del módulo" + "⚙️ Configurando la opción {} del módulo" " {} \nℹ️ {}\n\nPor defecto:" " {}\n\nActual: {}\n\n{}" ), "configuring_option_lib": ( - "🪴 Configurando la opción {} de la librería del" + "📦 Configurando la opción {} de la librería del" " módulo {} \nℹ️ {}\n\nPor defecto:" " {}\n\nActual: {}\n\n{}" ), "option_saved": ( - "🎚 ¡Guardada la opción {} del módulo" - " {}!\nActual: {}" + "⚙️ ¡Guardada la opción" + " {} del módulo {}!\nActual:" + " {}" ), "option_saved_lib": ( - "🪴 ¡Guardada la opción {} de la librería del módulo" + "📦 ¡Guardada la opción" + " {} de la librería del módulo" " {}!\nActual: {}" ), "option_reset": ( @@ -365,29 +375,30 @@ class HikkaConfigMod(loader.Module): "hide_value": "🔒 Ocultar valores", "builtin": "🛰 Integrado", "external": "🛸 Externo", - "libraries": "🪴 Librerías", + "libraries": "📦 Librerías", "back_btn": "👈 Volver", } strings_kk = { "configuring_option": ( - "🎚 Модуль {} ішіндегі {}" + "⚙️ Модуль {} ішіндегі {}" " параметрін баптау\nℹ️ {}\n\nӘдепкі:" " {}\n\nАғымдағы: {}\n\n{}" ), "configuring_option_lib": ( - "🪴 Модуль {} ішіндегі" + "📦 Модуль {} ішіндегі" " кітапхананың{} параметрін баптау\nℹ️" " {}\n\nӘдепкі: {}\n\nАғымдағы: {}\n\n{}" ), "option_saved": ( - "🎚 Модуль {} ішіндегі {}" - " параметрі сақталды!\nАғымдағы: {}" + "⚙️ Модуль" + " {} ішіндегі {} параметрі" + " сақталды!\nАғымдағы: {}" ), "option_saved_lib": ( - "🪴 Модуль {} ішіндегі" - " кітапхананың{} параметрі сақталды!\nАғымдағы:" - " {}" + "📦 Модуль" + " {} ішіндегі кітапхананың{}" + " параметрі сақталды!\nАғымдағы: {}" ), "option_reset": ( "♻️ Модуль {} ішіндегі {}" @@ -413,7 +424,7 @@ class HikkaConfigMod(loader.Module): "hide_value": "🔒 Мәндерді жасыру", "builtin": "🛰 Ішкі", "external": "🛸 Сыртқы", - "libraries": "🪴 Кітапханалар", + "libraries": "📦 Кітапханалар", "back_btn": "👈 Артқа", } @@ -1381,7 +1392,7 @@ class HikkaConfigMod(loader.Module): """Configure modules""" args = utils.get_args_raw(message) if self.lookup(args) and hasattr(self.lookup(args), "config"): - form = await self.inline.form("🌘", message) + form = await self.inline.form("🌘", message, silent=True) mod = self.lookup(args) if isinstance(mod, loader.Library): type_ = "library" diff --git a/hikka/modules/hikka_settings.py b/hikka/modules/hikka_settings.py index 86ddbcf..4499ce1 100755 --- a/hikka/modules/hikka_settings.py +++ b/hikka/modules/hikka_settings.py @@ -20,8 +20,8 @@ from telethon.tl.types import Message from telethon.utils import get_display_name from .. import loader, main, utils -from ..inline.types import InlineCall from .._internal import restart +from ..inline.types import InlineCall logger = logging.getLogger(__name__) diff --git a/hikka/modules/python.py b/hikka/modules/python.py index 9dd7d43..60c144e 100755 --- a/hikka/modules/python.py +++ b/hikka/modules/python.py @@ -169,14 +169,12 @@ class PythonMod(loader.Module): message, self.strings("err").format( utils.escape_html(utils.get_args_raw(message)), - utils.escape_html( - self.censor( - ( - "\n".join(item.full_stack.splitlines()[:-1]) - + "\n\n" - + "🚫 " - + item.full_stack.splitlines()[-1] - ) + self.censor( + ( + "\n".join(item.full_stack.splitlines()[:-1]) + + "\n\n" + + "🚫 " + + item.full_stack.splitlines()[-1] ) ), ), diff --git a/hikka/modules/settings.py b/hikka/modules/settings.py index cbda201..b4745a6 100755 --- a/hikka/modules/settings.py +++ b/hikka/modules/settings.py @@ -270,8 +270,8 @@ class CoreMod(loader.Module): " document_id=5377437404078546699>💜 Hikka-TL:" " {}\n{}" " Hikka-Pyro:" - " {}\n\n⌨️" - " Entwickler:t.me/hikariatama" + " {}\n\n⌨️" + " Entwickler: t.me/hikariatama" ), "_cls_doc": "Verwaltung der Grundeinstellungen des Userbots", "confirm_cleardb": ( @@ -362,8 +362,8 @@ class CoreMod(loader.Module): " document_id=5377437404078546699>💜 Hikka-TL:" " {}\n{}" " Hikka-Pyro:" - " {}\n\n⌨️" - " Geliştirici:t.me/hikariatama" + " {}\n\n⌨️" + " Geliştirici: t.me/hikariatama" ), "_cls_doc": "Userbot temel ayar yönetimi", "confirm_cleardb": ( @@ -624,7 +624,7 @@ class CoreMod(loader.Module): " document_id=5377437404078546699>💜 Hikka-TL:" " {}\n{}" " Hikka-Pyro: {}\n\n⌨️ Developer:" + " document_id=5454182070156794055>⌨️ Әзірлеуші:" " t.me/hikariatama" ), "_cls_doc": "Жүйе бастапқы параметрлерін басқару", diff --git a/hikka/modules/updater.py b/hikka/modules/updater.py index 72f7099..f048d46 100755 --- a/hikka/modules/updater.py +++ b/hikka/modules/updater.py @@ -26,8 +26,8 @@ from telethon.tl.functions.messages import ( from telethon.tl.types import DialogFilter, Message from .. import loader, main, utils, version -from ..inline.types import InlineCall from .._internal import get_startup_callback +from ..inline.types import InlineCall logger = logging.getLogger(__name__) diff --git a/hikka/utils.py b/hikka/utils.py index 1e6eecc..91cee53 100755 --- a/hikka/utils.py +++ b/hikka/utils.py @@ -25,6 +25,7 @@ # 🌐 https://www.gnu.org/licenses/agpl-3.0.html import asyncio +import atexit as _atexit import contextlib import functools import inspect @@ -35,7 +36,6 @@ import os import random import re import shlex -import atexit as _atexit import signal import string import time @@ -1443,7 +1443,13 @@ def get_topic(message: Message) -> typing.Optional[int]: """ return ( (message.reply_to.reply_to_top_id or message.reply_to.reply_to_msg_id) - if message.reply_to and message.reply_to.forum_topic + if ( + isinstance(message, Message) + and message.reply_to + and message.reply_to.forum_topic + ) + else message.form["top_msg_id"] + if isinstance(message, (InlineCall, InlineMessage)) else None ) diff --git a/hikka/web/debugger.py b/hikka/web/debugger.py index 9f8d796..68f1902 100644 --- a/hikka/web/debugger.py +++ b/hikka/web/debugger.py @@ -1,12 +1,12 @@ import asyncio -import random - -from werkzeug.debug import DebuggedApplication -from werkzeug import Request, Response -from werkzeug.serving import make_server, BaseWSGIServer import os +import random from threading import Thread +from werkzeug import Request, Response +from werkzeug.debug import DebuggedApplication +from werkzeug.serving import BaseWSGIServer, make_server + from .. import main, utils from . import proxypass @@ -29,7 +29,7 @@ class WebDebugger: self.port = main.gen_port("werkzeug_port", True) main.save_config_key("werkzeug_port", self.port) self._url = None - self._proxypasser = proxypass.ProxyPasser() + self._proxypasser = proxypass.ProxyPasser(self._url_changed) asyncio.ensure_future(self._getproxy()) self._create_server() self._controller = ServerThread(self._server) @@ -39,6 +39,9 @@ class WebDebugger: async def _getproxy(self): self._url = await self._proxypasser.get_url(self.port) + def _url_changed(self, url: str): + self._url = url + def _create_server(self) -> BaseWSGIServer: os.environ["WERKZEUG_DEBUG_PIN"] = self.pin os.environ["WERKZEUG_RUN_MAIN"] = "true" diff --git a/hikka/web/proxypass.py b/hikka/web/proxypass.py index 28385bd..f31ff38 100644 --- a/hikka/web/proxypass.py +++ b/hikka/web/proxypass.py @@ -9,12 +9,13 @@ logger = logging.getLogger(__name__) class ProxyPasser: - def __init__(self): + def __init__(self, change_url_callback: callable = lambda _: None): self._tunnel_url = None self._sproc = None self._url_available = asyncio.Event() self._url_available.set() self._lock = asyncio.Lock() + self._change_url_callback = change_url_callback async def _sleep_for_task(self, callback: callable, data: bytes, delay: int): await asyncio.sleep(delay) @@ -57,13 +58,14 @@ class ProxyPasser: if re.search(regex, stdout_line): logger.debug("Proxy pass tunneled: %s", stdout_line) self._tunnel_url = re.search(regex, stdout_line)[1] + self._change_url_callback(self._tunnel_url) self._url_available.set() async def get_url(self, port: int) -> typing.Optional[str]: async with self._lock: if self._tunnel_url: try: - await asyncio.wait_for(self._sproc.wait(), timeout=0.1) + await asyncio.wait_for(self._sproc.wait(), timeout=0.05) except asyncio.TimeoutError: return self._tunnel_url else: