Merge branch 'main' into main
This commit is contained in:
@@ -1196,3 +1196,12 @@ async def get_servers_from_db():
|
||||
)
|
||||
|
||||
return servers
|
||||
|
||||
|
||||
async def delete_user_data(session: Any, tg_id: int):
|
||||
await session.execute("DELETE FROM gifts WHERE sender_tg_id = $1 OR recipient_tg_id = $1", tg_id)
|
||||
await session.execute("DELETE FROM payments WHERE tg_id = $1", tg_id)
|
||||
await session.execute("DELETE FROM users WHERE tg_id = $1", tg_id)
|
||||
await session.execute("DELETE FROM connections WHERE tg_id = $1", tg_id)
|
||||
await session.execute("DELETE FROM keys WHERE tg_id = $1", tg_id)
|
||||
await session.execute("DELETE FROM referrals WHERE referrer_tg_id = $1", tg_id)
|
||||
|
||||
@@ -5,7 +5,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, InlineKeyboardButton
|
||||
from aiogram.types import CallbackQuery, InlineKeyboardButton, InlineKeyboardMarkup
|
||||
from aiogram.utils.keyboard import InlineKeyboardBuilder
|
||||
from config import TOTAL_GB
|
||||
|
||||
@@ -15,6 +15,7 @@ from database import (
|
||||
restore_trial,
|
||||
update_key_expiry,
|
||||
)
|
||||
|
||||
from filters.admin import IsAdminFilter
|
||||
from handlers.keys.key_utils import (
|
||||
delete_key_from_cluster,
|
||||
@@ -117,7 +118,7 @@ async def handle_username_input(
|
||||
callback_data=f"restore_trial_{tg_id}",
|
||||
)
|
||||
)
|
||||
|
||||
builder.row(InlineKeyboardButton(text="❌ Удалить клиента", callback_data=f"confirm_delete_user_{tg_id}"))
|
||||
builder.row(InlineKeyboardButton(text="🔙 Назад", callback_data="user_editor"))
|
||||
|
||||
user_info = (
|
||||
@@ -606,20 +607,9 @@ async def handle_user_info(
|
||||
InlineKeyboardButton(text=f"🔑 {email}", callback_data=f"edit_key_{email}")
|
||||
)
|
||||
|
||||
builder.row(
|
||||
InlineKeyboardButton(
|
||||
text="📝 Изменить баланс",
|
||||
callback_data=f"change_balance_{tg_id}",
|
||||
)
|
||||
)
|
||||
|
||||
builder.row(
|
||||
InlineKeyboardButton(
|
||||
text="🔄 Восстановить пробник",
|
||||
callback_data=f"restore_trial_{tg_id}",
|
||||
)
|
||||
)
|
||||
|
||||
builder.row(InlineKeyboardButton(text="📝 Изменить баланс", callback_data=f"change_balance_{tg_id}"))
|
||||
builder.row(InlineKeyboardButton(text="🔄 Восстановить пробник", callback_data=f"restore_trial_{tg_id}"))
|
||||
builder.row(InlineKeyboardButton(text="❌ Удалить клиента", callback_data=f"confirm_delete_user_{tg_id}"))
|
||||
builder.row(InlineKeyboardButton(text="🔙 Назад", callback_data="user_editor"))
|
||||
|
||||
user_info = (
|
||||
@@ -630,5 +620,56 @@ async def handle_user_info(
|
||||
f"👥 Количество рефералов: <b>{referral_count}</b>\n"
|
||||
f"🔑 Ключи (для редактирования нажмите на ключ):"
|
||||
)
|
||||
|
||||
await callback_query.message.answer(user_info, reply_markup=builder.as_markup())
|
||||
await state.set_state(UserEditorState.displaying_user_info)
|
||||
|
||||
|
||||
@router.callback_query(F.data.startswith("confirm_delete_user_"), IsAdminFilter())
|
||||
async def confirm_delete_user(callback_query: types.CallbackQuery, state: FSMContext, session: Any):
|
||||
tg_id = int(callback_query.data.split("_")[3])
|
||||
|
||||
confirmation_markup = InlineKeyboardMarkup(
|
||||
row_width=2,
|
||||
inline_keyboard=[
|
||||
[InlineKeyboardButton(text="✅ Подтвердить", callback_data=f"delete_user_{tg_id}")],
|
||||
[InlineKeyboardButton(text="❌ Отменить", callback_data="user_editor")],
|
||||
],
|
||||
)
|
||||
|
||||
await callback_query.message.answer(
|
||||
f"Вы уверены, что хотите удалить пользователя с ID {tg_id}?", reply_markup=confirmation_markup
|
||||
)
|
||||
|
||||
|
||||
@router.callback_query(F.data.startswith("delete_user_"), IsAdminFilter())
|
||||
async def delete_user(callback_query: types.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)
|
||||
|
||||
async def delete_keys_from_servers():
|
||||
try:
|
||||
tasks = []
|
||||
for email, client_id in key_records:
|
||||
servers = await get_servers_from_db()
|
||||
for cluster_id, cluster in servers.items():
|
||||
tasks.append(delete_key_from_cluster(cluster_id, email, client_id))
|
||||
await asyncio.gather(*tasks)
|
||||
except Exception as e:
|
||||
logger.error(f"Ошибка при удалении ключей с серверов для пользователя {tg_id}: {e}")
|
||||
|
||||
await delete_keys_from_servers()
|
||||
|
||||
try:
|
||||
await delete_user_data(session, tg_id)
|
||||
|
||||
back_button = InlineKeyboardButton(text="🔙 Назад", callback_data="user_editor")
|
||||
keyboard = InlineKeyboardMarkup(inline_keyboard=[[back_button]])
|
||||
|
||||
await callback_query.message.answer(f"🗑️ Пользователь с ID {tg_id} был удален.", reply_markup=keyboard)
|
||||
except Exception as e:
|
||||
logger.error(f"Ошибка при удалении данных из базы данных для пользователя {tg_id}: {e}")
|
||||
await callback_query.message.answer(
|
||||
f"❌ Произошла ошибка при удалении пользователя с ID {tg_id}. Попробуйте снова."
|
||||
)
|
||||
|
||||
@@ -8,6 +8,9 @@ from config import DATABASE_URL, TRANSITION_DATE_STR
|
||||
|
||||
from database import get_servers_from_db
|
||||
from logger import logger
|
||||
import urllib.parse
|
||||
|
||||
from config import PROJECT_NAME, NEWS_MESSAGE
|
||||
|
||||
|
||||
async def fetch_url_content(url, tg_id):
|
||||
@@ -75,10 +78,12 @@ async def handle_old_subscription(request):
|
||||
|
||||
conn = await asyncpg.connect(DATABASE_URL)
|
||||
try:
|
||||
|
||||
key_info = await conn.fetchrow(
|
||||
"SELECT created_at FROM keys WHERE email = $1", email
|
||||
)
|
||||
|
||||
|
||||
if not key_info:
|
||||
logger.warning(f"Клиент с email {email} не найден в базе.")
|
||||
return web.Response(
|
||||
@@ -87,7 +92,8 @@ async def handle_old_subscription(request):
|
||||
)
|
||||
|
||||
created_at_ms = key_info["created_at"]
|
||||
logger.info(f"Значение created_at для клиента с email {email}: {created_at_ms}")
|
||||
cluster_name = key_info["cluster_name"]
|
||||
logger.info(f"Значение created_at для клиента с email {email}: {created_at_ms}, кластер: {cluster_name}")
|
||||
|
||||
created_at_datetime = datetime.utcfromtimestamp(created_at_ms / 1000)
|
||||
logger.info(
|
||||
@@ -102,12 +108,13 @@ async def handle_old_subscription(request):
|
||||
)
|
||||
|
||||
servers = await get_servers_from_db()
|
||||
cluster_servers = servers.get(cluster_name, [])
|
||||
logger.info(f"Сервера в кластере: {cluster_servers}")
|
||||
|
||||
urls = []
|
||||
for cluster_name, cluster_servers in servers.items():
|
||||
for server in cluster_servers:
|
||||
server_subscription_url = f"{server['subscription_url']}/{email}"
|
||||
urls.append(server_subscription_url)
|
||||
for server in cluster_servers:
|
||||
server_subscription_url = f"{server['subscription_url']}/{email}"
|
||||
urls.append(server_subscription_url)
|
||||
|
||||
combined_subscriptions = await combine_unique_lines(urls, email, "")
|
||||
|
||||
@@ -115,11 +122,12 @@ async def handle_old_subscription(request):
|
||||
"\n".join(combined_subscriptions).encode("utf-8")
|
||||
).decode("utf-8")
|
||||
|
||||
encoded_project_name = urllib.parse.quote(f"{PROJECT_NAME}\n{NEWS_MESSAGE}")
|
||||
headers = {
|
||||
"Content-Type": "text/plain; charset=utf-8",
|
||||
"Content-Disposition": "inline",
|
||||
"profile-update-interval": "7",
|
||||
"profile-title": email,
|
||||
"profile-title": encoded_project_name,
|
||||
}
|
||||
|
||||
logger.info(f"Возвращаем объединенные подписки для email: {email}")
|
||||
@@ -144,10 +152,12 @@ async def handle_new_subscription(request):
|
||||
|
||||
conn = await asyncpg.connect(DATABASE_URL)
|
||||
try:
|
||||
|
||||
client_data = await conn.fetchrow(
|
||||
"SELECT tg_id FROM keys WHERE email = $1", email
|
||||
)
|
||||
|
||||
|
||||
if not client_data:
|
||||
logger.warning(f"Клиент с email {email} не найден в базе.")
|
||||
return web.Response(
|
||||
@@ -156,6 +166,7 @@ async def handle_new_subscription(request):
|
||||
)
|
||||
|
||||
stored_tg_id = client_data["tg_id"]
|
||||
cluster_name = client_data["server_id"]
|
||||
|
||||
if str(tg_id) != str(stored_tg_id):
|
||||
logger.warning(f"Неверный tg_id для клиента с email {email}.")
|
||||
@@ -163,16 +174,17 @@ async def handle_new_subscription(request):
|
||||
text="❌ Неверные данные. Получите свой ключ в боте.",
|
||||
status=403,
|
||||
)
|
||||
|
||||
finally:
|
||||
await conn.close()
|
||||
|
||||
servers = await get_servers_from_db()
|
||||
cluster_servers = servers.get(cluster_name, [])
|
||||
|
||||
urls = []
|
||||
for cluster_name, cluster_servers in servers.items():
|
||||
for server in cluster_servers:
|
||||
server_subscription_url = f"{server['subscription_url']}/{email}"
|
||||
urls.append(server_subscription_url)
|
||||
for server in cluster_servers:
|
||||
server_subscription_url = f"{server['subscription_url']}/{email}"
|
||||
urls.append(server_subscription_url)
|
||||
|
||||
query_string = request.query_string
|
||||
logger.info(f"Извлечен query string: {query_string}")
|
||||
@@ -183,11 +195,12 @@ async def handle_new_subscription(request):
|
||||
"\n".join(combined_subscriptions).encode("utf-8")
|
||||
).decode("utf-8")
|
||||
|
||||
encoded_project_name = urllib.parse.quote(f"{PROJECT_NAME}\n{NEWS_MESSAGE}")
|
||||
headers = {
|
||||
"Content-Type": "text/plain; charset=utf-8",
|
||||
"Content-Disposition": "inline",
|
||||
"profile-update-interval": "7",
|
||||
"profile-title": email,
|
||||
"profile-title": encoded_project_name,
|
||||
}
|
||||
|
||||
logger.info(f"Возвращаем объединенные подписки для email: {email}")
|
||||
|
||||
@@ -132,7 +132,7 @@ async def process_amount_selection(
|
||||
"description": "Пополнение баланса",
|
||||
"quantity": "1.00",
|
||||
"amount": {"value": str(amount), "currency": "RUB"},
|
||||
"vat_code": 6,
|
||||
"vat_code": 1,
|
||||
}
|
||||
],
|
||||
},
|
||||
@@ -232,7 +232,7 @@ async def process_custom_amount_input(message: types.Message, state: FSMContext)
|
||||
"value": str(amount),
|
||||
"currency": "RUB",
|
||||
},
|
||||
"vat_code": 6,
|
||||
"vat_code": 1,
|
||||
}
|
||||
],
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user