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="已拒绝好友申请",
|
|||
|
|
)
|