Merge branch 'main' into main

This commit is contained in:
Vladislav Lisitsyn
2024-12-14 02:02:00 +03:00
committed by GitHub
4 changed files with 92 additions and 29 deletions
+9
View File
@@ -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)
+57 -16
View File
@@ -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}. Попробуйте снова."
)
+24 -11
View File
@@ -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}")
+2 -2
View File
@@ -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,
}
],
},