mirror of
https://github.com/remnawave/python-sdk.git
synced 2026-08-03 22:25:14 +00:00
Новые эндпоинты: - GET /tokens/scopes (api_tokens_management.get_scopes) - GET /users/stream — keyset-пагинация (users.get_users_stream) - PATCH /hosts/bulk/update (hosts_bulk_actions.update_hosts) - POST /bandwidth-stats/nodes/users (bandwidthstats.get_stats_nodes_users_usage) Удалённые эндпоинты (вслед за API): - POST /hosts/bulk/set-inbound, /hosts/bulk/set-port (заменены update_hosts) - POST /system/tools/happ/encrypt Изменения моделей: - Hosts: tags (вместо tag), mihomoIpVersion, pinnedPeerCertSha256, verifyPeerCertByName, finalMask, xhttpExtraParams; fingerprint -> str; удалены tag/allowInsecure (с обратной совместимостью через свойства) - API-токены: name/expiresInDays/scopes, tokens/enabled; новый enum Scope (полный каталог scope-ов v2.8.0) - Nodes: nodeConsumptionMultiplier, note, proxyUrl; тело RestartNodeRequestBodyDto - trafficLimitBytes int -> float (users, nodes, bulk-actions) - Infra billing: name, nullable nodeUuid, обязательное nextBillingAt - HWID: requestIp; webhook-события (user/service) обновлены - Новый enum MihomoIpVersion Исправления: - Bulk-ответы хостов переведены на RootModel (раньше падали с ValueError) - revoke_user_subscription: исправлен порядок Annotated/Optional (тело терялось) - Restart*RequestBodyDto: populate_by_name (force_restart игнорировался) Зависимости: - Убраны избыточные пины pydantic и pydantic-core (покрыты pydantic[email]) - requires-python <3.14 -> <3.15, добавлен классификатор Python 3.14 Версия пакета 2.7.1 -> 2.8.0.
116 lines
No EOL
5.1 KiB
Python
116 lines
No EOL
5.1 KiB
Python
from typing import Annotated
|
|
|
|
from rapid_api_client import Path, Query
|
|
from rapid_api_client.annotations import PydanticBody
|
|
|
|
from remnawave.models.bandwidthstats import (
|
|
GetLegacyStatsNodesUsersUsageResponseDto,
|
|
GetLegacyStatsUserUsageResponseDto,
|
|
GetNodeUserUsageByRangeResponseDto,
|
|
GetNodesRealtimeUsageResponseDto,
|
|
GetNodesUsageByRangeResponseDto,
|
|
GetStatsNodesRealtimeUsageResponseDto,
|
|
GetStatsNodesUsageResponseDto,
|
|
GetStatsNodeUsersUsageResponseDto,
|
|
GetStatsNodesUsersUsageRequestDto,
|
|
GetStatsNodesUsersUsageResponseDto,
|
|
GetStatsUserUsageResponseDto,
|
|
GetUserUsageByRangeResponseDto,
|
|
)
|
|
from remnawave.rapid import BaseController, get, post
|
|
|
|
|
|
class BandWidthStatsController(BaseController):
|
|
# ============ Legacy Endpoints (Deprecated) ============
|
|
|
|
@get("/bandwidth-stats/users/{userUuid}/legacy", response_class=GetUserUsageByRangeResponseDto)
|
|
async def get_user_usage_legacy_old(
|
|
self,
|
|
user_uuid: Annotated[str, Path(description="UUID of the user", alias="userUuid")],
|
|
start: Annotated[str, Query(description="Start date")],
|
|
end: Annotated[str, Query(description="End date")],
|
|
) -> GetUserUsageByRangeResponseDto:
|
|
"""Get User Usage by Range (Legacy - Deprecated)"""
|
|
...
|
|
|
|
@get("/bandwidth-stats/nodes/{nodeUuid}/users/legacy", response_class=GetNodeUserUsageByRangeResponseDto)
|
|
async def get_node_user_usage_legacy_old(
|
|
self,
|
|
node_uuid: Annotated[str, Path(description="UUID of the node", alias="nodeUuid")],
|
|
start: Annotated[str, Query(description="Start date")],
|
|
end: Annotated[str, Query(description="End date")],
|
|
) -> GetNodeUserUsageByRangeResponseDto:
|
|
"""Get Node User Usage by Range and Node UUID (Legacy - Deprecated)"""
|
|
...
|
|
|
|
# ============ New Stats Endpoints ============
|
|
|
|
@get("/bandwidth-stats/nodes/realtime", response_class=GetStatsNodesRealtimeUsageResponseDto)
|
|
async def get_nodes_realtime_usage(
|
|
self,
|
|
) -> GetStatsNodesRealtimeUsageResponseDto:
|
|
"""Get Nodes Realtime Usage"""
|
|
...
|
|
|
|
@get("/bandwidth-stats/nodes/{uuid}/users/legacy", response_class=GetLegacyStatsNodesUsersUsageResponseDto)
|
|
async def get_node_users_usage_legacy_stats(
|
|
self,
|
|
uuid: Annotated[str, Path(description="UUID of the node")],
|
|
start: Annotated[str, Query(description="Start date")],
|
|
end: Annotated[str, Query(description="End date")],
|
|
) -> GetLegacyStatsNodesUsersUsageResponseDto:
|
|
"""Get Node Users Usage by Range and Node UUID (Legacy Stats)"""
|
|
...
|
|
|
|
@get("/bandwidth-stats/nodes/{uuid}/users", response_class=GetStatsNodeUsersUsageResponseDto)
|
|
async def get_stats_node_users_usage(
|
|
self,
|
|
uuid: Annotated[str, Path(description="UUID of the node")],
|
|
top_users_limit: Annotated[int, Query(description="Limit of top users to return", alias="topUsersLimit")],
|
|
start: Annotated[str, Query(description="Start date")],
|
|
end: Annotated[str, Query(description="End date")],
|
|
) -> GetStatsNodeUsersUsageResponseDto:
|
|
"""Get Node Users Usage by Node UUID"""
|
|
...
|
|
|
|
@post("/bandwidth-stats/nodes/users", response_class=GetStatsNodesUsersUsageResponseDto)
|
|
async def get_stats_nodes_users_usage(
|
|
self,
|
|
body: Annotated[GetStatsNodesUsersUsageRequestDto, PydanticBody()],
|
|
top_users_limit: Annotated[int, Query(description="Limit of top users to return", alias="topUsersLimit")],
|
|
start: Annotated[str, Query(description="Start date (YYYY-MM-DD)")],
|
|
end: Annotated[str, Query(description="End date (YYYY-MM-DD)")],
|
|
) -> GetStatsNodesUsersUsageResponseDto:
|
|
"""Get Nodes Users Usage by Nodes UUIDs"""
|
|
...
|
|
|
|
@get("/bandwidth-stats/users/{uuid}", response_class=GetStatsUserUsageResponseDto)
|
|
async def get_stats_user_usage(
|
|
self,
|
|
uuid: Annotated[str, Path(description="UUID of the user")],
|
|
top_nodes_limit: Annotated[int, Query(description="Limit of top nodes to return", alias="topNodesLimit")],
|
|
start: Annotated[str, Query(description="Start date")],
|
|
end: Annotated[str, Query(description="End date")],
|
|
) -> GetStatsUserUsageResponseDto:
|
|
"""Get User Usage by Range"""
|
|
...
|
|
|
|
@get("/bandwidth-stats/nodes", response_class=GetStatsNodesUsageResponseDto)
|
|
async def get_stats_nodes_usage(
|
|
self,
|
|
top_nodes_limit: Annotated[int, Query(description="Limit of top nodes to return", alias="topNodesLimit")],
|
|
start: Annotated[str, Query(description="Start date")],
|
|
end: Annotated[str, Query(description="End date")],
|
|
) -> GetStatsNodesUsageResponseDto:
|
|
"""Get Nodes Usage by Range"""
|
|
...
|
|
|
|
@get("/bandwidth-stats/users/{uuid}/legacy", response_class=GetLegacyStatsUserUsageResponseDto)
|
|
async def get_user_usage_legacy_stats(
|
|
self,
|
|
uuid: Annotated[str, Path(description="UUID of the user")],
|
|
start: Annotated[str, Query(description="Start date")],
|
|
end: Annotated[str, Query(description="End date")],
|
|
) -> GetLegacyStatsUserUsageResponseDto:
|
|
"""Get User Usage by Range (Legacy Stats)"""
|
|
... |