src.handlers.info
Информационные сообщения
1"""Информационные сообщения""" 2 3import logging 4from contextlib import suppress 5from datetime import timedelta 6from typing import Union 7 8from aiogram import Bot, F, Router 9from aiogram.exceptions import TelegramBadRequest 10from aiogram.filters.command import Command 11from aiogram.types import CallbackQuery, Message 12from aiogram.utils.formatting import Bold, as_list, as_marked_section 13 14import kb 15import text 16from core.config import settings 17from core.err import bot_except 18from core.exceptions import BaseBotError, DatabaseError, WireguardError 19from db.models import UserData 20from db.utils import get_user, test_server_speed 21from handlers.utils import find_user 22from wg.utils import WgServerTools 23 24logger = logging.getLogger() 25router = Router() 26router.message.filter(F.chat.type == "private") 27 28 29async def more_help_info(callback: CallbackQuery): 30 """Отправляет дополнительную информацию о помощи. 31 32 Args: 33 callback (CallbackQuery): Событие обратного вызова, содержащее информацию о запросе. 34 35 Отправляет сообщение с предложением задать дополнительные вопросы и кнопкой для доступа к меню помощи. 36 """ 37 await callback.message.answer( 38 "Если у вас есть дополнительные вопросы, не стесняйтесь спрашивать! Мы здесь, чтобы помочь вам. 🚀", 39 reply_markup=kb.get_help_menu( 40 callback.from_user.full_name, callback.from_user.id 41 ), 42 ) 43 44 45async def change_help_page(message: Message, pages: list, page: int, prefix: str): 46 """Изменяет страницу помощи. 47 48 Args: 49 message (Message): Сообщение, которое будет изменено. 50 pages (list): Список страниц помощи. 51 page (int): Индекс текущей страницы. 52 prefix (str): Префикс для кнопок навигации. 53 54 Обновляет текст сообщения с новой страницей помощи и кнопками навигации. 55 """ 56 with suppress(TelegramBadRequest): 57 await message.edit_text( 58 pages[page], reply_markup=kb.get_help_book_keyboard(pages, page, prefix) 59 ) 60 61 62async def post_help_book( 63 callback: CallbackQuery, book: list, step: str, start_message: str, prefix: str 64): 65 """Отправляет книгу помощи пользователю. 66 67 Args: 68 callback (CallbackQuery): Событие обратного вызова, содержащее информацию о запросе. 69 book (list): Список шагов помощи. 70 step (str): Текущий шаг. 71 start_message (str): Сообщение, отправляемое в начале. 72 prefix (str): Префикс для кнопок навигации. 73 74 Отправляет сообщения с шагами помощи в зависимости от текущего шага. 75 """ 76 if step == "start": 77 await callback.message.answer(start_message) 78 79 await callback.message.answer( 80 book[0], 81 reply_markup=kb.get_help_book_keyboard(pages=book, page=0, prefix=prefix), 82 ) 83 elif step.isdigit(): 84 await change_help_page( 85 callback.message, pages=book, page=int(step), prefix=prefix 86 ) 87 else: 88 for step in book: 89 await callback.message.answer(step) 90 await more_help_info(callback) 91 92 93@router.message(Command("help")) 94@router.message(F.text == "Помощь") 95@router.callback_query(F.data == "main_help") 96@bot_except 97async def help_me(trigger: Union[Message, CallbackQuery]): 98 """Обработчик команды помощи. 99 100 Args: 101 trigger (Union[Message, CallbackQuery]): Сообщение или событие обратного вызова, инициировавшее команду. 102 103 Отправляет сообщение с предложением помощи и кнопками для доступа к меню помощи. 104 """ 105 await getattr(trigger, "message", trigger).answer( 106 "Чем вам помочь?", 107 reply_markup=kb.get_help_menu( 108 trigger.from_user.full_name, trigger.from_user.id 109 ), 110 ) 111 112 113@router.callback_query(F.data == "bot_info") 114@bot_except 115async def bot_info(callback: CallbackQuery): 116 """Отправляет информацию о боте. 117 118 Args: 119 callback (CallbackQuery): Событие обратного вызова, содержащее информацию о запросе. 120 121 Отправляет сообщение с информацией о боте и кнопкой для доступа к дополнительной помощи. 122 """ 123 await callback.message.answer(text.BOT_INFO, reply_markup=kb.static_join_button) 124 await more_help_info(callback) 125 126 127@router.callback_query(F.data.startswith("first_help_info_")) 128@bot_except 129async def next_help(callback: CallbackQuery): 130 """Обработчик перехода к следующему шагу помощи. 131 132 Args: 133 callback (CallbackQuery): Событие обратного вызова, содержащее информацию о запросе. 134 135 Отправляет сообщения с шагами помощи в зависимости от текущего шага. 136 """ 137 current_step: str = callback.data.split("_")[-1] 138 139 await post_help_book( 140 callback, 141 book=text.BOT_STEPS, 142 step=current_step, 143 start_message="🤖 <b>Что делать дальше? Вот краткий алгоритм работы с нашим ботом и WireGuard:</b>", 144 prefix="first_help_info", 145 ) 146 147 148@router.callback_query(F.data == "wg_help_info") 149@bot_except 150async def wg_help(callback: CallbackQuery): 151 """Отправляет информацию о платформе для установки WireGuard. 152 153 Args: 154 callback (CallbackQuery): Событие обратного вызова, содержащее информацию о запросе. 155 156 Отправляет сообщение с вопросом о платформе для установки WireGuard и кнопками для выбора. 157 """ 158 await callback.message.answer( 159 "На какую платформу вы хотите установить WireGuard?", 160 reply_markup=kb.static_wg_platform_keyboard, 161 ) 162 163 164@router.callback_query(F.data.startswith("wg_help_info_")) 165@bot_except 166async def wg_help_platform(callback: CallbackQuery): 167 """Обработчик помощи по установке WireGuard на выбранной платформе. 168 169 Args: 170 callback (CallbackQuery): Событие обратного вызова, содержащее информацию о запросе. 171 172 Отправляет сообщения с шагами помощи для установки WireGuard на выбранной платформе. 173 """ 174 *_, current_platform, current_step = callback.data.split("_") 175 176 await post_help_book( 177 callback, 178 book=text.WG_STEPS[current_platform], 179 step=current_step, 180 start_message=f"🛠️ <b>Настройка WireGuard на {current_platform}:</b>", 181 prefix=f"wg_help_info_{current_platform}", 182 ) 183 184 185@router.callback_query(F.data.startswith("error_help_info")) 186@bot_except 187async def error_help(callback: CallbackQuery): 188 """Обработчик помощи по устранению ошибок. 189 190 Args: 191 callback (CallbackQuery): Событие обратного вызова, содержащее информацию о запросе. 192 193 Отправляет сообщения с шагами помощи для устранения ошибок. 194 """ 195 current_step: str = callback.data.split("_")[-1] 196 197 await post_help_book( 198 callback, 199 book=text.BOT_ERROR_STEP, 200 step=current_step, 201 start_message="📋 <b>Не волнуйтесь, вот инструкции по устранению проблем с DanVPN</b>", 202 prefix="error_help_info", 203 ) 204 205 206@router.message(Command("time")) 207@bot_except 208async def started(message: Message, started_at): 209 """Отправляет время начала работы бота. 210 211 Args: 212 message (Message): Сообщение, инициировавшее команду. 213 started_at: Время начала работы бота. 214 215 Отправляет сообщение с временем начала работы бота. 216 """ 217 await message.answer(f"Время начала работы бота: {started_at}") 218 219 220@router.message(Command("id")) 221@router.callback_query(F.data == "user_id_info") 222@bot_except 223async def start_bot(trigger: Union[Message, CallbackQuery]): 224 """Отправляет ID пользователя. 225 226 Args: 227 trigger (Union[Message, CallbackQuery]): Сообщение или событие обратного вызова, инициировавшее команду. 228 229 Отправляет сообщение с Telegram ID пользователя. 230 """ 231 await getattr(trigger, "message", trigger).answer( 232 f'Ваш Telegram ID\n\n<span class="tg-spoiler">{trigger.from_user.id}</span>' 233 ) 234 235 236@router.message(Command("cmd")) 237@router.message(Command("commands")) 238@router.message(F.text == "Команды") 239@router.callback_query(F.data == "cmd_help_info") 240@bot_except 241async def commands_list(trigger: Union[Message, CallbackQuery]): 242 """Отправляет список доступных команд. 243 244 Args: 245 trigger (Union[Message, CallbackQuery]): Сообщение или событие обратного вызова, инициировавшее команду. 246 247 Отправляет сообщение с перечислением доступных команд и их описанием. 248 """ 249 help_t = as_list( 250 Bold("Запуск:"), 251 "/start - запуск (перезагрузка) бота", 252 Bold("Действия с аккаунтом:"), 253 as_marked_section( 254 "/account | /app - Основной функционал аккаунта", 255 "/reg - Регистрация в БД Бота", 256 "/freeze - Заморозить аккаунт", 257 "/recover - Разморозить аккаунт", 258 "/chat - Получить доступ в клиентский чат", 259 marker="~ ", 260 ), 261 Bold("Действия с конфигурациями:"), 262 as_marked_section( 263 "/me | /config - данные о моих конфигурациях wireguard", 264 "/create - создать конфигурацию", 265 marker="~ ", 266 ), 267 Bold("Действия с подпиской:"), 268 as_marked_section( 269 "/sub - Купить подписку", 270 "/refund - Сделать запрос на возврат средств", 271 "/history - История транзакций", 272 marker="~ ", 273 ), 274 Bold("Информация:"), 275 as_marked_section( 276 "/help - Помощь", 277 "/cmd - Список всех команд", 278 "/admin - функционал администратора", 279 "/bug - Доложить о баге", 280 "/id - Ваш Telegram ID", 281 "/time - время запуска бота", 282 marker="~ ", 283 ), 284 as_marked_section( 285 Bold("Расширенные возможности (тарифы от расширенного и выше):"), 286 "/server - Анализ работы сервера", 287 "/speed - Максимально доступная скорость VPN на данный момент", 288 "/mute - Отключить уведомления", 289 ), 290 ) 291 await getattr(trigger, "message", trigger).answer(**help_t.as_kwargs()) 292 293 294@router.callback_query(F.data == "freeze_info") 295@bot_except 296async def freeze_config_info(callback: CallbackQuery): 297 """Отправляет информацию о заморозке конфигураций. 298 299 Args: 300 callback (CallbackQuery): Событие обратного вызова, содержащее информацию о запросе. 301 302 Отправляет сообщение с информацией о том, как заморозить конфигурации и что делать в случае проблем. 303 """ 304 await callback.message.answer( 305 "Конфигурации замораживаются, когда становятся недоступными. " 306 "\n\nПроверьте, достаточно ли средств на вашем счете? Соответствует ли количество ваших конфигураций вашему тарифу? " 307 "Возможно недавно произошли изменения в вашем тарифе, подождите несколько минут и попробуйте снова." 308 "\n\nЕсли вам все равно не понятно, почему ваша конфигурация заблокирована, воспользуйтесь командой /bug и сообщите о вашей проблеме." 309 ) 310 311 312@router.callback_query(F.data == "freeze_account_info") 313@bot_except 314async def freeze_user_info(callback: CallbackQuery): 315 """Отправляет информацию о заморозке аккаунта. 316 317 Args: 318 callback (CallbackQuery): Событие обратного вызова, содержащее информацию о запросе. 319 320 Отправляет сообщение с информацией о том, как заморозить аккаунт и его последствиях. 321 """ 322 await callback.message.answer( 323 "Заморозка аккаунта подразумевает приостановку ежедневных списаний " 324 "и, соответственно, блокировку всех созданных конфигураций." 325 "\nРазморозить свой аккаунт можно в меню /app. После разморозки восстановление конфигураций произойдет в течение 1 минуты." 326 "\n\n<b>Стоимость услуги равна одному ежедневному списанию вашего тарифа!</b>" 327 "\n<b>Разблокировка бесплатна.</b>", 328 reply_markup=kb.freeze_user_button, 329 ) 330 331 332@router.message(Command("server")) 333@router.callback_query(F.data == "server_status") 334@bot_except 335async def server_status(trigger: Union[Message, CallbackQuery], bot: Bot): 336 """Отправляет информацию о состоянии сервера. 337 338 Args: 339 trigger (Union[Message, CallbackQuery]): Сообщение или событие обратного вызова, инициировавшее команду. 340 bot (Bot): Экземпляр бота для выполнения действий. 341 342 Отправляет сообщение с текущим состоянием сервера и его загрузкой. 343 """ 344 await bot.send_chat_action(trigger.from_user.id, "typing") 345 346 user_data: UserData = await find_user(trigger) 347 if not user_data: 348 return 349 elif user_data.stage < 2: 350 await getattr(trigger, "message", trigger).answer( 351 "Команда заблокирована. Выберите тариф от 'Расширенного' или выше." 352 ) 353 return 354 355 try: 356 wg = WgServerTools() 357 358 server_status = await wg.get_server_status() 359 cpu_usage = await wg.get_server_cpu_usage() 360 361 except WireguardError: 362 await getattr(trigger, "message", trigger).answer(text.WG_ERROR) 363 364 else: 365 server_data = ( 366 "Текущие параметры сервера:\n\n" 367 f"🖥 Сервер: <b>{server_status.capitalize()}</b>\n\n" 368 f"🦾 СPU usage: <b>{cpu_usage}</b>" 369 ) 370 371 await getattr(trigger, "message", trigger).answer(server_data) 372 373 374@router.message(Command("speed")) 375@router.callback_query(F.data == "server_speed") 376@bot_except 377async def server_speed(trigger: Union[Message, CallbackQuery], bot: Bot): 378 """Отправляет информацию о скорости сервера. 379 380 Args: 381 trigger (Union[Message, CallbackQuery]): Сообщение или событие обратного вызова, инициировавшее команду. 382 bot (Bot): Экземпляр бота для выполнения действий. 383 384 Отправляет сообщение с текущей доступной скоростью интернет-соединения по VPN. 385 """ 386 await bot.send_chat_action(trigger.from_user.id, "typing") 387 388 user_data: UserData = await find_user(trigger) 389 if not user_data: 390 return 391 elif user_data.stage < 2: 392 await getattr(trigger, "message", trigger).answer( 393 "Команда заблокирована. Выберите тариф от 'Расширенного' или выше." 394 ) 395 return 396 397 try: 398 server_speed_in, server_speed_out = await test_server_speed() 399 400 except WireguardError: 401 await getattr(trigger, "message", trigger).answer( 402 text.WG_ERROR, show_alert=True 403 ) 404 except DatabaseError: 405 await trigger.answer(text=text.DB_ERROR, show_alert=True) 406 except BaseBotError: 407 await trigger.answer( 408 text="Ошибка измерения пропускной способности. Попробуйте позже.", 409 show_alert=True, 410 ) 411 412 else: 413 server_data = ( 414 "Текущая максимально доступная скорость интернет соединения по VPN:\n\n" 415 f"📥 Скачивание: <b>{round(server_speed_in/1048576, 2)} Мбит/с</b>\n\n" 416 f"📤 Загрузка: <b>{round(server_speed_out/1048576, 2)} Мбит/с</b>" 417 ) 418 419 await getattr(trigger, "message", trigger).answer(server_data) 420 421 422@router.message(Command("chat")) 423@router.message(F.text == "Чат") 424@router.callback_query(F.data == "invite_to_chat") 425@bot_except 426async def get_chat_invite(trigger: Union[Message, CallbackQuery], bot: Bot): 427 """Отправляет приглашение в чат. 428 429 Args: 430 trigger (Union[Message, CallbackQuery]): Сообщение или событие обратного вызова, инициировавшее команду. 431 bot (Bot): Экземпляр бота для выполнения действий. 432 433 Отправляет сообщение с ссылкой на чат для зарегистрированных пользователей. 434 """ 435 user_data = await get_user(trigger.from_user.id) 436 437 if user_data is None: 438 await getattr(trigger, "message", trigger).answer( 439 "Чат доступен только зарегистрированным пользователям. " 440 "Для начала выполните команду /reg" 441 ) 442 else: 443 try: 444 link = await bot.create_chat_invite_link( 445 settings.BOT_CHAT, "chat", timedelta(hours=12), member_limit=1 446 ) 447 except TelegramBadRequest: 448 logger.exception("Недоступен пользовательский чат") 449 else: 450 await getattr(trigger, "message", trigger).answer( 451 "🎉Поздравляем! Вам открыт доступ в клиентский чат.", 452 reply_markup=kb.get_chat_button(link.invite_link), 453 )
30async def more_help_info(callback: CallbackQuery): 31 """Отправляет дополнительную информацию о помощи. 32 33 Args: 34 callback (CallbackQuery): Событие обратного вызова, содержащее информацию о запросе. 35 36 Отправляет сообщение с предложением задать дополнительные вопросы и кнопкой для доступа к меню помощи. 37 """ 38 await callback.message.answer( 39 "Если у вас есть дополнительные вопросы, не стесняйтесь спрашивать! Мы здесь, чтобы помочь вам. 🚀", 40 reply_markup=kb.get_help_menu( 41 callback.from_user.full_name, callback.from_user.id 42 ), 43 )
Отправляет дополнительную информацию о помощи.
Arguments:
- callback (CallbackQuery): Событие обратного вызова, содержащее информацию о запросе.
Отправляет сообщение с предложением задать дополнительные вопросы и кнопкой для доступа к меню помощи.
46async def change_help_page(message: Message, pages: list, page: int, prefix: str): 47 """Изменяет страницу помощи. 48 49 Args: 50 message (Message): Сообщение, которое будет изменено. 51 pages (list): Список страниц помощи. 52 page (int): Индекс текущей страницы. 53 prefix (str): Префикс для кнопок навигации. 54 55 Обновляет текст сообщения с новой страницей помощи и кнопками навигации. 56 """ 57 with suppress(TelegramBadRequest): 58 await message.edit_text( 59 pages[page], reply_markup=kb.get_help_book_keyboard(pages, page, prefix) 60 )
Изменяет страницу помощи.
Arguments:
- message (Message): Сообщение, которое будет изменено.
- pages (list): Список страниц помощи.
- page (int): Индекс текущей страницы.
- prefix (str): Префикс для кнопок навигации.
Обновляет текст сообщения с новой страницей помощи и кнопками навигации.
63async def post_help_book( 64 callback: CallbackQuery, book: list, step: str, start_message: str, prefix: str 65): 66 """Отправляет книгу помощи пользователю. 67 68 Args: 69 callback (CallbackQuery): Событие обратного вызова, содержащее информацию о запросе. 70 book (list): Список шагов помощи. 71 step (str): Текущий шаг. 72 start_message (str): Сообщение, отправляемое в начале. 73 prefix (str): Префикс для кнопок навигации. 74 75 Отправляет сообщения с шагами помощи в зависимости от текущего шага. 76 """ 77 if step == "start": 78 await callback.message.answer(start_message) 79 80 await callback.message.answer( 81 book[0], 82 reply_markup=kb.get_help_book_keyboard(pages=book, page=0, prefix=prefix), 83 ) 84 elif step.isdigit(): 85 await change_help_page( 86 callback.message, pages=book, page=int(step), prefix=prefix 87 ) 88 else: 89 for step in book: 90 await callback.message.answer(step) 91 await more_help_info(callback)
Отправляет книгу помощи пользователю.
Arguments:
- callback (CallbackQuery): Событие обратного вызова, содержащее информацию о запросе.
- book (list): Список шагов помощи.
- step (str): Текущий шаг.
- start_message (str): Сообщение, отправляемое в начале.
- prefix (str): Префикс для кнопок навигации.
Отправляет сообщения с шагами помощи в зависимости от текущего шага.
94@router.message(Command("help")) 95@router.message(F.text == "Помощь") 96@router.callback_query(F.data == "main_help") 97@bot_except 98async def help_me(trigger: Union[Message, CallbackQuery]): 99 """Обработчик команды помощи. 100 101 Args: 102 trigger (Union[Message, CallbackQuery]): Сообщение или событие обратного вызова, инициировавшее команду. 103 104 Отправляет сообщение с предложением помощи и кнопками для доступа к меню помощи. 105 """ 106 await getattr(trigger, "message", trigger).answer( 107 "Чем вам помочь?", 108 reply_markup=kb.get_help_menu( 109 trigger.from_user.full_name, trigger.from_user.id 110 ), 111 )
Обработчик команды помощи.
Arguments:
- trigger (Union[Message, CallbackQuery]): Сообщение или событие обратного вызова, инициировавшее команду.
Отправляет сообщение с предложением помощи и кнопками для доступа к меню помощи.
114@router.callback_query(F.data == "bot_info") 115@bot_except 116async def bot_info(callback: CallbackQuery): 117 """Отправляет информацию о боте. 118 119 Args: 120 callback (CallbackQuery): Событие обратного вызова, содержащее информацию о запросе. 121 122 Отправляет сообщение с информацией о боте и кнопкой для доступа к дополнительной помощи. 123 """ 124 await callback.message.answer(text.BOT_INFO, reply_markup=kb.static_join_button) 125 await more_help_info(callback)
Отправляет информацию о боте.
Arguments:
- callback (CallbackQuery): Событие обратного вызова, содержащее информацию о запросе.
Отправляет сообщение с информацией о боте и кнопкой для доступа к дополнительной помощи.
128@router.callback_query(F.data.startswith("first_help_info_")) 129@bot_except 130async def next_help(callback: CallbackQuery): 131 """Обработчик перехода к следующему шагу помощи. 132 133 Args: 134 callback (CallbackQuery): Событие обратного вызова, содержащее информацию о запросе. 135 136 Отправляет сообщения с шагами помощи в зависимости от текущего шага. 137 """ 138 current_step: str = callback.data.split("_")[-1] 139 140 await post_help_book( 141 callback, 142 book=text.BOT_STEPS, 143 step=current_step, 144 start_message="🤖 <b>Что делать дальше? Вот краткий алгоритм работы с нашим ботом и WireGuard:</b>", 145 prefix="first_help_info", 146 )
Обработчик перехода к следующему шагу помощи.
Arguments:
- callback (CallbackQuery): Событие обратного вызова, содержащее информацию о запросе.
Отправляет сообщения с шагами помощи в зависимости от текущего шага.
149@router.callback_query(F.data == "wg_help_info") 150@bot_except 151async def wg_help(callback: CallbackQuery): 152 """Отправляет информацию о платформе для установки WireGuard. 153 154 Args: 155 callback (CallbackQuery): Событие обратного вызова, содержащее информацию о запросе. 156 157 Отправляет сообщение с вопросом о платформе для установки WireGuard и кнопками для выбора. 158 """ 159 await callback.message.answer( 160 "На какую платформу вы хотите установить WireGuard?", 161 reply_markup=kb.static_wg_platform_keyboard, 162 )
Отправляет информацию о платформе для установки WireGuard.
Arguments:
- callback (CallbackQuery): Событие обратного вызова, содержащее информацию о запросе.
Отправляет сообщение с вопросом о платформе для установки WireGuard и кнопками для выбора.
165@router.callback_query(F.data.startswith("wg_help_info_")) 166@bot_except 167async def wg_help_platform(callback: CallbackQuery): 168 """Обработчик помощи по установке WireGuard на выбранной платформе. 169 170 Args: 171 callback (CallbackQuery): Событие обратного вызова, содержащее информацию о запросе. 172 173 Отправляет сообщения с шагами помощи для установки WireGuard на выбранной платформе. 174 """ 175 *_, current_platform, current_step = callback.data.split("_") 176 177 await post_help_book( 178 callback, 179 book=text.WG_STEPS[current_platform], 180 step=current_step, 181 start_message=f"🛠️ <b>Настройка WireGuard на {current_platform}:</b>", 182 prefix=f"wg_help_info_{current_platform}", 183 )
Обработчик помощи по установке WireGuard на выбранной платформе.
Arguments:
- callback (CallbackQuery): Событие обратного вызова, содержащее информацию о запросе.
Отправляет сообщения с шагами помощи для установки WireGuard на выбранной платформе.
186@router.callback_query(F.data.startswith("error_help_info")) 187@bot_except 188async def error_help(callback: CallbackQuery): 189 """Обработчик помощи по устранению ошибок. 190 191 Args: 192 callback (CallbackQuery): Событие обратного вызова, содержащее информацию о запросе. 193 194 Отправляет сообщения с шагами помощи для устранения ошибок. 195 """ 196 current_step: str = callback.data.split("_")[-1] 197 198 await post_help_book( 199 callback, 200 book=text.BOT_ERROR_STEP, 201 step=current_step, 202 start_message="📋 <b>Не волнуйтесь, вот инструкции по устранению проблем с DanVPN</b>", 203 prefix="error_help_info", 204 )
Обработчик помощи по устранению ошибок.
Arguments:
- callback (CallbackQuery): Событие обратного вызова, содержащее информацию о запросе.
Отправляет сообщения с шагами помощи для устранения ошибок.
207@router.message(Command("time")) 208@bot_except 209async def started(message: Message, started_at): 210 """Отправляет время начала работы бота. 211 212 Args: 213 message (Message): Сообщение, инициировавшее команду. 214 started_at: Время начала работы бота. 215 216 Отправляет сообщение с временем начала работы бота. 217 """ 218 await message.answer(f"Время начала работы бота: {started_at}")
Отправляет время начала работы бота.
Arguments:
- message (Message): Сообщение, инициировавшее команду.
- started_at: Время начала работы бота.
Отправляет сообщение с временем начала работы бота.
221@router.message(Command("id")) 222@router.callback_query(F.data == "user_id_info") 223@bot_except 224async def start_bot(trigger: Union[Message, CallbackQuery]): 225 """Отправляет ID пользователя. 226 227 Args: 228 trigger (Union[Message, CallbackQuery]): Сообщение или событие обратного вызова, инициировавшее команду. 229 230 Отправляет сообщение с Telegram ID пользователя. 231 """ 232 await getattr(trigger, "message", trigger).answer( 233 f'Ваш Telegram ID\n\n<span class="tg-spoiler">{trigger.from_user.id}</span>' 234 )
Отправляет ID пользователя.
Arguments:
- trigger (Union[Message, CallbackQuery]): Сообщение или событие обратного вызова, инициировавшее команду.
Отправляет сообщение с Telegram ID пользователя.
237@router.message(Command("cmd")) 238@router.message(Command("commands")) 239@router.message(F.text == "Команды") 240@router.callback_query(F.data == "cmd_help_info") 241@bot_except 242async def commands_list(trigger: Union[Message, CallbackQuery]): 243 """Отправляет список доступных команд. 244 245 Args: 246 trigger (Union[Message, CallbackQuery]): Сообщение или событие обратного вызова, инициировавшее команду. 247 248 Отправляет сообщение с перечислением доступных команд и их описанием. 249 """ 250 help_t = as_list( 251 Bold("Запуск:"), 252 "/start - запуск (перезагрузка) бота", 253 Bold("Действия с аккаунтом:"), 254 as_marked_section( 255 "/account | /app - Основной функционал аккаунта", 256 "/reg - Регистрация в БД Бота", 257 "/freeze - Заморозить аккаунт", 258 "/recover - Разморозить аккаунт", 259 "/chat - Получить доступ в клиентский чат", 260 marker="~ ", 261 ), 262 Bold("Действия с конфигурациями:"), 263 as_marked_section( 264 "/me | /config - данные о моих конфигурациях wireguard", 265 "/create - создать конфигурацию", 266 marker="~ ", 267 ), 268 Bold("Действия с подпиской:"), 269 as_marked_section( 270 "/sub - Купить подписку", 271 "/refund - Сделать запрос на возврат средств", 272 "/history - История транзакций", 273 marker="~ ", 274 ), 275 Bold("Информация:"), 276 as_marked_section( 277 "/help - Помощь", 278 "/cmd - Список всех команд", 279 "/admin - функционал администратора", 280 "/bug - Доложить о баге", 281 "/id - Ваш Telegram ID", 282 "/time - время запуска бота", 283 marker="~ ", 284 ), 285 as_marked_section( 286 Bold("Расширенные возможности (тарифы от расширенного и выше):"), 287 "/server - Анализ работы сервера", 288 "/speed - Максимально доступная скорость VPN на данный момент", 289 "/mute - Отключить уведомления", 290 ), 291 ) 292 await getattr(trigger, "message", trigger).answer(**help_t.as_kwargs())
Отправляет список доступных команд.
Arguments:
- trigger (Union[Message, CallbackQuery]): Сообщение или событие обратного вызова, инициировавшее команду.
Отправляет сообщение с перечислением доступных команд и их описанием.
295@router.callback_query(F.data == "freeze_info") 296@bot_except 297async def freeze_config_info(callback: CallbackQuery): 298 """Отправляет информацию о заморозке конфигураций. 299 300 Args: 301 callback (CallbackQuery): Событие обратного вызова, содержащее информацию о запросе. 302 303 Отправляет сообщение с информацией о том, как заморозить конфигурации и что делать в случае проблем. 304 """ 305 await callback.message.answer( 306 "Конфигурации замораживаются, когда становятся недоступными. " 307 "\n\nПроверьте, достаточно ли средств на вашем счете? Соответствует ли количество ваших конфигураций вашему тарифу? " 308 "Возможно недавно произошли изменения в вашем тарифе, подождите несколько минут и попробуйте снова." 309 "\n\nЕсли вам все равно не понятно, почему ваша конфигурация заблокирована, воспользуйтесь командой /bug и сообщите о вашей проблеме." 310 )
Отправляет информацию о заморозке конфигураций.
Arguments:
- callback (CallbackQuery): Событие обратного вызова, содержащее информацию о запросе.
Отправляет сообщение с информацией о том, как заморозить конфигурации и что делать в случае проблем.
313@router.callback_query(F.data == "freeze_account_info") 314@bot_except 315async def freeze_user_info(callback: CallbackQuery): 316 """Отправляет информацию о заморозке аккаунта. 317 318 Args: 319 callback (CallbackQuery): Событие обратного вызова, содержащее информацию о запросе. 320 321 Отправляет сообщение с информацией о том, как заморозить аккаунт и его последствиях. 322 """ 323 await callback.message.answer( 324 "Заморозка аккаунта подразумевает приостановку ежедневных списаний " 325 "и, соответственно, блокировку всех созданных конфигураций." 326 "\nРазморозить свой аккаунт можно в меню /app. После разморозки восстановление конфигураций произойдет в течение 1 минуты." 327 "\n\n<b>Стоимость услуги равна одному ежедневному списанию вашего тарифа!</b>" 328 "\n<b>Разблокировка бесплатна.</b>", 329 reply_markup=kb.freeze_user_button, 330 )
Отправляет информацию о заморозке аккаунта.
Arguments:
- callback (CallbackQuery): Событие обратного вызова, содержащее информацию о запросе.
Отправляет сообщение с информацией о том, как заморозить аккаунт и его последствиях.
333@router.message(Command("server")) 334@router.callback_query(F.data == "server_status") 335@bot_except 336async def server_status(trigger: Union[Message, CallbackQuery], bot: Bot): 337 """Отправляет информацию о состоянии сервера. 338 339 Args: 340 trigger (Union[Message, CallbackQuery]): Сообщение или событие обратного вызова, инициировавшее команду. 341 bot (Bot): Экземпляр бота для выполнения действий. 342 343 Отправляет сообщение с текущим состоянием сервера и его загрузкой. 344 """ 345 await bot.send_chat_action(trigger.from_user.id, "typing") 346 347 user_data: UserData = await find_user(trigger) 348 if not user_data: 349 return 350 elif user_data.stage < 2: 351 await getattr(trigger, "message", trigger).answer( 352 "Команда заблокирована. Выберите тариф от 'Расширенного' или выше." 353 ) 354 return 355 356 try: 357 wg = WgServerTools() 358 359 server_status = await wg.get_server_status() 360 cpu_usage = await wg.get_server_cpu_usage() 361 362 except WireguardError: 363 await getattr(trigger, "message", trigger).answer(text.WG_ERROR) 364 365 else: 366 server_data = ( 367 "Текущие параметры сервера:\n\n" 368 f"🖥 Сервер: <b>{server_status.capitalize()}</b>\n\n" 369 f"🦾 СPU usage: <b>{cpu_usage}</b>" 370 ) 371 372 await getattr(trigger, "message", trigger).answer(server_data)
Отправляет информацию о состоянии сервера.
Arguments:
- trigger (Union[Message, CallbackQuery]): Сообщение или событие обратного вызова, инициировавшее команду.
- bot (Bot): Экземпляр бота для выполнения действий.
Отправляет сообщение с текущим состоянием сервера и его загрузкой.
375@router.message(Command("speed")) 376@router.callback_query(F.data == "server_speed") 377@bot_except 378async def server_speed(trigger: Union[Message, CallbackQuery], bot: Bot): 379 """Отправляет информацию о скорости сервера. 380 381 Args: 382 trigger (Union[Message, CallbackQuery]): Сообщение или событие обратного вызова, инициировавшее команду. 383 bot (Bot): Экземпляр бота для выполнения действий. 384 385 Отправляет сообщение с текущей доступной скоростью интернет-соединения по VPN. 386 """ 387 await bot.send_chat_action(trigger.from_user.id, "typing") 388 389 user_data: UserData = await find_user(trigger) 390 if not user_data: 391 return 392 elif user_data.stage < 2: 393 await getattr(trigger, "message", trigger).answer( 394 "Команда заблокирована. Выберите тариф от 'Расширенного' или выше." 395 ) 396 return 397 398 try: 399 server_speed_in, server_speed_out = await test_server_speed() 400 401 except WireguardError: 402 await getattr(trigger, "message", trigger).answer( 403 text.WG_ERROR, show_alert=True 404 ) 405 except DatabaseError: 406 await trigger.answer(text=text.DB_ERROR, show_alert=True) 407 except BaseBotError: 408 await trigger.answer( 409 text="Ошибка измерения пропускной способности. Попробуйте позже.", 410 show_alert=True, 411 ) 412 413 else: 414 server_data = ( 415 "Текущая максимально доступная скорость интернет соединения по VPN:\n\n" 416 f"📥 Скачивание: <b>{round(server_speed_in/1048576, 2)} Мбит/с</b>\n\n" 417 f"📤 Загрузка: <b>{round(server_speed_out/1048576, 2)} Мбит/с</b>" 418 ) 419 420 await getattr(trigger, "message", trigger).answer(server_data)
Отправляет информацию о скорости сервера.
Arguments:
- trigger (Union[Message, CallbackQuery]): Сообщение или событие обратного вызова, инициировавшее команду.
- bot (Bot): Экземпляр бота для выполнения действий.
Отправляет сообщение с текущей доступной скоростью интернет-соединения по VPN.
423@router.message(Command("chat")) 424@router.message(F.text == "Чат") 425@router.callback_query(F.data == "invite_to_chat") 426@bot_except 427async def get_chat_invite(trigger: Union[Message, CallbackQuery], bot: Bot): 428 """Отправляет приглашение в чат. 429 430 Args: 431 trigger (Union[Message, CallbackQuery]): Сообщение или событие обратного вызова, инициировавшее команду. 432 bot (Bot): Экземпляр бота для выполнения действий. 433 434 Отправляет сообщение с ссылкой на чат для зарегистрированных пользователей. 435 """ 436 user_data = await get_user(trigger.from_user.id) 437 438 if user_data is None: 439 await getattr(trigger, "message", trigger).answer( 440 "Чат доступен только зарегистрированным пользователям. " 441 "Для начала выполните команду /reg" 442 ) 443 else: 444 try: 445 link = await bot.create_chat_invite_link( 446 settings.BOT_CHAT, "chat", timedelta(hours=12), member_limit=1 447 ) 448 except TelegramBadRequest: 449 logger.exception("Недоступен пользовательский чат") 450 else: 451 await getattr(trigger, "message", trigger).answer( 452 "🎉Поздравляем! Вам открыт доступ в клиентский чат.", 453 reply_markup=kb.get_chat_button(link.invite_link), 454 )
Отправляет приглашение в чат.
Arguments:
- trigger (Union[Message, CallbackQuery]): Сообщение или событие обратного вызова, инициировавшее команду.
- bot (Bot): Экземпляр бота для выполнения действий.
Отправляет сообщение с ссылкой на чат для зарегистрированных пользователей.