api 0.2.0/ minor fixes
This commit is contained in:
+1
-1
@@ -3,7 +3,7 @@ from api.routes import users, keys, coupons, servers, tariffs, gifts, referrals,
|
||||
|
||||
app = FastAPI(
|
||||
title="SoloBot API (preAlpha)",
|
||||
version="0.1.2",
|
||||
version="0.2.0",
|
||||
docs_url="/api/docs",
|
||||
redoc_url="/api/redoc",
|
||||
openapi_url="/api/openapi.json"
|
||||
|
||||
+32
-3
@@ -1,16 +1,16 @@
|
||||
from fastapi import Depends, HTTPException, Path, Body
|
||||
from fastapi import Depends, HTTPException, Path, Body, status
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from sqlalchemy import select
|
||||
from datetime import datetime
|
||||
|
||||
from database.models import Key, Admin, Tariff
|
||||
from api.schemas.keys import KeyBase, KeyResponse, KeyUpdate
|
||||
from api.schemas.keys import KeyBase, KeyResponse, KeyUpdate, KeyCreateRequest
|
||||
from api.routes.base_crud import generate_crud_router
|
||||
from api.depends import get_session, verify_admin_token
|
||||
from handlers.keys.key_utils import delete_key_from_cluster
|
||||
from logger import logger
|
||||
|
||||
from handlers.keys.key_utils import renew_key_in_cluster
|
||||
from handlers.keys.key_utils import renew_key_in_cluster, create_key_on_cluster
|
||||
|
||||
router = generate_crud_router(
|
||||
model=Key,
|
||||
@@ -119,3 +119,32 @@ async def edit_key_by_email(
|
||||
except Exception as e:
|
||||
logger.error(f"[API] Ошибка при обновлении ключа: {e}")
|
||||
raise HTTPException(status_code=500, detail="Ошибка при обновлении ключа")
|
||||
|
||||
|
||||
@router.post("/create", response_model=dict, status_code=status.HTTP_201_CREATED)
|
||||
async def create_key_api(
|
||||
payload: KeyCreateRequest = Body(...),
|
||||
session: AsyncSession = Depends(get_session),
|
||||
admin: Admin = Depends(verify_admin_token),
|
||||
):
|
||||
logger.info(f"[API] Запрос на создание ключа: {payload.dict()}")
|
||||
|
||||
try:
|
||||
await create_key_on_cluster(
|
||||
cluster_id=payload.cluster_id,
|
||||
tg_id=payload.tg_id,
|
||||
client_id=payload.client_id,
|
||||
email=payload.email or f"{payload.tg_id}_key",
|
||||
expiry_timestamp=payload.expiry_timestamp,
|
||||
plan=payload.tariff_id,
|
||||
session=session,
|
||||
remnawave_link=payload.remnawave_link,
|
||||
hwid_limit=payload.hwid_limit,
|
||||
traffic_limit_bytes=payload.traffic_limit_bytes,
|
||||
is_trial=payload.is_trial or False,
|
||||
)
|
||||
return {"message": "Ключ успешно создан"}
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"[API] Ошибка при создании ключа: {e}")
|
||||
raise HTTPException(status_code=500, detail="Ошибка при создании ключа")
|
||||
@@ -13,10 +13,12 @@ class CouponBase(BaseModel):
|
||||
|
||||
@model_validator(mode="after")
|
||||
def check_exactly_one_of_amount_or_days(self) -> "CouponBase":
|
||||
has_amount = getattr(self, "amount", None) is not None
|
||||
has_days = getattr(self, "days", None) is not None
|
||||
has_amount = self.amount not in (None, 0)
|
||||
has_days = self.days is not None
|
||||
|
||||
if has_amount == has_days:
|
||||
if has_amount and has_days:
|
||||
raise ValueError("Coupon must have exactly one of: 'amount' or 'days'")
|
||||
if not has_amount and not has_days:
|
||||
raise ValueError("Coupon must have exactly one of: 'amount' or 'days'")
|
||||
return self
|
||||
|
||||
|
||||
+13
-7
@@ -1,4 +1,4 @@
|
||||
from pydantic import BaseModel
|
||||
from pydantic import BaseModel, Field
|
||||
from typing import Optional
|
||||
|
||||
|
||||
@@ -63,9 +63,15 @@ class KeyUpdate(BaseModel):
|
||||
|
||||
|
||||
class KeyCreateRequest(BaseModel):
|
||||
tg_id: int
|
||||
cluster_id: str
|
||||
tariff_id: int
|
||||
email: Optional[str] = None
|
||||
alias: Optional[str] = None
|
||||
remnawave_link: Optional[str] = None
|
||||
tg_id: int = Field(..., description="Telegram ID пользователя")
|
||||
cluster_id: str = Field(..., description="Имя кластера или сервера")
|
||||
tariff_id: int = Field(..., description="ID тарифа из базы данных")
|
||||
client_id: str = Field(..., description="UUID клиента (уникальный)")
|
||||
expiry_timestamp: int = Field(..., description="Срок окончания в миллисекундах")
|
||||
|
||||
email: Optional[str] = Field(None, description="Условное имя подписки")
|
||||
alias: Optional[str] = Field(None, description="пользовательское имя")
|
||||
remnawave_link: Optional[str] = Field(None, description="Ссылка на подписку Remnawave")
|
||||
hwid_limit: Optional[int] = Field(None, description="Ограничение по HWID")
|
||||
traffic_limit_bytes: Optional[int] = Field(None, description="Ограничение трафика в байтах")
|
||||
is_trial: Optional[bool] = Field(False, description="Флаг триального ключа")
|
||||
Reference in New Issue
Block a user