191 lines
7.7 KiB
Python
191 lines
7.7 KiB
Python
"""
|
||
好友路由。
|
||
|
||
按“用户向博主申请、博主审批”实现(Friend.user_id 为申请人):
|
||
- POST /api/friend/apply 申请好友(登录用户;博主与已是好友的用户不可申请)
|
||
- GET /api/friend/status 查询当前用户的好友状态(none / pending / accepted / rejected)
|
||
- GET /api/friend/applications 好友申请列表(仅博主)
|
||
- POST /api/friend/{friend_id}/approve 审批通过(仅博主):申请人角色提升为 friend
|
||
- POST /api/friend/{friend_id}/reject 审批拒绝(仅博主)
|
||
"""
|
||
|
||
from fastapi import APIRouter, Depends, HTTPException, status
|
||
from sqlalchemy.orm import Session
|
||
|
||
from ..auth import get_current_user
|
||
from ..database import get_db
|
||
from ..models import (
|
||
FRIEND_STATUS_ACCEPTED,
|
||
FRIEND_STATUS_PENDING,
|
||
FRIEND_STATUS_REJECTED,
|
||
ROLE_BLOGGER,
|
||
ROLE_FRIEND,
|
||
Friend,
|
||
User,
|
||
)
|
||
from ..schemas import UnifiedResponse
|
||
|
||
router = APIRouter(prefix="/api/friend", tags=["friend"])
|
||
|
||
|
||
@router.post("/apply", response_model=UnifiedResponse)
|
||
def apply_friend(
|
||
current_user: User = Depends(get_current_user),
|
||
db: Session = Depends(get_db),
|
||
) -> UnifiedResponse:
|
||
"""申请好友:注册用户向博主发起好友申请。"""
|
||
if current_user.role == ROLE_BLOGGER:
|
||
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="博主无需申请好友")
|
||
if current_user.role == ROLE_FRIEND:
|
||
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="你们已经是好友")
|
||
|
||
record = db.query(Friend).filter(Friend.user_id == current_user.id).first()
|
||
if record is None:
|
||
# 首次申请:新建待审批记录
|
||
record = Friend(user_id=current_user.id, status=FRIEND_STATUS_PENDING)
|
||
db.add(record)
|
||
elif record.status == FRIEND_STATUS_PENDING:
|
||
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="申请已提交,请等待博主审批")
|
||
elif record.status == FRIEND_STATUS_ACCEPTED:
|
||
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="你们已经是好友")
|
||
else:
|
||
# 此前被拒绝:允许重新提交申请
|
||
record.status = FRIEND_STATUS_PENDING
|
||
db.commit()
|
||
db.refresh(record)
|
||
|
||
return UnifiedResponse(
|
||
success=True,
|
||
data={"id": record.id, "status": record.status},
|
||
message="申请成功,等待博主审批",
|
||
)
|
||
|
||
|
||
@router.get("/status", response_model=UnifiedResponse)
|
||
def get_friend_status(
|
||
current_user: User = Depends(get_current_user),
|
||
db: Session = Depends(get_db),
|
||
) -> UnifiedResponse:
|
||
"""查询当前用户的好友状态:none / pending / accepted / rejected(博主返回 blogger)。"""
|
||
if current_user.role == ROLE_BLOGGER:
|
||
return UnifiedResponse(success=True, data={"status": "blogger"}, message="获取成功")
|
||
if current_user.role == ROLE_FRIEND:
|
||
return UnifiedResponse(success=True, data={"status": "accepted"}, message="获取成功")
|
||
|
||
record = db.query(Friend).filter(Friend.user_id == current_user.id).first()
|
||
status_value = record.status if record is not None else "none"
|
||
return UnifiedResponse(success=True, data={"status": status_value}, message="获取成功")
|
||
|
||
|
||
@router.get("/list", response_model=UnifiedResponse)
|
||
def list_friends(
|
||
current_user: User = Depends(get_current_user),
|
||
db: Session = Depends(get_db),
|
||
) -> UnifiedResponse:
|
||
"""好友列表:博主查看全部已成为好友的用户;好友用户查看自己与博主的好友关系。"""
|
||
if current_user.role not in (ROLE_BLOGGER, ROLE_FRIEND):
|
||
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="登录并成为好友后可查看好友列表")
|
||
|
||
if current_user.role == ROLE_BLOGGER:
|
||
# 博主视角:所有已通过的好友申请,申请人即好友
|
||
records = db.query(Friend).filter(Friend.status == FRIEND_STATUS_ACCEPTED).all()
|
||
else:
|
||
# 好友视角:自己那条已通过的申请,对应好友为博主
|
||
records = db.query(Friend).filter(
|
||
Friend.user_id == current_user.id,
|
||
Friend.status == FRIEND_STATUS_ACCEPTED,
|
||
).all()
|
||
|
||
data = []
|
||
for record in records:
|
||
member = (
|
||
db.query(User).filter(User.id == record.user_id).first()
|
||
if current_user.role == ROLE_BLOGGER
|
||
else db.query(User).filter(User.role == ROLE_BLOGGER).first()
|
||
)
|
||
if member is None:
|
||
continue
|
||
data.append({
|
||
"id": member.id,
|
||
"username": member.username,
|
||
"avatar": member.avatar,
|
||
"bio": member.bio,
|
||
"friend_since": record.created_time,
|
||
})
|
||
return UnifiedResponse(success=True, data=data, message="获取成功")
|
||
|
||
|
||
@router.get("/applications", response_model=UnifiedResponse)
|
||
def list_applications(
|
||
current_user: User = Depends(get_current_user),
|
||
db: Session = Depends(get_db),
|
||
) -> UnifiedResponse:
|
||
"""好友申请列表:仅博主可查看全部申请记录。"""
|
||
if current_user.role != ROLE_BLOGGER:
|
||
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="只有博主可以查看好友申请")
|
||
records = db.query(Friend).order_by(Friend.id.asc()).all()
|
||
data = [
|
||
{
|
||
"id": r.id,
|
||
"user_id": r.user_id,
|
||
"username": r.user.username if r.user else None,
|
||
"email": r.user.email if r.user else None,
|
||
"status": r.status,
|
||
"created_time": r.created_time,
|
||
}
|
||
for r in records
|
||
]
|
||
return UnifiedResponse(success=True, data=data, message="获取成功")
|
||
|
||
|
||
@router.post("/{friend_id}/approve", response_model=UnifiedResponse)
|
||
def approve_friend(
|
||
friend_id: int,
|
||
current_user: User = Depends(get_current_user),
|
||
db: Session = Depends(get_db),
|
||
) -> UnifiedResponse:
|
||
"""审批通过好友申请:仅博主;通过后申请人角色提升为 friend。"""
|
||
if current_user.role != ROLE_BLOGGER:
|
||
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="只有博主可以审批好友申请")
|
||
record = db.query(Friend).filter(Friend.id == friend_id).first()
|
||
if record is None:
|
||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="好友申请不存在")
|
||
if record.status != FRIEND_STATUS_PENDING:
|
||
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="该申请已处理,不能重复审批")
|
||
|
||
applicant = db.query(User).filter(User.id == record.user_id).first()
|
||
record.status = FRIEND_STATUS_ACCEPTED
|
||
if applicant is not None and applicant.role != ROLE_BLOGGER:
|
||
applicant.role = ROLE_FRIEND
|
||
db.commit()
|
||
|
||
return UnifiedResponse(
|
||
success=True,
|
||
data={"id": record.id, "status": record.status},
|
||
message="已通过好友申请",
|
||
)
|
||
|
||
|
||
@router.post("/{friend_id}/reject", response_model=UnifiedResponse)
|
||
def reject_friend(
|
||
friend_id: int,
|
||
current_user: User = Depends(get_current_user),
|
||
db: Session = Depends(get_db),
|
||
) -> UnifiedResponse:
|
||
"""拒绝好友申请:仅博主。"""
|
||
if current_user.role != ROLE_BLOGGER:
|
||
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="只有博主可以审批好友申请")
|
||
record = db.query(Friend).filter(Friend.id == friend_id).first()
|
||
if record is None:
|
||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="好友申请不存在")
|
||
if record.status != FRIEND_STATUS_PENDING:
|
||
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="该申请已处理,不能重复操作")
|
||
|
||
record.status = FRIEND_STATUS_REJECTED
|
||
db.commit()
|
||
|
||
return UnifiedResponse(
|
||
success=True,
|
||
data={"id": record.id, "status": record.status},
|
||
message="已拒绝好友申请",
|
||
) |