mirror of
https://github.com/remnawave/python-sdk.git
synced 2026-08-31 14:21:05 +00:00
- Bump version to 2.4.4 and update description in pyproject.toml - Refactor RemnawaveSDK to include SubscriptionPageConfigController - Introduce new subscription page management endpoints: - Get, create, update, delete, reorder, and clone subscription page configs - Remove deprecated NodesUsageHistoryController and UsersStatsController - Add new bandwidth stats models and endpoints for legacy and new stats - Enhance tests for bandwidth stats and subscription page management - Ensure backward compatibility with legacy endpoints while introducing new stats models
294 lines
No EOL
8.1 KiB
Python
294 lines
No EOL
8.1 KiB
Python
from datetime import datetime, date
|
|
from typing import List
|
|
from uuid import UUID
|
|
|
|
from pydantic import BaseModel, Field, RootModel
|
|
|
|
|
|
# ============ Legacy Models (Deprecated) ============
|
|
|
|
class NodeUsageResponseDto(BaseModel):
|
|
"""Deprecated: Old node usage model"""
|
|
node_uuid: UUID = Field(alias="nodeUuid")
|
|
node_name: str = Field(alias="nodeName")
|
|
total: int
|
|
total_download: float = Field(alias="totalDownload")
|
|
total_upload: float = Field(alias="totalUpload")
|
|
human_readable_total: str = Field(alias="humanReadableTotal")
|
|
human_readable_total_download: str = Field(alias="humanReadableTotalDownload")
|
|
human_readable_total_upload: str = Field(alias="humanReadableTotalUpload")
|
|
date: date
|
|
|
|
|
|
class NodesUsageResponseDto(RootModel[List[NodeUsageResponseDto]]):
|
|
"""Deprecated: Use GetStatsNodesUsageResponseDto instead"""
|
|
def __iter__(self):
|
|
return iter(self.root)
|
|
|
|
def __getitem__(self, item):
|
|
return self.root[item]
|
|
|
|
def __bool__(self):
|
|
return bool(self.root)
|
|
|
|
def __len__(self):
|
|
return len(self.root)
|
|
|
|
|
|
class GetNodesUsageByRangeResponseDto(RootModel[List[NodeUsageResponseDto]]):
|
|
"""Deprecated: Use GetStatsNodesUsageResponseDto instead"""
|
|
def __iter__(self):
|
|
return iter(self.root)
|
|
|
|
def __getitem__(self, item):
|
|
return self.root[item]
|
|
|
|
def __bool__(self):
|
|
return bool(self.root)
|
|
|
|
def __len__(self):
|
|
return len(self.root)
|
|
|
|
|
|
class NodeRealtimeUsageResponseDto(BaseModel):
|
|
"""Deprecated: Use NodeRealtimeUsageItem instead"""
|
|
node_uuid: UUID = Field(alias="nodeUuid")
|
|
node_name: str = Field(alias="nodeName")
|
|
country_code: str = Field(alias="countryCode")
|
|
download_bytes: float = Field(alias="downloadBytes")
|
|
upload_bytes: float = Field(alias="uploadBytes")
|
|
total_bytes: float = Field(alias="totalBytes")
|
|
download_speed_bps: float = Field(alias="downloadSpeedBps")
|
|
upload_speed_bps: float = Field(alias="uploadSpeedBps")
|
|
total_speed_bps: float = Field(alias="totalSpeedBps")
|
|
|
|
|
|
class NodesRealtimeUsageResponseDto(RootModel[List[NodeRealtimeUsageResponseDto]]):
|
|
"""Deprecated: Use GetStatsNodesRealtimeUsageResponseDto instead"""
|
|
def __iter__(self):
|
|
return iter(self.root)
|
|
|
|
def __getitem__(self, item):
|
|
return self.root[item]
|
|
|
|
def __bool__(self):
|
|
return bool(self.root)
|
|
|
|
def __len__(self):
|
|
return len(self.root)
|
|
|
|
|
|
class GetNodesRealtimeUsageResponseDto(RootModel[List[NodeRealtimeUsageResponseDto]]):
|
|
"""Deprecated: Use GetStatsNodesRealtimeUsageResponseDto instead"""
|
|
def __iter__(self):
|
|
return iter(self.root)
|
|
|
|
def __getitem__(self, item):
|
|
return self.root[item]
|
|
|
|
def __bool__(self):
|
|
return bool(self.root)
|
|
|
|
def __len__(self):
|
|
return len(self.root)
|
|
|
|
|
|
class UserUsageByRangeItem(BaseModel):
|
|
"""Deprecated: Use LegacyUserUsageItem instead"""
|
|
user_uuid: UUID = Field(alias="userUuid")
|
|
node_uuid: UUID = Field(alias="nodeUuid")
|
|
node_name: str = Field(alias="nodeName")
|
|
total: int
|
|
date: str
|
|
|
|
|
|
class GetUserUsageByRangeResponseDto(RootModel[List[UserUsageByRangeItem]]):
|
|
"""Deprecated: Use GetLegacyStatsUserUsageResponseDto instead"""
|
|
def __iter__(self):
|
|
return iter(self.root)
|
|
|
|
def __getitem__(self, item):
|
|
return self.root[item]
|
|
|
|
def __bool__(self):
|
|
return bool(self.root)
|
|
|
|
def __len__(self):
|
|
return len(self.root)
|
|
|
|
|
|
class NodeUserUsageItem(BaseModel):
|
|
"""Deprecated: Use LegacyNodeUserUsageItem instead"""
|
|
user_uuid: UUID = Field(alias="userUuid")
|
|
username: str
|
|
node_uuid: UUID = Field(alias="nodeUuid")
|
|
total: int
|
|
date: str
|
|
|
|
|
|
class GetNodeUserUsageByRangeResponseDto(RootModel[List[NodeUserUsageItem]]):
|
|
"""Deprecated: Use GetLegacyStatsNodesUsersUsageResponseDto instead"""
|
|
def __iter__(self):
|
|
return iter(self.root)
|
|
|
|
def __getitem__(self, item):
|
|
return self.root[item]
|
|
|
|
def __bool__(self):
|
|
return bool(self.root)
|
|
|
|
def __len__(self):
|
|
return len(self.root)
|
|
|
|
|
|
# ============ New Stats Models ============
|
|
|
|
# Legacy Stats Models
|
|
|
|
class LegacyUserUsageItem(BaseModel):
|
|
"""Legacy user usage item"""
|
|
user_uuid: UUID = Field(alias="userUuid")
|
|
node_uuid: UUID = Field(alias="nodeUuid")
|
|
node_name: str = Field(alias="nodeName")
|
|
country_code: str = Field(alias="countryCode")
|
|
total: int
|
|
date: str
|
|
|
|
|
|
class GetLegacyStatsUserUsageResponseDto(RootModel[List[LegacyUserUsageItem]]):
|
|
"""Response for legacy user usage"""
|
|
@property
|
|
def response(self) -> List[LegacyUserUsageItem]:
|
|
return self.root
|
|
|
|
def __iter__(self):
|
|
return iter(self.root)
|
|
|
|
def __getitem__(self, item):
|
|
return self.root[item]
|
|
|
|
|
|
class LegacyNodeUserUsageItem(BaseModel):
|
|
"""Legacy node user usage item"""
|
|
user_uuid: UUID = Field(alias="userUuid")
|
|
username: str
|
|
node_uuid: UUID = Field(alias="nodeUuid")
|
|
total: int
|
|
date: str
|
|
|
|
|
|
class GetLegacyStatsNodesUsersUsageResponseDto(RootModel[List[LegacyNodeUserUsageItem]]):
|
|
"""Response for legacy nodes users usage"""
|
|
@property
|
|
def response(self) -> List[LegacyNodeUserUsageItem]:
|
|
return self.root
|
|
|
|
def __iter__(self):
|
|
return iter(self.root)
|
|
|
|
def __getitem__(self, item):
|
|
return self.root[item]
|
|
|
|
|
|
# Realtime Stats
|
|
|
|
class NodeRealtimeUsageItem(BaseModel):
|
|
"""Node realtime usage item"""
|
|
node_uuid: UUID = Field(alias="nodeUuid")
|
|
node_name: str = Field(alias="nodeName")
|
|
country_code: str = Field(alias="countryCode")
|
|
download_bytes: float = Field(alias="downloadBytes")
|
|
upload_bytes: float = Field(alias="uploadBytes")
|
|
total_bytes: float = Field(alias="totalBytes")
|
|
download_speed_bps: float = Field(alias="downloadSpeedBps")
|
|
upload_speed_bps: float = Field(alias="uploadSpeedBps")
|
|
total_speed_bps: float = Field(alias="totalSpeedBps")
|
|
|
|
|
|
class GetStatsNodesRealtimeUsageResponseDto(RootModel[List[NodeRealtimeUsageItem]]):
|
|
"""Response for nodes realtime usage"""
|
|
@property
|
|
def response(self) -> List[NodeRealtimeUsageItem]:
|
|
return self.root
|
|
|
|
def __iter__(self):
|
|
return iter(self.root)
|
|
|
|
def __getitem__(self, item):
|
|
return self.root[item]
|
|
|
|
|
|
# Stats Nodes Usage (with charts)
|
|
|
|
class TopNodeItem(BaseModel):
|
|
"""Top node item"""
|
|
uuid: UUID
|
|
color: str
|
|
name: str
|
|
country_code: str = Field(alias="countryCode")
|
|
total: int
|
|
|
|
|
|
class NodeSeriesItem(BaseModel):
|
|
"""Node series item for charts"""
|
|
uuid: UUID
|
|
name: str
|
|
color: str
|
|
country_code: str = Field(alias="countryCode")
|
|
total: int
|
|
data: List[int]
|
|
|
|
|
|
class StatsNodesUsageData(BaseModel):
|
|
"""Stats nodes usage data"""
|
|
categories: List[str]
|
|
sparkline_data: List[int] = Field(alias="sparklineData")
|
|
top_nodes: List[TopNodeItem] = Field(alias="topNodes")
|
|
series: List[NodeSeriesItem]
|
|
|
|
|
|
class GetStatsNodesUsageResponseDto(RootModel[StatsNodesUsageData]):
|
|
"""Response for stats nodes usage"""
|
|
@property
|
|
def response(self) -> StatsNodesUsageData:
|
|
return self.root
|
|
|
|
|
|
# Stats Node Users Usage (with charts)
|
|
|
|
class TopUserItem(BaseModel):
|
|
"""Top user item"""
|
|
color: str
|
|
username: str
|
|
total: int
|
|
|
|
|
|
class StatsNodeUsersUsageData(BaseModel):
|
|
"""Stats node users usage data"""
|
|
categories: List[str]
|
|
sparkline_data: List[int] = Field(alias="sparklineData")
|
|
top_users: List[TopUserItem] = Field(alias="topUsers")
|
|
|
|
|
|
class GetStatsNodeUsersUsageResponseDto(RootModel[StatsNodeUsersUsageData]):
|
|
"""Response for stats node users usage"""
|
|
@property
|
|
def response(self) -> StatsNodeUsersUsageData:
|
|
return self.root
|
|
|
|
|
|
# Stats User Usage (with charts)
|
|
|
|
class StatsUserUsageData(BaseModel):
|
|
"""Stats user usage data"""
|
|
categories: List[str]
|
|
sparkline_data: List[int] = Field(alias="sparklineData")
|
|
top_nodes: List[TopNodeItem] = Field(alias="topNodes")
|
|
series: List[NodeSeriesItem]
|
|
|
|
|
|
class GetStatsUserUsageResponseDto(RootModel[StatsUserUsageData]):
|
|
"""Response for stats user usage"""
|
|
@property
|
|
def response(self) -> StatsUserUsageData:
|
|
return self.root |