Refactored various modules, applied multiple improvements and fixed critical bugs
This commit is contained in:
+23
-4
@@ -24,11 +24,21 @@ async def generate_captcha(message: Message, state: FSMContext):
|
||||
all_emojis = [correct_emoji] + wrong_emojis
|
||||
random.shuffle(all_emojis)
|
||||
|
||||
from_user = message.from_user or message.chat
|
||||
|
||||
await state.update_data(
|
||||
correct_emoji=correct_emoji,
|
||||
message_id=message.message_id,
|
||||
chat_id=message.chat.id,
|
||||
original_text=message.text,
|
||||
user_data={
|
||||
"tg_id": from_user.id,
|
||||
"username": getattr(from_user, "username", None),
|
||||
"first_name": getattr(from_user, "first_name", None),
|
||||
"last_name": getattr(from_user, "last_name", None),
|
||||
"language_code": getattr(from_user, "language_code", None),
|
||||
"is_bot": getattr(from_user, "is_bot", False),
|
||||
}
|
||||
)
|
||||
|
||||
builder = InlineKeyboardBuilder()
|
||||
@@ -44,13 +54,15 @@ async def generate_captcha(message: Message, state: FSMContext):
|
||||
|
||||
@router.callback_query(F.data.startswith("captcha_"))
|
||||
async def check_captcha(callback: CallbackQuery, state: FSMContext, session: Any, admin: bool):
|
||||
from handlers.start import start_command
|
||||
from handlers.start import process_start_logic
|
||||
|
||||
selected_emoji = callback.data.split("captcha_")[1]
|
||||
state_data = await state.get_data()
|
||||
correct_emoji = state_data.get("correct_emoji")
|
||||
message_id = state_data.get("message_id")
|
||||
chat_id = state_data.get("chat_id")
|
||||
original_text = state_data.get("original_text")
|
||||
user_data = state_data.get("user_data")
|
||||
|
||||
if not message_id or not chat_id:
|
||||
target_message = callback.message
|
||||
@@ -65,10 +77,17 @@ async def check_captcha(callback: CallbackQuery, state: FSMContext, session: Any
|
||||
target_message = callback.message
|
||||
|
||||
if selected_emoji == correct_emoji:
|
||||
logger.info(f"Пользователь {callback.message.chat.id} успешно прошел капчу")
|
||||
await start_command(target_message, state, session, admin, captcha=False)
|
||||
logger.info(f"Пользователь {callback.from_user.id} успешно прошел капчу")
|
||||
await process_start_logic(
|
||||
message=target_message,
|
||||
state=state,
|
||||
session=session,
|
||||
admin=admin,
|
||||
text_to_process=original_text,
|
||||
user_data=user_data
|
||||
)
|
||||
else:
|
||||
logger.warning(f"Пользователь {callback.message.chat.id} неверно ответил на капчу")
|
||||
logger.warning(f"Пользователь {callback.from_user.id} неверно ответил на капчу")
|
||||
captcha = await generate_captcha(target_message, state)
|
||||
await edit_or_send_message(
|
||||
target_message=target_message,
|
||||
|
||||
+22
-12
@@ -69,7 +69,14 @@ async def process_coupon_code(message: Message, state: FSMContext, session: Any)
|
||||
await activate_coupon(message, state, session, coupon_code=coupon_code)
|
||||
|
||||
|
||||
async def activate_coupon(message: Message, state: FSMContext, session: Any, coupon_code: str, admin: bool = False):
|
||||
async def activate_coupon(
|
||||
message: Message,
|
||||
state: FSMContext,
|
||||
session: Any,
|
||||
coupon_code: str,
|
||||
admin: bool = False,
|
||||
user_data: dict | None = None,
|
||||
):
|
||||
logger.info(f"Активация купона: {coupon_code}")
|
||||
coupon_record = await get_coupon_by_code(coupon_code, session)
|
||||
|
||||
@@ -84,7 +91,8 @@ async def activate_coupon(message: Message, state: FSMContext, session: Any, cou
|
||||
await state.clear()
|
||||
return
|
||||
|
||||
user_id = message.chat.id
|
||||
user = user_data or message.from_user or message.chat
|
||||
user_id = user["tg_id"] if isinstance(user, dict) else user.id
|
||||
|
||||
usage = await check_coupon_usage(coupon_record["id"], user_id, session)
|
||||
if usage:
|
||||
@@ -94,16 +102,18 @@ async def activate_coupon(message: Message, state: FSMContext, session: Any, cou
|
||||
|
||||
user_exists = await check_user_exists(user_id)
|
||||
if not user_exists:
|
||||
from_user = message.from_user
|
||||
await add_user(
|
||||
tg_id=from_user.id,
|
||||
username=from_user.username,
|
||||
first_name=from_user.first_name,
|
||||
last_name=from_user.last_name,
|
||||
language_code=from_user.language_code,
|
||||
is_bot=from_user.is_bot,
|
||||
session=session,
|
||||
)
|
||||
if isinstance(user, dict):
|
||||
await add_user(session=session, **user)
|
||||
else:
|
||||
await add_user(
|
||||
tg_id=user.id,
|
||||
username=getattr(user, "username", None),
|
||||
first_name=getattr(user, "first_name", None),
|
||||
last_name=getattr(user, "last_name", None),
|
||||
language_code=getattr(user, "language_code", None),
|
||||
is_bot=getattr(user, "is_bot", False),
|
||||
session=session,
|
||||
)
|
||||
|
||||
if coupon_record["amount"] > 0:
|
||||
try:
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+28
-22
@@ -213,49 +213,55 @@ async def top_referrals_handler(callback_query: CallbackQuery):
|
||||
await conn.close()
|
||||
|
||||
|
||||
async def handle_referral_link(referral_code: str, message: Message, state: FSMContext, session: Any):
|
||||
async def handle_referral_link(
|
||||
referral_code: str,
|
||||
message: Message,
|
||||
state: FSMContext,
|
||||
session: Any,
|
||||
user_data: dict | None = None,
|
||||
):
|
||||
try:
|
||||
referrer_tg_id = int(referral_code)
|
||||
user_exists_now = await check_user_exists(message.chat.id)
|
||||
|
||||
if referrer_tg_id == message.chat.id:
|
||||
user = user_data or message.from_user or message.chat
|
||||
user_id = user["tg_id"] if isinstance(user, dict) else user.id
|
||||
|
||||
if referrer_tg_id == user_id:
|
||||
await message.answer("❌ Вы не можете быть реферальной ссылкой самого себя.")
|
||||
return
|
||||
|
||||
if user_exists_now:
|
||||
await message.answer("❌ Вы уже зарегистрированы и не можете использовать реферальную ссылку.")
|
||||
return
|
||||
|
||||
existing_referral = await get_referral_by_referred_id(message.chat.id, session)
|
||||
existing_referral = await get_referral_by_referred_id(user_id, session)
|
||||
if existing_referral:
|
||||
await message.answer("❌ Вы уже использовали реферальную ссылку.")
|
||||
return
|
||||
|
||||
await add_referral(message.chat.id, referrer_tg_id, session)
|
||||
user_exists = await check_user_exists(user_id)
|
||||
if not user_exists:
|
||||
if isinstance(user, dict):
|
||||
await add_user(session=session, **user)
|
||||
else:
|
||||
await add_user(
|
||||
tg_id=user.id,
|
||||
username=getattr(user, "username", None),
|
||||
first_name=getattr(user, "first_name", None),
|
||||
last_name=getattr(user, "last_name", None),
|
||||
language_code=getattr(user, "language_code", None),
|
||||
is_bot=getattr(user, "is_bot", False),
|
||||
session=session,
|
||||
)
|
||||
|
||||
from_user = message.from_user
|
||||
await add_user(
|
||||
tg_id=from_user.id,
|
||||
username=from_user.username,
|
||||
first_name=from_user.first_name,
|
||||
last_name=from_user.last_name,
|
||||
language_code=from_user.language_code,
|
||||
is_bot=from_user.is_bot,
|
||||
session=session,
|
||||
)
|
||||
await add_referral(user_id, referrer_tg_id, session)
|
||||
|
||||
try:
|
||||
await bot.send_message(
|
||||
referrer_tg_id,
|
||||
NEW_REFERRAL_NOTIFICATION.format(referred_id=message.chat.id),
|
||||
NEW_REFERRAL_NOTIFICATION.format(referred_id=user_id),
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(f"Не удалось отправить уведомление пригласившему ({referrer_tg_id}): {e}")
|
||||
|
||||
await message.answer(REFERRAL_SUCCESS_MSG.format(referrer_tg_id=referrer_tg_id))
|
||||
return
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Ошибка при обработке реферальной ссылки {referral_code}: {e}")
|
||||
await message.answer("❌ Произошла ошибка при обработке реферальной ссылки.")
|
||||
return
|
||||
|
||||
+33
-39
@@ -137,12 +137,25 @@ async def check_subscription_callback(callback_query: CallbackQuery, state: FSMC
|
||||
|
||||
|
||||
async def process_start_logic(
|
||||
message: Message, state: FSMContext, session: Any, admin: bool, text_to_process: str = None
|
||||
message: Message,
|
||||
state: FSMContext,
|
||||
session: Any,
|
||||
admin: bool,
|
||||
text_to_process: str = None,
|
||||
user_data: dict | None = None
|
||||
):
|
||||
text = text_to_process or message.text or message.caption
|
||||
user_data = user_data or {
|
||||
"tg_id": (message.from_user or message.chat).id,
|
||||
"username": getattr(message.from_user, "username", None),
|
||||
"first_name": getattr(message.from_user, "first_name", None),
|
||||
"last_name": getattr(message.from_user, "last_name", None),
|
||||
"language_code": getattr(message.from_user, "language_code", None),
|
||||
"is_bot": getattr(message.from_user, "is_bot", False),
|
||||
}
|
||||
|
||||
if not text:
|
||||
logger.info(f"[StartLogic] Текста нет — вызываю стартовое меню для {message.chat.id}")
|
||||
logger.info(f"[StartLogic] Текста нет — вызываю стартовое меню для {user_data['tg_id']}")
|
||||
await show_start_menu(message, admin, session)
|
||||
return
|
||||
|
||||
@@ -159,7 +172,7 @@ async def process_start_logic(
|
||||
if "coupons" in part:
|
||||
logger.info(f"Обнаружена ссылка на купон: {part}")
|
||||
coupon_code = part.split("coupons")[1].strip("_")
|
||||
await activate_coupon(message, state, session, coupon_code=coupon_code, admin=admin)
|
||||
await activate_coupon(message, state, session, coupon_code, admin=admin, user_data=user_data)
|
||||
continue
|
||||
|
||||
if "gift" in part:
|
||||
@@ -172,7 +185,7 @@ async def process_start_logic(
|
||||
gift_id = parts[0]
|
||||
sender_id = parts[1]
|
||||
logger.info(f"[GIFT] Обнаружен подарок {gift_id} от {sender_id}")
|
||||
await handle_gift_link(gift_id, message, state, session)
|
||||
await handle_gift_link(gift_id, message, state, session, user_data=user_data)
|
||||
gift_detected = True
|
||||
break
|
||||
|
||||
@@ -180,34 +193,25 @@ async def process_start_logic(
|
||||
referrer_tg_id = part.split("referral")[1].strip("_")
|
||||
try:
|
||||
referrer_tg_id = int(referrer_tg_id)
|
||||
await handle_referral_link(referrer_tg_id, message, state, session)
|
||||
await handle_referral_link(referrer_tg_id, message, state, session, user_data=user_data)
|
||||
except (ValueError, IndexError):
|
||||
pass
|
||||
continue
|
||||
|
||||
if "utm" in part:
|
||||
utm_code = part
|
||||
logger.info(f"Обнаружена ссылка на UTM: {utm_code}")
|
||||
await handle_utm_link(utm_code, message, state, session)
|
||||
logger.info(f"[UTM] Обнаружена ссылка на UTM: {utm_code}")
|
||||
await handle_utm_link(utm_code, message, state, session, user_data=user_data)
|
||||
continue
|
||||
|
||||
if gift_detected:
|
||||
return
|
||||
|
||||
user_exists = await check_user_exists(message.chat.id)
|
||||
user_exists = await check_user_exists(user_data["tg_id"])
|
||||
if not user_exists:
|
||||
from_user = message.from_user
|
||||
await add_user(
|
||||
tg_id=from_user.id,
|
||||
username=from_user.username,
|
||||
first_name=from_user.first_name,
|
||||
last_name=from_user.last_name,
|
||||
language_code=from_user.language_code,
|
||||
is_bot=from_user.is_bot,
|
||||
session=session,
|
||||
)
|
||||
await add_user(session=session, **user_data)
|
||||
|
||||
trial_status = await get_trial(message.chat.id, session)
|
||||
trial_status = await get_trial(user_data["tg_id"], session)
|
||||
|
||||
if SHOW_START_MENU_ONCE:
|
||||
if trial_status > 0:
|
||||
@@ -218,31 +222,22 @@ async def process_start_logic(
|
||||
await show_start_menu(message, admin, session)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Ошибка при обработке текста {message.text} — {e}", exc_info=True)
|
||||
logger.error(f"Ошибка при обработке текста {text} — {e}", exc_info=True)
|
||||
await message.answer("❌ Произошла ошибка. Попробуйте позже.")
|
||||
|
||||
|
||||
async def handle_utm_link(utm_code, message, state, session):
|
||||
async def handle_utm_link(utm_code, message, state, session, user_data: dict):
|
||||
user_id = user_data["tg_id"]
|
||||
exists = await session.fetchval("SELECT 1 FROM tracking_sources WHERE code = $1", utm_code)
|
||||
if exists:
|
||||
current_code = await session.fetchval("SELECT source_code FROM users WHERE tg_id = $1", message.chat.id)
|
||||
current_code = await session.fetchval("SELECT source_code FROM users WHERE tg_id = $1", user_id)
|
||||
if current_code is None:
|
||||
user_exists = await check_user_exists(message.chat.id)
|
||||
from_user = message.from_user
|
||||
user_exists = await check_user_exists(user_id)
|
||||
if not user_exists:
|
||||
await add_user(
|
||||
tg_id=from_user.id,
|
||||
username=from_user.username,
|
||||
first_name=from_user.first_name,
|
||||
last_name=from_user.last_name,
|
||||
language_code=from_user.language_code,
|
||||
is_bot=from_user.is_bot,
|
||||
session=session,
|
||||
source_code=utm_code,
|
||||
)
|
||||
await add_user(session=session, source_code=utm_code, **user_data)
|
||||
else:
|
||||
await session.execute("UPDATE users SET source_code = $1 WHERE tg_id = $2", utm_code, message.chat.id)
|
||||
logger.info(f"[UTM] Привязана {utm_code} к пользователю {message.chat.id}")
|
||||
await session.execute("UPDATE users SET source_code = $1 WHERE tg_id = $2", utm_code, user_id)
|
||||
logger.info(f"[UTM] Привязана {utm_code} к пользователю {user_id}")
|
||||
else:
|
||||
await message.answer("❌ UTM ссылка не найдена.")
|
||||
|
||||
@@ -255,17 +250,16 @@ async def show_start_menu(message: Message, admin: bool, session: Any):
|
||||
image_path = os.path.join("img", "pic.jpg")
|
||||
builder = InlineKeyboardBuilder()
|
||||
|
||||
trial_status = None
|
||||
if session is not None:
|
||||
trial_status = await get_trial(message.chat.id, session)
|
||||
logger.info(f"Trial status для {message.chat.id}: {trial_status}")
|
||||
if trial_status == 0:
|
||||
builder.row(InlineKeyboardButton(text=TRIAL_SUB, callback_data="create_key"))
|
||||
else:
|
||||
builder.row(InlineKeyboardButton(text=MAIN_MENU, callback_data="profile"))
|
||||
else:
|
||||
logger.warning(f"Сессия базы данных отсутствует, пропускаем проверку триала для {message.chat.id}")
|
||||
|
||||
if not SHOW_START_MENU_ONCE:
|
||||
if trial_status != 0 or not SHOW_START_MENU_ONCE:
|
||||
builder.row(InlineKeyboardButton(text=MAIN_MENU, callback_data="profile"))
|
||||
|
||||
if CHANNEL_EXISTS:
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user