mirror of
https://github.com/remnawave/python-sdk.git
synced 2026-05-13 12:16:42 +00:00
feat: обновить модели для поддержки плавающих значений и улучшить валидацию
This commit is contained in:
parent
0ed1ce92c0
commit
a880da073f
16 changed files with 150 additions and 79 deletions
|
|
@ -34,10 +34,10 @@ class SubscriptionController(BaseController):
|
|||
"""None"""
|
||||
...
|
||||
|
||||
@get("/sub/outline/{short_uuid}/{type}/{encoded_tag}", response_class=str)
|
||||
@get("/sub/outline/{shortUuid}/{type}/{encodedTag}", response_class=str)
|
||||
async def get_subscription_with_type(
|
||||
self,
|
||||
short_uuid: Annotated[str, Path(description="Short UUID of the user")],
|
||||
short_uuid: Annotated[str, Path(description="Short UUID of the user", alias="shortUuid")],
|
||||
type: Annotated[
|
||||
str,
|
||||
Path(
|
||||
|
|
@ -47,7 +47,8 @@ class SubscriptionController(BaseController):
|
|||
encoded_tag: Annotated[
|
||||
str,
|
||||
Path(
|
||||
description="Base64 encoded tag for Outline config. This paramter is optional. It is required only when type=ss."
|
||||
description="Base64 encoded tag for Outline config. This paramter is optional. It is required only when type=ss.",
|
||||
alias="encodedTag",
|
||||
),
|
||||
] = "VGVzdGVy",
|
||||
) -> str:
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
from typing import Annotated, Any, Dict, Optional
|
||||
|
||||
from pydantic import BaseModel, Field, StringConstraints
|
||||
from pydantic import BaseModel, Field, StringConstraints, field_validator
|
||||
|
||||
from remnawave.enums.auth import OAuth2Provider
|
||||
|
||||
|
|
@ -57,6 +57,17 @@ class RegisterRequestDto(BaseModel):
|
|||
username: str
|
||||
password: Annotated[str, StringConstraints(min_length=24)]
|
||||
|
||||
@field_validator("password")
|
||||
@classmethod
|
||||
def validate_password_complexity(cls, v: str) -> str:
|
||||
if not any(c.isupper() for c in v):
|
||||
raise ValueError("Password must contain at least one uppercase letter")
|
||||
if not any(c.islower() for c in v):
|
||||
raise ValueError("Password must contain at least one lowercase letter")
|
||||
if not any(c.isdigit() for c in v):
|
||||
raise ValueError("Password must contain at least one digit")
|
||||
return v
|
||||
|
||||
|
||||
class TelegramCallbackRequestDto(BaseModel):
|
||||
id: int
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
from datetime import datetime
|
||||
from typing import Any, Dict, List, Optional
|
||||
from typing import Annotated, Any, Dict, List, Optional
|
||||
from uuid import UUID
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
from pydantic import BaseModel, Field, StringConstraints
|
||||
|
||||
|
||||
class InboundDto(BaseModel):
|
||||
|
|
@ -32,7 +32,7 @@ class ConfigProfileDto(BaseModel):
|
|||
|
||||
|
||||
class CreateConfigProfileRequestDto(BaseModel):
|
||||
name: str
|
||||
name: Annotated[str, StringConstraints(min_length=2, max_length=30, pattern=r"^[A-Za-z0-9_\s-]+$")]
|
||||
config: Dict[str, Any]
|
||||
|
||||
|
||||
|
|
@ -42,7 +42,7 @@ class CreateConfigProfileResponseDto(ConfigProfileDto):
|
|||
|
||||
class UpdateConfigProfileRequestDto(BaseModel):
|
||||
uuid: UUID
|
||||
name: Optional[str] = Field(None, pattern=r"^[A-Za-z0-9_-]+$")
|
||||
name: Optional[Annotated[str, StringConstraints(min_length=2, max_length=30, pattern=r"^[A-Za-z0-9_\s-]+$")]] = None
|
||||
config: Optional[Dict[str, Any]] = None
|
||||
|
||||
|
||||
|
|
@ -51,7 +51,7 @@ class UpdateConfigProfileResponseDto(ConfigProfileDto):
|
|||
|
||||
|
||||
class GetAllConfigProfilesResponsePaginated(BaseModel):
|
||||
total: int
|
||||
total: float
|
||||
config_profiles: List[ConfigProfileDto] = Field(alias="configProfiles")
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@ class ExternalSquadDto(BaseModel):
|
|||
response_headers: Optional[Dict[str, str]] = Field(None, alias="responseHeaders")
|
||||
hwid_settings: Optional[HwidSettingsDto] = Field(None, alias="hwidSettings")
|
||||
custom_remarks: Optional[CustomRemarksDto] = Field(None, alias="customRemarks")
|
||||
subpage_config_uuid: Optional[UUID] = Field(None, alias="subpageConfigUuid")
|
||||
created_at: datetime = Field(alias="createdAt")
|
||||
updated_at: datetime = Field(alias="updatedAt")
|
||||
|
||||
|
|
@ -65,7 +66,7 @@ class ExternalSquadDto(BaseModel):
|
|||
# Request/Response models
|
||||
class GetExternalSquadsResponseDto(BaseModel):
|
||||
"""Response with all external squads"""
|
||||
total: int = Field(alias="total")
|
||||
total: float = Field(alias="total")
|
||||
external_squads: List[ExternalSquadDto] = Field(alias="externalSquads")
|
||||
|
||||
|
||||
|
|
@ -94,6 +95,7 @@ class UpdateExternalSquadRequestDto(BaseModel):
|
|||
hwid_settings: Optional[HwidSettingsDto] = Field(None, alias="hwidSettings")
|
||||
custom_remarks: Optional[CustomRemarksDto] = Field(None, alias="customRemarks")
|
||||
response_headers: Optional[Dict[str, str]] = Field(None, serialization_alias="responseHeaders")
|
||||
subpage_config_uuid: Optional[UUID] = Field(None, serialization_alias="subpageConfigUuid")
|
||||
|
||||
|
||||
class UpdateExternalSquadResponseDto(ExternalSquadDto):
|
||||
|
|
@ -117,15 +119,10 @@ class ReorderExternalSquadsRequestDto(BaseModel):
|
|||
|
||||
class ReorderExternalSquadsResponseDto(BaseModel):
|
||||
"""Response after reordering external squads"""
|
||||
total: int = Field(alias="total")
|
||||
total: float = Field(alias="total")
|
||||
external_squads: List[ExternalSquadDto] = Field(alias="externalSquads")
|
||||
|
||||
|
||||
class DeleteExternalSquadResponseDto(BaseModel):
|
||||
"""Response after deleting external squad"""
|
||||
is_deleted: bool = Field(alias="isDeleted")
|
||||
|
||||
|
||||
class AddUsersToExternalSquadResponseDto(BaseModel):
|
||||
"""Response after adding users to external squad"""
|
||||
event_sent: bool = Field(alias="eventSent")
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ class UpdateHostRequestDto(BaseModel):
|
|||
tag: Optional[Annotated[str, StringConstraints(max_length=32, pattern=r"^[A-Z0-9_:]+$")]] = None
|
||||
is_hidden: Optional[bool] = Field(None, serialization_alias="isHidden")
|
||||
override_sni_from_address: Optional[bool] = Field(None, serialization_alias="overrideSniFromAddress")
|
||||
keep_blank_sni: Optional[bool] = Field(None, serialization_alias="keepBlankSni")
|
||||
keep_blank_sni: Optional[bool] = Field(None, serialization_alias="keepSniBlank")
|
||||
vless_route_id: Optional[int] = Field(None, serialization_alias="vlessRouteId", ge=0, le=65535)
|
||||
shuffle_host: Optional[bool] = Field(None, serialization_alias="shuffleHost")
|
||||
mihomo_x25519: Optional[bool] = Field(None, serialization_alias="mihomoX25519")
|
||||
|
|
@ -89,7 +89,7 @@ class HostResponseDto(BaseModel):
|
|||
security_layer: SecurityLayer = Field(SecurityLayer.DEFAULT, alias="securityLayer")
|
||||
is_hidden: bool = Field(False, alias="isHidden")
|
||||
override_sni_from_address: bool = Field(False, alias="overrideSniFromAddress")
|
||||
keep_blank_sni: bool = Field(False, alias="keepBlankSni")
|
||||
keep_blank_sni: bool = Field(False, alias="keepSniBlank")
|
||||
allow_insecure: bool = Field(False, alias="allowInsecure")
|
||||
xray_json_template_uuid: UUID | None = Field(alias="xrayJsonTemplateUuid")
|
||||
excluded_internal_squads: List[UUID] = Field(default_factory=list, alias="excludedInternalSquads")
|
||||
|
|
@ -128,7 +128,7 @@ class CreateHostRequestDto(BaseModel):
|
|||
security_layer: SecurityLayer = Field(SecurityLayer.DEFAULT, serialization_alias="securityLayer")
|
||||
is_hidden: bool = Field(False, serialization_alias="isHidden")
|
||||
override_sni_from_address: bool = Field(False, serialization_alias="overrideSniFromAddress")
|
||||
keep_blank_sni: bool = Field(False, serialization_alias="keepBlankSni")
|
||||
keep_blank_sni: bool = Field(False, serialization_alias="keepSniBlank")
|
||||
xray_json_template_uuid: Optional[UUID] = Field(None, serialization_alias="xrayJsonTemplateUuid")
|
||||
excluded_internal_squads: List[UUID] = Field(default_factory=list, serialization_alias="excludedInternalSquads")
|
||||
exclude_from_subscription_types: List[SubscriptionType] = Field(
|
||||
|
|
@ -147,6 +147,10 @@ class CreateHostRequestDto(BaseModel):
|
|||
config_profile_uuid: Optional[UUID] = None,
|
||||
**data,
|
||||
):
|
||||
# Backward-compatible support for misspelled helper argument used in old tests/examples
|
||||
if config_profile_uuid is None and "config_profile_inbound_uuid" in data:
|
||||
config_profile_uuid = data.pop("config_profile_inbound_uuid")
|
||||
|
||||
if inbound_uuid is not None and "inbound" not in data:
|
||||
data["inbound"] = CreateHostInboundData(
|
||||
config_profile_uuid=config_profile_uuid
|
||||
|
|
|
|||
|
|
@ -31,22 +31,22 @@ class HwidDeviceDto(BaseModel):
|
|||
|
||||
|
||||
class HwidDevicesData(BaseModel):
|
||||
total: int
|
||||
total: float
|
||||
devices: List[HwidDeviceDto]
|
||||
|
||||
|
||||
class CreateUserHwidDeviceResponseDto(BaseModel):
|
||||
total: int
|
||||
total: float
|
||||
devices: List[HwidDeviceDto]
|
||||
|
||||
|
||||
class DeleteUserHwidDeviceResponseDto(BaseModel):
|
||||
total: int
|
||||
total: float
|
||||
devices: List[HwidDeviceDto]
|
||||
|
||||
|
||||
class GetUserHwidDevicesResponseDto(BaseModel):
|
||||
total: int
|
||||
total: float
|
||||
devices: List[HwidDeviceDto]
|
||||
|
||||
class PlatformStatItem(BaseModel):
|
||||
|
|
@ -82,13 +82,13 @@ class TopUserByHwidDevicesDto(BaseModel):
|
|||
user_uuid: UUID = Field(alias="userUuid")
|
||||
id: int
|
||||
username: str
|
||||
devices_count: int = Field(alias="devicesCount")
|
||||
devices_count: float = Field(alias="devicesCount")
|
||||
|
||||
|
||||
class TopUsersByHwidDevicesData(BaseModel):
|
||||
"""Top users by HWID devices data"""
|
||||
users: list[TopUserByHwidDevicesDto]
|
||||
total: int
|
||||
total: float
|
||||
|
||||
|
||||
class GetTopUsersByHwidDevicesResponseDto(TopUsersByHwidDevicesData):
|
||||
|
|
|
|||
|
|
@ -13,11 +13,11 @@ class InboundResponseDto(BaseModel):
|
|||
security: Optional[str] = None
|
||||
port: Optional[float] = None
|
||||
raw_inbound: Optional[Any] = Field(None, alias="rawInbound")
|
||||
active_squads: Optional[list[UUID]] = Field(None, alias="activeSquads")
|
||||
active_squads: List[UUID] = Field(default_factory=list, alias="activeSquads")
|
||||
|
||||
|
||||
class AllInboundsData(BaseModel):
|
||||
total: int
|
||||
total: float
|
||||
inbounds: List[InboundResponseDto]
|
||||
|
||||
|
||||
|
|
@ -26,7 +26,7 @@ class GetAllInboundsResponseDto(AllInboundsData):
|
|||
|
||||
|
||||
class InboundsByProfileData(BaseModel):
|
||||
total: int
|
||||
total: float
|
||||
inbounds: List[InboundResponseDto]
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ class UpdateInfraProviderResponseDto(InfraProviderDto):
|
|||
|
||||
|
||||
class AllInfraProvidersData(BaseModel):
|
||||
total: int = Field(alias="total")
|
||||
total: float = Field(alias="total")
|
||||
providers: List[InfraProviderDto]
|
||||
|
||||
|
||||
|
|
@ -135,7 +135,7 @@ class CreateInfraBillingHistoryRecordResponseDto(InfraBillingHistoryDto):
|
|||
|
||||
class InfraBillingHistoryData(BaseModel):
|
||||
records: List[InfraBillingHistoryDto]
|
||||
total: int
|
||||
total: float
|
||||
|
||||
|
||||
class GetInfraBillingHistoryRecordsResponseDto(InfraBillingHistoryData):
|
||||
|
|
@ -167,8 +167,12 @@ class UpdateInfraBillingNodeRequestDto(BaseModel):
|
|||
next_billing_at: datetime = Field(serialization_alias="nextBillingAt")
|
||||
|
||||
|
||||
class UpdateInfraBillingNodeResponseDto(InfraBillingNodeDto):
|
||||
pass
|
||||
class UpdateInfraBillingNodeResponseDto(BaseModel):
|
||||
total_billing_nodes: float = Field(alias="totalBillingNodes")
|
||||
billing_nodes: List[InfraBillingNodeDto] = Field(alias="billingNodes")
|
||||
available_billing_nodes: List[AvailableBillingNodeDto] = Field(alias="availableBillingNodes")
|
||||
total_available_billing_nodes: float = Field(alias="totalAvailableBillingNodes")
|
||||
stats: BillingStatsDto
|
||||
|
||||
|
||||
class InfraBillingNodesData(BaseModel):
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
from datetime import datetime
|
||||
from typing import List, Optional
|
||||
from typing import Annotated, List, Optional
|
||||
from uuid import UUID
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
from pydantic import BaseModel, Field, StringConstraints
|
||||
|
||||
|
||||
class InboundsDto(BaseModel):
|
||||
|
|
@ -17,8 +17,8 @@ class InboundsDto(BaseModel):
|
|||
|
||||
|
||||
class InfoDto(BaseModel):
|
||||
members_count: int = Field(alias="membersCount")
|
||||
inbounds_count: int = Field(alias="inboundsCount")
|
||||
members_count: float = Field(alias="membersCount")
|
||||
inbounds_count: float = Field(alias="inboundsCount")
|
||||
|
||||
|
||||
class InternalSquadDto(BaseModel):
|
||||
|
|
@ -32,7 +32,7 @@ class InternalSquadDto(BaseModel):
|
|||
|
||||
|
||||
class CreateInternalSquadRequestDto(BaseModel):
|
||||
name: str
|
||||
name: Annotated[str, StringConstraints(min_length=2, max_length=30, pattern=r"^[A-Za-z0-9_\s-]+$")]
|
||||
inbounds: List[UUID] = Field(default_factory=list)
|
||||
|
||||
|
||||
|
|
@ -43,7 +43,7 @@ class CreateInternalSquadResponseDto(InternalSquadDto):
|
|||
class UpdateInternalSquadRequestDto(BaseModel):
|
||||
uuid: UUID
|
||||
inbounds: List[UUID] = Field(default_factory=list)
|
||||
name: Optional[str] = Field(None, pattern=r"^[A-Za-z0-9_-]+$")
|
||||
name: Optional[Annotated[str, StringConstraints(min_length=2, max_length=30, pattern=r"^[A-Za-z0-9_\s-]+$")]] = None
|
||||
|
||||
|
||||
class UpdateInternalSquadResponseDto(InternalSquadDto):
|
||||
|
|
@ -51,7 +51,7 @@ class UpdateInternalSquadResponseDto(InternalSquadDto):
|
|||
|
||||
|
||||
class GetAllInternalSquadsResponse(BaseModel):
|
||||
total: int
|
||||
total: float
|
||||
internal_squads: List[InternalSquadDto] = Field(alias="internalSquads")
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -89,6 +89,9 @@ class CreateNodeRequestDto(BaseModel):
|
|||
serialization_alias="tags",
|
||||
max_length=10
|
||||
)
|
||||
active_plugin_uuid: Optional[UUID] = Field(
|
||||
None, serialization_alias="activePluginUuid"
|
||||
)
|
||||
|
||||
|
||||
class UpdateNodeRequestDto(BaseModel):
|
||||
|
|
@ -126,6 +129,9 @@ class UpdateNodeRequestDto(BaseModel):
|
|||
serialization_alias="tags",
|
||||
max_length=10
|
||||
)
|
||||
active_plugin_uuid: Optional[UUID] = Field(
|
||||
None, serialization_alias="activePluginUuid"
|
||||
)
|
||||
|
||||
|
||||
class ReorderNodeRequestDto(BaseModel):
|
||||
|
|
@ -163,6 +169,7 @@ class NodeResponseDto(BaseModel):
|
|||
provider_uuid: Optional[UUID] = Field(None, alias="providerUuid")
|
||||
provider: Optional[NodeProviderDto] = None
|
||||
tags: List[str] = Field(default_factory=list, alias="tags")
|
||||
active_plugin_uuid: Optional[UUID] = Field(None, alias="activePluginUuid")
|
||||
|
||||
|
||||
class CreateNodeResponseDto(NodeResponseDto):
|
||||
|
|
|
|||
|
|
@ -176,7 +176,7 @@ class GetRawSubscriptionByShortUuidResponseDto(RawSubscriptionResponse):
|
|||
class UserSubscription(BaseModel):
|
||||
short_uuid: str = Field(alias="shortUuid")
|
||||
username: str
|
||||
days_left: int = Field(alias="daysLeft")
|
||||
days_left: float = Field(alias="daysLeft")
|
||||
traffic_used: str = Field(alias="trafficUsed")
|
||||
traffic_limit: str = Field(alias="trafficLimit")
|
||||
lifetime_traffic_used: str = Field(alias="lifetimeTrafficUsed")
|
||||
|
|
@ -222,7 +222,7 @@ class SubscriptionWithoutHapp(BaseModel):
|
|||
|
||||
class GetAllSubscriptionsResponseDto(BaseModel):
|
||||
subscriptions: List[SubscriptionWithoutHapp]
|
||||
total: int
|
||||
total: float
|
||||
|
||||
|
||||
class GetSubscriptionByUsernameResponseDto(BaseModel):
|
||||
|
|
@ -242,7 +242,14 @@ class GetSubscriptionByUUIDResponseDto(GetSubscriptionByUsernameResponseDto):
|
|||
|
||||
|
||||
class GetConnectionKeysByUuidResponseDto(BaseModel):
|
||||
connection_keys: List[str] = Field(alias="connectionKeys")
|
||||
enabled_keys: List[str] = Field(alias="enabledKeys")
|
||||
hidden_keys: List[str] = Field(alias="hiddenKeys")
|
||||
disabled_keys: List[str] = Field(alias="disabledKeys")
|
||||
|
||||
@property
|
||||
def connection_keys(self) -> List[str]:
|
||||
"""Backward compatibility: historically SDK exposed a flat list of keys."""
|
||||
return self.enabled_keys
|
||||
|
||||
|
||||
# Legacy alias for backward compatibility
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ class SubscriptionPageConfigDto(BaseModel):
|
|||
|
||||
class GetSubscriptionPageConfigsData(BaseModel):
|
||||
"""Data for getting all subscription page configs"""
|
||||
total: int
|
||||
total: float
|
||||
configs: List[SubscriptionPageConfigDto]
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ class GetTemplateResponseDto(TemplateResponseDto):
|
|||
pass
|
||||
|
||||
class GetTemplatesData(BaseModel):
|
||||
total: int
|
||||
total: float
|
||||
templates: List[TemplateInfoDto]
|
||||
|
||||
class GetTemplatesResponseDto(GetTemplatesData):
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ from remnawave.models.subscriptions_settings import ResponseRule, ResponseRules
|
|||
class NodeStatistic(BaseModel):
|
||||
node_name: str = Field(alias="nodeName")
|
||||
date: datetime.date
|
||||
total_bytes: int = Field(alias="totalBytes")
|
||||
total_bytes: str = Field(alias="totalBytes")
|
||||
|
||||
|
||||
class NodesStatisticResponseDto(BaseModel):
|
||||
|
|
@ -32,16 +32,16 @@ class BandwidthStatisticResponseDto(BaseModel):
|
|||
|
||||
|
||||
class CPUStatistic(BaseModel):
|
||||
cores: int
|
||||
physical_cores: int = Field(alias="physicalCores")
|
||||
cores: float
|
||||
physical_cores: float = Field(alias="physicalCores")
|
||||
|
||||
|
||||
class MemoryStatistic(BaseModel):
|
||||
total: int
|
||||
free: int
|
||||
used: int
|
||||
active: int
|
||||
available: int
|
||||
total: float
|
||||
free: float
|
||||
used: float
|
||||
active: float
|
||||
available: float
|
||||
|
||||
|
||||
class StatusCounts(BaseModel):
|
||||
|
|
@ -59,18 +59,18 @@ class StatusCounts(BaseModel):
|
|||
|
||||
class UsersStatistic(BaseModel):
|
||||
status_counts: StatusCounts = Field(alias="statusCounts")
|
||||
total_users: int = Field(alias="totalUsers")
|
||||
total_users: float = Field(alias="totalUsers")
|
||||
|
||||
|
||||
class OnlineStatistic(BaseModel):
|
||||
last_day: int = Field(alias="lastDay")
|
||||
last_week: int = Field(alias="lastWeek")
|
||||
never_online: int = Field(alias="neverOnline")
|
||||
online_now: int = Field(alias="onlineNow")
|
||||
last_day: float = Field(alias="lastDay")
|
||||
last_week: float = Field(alias="lastWeek")
|
||||
never_online: float = Field(alias="neverOnline")
|
||||
online_now: float = Field(alias="onlineNow")
|
||||
|
||||
|
||||
class NodesStatistic(BaseModel):
|
||||
total_online: int = Field(alias="totalOnline")
|
||||
total_online: float = Field(alias="totalOnline")
|
||||
total_bytes_lifetime: str = Field(alias="totalBytesLifetime")
|
||||
|
||||
|
||||
|
|
@ -79,7 +79,7 @@ class StatisticResponseDto(BaseModel):
|
|||
cpu: CPUStatistic
|
||||
memory: MemoryStatistic
|
||||
uptime: float
|
||||
timestamp: int
|
||||
timestamp: float
|
||||
users: UsersStatistic
|
||||
online_stats: OnlineStatistic = Field(alias="onlineStats")
|
||||
nodes: NodesStatistic
|
||||
|
|
@ -116,21 +116,57 @@ class GetRemnawaveHealthResponseDto(BaseModel):
|
|||
pm2_stats: List[PM2Stat] = Field(alias="pm2Stats")
|
||||
|
||||
|
||||
class TrafficStatDto(BaseModel):
|
||||
tag: str
|
||||
upload: str
|
||||
download: str
|
||||
|
||||
|
||||
class NodeMetric(BaseModel):
|
||||
"""Node metric data"""
|
||||
uuid: str = Field(alias="nodeUuid")
|
||||
name: Optional[str] = None
|
||||
address: Optional[str] = None
|
||||
is_online: Optional[bool] = Field(None, alias="isOnline")
|
||||
cpu_usage: Optional[float] = Field(None, alias="cpuUsage")
|
||||
memory_usage: Optional[float] = Field(None, alias="memoryUsage")
|
||||
network_upload: Optional[int] = Field(None, alias="networkUpload")
|
||||
network_download: Optional[int] = Field(None, alias="networkDownload")
|
||||
uptime: Optional[int] = None
|
||||
last_seen: Optional[datetime.datetime] = Field(None, alias="lastSeen")
|
||||
connected_users: Optional[int] = Field(None, alias="connectedUsers")
|
||||
upload: Optional[str] = None
|
||||
download: Optional[str] = None
|
||||
"""Node metric data (API v1.10)"""
|
||||
node_uuid: str = Field(alias="nodeUuid")
|
||||
node_name: str = Field(alias="nodeName")
|
||||
country_emoji: str = Field(alias="countryEmoji")
|
||||
provider_name: str = Field(alias="providerName")
|
||||
users_online: float = Field(alias="usersOnline")
|
||||
inbounds_stats: List[TrafficStatDto] = Field(alias="inboundsStats")
|
||||
outbounds_stats: List[TrafficStatDto] = Field(alias="outboundsStats")
|
||||
|
||||
@property
|
||||
def uuid(self) -> str:
|
||||
return self.node_uuid
|
||||
|
||||
@property
|
||||
def name(self) -> str:
|
||||
return self.node_name
|
||||
|
||||
@property
|
||||
def connected_users(self) -> float:
|
||||
return self.users_online
|
||||
|
||||
@property
|
||||
def cpu_usage(self) -> None:
|
||||
return None
|
||||
|
||||
@property
|
||||
def memory_usage(self) -> None:
|
||||
return None
|
||||
|
||||
@property
|
||||
def network_upload(self) -> None:
|
||||
return None
|
||||
|
||||
@property
|
||||
def network_download(self) -> None:
|
||||
return None
|
||||
|
||||
@property
|
||||
def uptime(self) -> None:
|
||||
return None
|
||||
|
||||
@property
|
||||
def last_seen(self) -> None:
|
||||
return None
|
||||
|
||||
|
||||
class GetNodesMetricsResponseDto(BaseModel):
|
||||
|
|
@ -143,7 +179,11 @@ class X25519KeyPair(BaseModel):
|
|||
|
||||
|
||||
class GetX25519KeyPairResponseDto(BaseModel):
|
||||
key_pairs: List[X25519KeyPair] = Field(alias="keyPairs")
|
||||
key_pairs: List[X25519KeyPair] = Field(alias="keypairs")
|
||||
|
||||
|
||||
# OpenAPI v1.10 schema name
|
||||
GenerateX25519ResponseDto = GetX25519KeyPairResponseDto
|
||||
|
||||
|
||||
class EncryptHappCryptoLinkRequestDto(BaseModel):
|
||||
|
|
|
|||
|
|
@ -109,8 +109,8 @@ class UpdateUserRequestDto(BaseModel):
|
|||
|
||||
class UserTrafficDto(BaseModel):
|
||||
"""User traffic information"""
|
||||
used_traffic_bytes: int = Field(alias="usedTrafficBytes")
|
||||
lifetime_used_traffic_bytes: int = Field(alias="lifetimeUsedTrafficBytes")
|
||||
used_traffic_bytes: float = Field(alias="usedTrafficBytes")
|
||||
lifetime_used_traffic_bytes: float = Field(alias="lifetimeUsedTrafficBytes")
|
||||
online_at: Optional[datetime] = Field(None, alias="onlineAt")
|
||||
first_connected_at: Optional[datetime] = Field(None, alias="firstConnectedAt")
|
||||
last_connected_node_uuid: Optional[UUID] = Field(None, alias="lastConnectedNodeUuid")
|
||||
|
|
@ -149,12 +149,12 @@ class UserResponseDto(BaseModel):
|
|||
user_traffic: UserTrafficDto = Field(alias="userTraffic")
|
||||
|
||||
@property
|
||||
def used_traffic_bytes(self) -> int:
|
||||
def used_traffic_bytes(self) -> float:
|
||||
"""Backward compatibility property"""
|
||||
return self.user_traffic.used_traffic_bytes
|
||||
|
||||
@property
|
||||
def lifetime_used_traffic_bytes(self) -> int:
|
||||
def lifetime_used_traffic_bytes(self) -> float:
|
||||
"""Backward compatibility property"""
|
||||
return self.user_traffic.lifetime_used_traffic_bytes
|
||||
|
||||
|
|
|
|||
|
|
@ -139,7 +139,7 @@ class BulkAllExtendExpirationDateRequestDto(BaseModel):
|
|||
# Base Response DTOs (без обертки response)
|
||||
class BulkResponseData(BaseModel):
|
||||
"""Common bulk response with affected rows"""
|
||||
affected_rows: int = Field(alias="affectedRows")
|
||||
affected_rows: float = Field(alias="affectedRows")
|
||||
|
||||
|
||||
class BulkEventResponseData(BaseModel):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue