"""好友路由""" from fastapi import APIRouter, Depends, HTTPException from sqlalchemy.ext.asyncio import AsyncSession from app.dependencies import get_db, get_current_user from app.models.user import User from app.schemas.friend import FriendRequestCreate, FriendRead, FriendRequestRead, RemarkUpdate from app.services.friend_service import FriendService from app.websocket.events import EventType from app.websocket.manager import manager router = APIRouter() @router.get("/", response_model=list[dict]) async def list_friends( user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ): """获取好友列表""" service = FriendService(db) return await service.get_friends(user.id) @router.get("/requests", response_model=list[dict]) async def list_requests( user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ): """获取待处理的好友请求""" service = FriendService(db) return await service.get_pending_requests(user.id) @router.post("/request") async def send_friend_request( req: FriendRequestCreate, user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ): """发送好友请求""" service = FriendService(db) try: await service.send_request(user.id, req.to_user_id, req.message) # 通知接收者 await manager.send_to_user(req.to_user_id, EventType.FRIEND_REQUEST, { "from_user_id": user.id, "from_username": user.username, "from_nickname": user.nickname, "from_avatar": user.avatar_url, "message": req.message, }) return {"success": True, "message": "好友请求已发送"} except ValueError as e: raise HTTPException(status_code=400, detail=str(e)) @router.put("/{friend_user_id}/remark") async def update_friend_remark( friend_user_id: str, req: RemarkUpdate, user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ): """修改好友备注""" service = FriendService(db) try: await service.update_remark(user.id, friend_user_id, req.remark) return {"success": True, "message": "备注已更新"} except ValueError as e: raise HTTPException(status_code=400, detail=str(e)) @router.put("/request/{request_id}/accept") async def accept_friend_request( request_id: str, user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ): """接受好友请求""" service = FriendService(db) try: # Get request details before accepting to know who sent it request = await service.get_pending_requests(user.id) from_user_id = None for r in request: if r["id"] == request_id: from_user_id = r["from_user_id"] break await service.accept_request(request_id, user.id) # Notify the requester that their request was accepted if from_user_id: await manager.send_to_user(from_user_id, EventType.FRIEND_ACCEPTED, { "accepted_by_user_id": user.id, "accepted_by_username": user.username, "accepted_by_nickname": user.nickname, }) return {"success": True, "message": "已添加好友"} except ValueError as e: raise HTTPException(status_code=400, detail=str(e)) @router.put("/request/{request_id}/reject") async def reject_friend_request( request_id: str, user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ): """拒绝好友请求""" service = FriendService(db) try: await service.reject_request(request_id, user.id) return {"success": True, "message": "已拒绝"} except ValueError as e: raise HTTPException(status_code=400, detail=str(e)) @router.delete("/{friend_id}") async def remove_friend( friend_id: str, user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ): """删除好友""" service = FriendService(db) await service.remove_friend(user.id, friend_id) return {"success": True, "message": "已删除好友"} # ============ 好友分组/标签 ============ @router.get("/tags/list") async def list_tags( user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ): """获取我的好友标签""" from app.models.friend_tag import FriendTag result = await db.execute( select(FriendTag).where(FriendTag.user_id == user.id).order_by(FriendTag.created_at) ) return [{"id": t.id, "name": t.name} for t in result.scalars().all()] @router.post("/tags/create") async def create_tag( body: dict, user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ): """创建好友标签""" from app.models.friend_tag import FriendTag import uuid tag = FriendTag(id=str(uuid.uuid4()), user_id=user.id, name=body.get("name", "")[:30]) db.add(tag) await db.flush() return {"id": tag.id, "name": tag.name} @router.delete("/tags/{tag_id}") async def delete_tag( tag_id: str, user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ): """删除好友标签""" from app.models.friend_tag import FriendTag from sqlalchemy import delete as sql_delete await db.execute(sql_delete(FriendTag).where(FriendTag.id == tag_id, FriendTag.user_id == user.id)) return {"success": True} @router.put("/{friend_id}/tags") async def assign_tags( friend_id: str, body: dict, user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ): """给好友分配标签(覆盖式)""" from app.models.friend_tag import FriendTag, FriendTagAssignment from app.models.friend import Friend from sqlalchemy import delete as sql_delete # 找到该好友关系记录 fr = await db.execute( select(Friend).where(Friend.user_id == user.id, Friend.friend_user_id == friend_id) ) friendship = fr.scalars().first() if not friendship: raise HTTPException(status_code=404, detail="好友不存在") # 清空旧分配 await db.execute( sql_delete(FriendTagAssignment).where(FriendTagAssignment.friend_id == friendship.id) ) # 新分配 tag_ids = body.get("tag_ids", []) import uuid for tid in tag_ids: db.add(FriendTagAssignment(id=str(uuid.uuid4()), friend_id=friendship.id, tag_id=tid)) return {"success": True}