Merge pull request #64 from Vladless/subscriptions-feature

Подписки. Обновление ключей. Кнопки
This commit is contained in:
Vladislav Lisitsyn
2024-11-02 04:25:49 +03:00
committed by GitHub
5 changed files with 90 additions and 61 deletions
+22 -15
View File
@@ -1,7 +1,7 @@
import uuid
from datetime import datetime, timedelta
from bot import dp
from bot import dp, bot
import asyncpg
from aiogram import F, Router
from aiogram.fsm.context import FSMContext
@@ -12,7 +12,7 @@ from aiogram.types import (CallbackQuery, InlineKeyboardButton,
from auth import login_with_credentials, link_subscription
from client import add_client
from config import (ADMIN_PASSWORD, ADMIN_USERNAME, DATABASE_URL,
SERVERS)
SERVERS, APP_URL)
from database import add_connection, get_balance, store_key, update_balance
from handlers.instructions.instructions import send_instructions
from handlers.profile import process_callback_view_profile
@@ -43,16 +43,17 @@ async def process_callback_create_key(callback_query: CallbackQuery, state: FSMC
await conn.close()
button_back = InlineKeyboardButton(text='⬅️ Назад', callback_data='view_profile')
server_buttons.append([button_back])
server_buttons.append([button_back])
await callback_query.message.edit_text(
"<b>⚙️ Выберите сервер для создания ключа:</b>",
await callback_query.message.delete()
await bot.send_message(
chat_id=tg_id,
text="<b>⚙️ Выберите сервер для создания ключа:</b>",
parse_mode="HTML",
reply_markup=InlineKeyboardMarkup(inline_keyboard=server_buttons)
)
await state.set_state(Form.waiting_for_server_selection)
await state.set_state(Form.waiting_for_server_selection)
await callback_query.answer()
@@ -190,18 +191,24 @@ async def handle_key_name_input(message: Message, state: FSMContext):
hours, remainder = divmod(remaining_time.seconds, 3600)
minutes, _ = divmod(remainder, 60)
remaining_time_message = (
f"Оставшееся время ключа: {days} день"
)
remaining_time_message = f"Оставшееся время ключа: {days} день"
button_profile = InlineKeyboardButton(text='👤 Мой профиль', callback_data='view_profile')
button_iphone = InlineKeyboardButton(
text='🍏IPhone',
url=f'{APP_URL}/?url=v2raytun://import/{connection_link}'
)
button_android = InlineKeyboardButton(
text='🤖Android',
url=f'{APP_URL}/?url=v2raytun://import-sub?url={connection_link}'
)
keyboard = InlineKeyboardMarkup(inline_keyboard=[
[InlineKeyboardButton(text='📘 Инструкции по использованию', callback_data='instructions')],
[InlineKeyboardButton(text='🔙 Перейти в профиль', callback_data='view_profile')]
[button_iphone, button_android],
[button_profile]
])
key_message = (
key_message_success(connection_link, remaining_time_message)
)
key_message = key_message_success(connection_link, remaining_time_message)
await message.bot.send_message(tg_id, key_message, parse_mode="HTML", reply_markup=keyboard)
+30 -12
View File
@@ -42,20 +42,32 @@ async def process_callback_view_keys(callback_query: types.CallbackQuery):
inline_keyboard = types.InlineKeyboardMarkup(inline_keyboard=buttons)
response_message = (
"<b>Это ваши устройства:</b>\n\n"
"<i>Нажмите на имя устройства для управления его ключом.</i>" # Добавлено курсивом
"<i>Нажмите на имя устройства для управления его ключом.</i>"
)
await bot.edit_message_text(response_message, chat_id=tg_id, message_id=callback_query.message.message_id, reply_markup=inline_keyboard, parse_mode="HTML")
else:
response_message = (
NO_KEYS
await bot.delete_message(chat_id=tg_id, message_id=callback_query.message.message_id)
await bot.send_message(
chat_id=tg_id,
text=response_message,
reply_markup=inline_keyboard,
parse_mode="HTML"
)
else:
response_message = NO_KEYS
create_key_button = types.InlineKeyboardButton(text=' Создать ключ', callback_data='create_key')
back_button = types.InlineKeyboardButton(text='🔙 Назад', callback_data='view_profile')
keyboard = types.InlineKeyboardMarkup(inline_keyboard=[[create_key_button], [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.delete_message(chat_id=tg_id, message_id=callback_query.message.message_id)
await bot.send_message(
chat_id=tg_id,
text=response_message,
reply_markup=keyboard,
parse_mode="HTML"
)
finally:
await conn.close()
@@ -65,7 +77,6 @@ async def process_callback_view_keys(callback_query: types.CallbackQuery):
await callback_query.answer()
@router.callback_query(lambda c: c.data.startswith('view_key|'))
async def process_callback_view_key(callback_query: types.CallbackQuery):
tg_id = callback_query.from_user.id
@@ -281,7 +292,15 @@ async def handle_error(tg_id, callback_query, message):
@router.callback_query(lambda c: c.data.startswith('change_location|'))
async def process_callback_change_location(callback_query: types.CallbackQuery):
tg_id = callback_query.from_user.id
client_id = callback_query.data.split('|')[1]
client_id = callback_query.data.split('|')[1]
instructions_message = (
"<b>Перед сменой локации:</b>\n\n"
"1. Пожалуйста, отключите ваш VPN.\n"
"2. Удалите старый ключ, чтобы избежать конфликтов.\n\n"
"Теперь выберите новый сервер для вашего ключа:"
)
server_buttons = []
conn = await asyncpg.connect(DATABASE_URL)
try:
@@ -295,8 +314,7 @@ async def process_callback_change_location(callback_query: types.CallbackQuery):
keyboard = types.InlineKeyboardMarkup(inline_keyboard=server_buttons)
response_message = "<b>Выберите новый сервер для вашего ключа:</b>"
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(instructions_message, chat_id=tg_id, message_id=callback_query.message.message_id, reply_markup=keyboard, parse_mode="HTML")
await callback_query.answer()
@router.callback_query(lambda c: c.data.startswith('select_server&'))
@@ -355,11 +373,11 @@ async def process_callback_select_server(callback_query: types.CallbackQuery):
back_button = types.InlineKeyboardButton(text='Назад', callback_data='view_keys')
iphone_button = types.InlineKeyboardButton(
text='🍏IPhone',
url=f'{APP_URL}/?url=streisand://import/{new_key}'
url=f'{APP_URL}/?url=v2raytun://import/{new_key}'
)
android_button = types.InlineKeyboardButton(
text='🤖Android',
url=f'{APP_URL}/?url=v2rayng://install-sub?url={new_key}'
url=f'{APP_URL}/?url=v2raytun://import-sub?url={new_key}'
)
keyboard = types.InlineKeyboardMarkup(
+5 -2
View File
@@ -76,14 +76,17 @@ async def process_callback_replenish_balance(callback_query: types.CallbackQuery
]
])
await callback_query.message.edit_text(
await bot.delete_message(chat_id=tg_id, message_id=callback_query.message.message_id)
await bot.send_message(
chat_id=tg_id,
text="Выберите сумму пополнения:",
reply_markup=amount_keyboard
)
await state.set_state(ReplenishBalanceState.choosing_amount)
await callback_query.answer()
@router.callback_query(lambda c: c.data == 'back_to_profile')
async def back_to_profile_handler(callback_query: types.CallbackQuery, state: FSMContext):
await process_callback_view_profile(callback_query, state)
+31 -30
View File
@@ -1,7 +1,9 @@
import os
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.types import InlineKeyboardButton, InlineKeyboardMarkup, BufferedInputFile
from bot import bot
from database import get_balance, get_key_count, get_referral_stats
@@ -14,54 +16,53 @@ class ReplenishBalanceState(StatesGroup):
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
image_path = os.path.join(os.path.dirname(__file__), 'pic.jpg')
if not os.path.isfile(image_path):
await bot.send_message(tg_id, "Файл изображения не найден.")
return
try:
key_count = await get_key_count(tg_id)
balance = await get_balance(tg_id)
if balance is None:
balance = 0
profile_message = (
profile_message_send(username, tg_id, balance, key_count)
)
profile_message = profile_message_send(username, tg_id, balance, key_count)
profile_message += (
f"<b>Обязательно подпишитесь на канал</b> <a href='{CHANNEL_LINK}'>здесь</a>\n"
)
if key_count == 0:
profile_message += "\n<i>Нажмите ➕Устройство снизу чтобы добавить устройство в VPN</i>"
profile_message += "\n<i>Нажмите ➕Устройство снизу, чтобы добавить устройство в VPN</i>"
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_invite = InlineKeyboardButton(text='👥 Пригласить', callback_data='invite')
button_instructions = InlineKeyboardButton(text='📘 Инструкции', callback_data='instructions')
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_instructions],
[button_back]
inline_keyboard = InlineKeyboardMarkup(inline_keyboard=[
[InlineKeyboardButton(text=' Устройство', callback_data='create_key'), InlineKeyboardButton(text='📱 Мои устр-ва', callback_data='view_keys')],
[InlineKeyboardButton(text='💳 Пополнить баланс', callback_data='replenish_balance')],
[InlineKeyboardButton(text='👥 Пригласить', callback_data='invite'), InlineKeyboardButton(text='📘 Инструкции', callback_data='instructions')],
[InlineKeyboardButton(text='⬅️ Назад', callback_data='back_to_menu')]
])
await callback_query.message.delete()
with open(image_path, 'rb') as image_file:
await bot.send_photo(
chat_id=tg_id,
photo=BufferedInputFile(image_file.read(), filename="pic.jpg"),
caption=profile_message,
parse_mode='HTML',
reply_markup=inline_keyboard
)
except Exception as e:
profile_message = f"❗️ Ошибка при получении данных профиля: {e}"
keyboard = None
await callback_query.message.delete()
await bot.send_message(
chat_id=tg_id,
text=profile_message,
parse_mode='HTML',
reply_markup=keyboard
)
await bot.send_message(tg_id, f"❗️ Ошибка при получении данных профиля: {e}")
await callback_query.answer()
@router.callback_query(lambda c: c.data == 'invite')
+2 -2
View File
@@ -79,11 +79,11 @@ async def handle_connect_vpn(callback_query: CallbackQuery):
button_iphone = InlineKeyboardButton(
text='🍏IPhone',
url=f'{APP_URL}/?url=streisand://import/{trial_key_info["key"]}'
url=f'{APP_URL}/?url=v2raytun://import/{trial_key_info["key"]}'
)
button_android = InlineKeyboardButton(
text='🤖Android',
url=f'{APP_URL}/?url=v2rayng://install-sub?url={trial_key_info["key"]}'
url=f'{APP_URL}/?url=v2raytun://import-sub?url={trial_key_info["key"]}'
)
inline_keyboard = InlineKeyboardMarkup(inline_keyboard=[