163 lines
5.7 KiB
Python
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)
|
|
)
|
|
)
|