Merge pull request #64 from Vladless/subscriptions-feature
Подписки. Обновление ключей. Кнопки
This commit is contained in:
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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=[
|
||||
|
||||
Reference in New Issue
Block a user