1.6
This commit is contained in:
@@ -0,0 +1,105 @@
|
||||
"""时光胶囊服务(懒解锁)"""
|
||||
|
||||
import uuid
|
||||
from datetime import datetime
|
||||
|
||||
from sqlalchemy import select, or_
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from app.models.time_capsule import TimeCapsule
|
||||
from app.models.friend import Friend
|
||||
|
||||
|
||||
class CapsuleService:
|
||||
def __init__(self, db: AsyncSession):
|
||||
self.db = db
|
||||
|
||||
async def create_capsule(self, sender_id: str, recipient_id: str, title: str,
|
||||
content: str, unlock_at: datetime,
|
||||
mood: str | None = None) -> dict:
|
||||
"""创建时光胶囊"""
|
||||
# 校验解锁时间是未来
|
||||
if unlock_at <= datetime.utcnow():
|
||||
raise ValueError("解锁时间必须是未来时间")
|
||||
|
||||
# 校验收件人:自己 或 好友
|
||||
if recipient_id != sender_id:
|
||||
friend_result = await self.db.execute(
|
||||
select(Friend).where(
|
||||
Friend.user_id == sender_id,
|
||||
Friend.friend_user_id == recipient_id,
|
||||
)
|
||||
)
|
||||
if not friend_result.scalars().first():
|
||||
raise ValueError("只能给好友或自己寄胶囊")
|
||||
|
||||
capsule = TimeCapsule(
|
||||
id=str(uuid.uuid4()),
|
||||
sender_id=sender_id,
|
||||
recipient_id=recipient_id,
|
||||
title=title,
|
||||
content=content,
|
||||
unlock_at=unlock_at,
|
||||
mood=mood,
|
||||
)
|
||||
self.db.add(capsule)
|
||||
await self.db.flush()
|
||||
return self._capsule_to_dict(capsule, sender_id)
|
||||
|
||||
async def get_capsules(self, user_id: str) -> list[dict]:
|
||||
"""获取我发的 + 我收的胶囊"""
|
||||
result = await self.db.execute(
|
||||
select(TimeCapsule).where(
|
||||
or_(
|
||||
TimeCapsule.sender_id == user_id,
|
||||
TimeCapsule.recipient_id == user_id,
|
||||
)
|
||||
).order_by(TimeCapsule.unlock_at.desc())
|
||||
)
|
||||
return [self._capsule_to_dict(c, user_id) for c in result.scalars().all()]
|
||||
|
||||
async def get_capsule(self, user_id: str, capsule_id: str) -> dict:
|
||||
"""获取单个胶囊"""
|
||||
result = await self.db.execute(
|
||||
select(TimeCapsule).where(TimeCapsule.id == capsule_id)
|
||||
)
|
||||
capsule = result.scalars().first()
|
||||
if not capsule:
|
||||
raise ValueError("胶囊不存在")
|
||||
if capsule.sender_id != user_id and capsule.recipient_id != user_id:
|
||||
raise ValueError("无权查看此胶囊")
|
||||
|
||||
# 若已解锁且收件人首次查看,标记 opened
|
||||
now = datetime.utcnow()
|
||||
if now >= capsule.unlock_at and capsule.recipient_id == user_id and not capsule.is_opened:
|
||||
capsule.is_opened = True
|
||||
await self.db.flush()
|
||||
return self._capsule_to_dict(capsule, user_id)
|
||||
|
||||
def _capsule_to_dict(self, capsule: TimeCapsule, viewer_id: str) -> dict:
|
||||
"""转字典,应用懒解锁:未到期则隐藏内容"""
|
||||
now = datetime.utcnow()
|
||||
locked = now < capsule.unlock_at
|
||||
seconds_left = int((capsule.unlock_at - now).total_seconds()) if locked else 0
|
||||
|
||||
# 内容可见性:发送人可看自己的(即使锁定);收件人锁定时不可看
|
||||
can_see_content = (
|
||||
capsule.sender_id == viewer_id # 发送人始终能看自己发的
|
||||
or not locked # 已解锁
|
||||
)
|
||||
|
||||
return {
|
||||
"id": capsule.id,
|
||||
"sender_id": capsule.sender_id,
|
||||
"recipient_id": capsule.recipient_id,
|
||||
"is_mine_sent": capsule.sender_id == viewer_id,
|
||||
"is_mine_received": capsule.recipient_id == viewer_id,
|
||||
"title": capsule.title,
|
||||
"content": capsule.content if can_see_content else None,
|
||||
"unlock_at": capsule.unlock_at.isoformat(),
|
||||
"mood": capsule.mood,
|
||||
"locked": locked,
|
||||
"seconds_left": seconds_left,
|
||||
"is_opened": capsule.is_opened,
|
||||
"created_at": capsule.created_at.isoformat(),
|
||||
}
|
||||
Reference in New Issue
Block a user