122 lines
3.6 KiB
Python
122 lines
3.6 KiB
Python
from __future__ import annotations
|
|
|
|
from typing import TYPE_CHECKING
|
|
|
|
from yuxi.utils.logging_config import logger
|
|
|
|
if TYPE_CHECKING:
|
|
from nio import AsyncClient
|
|
|
|
|
|
_DIRECT_ROOM_TYPE = "m.direct"
|
|
|
|
|
|
async def inspect_direct_room(
|
|
client: AsyncClient,
|
|
room_id: str,
|
|
) -> dict:
|
|
try:
|
|
members_resp = await client.joined_members(room_id)
|
|
members = getattr(members_resp, "members", [])
|
|
|
|
name_resp = await client.room_get_state_event(room_id, "m.room.name")
|
|
name = getattr(name_resp, "name", "") if name_resp else ""
|
|
|
|
join_rules = await client.room_get_state_event(room_id, "m.room.join_rules")
|
|
rule = getattr(join_rules, "join_rule", "") if join_rules else ""
|
|
|
|
return {
|
|
"room_id": room_id,
|
|
"name": name,
|
|
"member_count": len(members),
|
|
"join_rule": rule,
|
|
"is_direct": _is_direct_room(client, room_id),
|
|
}
|
|
except Exception as e:
|
|
logger.debug(f"Matrix direct room inspect failed for {room_id}: {e}")
|
|
return {"room_id": room_id, "error": str(e)}
|
|
|
|
|
|
async def repair_direct_room(
|
|
client: AsyncClient,
|
|
room_id: str,
|
|
target_user_id: str,
|
|
) -> dict:
|
|
try:
|
|
await client.room_set_account_data(
|
|
room_id=room_id,
|
|
event_type="m.direct",
|
|
content={"room_id": room_id, "user_id": target_user_id},
|
|
)
|
|
|
|
return {
|
|
"status": "repaired",
|
|
"room_id": room_id,
|
|
"user_id": target_user_id,
|
|
"action": "set_account_data_m.direct",
|
|
}
|
|
except Exception as e:
|
|
logger.error(f"Matrix direct room repair failed for {room_id}: {e}")
|
|
return {"status": "error", "room_id": room_id, "error": str(e)}
|
|
|
|
|
|
async def promote_room_to_direct(
|
|
client: AsyncClient,
|
|
room_id: str,
|
|
user_id: str,
|
|
) -> dict:
|
|
try:
|
|
direct_rooms = await client.get_account_data(_DIRECT_ROOM_TYPE)
|
|
current = getattr(direct_rooms, "content", {}) if direct_rooms else {}
|
|
|
|
current.setdefault(user_id, [])
|
|
if room_id not in current[user_id]:
|
|
current[user_id].append(room_id)
|
|
|
|
await client.set_account_data(_DIRECT_ROOM_TYPE, current)
|
|
|
|
return {
|
|
"status": "promoted",
|
|
"room_id": room_id,
|
|
"user_id": user_id,
|
|
}
|
|
except Exception as e:
|
|
logger.error(f"Matrix promote to direct room failed: {e}")
|
|
return {"status": "error", "error": str(e)}
|
|
|
|
|
|
async def demote_direct_room(
|
|
client: AsyncClient,
|
|
room_id: str,
|
|
user_id: str,
|
|
) -> dict:
|
|
try:
|
|
direct_rooms = await client.get_account_data(_DIRECT_ROOM_TYPE)
|
|
current = getattr(direct_rooms, "content", {}) if direct_rooms else {}
|
|
|
|
if user_id in current and room_id in current[user_id]:
|
|
current[user_id].remove(room_id)
|
|
if not current[user_id]:
|
|
del current[user_id]
|
|
|
|
await client.set_account_data(_DIRECT_ROOM_TYPE, current)
|
|
|
|
return {"status": "demoted", "room_id": room_id, "user_id": user_id}
|
|
except Exception as e:
|
|
logger.error(f"Matrix demote direct room failed: {e}")
|
|
return {"status": "error", "error": str(e)}
|
|
|
|
|
|
def _is_direct_room(client: AsyncClient, room_id: str) -> bool:
|
|
try:
|
|
account_data = client.account_data if client else {}
|
|
if account_data:
|
|
direct_data = account_data.get("m.direct", {})
|
|
if isinstance(direct_data, dict):
|
|
for room_ids in direct_data.values():
|
|
if isinstance(room_ids, list) and room_id in room_ids:
|
|
return True
|
|
except Exception:
|
|
pass
|
|
return False
|