Merge pull request #28 from Vladless/youkassa

Youkassa
This commit is contained in:
Vladislav Lisitsyn
2024-10-04 02:13:12 +03:00
committed by GitHub
6 changed files with 131 additions and 25 deletions
+59 -1
View File
@@ -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')
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
}
+9 -5
View File
@@ -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(
"<b>⚙️ Выберите сервер для создания ключа:</b>",
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)
+4 -3
View File
@@ -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"
"<b>Не забудьте удалить старый ключ из вашего приложения и установить новый.<b>")
"<b>Не забудьте удалить старый ключ из вашего приложения и установить новый.</b>")
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()
+7 -4
View File
@@ -104,19 +104,22 @@ async def send_message_to_all_clients(message: types.Message):
await message.answer("У вас нет прав для выполнения этой команды.")
return
text = message.get_args()
if not text:
# Получаем текст сообщения после команды
text = message.text.split(maxsplit=1) # Разделяем текст сообщения на части
if len(text) < 2: # Если нет текста после команды
await message.answer("Пожалуйста, введите текст сообщения после команды.")
return
text_message = text[1] # Получаем текст сообщения
try:
conn = await asyncpg.connect(DATABASE_URL)
tg_ids = await conn.fetch('SELECT tg_id FROM keys')
tg_ids = await conn.fetch('SELECT tg_id FROM connections')
for record in tg_ids:
tg_id = record['tg_id']
try:
await bot.send_message(chat_id=tg_id, text=text)
await bot.send_message(chat_id=tg_id, text=text_message)
except Exception as e:
print(f"Ошибка при отправке сообщения пользователю {tg_id}: {e}. Пропускаем этого пользователя.")
+37 -6
View File
@@ -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"👥 <b>Ваша реферальная ссылка:</b> {referral_link}\n\n"
f"🔹 <b>Всего приглашено:</b> {referral_stats['total_referrals']} пользователей\n"
f"🔹 <b>Активных рефералов:</b> {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)
+15 -6
View File
@@ -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):
"<b>Ваш ключ — ваша безопасность! Не передавайте своё шифрование сторонним лицам.</b>"
)
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()