98 lines
3.5 KiB
Python
98 lines
3.5 KiB
Python
"""念念回音服务"""
|
|
|
|
import hashlib
|
|
import uuid
|
|
from datetime import datetime
|
|
|
|
from sqlalchemy import select, or_
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
|
from app.models.miss_echo import MissEcho
|
|
from app.models.user import User
|
|
from app.websocket.events import EventType
|
|
from app.websocket.manager import manager
|
|
|
|
|
|
class EchoService:
|
|
def __init__(self, db: AsyncSession):
|
|
self.db = db
|
|
|
|
async def send_echo(self, from_user_id: str, to_user_id: str,
|
|
message: str | None = None) -> dict:
|
|
"""发送一片回音叶"""
|
|
if from_user_id == to_user_id:
|
|
raise ValueError("不能给自己回音")
|
|
|
|
# 校验目标用户存在
|
|
target_result = await self.db.execute(select(User).where(User.id == to_user_id))
|
|
if not target_result.scalars().first():
|
|
raise ValueError("目标用户不存在")
|
|
|
|
# 派生叶子种子
|
|
today = datetime.utcnow().strftime("%Y%m%d")
|
|
seed = hashlib.md5(f"echo:{from_user_id}:{to_user_id}:{today}".encode()).hexdigest()[:16]
|
|
|
|
is_online = manager.is_online(to_user_id)
|
|
|
|
echo = MissEcho(
|
|
id=str(uuid.uuid4()),
|
|
from_user_id=from_user_id,
|
|
to_user_id=to_user_id,
|
|
leaf_seed=seed,
|
|
message=message,
|
|
delivered_online=is_online,
|
|
)
|
|
self.db.add(echo)
|
|
await self.db.flush()
|
|
|
|
# 发送者信息
|
|
from_result = await self.db.execute(select(User).where(User.id == from_user_id))
|
|
from_user = from_result.scalars().first()
|
|
|
|
payload = {
|
|
"id": echo.id,
|
|
"from_user_id": from_user_id,
|
|
"from_username": from_user.username if from_user else "未知",
|
|
"from_nickname": from_user.nickname if from_user else None,
|
|
"from_avatar": from_user.avatar_url if from_user else None,
|
|
"leaf_seed": seed,
|
|
"message": message,
|
|
"delivered_online": is_online,
|
|
"created_at": echo.created_at.isoformat(),
|
|
}
|
|
|
|
# 在线则实时推送,离线则在用户下次打开时收到(落入花园)
|
|
if is_online:
|
|
await manager.send_to_user(to_user_id, EventType.ECHO_SEND, payload)
|
|
|
|
return payload
|
|
|
|
async def get_echoes(self, user_id: str, limit: int = 30) -> list[dict]:
|
|
"""获取我收到的回音(花园里飘落的叶子)"""
|
|
result = await self.db.execute(
|
|
select(MissEcho).where(
|
|
or_(
|
|
MissEcho.to_user_id == user_id,
|
|
MissEcho.from_user_id == user_id,
|
|
)
|
|
).order_by(MissEcho.created_at.desc()).limit(limit)
|
|
)
|
|
echoes = []
|
|
for e in result.scalars().all():
|
|
from_result = await self.db.execute(select(User).where(User.id == e.from_user_id))
|
|
fu = from_result.scalars().first()
|
|
echoes.append({
|
|
"id": e.id,
|
|
"from_user_id": e.from_user_id,
|
|
"to_user_id": e.to_user_id,
|
|
"from_username": fu.username if fu else "未知",
|
|
"from_nickname": fu.nickname if fu else None,
|
|
"from_avatar": fu.avatar_url if fu else None,
|
|
"leaf_seed": e.leaf_seed,
|
|
"message": e.message,
|
|
"delivered_online": e.delivered_online,
|
|
"is_received": e.to_user_id == user_id,
|
|
"created_at": e.created_at.isoformat(),
|
|
})
|
|
return echoes
|