Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feat] 게시물 좋아요 기능 구현 #28

Merged
merged 11 commits into from
Aug 26, 2024
Merged

This file was deleted.

This file was deleted.

This file was deleted.

15 changes: 15 additions & 0 deletions src/main/java/wanted/media/exception/CustomException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package wanted.media.exception;

import lombok.Getter;

@Getter
public class CustomException extends RuntimeException {
private final ErrorCode errorCode;
private String customMessage;

public CustomException(ErrorCode errorCode) {
super(errorCode.getMessage());
this.errorCode = errorCode;
this.customMessage = errorCode.getMessage();
}
}
11 changes: 6 additions & 5 deletions src/main/java/wanted/media/exception/ErrorCode.java
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
package wanted.media.exception;

import org.springframework.http.HttpStatus;

import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;

@Getter
@RequiredArgsConstructor
public enum ErrorCode {
ENTITY_NOT_FOUND(HttpStatus.NOT_FOUND, "존재하지 않는 엔티티입니다.");
ENTITY_NOT_FOUND(HttpStatus.NOT_FOUND, "존재하지 않는 엔티티입니다."),
// 클라이언트의 입력 값에 대한 일반적인 오류 (@PathVariable, @RequestParam가 잘못되었을 때)
INVALID_INPUT_VALUE(HttpStatus.BAD_REQUEST, "클라이언트의 입력 값을 확인해주세요.");

private final HttpStatus status;
private final String message;
private final HttpStatus status;
private final String message;
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,22 @@
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import wanted.media.exception.CustomException;
import wanted.media.exception.ErrorResponse;

@RestControllerAdvice
public class GlobalExceptionHandler {

@ExceptionHandler(BadRequestException.class)
public ResponseEntity<ErrorResponse> handleBadRequestException(BadRequestException e) {
return ResponseEntity.badRequest()
.body(new ErrorResponse(400, e.getMessage()));
}
@ExceptionHandler(BadRequestException.class)
public ResponseEntity<ErrorResponse> handleBadRequestException(BadRequestException e) {
return ResponseEntity.badRequest()
.body(new ErrorResponse(400, e.getMessage()));
}

@ExceptionHandler(CustomException.class)
protected ResponseEntity<ErrorResponse> handleCustomException(final CustomException e) {
return ResponseEntity
.status(e.getErrorCode().getStatus().value())
.body(new ErrorResponse(e.getErrorCode().getStatus().value(), e.getCustomMessage()));
}
}
31 changes: 31 additions & 0 deletions src/main/java/wanted/media/post/controller/PostController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package wanted.media.post.controller;

import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import wanted.media.post.dto.PostIdResponse;
import wanted.media.post.service.PostService;

@RestController
@RequestMapping("/api/posts")
@RequiredArgsConstructor
public class PostController {
private final PostService postService;

@PostMapping("/likes/{postId}")
public ResponseEntity getLikes(@PathVariable(name = "postId") String postId) {
if (postId == null) {
rhaehf marked this conversation as resolved.
Show resolved Hide resolved
return ResponseEntity.badRequest().body("잘못된 요청입니다.");
}

try {
String id = postService.increaseLike(postId);
return ResponseEntity.ok().body(new PostIdResponse(id, "좋아요 수 증가 완료"));
} catch (Exception e) {
return ResponseEntity.internalServerError().body("좋아요 수 증가 실패 : " + e.getMessage());
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package wanted.media.content.domain;
package wanted.media.post.domain;

import jakarta.persistence.*;
import jakarta.validation.constraints.NotNull;
Expand All @@ -13,16 +13,15 @@

@Entity
@Getter
@Table(name = "contents")
@Table(name = "posts")
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
@Builder
@EntityListeners(AuditingEntityListener.class)
public class Content {
public class Post {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "content_id", nullable = false)
private Long id;
@Column(name = "post_id", nullable = false)
private String id;

@Column(name = "like_count")
private Long likeCount;
Expand Down Expand Up @@ -54,4 +53,7 @@ public class Content {
@NotNull
private User user;

public void addLikeCount() {
this.likeCount++;
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package wanted.media.content.domain;
package wanted.media.post.domain;

public enum Type {
FACEBOOK, TWITTER, INSTAGRAM, THREADS;
Expand Down
11 changes: 11 additions & 0 deletions src/main/java/wanted/media/post/dto/PostIdResponse.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package wanted.media.post.dto;

import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public class PostIdResponse {
private final String postId;
private final String messgae;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package wanted.media.post.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import wanted.media.post.domain.Post;

public interface PostRepository extends JpaRepository<Post, String> {
}
60 changes: 60 additions & 0 deletions src/main/java/wanted/media/post/service/PostService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package wanted.media.post.service;

import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import wanted.media.exception.CustomException;
import wanted.media.exception.ErrorCode;
import wanted.media.post.domain.Post;
import wanted.media.post.repository.PostRepository;

@Service
@RequiredArgsConstructor
public class PostService {
private final PostRepository postRepository;

@Transactional
public String increaseLike(String postId) {
if (postId == null) {
new CustomException(ErrorCode.INVALID_INPUT_VALUE);
}

// contentId를 통해 게시물의 SNS 유형 조회
Post post = postRepository.findById(postId).orElseThrow(() -> new CustomException(ErrorCode.ENTITY_NOT_FOUND));

String snsType = post.getType().name();
// 외부 SNS API 호출 부분 (기능 개발을 위한 요소로, 실제 동작하지 않음)
snsApi(snsType, postId);

// 좋아요 수 증가
post.addLikeCount();
return postId;
}

// 외부 SNS API 호출 부분 (기능 개발을 위한 요소로, 실제 동작하지 않음)
public void snsApi(String snsType, String postId) {
String endpoint = "";

// SNS 유형에 따른 외부 엔드포인트 구성
switch (snsType.toLowerCase()) {
case "facebook":
endpoint = "https://www.facebook.com/likes/" + postId;
break;
case "twitter":
endpoint = "https://www.twitter.com/likes/" + postId;
break;
case "instagram":
endpoint = "https://www.instagram.com/likes/" + postId;
break;
case "threads":
endpoint = "https://www.threads.net/likes/" + postId;
break;
default:
endpoint = null;
}

// 요구사항 시나리오에 따라 필요하지만 실제 동작하지 않기에 주석 처리함
// RestTemplate restTemplate = new RestTemplate();
// String response = restTemplate.postForObject(endpoint, null, String.class);
}
}