fixing bugs

This commit is contained in:
Vladless
2025-04-01 02:37:52 +03:00
parent f2427d655e
commit 4f2cdef7f9
6 changed files with 65 additions and 39 deletions
+17 -4
View File
@@ -549,8 +549,8 @@ async def update_balance(
amount: float,
session: Any = None,
is_admin: bool = False,
skip_referral: bool = False, # <- флаг "пропустить реферальное начисление"
skip_cashback: bool = False, # <- флаг "пропустить кэшбэк"
skip_referral: bool = False,
skip_cashback: bool = False,
):
"""
Обновляет баланс пользователя в базе данных.
@@ -563,7 +563,6 @@ async def update_balance(
conn = await asyncpg.connect(DATABASE_URL)
session = conn
# Если пополнение не от админа и не сказали пропустить кэшбэк
if CASHBACK > 0 and amount > 0 and not is_admin and not skip_cashback:
extra = amount * (CASHBACK / 100.0)
else:
@@ -589,7 +588,6 @@ async def update_balance(
f"({'+ кешбэк' if extra > 0 else 'без кешбэка'}), стало: {new_balance}"
)
# Если не админ и не пропустили реферальное начисление — обрабатываем реферальную цепочку
if not is_admin and not skip_referral:
await handle_referral_on_balance_update(tg_id, int(amount))
@@ -1235,6 +1233,21 @@ async def add_notification(tg_id: int, notification_type: str, session: Any):
raise
async def delete_notification(tg_id: int, notification_type: str, session):
"""
Удаляет уведомление пользователя по типу (например: 'email_key_expired').
"""
try:
await session.execute(
"DELETE FROM notifications WHERE tg_id = $1 AND notification_type = $2",
tg_id,
notification_type,
)
logger.info(f"🗑 Уведомление '{notification_type}' для пользователя {tg_id} удалено.")
except Exception as e:
logger.error(f"❌ Ошибка при удалении уведомления '{notification_type}' для пользователя {tg_id}: {e}")
async def check_notification_time(tg_id: int, notification_type: str, hours: int = 12, session: Any = None) -> bool:
"""
Проверяет, прошло ли указанное количество часов с момента последнего уведомления.
+11 -2
View File
@@ -2,12 +2,15 @@ from aiogram import F, Router
from aiogram.filters import Command
from aiogram.fsm.context import FSMContext
from aiogram.types import CallbackQuery, Message
from aiogram.exceptions import TelegramBadRequest
from bot import version
from filters.admin import IsAdminFilter
from .keyboard import AdminPanelCallback, build_panel_kb
from logger import logger
router = Router()
@@ -19,12 +22,18 @@ async def handle_admin_callback_query(callback_query: CallbackQuery, state: FSMC
await state.clear()
if callback_query.message.text:
await callback_query.message.edit_text(text=text, reply_markup=build_panel_kb())
try:
await callback_query.message.edit_text(text=text, reply_markup=build_panel_kb())
except TelegramBadRequest as e:
if "message is not modified" in str(e):
logger.warning("🔄 Попытка редактировать сообщение без изменений — пропущено.")
else:
raise
else:
try:
await callback_query.message.delete()
except Exception as e:
print(f"Ошибка при удалении сообщения: {e}")
logger.error(f"Ошибка при удалении сообщения: {e}")
await callback_query.message.answer(text=text, reply_markup=build_panel_kb())
+13 -15
View File
@@ -8,7 +8,7 @@ import pytz
from aiogram import F, Router
from aiogram.fsm.context import FSMContext
from aiogram.types import CallbackQuery, InlineKeyboardButton, Message
from aiogram.types import CallbackQuery, InlineKeyboardButton, Message, InputFile
from aiogram.utils.keyboard import InlineKeyboardBuilder
from py3xui import AsyncApi
@@ -16,11 +16,7 @@ from bot import bot
from config import (
ADMIN_PASSWORD,
ADMIN_USERNAME,
CONNECT_ANDROID,
CONNECT_IOS,
CONNECT_PHONE_BUTTON,
DOWNLOAD_ANDROID,
DOWNLOAD_IOS,
NOTIFY_EXTRA_DAYS,
PUBLIC_LINK,
RENEWAL_PRICES,
@@ -45,10 +41,6 @@ from handlers.buttons import (
BACK,
CONNECT_DEVICE,
CONNECT_PHONE,
DOWNLOAD_ANDROID_BUTTON,
DOWNLOAD_IOS_BUTTON,
IMPORT_ANDROID,
IMPORT_IOS,
MAIN_MENU,
PAYMENT,
PC_BUTTON,
@@ -323,17 +315,23 @@ async def create_key(
days = remaining_time.days
key_message_text = key_message_success(public_link, f"⏳ Осталось дней: {days} 📅")
default_media_path = "img/pic.jpg"
if target_message:
await edit_or_send_message(
target_message=target_message, text=key_message_text, reply_markup=builder.as_markup(), media_path=None
)
else:
await bot.send_message(
chat_id=tg_id,
target_message=target_message,
text=key_message_text,
reply_markup=builder.as_markup(),
media_path=default_media_path,
)
else:
photo = InputFile(default_media_path)
await bot.send_photo(
chat_id=tg_id,
photo=photo,
caption=key_message_text,
reply_markup=builder.as_markup(),
)
if state:
await state.clear()
+7 -1
View File
@@ -7,7 +7,7 @@ import asyncpg
from py3xui import AsyncApi
from config import ADMIN_PASSWORD, ADMIN_USERNAME, DATABASE_URL, LIMIT_IP, PUBLIC_LINK, SUPERNODE, TOTAL_GB
from database import get_servers, store_key
from database import get_servers, store_key, delete_notification
from handlers.utils import get_least_loaded_cluster
from logger import logger
from panels.three_xui import (
@@ -144,6 +144,12 @@ async def renew_key_in_cluster(cluster_id, email, client_id, new_expiry_time, to
return False
tg_id = tg_id_record["tg_id"]
notification_prefixes = ["key_24h", "key_10h", "key_expired", "renew"]
for notif in notification_prefixes:
notification_id = f"{email}_{notif}"
await delete_notification(tg_id, notification_id, session=conn)
logger.info(f"🧹 Уведомления для ключа {email} очищены при продлении.")
tasks = []
for server_info in cluster:
xui = AsyncApi(
@@ -29,6 +29,7 @@ from database import (
get_last_notification_time,
update_balance,
update_key_expiry,
delete_notification
)
from handlers.keys.key_utils import delete_key_from_cluster, renew_key_in_cluster
from handlers.notifications.notify_kb import build_notification_expired_kb, build_notification_kb
@@ -269,22 +270,6 @@ async def handle_expired_keys(bot: Bot, conn: asyncpg.Connection, current_time:
delete_immediately = NOTIFY_DELETE_DELAY == 0
delete_after_delay = False
if NOTIFY_DELETE_DELAY > 0 and last_notification_time is not None:
minutes_since = (current_time - last_notification_time) / (1000 * 60)
if minutes_since >= NOTIFY_DELETE_DELAY / 2 and minutes_since < NOTIFY_DELETE_DELAY:
try:
await conn.execute(
"DELETE FROM notifications WHERE tg_id = $1 AND notification_type = $2",
tg_id,
notification_id,
)
logger.info(
f"⛔ Уведомление {notification_id} для {tg_id} удалено (прошло больше половины задержки)."
)
except Exception as e:
logger.error(f"Ошибка при удалении уведомления: {e}")
continue
if last_notification_time is not None:
delete_after_delay = (current_time - last_notification_time) / (1000 * 60) >= NOTIFY_DELETE_DELAY
logger.info(
@@ -355,7 +340,13 @@ async def handle_expired_keys(bot: Bot, conn: asyncpg.Connection, current_time:
async def process_auto_renew_or_notify(
bot, conn, key: dict, notification_id: str, renewal_period_months: int, standard_photo: str, standard_caption: str
bot,
conn,
key: dict,
notification_id: str,
renewal_period_months: int,
standard_photo: str,
standard_caption: str
):
"""
Если баланс пользователя позволяет, продлевает ключ на максимальный возможный срок и списывает средства;
@@ -405,6 +396,7 @@ async def process_auto_renew_or_notify(
await update_key_expiry(client_id, new_expiry_time, conn)
await add_notification(tg_id, renew_notification_id, session=conn)
await delete_notification(tg_id, notification_id, session=conn)
logger.info(
f"✅ Ключ {client_id} продлён на {renewal_period_months} мес. для пользователя {tg_id}. Списано {renewal_cost}."
+8
View File
@@ -142,6 +142,10 @@ async def process_start_logic(
await message.answer("❌ Этот купон уже использован!")
return await process_callback_view_profile(message, state, admin)
connection_exists = await check_connection_exists(message.chat.id)
if not connection_exists:
await add_connection(tg_id=message.chat.id, session=session)
await update_balance(message.chat.id, coupon["amount"])
await session.execute(
"UPDATE coupons SET usage_count = $1, is_used = $2 WHERE code = $3",
@@ -193,6 +197,10 @@ async def process_start_logic(
if not existing_referral:
await add_referral(message.chat.id, gift_info["sender_tg_id"], session)
connection_exists = await check_connection_exists(message.chat.id)
if not connection_exists:
await add_connection(tg_id=message.chat.id, session=session)
await session.execute("UPDATE connections SET trial = 1 WHERE tg_id = $1", message.chat.id)
await create_key(