значительная переработка интерфейса
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 62 KiB |
@@ -1,8 +1,12 @@
|
||||
import os
|
||||
from aiogram import types
|
||||
from aiogram.types import InlineKeyboardButton, InlineKeyboardMarkup
|
||||
|
||||
from aiogram.types import BufferedInputFile
|
||||
|
||||
async def send_instructions(callback_query: types.CallbackQuery):
|
||||
# Удаляем предыдущее сообщение
|
||||
await callback_query.message.delete()
|
||||
|
||||
instructions_message = (
|
||||
"*📋 Инструкции по использованию вашего ключа:*\n\n"
|
||||
"1. **Скачайте приложение для вашего устройства:**\n"
|
||||
@@ -14,8 +18,26 @@ async def send_instructions(callback_query: types.CallbackQuery):
|
||||
"4. **Выберите 'Вставить из буфера обмена' для добавления ключа.**\n\n"
|
||||
"💬 Если у вас возникнут вопросы, не стесняйтесь обращаться в [поддержку](https://t.me/solonet_sup)."
|
||||
)
|
||||
|
||||
# Путь к изображению
|
||||
image_path = os.path.join(os.path.dirname(__file__), 'instructions.jpg')
|
||||
|
||||
# Проверка существования файла изображения
|
||||
if not os.path.isfile(image_path):
|
||||
await callback_query.message.answer("Файл изображения не найден.")
|
||||
await callback_query.answer()
|
||||
return
|
||||
|
||||
back_button = InlineKeyboardButton(text='🔙 Назад', callback_data='back_to_main')
|
||||
keyboard = InlineKeyboardMarkup(inline_keyboard=[[back_button]])
|
||||
|
||||
await callback_query.message.edit_text(instructions_message, parse_mode='Markdown', reply_markup=keyboard)
|
||||
await callback_query.answer()
|
||||
# Отправка изображения и сообщения
|
||||
with open(image_path, 'rb') as image_from_buffer:
|
||||
await callback_query.message.answer_photo(
|
||||
BufferedInputFile(image_from_buffer.read(), filename="instructions.jpg"),
|
||||
caption=instructions_message,
|
||||
parse_mode='Markdown',
|
||||
reply_markup=keyboard
|
||||
)
|
||||
|
||||
await callback_query.answer()
|
||||
|
||||
@@ -271,7 +271,7 @@ async def handle_key_name_input(message: Message, state: FSMContext):
|
||||
)
|
||||
|
||||
keyboard = InlineKeyboardMarkup(inline_keyboard=[
|
||||
[InlineKeyboardButton(text='📖 Инструкции по использованию', callback_data='instructions')],
|
||||
[InlineKeyboardButton(text='📘 Инструкции по использованию', callback_data='instructions')],
|
||||
[InlineKeyboardButton(text='🔙 Перейти в профиль', callback_data='view_profile')]
|
||||
])
|
||||
|
||||
|
||||
+45
-28
@@ -318,57 +318,74 @@ async def process_callback_select_server(callback_query: types.CallbackQuery):
|
||||
try:
|
||||
conn = await asyncpg.connect(DATABASE_URL)
|
||||
try:
|
||||
record = await conn.fetchrow('SELECT email, expiry_time, server_id FROM keys WHERE client_id = $1', client_id)
|
||||
# Начинаем транзакцию с блокировкой строки по client_id, чтобы предотвратить параллельную миграцию
|
||||
async with conn.transaction():
|
||||
record = await conn.fetchrow(
|
||||
'SELECT email, expiry_time, server_id FROM keys WHERE client_id = $1 FOR UPDATE', client_id
|
||||
)
|
||||
|
||||
if record:
|
||||
email = record['email']
|
||||
expiry_time = record['expiry_time']
|
||||
current_server_id = record['server_id']
|
||||
if record:
|
||||
email = record['email']
|
||||
expiry_time = record['expiry_time']
|
||||
current_server_id = record['server_id']
|
||||
|
||||
# Авторизация на новом сервере
|
||||
session_new = await login_with_credentials(server_id, ADMIN_USERNAME, ADMIN_PASSWORD)
|
||||
new_expiry_time = int(datetime.utcnow().timestamp() * 1000) + (expiry_time - datetime.utcnow().timestamp() * 1000)
|
||||
if current_server_id == server_id:
|
||||
await callback_query.answer("Клиент уже на этом сервере.")
|
||||
return
|
||||
|
||||
# Добавляем клиента на новый сервер
|
||||
new_client_data = await add_client(session_new, server_id, client_id, email, tg_id, limit_ip=1, total_gb=0, expiry_time=new_expiry_time, enable=True, flow="xtls-rprx-vision")
|
||||
# Проверка наличия клиента на новом сервере перед добавлением
|
||||
session_new = await login_with_credentials(server_id, ADMIN_USERNAME, ADMIN_PASSWORD)
|
||||
new_client_data = await add_client(
|
||||
session_new, server_id, client_id, email, tg_id, limit_ip=1, total_gb=0,
|
||||
expiry_time=int(datetime.utcnow().timestamp() * 1000) + (expiry_time - datetime.utcnow().timestamp() * 1000),
|
||||
enable=True, flow="xtls-rprx-vision"
|
||||
)
|
||||
|
||||
if not new_client_data:
|
||||
raise Exception("Ошибка при создании клиента на новом сервере.")
|
||||
|
||||
if new_client_data:
|
||||
# Генерация нового ключа
|
||||
new_key = await link(session_new, server_id, client_id, email)
|
||||
|
||||
# Обновляем запись в БД
|
||||
await conn.execute('UPDATE keys SET server_id = $1, key = $2 WHERE client_id = $3',
|
||||
server_id, new_key, client_id)
|
||||
await conn.execute(
|
||||
'UPDATE keys SET server_id = $1, key = $2 WHERE client_id = $3',
|
||||
server_id, new_key, client_id
|
||||
)
|
||||
|
||||
# Логируем удаление клиента со старого сервера
|
||||
# Удаление клиента со старого сервера
|
||||
try:
|
||||
session_old = await login_with_credentials(current_server_id, ADMIN_USERNAME, ADMIN_PASSWORD)
|
||||
success_delete = await delete_client(session_old, current_server_id, client_id)
|
||||
|
||||
if success_delete:
|
||||
response_message = (f"Ключ успешно перемещен на новый сервер.\n\n"
|
||||
f"<b>Удалите старый ключ из вашего приложения и используйте новый для подключения к новому серверу:</b>\n"
|
||||
f"<pre>{new_key}</pre>")
|
||||
else:
|
||||
response_message = "Ошибка при удалении ключа с текущего сервера. Клиент не удален."
|
||||
print(f"Не удалось удалить клиента {client_id} с сервера {current_server_id}. Ответ API: {success_delete}")
|
||||
if not success_delete:
|
||||
raise Exception(f"Ошибка при удалении клиента с сервера {current_server_id}")
|
||||
|
||||
response_message = (
|
||||
f"Ключ успешно перемещен на новый сервер.\n\n"
|
||||
f"<b>Удалите старый ключ из вашего приложения и используйте новый для подключения к новому серверу:</b>\n"
|
||||
f"<pre>{new_key}</pre>"
|
||||
)
|
||||
except Exception as e:
|
||||
response_message = f"Ошибка при удалении клиента с текущего сервера: {e}"
|
||||
print(f"Ошибка при авторизации на старом сервере {current_server_id}: {e}")
|
||||
response_message = f"Ключ перемещен, но возникла ошибка при удалении клиента с текущего сервера: {e}"
|
||||
|
||||
else:
|
||||
response_message = "Ошибка при создании клиента на новом сервере."
|
||||
else:
|
||||
response_message = "Ключ не найден или уже удален."
|
||||
response_message = "Ключ не найден или уже удален."
|
||||
|
||||
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, parse_mode='HTML')
|
||||
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()
|
||||
|
||||
+5
-7
@@ -11,7 +11,6 @@ class ReplenishBalanceState(StatesGroup):
|
||||
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
|
||||
@@ -33,7 +32,6 @@ async def process_callback_view_profile(callback_query: types.CallbackQuery, sta
|
||||
f"<b>Обязательно подпишитесь на канал</b> <a href='https://t.me/solonet_vpn'>здесь</a>\n"
|
||||
)
|
||||
|
||||
# Если у клиента нет ключей, добавляем сообщение
|
||||
if key_count == 0:
|
||||
profile_message += "\n<i>Нажмите ➕Устройство снизу чтобы добавить устройство в VPN</i>"
|
||||
|
||||
@@ -41,14 +39,14 @@ async def process_callback_view_profile(callback_query: types.CallbackQuery, sta
|
||||
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_back]
|
||||
[button_create_key, button_view_keys], # В один ряд "➕ Устройство" и "📱 Мои устройства"
|
||||
[button_replenish_balance], # Отдельная кнопка для пополнения баланса
|
||||
[button_invite, button_instructions], # В один ряд "👥 Пригласить" и "📘 Инструкции"
|
||||
[button_back] # Отдельная кнопка "Назад"
|
||||
])
|
||||
|
||||
except Exception as e:
|
||||
|
||||
+2
-2
@@ -18,14 +18,14 @@ async def send_welcome_message(chat_id: int):
|
||||
welcome_text = (
|
||||
"<b>🎉 SoloNet — твой доступ в свободный интернет! 🌐✨</b>\n\n"
|
||||
"<b>Наши преимущества:</b>\n"
|
||||
"<pre>"
|
||||
"<blockquote>"
|
||||
"🚀 <b>Высокая скорость</b>\n"
|
||||
"🔄 <b>Стабильность</b>\n"
|
||||
"🌍 <b>Смена локаций</b>\n"
|
||||
"💬 <b>Отзывчивая поддержка</b>\n"
|
||||
"📱💻 <b>Для телефонов, компьютеров и планшетов</b>\n"
|
||||
"💰 <b>Реферальная программа: 25% от покупки</b>\n"
|
||||
"</pre>"
|
||||
"</blockquote>"
|
||||
"\n🎁 <b>1 день бесплатно</b>\n\n"
|
||||
"<i>Перейдите в профиль для продолжения 👇</i>"
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user