mirror of
https://github.com/remnawave/python-sdk.git
synced 2026-05-13 12:16:42 +00:00
Aktualizacja do wersji 2.1.8:
- Zmieniono wersję pakietu z 2.1.7.post1 na 2.1.8 w pliku pyproject.toml oraz README.md.
- Przeniesiono endpoint `/sub/{short_uuid}/raw` z `SubscriptionController` do `SubscriptionsController`.
- Rozszerzono modele subskrypcji o dodatkowe informacje o użytkowniku, połączeniach, hasłach i wykorzystaniu ruchu.
- Dodano nowy endpoint `/system/tools/x25519/generate` do generowania pary kluczy X25519.
- Uzupełniono klasyfikatory projektu o nowe tematy w `pyproject.toml`.
Zmiany poprawiają strukturę API, rozszerzają możliwości diagnostyczne oraz wprowadzają nową funkcjonalność kryptograficzną.
This commit is contained in:
parent
c1ac9903dd
commit
c8e13c41af
8 changed files with 102 additions and 23 deletions
|
|
@ -63,7 +63,8 @@ pip install git+https://github.com/remnawave/python-sdk.git@development
|
|||
|
||||
| Contract Version | Remnawave Panel Version |
|
||||
| ---------------- | ----------------------- |
|
||||
| 2.1.7.post1 | >=2.1.7 |
|
||||
| 2.1.8 | >=2.1.8 |
|
||||
| 2.1.7.post1 | ==2.1.7 |
|
||||
| 2.1.4 | >=2.1.4, <2.1.7 |
|
||||
| 2.1.1 | >=2.1.1, <2.1.4 |
|
||||
| 2.0.0 | >=2.0.0,<2.1.0 |
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
[project]
|
||||
name = "remnawave"
|
||||
version = "2.1.7.post1"
|
||||
description = "A Python SDK for interacting with the Remnawave API v2.1.7."
|
||||
version = "2.1.8"
|
||||
description = "A Python SDK for interacting with the Remnawave API v2.1.8."
|
||||
authors = [
|
||||
{name = "Artem",email = "dev@forestsnet.com"}
|
||||
]
|
||||
|
|
@ -28,6 +28,10 @@ classifiers = [
|
|||
"Programming Language :: Python :: Implementation :: CPython",
|
||||
"Programming Language :: Python :: Implementation :: PyPy",
|
||||
"Framework :: AsyncIO",
|
||||
"Topic :: Software Development :: Libraries :: Python Modules",
|
||||
"Topic :: Internet :: WWW/HTTP",
|
||||
"Topic :: Utilities",
|
||||
"Topic :: Rest APIs",
|
||||
]
|
||||
|
||||
[project.urls]
|
||||
|
|
|
|||
|
|
@ -3,11 +3,12 @@ from typing import Annotated
|
|||
from rapid_api_client import Path
|
||||
|
||||
from remnawave.enums import ClientType
|
||||
from remnawave.models import GetSubscriptionInfoResponseDto, GetRawSubscriptionByShortUuidResponseDto
|
||||
from remnawave.models import GetSubscriptionInfoResponseDto
|
||||
from remnawave.rapid import BaseController, get
|
||||
|
||||
|
||||
class SubscriptionController(BaseController):
|
||||
# Public endpoints below
|
||||
@get("/sub/{short_uuid}/info", response_class=GetSubscriptionInfoResponseDto)
|
||||
async def get_subscription_info_by_short_uuid(
|
||||
self,
|
||||
|
|
@ -50,15 +51,5 @@ class SubscriptionController(BaseController):
|
|||
),
|
||||
] = "VGVzdGVy",
|
||||
) -> str:
|
||||
"""None"""
|
||||
...
|
||||
|
||||
# get raw sub by short uuid
|
||||
@get("/sub/{short_uuid}/raw", response_class=GetRawSubscriptionByShortUuidResponseDto)
|
||||
async def get_raw_subscription(
|
||||
self,
|
||||
short_uuid: Annotated[str, Path(description="Short UUID of the user")],
|
||||
withDisabledHosts: Annotated[Annotated[bool, Path(description="Include disabled hosts")], bool] = False,
|
||||
) -> GetRawSubscriptionByShortUuidResponseDto:
|
||||
"""None"""
|
||||
...
|
||||
|
|
@ -3,11 +3,13 @@ from typing import Annotated
|
|||
from rapid_api_client import Path, Query
|
||||
|
||||
from remnawave.enums import ClientType
|
||||
from remnawave.models.subscription import GetRawSubscriptionByShortUuidResponseDto
|
||||
from remnawave.rapid import BaseController, get
|
||||
from remnawave.models import GetAllSubscriptionsResponseDto, GetSubscriptionByUsernameResponseDto, GetSubscriptionByShortUUIDResponseDto, GetSubscriptionByUUIDResponseDto
|
||||
|
||||
|
||||
class SubscriptionsController(BaseController):
|
||||
# Protected endpoints below
|
||||
@get("/subscriptions", response_class=GetAllSubscriptionsResponseDto)
|
||||
async def get_all_subscriptions(
|
||||
self,
|
||||
|
|
@ -42,5 +44,14 @@ class SubscriptionsController(BaseController):
|
|||
self,
|
||||
uuid: Annotated[str, Path(description="UUID of the user")],
|
||||
) -> GetSubscriptionByUUIDResponseDto:
|
||||
"""None"""
|
||||
...
|
||||
|
||||
@get("/subscriptions/by-short-uuid/{short_uuid}/raw", response_class=GetRawSubscriptionByShortUuidResponseDto)
|
||||
async def get_raw_subscription(
|
||||
self,
|
||||
short_uuid: Annotated[str, Path(description="Short UUID of the user")],
|
||||
withDisabledHosts: Annotated[Annotated[bool, Path(description="Include disabled hosts")], bool] = False,
|
||||
) -> GetRawSubscriptionByShortUuidResponseDto:
|
||||
"""None"""
|
||||
...
|
||||
|
|
@ -4,6 +4,7 @@ from remnawave.models import (
|
|||
GetStatsResponseDto,
|
||||
GetNodesMetricsResponseDto,
|
||||
GetRemnawaveHealthResponseDto,
|
||||
GetX25519KeyPairResponseDto
|
||||
)
|
||||
from remnawave.rapid import BaseController, get
|
||||
|
||||
|
|
@ -43,3 +44,10 @@ class SystemController(BaseController):
|
|||
) -> GetNodesMetricsResponseDto:
|
||||
"""Get Nodes Metrics"""
|
||||
...
|
||||
|
||||
@get("/system/tools/x25519/generate", response_class=GetX25519KeyPairResponseDto)
|
||||
async def get_x25519_key_pair(
|
||||
self,
|
||||
) -> GetX25519KeyPairResponseDto:
|
||||
"""Get X25519 Key Pair"""
|
||||
...
|
||||
|
|
@ -199,6 +199,8 @@ from .system import (
|
|||
StatusCounts,
|
||||
UsersStatistic,
|
||||
GetNodesMetricsResponseDto,
|
||||
GetX25519KeyPairResponseDto,
|
||||
X25519KeyPair,
|
||||
)
|
||||
from .users import (
|
||||
ActiveInternalSquadDto,
|
||||
|
|
@ -327,6 +329,8 @@ __all__ = [
|
|||
"StatusCounts",
|
||||
"UsersStatistic",
|
||||
"GetNodesMetricsResponseDto",
|
||||
"GetX25519KeyPairResponseDto",
|
||||
"X25519KeyPair",
|
||||
# XRay config models
|
||||
"ConfigResponseDto", # Legacy alias
|
||||
"GetConfigResponseDto",
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
from datetime import datetime
|
||||
from typing import Any, Dict, List, Optional
|
||||
from uuid import UUID
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
|
|
@ -25,7 +26,6 @@ class UserSubscription(BaseModel):
|
|||
user_status: UserStatus = Field(alias="userStatus")
|
||||
is_active: bool = Field(alias="isActive")
|
||||
|
||||
|
||||
class SubscriptionInfoData(BaseModel):
|
||||
is_found: bool = Field(alias="isFound")
|
||||
user: UserSubscription
|
||||
|
|
@ -43,6 +43,63 @@ class GetSubscriptionInfoResponseDto(BaseModel):
|
|||
subscription_url: str = Field(alias="subscriptionUrl")
|
||||
happ: HappCrypto
|
||||
|
||||
class UserLastConnectedNodeDto(BaseModel):
|
||||
connected_at: datetime = Field(alias="connectedAt")
|
||||
node_name: str = Field(alias="nodeName")
|
||||
country_code: Optional[str] = Field(None, alias="countryCode") # новое поле
|
||||
|
||||
class ActiveInternalSquadDto(BaseModel):
|
||||
uuid: UUID
|
||||
name: str
|
||||
|
||||
class HappCrypto(BaseModel):
|
||||
crypto_link: str = Field(alias="cryptoLink")
|
||||
|
||||
class UserResponseDto(BaseModel):
|
||||
uuid: UUID
|
||||
short_uuid: str = Field(alias="shortUuid")
|
||||
username: str
|
||||
status: str
|
||||
used_traffic_bytes: float = Field(alias="usedTrafficBytes")
|
||||
lifetime_used_traffic_bytes: float = Field(alias="lifetimeUsedTrafficBytes")
|
||||
traffic_limit_bytes: int = Field(alias="trafficLimitBytes")
|
||||
traffic_limit_strategy: str = Field(alias="trafficLimitStrategy")
|
||||
sub_last_user_agent: Optional[str] = Field(None, alias="subLastUserAgent")
|
||||
sub_last_opened_at: Optional[datetime] = Field(None, alias="subLastOpenedAt")
|
||||
expire_at: datetime = Field(alias="expireAt")
|
||||
online_at: Optional[datetime] = Field(None, alias="onlineAt")
|
||||
sub_revoked_at: Optional[datetime] = Field(None, alias="subRevokedAt")
|
||||
last_traffic_reset_at: Optional[datetime] = Field(None, alias="lastTrafficResetAt")
|
||||
trojan_password: str = Field(alias="trojanPassword")
|
||||
vless_uuid: UUID = Field(alias="vlessUuid")
|
||||
ss_password: str = Field(alias="ssPassword")
|
||||
description: Optional[str] = None
|
||||
tag: Optional[str] = None
|
||||
telegram_id: Optional[int] = Field(None, alias="telegramId")
|
||||
email: Optional[str] = None
|
||||
hwidDeviceLimit: Optional[int] = Field(None, alias="hwidDeviceLimit")
|
||||
first_connected_at: Optional[datetime] = Field(None, alias="firstConnectedAt")
|
||||
last_triggered_threshold: int = Field(alias="lastTriggeredThreshold")
|
||||
created_at: datetime = Field(alias="createdAt")
|
||||
updated_at: datetime = Field(alias="updatedAt")
|
||||
active_internal_squads: List[ActiveInternalSquadDto] = Field(alias="activeInternalSquads")
|
||||
subscription_url: str = Field(alias="subscriptionUrl")
|
||||
last_connected_node: Optional[UserLastConnectedNodeDto] = Field(None, alias="lastConnectedNode")
|
||||
happ: Optional[HappCrypto] = Field(None, alias="happ")
|
||||
|
||||
class ConvertedUserInfo(BaseModel):
|
||||
days_left: int = Field(alias="daysLeft")
|
||||
traffic_limit: str = Field(alias="trafficLimit")
|
||||
traffic_used: str = Field(alias="trafficUsed")
|
||||
lifetime_traffic_used: str = Field(alias="lifetimeTrafficUsed")
|
||||
is_hwid_limited: bool = Field(alias="isHwidLimited")
|
||||
|
||||
class Passwords(BaseModel):
|
||||
ss_password: Optional[str] = Field(None, alias="ssPassword")
|
||||
trojan_password: Optional[str] = Field(None, alias="trojanPassword")
|
||||
vless_password: Optional[str] = Field(None, alias="vlessPassword")
|
||||
|
||||
|
||||
|
||||
class RawHostAdditionalParams(BaseModel):
|
||||
mode: Optional[str] = None
|
||||
|
|
@ -68,14 +125,13 @@ class RawHostDbData(BaseModel):
|
|||
is_hidden: bool = Field(alias="isHidden")
|
||||
tag: Optional[str] = None
|
||||
|
||||
|
||||
class RawHost(BaseModel):
|
||||
address: Optional[str] = None
|
||||
alpn: Optional[str] = None
|
||||
fingerprint: Optional[str] = None
|
||||
host: Optional[str] = None
|
||||
network: Optional[str] = None
|
||||
password: Optional[str] = None
|
||||
password: Optional[Passwords] = None
|
||||
path: Optional[str] = None
|
||||
public_key: Optional[str] = Field(None, alias="publicKey")
|
||||
port: Optional[int] = None
|
||||
|
|
@ -95,14 +151,11 @@ class RawHost(BaseModel):
|
|||
protocol_options: Optional[RawHostProtocolOptions] = Field(None, alias="protocolOptions")
|
||||
db_data: RawHostDbData = Field(alias="dbData")
|
||||
|
||||
|
||||
class RawSubscriptionResponse(BaseModel):
|
||||
user: UserSubscription
|
||||
subscription_url: str = Field(alias="subscriptionUrl")
|
||||
raw_hosts: List[RawHost] = Field(alias="rawHosts")
|
||||
user: UserResponseDto
|
||||
converted_user_info: ConvertedUserInfo = Field(alias="convertedUserInfo")
|
||||
headers: Dict[str, str]
|
||||
is_hwid_limited: bool = Field(alias="isHwidLimited")
|
||||
|
||||
raw_hosts: List[RawHost] = Field(alias="rawHosts")
|
||||
|
||||
class GetRawSubscriptionByShortUuidResponseDto(RawSubscriptionResponse):
|
||||
pass
|
||||
|
|
|
|||
|
|
@ -121,3 +121,10 @@ class NodeMetric(BaseModel):
|
|||
|
||||
class GetNodesMetricsResponseDto(BaseModel):
|
||||
response: List[NodeMetric]
|
||||
|
||||
class X25519KeyPair(BaseModel):
|
||||
public_key: str = Field(alias="publicKey")
|
||||
private_key: str = Field(alias="privateKey")
|
||||
|
||||
class GetX25519KeyPairResponseDto(BaseModel):
|
||||
key_pairs: List[X25519KeyPair] = Field(alias="keyPairs")
|
||||
Loading…
Add table
Add a link
Reference in a new issue