diff --git a/client.py b/client.py
index 96c105f5..c7609ec8 100644
--- a/client.py
+++ b/client.py
@@ -72,7 +72,14 @@ async def add_client(xui: py3xui.AsyncApi, config: ClientConfig) -> dict[str, An
async def extend_client_key(
- xui: py3xui.AsyncApi, inbound_id: int, email: str, new_expiry_time: int, client_id: str, total_gb: int, sub_id: str, tg_id: int
+ xui: py3xui.AsyncApi,
+ inbound_id: int,
+ email: str,
+ new_expiry_time: int,
+ client_id: str,
+ total_gb: int,
+ sub_id: str,
+ tg_id: int,
) -> bool | None:
"""
Обновляет срок действия ключа клиента.
diff --git a/handlers/admin/users/users_handler.py b/handlers/admin/users/users_handler.py
index c95780b1..db48c12e 100644
--- a/handlers/admin/users/users_handler.py
+++ b/handlers/admin/users/users_handler.py
@@ -733,10 +733,11 @@ async def confirm_restore_trials(callback_query: types.CallbackQuery):
await callback_query.message.edit_text(
text="⚠ Вы уверены, что хотите восстановить пробники для пользователей? \n\n"
- "Только для тех, у кого нет активной подписки!",
- reply_markup=builder.as_markup()
+ "Только для тех, у кого нет активной подписки!",
+ reply_markup=builder.as_markup(),
)
+
@router.callback_query(AdminPanelCallback.filter(F.action == "confirm_restore_trials"), IsAdminFilter())
async def restore_trials(callback_query: types.CallbackQuery, session: Any):
"""
@@ -759,15 +760,13 @@ async def restore_trials(callback_query: types.CallbackQuery, session: Any):
await callback_query.message.edit_text(
text="✅ Пробники успешно восстановлены для пользователей, у которых нет активных подписок.",
- reply_markup=builder.as_markup()
+ reply_markup=builder.as_markup(),
)
@router.callback_query(AdminUserEditorCallback.filter(F.action == "users_export_referrals"), IsAdminFilter())
async def handle_users_export_referrals(
- callback_query: types.CallbackQuery,
- callback_data: AdminUserEditorCallback,
- session: Any
+ callback_query: types.CallbackQuery, callback_data: AdminUserEditorCallback, session: Any
):
"""
Обработчик: получает tg_id реферера из callback_data,
@@ -783,6 +782,5 @@ async def handle_users_export_referrals(
return
await callback_query.message.answer_document(
- document=csv_file,
- caption=f"Список рефералов для пользователя {referrer_tg_id}."
- )
\ No newline at end of file
+ document=csv_file, caption=f"Список рефералов для пользователя {referrer_tg_id}."
+ )
diff --git a/handlers/buttons/yookassa.py b/handlers/buttons/yookassa.py
index 387fc745..5aaded81 100644
--- a/handlers/buttons/yookassa.py
+++ b/handlers/buttons/yookassa.py
@@ -4,4 +4,4 @@ BACK = "⬅️ Назад"
CUSTOM_SUM = "💰 Ввести свою сумму"
CUSTOM_SUM_ANSWER = "Пожалуйста, введите сумму пополнения."
PROFILE = "👤 Личный кабинет"
-DEFAULT_PAYMENT_MESSAGE = "Вы выбрали пополнение на {amount} рублей. Перейдите по ссылке для оплаты:"
\ No newline at end of file
+DEFAULT_PAYMENT_MESSAGE = "Вы выбрали пополнение на {amount} рублей. Перейдите по ссылке для оплаты:"
diff --git a/handlers/keys/keys.py b/handlers/keys/keys.py
index e41a6b6d..1c603573 100644
--- a/handlers/keys/keys.py
+++ b/handlers/keys/keys.py
@@ -26,7 +26,7 @@ from config import (
TOTAL_GB,
USE_COUNTRY_SELECTION,
USE_NEW_PAYMENT_FLOW,
- TOGGLE_CLIENT
+ TOGGLE_CLIENT,
)
from bot import bot
@@ -146,10 +146,7 @@ async def process_callback_view_key(callback_query: CallbackQuery, session: Any)
is_frozen = record["is_frozen"]
if is_frozen:
- response_message = (
- "Подписка заморожена.\n"
- "Дата истечения будет обновлена после разморозки."
- )
+ response_message = "Подписка заморожена.\nДата истечения будет обновлена после разморозки."
builder = InlineKeyboardBuilder()
builder.row(
@@ -174,7 +171,7 @@ async def process_callback_view_key(callback_query: CallbackQuery, session: Any)
reply_markup=keyboard,
media_path=image_path,
)
-
+
else:
key = record["key"]
expiry_time = record["expiry_time"]
@@ -185,17 +182,13 @@ async def process_callback_view_key(callback_query: CallbackQuery, session: Any)
time_left = expiry_date - current_date
if time_left.total_seconds() <= 0:
- days_left_message = (
- "🕒 Статус подписки:\n🔴 Истекла\nОсталось часов: 0\nОсталось минут: 0"
- )
+ days_left_message = "🕒 Статус подписки:\n🔴 Истекла\nОсталось часов: 0\nОсталось минут: 0"
else:
total_seconds = int(time_left.total_seconds())
days = total_seconds // 86400
hours = (total_seconds % 86400) // 3600
minutes = (total_seconds % 3600) // 60
- days_left_message = (
- f"Осталось: {days} дней, {hours} часов, {minutes} минут"
- )
+ days_left_message = f"Осталось: {days} дней, {hours} часов, {minutes} минут"
formatted_expiry_date = expiry_date.strftime("%d %B %Y года")
response_message = key_message(
@@ -245,18 +238,12 @@ async def process_callback_view_key(callback_query: CallbackQuery, session: Any)
)
else:
builder.row(
- InlineKeyboardButton(
- text="⏳ Продлить подписку",
- callback_data=f"renew_key|{key_name}"
- )
+ InlineKeyboardButton(text="⏳ Продлить подписку", callback_data=f"renew_key|{key_name}")
)
if USE_COUNTRY_SELECTION:
builder.row(
- InlineKeyboardButton(
- text="🌍 Сменить локацию",
- callback_data=f"change_location|{key_name}"
- )
+ InlineKeyboardButton(text="🌍 Сменить локацию", callback_data=f"change_location|{key_name}")
)
if TOGGLE_CLIENT:
@@ -297,8 +284,7 @@ async def process_callback_view_key(callback_query: CallbackQuery, session: Any)
async def process_callback_unfreeze_subscription(callback_query: CallbackQuery, session: Any):
key_name = callback_query.data.split("|")[1]
confirm_text = (
- "Хотите включить (разморозить) подписку?\n\n"
- "После включения доступа трафик и время снова начнут расходоваться."
+ "Хотите включить (разморозить) подписку?\n\nПосле включения доступа трафик и время снова начнут расходоваться."
)
builder = InlineKeyboardBuilder()
@@ -356,7 +342,7 @@ async def process_callback_unfreeze_subscription_confirm(callback_query: Callbac
""",
new_expiry_time,
record["tg_id"],
- client_id
+ client_id,
)
await renew_key_in_cluster(
@@ -364,16 +350,11 @@ async def process_callback_unfreeze_subscription_confirm(callback_query: Callbac
email=email,
client_id=client_id,
new_expiry_time=new_expiry_time,
- total_gb=TOTAL_GB
- )
- text_ok = (
- "✅ Подписка успешно включена.\n\n"
- "Теперь трафик и время подписки будут расходоваться."
+ total_gb=TOTAL_GB,
)
+ text_ok = "✅ Подписка успешно включена.\n\nТеперь трафик и время подписки будут расходоваться."
builder = InlineKeyboardBuilder()
- builder.row(
- InlineKeyboardButton(text="⬅️ Назад", callback_data=f"view_key|{key_name}")
- )
+ builder.row(InlineKeyboardButton(text="⬅️ Назад", callback_data=f"view_key|{key_name}"))
await edit_or_send_message(
target_message=callback_query.message,
text=text_ok,
@@ -381,13 +362,10 @@ async def process_callback_unfreeze_subscription_confirm(callback_query: Callbac
)
else:
text_error = (
- "Произошла ошибка при включении подписки.\n"
- f"Детали: {result.get('error') or result.get('results')}"
+ f"Произошла ошибка при включении подписки.\nДетали: {result.get('error') or result.get('results')}"
)
builder = InlineKeyboardBuilder()
- builder.row(
- InlineKeyboardButton(text="⬅️ Назад", callback_data=f"view_key|{key_name}")
- )
+ builder.row(InlineKeyboardButton(text="⬅️ Назад", callback_data=f"view_key|{key_name}"))
await edit_or_send_message(
target_message=callback_query.message,
text=text_error,
@@ -455,7 +433,7 @@ async def process_callback_freeze_subscription_confirm(callback_query: CallbackQ
now_ms = int(time.time() * 1000)
time_left = record["expiry_time"] - now_ms
if time_left < 0:
- time_left = 0
+ time_left = 0
update_result = await session.execute(
"""
@@ -467,7 +445,7 @@ async def process_callback_freeze_subscription_confirm(callback_query: CallbackQ
""",
time_left,
record["tg_id"],
- client_id
+ client_id,
)
text_ok = (
@@ -475,9 +453,7 @@ async def process_callback_freeze_subscription_confirm(callback_query: CallbackQ
"Чтобы включить обратно, зайдите в меню ключа и нажмите «Включить подписку»."
)
builder = InlineKeyboardBuilder()
- builder.row(
- InlineKeyboardButton(text="⬅️ Назад", callback_data=f"view_key|{key_name}")
- )
+ builder.row(InlineKeyboardButton(text="⬅️ Назад", callback_data=f"view_key|{key_name}"))
await edit_or_send_message(
target_message=callback_query.message,
text=text_ok,
@@ -485,13 +461,10 @@ async def process_callback_freeze_subscription_confirm(callback_query: CallbackQ
)
else:
text_error = (
- "Произошла ошибка при заморозке подписки.\n"
- f"Детали: {result.get('error') or result.get('results')}"
+ f"Произошла ошибка при заморозке подписки.\nДетали: {result.get('error') or result.get('results')}"
)
builder = InlineKeyboardBuilder()
- builder.row(
- InlineKeyboardButton(text="⬅️ Назад", callback_data=f"view_key|{key_name}")
- )
+ builder.row(InlineKeyboardButton(text="⬅️ Назад", callback_data=f"view_key|{key_name}"))
await edit_or_send_message(
target_message=callback_query.message,
text=text_error,
diff --git a/handlers/notifications/general_notifications.py b/handlers/notifications/general_notifications.py
index 2529cf48..2895f305 100644
--- a/handlers/notifications/general_notifications.py
+++ b/handlers/notifications/general_notifications.py
@@ -17,7 +17,7 @@ from config import (
RENEWAL_PRICES,
TOTAL_GB,
TRIAL_TIME_DISABLE,
- NOTIFY_INACTIVE_TRAFFIC
+ NOTIFY_INACTIVE_TRAFFIC,
)
from database import (
diff --git a/middlewares/loggings.py b/middlewares/loggings.py
index db4a2ebf..f329759f 100644
--- a/middlewares/loggings.py
+++ b/middlewares/loggings.py
@@ -1,5 +1,5 @@
from collections.abc import Awaitable, Callable
-from typing import Any,TypedDict
+from typing import Any, TypedDict
from aiogram import BaseMiddleware
from aiogram.types import CallbackQuery, InlineQuery, Message, TelegramObject, User
diff --git a/middlewares/throttling.py b/middlewares/throttling.py
index 50e20bf4..710744c5 100644
--- a/middlewares/throttling.py
+++ b/middlewares/throttling.py
@@ -28,4 +28,4 @@ class ThrottlingMiddleware(BaseMiddleware):
else:
self.cache[user_id] = current_count + 1
- return await handler(event, data)
\ No newline at end of file
+ return await handler(event, data)
diff --git a/servers.py b/servers.py
index d23bda94..b403e24f 100644
--- a/servers.py
+++ b/servers.py
@@ -60,10 +60,7 @@ async def notify_admin(server_name: str, status: str, down_duration: timedelta =
)
else:
downtime = str(down_duration).split(".")[0]
- message = (
- f"✅ Сервер '{server_name}' снова в сети!\n\n"
- f"⏳ Время простоя: {downtime}."
- )
+ message = f"✅ Сервер '{server_name}' снова в сети!\n\n⏳ Время простоя: {downtime}."
for admin_id in ADMIN_ID:
logger.info(f"📨 Отправляем уведомление '{status}' администратору {admin_id} о сервере {server_name}")
@@ -119,11 +116,13 @@ async def check_servers():
if last_ping_time is None:
last_ping_times[server_name] = current_time
- last_down_times[server_name] = current_time
+ last_down_times[server_name] = current_time
if last_ping_time and (current_time - last_ping_time > timedelta(seconds=PING_TIME * 3)):
if server_name not in notified_servers:
- logger.warning(f"🚨 Уведомление: сервер {server_name} не отвечает более {PING_TIME * 3} секунд!")
+ logger.warning(
+ f"🚨 Уведомление: сервер {server_name} не отвечает более {PING_TIME * 3} секунд!"
+ )
await notify_admin(server_name, "down")
notified_servers.add(server_name)
last_down_times[server_name] = current_time
@@ -145,4 +144,4 @@ async def check_servers():
def extract_host(api_url: str) -> str:
"""Извлекает хост из `api_url`."""
match = re.match(r"(https?://)?([^:/]+)", api_url)
- return match.group(2) if match else api_url
\ No newline at end of file
+ return match.group(2) if match else api_url
diff --git a/utils/csv_export.py b/utils/csv_export.py
index 276c79ea..179249c7 100644
--- a/utils/csv_export.py
+++ b/utils/csv_export.py
@@ -115,14 +115,14 @@ async def export_referrals_csv(referrer_tg_id: int, session: Any) -> BufferedInp
WHERE r.referrer_tg_id = $1
ORDER BY r.referred_tg_id
""",
- referrer_tg_id
+ referrer_tg_id,
)
if not rows:
return None
output = StringIO()
- writer = csv.writer(output, delimiter=';')
+ writer = csv.writer(output, delimiter=";")
writer.writerow(["Приглашённый (tg_id)", "Имя"])
for row in rows:
@@ -136,4 +136,4 @@ async def export_referrals_csv(referrer_tg_id: int, session: Any) -> BufferedInp
csv_data = output.getvalue().encode("utf-8")
filename = f"referrals_{referrer_tg_id}.csv"
- return BufferedInputFile(file=csv_data, filename=filename)
\ No newline at end of file
+ return BufferedInputFile(file=csv_data, filename=filename)