fix: support nested remnawave activity fields

This commit is contained in:
3252a8
2026-06-05 16:19:53 +03:00
parent 6890b58ced
commit 6913676420
2 changed files with 51 additions and 35 deletions
+32 -22
View File
@@ -110,15 +110,24 @@ def _panel_nested_dicts(panel_user: Dict[str, Any], keys: Tuple[str, ...]) -> Li
return out
def _panel_user_connection_containers(panel_user: Dict[str, Any]) -> List[Dict[str, Any]]:
traffic_containers = _panel_nested_dicts(panel_user, _PANEL_TRAFFIC_OBJECT_KEYS)
marker_containers = _panel_nested_dicts(
panel_user,
_PANEL_CONNECTION_MARKER_OBJECT_KEYS,
)
for traffic_container in traffic_containers:
marker_containers.extend(
_panel_nested_dicts(traffic_container, _PANEL_CONNECTION_MARKER_OBJECT_KEYS)
)
return [panel_user, *traffic_containers, *marker_containers]
def _panel_user_last_connected_at(panel_user_data: Any) -> Optional[str]:
panel_user = _panel_user_payload(panel_user_data)
if not panel_user:
return None
containers = [
panel_user,
*_panel_nested_dicts(panel_user, _PANEL_CONNECTION_MARKER_OBJECT_KEYS),
]
for container in containers:
for container in _panel_user_connection_containers(panel_user):
for key in _PANEL_LAST_CONNECTED_KEYS:
connected_at = _coerce_panel_datetime(container.get(key))
if connected_at:
@@ -137,33 +146,34 @@ def _panel_user_positive_traffic_bytes(panel_user: Dict[str, Any]) -> bool:
def _panel_user_has_connection_marker(panel_user: Dict[str, Any]) -> bool:
for key in _PANEL_CONNECTION_MARKER_KEYS:
if key in panel_user:
return True
for key in _PANEL_CONNECTION_MARKER_OBJECT_KEYS:
if key in panel_user:
return True
for container in _panel_user_connection_containers(panel_user):
for key in _PANEL_CONNECTION_MARKER_KEYS:
if key in container:
return True
for container in [panel_user, *_panel_nested_dicts(panel_user, _PANEL_TRAFFIC_OBJECT_KEYS)]:
for key in _PANEL_CONNECTION_MARKER_OBJECT_KEYS:
if key in container:
return True
return False
def _panel_user_has_connected_marker_value(panel_user: Dict[str, Any]) -> bool:
containers = [
panel_user,
*_panel_nested_dicts(panel_user, _PANEL_CONNECTION_MARKER_OBJECT_KEYS),
]
for container in containers:
for container in _panel_user_connection_containers(panel_user):
for key in (*_PANEL_LAST_CONNECTED_KEYS, "firstConnectedAt", "first_connected_at"):
if _coerce_panel_datetime(container.get(key)):
return True
for key in ("lastConnectedNodeUuid", "last_connected_node_uuid"):
if str(container.get(key) or "").strip():
return True
for key in _PANEL_CONNECTION_MARKER_OBJECT_KEYS:
marker = panel_user.get(key)
if isinstance(marker, dict) and any(str(value or "").strip() for value in marker.values()):
return True
if marker and not isinstance(marker, dict):
return True
for container in [panel_user, *_panel_nested_dicts(panel_user, _PANEL_TRAFFIC_OBJECT_KEYS)]:
for key in _PANEL_CONNECTION_MARKER_OBJECT_KEYS:
marker = container.get(key)
if isinstance(marker, dict) and any(
str(value or "").strip() for value in marker.values()
):
return True
if marker and not isinstance(marker, dict):
return True
return False
+19 -13
View File
@@ -72,7 +72,7 @@ class AdminPanelActivityTests(unittest.IsolatedAsyncioTestCase):
def test_panel_activity_detects_connected_and_never_connected_users(self):
self.assertEqual(
common_module._panel_user_connection_activity(
{"onlineAt": "2026-06-05T12:00:00Z"}
{"userTraffic": {"onlineAt": "2026-06-05T12:00:00Z"}}
),
{
"status": "connected",
@@ -82,10 +82,12 @@ class AdminPanelActivityTests(unittest.IsolatedAsyncioTestCase):
self.assertEqual(
common_module._panel_user_connection_activity(
{
"onlineAt": None,
"firstConnectedAt": None,
"lastConnectedNode": None,
"userTraffic": {"lifetimeUsedTrafficBytes": 0},
"userTraffic": {
"onlineAt": None,
"firstConnectedAt": None,
"lastConnectedNodeUuid": None,
"lifetimeUsedTrafficBytes": 0,
},
}
),
{"status": "never", "last_connected_at": None},
@@ -115,15 +117,19 @@ class AdminPanelActivityTests(unittest.IsolatedAsyncioTestCase):
async def get_user_by_uuid(panel_uuid):
return {
"never-panel": {
"onlineAt": None,
"firstConnectedAt": None,
"lastConnectedNode": None,
"userTraffic": {
"onlineAt": None,
"firstConnectedAt": None,
"lastConnectedNodeUuid": None,
},
},
"connected-panel": {"onlineAt": "2026-06-05T12:00:00Z"},
"connected-panel": {"userTraffic": {"onlineAt": "2026-06-05T12:00:00Z"}},
"also-never-panel": {
"onlineAt": None,
"firstConnectedAt": None,
"lastConnectedNode": None,
"userTraffic": {
"onlineAt": None,
"firstConnectedAt": None,
"lastConnectedNodeUuid": None,
},
},
"also-connected-panel": {
"userTraffic": {"lifetimeUsedTrafficBytes": 1},
@@ -172,7 +178,7 @@ class AdminPanelActivityTests(unittest.IsolatedAsyncioTestCase):
get_user_by_uuid=AsyncMock(
return_value={
"subscriptionUrl": "https://panel.example/sub/short",
"onlineAt": "2026-06-05T12:00:00Z",
"userTraffic": {"onlineAt": "2026-06-05T12:00:00Z"},
}
)
)