From d42e4fa0ca0bbebe856a92e58018574cf836f1f6 Mon Sep 17 00:00:00 2001 From: dyhj625 Date: Fri, 24 Jan 2025 12:38:24 +0900 Subject: [PATCH] =?UTF-8?q?=EB=B3=B8=EB=AC=B8=20=EC=9D=B4=EB=AF=B8?= =?UTF-8?q?=EC=A7=80=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/api/BoardController.java | 337 ++++-------------- .../localhost/service/localbordService.java | 181 ++++++++-- 2 files changed, 223 insertions(+), 295 deletions(-) diff --git a/src/main/java/io/company/localhost/controller/api/BoardController.java b/src/main/java/io/company/localhost/controller/api/BoardController.java index e7b3acf..e1bd221 100644 --- a/src/main/java/io/company/localhost/controller/api/BoardController.java +++ b/src/main/java/io/company/localhost/controller/api/BoardController.java @@ -16,25 +16,11 @@ package io.company.localhost.controller.api; import java.math.BigInteger; -import java.nio.charset.StandardCharsets; -import java.sql.Blob; -import java.util.HashMap; import java.util.List; -import java.util.Map; -import java.util.UUID; -import org.springframework.security.crypto.password.PasswordEncoder; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; -import com.fasterxml.jackson.databind.ObjectMapper; import com.github.pagehelper.PageInfo; -import com.github.pagehelper.PageSerializable; import io.company.localhost.common.annotation.Member; import io.company.localhost.common.annotation.ParameterCheck; @@ -50,36 +36,19 @@ import lombok.extern.slf4j.Slf4j; @RequiredArgsConstructor @Slf4j public class BoardController { + private final localbordService boardService; - private final PasswordEncoder passwordEncoder; - + /** * 공지사항 목록 조회 * @ReqMap map 요청 파라미터 (searchKeyword) * @return 전체 공지사항 목록 */ @Member - @ParameterCheck + @ParameterCheck @GetMapping("/notices") public ApiResponse> getNotices(@ReqMap MapDto map) { - List posts = boardService.getNotices(map); - - // Blob 데이터를 처리 (문자열로 변환) - for (MapDto post : posts) { - Object content = post.get("content"); - if (content instanceof Blob) { - Blob blob = (Blob) content; - post.put("content", safeBlobToString(blob)); - } - - // "id" 값을 Number로 받고 longValue()로 변환 - Object idObject = post.get("id"); - long postId = ((Number) idObject).longValue(); - post.put("hasAttachment", boardService.hasAttachments(postId)); - - } - - return ApiResponse.ok(posts); + return ApiResponse.ok(boardService.getNotices(map)); } /** @@ -88,335 +57,169 @@ public class BoardController { * @return 페이징된 자유/익명 게시판 목록 */ @Member - @ParameterCheck + @ParameterCheck @GetMapping("/general") public ApiResponse> getGeneralPosts(@ReqMap MapDto map) { - PageInfo posts = boardService.getGeneralPosts(map); - - // Blob 데이터를 처리 (문자열로 변환) - for (MapDto post : posts.getList()) { - Object content = post.get("content"); - if (content instanceof Blob) { - Blob blob = (Blob) content; - post.put("content", safeBlobToString(blob)); - } - - // "id" 값을 Number로 받고 longValue()로 변환 - Object idObject = post.get("id"); - if (idObject instanceof Number) { - long postId = ((Number) idObject).longValue(); - post.put("commentCount", boardService.getCommentCount(postId)); - post.put("hasAttachment", boardService.hasAttachments(postId)); - MapDto reactions = boardService.getBoardReactions(postId); - post.put("likeCount", reactions.getOrDefault("likeCount", 0)); - post.put("dislikeCount", reactions.getOrDefault("dislikeCount", 0)); - } else { - post.put("commentCount", 0); // id가 없거나 잘못된 경우 기본값 설정 - } - } - - return ApiResponse.ok(posts); + return ApiResponse.ok(boardService.getGeneralPosts(map)); } /** - * 안전하게 Blob 데이터를 문자열로 변환하는 메서드 - * @ReqMap - * @return 변환된 문자열 또는 null - */ - private String safeBlobToString(Blob blob) { - if (blob == null) { - return null; // Blob이 null이면 null 반환 - } - - try { - long blobLength = blob.length(); - if (blobLength > Integer.MAX_VALUE) { - throw new IllegalArgumentException("Blob is too large to process."); - } - - return new String(blob.getBytes(1, (int) blobLength), StandardCharsets.UTF_8); - } catch (Exception e) { - System.err.println("Failed to convert Blob to String: " + e.getMessage()); - e.printStackTrace(); - return null; // 변환 실패 시 null 반환 - } - } - - /** * 게시물 작성 * @ReqMap map 요청 파라미터 (LOCBRDTTL, LOCBRDCON, MEMBERSEQ, LOCBRDTYP, - * LOCBRDPWD(익명일떄에만), LOCBRDCAT(지식커뮤니티만)) + * LOCBRDPWD(익명일 때만), LOCBRDCAT(지식커뮤니티만)) * @return 작성된 게시물의 ID */ - @Member - @ParameterCheck - @PostMapping - public ApiResponse createBoard(@ReqMap MapDto map) { - // 비밀번호 암호화 - if (map.containsKey("LOCBRDPWD")) { - String rawPassword = map.getString("LOCBRDPWD"); - String encodedPassword = passwordEncoder.encode(rawPassword); - map.put("LOCBRDPWD", encodedPassword); - } - -// <--- 프론드 단에서 해줌 할필요 없음 삭제 ---> - // LOCBRDCON 필드를 JSON 문자열로 변환 -// ObjectMapper objectMapper = new ObjectMapper(); -// if (map.containsKey("LOCBRDCON")) { -// try { -// String jsonContent = objectMapper.writeValueAsString(map.get("LOCBRDCON")); -// map.put("LOCBRDCON", jsonContent); // JSON 문자열로 변환된 값 설정 -// } catch (Exception e) { -// throw new RuntimeException("Error serializing LOCBRDCON field", e); -// } -// } - //로그인 미개발 ->임시 - map.put("MEMBERSEQ", 1); - - BigInteger createdIdx = boardService.createBoard(map); // 작성된 게시물의 idx를 반환 - Map responseData = new HashMap<>(); - responseData.put("CMNBRDSEQ", createdIdx); - responseData.put("message", "게시물이 작성되었습니다."); - return ApiResponse.ok(responseData); - } - - /** - * 첨부파일 추가 - * @ReqMap map 요청 파라미터 (CMNFLEREG, CMNFLESIZ, CMNFLEEXT, CMNFLEORG, CMNFLENAM, CMNFLEPAT, CMNBRDSEQ) - * @return 첨부파일 저장 결과 메시지 - */ - @Member - @ParameterCheck - @PostMapping("/{CMNBRDSEQ}/attachments") - public ApiResponse uploadAttachment(@ReqMap MapDto map) { - String filename = UUID.randomUUID().toString(); - map.put("CMNFLENAM", filename); - map.put("CMNFLEREG", 1); - // 파일 데이터 저장 - boardService.addAttachment(map); - - return ApiResponse.ok("첨부파일이 저장되었습니다."); + @Member + @ParameterCheck + @PostMapping + public ApiResponse createBoard(@ReqMap MapDto map) { + return ApiResponse.ok(boardService.createBoard(map)); } - - /** + + /** * 게시물 상세보기 * @param boardId 게시물 ID - * @return 게시물 상세정보, 첨부파일 목록, 댓글 목록 + * @return 게시물 상세정보 */ - @Member - @ParameterCheck + @Member + @ParameterCheck @GetMapping("/{boardId}") public ApiResponse getBoardDetail(@PathVariable("boardId") Long boardId) { - log.info("Fetching details for board ID: {}", boardId); - - // 조회수 증가 - boardService.incrementViewCount(boardId); - - // 게시물 상세정보 조회 - MapDto boardDetail = boardService.getBoardDetail(boardId); - if (boardDetail == null) { - throw new IllegalArgumentException("Board not found for ID: " + boardId); - } - - // Blob 데이터를 문자열로 변환 - if (boardDetail.get("content") instanceof Blob) { - try { - Blob blob = (Blob) boardDetail.get("content"); - String contentString = new String(blob.getBytes(1, (int) blob.length()), StandardCharsets.UTF_8); - boardDetail.put("content", contentString); - } catch (Exception e) { - throw new RuntimeException("Failed to process Blob content", e); - } - } - - MapDto reactions = boardService.getBoardReactions(boardId); - boardDetail.put("likeCount", reactions.getOrDefault("likeCount", 0)); - boardDetail.put("dislikeCount", reactions.getOrDefault("dislikeCount", 0)); - - List attachments = boardService.getAttachments(boardId); - List comments = boardService.getComments(boardId.intValue()); - - List commentReactions = boardService.getCommentReactions(boardId); - for (MapDto comment : comments) { - Integer commentId = (Integer) comment.get("LOCCMTSEQ"); - for (MapDto reaction : commentReactions) { - if (reaction.get("LOCCMTSEQ").equals(commentId)) { - comment.put("likeCount", reaction.getOrDefault("likeCount", 0)); - comment.put("dislikeCount", reaction.getOrDefault("dislikeCount", 0)); - } - } - } - - // 결과 조합 - MapDto result = new MapDto(); - result.put("boardDetail", boardDetail); - result.put("attachments", attachments); - result.put("comments", comments); - result.put("commentCount", boardService.getCommentCount(boardId)); - result.put("hasAttachment", boardService.hasAttachments(boardId)); - - return ApiResponse.ok(result); + return ApiResponse.ok(boardService.getBoardDetail(boardId)); } - - /** + + /** * 게시물 삭제 * @param boardId 게시물 ID * @return 삭제 결과 메시지 */ - @Member - @ParameterCheck + @Member + @ParameterCheck @DeleteMapping("/{boardId}") public ApiResponse deleteBoard(@PathVariable("boardId") Long boardId, @ReqMap MapDto map) { map.put("LOCBRDSEQ", boardId); - log.info("Deleting board with ID: {}", boardId); boardService.deleteBoard(map); return ApiResponse.ok("게시물이 삭제되었습니다."); } - - /** + + /** * 게시물 수정 * @param boardId 게시물 ID * @ReqMap map 수정 데이터 (LOCBRDTTL, LOCBRDCON) * @return 수정 결과 메시지 */ - @Member - @ParameterCheck + @Member + @ParameterCheck @PutMapping("/{boardId}") - public ApiResponse updateBoard(@PathVariable("boardId") Long boardId,@ReqMap MapDto map) { - map.put("LOCBRDSEQ", boardId); + public ApiResponse updateBoard(@PathVariable("boardId") Long boardId, @ReqMap MapDto map) { + map.put("LOCBRDSEQ", boardId); boardService.updateBoard(map); return ApiResponse.ok("게시물이 수정되었습니다."); } - - /** - * 게시물,댓글 좋아요/싫어요 추가 + + /** + * 첨부파일 추가 + * @ReqMap map 요청 파라미터 (CMNFLEREG, CMNFLESIZ, CMNFLEEXT, CMNFLEORG, CMNFLENAM, CMNFLEPAT, CMNBRDSEQ) + * @return 첨부파일 저장 결과 메시지 + */ + @Member + @ParameterCheck + @PostMapping("/{CMNBRDSEQ}/attachments") + public ApiResponse uploadAttachment(@ReqMap MapDto map) { + boardService.addAttachment(map); + return ApiResponse.ok("첨부파일이 저장되었습니다."); + } + + /** + * 게시물, 댓글 좋아요/싫어요 추가 * @ReqMap map 데이터 (LOCCMTSEQ, MEMBERSEQ, LOCGOBGOD, LOCGOBBAD, LOCBRDSEQ) * @return 반응 추가 결과 메시지 */ - @Member - @ParameterCheck + @Member + @ParameterCheck @PostMapping("/{LOCBRDSEQ}/{LOCCMTSEQ}/reaction") public ApiResponse reactToBoard(@ReqMap MapDto map) { - //로그인 미개발 ->임시 - map.put("MEMBERSEQ", 1); boardService.reactToBoard(map); return ApiResponse.ok("반응이 성공적으로 처리되었습니다."); } - /** * 댓글/대댓글 조회 * @param boardId 게시물 ID * @return 댓글과 대댓글의 계층 구조 데이터 */ - @Member - @ParameterCheck + @Member + @ParameterCheck @GetMapping("/{boardId}/comments") public ApiResponse> getComments(@PathVariable("boardId") int boardId) { - // 모든 댓글과 대댓글 조회 - List comments = boardService.getComments(boardId); - - return ApiResponse.ok(comments); + return ApiResponse.ok(boardService.getComments(boardId)); } - - /** + /** * 댓글/대댓글 작성 * @param boardId 게시물 ID * @ReqMap map 댓글 데이터 (LOCBRDSEQ, LOCCMTRPY, LOCCMTPNT, LOCCMTPWD, MEMBERSEQ 등) * @return 작성 결과 메시지 */ - @Member - @ParameterCheck + @Member + @ParameterCheck @PostMapping("/{LOCBRDSEQ}/comment") public ApiResponse addCommentOrReply(@ReqMap MapDto map) { - //로그인 미개발 ->임시 - map.put("MEMBERSEQ", 1); - - // 비밀번호 암호화 (비밀번호가 있는 경우에만) - if (map.containsKey("LOCCMTPWD")) { - String rawPassword = map.getString("LOCCMTPWD"); - String encodedPassword = passwordEncoder.encode(rawPassword); - map.put("LOCCMTPWD", encodedPassword); - } - boardService.addCommentOrReply(map); return ApiResponse.ok("댓글 또는 대댓글이 작성되었습니다."); } - /** + /** * 댓글/대댓글 수정 * @param commentId 댓글 ID - * @ReqMap map 수정 데이터 (LOCCMTSEQ, LOCCMTRPY ) + * @ReqMap map 수정 데이터 (LOCCMTSEQ, LOCCMTRPY) * @return 수정 결과 메시지 */ - @Member - @ParameterCheck + @Member + @ParameterCheck @PutMapping("/comment/{commentId}") public ApiResponse updateComment(@PathVariable("commentId") int commentId, @ReqMap MapDto map) { - // 기존 댓글 조회 - MapDto existingComment = boardService.getCommentById(commentId); - if (existingComment == null) { - throw new IllegalArgumentException("Comment not found for ID: " + commentId); - } - - map.put("LOCCMTSEQ", commentId); boardService.updateComment(map); - return ApiResponse.ok("댓글이 수정되었습니다."); } - /** + /** * 댓글/대댓글 삭제 * @param commentId 댓글 ID + * @ReqMap map 삭제 데이터 * @return 삭제 결과 메시지 */ - @Member - @ParameterCheck + @Member + @ParameterCheck @DeleteMapping("/comment/{commentId}") public ApiResponse deleteComment(@PathVariable("commentId") int commentId, @ReqMap MapDto map) { - map.put("LOCCMTSEQ", commentId); boardService.deleteComment(map); - return ApiResponse.ok("댓글이 삭제되었습니다."); } - /** + /** * 댓글 비밀번호 확인 * @param commentId 댓글 ID * @ReqMap map 비밀번호 데이터 * @return 비밀번호 확인 결과 */ - @Member - @ParameterCheck + @Member + @ParameterCheck @PostMapping("/comment/{commentId}/password") public ApiResponse checkCommentPassword(@PathVariable("commentId") int commentId, @ReqMap MapDto map) { - // DB에서 암호화된 비밀번호 조회 - String storedPassword = boardService.getCommentPassword(commentId); - String rawPassword = map.getString("LOCCMTPWD"); - - // 비밀번호 검증 - boolean isMatch = passwordEncoder.matches(rawPassword, storedPassword); - return ApiResponse.ok(isMatch); + return ApiResponse.ok(boardService.getCommentPassword(commentId).equals(map.getString("LOCCMTPWD"))); } - /** + /** * 게시물 비밀번호 확인 * @param boardId 게시물 ID * @ReqMap map 비밀번호 데이터 * @return 비밀번호 확인 결과 */ - @Member - @ParameterCheck + @Member + @ParameterCheck @PostMapping("/{boardId}/password") public ApiResponse checkBoardPassword(@PathVariable("boardId") int boardId, @ReqMap MapDto map) { - // DB에서 암호화된 비밀번호 조회 - String storedPassword = boardService.getBoardPassword(boardId); - String rawPassword = map.getString("LOCBRDPWD"); - - // 비밀번호 검증 - boolean isMatch = passwordEncoder.matches(rawPassword, storedPassword); - return ApiResponse.ok(isMatch); + return ApiResponse.ok(boardService.getBoardPassword(boardId).equals(map.getString("LOCBRDPWD"))); } - -} +} \ No newline at end of file diff --git a/src/main/java/io/company/localhost/service/localbordService.java b/src/main/java/io/company/localhost/service/localbordService.java index b74afea..7a36ee2 100644 --- a/src/main/java/io/company/localhost/service/localbordService.java +++ b/src/main/java/io/company/localhost/service/localbordService.java @@ -1,11 +1,15 @@ package io.company.localhost.service; +import java.io.ByteArrayInputStream; import java.math.BigInteger; +import java.nio.charset.StandardCharsets; import java.util.List; import java.util.Map; import org.springframework.stereotype.Service; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageInfo; @@ -20,13 +24,15 @@ public class localbordService { private final localbordMapper boardMapper; public List getNotices(MapDto map) { - return boardMapper.getNotices(map); + List posts = boardMapper.getNotices(map); + enrichPostsWithAdditionalData(posts); + return posts; } public PageInfo getGeneralPosts(MapDto map) { int page = map.getString("page") != null ? Integer.parseInt(map.getString("page")) : 1; int size = map.getString("size") != null ? Integer.parseInt(map.getString("size")) : 10; - + String orderBy = map.getString("orderBy"); if (orderBy == null || (!orderBy.equals("date") && !orderBy.equals("views"))) { map.put("orderBy", "date"); @@ -35,33 +41,38 @@ public class localbordService { PageHelper.startPage(page, size); List result = boardMapper.getGeneralPosts(map); + enrichPostsWithAdditionalData(result); return PageUtil.redefineNavigation(new PageInfo<>(result, size)); } - + public void incrementViewCount(Long boardId) { boardMapper.incrementViewCount(boardId); } public BigInteger createBoard(MapDto map) { boardMapper.createBoard(map); - return (BigInteger) map.get("LOCBRDSEQ"); // Mapper에서 자동 생성된 key를 가져옴 + return (BigInteger) map.get("LOCBRDSEQ"); } - + public void addAttachment(MapDto map) { boardMapper.addAttachment(map); } - + public MapDto getBoardDetail(Long boardId) { - return boardMapper.selectBoardDetail(boardId); + MapDto boardDetail = boardMapper.selectBoardDetail(boardId); + if (boardDetail != null) { + enrichBoardDetail(boardDetail); + } + return boardDetail; } public List getAttachments(Long boardId) { return boardMapper.selectAttachments(boardId); } - + public void deleteBoard(MapDto map) { - boardMapper.deleteCommentsByBoardId(map); + boardMapper.deleteCommentsByBoardId(map); boardMapper.deleteBoard(map); } @@ -70,14 +81,11 @@ public class localbordService { } public void reactToBoard(MapDto map) { - // 기존 반응 확인 MapDto existingReaction = boardMapper.findReaction(map); if (existingReaction != null) { - // 기존 반응이 있는 경우 업데이트 boardMapper.updateReaction(map); } else { - // 기존 반응이 없는 경우 새로 삽입 boardMapper.insertReaction(map); } } @@ -87,8 +95,8 @@ public class localbordService { } public void addCommentOrReply(MapDto map) { - if (map.get("LOCCMTPNT") == null) { - map.put("LOCCMTPNT", null); + if (map.get("LOCCMTPNT") == null) { + map.put("LOCCMTPNT", null); } boardMapper.addCommentOrReply(map); } @@ -98,22 +106,17 @@ public class localbordService { } public void deleteComment(MapDto map) { - // 댓글인지 대댓글인지 확인 boolean isReply = boardMapper.isReply(map); if (isReply) { - // 대댓글 삭제 - boardMapper.deleteReply(map); + boardMapper.deleteReply(map); } else { - // 댓글인 경우 boolean hasReplies = boardMapper.hasReplies(map); if (hasReplies) { - // 대댓글이 있는 경우 내용 업데이트 - boardMapper.softDeleteComment(map); + boardMapper.softDeleteComment(map); } else { - // 대댓글이 없는 경우 댓글 삭제 - boardMapper.deleteComment(map); + boardMapper.deleteComment(map); } } } @@ -121,24 +124,24 @@ public class localbordService { public String getCommentPassword(int commentId) { return boardMapper.selectCommentPassword(commentId); } - + public String getBoardPassword(int boardId) { return boardMapper.selectBoardPassword(boardId); } - + public MapDto getCommentById(int commentId) { return boardMapper.getCommentById(commentId); } - + public int getCommentCount(Long boardId) { return boardMapper.countComments(boardId); } - + public boolean hasAttachments(Long boardId) { int count = boardMapper.countAttachments(boardId); return count > 0; } - + public MapDto getBoardReactions(Long boardId) { return boardMapper.getBoardReactions(boardId); } @@ -147,6 +150,128 @@ public class localbordService { return boardMapper.getCommentReactions(boardId); } -} + private void enrichBoardDetail(MapDto boardDetail) { + long boardId = ((Number) boardDetail.get("id")).longValue(); + boardDetail.put("hasAttachment", hasAttachments(boardId)); + boardDetail.put("commentCount", getCommentCount(boardId)); + MapDto reactions = getBoardReactions(boardId); + boardDetail.put("likeCount", reactions.getOrDefault("likeCount", 0)); + boardDetail.put("dislikeCount", reactions.getOrDefault("dislikeCount", 0)); + // Blob 데이터를 문자열로 변환 + Object content = boardDetail.get("content"); + if (content != null) { + String contentString = convertBlobToString(content); // Blob을 문자열로 변환 + boardDetail.put("content", contentString); // JSON 변환 가능 + } + } + private String convertBlobToString(Object blob) { + try { + if (blob instanceof String) { + return (String) blob; // 이미 문자열인 경우 반환 + } else if (blob instanceof java.sql.Blob) { + java.sql.Blob sqlBlob = (java.sql.Blob) blob; + long blobLength = sqlBlob.length(); + byte[] blobBytes = sqlBlob.getBytes(1, (int) blobLength); + return new String(blobBytes, StandardCharsets.UTF_8); + } else if (blob instanceof ByteArrayInputStream) { + ByteArrayInputStream inputStream = (ByteArrayInputStream) blob; + byte[] bytes = inputStream.readAllBytes(); + return new String(bytes, StandardCharsets.UTF_8); + } else { + System.err.println("Unsupported blob type: " + blob.getClass()); + } + } catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException("Failed to convert Blob to String: " + e.getMessage(), e); + } + return null; + } + + private String extractFirstImageUrl(String jsonContent) { + try { + ObjectMapper objectMapper = new ObjectMapper(); + JsonNode rootNode = objectMapper.readTree(jsonContent); + + if (!rootNode.isArray()) { + System.err.println("JSON content is not an array"); + return null; + } + + for (JsonNode node : rootNode) { + JsonNode insertNode = node.get("insert"); + if (insertNode != null && insertNode.has("image")) { + return insertNode.get("image").asText(); // 첫 번째 이미지 URL 반환 + } + } + } catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException("Failed to extract first image URL: " + e.getMessage(), e); + } + return null; // 이미지가 없는 경우 + } + + private String extractPlainTextFromJson(String jsonContent) { + StringBuilder plainTextBuilder = new StringBuilder(); + try { + ObjectMapper objectMapper = new ObjectMapper(); + JsonNode rootNode = objectMapper.readTree(jsonContent); + + // JSON 배열인지 확인 + if (!rootNode.isArray()) { + System.err.println("JSON content is not an array"); + return ""; + } + + // JSON 노드 순회 + for (JsonNode node : rootNode) { + JsonNode insertNode = node.get("insert"); + + // insert 노드가 텍스트인지 확인 + if (insertNode != null && insertNode.isTextual()) { + String text = insertNode.asText(); + + // '\n' 제거하고 순수 텍스트만 추가 + if (!text.trim().isEmpty() && !text.trim().equals("\n")) { + plainTextBuilder.append(text.trim()); + } + } + } + } catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException("Failed to extract plain text: " + e.getMessage(), e); + } + return plainTextBuilder.toString(); + } + + private void enrichPostsWithAdditionalData(List posts) { + for (MapDto post : posts) { + Object idObject = post.get("id"); + if (idObject instanceof Number) { + long postId = ((Number) idObject).longValue(); + post.put("commentCount", getCommentCount(postId)); + post.put("hasAttachment", hasAttachments(postId)); + MapDto reactions = getBoardReactions(postId); + post.put("likeCount", reactions.getOrDefault("likeCount", 0)); + post.put("dislikeCount", reactions.getOrDefault("dislikeCount", 0)); + + Object content = post.get("content"); + if (content != null) { + String contentString = convertBlobToString(content); + post.put("content", contentString); + + // 첫 번째 이미지 URL 및 순수 텍스트 추출 + String firstImageUrl = extractFirstImageUrl(contentString); + post.put("firstImageUrl", firstImageUrl); + + String plainContent = extractPlainTextFromJson(contentString); + post.put("plainContent", plainContent); + } + } else { + post.put("commentCount", 0); + } + } + } + +} \ No newline at end of file