@@ -1,13 +1,15 @@
|
||||
import requests
|
||||
from config import ADMIN_USERNAME, ADMIN_PASSWORD, GET_INBOUNDS_URL
|
||||
import json
|
||||
|
||||
import requests
|
||||
|
||||
from config import API_URL, GET_INBOUNDS_URL
|
||||
|
||||
session = None
|
||||
|
||||
def login_with_credentials(username, password):
|
||||
global session
|
||||
session = requests.Session()
|
||||
auth_url = "https://solonet.pocomacho.ru:62553/solonet/login/"
|
||||
auth_url = f"{API_URL}/login/"
|
||||
data = {
|
||||
"username": username,
|
||||
"password": password
|
||||
@@ -39,7 +41,7 @@ def link(session, client_id: str, email: str):
|
||||
if 'obj' not in response or len(response['obj']) == 0:
|
||||
raise Exception("Не удалось получить данные клиентов.")
|
||||
|
||||
inbounds = response['obj'][0] # Убедитесь, что это правильный индекс
|
||||
inbounds = response['obj'][0]
|
||||
settings = json.loads(inbounds['settings'])
|
||||
|
||||
# Найти клиентский ID в настройках
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
from aiogram import Bot, Dispatcher, Router
|
||||
from aiogram.fsm.storage.memory import MemoryStorage
|
||||
from config import API_TOKEN
|
||||
|
||||
from auth import login_with_credentials
|
||||
from config import API_TOKEN
|
||||
|
||||
bot = Bot(token=API_TOKEN)
|
||||
storage = MemoryStorage()
|
||||
dp = Dispatcher(bot=bot, storage=storage)
|
||||
router = Router()
|
||||
|
||||
from handlers import start, profile, keys, balance, pay
|
||||
from handlers import balance, keys, pay, profile, start
|
||||
from key_management import router as key_management_router
|
||||
|
||||
|
||||
# Регистрация обработчиков
|
||||
dp.include_router(start.router)
|
||||
dp.include_router(profile.router)
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import json
|
||||
|
||||
from config import API_URL
|
||||
|
||||
|
||||
def add_client(session, client_id: str, email: str, tg_id: str, limit_ip: int, total_gb: int, expiry_time: int, enable: bool, flow: str):
|
||||
url = 'https://solonet.pocomacho.ru:62553/solonet/panel/api/inbounds/addClient'
|
||||
url = f'{API_URL}/panel/api/inbounds/addClient'
|
||||
|
||||
email = email.lower()
|
||||
|
||||
@@ -41,7 +44,7 @@ def add_client(session, client_id: str, email: str, tg_id: str, limit_ip: int, t
|
||||
print(f"Ошибка при добавлении клиента: {response.status_code}, {response.text}")
|
||||
|
||||
def extend_client_key(session, tg_id, client_id, email: str, new_expiry_time: int) -> bool:
|
||||
response = session.get(f"https://solonet.pocomacho.ru:62553/solonet/panel/api/inbounds/getClientTraffics/{email}")
|
||||
response = session.get(f"{API_URL}/panel/api/inbounds/getClientTraffics/{email}")
|
||||
print(f"GET {response.url} Status: {response.status_code}")
|
||||
print(f"GET Response: {response.text}")
|
||||
|
||||
@@ -89,7 +92,7 @@ def extend_client_key(session, tg_id, client_id, email: str, new_expiry_time: in
|
||||
}
|
||||
|
||||
try:
|
||||
response = session.post(f"https://solonet.pocomacho.ru:62553/solonet/panel/api/inbounds/updateClient/{client_id}", json=payload, headers=headers)
|
||||
response = session.post(f"{API_URL}/panel/api/inbounds/updateClient/{client_id}", json=payload, headers=headers)
|
||||
print(f"POST {response.url} Status: {response.status_code}")
|
||||
print(f"POST Request Data: {json.dumps(payload, indent=2)}")
|
||||
print(f"POST Response: {response.text}")
|
||||
@@ -104,7 +107,7 @@ def extend_client_key(session, tg_id, client_id, email: str, new_expiry_time: in
|
||||
return False
|
||||
|
||||
def delete_client(session, client_id: str) -> bool:
|
||||
url = f"https://solonet.pocomacho.ru:62553/solonet/panel/api/inbounds/1/delClient/{client_id}"
|
||||
url = f"{API_URL}/panel/api/inbounds/1/delClient/{client_id}"
|
||||
headers = {
|
||||
'Accept': 'application/json'
|
||||
}
|
||||
|
||||
+5
-2
@@ -1,6 +1,9 @@
|
||||
import asyncpg
|
||||
from datetime import datetime
|
||||
from config import DATABASE_URL
|
||||
|
||||
import asyncpg
|
||||
|
||||
from config import DATABASE_URL
|
||||
|
||||
|
||||
async def init_db():
|
||||
conn = await asyncpg.connect(DATABASE_URL)
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+1
-1
@@ -1,5 +1,5 @@
|
||||
from aiogram import types, Router
|
||||
import aiosqlite
|
||||
from aiogram import Router, types
|
||||
|
||||
router = Router()
|
||||
|
||||
|
||||
+8
-7
@@ -1,12 +1,13 @@
|
||||
import asyncpg
|
||||
from aiogram import types, Router
|
||||
from bot import bot
|
||||
from datetime import datetime, timedelta
|
||||
from database import get_balance, update_balance
|
||||
from client import extend_client_key
|
||||
from config import ADMIN_USERNAME, DATABASE_URL, ADMIN_PASSWORD
|
||||
|
||||
import asyncpg
|
||||
from aiogram import Router, types
|
||||
|
||||
from auth import login_with_credentials
|
||||
from client import extend_client_key, delete_client
|
||||
from bot import bot
|
||||
from client import delete_client, extend_client_key
|
||||
from config import ADMIN_PASSWORD, ADMIN_USERNAME, DATABASE_URL
|
||||
from database import get_balance, update_balance
|
||||
|
||||
router = Router()
|
||||
|
||||
|
||||
+6
-5
@@ -1,12 +1,13 @@
|
||||
from aiogram import types, Router
|
||||
from aiogram.types import InlineKeyboardButton, InlineKeyboardMarkup
|
||||
import asyncpg
|
||||
from aiogram import Router, types
|
||||
from aiogram.fsm.context import FSMContext
|
||||
from aiogram.fsm.state import State, StatesGroup
|
||||
from config import ADMIN_ID, DATABASE_URL
|
||||
from database import get_balance, update_balance, get_key_count
|
||||
from aiogram.types import InlineKeyboardButton, InlineKeyboardMarkup
|
||||
|
||||
from bot import bot
|
||||
from config import ADMIN_ID, DATABASE_URL
|
||||
from database import get_balance, get_key_count, update_balance
|
||||
from handlers.profile import process_callback_view_profile
|
||||
import asyncpg
|
||||
|
||||
router = Router()
|
||||
|
||||
|
||||
+23
-14
@@ -1,9 +1,12 @@
|
||||
from aiogram import types, Router
|
||||
from aiogram.types import InlineKeyboardButton, InlineKeyboardMarkup
|
||||
from datetime import datetime
|
||||
|
||||
from aiogram import Router, types
|
||||
from aiogram.fsm.context import FSMContext
|
||||
from aiogram.fsm.state import State, StatesGroup
|
||||
from datetime import datetime
|
||||
from aiogram.types import InlineKeyboardButton, InlineKeyboardMarkup
|
||||
|
||||
from database import get_balance, get_key_count
|
||||
from bot import bot # Импортируем объект bot
|
||||
|
||||
router = Router()
|
||||
|
||||
@@ -13,6 +16,7 @@ class ReplenishBalanceState(StatesGroup):
|
||||
|
||||
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 # Получаем имя пользователя
|
||||
|
||||
try:
|
||||
# Получаем количество ключей
|
||||
@@ -24,38 +28,43 @@ async def process_callback_view_profile(callback_query: types.CallbackQuery, sta
|
||||
balance = 0 # По умолчанию 0, если баланс неизвестен
|
||||
|
||||
profile_message = (
|
||||
f"<b>Профиль пользователя</b>\n\n"
|
||||
f"<b>Профиль: {username}</b>\n\n"
|
||||
f"🔹 <b>ID:</b> {tg_id}\n"
|
||||
f"🔹 <b>Количество ключей:</b> {key_count}\n"
|
||||
f"🔹 <b>Баланс:</b> {balance} RUB\n"
|
||||
f"🔹 <b>Дата регистрации:</b> {datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S')}\n"
|
||||
f"🔹 <b>Количество ключей:</b> {key_count}\n"
|
||||
)
|
||||
|
||||
# Кнопки для действий в профиле
|
||||
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_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') # Добавляем кнопку "Назад"
|
||||
|
||||
keyboard = InlineKeyboardMarkup(inline_keyboard=[
|
||||
[button_create_key], # Добавляем кнопку "Создать ключ"
|
||||
[button_create_key],
|
||||
[button_view_keys],
|
||||
[button_replenish_balance],
|
||||
[button_back] # Добавляем кнопку "Назад" в клавиатуру
|
||||
[button_back]
|
||||
])
|
||||
|
||||
except Exception as e:
|
||||
profile_message = f"❗️ Ошибка при получении данных профиля: {e}"
|
||||
keyboard = None
|
||||
|
||||
# Редактируем существующее сообщение, а не отправляем новое
|
||||
await callback_query.message.edit_text(
|
||||
# Удаляем текущее сообщение
|
||||
await callback_query.message.delete()
|
||||
|
||||
# Отправляем новое сообщение с профилем через bot
|
||||
await bot.send_message(
|
||||
chat_id=tg_id, # ID чата, куда отправляем сообщение
|
||||
text=profile_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)
|
||||
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.7 KiB |
+58
-74
@@ -1,47 +1,66 @@
|
||||
from aiogram import Router, types
|
||||
from aiogram.filters import Command
|
||||
from aiogram.types import InlineKeyboardButton, InlineKeyboardMarkup, CallbackQuery, Message, ReplyKeyboardMarkup, KeyboardButton
|
||||
from aiogram.fsm.context import FSMContext
|
||||
from aiogram.fsm.state import State, StatesGroup
|
||||
from aiogram.types import (CallbackQuery, InlineKeyboardButton,
|
||||
InlineKeyboardMarkup, Message)
|
||||
from aiogram.types import BufferedInputFile
|
||||
import os
|
||||
|
||||
from bot import bot
|
||||
from config import ADMIN_ID, CHANNEL_URL
|
||||
from bot import bot # Убедитесь, что bot и dp импортируются из правильного места
|
||||
|
||||
router = Router()
|
||||
|
||||
class FeedbackState(StatesGroup):
|
||||
waiting_for_feedback = State()
|
||||
|
||||
async def start_command(message: types.Message):
|
||||
async def send_welcome_message(chat_id: int):
|
||||
# Новый текст приветствия
|
||||
welcome_text = (
|
||||
"*Добро пожаловать в наш сервис!*\n\n"
|
||||
"Вы можете воспользоваться следующими функциями:\n\n"
|
||||
"🔑 *Создать ключ для подключения VPN* - Получите уникальный ключ для доступа к VPN.\n"
|
||||
"📅 *Узнать дату окончания ключа* - Проверьте, когда истекает срок действия вашего ключа.\n"
|
||||
"👤 *Просмотреть ваш профиль* - Получите информацию о вашем аккаунте и балансе.\n\n"
|
||||
"Нажмите на соответствующую кнопку ниже, чтобы начать!"
|
||||
"*SoloNet -- ваш провайдер в бесцензурный интернет!*\n\n"
|
||||
"Получите высокую скорость и самый безопасный протокол VPN, "
|
||||
"который работает даже в Китае."
|
||||
)
|
||||
|
||||
button_view_profile = InlineKeyboardButton(text='👤 Мой профиль', callback_data='view_profile')
|
||||
button_about_vpn = InlineKeyboardButton(text='🔒 О VPN', callback_data='about_vpn')
|
||||
button_feedback = InlineKeyboardButton(text='📝 Обратная связь', callback_data='feedback')
|
||||
button_channel = InlineKeyboardButton(text='📢 Наш канал', url=CHANNEL_URL)
|
||||
# Путь к изображению
|
||||
image_path = os.path.join(os.path.dirname(__file__), 'solo_pic.png')
|
||||
|
||||
# Проверка существования файла
|
||||
if not os.path.isfile(image_path):
|
||||
await bot.send_message(chat_id, "Файл изображения не найден.")
|
||||
return
|
||||
|
||||
# Создаем клавиатуру
|
||||
inline_keyboard = InlineKeyboardMarkup(inline_keyboard=[
|
||||
[button_view_profile],
|
||||
[button_about_vpn],
|
||||
[button_feedback],
|
||||
[button_channel]
|
||||
[InlineKeyboardButton(text='👤 Мой профиль', callback_data='view_profile')],
|
||||
[InlineKeyboardButton(text='🔒 О VPN', callback_data='about_vpn')],
|
||||
[InlineKeyboardButton(text='📝 Обратная связь', callback_data='feedback')],
|
||||
[InlineKeyboardButton(text='📢 Наш канал', url=CHANNEL_URL)]
|
||||
])
|
||||
|
||||
await message.bot.send_message(
|
||||
chat_id=message.chat.id,
|
||||
text=welcome_text,
|
||||
parse_mode='Markdown',
|
||||
reply_markup=inline_keyboard
|
||||
)
|
||||
# Используем BufferedInputFile для отправки изображения
|
||||
with open(image_path, 'rb') as image_from_buffer:
|
||||
await bot.send_photo(
|
||||
chat_id,
|
||||
BufferedInputFile(
|
||||
image_from_buffer.read(),
|
||||
filename="solo_pic.png"
|
||||
),
|
||||
caption=welcome_text,
|
||||
parse_mode='Markdown',
|
||||
reply_markup=inline_keyboard
|
||||
)
|
||||
|
||||
@router.message(Command('start'))
|
||||
async def start_command(message: Message):
|
||||
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"
|
||||
"Мы используем VLESS для обеспечения безопасного и надежного подключения к интернету. "
|
||||
@@ -49,69 +68,39 @@ async def handle_about_vpn(callback_query: CallbackQuery):
|
||||
"Этот ключ необходим для использования нашего VPN-сервиса."
|
||||
)
|
||||
|
||||
# Кнопка "Назад"
|
||||
button_back = InlineKeyboardButton(text='⬅️ Назад', callback_data='back_to_menu')
|
||||
inline_keyboard_back = InlineKeyboardMarkup(inline_keyboard=[[button_back]])
|
||||
|
||||
# Обновлённая клавиатура с кнопкой "Назад"
|
||||
inline_keyboard_back = InlineKeyboardMarkup(inline_keyboard=[
|
||||
[button_back]
|
||||
])
|
||||
|
||||
await callback_query.message.edit_text(
|
||||
await callback_query.message.answer(
|
||||
info_message,
|
||||
parse_mode='Markdown',
|
||||
reply_markup=inline_keyboard_back # Добавление клавиатуры с кнопкой "Назад"
|
||||
reply_markup=inline_keyboard_back
|
||||
)
|
||||
await callback_query.answer()
|
||||
|
||||
@router.callback_query(lambda c: c.data == 'back_to_menu')
|
||||
async def handle_back_to_menu(callback_query: CallbackQuery):
|
||||
welcome_text = (
|
||||
"*Добро пожаловать в наш сервис!*\n\n"
|
||||
"Вы можете воспользоваться следующими функциями:\n\n"
|
||||
"🔑 *Создать ключ для подключения VPN* - Получите уникальный ключ для доступа к VPN.\n"
|
||||
"📅 *Узнать дату окончания ключа* - Проверьте, когда истекает срок действия вашего ключа.\n"
|
||||
"👤 *Просмотреть ваш профиль* - Получите информацию о вашем аккаунте и балансе.\n\n"
|
||||
"Нажмите на соответствующую кнопку ниже, чтобы начать!"
|
||||
)
|
||||
|
||||
button_view_profile = InlineKeyboardButton(text='👤 Мой профиль', callback_data='view_profile')
|
||||
button_about_vpn = InlineKeyboardButton(text='🔒 О VPN', callback_data='about_vpn')
|
||||
button_feedback = InlineKeyboardButton(text='📝 Обратная связь', callback_data='feedback')
|
||||
button_channel = InlineKeyboardButton(text='📢 Наш канал', url=CHANNEL_URL)
|
||||
|
||||
inline_keyboard = InlineKeyboardMarkup(inline_keyboard=[
|
||||
[button_view_profile],
|
||||
[button_about_vpn],
|
||||
[button_feedback],
|
||||
[button_channel]
|
||||
])
|
||||
|
||||
# Редактирование сообщения на главное меню
|
||||
await callback_query.message.edit_text(
|
||||
welcome_text,
|
||||
parse_mode='Markdown',
|
||||
reply_markup=inline_keyboard
|
||||
)
|
||||
# Удаляем текущее сообщение
|
||||
await callback_query.message.delete()
|
||||
|
||||
# Отправляем приветственное сообщение
|
||||
await send_welcome_message(callback_query.from_user.id)
|
||||
await callback_query.answer()
|
||||
|
||||
@router.callback_query(lambda c: c.data == 'feedback')
|
||||
async def handle_feedback(callback_query: CallbackQuery, state: FSMContext):
|
||||
# Удаляем сообщение главного меню
|
||||
await callback_query.message.delete()
|
||||
|
||||
feedback_text = "Напишите нам, если у вас возникли трудности с подключением, есть отзыв или предложение. @pocomacho"
|
||||
|
||||
# Кнопка "Назад"
|
||||
button_back = InlineKeyboardButton(text='⬅️ Назад', callback_data='back_to_menu')
|
||||
inline_keyboard_back = InlineKeyboardMarkup(inline_keyboard=[[button_back]])
|
||||
|
||||
# Обновлённая клавиатура с кнопкой "Назад"
|
||||
inline_keyboard_back = InlineKeyboardMarkup(inline_keyboard=[
|
||||
[button_back]
|
||||
])
|
||||
|
||||
# Редактирование сообщения с кнопкой "Назад"
|
||||
await callback_query.message.edit_text(
|
||||
await callback_query.message.answer(
|
||||
feedback_text,
|
||||
parse_mode='Markdown',
|
||||
reply_markup=inline_keyboard_back # Клавиатура с кнопкой "Назад"
|
||||
reply_markup=inline_keyboard_back
|
||||
)
|
||||
|
||||
await state.set_state(FeedbackState.waiting_for_feedback)
|
||||
@@ -127,17 +116,12 @@ async def receive_feedback(message: types.Message, state: FSMContext):
|
||||
f"Обратная связь от пользователя {user_id}:\n\n"
|
||||
f"{message.text}"
|
||||
)
|
||||
|
||||
|
||||
try:
|
||||
await bot.send_message(ADMIN_ID, feedback_message)
|
||||
await message.answer("Спасибо за ваше сообщение! Мы свяжемся с вами, если это будет необходимо.")
|
||||
except Exception as e:
|
||||
await message.answer("Произошла ошибка при отправке вашего сообщения.")
|
||||
print(f"Ошибка при отправке обратной связи: {e}") # Логирование ошибок
|
||||
|
||||
await state.clear()
|
||||
|
||||
# Пример обработки команды старт
|
||||
@router.message(Command('start'))
|
||||
async def cmd_start(message: Message):
|
||||
await start_command(message)
|
||||
await state.clear()
|
||||
|
||||
+53
-38
@@ -1,21 +1,24 @@
|
||||
import asyncio
|
||||
import re
|
||||
import uuid
|
||||
import asyncio
|
||||
from datetime import datetime, timedelta
|
||||
from aiogram import Router, types, F
|
||||
from aiogram.types import InlineKeyboardButton, InlineKeyboardMarkup, CallbackQuery, Message
|
||||
from aiogram.fsm.context import FSMContext
|
||||
from aiogram.fsm.state import State, StatesGroup
|
||||
|
||||
from auth import login_with_credentials, link
|
||||
from client import add_client
|
||||
from config import API_TOKEN, ADMIN_PASSWORD, ADMIN_USERNAME, ADMIN_CHAT_ID, DATABASE_URL
|
||||
from database import add_connection, has_active_key, get_balance, store_key, update_balance
|
||||
from bot import dp, bot
|
||||
from handlers.profile import process_callback_view_profile
|
||||
from handlers.start import start_command
|
||||
|
||||
import asyncpg
|
||||
from aiogram import F, Router, types
|
||||
from aiogram.fsm.context import FSMContext
|
||||
from aiogram.fsm.state import State, StatesGroup
|
||||
from aiogram.types import (CallbackQuery, InlineKeyboardButton,
|
||||
InlineKeyboardMarkup, Message)
|
||||
|
||||
from auth import link, login_with_credentials
|
||||
from bot import bot, dp
|
||||
from client import add_client
|
||||
from config import (ADMIN_CHAT_ID, ADMIN_PASSWORD, ADMIN_USERNAME, API_TOKEN,
|
||||
DATABASE_URL)
|
||||
from database import (add_connection, get_balance, has_active_key, store_key,
|
||||
update_balance)
|
||||
from handlers.profile import process_callback_view_profile
|
||||
from handlers.start import start_command
|
||||
|
||||
router = Router()
|
||||
|
||||
@@ -42,7 +45,7 @@ async def process_callback_create_key(callback_query: CallbackQuery, state: FSMC
|
||||
|
||||
if trial_status == 1:
|
||||
await callback_query.message.edit_text(
|
||||
"У вас уже был пробный ключ. Вы можете создать новый за 100 рублей. "
|
||||
"У вас уже был пробный ключ. Новый стоит 100 рублей и сразу на месяц. \n\n"
|
||||
"Хотите продолжить?",
|
||||
reply_markup=InlineKeyboardMarkup(inline_keyboard=[
|
||||
[InlineKeyboardButton(text='Да, создать новый ключ', callback_data='confirm_create_new_key')],
|
||||
@@ -65,11 +68,15 @@ async def confirm_create_new_key(callback_query: CallbackQuery, state: FSMContex
|
||||
if balance < 100:
|
||||
replenish_button = InlineKeyboardButton(text='Перейти в профиль', callback_data='view_profile')
|
||||
keyboard = InlineKeyboardMarkup(inline_keyboard=[[replenish_button]])
|
||||
await callback_query.message.edit_text("Недостаточно средств на балансе для создания нового ключа.", reply_markup=keyboard)
|
||||
await callback_query.message.edit_text(
|
||||
"❗️ Недостаточно средств на балансе для создания нового ключа. "
|
||||
"Пожалуйста, пополните баланс.",
|
||||
reply_markup=keyboard
|
||||
)
|
||||
await state.clear()
|
||||
return
|
||||
|
||||
await callback_query.message.edit_text("Пожалуйста, выберите имя для вашего нового ключа:")
|
||||
await callback_query.message.edit_text("🔑 Пожалуйста, выберите имя для вашего нового ключа:")
|
||||
await state.set_state(Form.waiting_for_key_name)
|
||||
await state.update_data(creating_new_key=True)
|
||||
|
||||
@@ -109,8 +116,8 @@ async def handle_key_name_input(message: Message, state: FSMContext):
|
||||
key_name = sanitize_key_name(message.text)
|
||||
|
||||
if not key_name:
|
||||
await message.bot.send_message(tg_id, "Назовите профиль на английском языке.")
|
||||
return # Прерываем выполнение функции
|
||||
await message.bot.send_message(tg_id, "📝 Пожалуйста, назовите профиль на английском языке.")
|
||||
return
|
||||
|
||||
data = await state.get_data()
|
||||
creating_new_key = data.get('creating_new_key', False)
|
||||
@@ -119,28 +126,32 @@ async def handle_key_name_input(message: Message, state: FSMContext):
|
||||
client_id = str(uuid.uuid4())
|
||||
email = key_name.lower()
|
||||
current_time = datetime.utcnow()
|
||||
expiry_time = int((current_time + timedelta(days=1)).timestamp() * 1000)
|
||||
expiry_time = None
|
||||
|
||||
if creating_new_key:
|
||||
# Проверяем, занято ли имя ключа
|
||||
conn = await asyncpg.connect(DATABASE_URL)
|
||||
try:
|
||||
existing_key = await conn.fetchrow('SELECT * FROM keys WHERE email = $1', email)
|
||||
if existing_key:
|
||||
await message.bot.send_message(tg_id, "Это имя уже занято. Пожалуйста, выберите другое имя.")
|
||||
return # Прерываем выполнение функции
|
||||
finally:
|
||||
await conn.close()
|
||||
# Получаем статус пробного ключа из базы данных
|
||||
conn = await asyncpg.connect(DATABASE_URL)
|
||||
try:
|
||||
existing_connection = await conn.fetchrow('SELECT trial FROM connections WHERE tg_id = $1', tg_id)
|
||||
finally:
|
||||
await conn.close()
|
||||
|
||||
trial_status = existing_connection['trial'] if existing_connection else 0
|
||||
|
||||
if trial_status == 0:
|
||||
# Создаем пробный ключ на 1 день
|
||||
expiry_time = int((current_time + timedelta(days=1)).timestamp() * 1000)
|
||||
else:
|
||||
# Проверяем баланс перед созданием нового ключа
|
||||
balance = await get_balance(tg_id)
|
||||
if balance < 100:
|
||||
replenish_button = InlineKeyboardButton(text='Перейти в профиль', callback_data='view_profile')
|
||||
keyboard = InlineKeyboardMarkup(inline_keyboard=[[replenish_button]])
|
||||
await message.bot.send_message(tg_id, "Недостаточно средств на балансе для создания нового ключа.", reply_markup=keyboard)
|
||||
await message.bot.send_message(tg_id, "❗️ Недостаточно средств на балансе для создания нового ключа.", reply_markup=keyboard)
|
||||
await state.clear()
|
||||
return
|
||||
|
||||
|
||||
await update_balance(tg_id, -100)
|
||||
expiry_time = int((current_time + timedelta(days=30)).timestamp() * 1000)
|
||||
|
||||
try:
|
||||
add_client(session, client_id, email, tg_id, limit_ip=1, total_gb=0, expiry_time=expiry_time, enable=True, flow="xtls-rprx-vision")
|
||||
@@ -162,32 +173,36 @@ async def handle_key_name_input(message: Message, state: FSMContext):
|
||||
await store_key(tg_id, client_id, email, expiry_time, connection_link)
|
||||
|
||||
keyboard = InlineKeyboardMarkup(inline_keyboard=[
|
||||
[InlineKeyboardButton(text='Инструкции по использованию', callback_data='instructions')],
|
||||
[InlineKeyboardButton(text='Перейти в профиль', callback_data='view_profile')]
|
||||
[InlineKeyboardButton(text='📖 Инструкции по использованию', callback_data='instructions')],
|
||||
[InlineKeyboardButton(text='🔙 Перейти в профиль', callback_data='view_profile')]
|
||||
])
|
||||
|
||||
key_message = f"Ключ создан:\n<pre>{connection_link}</pre>"
|
||||
key_message = (
|
||||
"✅ Ключ успешно создан:\n"
|
||||
f"<pre>{connection_link}</pre>"
|
||||
)
|
||||
await message.bot.send_message(tg_id, key_message, parse_mode="HTML", reply_markup=keyboard)
|
||||
except Exception as e:
|
||||
await message.bot.send_message(tg_id, f"Ошибка при создании ключа: {e}")
|
||||
await message.bot.send_message(tg_id, f"❌ Ошибка при создании ключа: {e}")
|
||||
|
||||
await state.clear()
|
||||
|
||||
|
||||
|
||||
@dp.callback_query(F.data == 'instructions')
|
||||
async def handle_instructions(callback_query: CallbackQuery):
|
||||
instructions_message = (
|
||||
"*Инструкции по использованию вашего ключа:*\n\n"
|
||||
"*📋 Инструкции по использованию вашего ключа:*\n\n"
|
||||
"1. Скачайте приложение для вашего устройства:\n"
|
||||
" - Для Android: [V2Ray](https://play.google.com/store/apps/details?id=com.v2ray.ang&hl=ru&pli=1)\n"
|
||||
" - Для iPhone: [Streisand](https://apps.apple.com/ru/app/streisand/id6450534064)\n\n"
|
||||
"2. Скопируйте предоставленный ключ, который вы получили ранее.\n"
|
||||
"3. Откройте приложение и нажмите на плюсик сверху справа.\n"
|
||||
"4. Выберите 'Вставить из буфера обмена' для добавления ключа.\n\n"
|
||||
"Если у вас возникнут вопросы, не стесняйтесь обращаться в поддержку."
|
||||
"💬 Если у вас возникнут вопросы, не стесняйтесь обращаться в поддержку."
|
||||
)
|
||||
|
||||
back_button = InlineKeyboardButton(text='Назад', callback_data='back_to_main')
|
||||
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)
|
||||
|
||||
Reference in New Issue
Block a user