sukjenogi-backend/app/services/friend_service.py

212 lines
6.9 KiB
Python

from sqlalchemy.orm import Session, aliased
from sqlalchemy import select
from app.models.friend import FriendRequest, Friend, FriendRequestStatus
from app.models.user import User
from app.models.character import Character, CharacterHomework
from app.models.homework import HomeworkType
from fastapi import HTTPException, status
from datetime import datetime
def send_friend_request(db: Session, from_user_id: int, to_user_email: str):
to_user = db.query(User).filter(User.email == to_user_email).first()
if not to_user:
raise HTTPException(status_code=404, detail="해당 이메일의 유저를 찾을 수 없습니다.")
if to_user.id == from_user_id:
raise HTTPException(status_code=400, detail="자기 자신에게 친구 요청을 보낼 수 없습니다.")
# 이미 친구인지 확인
user_ids = sorted([from_user_id, to_user.id])
existing_friend = db.query(Friend).filter(
Friend.user_id_1 == user_ids[0],
Friend.user_id_2 == user_ids[1]
).first()
if existing_friend:
raise HTTPException(status_code=400, detail="이미 친구 상태입니다.")
# 이미 pending 요청이 있는지 확인
existing_request = db.query(FriendRequest).filter(
FriendRequest.from_user_id == from_user_id,
FriendRequest.to_user_id == to_user.id,
FriendRequest.status == FriendRequestStatus.pending
).first()
if existing_request:
raise HTTPException(status_code=400, detail="이미 친구 요청을 보낸 상태입니다.")
friend_request = FriendRequest(
from_user_id=from_user_id,
to_user_id=to_user.id,
)
db.add(friend_request)
db.commit()
db.refresh(friend_request)
return friend_request
def get_received_requests(db: Session, user_id: int):
sender = aliased(User)
receiver = aliased(User)
stmt = (
select(
FriendRequest.id,
FriendRequest.from_user_id,
FriendRequest.to_user_id,
sender.email.label("from_user_email"),
receiver.email.label("to_user_email"),
FriendRequest.status,
FriendRequest.created_at,
FriendRequest.updated_at,
)
.join(sender, FriendRequest.from_user_id == sender.id)
.join(receiver, FriendRequest.to_user_id == receiver.id)
.where(
FriendRequest.to_user_id == user_id,
FriendRequest.status == FriendRequestStatus.pending,
)
)
return db.execute(stmt).mappings().all()
def get_sent_requests(db: Session, user_id: int):
sender = aliased(User)
receiver = aliased(User)
stmt = (
select(
FriendRequest.id,
FriendRequest.from_user_id,
FriendRequest.to_user_id,
sender.email.label("from_user_email"),
receiver.email.label("to_user_email"),
FriendRequest.status,
FriendRequest.created_at,
FriendRequest.updated_at,
)
.join(sender, FriendRequest.from_user_id == sender.id)
.join(receiver, FriendRequest.to_user_id == receiver.id)
.where(
FriendRequest.from_user_id == user_id,
FriendRequest.status == FriendRequestStatus.pending,
)
)
return db.execute(stmt).mappings().all()
def cancel_sent_request(db: Session, request_id: int, user_id: int):
request = db.query(FriendRequest).filter(
FriendRequest.id == request_id,
FriendRequest.from_user_id == user_id
).first()
if not request:
raise HTTPException(status_code=404, detail="요청을 찾을 수 없습니다.")
request.status = FriendRequestStatus.cancelled
request.updated_at = datetime.utcnow()
db.commit()
def respond_to_request(db: Session, request_id: int, user_id: int, accept: bool):
request = db.query(FriendRequest).filter(
FriendRequest.id == request_id,
FriendRequest.to_user_id == user_id,
FriendRequest.status == FriendRequestStatus.pending
).first()
if not request:
raise HTTPException(status_code=404, detail="요청을 찾을 수 없습니다.")
request.status = FriendRequestStatus.accepted if accept else FriendRequestStatus.rejected
request.updated_at = datetime.utcnow()
# 친구 수락 시 friends 테이블에도 저장
if accept:
user_ids = sorted([request.from_user_id, request.to_user_id])
friend = Friend(
user_id_1=user_ids[0],
user_id_2=user_ids[1]
)
db.add(friend)
db.commit()
def get_friend_list(db: Session, user_id: int):
friends = db.query(Friend).filter(
(Friend.user_id_1 == user_id) | (Friend.user_id_2 == user_id)
).all()
result = []
for f in friends:
friend_id = f.user_id_2 if f.user_id_1 == user_id else f.user_id_1
friend = db.query(User).filter(User.id == friend_id).first()
friend_email = friend.email if friend else None
result.append({"id": friend_id, "email": friend_email})
return result
def get_public_characters_of_friend(db: Session, current_user_id: int, friend_id: int):
# 친구 관계 확인
user_ids = sorted([current_user_id, friend_id])
is_friend = db.query(Friend).filter(
Friend.user_id_1 == user_ids[0],
Friend.user_id_2 == user_ids[1]
).first()
if not is_friend:
raise HTTPException(status_code=403, detail="친구가 아닙니다.")
# 공개된 캐릭터 목록
characters = db.query(Character).filter(
Character.user_id == friend_id,
Character.is_public == True
).all()
return characters
def get_public_homeworks_of_friend_character(
db: Session,
current_user_id: int,
friend_id: int,
character_id: int
):
# 1. 친구인지 확인
user_ids = sorted([current_user_id, friend_id])
is_friend = db.query(Friend).filter(
Friend.user_id_1 == user_ids[0],
Friend.user_id_2 == user_ids[1]
).first()
if not is_friend:
raise HTTPException(status_code=403, detail="친구가 아닙니다.")
# 2. 해당 캐릭터가 공개인지 확인
character = db.query(Character).filter(
Character.id == character_id,
Character.user_id == friend_id,
Character.is_public == True
).first()
if not character:
raise HTTPException(status_code=404, detail="공개된 캐릭터를 찾을 수 없습니다.")
# 3. 공개된 숙제만 조회
results = db.query(HomeworkType).join(CharacterHomework).filter(
CharacterHomework.character_id == character_id,
HomeworkType.is_public == True
).all()
return results
def delete_friend(db: Session, user_id: int, friend_id: int):
user_ids = sorted([user_id, friend_id])
friend = db.query(Friend).filter(
Friend.user_id_1 == user_ids[0],
Friend.user_id_2 == user_ids[1]
).first()
if not friend:
raise HTTPException(status_code=404, detail="친구 관계가 존재하지 않습니다.")
db.delete(friend)
db.commit()