Начальный этап бота с выдачей ключей

This commit is contained in:
Vlad
2024-09-13 02:13:24 +03:00
commit c9f3aa4a20
8 changed files with 377 additions and 0 deletions
+4
View File
@@ -0,0 +1,4 @@
/venv
/__pycache__
/vpn_users.db
/config.py
View File
+65
View File
@@ -0,0 +1,65 @@
import requests
from config import GET_INBOUNDS_URL, AUTH_URL, DOMEN
import json
def login_with_credentials(username, password):
auth_url = AUTH_URL
data = {
"username": username,
"password": password
}
response = requests.post(auth_url, json=data)
if response.status_code == 200:
session = requests.Session()
session.cookies.update(response.cookies)
return session
else:
raise Exception(f"Ошибка авторизации: {response.status_code}, {response.text}")
def get_clients(session):
response = session.get(GET_INBOUNDS_URL)
if response.status_code == 200:
return response.json() # Возвращает данные по инбаундам и клиентам
else:
raise Exception(f"Ошибка при получении клиентов: {response.status_code}, {response.text}")
def link(session, user_id: str):
"""
Получение ссылки для подключения по ID пользователя.
:param session: requests.Session - авторизованная сессия
:param user_id: str - идентификатор пользователя (email или другой параметр)
:return: str - ссылка для подключения
"""
client_id = ''
# Получаем список клиентов через API
response = get_clients(session)
if 'obj' not in response or len(response['obj']) == 0:
raise Exception("Не удалось получить данные клиентов.")
# Извлекаем данные клиента
inbounds = response['obj'][0] # Убедитесь, что это правильный индекс
settings = json.loads(inbounds['settings'])
# Ищем клиента по user_id
for client in settings["clients"]:
if client['email'] == user_id:
client_id = client["id"]
break
if not client_id:
raise Exception(f"Клиент с идентификатором {user_id} не найден.")
# Получаем streamSettings и генерируем ссылку
stream_settings = json.loads(inbounds['streamSettings'])
tcp = stream_settings.get('network', 'tcp') # Предположим, по умолчанию 'tcp'
reality = stream_settings.get('security', 'reality') # Предположим, по умолчанию 'reality'
flow = stream_settings.get('flow', 'xtls-rprx-vision') # Предположим, по умолчанию 'xtls-rprx-vision'
email = user_id
# Создание ссылки для подключения VLESS
val = f"vless://{client_id}@{DOMEN}?type={tcp}&security={reality}&fp=chrome&pbk=ZIMoEnEd8-qMJkReVU5JxbiEj8CCSrvpm_ckvJ-46TE&sni=yahoo.com&sid=0fb4b595&spx=%2F&flow={flow}#VPN_F-{email}"
return val
+63
View File
@@ -0,0 +1,63 @@
from aiogram import Bot, Dispatcher, Router, F, types
from aiogram.filters import Command
from aiogram.types import InlineKeyboardButton, InlineKeyboardMarkup, Message
from aiogram.fsm.storage.memory import MemoryStorage
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, generate_client_id
from datetime import datetime, timedelta
from config import API_TOKEN, ADMIN_PASSWORD, ADMIN_USERNAME
class Form(StatesGroup):
waiting_for_key_name = State()
bot = Bot(token=API_TOKEN)
storage = MemoryStorage()
dp = Dispatcher(bot=bot, storage=storage)
router = Router()
@dp.message(Command("start"))
async def start_command(message: Message):
button_create_key = InlineKeyboardButton(text='Создать ключ', callback_data='create_key')
keyboard = InlineKeyboardMarkup(inline_keyboard=[[button_create_key]])
await message.reply("Выберите действие:", reply_markup=keyboard)
@dp.callback_query(F.data == 'create_key')
async def process_callback_create_key(callback_query: types.CallbackQuery, state: FSMContext):
await callback_query.message.reply("Введите имя вашего профиля VPN:")
await state.set_state(Form.waiting_for_key_name)
await callback_query.answer()
@dp.message()
async def handle_text(message: types.Message, state: FSMContext):
current_state = await state.get_state()
if current_state == Form.waiting_for_key_name.state:
try:
session = login_with_credentials(ADMIN_USERNAME, ADMIN_PASSWORD)
tg_id = message.from_user.id
email = message.text
client_id = generate_client_id()
email = message.text
limit_ip = 1
total_gb = 0
current_time = datetime.utcnow()
expiry_time = int((current_time + timedelta(days=30)).timestamp() * 1000)
enable = True
flow = "xtls-rprx-vision"
add_client(session, client_id, email, tg_id, limit_ip, total_gb, expiry_time, enable, flow)
connection_link = link(session, email)
await message.reply(f"Ключ создан:\n<pre>{connection_link}</pre>", parse_mode="HTML")
await state.clear()
except Exception as e:
await message.reply(f"Произошла ошибка: {e}")
+140
View File
@@ -0,0 +1,140 @@
from aiogram import Bot, Dispatcher, Router, F, types
from aiogram.filters import Command
from aiogram.types import Message
from aiogram.filters import Command
import requests
from database import add_user, get_user, update_subscription
from aiogram.types import InlineKeyboardButton, InlineKeyboardMarkup
from aiogram.fsm.storage.memory import MemoryStorage
from aiogram.fsm.context import FSMContext
from aiogram.fsm.state import State, StatesGroup
import asyncio
import json
from datetime import datetime, timedelta
import uuid
API_TOKEN = '7436953421:AAH9iUg86cLC8oxO_XZeqYEfSBhDGBodV5o'
API_URL = "https://vpn.pocomacho.ru:34268/solonet"
ADMIN_USERNAME = "paneladmin"
ADMIN_PASSWORD = "L7CMDASN9x7g"
ADD_CLIENT_URL = f"{API_URL}/panel/api/inbounds/addClient"
bot = Bot(token=API_TOKEN)
storage = MemoryStorage()
dp = Dispatcher(storage=storage)
router = Router()
class Form(StatesGroup):
waiting_for_key_name = State()
def login_with_credentials(username, password):
auth_url = "https://vpn.pocomacho.ru:34268/solonet/login/"
data = {
"username": ADMIN_USERNAME,
"password": ADMIN_PASSWORD
}
response = requests.post(auth_url, json=data)
if response.status_code == 200:
# Если API возвращает токен, используйте его в заголовке
# return {"Authorization": f"Bearer {response.json().get('token')}"}
# Если API использует сессии (например, с cookies)
session = requests.Session()
session.cookies.update(response.cookies)
return session
else:
raise Exception(f"Ошибка авторизации: {response.status_code}, {response.text}")
def add_client(session, client_id, email, tg_id, limit_ip, total_gb, expiry_time, enable, flow):
settings = {
"clients": [
{
"id": client_id,
"alterId": 0,
"email": email,
"limitIp": limit_ip,
"totalGB": total_gb,
"expiryTime": expiry_time,
"enable": enable,
"tgId": tg_id,
"subId": "",
"flow": flow
}
]
}
data = {
"id": 1, # Можно изменить в зависимости от ваших требований
"settings": json.dumps(settings)
}
headers = {
"Accept": "application/json"
}
response = session.post(ADD_CLIENT_URL, headers=headers, json=data)
if response.status_code == 200:
return response.json()
else:
raise Exception(f"Ошибка при добавлении клиента: {response.status_code}, {response.text}")
# Обработчик команды /start
@dp.message(Command("start"))
async def start_command(message: Message):
# Создаем кнопки
button_create_key = InlineKeyboardButton(text='Создать ключ', callback_data='create_key')
keyboard = InlineKeyboardMarkup(inline_keyboard=[[button_create_key]])
await message.reply("Выберите действие:", reply_markup=keyboard)
# Обработчик нажатия кнопки
@dp.callback_query(F.data == 'create_key')
async def process_callback_create_key(callback_query: types.CallbackQuery, state: FSMContext):
await callback_query.message.reply("Введите имя для нового ключа:")
await state.set_state(Form.waiting_for_key_name) # Устанавливаем состояние
await callback_query.answer()
# Обработчик текстовых сообщений
@dp.message()
async def handle_text(message: types.Message, state: FSMContext):
# Получаем текущее состояние
current_state = await state.get_state()
if current_state == Form.waiting_for_key_name.state:
try:
# Авторизация
session = login_with_credentials(ADMIN_USERNAME, ADMIN_PASSWORD)
# Параметры клиента
client_id = str(uuid.uuid4()) # Пример UUID
email = message.text
limit_ip = 1
tg_id = message.from_user.id
total_gb = 0 # В байтах
current_time = datetime.utcnow()
expiry_time = int((current_time + timedelta(days=30)).timestamp() * 1000) # Временная метка в миллисекундах
enable = True
flow = "xtls-rprx-vision"
# Добавление клиента
result = add_client(session, client_id, email, tg_id, limit_ip, total_gb, expiry_time, enable, flow)
await message.reply(f"Ключ создан: {result}")
# Сброс состояния
await state.clear()
except Exception as e:
await message.reply(f"Произошла ошибка: {e}")
# Запуск бота
async def main():
dp.include_router(router) # Подключение роутера
await dp.start_polling(bot) # Запуск поллинга
if __name__ == '__main__':
asyncio.run(main())
+41
View File
@@ -0,0 +1,41 @@
import json
import uuid
from config import ADD_CLIENT_URL
def add_client(session, client_id, email, tg_id, limit_ip, total_gb, expiry_time, enable, flow):
settings = {
"clients": [
{
"id": client_id,
"alterId": 0,
"email": email,
"limitIp": limit_ip,
"totalGB": total_gb,
"expiryTime": expiry_time,
"enable": enable,
"tgId": tg_id,
"subId": "",
"flow": flow
}
]
}
data = {
"id": 1, # Можно изменить в зависимости от ваших требований
"settings": json.dumps(settings)
}
headers = {
"Accept": "application/json"
}
response = session.post(ADD_CLIENT_URL, headers=headers, json=data)
if response.status_code == 200:
return response.json()
else:
raise Exception(f"Ошибка при добавлении клиента: {response.status_code}, {response.text}")
def generate_client_id():
return str(uuid.uuid4())
+38
View File
@@ -0,0 +1,38 @@
from sqlalchemy import create_engine, Column, Integer, String, DateTime
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
import datetime
DATABASE_URL = 'sqlite:///vpn_users.db'
engine = create_engine(DATABASE_URL)
Session = sessionmaker(bind=engine)
session = Session()
Base = declarative_base()
class VPNUser(Base):
__tablename__ = 'vpn_users'
id = Column(Integer, primary_key=True)
telegram_id = Column(Integer, unique=True)
username = Column(String)
subscription_end = Column(DateTime)
access_key = Column(String)
Base.metadata.create_all(engine)
def add_user(telegram_id, username, access_key):
user = VPNUser(telegram_id=telegram_id, username=username,
subscription_end=datetime.datetime.now() + datetime.timedelta(days=30),
access_key=access_key)
session.add(user)
session.commit()
def get_user(telegram_id):
return session.query(VPNUser).filter(VPNUser.telegram_id == telegram_id).first()
def update_subscription(telegram_id, days):
user = get_user(telegram_id)
if user:
user.subscription_end += datetime.timedelta(days=days)
session.commit()
+26
View File
@@ -0,0 +1,26 @@
aiofiles==23.2.1
aiogram==3.2.0
aiohttp==3.9.5
aiosignal==1.3.1
annotated-types==0.7.0
anyio==4.4.0
attrs==24.2.0
certifi==2024.8.30
charset-normalizer==3.3.2
frozenlist==1.4.1
greenlet==3.1.0
h11==0.14.0
httpcore==1.0.5
httpx==0.27.2
idna==3.8
magic-filter==1.0.12
multidict==6.1.0
py3xui==0.2.3
pydantic==2.5.3
pydantic_core==2.14.6
requests==2.32.3
sniffio==1.3.1
SQLAlchemy==2.0.34
typing_extensions==4.12.2
urllib3==2.2.3
yarl==1.11.1