|
1 | 1 | package com.chungang.capstone.openstep.domain.Issue.controller; |
2 | 2 |
|
| 3 | +import com.chungang.capstone.openstep.domain.Github.dto.GitHubIssueResponse; |
| 4 | +import com.chungang.capstone.openstep.domain.Github.service.GitHubGraphQLService; |
3 | 5 | import com.chungang.capstone.openstep.domain.Issue.service.IssueCommandService; |
4 | 6 | import com.chungang.capstone.openstep.domain.Issue.service.IssueQueryService; |
5 | 7 | import com.chungang.capstone.openstep.domain.Member.entity.Member; |
| 8 | +import com.chungang.capstone.openstep.domain.OpenAI.service.OpenAIService; |
6 | 9 | import com.chungang.capstone.openstep.domain.Task.entity.Task; |
7 | 10 | import com.chungang.capstone.openstep.domain.common.InterestLanguage; |
8 | 11 | import com.chungang.capstone.openstep.domain.common.UpdatePeriod; |
| 12 | +import com.chungang.capstone.openstep.global.apiPayload.code.status.ErrorStatus; |
9 | 13 | import com.chungang.capstone.openstep.global.apiPayload.code.status.SuccessStatus; |
10 | 14 | import com.chungang.capstone.openstep.global.apiPayload.ApiResponse; |
11 | 15 | import com.chungang.capstone.openstep.domain.Issue.converter.IssueConverter; |
12 | 16 | import com.chungang.capstone.openstep.domain.Issue.dto.IssueResponseDTO; |
13 | 17 | import com.chungang.capstone.openstep.domain.Issue.entity.Issue; |
| 18 | +import com.chungang.capstone.openstep.global.apiPayload.exception.handler.IssueHandler; |
14 | 19 | import com.chungang.capstone.openstep.global.security.util.SecurityUtils; |
15 | 20 |
|
16 | 21 | import io.swagger.v3.oas.annotations.Parameter; |
|
19 | 24 | import jakarta.validation.constraints.Max; |
20 | 25 | import jakarta.validation.constraints.Min; |
21 | 26 |
|
| 27 | +import lombok.extern.slf4j.Slf4j; |
22 | 28 | import org.springframework.data.domain.PageRequest; |
23 | 29 | import org.springframework.validation.annotation.Validated; |
24 | 30 | import org.springframework.web.bind.annotation.RequestMapping; |
|
35 | 41 | @RestController |
36 | 42 | @RequiredArgsConstructor |
37 | 43 | @Validated |
| 44 | +@Slf4j |
38 | 45 | @RequestMapping("/issues") |
39 | 46 | @Tag(name = "이슈 API", description = "GitHub 이슈 관련 API입니다.") |
40 | 47 | public class IssueController { |
41 | 48 |
|
42 | 49 | private final IssueQueryService issueQueryService; |
43 | 50 | private final IssueCommandService issueCommandService; |
| 51 | + private final GitHubGraphQLService gitHubGraphQLService; |
| 52 | + private final OpenAIService openAIService; |
44 | 53 |
|
45 | 54 | // 트렌딩 이슈 목록 조회 API |
46 | 55 | @GetMapping("/trending") |
@@ -105,6 +114,23 @@ public ApiResponse<IssueResponseDTO.IssueListDTO> searchIssuesByKeyword( |
105 | 114 | IssueConverter.toIssueListDTO(issues, bookmarkedIds)); |
106 | 115 | } |
107 | 116 |
|
| 117 | + @GetMapping("/detail-by-url") |
| 118 | + @Operation(summary = "GitHub URL 기반 이슈 상세 조회", description = "검색된 이슈의 GitHub URL로 상세 정보를 조회합니다.") |
| 119 | + public ApiResponse<IssueResponseDTO.IssueDetailDTO> getIssueDetailByUrl(@RequestParam String url) { |
| 120 | + GitHubIssueResponse.IssueNode node = gitHubGraphQLService.fetchIssueByUrl(url); |
| 121 | + if (node == null) throw new IssueHandler(ErrorStatus.ISSUE_NOT_FOUND); |
| 122 | + Issue issue = IssueConverter.fromGitHubIssueNode(node); |
| 123 | + try { |
| 124 | + String raw = openAIService.summarizeIssue(issue.getTitle(), issue.getBody()); |
| 125 | + issue.setSummary(openAIService.rewriteNaturalKorean(raw)); |
| 126 | + } catch (Exception e) { |
| 127 | + log.warn("[SUMMARY] 요약 실패: {}", url, e); |
| 128 | + issue.setSummary("요약을 생성할 수 없습니다."); |
| 129 | + } |
| 130 | + return ApiResponse.onSuccess(SuccessStatus.ISSUE_GET_DETAIL_OK, IssueConverter.toIssueDetailDTO(issue)); |
| 131 | + } |
| 132 | + |
| 133 | + |
108 | 134 |
|
109 | 135 |
|
110 | 136 |
|
|
0 commit comments