Merge pull request #41 from Vladless/new1

создание ключа в 1 кнопку
This commit is contained in:
Vladislav Lisitsyn
2024-10-26 00:57:22 +03:00
committed by GitHub
3 changed files with 130 additions and 16 deletions
+44 -10
View File
@@ -1,22 +1,22 @@
import os
from aiogram import Router
from aiogram.filters import Command
from aiogram.fsm.state import State, StatesGroup
from aiogram.types import (BufferedInputFile, CallbackQuery,
InlineKeyboardButton, InlineKeyboardMarkup, Message)
from handlers.texts import ABOUT_VPN, WELCOME_TEXT
from bot import bot
from config import CHANNEL_URL, SUPPORT_CHAT_URL
from database import add_connection, add_referral, check_connection_exists
from database import add_connection, add_referral, check_connection_exists, get_trial
from handlers.trial_key import create_trial_key
from handlers.texts import INSTRUCTIONS_TRIAL
router = Router()
class FeedbackState(StatesGroup):
waiting_for_feedback = State()
async def send_welcome_message(chat_id: int):
async def send_welcome_message(chat_id: int, trial_status: int):
welcome_text = WELCOME_TEXT
image_path = os.path.join(os.path.dirname(__file__), 'pic.jpg')
@@ -26,12 +26,15 @@ async def send_welcome_message(chat_id: int):
return
inline_keyboard = InlineKeyboardMarkup(inline_keyboard=[
[InlineKeyboardButton(text='🔗 Подключить VPN', callback_data='connect_vpn')] if trial_status == 0 else [],
[InlineKeyboardButton(text='👤 Мой профиль', callback_data='view_profile')],
[InlineKeyboardButton(text='🔒 О VPN', callback_data='about_vpn')],
[InlineKeyboardButton(text='📞 Поддержка', url=SUPPORT_CHAT_URL)],
[InlineKeyboardButton(text='📢 Наш канал', url=CHANNEL_URL)]
[InlineKeyboardButton(text='📞 Поддержка', url=SUPPORT_CHAT_URL)],
[InlineKeyboardButton(text='📢 Наш канал', url=CHANNEL_URL)],
])
inline_keyboard.inline_keyboard = [row for row in inline_keyboard.inline_keyboard if row]
with open(image_path, 'rb') as image_from_buffer:
await bot.send_photo(
chat_id,
@@ -49,13 +52,43 @@ async def start_command(message: Message):
print(f"Referral ID: {referrer_tg_id}")
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("Вы уже зарегистрированы в системе!")
await send_welcome_message(message.chat.id)
trial_status = await get_trial(message.from_user.id)
await send_welcome_message(message.chat.id, trial_status)
@router.callback_query(lambda c: c.data == 'connect_vpn')
async def handle_connect_vpn(callback_query: CallbackQuery):
await callback_query.message.delete()
user_id = callback_query.from_user.id
# Создаём триальный ключ
trial_key_info = await create_trial_key(user_id)
if 'error' in trial_key_info:
await callback_query.message.answer(trial_key_info['error'])
else:
# Формируем сообщение с ключом и инструкциями
key_message = (
f"<b>Ваш ключ доступа:</b>\n<pre>{trial_key_info['key']}</pre>\n\n"
f"<b>Инструкции:</b>\n{INSTRUCTIONS_TRIAL}"
)
# Кнопка "В профиль"
button_profile = InlineKeyboardButton(text='👤 Мой профиль', callback_data='view_profile')
inline_keyboard_profile = InlineKeyboardMarkup(inline_keyboard=[[button_profile]])
# Отправляем текст с ключом и инструкциями в виде цитаты
await callback_query.message.answer(
key_message,
parse_mode='HTML',
reply_markup=inline_keyboard_profile
)
await callback_query.answer()
@router.callback_query(lambda c: c.data == 'about_vpn')
async def handle_about_vpn(callback_query: CallbackQuery):
@@ -75,5 +108,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)
trial_status = await get_trial(callback_query.from_user.id)
await send_welcome_message(callback_query.from_user.id, trial_status)
await callback_query.answer()
+19 -6
View File
@@ -68,15 +68,28 @@ INSTRUCTIONS = (
"💬 Если у вас возникнут вопросы, не стесняйтесь обращаться в [поддержку](https://t.me/solonet_sup)."
)
KEY_EXPIRY_10H = "🔔 Уведомление: Ваш ключ для сервера {server_id} истекает через 10 часов.\n" \
"Email: {email}\n" \
"Дата истечения: {expiry_date}"
INSTRUCTIONS_TRIAL = (
"<b>📋 Инструкции по использованию вашего ключа:</b>\n\n"
"1. <b>Скачайте приложение для вашего устройства:</b>\n"
" - <b>Для Android:</b> <a href='https://play.google.com/store/apps/details?id=com.v2ray.ang&hl=ru&pli=1'>V2Ray</a>\n"
" - <b>Для iPhone:</b> <a href='https://apps.apple.com/ru/app/streisand/id6450534064'>Streisand</a>\n"
" - <b>Для Windows:</b> <a href='https://github.com/hiddify/hiddify-next/releases/latest/download/Hiddify-Windows-Setup-x64.Msix'>Hiddify Next</a>\n\n"
"2. <b>Скопируйте предоставленный ключ</b>, который вы получили ранее.\n"
"3. <b>Откройте приложение и нажмите на плюсик сверху справа.</b>\n"
"4. <b>Выберите 'Вставить из буфера обмена' для добавления ключа.</b>\n\n"
"💬 Если у вас возникнут вопросы, не стесняйтесь обращаться в <a href='https://t.me/solonet_sup'>поддержку</a>."
)
KEY_EXPIRY_24H = "⏳ Уведомление: Ваш ключ для сервера {server_id} истекает через 24 часа.\n" \
"Email: {email}\n" \
KEY_EXPIRY_10H = "🔔 Уведомление: Ваш ключ {email} для сервера {server_id} истекает через 10 часов.\n" \
"Дата истечения: {expiry_date}"\
"Перейдите в профиль и пополните баланс, всего 100 рублей на целый месяц"\
"ключ продлится автоматически"
KEY_EXPIRY_24H = "🔔 Уведомление: Ваш ключ {email} для сервера {server_id} истекает через 24 часа.\n" \
"Осталось времени: {hours_left} часов\n" \
"Дата истечения: {expiry_date}\n" \
"Баланс: {balance:.2f} руб."
"Баланс: {balance:.2f} руб."\
KEY_RENEWED = "Ваш ключ был продлен на месяц."
KEY_RENEWAL_FAILED = "Не удалось продлить ключ на панели, обратитесь в поддержку."
+67
View File
@@ -0,0 +1,67 @@
import random
import asyncpg
import time
import uuid # Импортируем модуль для генерации UUID
from config import DATABASE_URL, SERVERS, ADMIN_USERNAME, ADMIN_PASSWORD
from auth import login_with_credentials, link # Импортируйте необходимые функции
from client import add_client
from database import store_key, add_connection
from handlers.texts import INSTRUCTIONS
from datetime import datetime, timedelta
def generate_random_email():
"""Генерирует случайный набор символов."""
random_string = ''.join(random.choices('abcdefghijklmnopqrstuvwxyz0123456789', k=6))
return random_string
async def create_trial_key(tg_id: int):
conn = await asyncpg.connect(DATABASE_URL)
try:
server_id = await get_least_loaded_server(conn)
session = await login_with_credentials(server_id, ADMIN_USERNAME, ADMIN_PASSWORD)
current_time = datetime.utcnow()
expiry_time = current_time + timedelta(days=30, hours=3)
expiry_timestamp = int(expiry_time.timestamp() * 1000)
client_id = str(uuid.uuid4())
email = generate_random_email()
response = await add_client(
session, server_id, client_id, email, tg_id,
limit_ip=1, total_gb=0, expiry_time=expiry_timestamp,
enable=True, flow="xtls-rprx-vision"
)
if response.get("success"):
connection_link = await link(session, server_id, client_id, email)
existing_connection = await conn.fetchrow('SELECT * FROM connections WHERE tg_id = $1', tg_id)
if existing_connection:
await conn.execute('UPDATE connections SET trial = 1 WHERE tg_id = $1', tg_id)
else:
await add_connection(tg_id, 0, 1)
await store_key(tg_id, client_id, email, expiry_timestamp, connection_link, server_id)
instructions = INSTRUCTIONS
return {
'key': connection_link,
'instructions': instructions
}
else:
return {'error': 'Не удалось добавить клиента на панель'}
finally:
await conn.close()
async def get_least_loaded_server(conn):
least_loaded_server_id = None
min_load_percentage = float('inf')
for server_id, server in SERVERS.items():
count = await conn.fetchval('SELECT COUNT(*) FROM keys WHERE server_id = $1', server_id)
percent_full = (count / 60) * 100 if count <= 60 else 100
if percent_full < min_load_percentage:
min_load_percentage = percent_full
least_loaded_server_id = server_id
return least_loaded_server_id