From 62cc3e9cf49cc6cefe115e2db51c8458a409a2f8 Mon Sep 17 00:00:00 2001 From: Vladless Date: Fri, 4 Oct 2024 02:06:16 +0300 Subject: [PATCH] =?UTF-8?q?=D1=80=D0=B5=D1=84=D0=B5=D1=80=D0=B0=D0=BB?= =?UTF-8?q?=D1=8C=D0=BD=D0=B0=D1=8F=20=D1=81=D0=B8=D1=81=D1=82=D0=B5=D0=BC?= =?UTF-8?q?=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- database.py | 60 +++++++++++++++++++++++++++++++++++++- handlers/key_management.py | 14 +++++---- handlers/keys.py | 7 +++-- handlers/profile.py | 43 +++++++++++++++++++++++---- handlers/start.py | 21 +++++++++---- 5 files changed, 124 insertions(+), 21 deletions(-) diff --git a/database.py b/database.py index 603089de..339edc47 100644 --- a/database.py +++ b/database.py @@ -29,6 +29,13 @@ async def init_db(): PRIMARY KEY (tg_id, client_id) ) ''') + await conn.execute(''' + CREATE TABLE IF NOT EXISTS referrals ( + referred_tg_id BIGINT PRIMARY KEY NOT NULL, -- ID приглашенного пользователя + referrer_tg_id BIGINT NOT NULL, -- ID пригласившего пользователя + reward_issued BOOLEAN DEFAULT FALSE -- Был ли начислен бонус + ) + ''') try: await conn.execute(''' @@ -111,6 +118,10 @@ async def update_balance(tg_id: int, amount: float): SET balance = balance + $1 WHERE tg_id = $2 ''', amount, tg_id) + + # Проверка и начисление реферального бонуса + await handle_referral_on_balance_update(tg_id, amount) + await conn.close() async def get_trial(tg_id: int) -> int: @@ -126,4 +137,51 @@ async def get_key_count(tg_id: int) -> int: return count if count is not None else 0 async def get_all_users(conn): - return await conn.fetch('SELECT tg_id FROM connections') \ No newline at end of file + return await conn.fetch('SELECT tg_id FROM connections') + +async def add_referral(referred_tg_id: int, referrer_tg_id: int): + conn = await asyncpg.connect(DATABASE_URL) + await conn.execute(''' + INSERT INTO referrals (referred_tg_id, referrer_tg_id) + VALUES ($1, $2) + ''', referred_tg_id, referrer_tg_id) + await conn.close() + +async def handle_referral_on_balance_update(tg_id: int, amount: float): + conn = await asyncpg.connect(DATABASE_URL) + + # Проверяем, есть ли реферал в таблице + referral = await conn.fetchrow(''' + SELECT referrer_tg_id, reward_issued FROM referrals WHERE referred_tg_id = $1 + ''', tg_id) + + if referral and not referral['reward_issued'] and amount > 0: + referrer_tg_id = referral['referrer_tg_id'] + + # Начисляем бонус (25% от платежа) пригласившему + bonus = amount * 0.25 # 25% от платежа + await update_balance(referrer_tg_id, bonus) + + # Обновляем статус бонуса как выданный + await conn.execute(''' + UPDATE referrals SET reward_issued = TRUE WHERE referred_tg_id = $1 + ''', tg_id) + + await conn.close() + +async def get_referral_stats(referrer_tg_id: int): + conn = await asyncpg.connect(DATABASE_URL) + total_referrals = await conn.fetchval(''' + SELECT COUNT(*) FROM referrals WHERE referrer_tg_id = $1 + ''', referrer_tg_id) + + active_referrals = await conn.fetchval(''' + SELECT COUNT(*) FROM referrals WHERE referrer_tg_id = $1 AND reward_issued = TRUE + ''', referrer_tg_id) + + await conn.close() + + return { + 'total_referrals': total_referrals, + 'active_referrals': active_referrals + } \ No newline at end of file diff --git a/handlers/key_management.py b/handlers/key_management.py index 40679b3f..b7e5fbdc 100644 --- a/handlers/key_management.py +++ b/handlers/key_management.py @@ -44,6 +44,10 @@ async def process_callback_create_key(callback_query: CallbackQuery, state: FSMC finally: await conn.close() + # Добавляем кнопку "Назад" + button_back = InlineKeyboardButton(text='⬅️ Назад', callback_data='view_profile') + server_buttons.append([button_back]) # Кнопка "Назад" внизу списка серверов + await callback_query.message.edit_text( "⚙️ Выберите сервер для создания ключа:", parse_mode="HTML", @@ -121,7 +125,11 @@ async def cancel_create_key(callback_query: CallbackQuery, state: FSMContext): @dp.message() async def handle_text(message: Message, state: FSMContext): current_state = await state.get_state() - + + if message.text in ["/start", "/menu"]: + await start_command(message) + return + if message.text == "Мой профиль": callback_query = types.CallbackQuery( id="1", @@ -132,10 +140,6 @@ async def handle_text(message: Message, state: FSMContext): ) await process_callback_view_profile(callback_query, state) return - - if message.text in ["/start", "/menu"]: - await start_command(message) - return if message.text in ["/send_to_all"]: await send_message_to_all_clients(message) diff --git a/handlers/keys.py b/handlers/keys.py index 586cdcbe..b17f8289 100644 --- a/handlers/keys.py +++ b/handlers/keys.py @@ -320,7 +320,7 @@ async def process_callback_select_server(callback_query: types.CallbackQuery): success_delete = delete_client(session, current_server_id, client_id) if success_delete: response_message = ("Ключ успешно перемещен на новый сервер.\n\n" - "Не забудьте удалить старый ключ из вашего приложения и установить новый.") + "Не забудьте удалить старый ключ из вашего приложения и установить новый.") else: response_message = "Ошибка при удалении ключа с текущего сервера." else: @@ -332,12 +332,13 @@ async def process_callback_select_server(callback_query: types.CallbackQuery): back_button = types.InlineKeyboardButton(text='Назад', callback_data='view_keys') keyboard = types.InlineKeyboardMarkup(inline_keyboard=[[back_button]]) - await bot.edit_message_text(response_message, chat_id=tg_id, message_id=callback_query.message.message_id, reply_markup=keyboard) + # Указываем parse_mode='HTML' для форматирования + await bot.edit_message_text(response_message, chat_id=tg_id, message_id=callback_query.message.message_id, reply_markup=keyboard, parse_mode='HTML') finally: await conn.close() except Exception as e: - await bot.edit_message_text(f"Ошибка при смене локации: {e}", chat_id=tg_id, message_id=callback_query.message.message_id) + await bot.edit_message_text(f"Ошибка при смене локации: {e}", chat_id=tg_id, message_id=callback_query.message.message_id, parse_mode='HTML') await callback_query.answer() diff --git a/handlers/profile.py b/handlers/profile.py index 5641c6ea..78b7e6bb 100644 --- a/handlers/profile.py +++ b/handlers/profile.py @@ -1,17 +1,18 @@ from aiogram import Router, types from aiogram.fsm.context import FSMContext -from aiogram.fsm.state import State, StatesGroup from aiogram.types import InlineKeyboardButton, InlineKeyboardMarkup +from aiogram.fsm.state import State, StatesGroup from bot import bot -from database import get_balance, get_key_count - -router = Router() +from database import get_balance, get_key_count, get_referral_stats class ReplenishBalanceState(StatesGroup): choosing_transfer_method = State() waiting_for_admin_confirmation = State() +router = Router() + +# Хендлер для показа профиля async def process_callback_view_profile(callback_query: types.CallbackQuery, state: FSMContext): tg_id = callback_query.from_user.id username = callback_query.from_user.full_name @@ -32,12 +33,14 @@ async def process_callback_view_profile(callback_query: types.CallbackQuery, sta button_create_key = InlineKeyboardButton(text='➕ Устройство', callback_data='create_key') button_view_keys = InlineKeyboardButton(text='📱 Мои устройства', callback_data='view_keys') button_replenish_balance = InlineKeyboardButton(text='💳 Пополнить баланс', callback_data='replenish_balance') - button_back = InlineKeyboardButton(text='⬅️ Назад', callback_data='back_to_menu') # Добавляем кнопку "Назад" + button_invite = InlineKeyboardButton(text='👥 Пригласить', callback_data='invite') + button_back = InlineKeyboardButton(text='⬅️ Назад', callback_data='back_to_menu') keyboard = InlineKeyboardMarkup(inline_keyboard=[ [button_create_key], [button_view_keys], [button_replenish_balance], + [button_invite], # Добавили кнопку "Пригласить" [button_back] ]) @@ -56,6 +59,34 @@ async def process_callback_view_profile(callback_query: types.CallbackQuery, sta await callback_query.answer() +# Хендлер для кнопки "Пригласить" +@router.callback_query(lambda c: c.data == 'invite') +async def invite_handler(callback_query: types.CallbackQuery): + tg_id = callback_query.from_user.id + referral_link = f"https://t.me/SoloNetVPN_bot?start=referral_{tg_id}" + + referral_stats = await get_referral_stats(tg_id) + + invite_message = ( + f"👥 Ваша реферальная ссылка: {referral_link}\n\n" + f"🔹 Всего приглашено: {referral_stats['total_referrals']} пользователей\n" + f"🔹 Активных рефералов: {referral_stats['active_referrals']}" + ) + + button_back = InlineKeyboardButton(text='⬅️ Назад', callback_data='view_profile') + keyboard = InlineKeyboardMarkup(inline_keyboard=[[button_back]]) + + await callback_query.message.delete() + + await bot.send_message( + chat_id=tg_id, + text=invite_message, + parse_mode='HTML', + reply_markup=keyboard + ) + + await callback_query.answer() + @router.callback_query(lambda c: c.data == 'view_profile') async def view_profile_handler(callback_query: types.CallbackQuery, state: FSMContext): - await process_callback_view_profile(callback_query, state) + await process_callback_view_profile(callback_query, state) \ No newline at end of file diff --git a/handlers/start.py b/handlers/start.py index 87f002e4..1faa3e92 100644 --- a/handlers/start.py +++ b/handlers/start.py @@ -1,5 +1,4 @@ import os - from aiogram import Router from aiogram.filters import Command from aiogram.fsm.state import State, StatesGroup @@ -7,6 +6,7 @@ from aiogram.types import (BufferedInputFile, CallbackQuery, InlineKeyboardButton, InlineKeyboardMarkup, Message) from bot import bot +from database import add_referral, check_connection_exists, add_connection from config import CHANNEL_URL, SUPPORT_CHAT_URL router = Router() @@ -30,7 +30,7 @@ async def send_welcome_message(chat_id: int): inline_keyboard = InlineKeyboardMarkup(inline_keyboard=[ [InlineKeyboardButton(text='👤 Мой профиль', callback_data='view_profile')], [InlineKeyboardButton(text='🔒 О VPN', callback_data='about_vpn')], - [InlineKeyboardButton(text='📞 Поддержка', url=SUPPORT_CHAT_URL)], # Изменили на кнопку Поддержка + [InlineKeyboardButton(text='📞 Поддержка', url=SUPPORT_CHAT_URL)], [InlineKeyboardButton(text='📢 Наш канал', url=CHANNEL_URL)] ]) @@ -45,11 +45,22 @@ async def send_welcome_message(chat_id: int): @router.message(Command('start')) async def start_command(message: Message): - await send_welcome_message(message.chat.id) + if 'referral_' in message.text: + referrer_tg_id = int(message.text.split('referral_')[1]) + + if not await check_connection_exists(message.from_user.id): + await add_connection(message.from_user.id) + + await add_referral(message.from_user.id, referrer_tg_id) + + await message.answer("Вас пригласил друг, добро пожаловать!") + else: + await message.answer("Вы уже зарегистрированы в системе!") + else: + await send_welcome_message(message.chat.id) @router.callback_query(lambda c: c.data == 'about_vpn') async def handle_about_vpn(callback_query: CallbackQuery): - await callback_query.message.delete() info_message = ( "*О VPN*\n\n" @@ -58,7 +69,6 @@ async def handle_about_vpn(callback_query: CallbackQuery): "Ваш ключ — ваша безопасность! Не передавайте своё шифрование сторонним лицам." ) - button_back = InlineKeyboardButton(text='⬅️ Назад', callback_data='back_to_menu') inline_keyboard_back = InlineKeyboardMarkup(inline_keyboard=[[button_back]]) @@ -71,7 +81,6 @@ async def handle_about_vpn(callback_query: CallbackQuery): @router.callback_query(lambda c: c.data == 'back_to_menu') async def handle_back_to_menu(callback_query: CallbackQuery): - await callback_query.message.delete() await send_welcome_message(callback_query.from_user.id) await callback_query.answer()