From fea194768dd0b0297f8d981aa4cbbf6595fe44d3 Mon Sep 17 00:00:00 2001 From: baeksunghyun Date: Fri, 21 Feb 2025 17:28:57 +0900 Subject: [PATCH 1/2] =?UTF-8?q?Feat:=20=ED=8A=B9=EC=A0=95=20=EA=B8=B0?= =?UTF-8?q?=EA=B0=84=20=EB=A0=88=ED=8F=AC=EC=A7=80=ED=86=A0=EB=A6=AC=20?= =?UTF-8?q?=EB=B3=84=20=20=EC=BB=A4=EB=B0=8B=20=EC=88=98=20=EB=B6=88?= =?UTF-8?q?=EB=9F=AC=EC=98=A4=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/SinceCommitController.java | 31 +++++++++ .../dto/SinceCommitResponseDto.java | 37 +++++++++++ .../service/SinceCommitService.java | 64 +++++++++++++++++++ .../totalCommit/config/WebConfig.java | 2 +- .../controller/TotalCommitController.java | 6 +- .../dto/TotalCommitGraphQLResponse.java | 2 +- .../dto/TotalCommitResponseDto.java | 2 +- .../service/TotalCommitService.java | 6 +- 8 files changed, 141 insertions(+), 9 deletions(-) create mode 100644 src/main/java/cmf/commitField/domain/commit/sinceCommit/controller/SinceCommitController.java create mode 100644 src/main/java/cmf/commitField/domain/commit/sinceCommit/dto/SinceCommitResponseDto.java create mode 100644 src/main/java/cmf/commitField/domain/commit/sinceCommit/service/SinceCommitService.java rename src/main/java/cmf/commitField/domain/{ => commit}/totalCommit/config/WebConfig.java (90%) rename src/main/java/cmf/commitField/domain/{ => commit}/totalCommit/controller/TotalCommitController.java (72%) rename src/main/java/cmf/commitField/domain/{ => commit}/totalCommit/dto/TotalCommitGraphQLResponse.java (93%) rename src/main/java/cmf/commitField/domain/{ => commit}/totalCommit/dto/TotalCommitResponseDto.java (82%) rename src/main/java/cmf/commitField/domain/{ => commit}/totalCommit/service/TotalCommitService.java (90%) diff --git a/src/main/java/cmf/commitField/domain/commit/sinceCommit/controller/SinceCommitController.java b/src/main/java/cmf/commitField/domain/commit/sinceCommit/controller/SinceCommitController.java new file mode 100644 index 0000000..d7ba5bf --- /dev/null +++ b/src/main/java/cmf/commitField/domain/commit/sinceCommit/controller/SinceCommitController.java @@ -0,0 +1,31 @@ +package cmf.commitField.domain.commit.sinceCommit.controller; + +import cmf.commitField.domain.commit.sinceCommit.dto.SinceCommitResponseDto; +import cmf.commitField.domain.commit.sinceCommit.service.SinceCommitService; +import lombok.RequiredArgsConstructor; +import org.springframework.format.annotation.DateTimeFormat; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import java.time.LocalDateTime; +import java.util.List; + +@RestController +@RequiredArgsConstructor +public class SinceCommitController { + private final SinceCommitService sinceCommitService; + + @GetMapping("/api/github/commits-since") + public ResponseEntity> getCommits( + @RequestParam String owner, + @RequestParam String repo, + @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime since, + @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime until + ) { + List sinceCommits = sinceCommitService.getSinceCommits(owner, repo, since, until); + + return ResponseEntity.ok(sinceCommits); + } +} diff --git a/src/main/java/cmf/commitField/domain/commit/sinceCommit/dto/SinceCommitResponseDto.java b/src/main/java/cmf/commitField/domain/commit/sinceCommit/dto/SinceCommitResponseDto.java new file mode 100644 index 0000000..90cbb31 --- /dev/null +++ b/src/main/java/cmf/commitField/domain/commit/sinceCommit/dto/SinceCommitResponseDto.java @@ -0,0 +1,37 @@ +package cmf.commitField.domain.commit.sinceCommit.dto; + +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +public class SinceCommitResponseDto { + private String sha; + private Commit commit; + private Author author; + private String html_url; + + + @Getter + @NoArgsConstructor + public static class Commit { + private CommitAuthor author; // 원래 코드 작성자 + private String message; + + @Getter + @NoArgsConstructor + public static class CommitAuthor { + private String name; // 커밋한 사람의 깃허브 이름 + private String email; + private String date; + } + } + + @Getter + @NoArgsConstructor + public static class Author { + private String login; // 커밋한 사람의 깃허브 id + private String avatar_url; + private String html_url; // 사용자의 깃허브 주소 + } +} diff --git a/src/main/java/cmf/commitField/domain/commit/sinceCommit/service/SinceCommitService.java b/src/main/java/cmf/commitField/domain/commit/sinceCommit/service/SinceCommitService.java new file mode 100644 index 0000000..f4c985f --- /dev/null +++ b/src/main/java/cmf/commitField/domain/commit/sinceCommit/service/SinceCommitService.java @@ -0,0 +1,64 @@ +package cmf.commitField.domain.commit.sinceCommit.service; + +import cmf.commitField.domain.commit.sinceCommit.dto.SinceCommitResponseDto; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.stereotype.Service; +import org.springframework.web.reactive.function.client.WebClient; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.List; + +@Slf4j +@Service +public class SinceCommitService { + private static final String BASE_URL = "https://api.github.com"; + // ?since=2024-01-01T00:00:00Z&until=2025-02-1T23:59:59Z + + @Value("${github.token}") + private String PAT; + + private final WebClient webClient = WebClient.builder() + .baseUrl(BASE_URL) + .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) + .build(); + + public List getSinceCommits(String owner, String repo, LocalDateTime since, LocalDateTime until) { + try { + return webClient.get() + .uri(uriBuilder -> uriBuilder + .path("/repos/{owner}/{repo}/commits") + .queryParam("since", since.format(DateTimeFormatter.ISO_DATE_TIME)) + .queryParam("until", until.format(DateTimeFormatter.ISO_DATE_TIME)) + .build(owner, repo)) + .header("Authorization", "bearer " + PAT) + .retrieve() + .bodyToMono(new ParameterizedTypeReference>() {}) + .block(); + } catch (Exception e) { + log.error("GitHub API 호출 중 오류 발생: {}", e.getMessage()); + throw new RuntimeException("GitHub API 호출 중 오류가 발생했습니다.", e); + } + } +} + /* + ParameterizedTypeReference를 사용하는 주요 이유 + 1. 제네릭 타입 정보 보존 + 2. 복잡한 타입 구조 처리 가능 + 3. 타입 안전성 보장 + 4. 런타임에 올바른 타입으로 역직렬화 가능 + + ParameterizedTypeReference를 사용하지 않으면 + // 잘못된 예시 + List commits = webClient.get() + .retrieve() + .bodyToMono(List.class) + .block(); + + // 런타임 에러 발생 가능 + GitHubCommitResponse commit = commits.get(0); // ClassCastException 발생 위험 + */ \ No newline at end of file diff --git a/src/main/java/cmf/commitField/domain/totalCommit/config/WebConfig.java b/src/main/java/cmf/commitField/domain/commit/totalCommit/config/WebConfig.java similarity index 90% rename from src/main/java/cmf/commitField/domain/totalCommit/config/WebConfig.java rename to src/main/java/cmf/commitField/domain/commit/totalCommit/config/WebConfig.java index 5210512..26654db 100644 --- a/src/main/java/cmf/commitField/domain/totalCommit/config/WebConfig.java +++ b/src/main/java/cmf/commitField/domain/commit/totalCommit/config/WebConfig.java @@ -1,4 +1,4 @@ -package cmf.commitField.domain.totalCommit.config; +package cmf.commitField.domain.commit.totalCommit.config; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; diff --git a/src/main/java/cmf/commitField/domain/totalCommit/controller/TotalCommitController.java b/src/main/java/cmf/commitField/domain/commit/totalCommit/controller/TotalCommitController.java similarity index 72% rename from src/main/java/cmf/commitField/domain/totalCommit/controller/TotalCommitController.java rename to src/main/java/cmf/commitField/domain/commit/totalCommit/controller/TotalCommitController.java index 51d1757..ecac86b 100644 --- a/src/main/java/cmf/commitField/domain/totalCommit/controller/TotalCommitController.java +++ b/src/main/java/cmf/commitField/domain/commit/totalCommit/controller/TotalCommitController.java @@ -1,7 +1,7 @@ -package cmf.commitField.domain.totalCommit.controller; +package cmf.commitField.domain.commit.totalCommit.controller; -import cmf.commitField.domain.totalCommit.dto.TotalCommitResponseDto; -import cmf.commitField.domain.totalCommit.service.TotalCommitService; +import cmf.commitField.domain.commit.totalCommit.dto.TotalCommitResponseDto; +import cmf.commitField.domain.commit.totalCommit.service.TotalCommitService; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; diff --git a/src/main/java/cmf/commitField/domain/totalCommit/dto/TotalCommitGraphQLResponse.java b/src/main/java/cmf/commitField/domain/commit/totalCommit/dto/TotalCommitGraphQLResponse.java similarity index 93% rename from src/main/java/cmf/commitField/domain/totalCommit/dto/TotalCommitGraphQLResponse.java rename to src/main/java/cmf/commitField/domain/commit/totalCommit/dto/TotalCommitGraphQLResponse.java index 6f27b7c..6d45eeb 100644 --- a/src/main/java/cmf/commitField/domain/totalCommit/dto/TotalCommitGraphQLResponse.java +++ b/src/main/java/cmf/commitField/domain/commit/totalCommit/dto/TotalCommitGraphQLResponse.java @@ -1,4 +1,4 @@ -package cmf.commitField.domain.totalCommit.dto; +package cmf.commitField.domain.commit.totalCommit.dto; import lombok.Getter; import lombok.NoArgsConstructor; diff --git a/src/main/java/cmf/commitField/domain/totalCommit/dto/TotalCommitResponseDto.java b/src/main/java/cmf/commitField/domain/commit/totalCommit/dto/TotalCommitResponseDto.java similarity index 82% rename from src/main/java/cmf/commitField/domain/totalCommit/dto/TotalCommitResponseDto.java rename to src/main/java/cmf/commitField/domain/commit/totalCommit/dto/TotalCommitResponseDto.java index e18b023..b71a44e 100644 --- a/src/main/java/cmf/commitField/domain/totalCommit/dto/TotalCommitResponseDto.java +++ b/src/main/java/cmf/commitField/domain/commit/totalCommit/dto/TotalCommitResponseDto.java @@ -1,4 +1,4 @@ -package cmf.commitField.domain.totalCommit.dto; +package cmf.commitField.domain.commit.totalCommit.dto; import lombok.AllArgsConstructor; import lombok.Getter; diff --git a/src/main/java/cmf/commitField/domain/totalCommit/service/TotalCommitService.java b/src/main/java/cmf/commitField/domain/commit/totalCommit/service/TotalCommitService.java similarity index 90% rename from src/main/java/cmf/commitField/domain/totalCommit/service/TotalCommitService.java rename to src/main/java/cmf/commitField/domain/commit/totalCommit/service/TotalCommitService.java index 44f4374..e37bfcd 100644 --- a/src/main/java/cmf/commitField/domain/totalCommit/service/TotalCommitService.java +++ b/src/main/java/cmf/commitField/domain/commit/totalCommit/service/TotalCommitService.java @@ -1,7 +1,7 @@ -package cmf.commitField.domain.totalCommit.service; +package cmf.commitField.domain.commit.totalCommit.service; -import cmf.commitField.domain.totalCommit.dto.TotalCommitGraphQLResponse; -import cmf.commitField.domain.totalCommit.dto.TotalCommitResponseDto; +import cmf.commitField.domain.commit.totalCommit.dto.TotalCommitGraphQLResponse; +import cmf.commitField.domain.commit.totalCommit.dto.TotalCommitResponseDto; import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpHeaders; From ad6f53c1b62a413270a4bd074aa6bf3eb657171f Mon Sep 17 00:00:00 2001 From: baeksunghyun Date: Mon, 24 Feb 2025 11:11:32 +0900 Subject: [PATCH 2/2] =?UTF-8?q?Feat:=20=EC=82=AC=EC=9A=A9=EC=9E=90?= =?UTF-8?q?=EC=99=80=20=EB=A0=88=ED=8F=AC=EC=A7=80=ED=86=A0=EB=A6=AC?= =?UTF-8?q?=EB=A5=BC=20=ED=86=B5=ED=95=B4=EC=84=9C=20=EC=8B=9C=EC=A6=8C=20?= =?UTF-8?q?=EB=B3=84=20=EC=BB=A4=EB=B0=8B=20=EB=B6=88=EB=9F=AC=EC=98=A4?= =?UTF-8?q?=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .DS_Store | Bin 0 -> 6148 bytes src/.DS_Store | Bin 0 -> 6148 bytes src/main/.DS_Store | Bin 0 -> 6148 bytes src/main/java/.DS_Store | Bin 0 -> 6148 bytes src/main/java/cmf/.DS_Store | Bin 0 -> 6148 bytes src/main/java/cmf/commitField/.DS_Store | Bin 0 -> 6148 bytes .../java/cmf/commitField/domain/.DS_Store | Bin 0 -> 6148 bytes .../controller/SinceCommitController.java | 64 ++++++++++++++++++ 8 files changed, 64 insertions(+) create mode 100644 .DS_Store create mode 100644 src/.DS_Store create mode 100644 src/main/.DS_Store create mode 100644 src/main/java/.DS_Store create mode 100644 src/main/java/cmf/.DS_Store create mode 100644 src/main/java/cmf/commitField/.DS_Store create mode 100644 src/main/java/cmf/commitField/domain/.DS_Store diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..9a874b5768f336915163bb88cd434575b859f936 GIT binary patch literal 6148 zcmeH~Jr2S!425ml0g0s}V-^m;4I%_5-~tF3k&vj^b9A16778<}(6eNJu~Vz<8=6`~ zboab&MFtUB!i}=AFfm2m$tVxGT*u4pe81nUlA49C} z?O@64YO)2RT{MRe%{!}2F))pG(Sih~)xkgosK7*lF7m<7{{#Hn{6A@7N(HFEpDCdI z{V4u3`M`g7D#EfOgRk)$PGpaPQV2S&>%r5BKkQx-ySzvsH0W%E!l7ES!;KH zv9ktX>-*^w7y&HlPOLmk%$N_j;tOYdpMH*)!|itQBJHgMp3+B5_H$d10#ZNMM4T9irw zDe%t}uwk>?toc%Twm!X{*Y{cVb)%DUIm54?049DEf6&9YUwlE)m< zk%er^j=Knh3!DIf); zz>E~gV|@8Jqi52iNC7D@4+Z@DQ0UH@Y@PAxV2BZb99RzHI%Wy7c!8|R*2xOZa(b|A zwHQOZ9_?hw>uR!f_I6kfAC`AEpJHg%+hK(X&1yhF3P^#80*juHe*W+1ujcQ^n8@Auu4PPqH)~DC=`aY|^Zges(XZZ6Iz{HQ@6+Mjm#TR5vwoX=P`Vj~j6r{kv GD)0dNyb`AX literal 0 HcmV?d00001 diff --git a/src/main/java/.DS_Store b/src/main/java/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..db39f9807dc0183e11608f08346f390a73ffc47e GIT binary patch literal 6148 zcmeH~Jr2S!425lAKw|00n1usyg9yP1xBvpgRMY{n=jc5DEEHx`p=ZhdVy9NyH#D_~ z=kmcf)?M1z3|Uhzg890xkms75J$FF9JIe AV*mgE literal 0 HcmV?d00001 diff --git a/src/main/java/cmf/.DS_Store b/src/main/java/cmf/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..4a1c4db0a8d66242490fd959101caae605bf1fd2 GIT binary patch literal 6148 zcmeHKJ5Iw;5S)b+kL!UI;@5dt0!AcC>BrW`7O#}JyB5#NP%+& zZgac!{{KM#WBxxUX(t7wz*Q+=tNqh{$5*P}x_CM7wT*tDd(Ai9jq9K=L^~!%JLbmQ e@m&;UUGp{X_rf_b=*$P5sGkAXMJ5IQTY(=QXce{q literal 0 HcmV?d00001 diff --git a/src/main/java/cmf/commitField/.DS_Store b/src/main/java/cmf/commitField/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..23d2133ef3feb361f736a6ca73a3d7daf6bf14a3 GIT binary patch literal 6148 zcmeHKJ8r`;3?&nzFpwoqFDd5&a(cM$dm80eHGc<6!xkHObfO-&L_u=DZJWtcO$o@WH+y@zCk~ew& z%C`*~6`%rCfC^9nDzLf&Sz_DW>L>F+DnJGPx&ronC~(7?I0yQt1B15!zy@JA%)OTY z77GAt;v9$wOoIvxs%DF!K}Wn~UQL_>gD#rQhvvHE|AfI^s?T@@K$wp;3X~R^SGK-W7-d literal 0 HcmV?d00001 diff --git a/src/main/java/cmf/commitField/domain/.DS_Store b/src/main/java/cmf/commitField/domain/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..f943dc414758466700d81472ad03c158e7329550 GIT binary patch literal 6148 zcmeHKI}XAy47C9vBo;=-T!9-z2u{ES5U?PDIskho&c)Gq{tTeP1_S81a$e&2rRp2v zT10ey+08^IA~J#-%GHLh*}i$ldKpn59B1t1ygO|Vo2EH*vR?;`JCv<7a>Vn%w+$K< zpaN8Y3Qz$m@NosQ#E!-vKbZ$o0V?q83fTQn;D$A^4fLx6gSP;{0m5#WdoKYj768`7 zHV_e*1{D}o%@#w0j(Ewun%D*gT{N2y%{OayDC%#=`Nh*kYamA|Kn0!^=*Mzm^?wO} z)Bit{xS|47;I9lb| WO>6_5j=0l-{24G^XjI_a3fuvn5fz^R literal 0 HcmV?d00001 diff --git a/src/main/java/cmf/commitField/domain/commit/sinceCommit/controller/SinceCommitController.java b/src/main/java/cmf/commitField/domain/commit/sinceCommit/controller/SinceCommitController.java index d7ba5bf..b5fae86 100644 --- a/src/main/java/cmf/commitField/domain/commit/sinceCommit/controller/SinceCommitController.java +++ b/src/main/java/cmf/commitField/domain/commit/sinceCommit/controller/SinceCommitController.java @@ -10,6 +10,7 @@ import org.springframework.web.bind.annotation.RestController; import java.time.LocalDateTime; +import java.time.temporal.TemporalAdjusters; import java.util.List; @RestController @@ -28,4 +29,67 @@ public ResponseEntity> getCommits( return ResponseEntity.ok(sinceCommits); } + + // 시즌 별 커밋 수 불러오기 + + // 봄 시즌 + @GetMapping("/api/github/commits-spring") + public ResponseEntity> getSpringSeasonCommits( + @RequestParam String owner, + @RequestParam String repo + ) { + int currentYear = LocalDateTime.now().getYear(); + LocalDateTime since = LocalDateTime.of(2024, 3, 1, 0, 0); + LocalDateTime until = LocalDateTime.of(2024, 5, 31, 23, 59, 59); + + List sinceCommits = sinceCommitService.getSinceCommits(owner, repo, since, until); + + return ResponseEntity.ok(sinceCommits); + } + + // 여름 시즌 + @GetMapping("/api/github/commits-summer") + public ResponseEntity> getSummerSeasonCommits( + @RequestParam String owner, + @RequestParam String repo + ) { + int currentYear = LocalDateTime.now().getYear(); + LocalDateTime since = LocalDateTime.of(currentYear, 6, 1, 0, 0); + LocalDateTime until = LocalDateTime.of(currentYear, 8, 31, 23, 59, 59); + + List sinceCommits = sinceCommitService.getSinceCommits(owner, repo, since, until); + + return ResponseEntity.ok(sinceCommits); + } + + // 가을 시즌 + @GetMapping("/api/github/commits-fall") + public ResponseEntity> getFallSeasonCommits( + @RequestParam String owner, + @RequestParam String repo + ) { + int currentYear = LocalDateTime.now().getYear(); + LocalDateTime since = LocalDateTime.of(currentYear, 9, 1, 0, 0); + LocalDateTime until = LocalDateTime.of(currentYear, 11, 30, 23, 59, 59); + + List sinceCommits = sinceCommitService.getSinceCommits(owner, repo, since, until); + + return ResponseEntity.ok(sinceCommits); + } + + // 겨울 시즌 + @GetMapping("/api/github/commits-winter") + public ResponseEntity> getWinterSeasonCommits( + @RequestParam String owner, + @RequestParam String repo + ) { + int currentYear = LocalDateTime.now().getYear(); + LocalDateTime since = LocalDateTime.of(currentYear, 12, 1, 0, 0); + LocalDateTime until = LocalDateTime.of(currentYear + 1, 2, 1, 23, 59, 59) + .with(TemporalAdjusters.lastDayOfMonth()); // 윤년 고려 + + List sinceCommits = sinceCommitService.getSinceCommits(owner, repo, since, until); + + return ResponseEntity.ok(sinceCommits); + } }