71 lines
1.9 KiB
Python
71 lines
1.9 KiB
Python
|
|
from __future__ import annotations
|
||
|
|
|
||
|
|
import logging
|
||
|
|
import time
|
||
|
|
from typing import Any
|
||
|
|
|
||
|
|
from yuxi.channels.models import ChatType
|
||
|
|
|
||
|
|
logger = logging.getLogger(__name__)
|
||
|
|
|
||
|
|
_CACHE_TTL_SUCCESS = 300
|
||
|
|
_CACHE_TTL_ERROR = 30
|
||
|
|
|
||
|
|
_room_kind_cache: dict[str, tuple[float, str | None]] = {}
|
||
|
|
|
||
|
|
|
||
|
|
async def resolve_room_kind(
|
||
|
|
client,
|
||
|
|
api_base: str,
|
||
|
|
token: str,
|
||
|
|
api_user: str = "",
|
||
|
|
api_password: str = "",
|
||
|
|
) -> dict[str, Any]:
|
||
|
|
now = time.time()
|
||
|
|
cached = _room_kind_cache.get(token)
|
||
|
|
if cached:
|
||
|
|
cached_ts, cached_kind = cached
|
||
|
|
if cached_kind is not None and now - cached_ts < _CACHE_TTL_SUCCESS:
|
||
|
|
return _kind_result(cached_kind)
|
||
|
|
if cached_kind is None and now - cached_ts < _CACHE_TTL_ERROR:
|
||
|
|
return _kind_result(None)
|
||
|
|
|
||
|
|
try:
|
||
|
|
path = f"{api_base}/room/{token}"
|
||
|
|
result = await client.get(path)
|
||
|
|
ocs = result.get("ocs", {})
|
||
|
|
data = ocs.get("data", {})
|
||
|
|
room_type = data.get("type")
|
||
|
|
kind = _map_room_type(room_type)
|
||
|
|
_room_kind_cache[token] = (now, kind)
|
||
|
|
return _kind_result(kind)
|
||
|
|
except Exception as e:
|
||
|
|
logger.warning(f"[NextcloudTalk] Room type query failed for {token}: {e}")
|
||
|
|
_room_kind_cache[token] = (now, None)
|
||
|
|
return _kind_result(None)
|
||
|
|
|
||
|
|
|
||
|
|
def _map_room_type(room_type: int | None) -> str | None:
|
||
|
|
if room_type is None:
|
||
|
|
return None
|
||
|
|
if room_type in (1, 5, 6):
|
||
|
|
return "direct"
|
||
|
|
if room_type in (2, 3, 4):
|
||
|
|
return "group"
|
||
|
|
return None
|
||
|
|
|
||
|
|
|
||
|
|
def _kind_result(kind: str | None) -> dict[str, Any]:
|
||
|
|
if kind == "direct":
|
||
|
|
return {"kind": "direct", "chat_type": ChatType.DIRECT}
|
||
|
|
if kind == "group":
|
||
|
|
return {"kind": "group", "chat_type": ChatType.GROUP}
|
||
|
|
return {"kind": None, "chat_type": ChatType.GROUP, "source": "cache_fallback"}
|
||
|
|
|
||
|
|
|
||
|
|
def invalidate_room_cache(token: str | None = None) -> None:
|
||
|
|
if token:
|
||
|
|
_room_kind_cache.pop(token, None)
|
||
|
|
else:
|
||
|
|
_room_kind_cache.clear()
|