diff --git a/database.py b/database.py
index ea1b5cab..693ab291 100644
--- a/database.py
+++ b/database.py
@@ -433,7 +433,7 @@ async def get_keys(tg_id: int, session: Any):
try:
records = await session.fetch(
"""
- SELECT client_id, email, created_at, key
+ SELECT *
FROM keys
WHERE tg_id = $1
""",
diff --git a/handlers/__init__.py b/handlers/__init__.py
index 2ac2e777..c2cd5125 100644
--- a/handlers/__init__.py
+++ b/handlers/__init__.py
@@ -13,7 +13,6 @@ from .pay import router as pay_router
from .payments import router as payments_router
from .profile import router as profile_router
from .start import router as start_router
-from .user import router as user_router
router = Router(name="handlers_main_router")
@@ -29,5 +28,4 @@ router.include_routers(
keys_router,
instructions_router,
admin_router,
- user_router,
)
diff --git a/handlers/admin/admin_coupons.py b/handlers/admin/admin_coupons.py
index 52c10a4e..559f336e 100644
--- a/handlers/admin/admin_coupons.py
+++ b/handlers/admin/admin_coupons.py
@@ -3,6 +3,7 @@ from typing import Any
from aiogram import F, Router, types
from aiogram.fsm.context import FSMContext
from aiogram.fsm.state import State, StatesGroup
+from aiogram.types import CallbackQuery, Message
from database import create_coupon, delete_coupon, get_all_coupons
from filters.admin import IsAdminFilter
@@ -22,7 +23,7 @@ class AdminCouponsState(StatesGroup):
IsAdminFilter(),
)
async def handle_coupons(
- callback_query: types.CallbackQuery,
+ callback_query: CallbackQuery,
):
await callback_query.message.edit_text(text="🛠 Меню управления купонами:", reply_markup=build_coupons_kb())
@@ -31,7 +32,7 @@ async def handle_coupons(
AdminPanelCallback.filter(F.action == "coupons_create"),
IsAdminFilter(),
)
-async def handle_coupons_create(callback_query: types.CallbackQuery, state: FSMContext):
+async def handle_coupons_create(callback_query: CallbackQuery, state: FSMContext):
text = (
"🎫 Введите данные для создания купона в формате:\n\n"
"📝 код 💰 сумма 🔢 лимит\n\n"
@@ -46,7 +47,7 @@ async def handle_coupons_create(callback_query: types.CallbackQuery, state: FSMC
@router.message(AdminCouponsState.waiting_for_coupon_data, IsAdminFilter())
-async def handle_coupon_data_input(message: types.Message, state: FSMContext, session: Any):
+async def handle_coupon_data_input(message: Message, state: FSMContext, session: Any):
text = message.text.strip()
parts = text.split()
@@ -98,7 +99,7 @@ async def handle_coupon_data_input(message: types.Message, state: FSMContext, se
AdminPanelCallback.filter(F.action == "coupons_list"),
IsAdminFilter(),
)
-async def handle_coupons_list(callback_query: types.CallbackQuery, session: Any):
+async def handle_coupons_list(callback_query: CallbackQuery, session: Any):
try:
page = int(callback_query.data.split(":")[1]) if ":" in callback_query.data else 1
per_page = 10
@@ -136,9 +137,7 @@ async def handle_coupons_list(callback_query: types.CallbackQuery, session: Any)
AdminCouponDeleteCallback.filter(),
IsAdminFilter(),
)
-async def handle_coupon_delete(
- callback_query: types.CallbackQuery, callback_data: AdminCouponDeleteCallback, session: Any
-):
+async def handle_coupon_delete(callback_query: CallbackQuery, callback_data: AdminCouponDeleteCallback, session: Any):
coupon_code = callback_data.coupon_code
try:
diff --git a/handlers/admin/admin_panel.py b/handlers/admin/admin_panel.py
index f3d76f87..a2fb540b 100644
--- a/handlers/admin/admin_panel.py
+++ b/handlers/admin/admin_panel.py
@@ -1,7 +1,7 @@
from aiogram import F, Router, types
from aiogram.filters import Command
from aiogram.fsm.context import FSMContext
-from aiogram.types import CallbackQuery
+from aiogram.types import CallbackQuery, Message
from bot import version
from filters.admin import IsAdminFilter
@@ -24,7 +24,7 @@ async def handle_admin_callback_query(callback_query: CallbackQuery, state: FSMC
@router.message(Command("admin"), IsAdminFilter())
-async def handle_admin_message(message: types.Message, state: FSMContext):
+async def handle_admin_message(message: Message, state: FSMContext):
text = f"🤖 Панель администратора\n📌 Версия бота: {version}"
await state.clear()
diff --git a/handlers/admin/admin_sender.py b/handlers/admin/admin_sender.py
index 4e8a92cf..af0c7535 100644
--- a/handlers/admin/admin_sender.py
+++ b/handlers/admin/admin_sender.py
@@ -4,7 +4,7 @@ from typing import Any
from aiogram import F, Router, types
from aiogram.fsm.context import FSMContext
from aiogram.fsm.state import State, StatesGroup
-from aiogram.types import CallbackQuery
+from aiogram.types import CallbackQuery, Message
from filters.admin import IsAdminFilter
from keyboards.admin.panel_kb import AdminPanelCallback, build_admin_back_kb
@@ -46,7 +46,7 @@ async def handle_sender_callback(callback_query: CallbackQuery, callback_data: A
AdminSender.waiting_for_message,
IsAdminFilter(),
)
-async def handle_message_input(message: types.Message, state: FSMContext, session: Any):
+async def handle_message_input(message: Message, state: FSMContext, session: Any):
text_message = message.text
try:
diff --git a/handlers/admin/admin_servers.py b/handlers/admin/admin_servers.py
index 9632b424..792bc81f 100644
--- a/handlers/admin/admin_servers.py
+++ b/handlers/admin/admin_servers.py
@@ -4,6 +4,7 @@ import asyncpg
from aiogram import F, Router, types
from aiogram.fsm.context import FSMContext
from aiogram.fsm.state import State, StatesGroup
+from aiogram.types import CallbackQuery, Message
from py3xui import AsyncApi
from backup import create_backup_and_send_to_admins
@@ -34,7 +35,7 @@ class AdminServersEditor(StatesGroup):
AdminPanelCallback.filter(F.action == "servers"),
IsAdminFilter(),
)
-async def handle_servers(callback_query: types.CallbackQuery):
+async def handle_servers(callback_query: CallbackQuery):
servers = await get_servers()
text = (
@@ -55,7 +56,7 @@ async def handle_servers(callback_query: types.CallbackQuery):
AdminPanelCallback.filter(F.action == "clusters_add"),
IsAdminFilter(),
)
-async def handle_clusters_add(callback_query: types.CallbackQuery, state: FSMContext):
+async def handle_clusters_add(callback_query: CallbackQuery, state: FSMContext):
text = (
"🔧 Введите имя нового кластера:\n\n"
"Имя кластера должно быть уникальным!\n"
@@ -68,7 +69,7 @@ async def handle_clusters_add(callback_query: types.CallbackQuery, state: FSMCon
@router.message(AdminServersEditor.waiting_for_cluster_name, IsAdminFilter())
-async def handle_cluster_name_input(message: types.Message, state: FSMContext):
+async def handle_cluster_name_input(message: Message, state: FSMContext):
if not message.text:
await message.answer(
text="❌ Имя кластера не может быть пустым. Попробуйте снова.", reply_markup=build_admin_back_kb("servers")
@@ -93,7 +94,7 @@ async def handle_cluster_name_input(message: types.Message, state: FSMContext):
@router.message(AdminServersEditor.waiting_for_server_name, IsAdminFilter())
-async def handle_server_name_input(message: types.Message, state: FSMContext):
+async def handle_server_name_input(message: Message, state: FSMContext, session: Any):
if not message.text:
await message.answer(
text="❌ Имя сервера не может быть пустым. Попробуйте снова.", reply_markup=build_admin_back_kb("servers")
@@ -102,15 +103,16 @@ async def handle_server_name_input(message: types.Message, state: FSMContext):
server_name = message.text.strip()
- if not await check_unique_server_name(server_name):
+ user_data = await state.get_data()
+ cluster_name = user_data.get("cluster_name")
+
+ if not await check_unique_server_name(server_name, session, cluster_name):
await message.answer(
text="❌ Сервер с таким именем уже существует. Пожалуйста, выберите другое имя.",
reply_markup=build_admin_back_kb("servers"),
)
return
- user_data = await state.get_data()
- cluster_name = user_data.get("cluster_name")
await state.update_data(server_name=server_name)
text = (
@@ -129,7 +131,7 @@ async def handle_server_name_input(message: types.Message, state: FSMContext):
@router.message(AdminServersEditor.waiting_for_api_url, IsAdminFilter())
-async def handle_api_url_input(message: types.Message, state: FSMContext):
+async def handle_api_url_input(message: Message, state: FSMContext, session: Any):
if not message.text or not message.text.strip().startswith("https://"):
await message.answer(
text="❌ API URL должен начинаться с https://. Попробуйте снова.",
@@ -161,7 +163,7 @@ async def handle_api_url_input(message: types.Message, state: FSMContext):
@router.message(AdminServersEditor.waiting_for_subscription_url, IsAdminFilter())
-async def handle_subscription_url_input(message: types.Message, state: FSMContext):
+async def handle_subscription_url_input(message: Message, state: FSMContext):
if not message.text or not message.text.strip().startswith("https://"):
await message.answer(
text="❌ subscription_url должен начинаться с https://. Попробуйте снова.",
@@ -189,7 +191,7 @@ async def handle_subscription_url_input(message: types.Message, state: FSMContex
@router.message(AdminServersEditor.waiting_for_inbound_id, IsAdminFilter())
-async def handle_inbound_id_input(message: types.Message, state: FSMContext):
+async def handle_inbound_id_input(message: Message, state: FSMContext):
inbound_id = message.text.strip()
if not inbound_id.isdigit():
@@ -228,9 +230,7 @@ async def handle_inbound_id_input(message: types.Message, state: FSMContext):
@router.callback_query(AdminServerEditorCallback.filter(F.action == "clusters_manage"), IsAdminFilter())
-async def handle_clusters_manage(
- callback_query: types.CallbackQuery, callback_data: AdminServerEditorCallback, session: Any
-):
+async def handle_clusters_manage(callback_query: CallbackQuery, callback_data: AdminServerEditorCallback, session: Any):
cluster_name = callback_data.data
servers = await get_servers(session)
@@ -244,7 +244,7 @@ async def handle_clusters_manage(
@router.callback_query(AdminServerEditorCallback.filter(F.action == "servers_availability"), IsAdminFilter())
async def handle_servers_availability(
- callback_query: types.CallbackQuery, callback_data: AdminServerEditorCallback, session: Any
+ callback_query: CallbackQuery, callback_data: AdminServerEditorCallback, session: Any
):
cluster_name = callback_data.data
@@ -280,7 +280,7 @@ async def handle_servers_availability(
@router.callback_query(AdminServerEditorCallback.filter(F.action == "servers_manage"), IsAdminFilter())
-async def handle_servers_manage(callback_query: types.CallbackQuery, callback_data: AdminServerEditorCallback):
+async def handle_servers_manage(callback_query: CallbackQuery, callback_data: AdminServerEditorCallback):
server_name = callback_data.data
servers = await get_servers()
@@ -309,7 +309,7 @@ async def handle_servers_manage(callback_query: types.CallbackQuery, callback_da
@router.callback_query(AdminServerEditorCallback.filter(F.action == "servers_delete"), IsAdminFilter())
-async def handle_servers_delete(callback_query: types.CallbackQuery, callback_data: AdminServerEditorCallback):
+async def handle_servers_delete(callback_query: CallbackQuery, callback_data: AdminServerEditorCallback):
server_name = callback_data.data
await callback_query.message.edit_text(
@@ -320,7 +320,7 @@ async def handle_servers_delete(callback_query: types.CallbackQuery, callback_da
@router.callback_query(AdminServerEditorCallback.filter(F.action == "servers_delete_confirm"), IsAdminFilter())
async def handle_servers_delete_confirm(
- callback_query: types.CallbackQuery, callback_data: AdminServerEditorCallback, session: Any
+ callback_query: CallbackQuery, callback_data: AdminServerEditorCallback, session: Any
):
server_name = callback_data.data
@@ -333,7 +333,7 @@ async def handle_servers_delete_confirm(
@router.callback_query(AdminServerEditorCallback.filter(F.action == "servers_add"), IsAdminFilter())
async def handle_servers_add(
- callback_query: types.CallbackQuery, callback_data: AdminServerEditorCallback, state: FSMContext
+ callback_query: CallbackQuery, callback_data: AdminServerEditorCallback, state: FSMContext
):
cluster_name = callback_data.data
@@ -354,9 +354,7 @@ async def handle_servers_add(
@router.callback_query(AdminServerEditorCallback.filter(F.action == "clusters_backup"), IsAdminFilter())
-async def handle_clusters_backup(
- callback_query: types.CallbackQuery, callback_data: AdminServerEditorCallback, session: Any
-):
+async def handle_clusters_backup(callback_query: CallbackQuery, callback_data: AdminServerEditorCallback, session: Any):
cluster_name = callback_data.data
servers = await get_servers(session)
diff --git a/handlers/admin/admin_user_editor.py b/handlers/admin/admin_user_editor.py
index 4d4ff573..37026123 100644
--- a/handlers/admin/admin_user_editor.py
+++ b/handlers/admin/admin_user_editor.py
@@ -6,7 +6,7 @@ import pytz
from aiogram import Bot, F, Router, types
from aiogram.fsm.context import FSMContext
from aiogram.fsm.state import State, StatesGroup
-from aiogram.types import CallbackQuery, InlineKeyboardButton, InlineKeyboardMarkup
+from aiogram.types import CallbackQuery, InlineKeyboardButton, InlineKeyboardMarkup, Message
from aiogram.utils.keyboard import InlineKeyboardBuilder
from config import TOTAL_GB
@@ -58,7 +58,7 @@ async def prompt_username(callback_query: CallbackQuery, state: FSMContext):
@router.message(UserEditorState.waiting_for_username, IsAdminFilter())
-async def handle_username_input(message: types.Message, state: FSMContext, session: Any):
+async def handle_username_input(message: Message, state: FSMContext, session: Any):
username = message.text.strip().lstrip("@").replace("https://t.me/", "")
user_record = await session.fetchrow("SELECT tg_id FROM users WHERE username = $1", username)
@@ -72,7 +72,7 @@ async def handle_username_input(message: types.Message, state: FSMContext, sessi
await state.clear()
return
- tg_id = user_record["tg_id"]
+ tg_id = int(user_record["tg_id"])
username = await session.fetchval("SELECT username FROM users WHERE tg_id = $1", tg_id)
balance = await session.fetchval("SELECT balance FROM connections WHERE tg_id = $1", tg_id)
key_records = await get_keys(tg_id, session)
@@ -90,8 +90,8 @@ async def handle_username_input(message: types.Message, state: FSMContext, sessi
builder = InlineKeyboardBuilder()
- for (email,) in key_records:
- builder.row(InlineKeyboardButton(text=f"🔑 {email}", callback_data=f"edit_key_{email}"))
+ for key in key_records:
+ builder.row(InlineKeyboardButton(text=f"🔑 {key['email']}", callback_data=f"edit_key_{key['email']}"))
builder.row(
InlineKeyboardButton(
@@ -124,7 +124,7 @@ async def handle_username_input(message: types.Message, state: FSMContext, sessi
@router.callback_query(F.data.startswith("send_message_"))
-async def handle_send_message(callback_query: types.CallbackQuery, state: FSMContext):
+async def handle_send_message(callback_query: CallbackQuery, state: FSMContext):
tg_id = callback_query.data.split("_")[2]
await state.update_data(target_tg_id=tg_id)
await callback_query.message.answer("✉️ Введите текст сообщения, которое вы хотите отправить пользователю.")
@@ -132,7 +132,7 @@ async def handle_send_message(callback_query: types.CallbackQuery, state: FSMCon
@router.message(UserEditorState.waiting_for_message_text, IsAdminFilter())
-async def process_send_message(message: types.Message, state: FSMContext, bot: Bot):
+async def process_send_message(message: Message, state: FSMContext, bot: Bot):
data = await state.get_data()
target_tg_id = data.get("target_tg_id")
@@ -151,7 +151,7 @@ async def process_send_message(message: types.Message, state: FSMContext, bot: B
@router.message(UserEditorState.waiting_for_tg_id, F.text.isdigit(), IsAdminFilter())
-async def handle_tg_id_input(message: types.Message, state: FSMContext, session: Any):
+async def handle_tg_id_input(message: Message, state: FSMContext, session: Any):
tg_id = int(message.text)
username = await session.fetchval("SELECT username FROM users WHERE tg_id = $1", tg_id)
balance = await session.fetchval("SELECT balance FROM connections WHERE tg_id = $1", tg_id)
@@ -170,8 +170,8 @@ async def handle_tg_id_input(message: types.Message, state: FSMContext, session:
builder = InlineKeyboardBuilder()
- for (email,) in key_records:
- builder.row(InlineKeyboardButton(text=f"🔑 {email}", callback_data=f"edit_key_{email}"))
+ for key in key_records:
+ builder.row(InlineKeyboardButton(text=f"🔑 {key['email']}", callback_data=f"edit_key_{key['email']}"))
builder.row(
InlineKeyboardButton(
@@ -204,7 +204,7 @@ async def handle_tg_id_input(message: types.Message, state: FSMContext, session:
@router.callback_query(F.data.startswith("restore_trial_"), IsAdminFilter())
-async def handle_restore_trial(callback_query: types.CallbackQuery, session: Any):
+async def handle_restore_trial(callback_query: CallbackQuery, session: Any):
tg_id = int(callback_query.data.split("_")[2])
await update_trial(tg_id, 0, session)
@@ -226,7 +226,7 @@ async def process_balance_change(callback_query: CallbackQuery, state: FSMContex
@router.message(UserEditorState.waiting_for_new_balance, IsAdminFilter())
-async def handle_new_balance_input(message: types.Message, state: FSMContext, session: Any):
+async def handle_new_balance_input(message: Message, state: FSMContext, session: Any):
if not message.text.isdigit() or int(message.text) < 0:
builder = InlineKeyboardBuilder()
builder.row(InlineKeyboardButton(text="⬅️ Назад", callback_data="user_editor"))
@@ -313,7 +313,7 @@ async def prompt_key_name(callback_query: CallbackQuery, state: FSMContext):
@router.message(UserEditorState.waiting_for_key_name, IsAdminFilter())
-async def handle_key_name_input(message: types.Message, state: FSMContext, session: Any):
+async def handle_key_name_input(message: Message, state: FSMContext, session: Any):
key_name = sanitize_key_name(message.text)
key_details = await get_key_details(key_name, session)
@@ -370,7 +370,7 @@ async def prompt_expiry_change(callback_query: CallbackQuery, state: FSMContext)
@router.message(UserEditorState.waiting_for_expiry_time, IsAdminFilter())
-async def handle_expiry_time_input(message: types.Message, state: FSMContext, session: Any):
+async def handle_expiry_time_input(message: Message, state: FSMContext, session: Any):
user_data = await state.get_data()
email = user_data.get("email")
@@ -453,7 +453,7 @@ async def handle_expiry_time_input(message: types.Message, state: FSMContext, se
@router.callback_query(F.data.startswith("delete_key_admin|"), IsAdminFilter())
-async def process_callback_delete_key(callback_query: types.CallbackQuery, session: Any):
+async def process_callback_delete_key(callback_query: CallbackQuery, session: Any):
email = callback_query.data.split("|")[1]
key_details = await get_key_details(email, session)
@@ -478,7 +478,7 @@ async def process_callback_delete_key(callback_query: types.CallbackQuery, sessi
@router.callback_query(F.data.startswith("confirm_delete_admin|"), IsAdminFilter())
-async def process_callback_confirm_delete(callback_query: types.CallbackQuery, session: Any):
+async def process_callback_confirm_delete(callback_query: CallbackQuery, session: Any):
client_id = callback_query.data.split("|")[1]
record = await session.fetchrow("SELECT email FROM keys WHERE client_id = $1", client_id)
@@ -509,7 +509,7 @@ async def process_callback_confirm_delete(callback_query: types.CallbackQuery, s
@router.callback_query(F.data.startswith("user_info|"), IsAdminFilter())
-async def handle_user_info(callback_query: types.CallbackQuery, state: FSMContext, session: Any):
+async def handle_user_info(callback_query: CallbackQuery, state: FSMContext, session: Any):
tg_id = int(callback_query.data.split("|")[1])
username = await session.fetchval("SELECT username FROM users WHERE tg_id = $1", tg_id)
balance = await session.fetchval("SELECT balance FROM connections WHERE tg_id = $1", tg_id)
@@ -518,8 +518,8 @@ async def handle_user_info(callback_query: types.CallbackQuery, state: FSMContex
builder = InlineKeyboardBuilder()
- for (email,) in key_records:
- builder.row(InlineKeyboardButton(text=f"🔑 {email}", callback_data=f"edit_key_{email}"))
+ for key in key_records:
+ builder.row(InlineKeyboardButton(text=f"🔑 {key['email']}", callback_data=f"edit_key_{key['email']}"))
builder.row(InlineKeyboardButton(text="📝 Изменить баланс", callback_data=f"change_balance_{tg_id}"))
builder.row(InlineKeyboardButton(text="🔄 Восстановить пробник", callback_data=f"restore_trial_{tg_id}"))
@@ -542,7 +542,7 @@ async def handle_user_info(callback_query: types.CallbackQuery, state: FSMContex
@router.callback_query(F.data.startswith("confirm_delete_user_"), IsAdminFilter())
-async def confirm_delete_user(callback_query: types.CallbackQuery, state: FSMContext, session: Any):
+async def confirm_delete_user(callback_query: CallbackQuery, state: FSMContext, session: Any):
tg_id = int(callback_query.data.split("_")[3])
confirmation_markup = InlineKeyboardMarkup(
@@ -560,7 +560,7 @@ async def confirm_delete_user(callback_query: types.CallbackQuery, state: FSMCon
@router.callback_query(F.data.startswith("delete_user_"), IsAdminFilter())
-async def delete_user(callback_query: types.CallbackQuery, session: Any):
+async def delete_user(callback_query: CallbackQuery, session: Any):
tg_id = int(callback_query.data.split("_")[2])
key_records = await session.fetch("SELECT email, client_id FROM keys WHERE tg_id = $1", tg_id)
diff --git a/handlers/admin/admin_users.py b/handlers/admin/admin_users.py
index 8ad42bea..e73b3fb2 100644
--- a/handlers/admin/admin_users.py
+++ b/handlers/admin/admin_users.py
@@ -7,7 +7,7 @@ from aiogram.exceptions import TelegramBadRequest
from aiogram.filters.callback_data import CallbackData
from aiogram.fsm.context import FSMContext
from aiogram.fsm.state import State, StatesGroup
-from aiogram.types import CallbackQuery
+from aiogram.types import CallbackQuery, Message
from config import TOTAL_GB
from database import delete_key, delete_user_data, get_client_id_by_email, get_servers, update_key_expiry, update_trial
@@ -75,7 +75,7 @@ async def handle_search_key(callback_query: CallbackQuery, state: FSMContext):
@router.message(UserEditorState.waiting_for_user_data, IsAdminFilter())
-async def handle_user_data_input(message: types.Message, state: FSMContext, session: Any):
+async def handle_user_data_input(message: Message, state: FSMContext, session: Any):
kb = build_admin_back_kb()
if message.forward_from:
@@ -110,7 +110,7 @@ async def handle_user_data_input(message: types.Message, state: FSMContext, sess
@router.message(UserEditorState.waiting_for_key_name, IsAdminFilter())
-async def handle_key_name_input(message: types.Message, state: FSMContext, session: Any):
+async def handle_key_name_input(message: Message, state: FSMContext, session: Any):
kb = build_admin_back_kb()
if not message.text:
@@ -131,9 +131,7 @@ async def handle_key_name_input(message: types.Message, state: FSMContext, sessi
AdminUserEditorCallback.filter(F.action == "users_send_message"),
IsAdminFilter(),
)
-async def handle_send_message(
- callback_query: types.CallbackQuery, callback_data: AdminUserEditorCallback, state: FSMContext
-):
+async def handle_send_message(callback_query: CallbackQuery, callback_data: AdminUserEditorCallback, state: FSMContext):
tg_id = callback_data.tg_id
await callback_query.message.edit_text(
@@ -145,7 +143,7 @@ async def handle_send_message(
@router.message(UserEditorState.waiting_for_message_text, IsAdminFilter())
-async def handle_message_text_input(message: types.Message, state: FSMContext):
+async def handle_message_text_input(message: Message, state: FSMContext):
data = await state.get_data()
tg_id = data.get("tg_id")
@@ -162,9 +160,7 @@ async def handle_message_text_input(message: types.Message, state: FSMContext):
AdminUserEditorCallback.filter(F.action == "users_trial_restore"),
IsAdminFilter(),
)
-async def handle_trial_restore(
- callback_query: types.CallbackQuery, callback_data: AdminUserEditorCallback, session: Any
-):
+async def handle_trial_restore(callback_query: CallbackQuery, callback_data: AdminUserEditorCallback, session: Any):
tg_id = callback_data.tg_id
await update_trial(tg_id, 0, session)
@@ -260,7 +256,7 @@ async def handle_balance_set(callback_query: CallbackQuery, callback_data: Admin
@router.message(UserEditorState.waiting_for_balance, IsAdminFilter())
-async def handle_balance_input(message: types.Message, state: FSMContext, session: Any):
+async def handle_balance_input(message: Message, state: FSMContext, session: Any):
data = await state.get_data()
tg_id = data.get("tg_id")
op_type = data.get("op_type")
@@ -391,7 +387,7 @@ async def handle_expiry_set(
@router.message(UserEditorState.waiting_for_expiry_time, IsAdminFilter())
-async def handle_expiry_time_input(message: types.Message, state: FSMContext, session: Any):
+async def handle_expiry_time_input(message: Message, state: FSMContext, session: Any):
data = await state.get_data()
tg_id = data.get("tg_id")
email = data.get("email")
@@ -452,7 +448,7 @@ async def handle_update_key(callback_query: CallbackQuery, callback_data: AdminU
@router.callback_query(AdminUserEditorCallback.filter(F.action == "users_delete_key"), IsAdminFilter())
-async def handle_delete_key(callback_query: types.CallbackQuery, callback_data: AdminUserEditorCallback, session: Any):
+async def handle_delete_key(callback_query: CallbackQuery, callback_data: AdminUserEditorCallback, session: Any):
email = callback_data.data
client_id = await session.fetchval("SELECT client_id FROM keys WHERE email = $1", email)
@@ -469,7 +465,7 @@ async def handle_delete_key(callback_query: types.CallbackQuery, callback_data:
@router.callback_query(AdminUserEditorCallback.filter(F.action == "users_delete_key_confirm"), IsAdminFilter())
async def handle_delete_key_confirm(
- callback_query: types.CallbackQuery, callback_data: AdminUserEditorCallback, session: Any
+ callback_query: CallbackQuery, callback_data: AdminUserEditorCallback, session: Any
):
email = callback_data.data
record = await session.fetchrow("SELECT client_id FROM keys WHERE email = $1", email)
@@ -496,7 +492,7 @@ async def handle_delete_key_confirm(
@router.callback_query(AdminUserEditorCallback.filter(F.action == "users_delete_user"), IsAdminFilter())
-async def handle_delete_user(callback_query: types.CallbackQuery, callback_data: AdminUserEditorCallback):
+async def handle_delete_user(callback_query: CallbackQuery, callback_data: AdminUserEditorCallback):
tg_id = callback_data.tg_id
await callback_query.message.edit_text(
text=f"❗️ Вы уверены, что хотите удалить пользователя с ID {tg_id}?", reply_markup=build_user_delete_kb(tg_id)
@@ -505,7 +501,7 @@ async def handle_delete_user(callback_query: types.CallbackQuery, callback_data:
@router.callback_query(AdminUserEditorCallback.filter(F.action == "users_delete_user_confirm"), IsAdminFilter())
async def handle_delete_user_confirm(
- callback_query: types.CallbackQuery, callback_data: AdminUserEditorCallback, session: Any
+ callback_query: CallbackQuery, callback_data: AdminUserEditorCallback, session: Any
):
tg_id = callback_data.tg_id
key_records = await session.fetch("SELECT email, client_id FROM keys WHERE tg_id = $1", tg_id)
@@ -537,13 +533,13 @@ async def handle_delete_user_confirm(
@router.callback_query(AdminUserEditorCallback.filter(F.action == "users_editor"), IsAdminFilter())
async def handle_editor(
- callback_query: types.CallbackQuery, callback_data: AdminUserEditorCallback, state: FSMContext, session: Any
+ callback_query: CallbackQuery, callback_data: AdminUserEditorCallback, state: FSMContext, session: Any
):
await process_user_search(callback_query.message, state, session, callback_data.tg_id, callback_data.edit)
async def process_user_search(
- message: types.Message, state: FSMContext, session: Any, tg_id: int, edit: bool = False
+ message: Message, state: FSMContext, session: Any, tg_id: int, edit: bool = False
) -> None:
await state.clear()
@@ -637,7 +633,7 @@ async def change_expiry_time(expiry_time: int, email: str, session: Any) -> Exce
await asyncio.gather(*tasks)
await update_key_on_all_servers()
- await update_key_expiry(client_id, expiry_time)
+ await update_key_expiry(client_id, expiry_time, session)
async def get_user_balance(tg_id: int, session: Any) -> float:
diff --git a/handlers/coupons.py b/handlers/coupons.py
index 0a125da2..0976d8dc 100644
--- a/handlers/coupons.py
+++ b/handlers/coupons.py
@@ -3,7 +3,7 @@ from typing import Any
from aiogram import F, Router, types
from aiogram.fsm.context import FSMContext
from aiogram.fsm.state import State, StatesGroup
-from aiogram.types import InlineKeyboardButton
+from aiogram.types import CallbackQuery, InlineKeyboardButton, Message
from aiogram.utils.keyboard import InlineKeyboardBuilder
from database import (
@@ -23,7 +23,7 @@ router = Router()
@router.callback_query(F.data == "activate_coupon")
-async def handle_activate_coupon(callback_query: types.CallbackQuery, state: FSMContext):
+async def handle_activate_coupon(callback_query: CallbackQuery, state: FSMContext):
builder = InlineKeyboardBuilder()
builder.row(InlineKeyboardButton(text="👤 Личный кабинет", callback_data="profile"))
@@ -36,7 +36,7 @@ async def handle_activate_coupon(callback_query: types.CallbackQuery, state: FSM
@router.message(CouponActivationState.waiting_for_coupon_code)
-async def process_coupon_code(message: types.Message, state: FSMContext, session: Any):
+async def process_coupon_code(message: Message, state: FSMContext, session: Any):
coupon_code = message.text.strip()
activation_result = await activate_coupon(message.chat.id, coupon_code, session)
diff --git a/handlers/donate.py b/handlers/donate.py
index 3de7d323..552c4b8d 100644
--- a/handlers/donate.py
+++ b/handlers/donate.py
@@ -1,7 +1,7 @@
from aiogram import F, Router, types
from aiogram.fsm.context import FSMContext
from aiogram.fsm.state import State, StatesGroup
-from aiogram.types import InlineKeyboardButton, LabeledPrice, PreCheckoutQuery
+from aiogram.types import CallbackQuery, InlineKeyboardButton, LabeledPrice, Message, PreCheckoutQuery
from aiogram.utils.keyboard import InlineKeyboardBuilder
from config import RUB_TO_XTR
@@ -18,7 +18,7 @@ router = Router()
@router.callback_query(F.data == "donate")
-async def process_donate(callback_query: types.CallbackQuery, state: FSMContext):
+async def process_donate(callback_query: CallbackQuery, state: FSMContext):
await state.clear()
builder = InlineKeyboardBuilder()
@@ -40,7 +40,7 @@ async def process_donate(callback_query: types.CallbackQuery, state: FSMContext)
@router.callback_query(F.data == "enter_custom_donate_amount")
-async def process_enter_donate_amount(callback_query: types.CallbackQuery, state: FSMContext):
+async def process_enter_donate_amount(callback_query: CallbackQuery, state: FSMContext):
builder = InlineKeyboardBuilder()
builder.row(InlineKeyboardButton(text="⬅️ Назад", callback_data="donate"))
await callback_query.message.answer("💸 Введите сумму доната в рублях:", reply_markup=builder.as_markup())
@@ -48,7 +48,7 @@ async def process_enter_donate_amount(callback_query: types.CallbackQuery, state
@router.message(DonateState.entering_donate_amount)
-async def process_donate_amount_input(message: types.Message, state: FSMContext):
+async def process_donate_amount_input(message: Message, state: FSMContext):
if message.text.isdigit():
amount = int(message.text)
if amount // RUB_TO_XTR <= 0:
@@ -85,7 +85,7 @@ async def on_pre_checkout_query(pre_checkout_query: PreCheckoutQuery):
@router.message(F.successful_payment, DonateState.waiting_for_donate_payment)
-async def on_successful_donate(message: types.Message, state: FSMContext):
+async def on_successful_donate(message: Message, state: FSMContext):
try:
amount = float(message.successful_payment.invoice_payload.split("_")[0])
builder = InlineKeyboardBuilder()
diff --git a/handlers/instructions/instructions.py b/handlers/instructions/instructions.py
index 89053024..db8ec324 100644
--- a/handlers/instructions/instructions.py
+++ b/handlers/instructions/instructions.py
@@ -3,7 +3,7 @@ from typing import Any
import aiofiles
from aiogram import F, Router, types
-from aiogram.types import BufferedInputFile, InlineKeyboardButton
+from aiogram.types import BufferedInputFile, CallbackQuery, InlineKeyboardButton, Message
from aiogram.utils.keyboard import InlineKeyboardBuilder
from config import CONNECT_MACOS, CONNECT_WINDOWS, SUPPORT_CHAT_URL
@@ -23,13 +23,13 @@ router = Router()
@router.callback_query(F.data == "instructions")
@router.message(F.text == "/instructions")
async def send_instructions(
- callback_query_or_message: types.CallbackQuery | types.Message,
+ callback_query_or_message: CallbackQuery | Message,
):
instructions_message = INSTRUCTIONS
image_path = os.path.join("img", "instructions.jpg")
if not os.path.isfile(image_path):
- if isinstance(callback_query_or_message, types.CallbackQuery):
+ if isinstance(callback_query_or_message, CallbackQuery):
await callback_query_or_message.message.answer("Файл изображения не найден.")
else:
await callback_query_or_message.answer("Файл изображения не найден.")
@@ -41,7 +41,7 @@ async def send_instructions(
InlineKeyboardButton(text="👤 Личный кабинет", callback_data="profile"),
)
- if isinstance(callback_query_or_message, types.CallbackQuery):
+ if isinstance(callback_query_or_message, CallbackQuery):
send_photo = callback_query_or_message.message.answer_photo
else:
send_photo = callback_query_or_message.answer_photo
@@ -56,7 +56,7 @@ async def send_instructions(
@router.callback_query(F.data.startswith("connect_pc|"))
-async def process_connect_pc(callback_query: types.CallbackQuery, session: Any):
+async def process_connect_pc(callback_query: CallbackQuery, session: Any):
key_name = callback_query.data.split("|")[1]
record = await get_key_details(key_name, session)
@@ -83,7 +83,7 @@ async def process_connect_pc(callback_query: types.CallbackQuery, session: Any):
@router.callback_query(F.data.startswith("connect_tv|"))
-async def process_connect_tv(callback_query: types.CallbackQuery):
+async def process_connect_tv(callback_query: CallbackQuery):
key_name = callback_query.data.split("|")[1]
builder = InlineKeyboardBuilder()
@@ -98,7 +98,7 @@ async def process_connect_tv(callback_query: types.CallbackQuery):
@router.callback_query(F.data.startswith("continue_tv|"))
-async def process_continue_tv(callback_query: types.CallbackQuery, session: Any):
+async def process_continue_tv(callback_query: CallbackQuery, session: Any):
key_name = callback_query.data.split("|")[1]
tg_id = callback_query.from_user.id
diff --git a/handlers/keys/keys.py b/handlers/keys/keys.py
index 018d3f1e..149c1733 100644
--- a/handlers/keys/keys.py
+++ b/handlers/keys/keys.py
@@ -8,7 +8,7 @@ import aiofiles
import asyncpg
import pytz
from aiogram import F, Router, types
-from aiogram.types import BufferedInputFile, InlineKeyboardButton
+from aiogram.types import BufferedInputFile, CallbackQuery, InlineKeyboardButton, Message
from aiogram.utils.keyboard import InlineKeyboardBuilder
from bot import bot
@@ -70,10 +70,8 @@ router = Router()
@router.callback_query(F.data == "view_keys")
@router.message(F.text == "/subs")
-async def process_callback_or_message_view_keys(
- callback_query_or_message: types.Message | types.CallbackQuery, session: Any
-):
- if isinstance(callback_query_or_message, types.CallbackQuery):
+async def process_callback_or_message_view_keys(callback_query_or_message: Message | CallbackQuery, session: Any):
+ if isinstance(callback_query_or_message, CallbackQuery):
chat_id = callback_query_or_message.message.chat.id
send_message = callback_query_or_message.message.answer
send_photo = callback_query_or_message.message.answer_photo
@@ -154,7 +152,7 @@ async def send_with_optional_image(send_message, send_photo, image_path, text, k
@router.callback_query(F.data.startswith("view_key|"))
-async def process_callback_view_key(callback_query: types.CallbackQuery, session: Any):
+async def process_callback_view_key(callback_query: CallbackQuery, session: Any):
tg_id = callback_query.message.chat.id
key_name = callback_query.data.split("|")[1]
try:
@@ -247,7 +245,7 @@ async def process_callback_view_key(callback_query: types.CallbackQuery, session
@router.callback_query(F.data.startswith("update_subscription|"))
-async def process_callback_update_subscription(callback_query: types.CallbackQuery, session: Any):
+async def process_callback_update_subscription(callback_query: CallbackQuery, session: Any):
tg_id = callback_query.message.chat.id
email = callback_query.data.split("|")[1]
@@ -260,7 +258,7 @@ async def process_callback_update_subscription(callback_query: types.CallbackQue
@router.callback_query(F.data.startswith("delete_key|"))
-async def process_callback_delete_key(callback_query: types.CallbackQuery):
+async def process_callback_delete_key(callback_query: CallbackQuery):
client_id = callback_query.data.split("|")[1]
try:
confirmation_keyboard = types.InlineKeyboardMarkup(
@@ -285,7 +283,7 @@ async def process_callback_delete_key(callback_query: types.CallbackQuery):
@router.callback_query(F.data.startswith("renew_key|"))
-async def process_callback_renew_key(callback_query: types.CallbackQuery, session: Any):
+async def process_callback_renew_key(callback_query: CallbackQuery, session: Any):
tg_id = callback_query.message.chat.id
key_name = callback_query.data.split("|")[1]
try:
@@ -331,7 +329,7 @@ async def process_callback_renew_key(callback_query: types.CallbackQuery, sessio
@router.callback_query(F.data.startswith("confirm_delete|"))
-async def process_callback_confirm_delete(callback_query: types.CallbackQuery, session: Any):
+async def process_callback_confirm_delete(callback_query: CallbackQuery, session: Any):
email = callback_query.data.split("|")[1]
try:
record = await get_key_details(email, session)
@@ -379,7 +377,7 @@ async def process_callback_confirm_delete(callback_query: types.CallbackQuery, s
@router.callback_query(F.data.startswith("renew_plan|"))
-async def process_callback_renew_plan(callback_query: types.CallbackQuery, session: Any):
+async def process_callback_renew_plan(callback_query: CallbackQuery, session: Any):
tg_id = callback_query.message.chat.id
plan, client_id = callback_query.data.split("|")[1], callback_query.data.split("|")[2]
days_to_extend = 30 * int(plan)
@@ -486,8 +484,6 @@ async def complete_key_renewal(tg_id, client_id, email, new_expiry_time, total_g
else:
cluster_id = server_id
- await conn.close()
-
logger.info(f"[RENEW] Запуск продления ключа для пользователя {tg_id} на {plan} мес. в кластере {cluster_id}.")
async def renew_key_on_cluster():
@@ -503,4 +499,6 @@ async def complete_key_renewal(tg_id, client_id, email, new_expiry_time, total_g
await update_balance(tg_id, -cost, conn)
logger.info(f"[RENEW] Ключ {client_id} успешно продлён на {plan} мес. для пользователя {tg_id}.")
+ await conn.close()
+
await renew_key_on_cluster()
diff --git a/handlers/profile.py b/handlers/profile.py
index 64bbe141..7f50cb9b 100644
--- a/handlers/profile.py
+++ b/handlers/profile.py
@@ -5,7 +5,7 @@ import aiofiles
import asyncpg
from aiogram import F, Router, types
from aiogram.fsm.context import FSMContext
-from aiogram.types import BufferedInputFile, InlineKeyboardButton
+from aiogram.types import BufferedInputFile, CallbackQuery, InlineKeyboardButton, Message
from aiogram.utils.keyboard import InlineKeyboardBuilder
from config import DATABASE_URL, NEWS_MESSAGE, RENEWAL_PLANS
@@ -29,15 +29,15 @@ router = Router()
@router.callback_query(F.data == "profile")
@router.message(F.text == "/profile")
async def process_callback_view_profile(
- callback_query_or_message: types.Message | types.CallbackQuery,
+ callback_query_or_message: Message | CallbackQuery,
state: FSMContext,
admin: bool,
):
- if isinstance(callback_query_or_message, types.CallbackQuery):
+ if isinstance(callback_query_or_message, CallbackQuery):
chat_id = callback_query_or_message.message.chat.id
username = callback_query_or_message.from_user.full_name
is_callback = True
- elif isinstance(callback_query_or_message, types.Message):
+ elif isinstance(callback_query_or_message, Message):
chat_id = callback_query_or_message.chat.id
username = callback_query_or_message.from_user.full_name
is_callback = False
@@ -114,7 +114,7 @@ async def process_callback_view_profile(
@router.callback_query(F.data == "balance")
-async def balance_handler(callback_query: types.CallbackQuery):
+async def balance_handler(callback_query: CallbackQuery):
builder = InlineKeyboardBuilder()
builder.row(InlineKeyboardButton(text=PAYMENT, callback_data="pay"))
builder.row(InlineKeyboardButton(text=BALANCE_HISTORY, callback_data="balance_history"))
@@ -124,7 +124,7 @@ async def balance_handler(callback_query: types.CallbackQuery):
@router.callback_query(F.data == "balance_history")
-async def balance_history_handler(callback_query: types.CallbackQuery, session: Any):
+async def balance_history_handler(callback_query: CallbackQuery, session: Any):
builder = InlineKeyboardBuilder()
builder.row(InlineKeyboardButton(text=PAYMENT, callback_data="pay"))
builder.row(InlineKeyboardButton(text=MAIN_MENU, callback_data="profile"))
@@ -152,7 +152,7 @@ async def balance_history_handler(callback_query: types.CallbackQuery, session:
@router.message(F.text == "/tariffs")
@router.callback_query(F.data == "view_tariffs")
-async def view_tariffs_handler(callback_query: types.CallbackQuery):
+async def view_tariffs_handler(callback_query: CallbackQuery):
builder = InlineKeyboardBuilder()
builder.row(InlineKeyboardButton(text="👤 Личный кабинет", callback_data="profile"))
@@ -183,7 +183,7 @@ async def view_tariffs_handler(callback_query: types.CallbackQuery):
@router.callback_query(F.data == "invite")
-async def invite_handler(callback_query: types.CallbackQuery):
+async def invite_handler(callback_query: CallbackQuery):
chat_id = callback_query.message.chat.id
referral_link = get_referral_link(chat_id)
diff --git a/handlers/user.py b/handlers/user.py
deleted file mode 100644
index 44a190ec..00000000
--- a/handlers/user.py
+++ /dev/null
@@ -1,22 +0,0 @@
-from typing import Any
-
-from aiogram import Router
-from aiogram.filters.chat_member_updated import KICKED, MEMBER, ChatMemberUpdatedFilter
-from aiogram.types import ChatMemberUpdated
-
-from database import create_blocked_user, delete_blocked_user
-from logger import logger
-
-router = Router()
-
-
-@router.my_chat_member(ChatMemberUpdatedFilter(member_status_changed=KICKED))
-async def user_blocked_bot(event: ChatMemberUpdated, session: Any):
- logger.info(f"User {event.from_user.id} blocked the bot.")
- await create_blocked_user(event.from_user.id, session)
-
-
-@router.my_chat_member(ChatMemberUpdatedFilter(member_status_changed=MEMBER))
-async def user_unblocked_bot(event: ChatMemberUpdated, session: Any):
- logger.info(f"User {event.from_user.id} unblocked the bot.")
- await delete_blocked_user(event.from_user.id, session)