ruff formatting
This commit is contained in:
@@ -3,8 +3,8 @@ import subprocess
|
||||
from datetime import datetime
|
||||
|
||||
from aiogram.types import BufferedInputFile
|
||||
|
||||
from config import ADMIN_ID, BACK_DIR, DB_NAME, DB_PASSWORD, DB_USER, PG_HOST, PG_PORT
|
||||
|
||||
from logger import logger
|
||||
|
||||
|
||||
|
||||
@@ -8,8 +8,8 @@ from aiogram.filters import ExceptionTypeFilter
|
||||
from aiogram.fsm.storage.memory import MemoryStorage
|
||||
from aiogram.types import BufferedInputFile, ErrorEvent
|
||||
from aiogram.utils.markdown import hbold
|
||||
|
||||
from config import ADMIN_ID, API_TOKEN
|
||||
|
||||
from filters.private import IsPrivateFilter
|
||||
from logger import logger
|
||||
from middlewares import register_middleware
|
||||
|
||||
@@ -2,8 +2,8 @@ from dataclasses import dataclass
|
||||
from typing import Any
|
||||
|
||||
import py3xui
|
||||
|
||||
from config import LIMIT_IP, SUPERNODE
|
||||
|
||||
from logger import logger
|
||||
|
||||
|
||||
|
||||
+2
-2
@@ -4,8 +4,8 @@ from typing import Any
|
||||
|
||||
import asyncpg
|
||||
import pytz
|
||||
|
||||
from config import CASHBACK, DATABASE_URL, REFERRAL_BONUS_PERCENTAGES
|
||||
|
||||
from logger import logger
|
||||
|
||||
|
||||
@@ -556,7 +556,7 @@ async def update_balance(tg_id: int, amount: float, session: Any = None):
|
||||
session = conn
|
||||
|
||||
extra = amount * (CASHBACK / 100.0) if (CASHBACK > 0 and amount > 0) else 0
|
||||
total_amount = amount + extra
|
||||
total_amount = int(amount + extra)
|
||||
|
||||
await session.execute(
|
||||
"""
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
from aiogram.filters import BaseFilter
|
||||
from aiogram.types import Message
|
||||
|
||||
from config import ADMIN_ID
|
||||
|
||||
|
||||
|
||||
@@ -4,8 +4,8 @@ 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 config import USERNAME_BOT
|
||||
|
||||
from database import create_coupon, delete_coupon, get_all_coupons
|
||||
from filters.admin import IsAdminFilter
|
||||
from keyboards.admin.coupons_kb import AdminCouponDeleteCallback, build_coupons_kb, build_coupons_list_kb
|
||||
|
||||
@@ -6,10 +6,10 @@ 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 config import ADMIN_PASSWORD, ADMIN_USERNAME, DATABASE_URL
|
||||
from py3xui import AsyncApi
|
||||
|
||||
from backup import create_backup_and_send_to_admins
|
||||
from config import ADMIN_PASSWORD, ADMIN_USERNAME, DATABASE_URL
|
||||
from database import check_unique_server_name, delete_server, get_servers
|
||||
from filters.admin import IsAdminFilter
|
||||
from handlers.keys.key_utils import create_key_on_cluster
|
||||
@@ -264,7 +264,7 @@ async def handle_servers_availability(
|
||||
cluster_servers = servers.get(cluster_name, [])
|
||||
|
||||
if not cluster_servers:
|
||||
await callback_query.message.answer(text=f"Кластер '{cluster_name}' не содержит серверов.")
|
||||
await callback_query.message.edit_text(text=f"Кластер '{cluster_name}' не содержит серверов.")
|
||||
return
|
||||
|
||||
text = (
|
||||
@@ -272,23 +272,22 @@ async def handle_servers_availability(
|
||||
"Это может занять до 1 минуты, пожалуйста, подождите..."
|
||||
)
|
||||
|
||||
in_progress_message = await callback_query.message.answer(text=text)
|
||||
await callback_query.message.edit_text(text=text)
|
||||
|
||||
text = f"🖥️ Проверка доступности серверов для кластера {cluster_name} завершена:\n\n"
|
||||
result_text = f"🖥️ Проверка доступности серверов для кластера {cluster_name} завершена:\n\n"
|
||||
|
||||
for server in cluster_servers:
|
||||
xui = AsyncApi(server["api_url"], username=ADMIN_USERNAME, password=ADMIN_PASSWORD)
|
||||
|
||||
try:
|
||||
await xui.login()
|
||||
|
||||
online_users = len(await xui.client.online())
|
||||
text += f"🌍 {server['server_name']}: {online_users} активных пользователей.\n"
|
||||
result_text += f"🌍 {server['server_name']}: {online_users} активных пользователей.\n"
|
||||
|
||||
except Exception as e:
|
||||
text += f"❌ {server['server_name']}: Не удалось получить информацию. Ошибка: {e}\n"
|
||||
result_text += f"❌ {server['server_name']}: Не удалось получить информацию. Ошибка: {e}\n"
|
||||
|
||||
await in_progress_message.edit_text(text=text, reply_markup=build_admin_back_kb("servers"))
|
||||
await callback_query.message.edit_text(text=result_text, reply_markup=build_admin_back_kb("servers"))
|
||||
|
||||
|
||||
@router.callback_query(AdminServerEditorCallback.filter(F.action == "servers_manage"), IsAdminFilter())
|
||||
|
||||
@@ -7,8 +7,8 @@ from aiogram.exceptions import TelegramBadRequest
|
||||
from aiogram.fsm.context import FSMContext
|
||||
from aiogram.fsm.state import State, StatesGroup
|
||||
from aiogram.types import CallbackQuery, Message
|
||||
|
||||
from config import TOTAL_GB
|
||||
|
||||
from database import (
|
||||
delete_key,
|
||||
delete_user_data,
|
||||
|
||||
+1
-1
@@ -6,8 +6,8 @@ from aiogram import F, Router
|
||||
from aiogram.fsm.context import FSMContext
|
||||
from aiogram.types import CallbackQuery, Message
|
||||
from aiogram.utils.keyboard import InlineKeyboardBuilder
|
||||
|
||||
from config import CAPTCHA_EMOJIS
|
||||
|
||||
from logger import logger
|
||||
|
||||
router = Router()
|
||||
|
||||
+1
-1
@@ -3,8 +3,8 @@ from aiogram.fsm.context import FSMContext
|
||||
from aiogram.fsm.state import State, StatesGroup
|
||||
from aiogram.types import CallbackQuery, InlineKeyboardButton, LabeledPrice, Message, PreCheckoutQuery
|
||||
from aiogram.utils.keyboard import InlineKeyboardBuilder
|
||||
|
||||
from config import RUB_TO_XTR
|
||||
|
||||
from logger import logger
|
||||
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@ import aiofiles
|
||||
from aiogram import F, Router, types
|
||||
from aiogram.types import BufferedInputFile, CallbackQuery, InlineKeyboardButton, Message
|
||||
from aiogram.utils.keyboard import InlineKeyboardBuilder
|
||||
|
||||
from config import CONNECT_MACOS, CONNECT_WINDOWS, SUPPORT_CHAT_URL
|
||||
|
||||
from database import get_key_details
|
||||
from handlers.texts import (
|
||||
CONNECT_TV_TEXT,
|
||||
|
||||
@@ -8,10 +8,6 @@ from aiogram import F, Router
|
||||
from aiogram.fsm.context import FSMContext
|
||||
from aiogram.types import CallbackQuery, InlineKeyboardButton, Message
|
||||
from aiogram.utils.keyboard import InlineKeyboardBuilder
|
||||
from py3xui import AsyncApi
|
||||
|
||||
from bot import bot
|
||||
from client import delete_client
|
||||
from config import (
|
||||
ADMIN_PASSWORD,
|
||||
ADMIN_USERNAME,
|
||||
@@ -26,6 +22,10 @@ from config import (
|
||||
USE_COUNTRY_SELECTION,
|
||||
USE_NEW_PAYMENT_FLOW,
|
||||
)
|
||||
from py3xui import AsyncApi
|
||||
|
||||
from bot import bot
|
||||
from client import delete_client
|
||||
from database import (
|
||||
create_temporary_data,
|
||||
delete_key,
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import asyncio
|
||||
from typing import Any
|
||||
|
||||
from config import ADMIN_PASSWORD, ADMIN_USERNAME, LIMIT_IP, PUBLIC_LINK, SUPERNODE, TOTAL_GB
|
||||
from py3xui import AsyncApi
|
||||
|
||||
from client import ClientConfig, add_client, delete_client, extend_client_key
|
||||
from config import ADMIN_PASSWORD, ADMIN_USERNAME, LIMIT_IP, PUBLIC_LINK, SUPERNODE, TOTAL_GB
|
||||
from database import get_servers, store_key
|
||||
from handlers.utils import get_least_loaded_cluster
|
||||
from logger import logger
|
||||
|
||||
@@ -10,8 +10,6 @@ import pytz
|
||||
from aiogram import F, Router, types
|
||||
from aiogram.types import BufferedInputFile, CallbackQuery, InlineKeyboardButton, Message
|
||||
from aiogram.utils.keyboard import InlineKeyboardBuilder
|
||||
|
||||
from bot import bot
|
||||
from config import (
|
||||
CONNECT_ANDROID,
|
||||
CONNECT_IOS,
|
||||
@@ -26,6 +24,8 @@ from config import (
|
||||
USE_COUNTRY_SELECTION,
|
||||
USE_NEW_PAYMENT_FLOW,
|
||||
)
|
||||
|
||||
from bot import bot
|
||||
from database import (
|
||||
check_server_name_by_cluster,
|
||||
create_temporary_data,
|
||||
|
||||
@@ -5,8 +5,8 @@ from datetime import datetime
|
||||
import aiohttp
|
||||
import asyncpg
|
||||
from aiohttp import web
|
||||
|
||||
from config import DATABASE_URL, PROJECT_NAME, SUB_MESSAGE, SUPERNODE, TRANSITION_DATE_STR, USE_COUNTRY_SELECTION
|
||||
|
||||
from database import get_key_details, get_servers
|
||||
from logger import logger
|
||||
|
||||
|
||||
@@ -9,8 +9,6 @@ from aiogram import Bot, Router, types
|
||||
from aiogram.exceptions import TelegramForbiddenError
|
||||
from aiogram.types import BufferedInputFile
|
||||
from aiogram.utils.keyboard import InlineKeyboardBuilder
|
||||
from py3xui import AsyncApi
|
||||
|
||||
from config import (
|
||||
ADMIN_PASSWORD,
|
||||
ADMIN_USERNAME,
|
||||
@@ -25,6 +23,8 @@ from config import (
|
||||
TOTAL_GB,
|
||||
TRIAL_TIME,
|
||||
)
|
||||
from py3xui import AsyncApi
|
||||
|
||||
from database import (
|
||||
add_notification,
|
||||
check_notification_time,
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
from aiogram import F, Router
|
||||
from aiogram.types import CallbackQuery, InlineKeyboardButton
|
||||
from aiogram.utils.keyboard import InlineKeyboardBuilder
|
||||
|
||||
from config import (
|
||||
CRYPTO_BOT_ENABLE,
|
||||
DONATIONS_ENABLE,
|
||||
|
||||
+1
-1
@@ -7,8 +7,8 @@ from aiogram import F, Router
|
||||
from aiogram.fsm.context import FSMContext
|
||||
from aiogram.types import BufferedInputFile, CallbackQuery, InlineKeyboardButton, Message
|
||||
from aiogram.utils.keyboard import InlineKeyboardBuilder
|
||||
|
||||
from config import DATABASE_URL, INSTRUCTIONS_BUTTON, NEWS_MESSAGE, RENEWAL_PLANS
|
||||
|
||||
from database import get_balance, get_key_count, get_last_payments, get_referral_stats, get_trial
|
||||
from handlers.buttons.profile import (
|
||||
ADD_SUB,
|
||||
|
||||
+2
-2
@@ -12,8 +12,6 @@ from aiogram.types import (
|
||||
Message,
|
||||
)
|
||||
from aiogram.utils.keyboard import InlineKeyboardBuilder
|
||||
|
||||
from bot import bot
|
||||
from config import (
|
||||
CAPTCHA_ENABLE,
|
||||
CHANNEL_EXISTS,
|
||||
@@ -23,6 +21,8 @@ from config import (
|
||||
DONATIONS_ENABLE,
|
||||
SUPPORT_CHAT_URL,
|
||||
)
|
||||
|
||||
from bot import bot
|
||||
from database import (
|
||||
add_connection,
|
||||
add_referral,
|
||||
|
||||
+1
-1
@@ -5,9 +5,9 @@ import string
|
||||
|
||||
import aiohttp
|
||||
import asyncpg
|
||||
from config import DATABASE_URL
|
||||
|
||||
from bot import bot
|
||||
from config import DATABASE_URL
|
||||
from database import get_all_keys, get_servers
|
||||
from logger import logger
|
||||
|
||||
|
||||
@@ -3,8 +3,8 @@ from datetime import datetime, timezone
|
||||
from aiogram.filters.callback_data import CallbackData
|
||||
from aiogram.types import InlineKeyboardButton, InlineKeyboardMarkup
|
||||
from aiogram.utils.keyboard import InlineKeyboardBuilder
|
||||
|
||||
from config import RENEWAL_PRICES
|
||||
|
||||
from keyboards.admin.panel_kb import build_admin_back_btn
|
||||
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@ from typing import Any
|
||||
|
||||
from aiogram import BaseMiddleware
|
||||
from aiogram.types import TelegramObject
|
||||
|
||||
from config import ADMIN_ID
|
||||
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@ from typing import Any
|
||||
import asyncpg
|
||||
from aiogram import BaseMiddleware
|
||||
from aiogram.types import TelegramObject
|
||||
|
||||
from config import DATABASE_URL
|
||||
|
||||
|
||||
|
||||
+1
-1
@@ -5,10 +5,10 @@ from datetime import datetime, timedelta
|
||||
import asyncpg
|
||||
from aiogram.types import InlineKeyboardButton
|
||||
from aiogram.utils.keyboard import InlineKeyboardBuilder
|
||||
from config import ADMIN_ID, DATABASE_URL, PING_TIME
|
||||
from ping3 import ping
|
||||
|
||||
from bot import bot
|
||||
from config import ADMIN_ID, DATABASE_URL, PING_TIME
|
||||
from database import check_unique_server_name, create_server, get_servers
|
||||
from logger import logger
|
||||
|
||||
|
||||
+36
-34
@@ -5,60 +5,65 @@ from aiogram.types import BufferedInputFile
|
||||
|
||||
|
||||
async def export_users_csv(session: Any) -> BufferedInputFile:
|
||||
# Получение данных о платежах пользователя
|
||||
"""
|
||||
Экспорт пользователей в CSV с сортировкой от самого старого к новому.
|
||||
"""
|
||||
query = """
|
||||
SELECT
|
||||
u.tg_id,
|
||||
u.username,
|
||||
u.first_name,
|
||||
u.last_name,
|
||||
u.language_code,
|
||||
u.is_bot,
|
||||
c.balance,
|
||||
c.trial
|
||||
FROM users u
|
||||
LEFT JOIN connections c ON u.tg_id = c.tg_id
|
||||
"""
|
||||
SELECT
|
||||
u.tg_id,
|
||||
u.username,
|
||||
u.first_name,
|
||||
u.last_name,
|
||||
u.language_code,
|
||||
u.is_bot,
|
||||
c.balance,
|
||||
c.trial,
|
||||
u.created_at -- Добавляем дату регистрации
|
||||
FROM users u
|
||||
LEFT JOIN connections c ON u.tg_id = c.tg_id
|
||||
ORDER BY u.created_at ASC -- Сортировка от старых к новым
|
||||
"""
|
||||
|
||||
users = await session.fetch(query)
|
||||
|
||||
buffer = StringIO()
|
||||
buffer.write("tg_id,username,first_name,last_name,language_code,is_bot,balance,trial\n")
|
||||
buffer.write("tg_id,username,first_name,last_name,language_code,is_bot,balance,trial,created_at\n")
|
||||
|
||||
# Запись данных
|
||||
for user in users:
|
||||
buffer.write(
|
||||
f"{user['tg_id']},{user['username']},{user['first_name']},{user['last_name']},"
|
||||
f"{user['language_code']},{user['is_bot']},{user['balance']},{user['trial']}\n"
|
||||
f"{user['language_code']},{user['is_bot']},{user['balance']},{user['trial']},"
|
||||
f"{user['created_at']}\n"
|
||||
)
|
||||
|
||||
# Перемещение указателя в начало для чтения
|
||||
buffer.seek(0)
|
||||
|
||||
return BufferedInputFile(file=buffer.getvalue().encode("utf-8-sig"), filename="users_export.csv")
|
||||
|
||||
|
||||
async def export_payments_csv(session: Any) -> BufferedInputFile:
|
||||
# Получение данных о всех платежах
|
||||
"""
|
||||
Экспорт платежей в CSV с сортировкой от самого старого к новому.
|
||||
"""
|
||||
query = """
|
||||
SELECT
|
||||
u.tg_id,
|
||||
u.username,
|
||||
u.first_name,
|
||||
u.last_name,
|
||||
p.amount,
|
||||
p.payment_system,
|
||||
p.status,
|
||||
p.created_at
|
||||
FROM users u
|
||||
JOIN payments p ON u.tg_id = p.tg_id
|
||||
"""
|
||||
SELECT
|
||||
u.tg_id,
|
||||
u.username,
|
||||
u.first_name,
|
||||
u.last_name,
|
||||
p.amount,
|
||||
p.payment_system,
|
||||
p.status,
|
||||
p.created_at
|
||||
FROM users u
|
||||
JOIN payments p ON u.tg_id = p.tg_id
|
||||
ORDER BY p.created_at ASC -- Сортировка по дате от старых к новым
|
||||
"""
|
||||
payments = await session.fetch(query)
|
||||
return _export_payments_csv(payments, "payments_export.csv")
|
||||
|
||||
|
||||
async def export_user_payments_csv(tg_id: int, session: Any) -> BufferedInputFile:
|
||||
# Получение данных о платежах пользователя
|
||||
query = """
|
||||
SELECT
|
||||
u.tg_id,
|
||||
@@ -78,18 +83,15 @@ async def export_user_payments_csv(tg_id: int, session: Any) -> BufferedInputFil
|
||||
|
||||
|
||||
def _export_payments_csv(payments: list, filename: str) -> BufferedInputFile:
|
||||
# Формирование CSV данных через StringIO
|
||||
buffer = StringIO()
|
||||
buffer.write("tg_id,username,first_name,last_name,amount,payment_system,status,created_at\n")
|
||||
|
||||
# Запись данных
|
||||
for payment in payments:
|
||||
buffer.write(
|
||||
f"{payment['tg_id']},{payment['username']},{payment['first_name']},{payment['last_name']},"
|
||||
f"{payment['amount']},{payment['payment_system']},{payment['status']},{payment['created_at']}\n"
|
||||
)
|
||||
|
||||
# Перемещение указателя в начало для чтения
|
||||
buffer.seek(0)
|
||||
|
||||
return BufferedInputFile(file=buffer.getvalue().encode("utf-8-sig"), filename=filename)
|
||||
|
||||
Reference in New Issue
Block a user