Files
chat/backend/app/services/friend_service.py
T
2026-06-12 23:14:12 +08:00

163 lines
5.7 KiB
Python

"""好友服务"""
import uuid
from datetime import datetime, timezone
from sqlalchemy import select, and_
from sqlalchemy.ext.asyncio import AsyncSession
from app.models.user import User
from app.models.friend import Friend
from app.models.friend_request import FriendRequest
class FriendService:
def __init__(self, db: AsyncSession):
self.db = db
async def send_request(self, from_user_id: str, to_user_id: str,
message: str | None = None) -> FriendRequest:
"""发送好友请求"""
if from_user_id == to_user_id:
raise ValueError("不能添加自己为好友")
# 检查目标用户是否存在
target = await self.db.execute(select(User).where(User.id == to_user_id))
if not target.scalars().first():
raise ValueError("目标用户不存在")
# 检查是否已是好友
existing = await self.db.execute(
select(Friend).where(
Friend.user_id == from_user_id,
Friend.friend_user_id == to_user_id,
)
)
if existing.scalars().first():
raise ValueError("已经是好友了")
# 检查是否有待处理的请求
pending = await self.db.execute(
select(FriendRequest).where(
FriendRequest.from_user_id == from_user_id,
FriendRequest.to_user_id == to_user_id,
FriendRequest.status == "pending",
)
)
if pending.scalars().first():
raise ValueError("已发送过好友请求")
request = FriendRequest(
id=str(uuid.uuid4()),
from_user_id=from_user_id,
to_user_id=to_user_id,
message=message,
status="pending",
)
self.db.add(request)
return request
async def accept_request(self, request_id: str, user_id: str):
"""接受好友请求"""
result = await self.db.execute(
select(FriendRequest).where(FriendRequest.id == request_id)
)
request = result.scalars().first()
if not request:
raise ValueError("请求不存在")
if request.to_user_id != user_id:
raise ValueError("无权操作此请求")
if request.status != "pending":
raise ValueError("该请求已处理")
request.status = "accepted"
request.responded_at = datetime.utcnow()
# 创建双向好友关系
self.db.add(Friend(
id=str(uuid.uuid4()), user_id=request.from_user_id,
friend_user_id=request.to_user_id,
))
self.db.add(Friend(
id=str(uuid.uuid4()), user_id=request.to_user_id,
friend_user_id=request.from_user_id,
))
async def reject_request(self, request_id: str, user_id: str):
"""拒绝好友请求"""
result = await self.db.execute(
select(FriendRequest).where(FriendRequest.id == request_id)
)
request = result.scalars().first()
if not request:
raise ValueError("请求不存在")
if request.to_user_id != user_id:
raise ValueError("无权操作此请求")
request.status = "rejected"
request.responded_at = datetime.utcnow()
async def get_friends(self, user_id: str) -> list[dict]:
"""获取好友列表"""
result = await self.db.execute(
select(Friend).where(Friend.user_id == user_id)
)
friends = []
for friendship in result.scalars().all():
user_result = await self.db.execute(
select(User).where(User.id == friendship.friend_user_id)
)
user = user_result.scalars().first()
if user:
friends.append({
"id": friendship.id,
"friend_user_id": user.id,
"username": user.username,
"nickname": user.bio,
"avatar_url": user.avatar_url,
"remark": friendship.remark,
"status": user.status,
})
return friends
async def get_pending_requests(self, user_id: str) -> list[dict]:
"""获取待处理的好友请求"""
result = await self.db.execute(
select(FriendRequest).where(
FriendRequest.to_user_id == user_id,
FriendRequest.status == "pending",
).order_by(FriendRequest.created_at.desc())
)
requests = []
for req in result.scalars().all():
from_user = await self.db.execute(select(User).where(User.id == req.from_user_id))
fu = from_user.scalars().first()
requests.append({
"id": req.id,
"from_user_id": req.from_user_id,
"from_username": fu.username if fu else "未知",
"from_avatar": fu.avatar_url if fu else None,
"to_user_id": req.to_user_id,
"message": req.message,
"status": req.status,
"created_at": req.created_at,
})
return requests
async def remove_friend(self, user_id: str, friend_id: str):
"""删除好友"""
await self.db.execute(
select(Friend).where(
Friend.user_id == user_id,
Friend.friend_user_id == friend_id,
)
)
# 删除双向关系
from sqlalchemy import delete
await self.db.execute(
delete(Friend).where(
(Friend.user_id == user_id) & (Friend.friend_user_id == friend_id) |
(Friend.user_id == friend_id) & (Friend.friend_user_id == user_id)
)
)