diff --git a/src/main/java/org/winey/server/controller/FeedController.java b/src/main/java/org/winey/server/controller/FeedController.java index f1cdf02..023a633 100644 --- a/src/main/java/org/winey/server/controller/FeedController.java +++ b/src/main/java/org/winey/server/controller/FeedController.java @@ -11,10 +11,7 @@ import org.winey.server.common.dto.ApiResponse; import org.winey.server.config.resolver.UserId; import org.winey.server.controller.request.CreateFeedRequestDto; -import org.winey.server.controller.response.feed.CreateFeedResponseDto; -import org.winey.server.controller.response.feed.DeleteFeedResponseDto; -import org.winey.server.controller.response.feed.GetAllFeedResponseDto; -import org.winey.server.controller.response.feed.GetFeedDetailResponseDto; +import org.winey.server.controller.response.feed.*; import org.winey.server.exception.Error; import org.winey.server.exception.Success; import org.winey.server.external.client.aws.S3Service; @@ -22,6 +19,7 @@ import javax.validation.Valid; import javax.validation.constraints.Min; +import java.io.IOException; @RestController @RequiredArgsConstructor @@ -83,4 +81,11 @@ public ApiResponse getMyFeed(@RequestParam int page, @Use public ApiResponse getFeedDetail(@UserId Long userId, @PathVariable Long feedId) { return ApiResponse.success(Success.GET_DETAIL_SUCCESS, feedService.getFeedDetail(feedId, userId)); } + + @PostMapping(value = "/report/{feedId}") + @ResponseStatus(HttpStatus.OK) + @Operation(summary = "피드 신고 API", description = "피드를 신고합니다.") + public ApiResponse reportFeed(@UserId Long userId, @PathVariable Long feedId) throws IOException { + return ApiResponse.success(Success.REPORT_FEED_SUCCESS, feedService.reportFeed(feedId, userId)); + } } diff --git a/src/main/java/org/winey/server/controller/response/feed/ReportFeedResponseDto.java b/src/main/java/org/winey/server/controller/response/feed/ReportFeedResponseDto.java new file mode 100644 index 0000000..acfa18a --- /dev/null +++ b/src/main/java/org/winey/server/controller/response/feed/ReportFeedResponseDto.java @@ -0,0 +1,21 @@ +package org.winey.server.controller.response.feed; + +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor(access = AccessLevel.PRIVATE) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +public class ReportFeedResponseDto { + private Long reporterId; + private Long reportFeedId; + + private String reportMessage; + + public static ReportFeedResponseDto of(Long reporterId, Long reportFeedId, String reportMessage){ + return new ReportFeedResponseDto(reporterId, reportFeedId, reportMessage); + } + +} \ No newline at end of file diff --git a/src/main/java/org/winey/server/exception/Success.java b/src/main/java/org/winey/server/exception/Success.java index acc3e59..bc94262 100644 --- a/src/main/java/org/winey/server/exception/Success.java +++ b/src/main/java/org/winey/server/exception/Success.java @@ -25,6 +25,7 @@ public enum Success { UPDATE_NICKNAME_SUCCESS(HttpStatus.OK, "닉네임 변경 성공"), CHECK_NICKNAME_DUPLICATE_SUCCESS(HttpStatus.OK, "닉네임 중복 확인 성공"), CHECK_NEW_NOTIFICATION_SUCCESS(HttpStatus.OK, "새 알림 여부 조회 성공"), + REPORT_FEED_SUCCESS(HttpStatus.OK, "피드 신고 완료"), /** * 201 CREATED diff --git a/src/main/java/org/winey/server/service/FeedService.java b/src/main/java/org/winey/server/service/FeedService.java index f5b832b..8a20b8e 100644 --- a/src/main/java/org/winey/server/service/FeedService.java +++ b/src/main/java/org/winey/server/service/FeedService.java @@ -5,6 +5,7 @@ import org.springframework.data.domain.PageRequest; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.winey.server.common.dto.ApiResponse; import org.winey.server.controller.request.CreateFeedRequestDto; import org.winey.server.controller.response.PageResponseDto; import org.winey.server.controller.response.comment.CommentResponseDto; @@ -20,7 +21,9 @@ import org.winey.server.exception.model.NotFoundException; import org.winey.server.exception.model.UnauthorizedException; import org.winey.server.infrastructure.*; +import org.winey.server.slack.SlackApi; +import java.io.IOException; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.temporal.ChronoUnit; @@ -36,8 +39,8 @@ public class FeedService { private final GoalRepository goalRepository; private final FeedLikeRepository feedLikeRepository; private final CommentRepository commentRepository; - private final NotiRepository notiRepository; + private final SlackApi slackApi; @Transactional public CreateFeedResponseDto createFeed(CreateFeedRequestDto request, Long userId, String imageUrl) { @@ -292,4 +295,12 @@ private String getTimeAgo(LocalDateTime createdAt) { } return "지금"; } + @Transactional + public ReportFeedResponseDto reportFeed(Long userId, Long feedId) throws IOException { + Feed reportFeed = feedRepository.findByFeedId(feedId) + .orElseThrow(()-> new NotFoundException(Error.NOT_FOUND_FEED_EXCEPTION, Error.NOT_FOUND_FEED_EXCEPTION.getMessage())); + User reporter = userRepository.findByUserId(userId) + .orElseThrow(()-> new NotFoundException(Error.NOT_FOUND_USER_EXCEPTION, Error.NOT_FOUND_USER_EXCEPTION.getMessage())); + return ReportFeedResponseDto.of(userId,feedId,slackApi.sendReport(reporter, reportFeed)); + } } diff --git a/src/main/java/org/winey/server/slack/SlackApi.java b/src/main/java/org/winey/server/slack/SlackApi.java index 618fc95..9f2b14f 100644 --- a/src/main/java/org/winey/server/slack/SlackApi.java +++ b/src/main/java/org/winey/server/slack/SlackApi.java @@ -9,6 +9,8 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; +import org.winey.server.domain.feed.Feed; +import org.winey.server.domain.user.User; import javax.servlet.http.HttpServletRequest; import java.io.IOException; @@ -69,6 +71,15 @@ private String generateErrorPointMessage(HttpServletRequest request) { return sb.toString(); } + private String generateReportMessage(Feed feed){ + sb.setLength(0); + sb.append("*[🔥 feed id]*" + NEW_LINE + feed.getFeedId() + DOUBLE_NEW_LINE); + sb.append("*[📩 feed content]*" + NEW_LINE + feed.getFeedTitle() + DOUBLE_NEW_LINE); + sb.append("*[🚨 feed image]*" + NEW_LINE + feed.getFeedImage() + DOUBLE_NEW_LINE); + return sb.toString(); + } + + private String readRootStackTrace(Exception error) { return error.getStackTrace()[0].toString(); @@ -84,4 +95,23 @@ private LayoutBlock getSection(String message) { return Blocks.section(s -> s.text(BlockCompositions.markdownText(message))); } + public String sendReport(User user, Feed feed) throws IOException{ + List layoutBlocks = generateReportBlock(feed); + Slack.getInstance().send(webhookUrl, WebhookPayloads + .payload(p -> + p.username("신고가 접수되었습니다. 🚨") + .iconUrl("https://yt3.googleusercontent.com/ytc/AGIKgqMVUzRrhoo1gDQcqvPo0PxaJz7e0gqDXT0D78R5VQ=s900-c-k-c0x00ffffff-no-rj") + .blocks(layoutBlocks))); + return "신고가 정상적으로 접수되었습니다."; + } + + private List generateReportBlock(Feed feed) { + return Blocks.asBlocks( + getHeader("신고가 들어온 게시물이 있습니다.🚨"+NEW_LINE+"정신적으로 해로운 사진일 수 있으니 주의하세요."), + Blocks.divider(), + getSection(generateReportMessage(feed)), + Blocks.divider(), + getSection("") + ); + } } \ No newline at end of file