Files

191 lines
7.7 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
好友路由。
按“用户向博主申请、博主审批”实现(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="已拒绝好友申请",
)