Merge pull request #141 from izzzzzi/main

Fix key
This commit is contained in:
Vladislav Lisitsyn
2025-01-31 14:30:13 +03:00
committed by GitHub
14 changed files with 100 additions and 133 deletions
+1 -1
View File
@@ -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
""",
-2
View File
@@ -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,
)
+6 -7
View File
@@ -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 = (
"🎫 <b>Введите данные для создания купона в формате:</b>\n\n"
"📝 <i>код</i> 💰 <i>сумма</i> 🔢 <i>лимит</i>\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:
+2 -2
View File
@@ -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()
+2 -2
View File
@@ -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:
+19 -21
View File
@@ -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 = (
"🔧 <b>Введите имя нового кластера:</b>\n\n"
"<b>Имя кластера должно быть уникальным!</b>\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 должен начинаться с <code>https://</code>. Попробуйте снова.",
@@ -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 должен начинаться с <code>https://</code>. Попробуйте снова.",
@@ -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)
+21 -21
View File
@@ -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)
+15 -19
View File
@@ -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:
+3 -3
View File
@@ -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)
+5 -5
View File
@@ -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()
+7 -7
View File
@@ -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
+11 -13
View File
@@ -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()
+8 -8
View File
@@ -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)
-22
View File
@@ -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)