From b40cd79eeda9e96aca60c05d2f7d26ccff07e1d8 Mon Sep 17 00:00:00 2001 From: gitdog01 Date: Sat, 6 Jan 2024 23:43:09 +0900 Subject: [PATCH 1/2] =?UTF-8?q?commit=20=EB=82=A0=EC=A7=9C,=20commit=20Lan?= =?UTF-8?q?g=20=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bun.lockb | Bin 68623 -> 90812 bytes package.json | 1 + src/routes/v1/index.ts | 21 +++-- src/services/commit/index.ts | 148 +++++++++++++++++++++++++++++++---- src/services/index.ts | 7 +- 5 files changed, 151 insertions(+), 26 deletions(-) diff --git a/bun.lockb b/bun.lockb index 8b8ef37d7aaefb2b5029763360081d07ff0e8b06..230956749488e0acff841a2ed6692d7d62b86bd8 100755 GIT binary patch delta 21223 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 delta 7629 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 diff --git a/package.json b/package.json index a953ae6..7859bac 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "@types/axios": "^0.14.0", "axios": "^1.6.2", "express": "^4.18.2", + "octokit": "^3.1.2", "prettier": "^3.1.1", "query-string": "^8.1.0", "swagger-jsdoc": "^6.2.8", diff --git a/src/routes/v1/index.ts b/src/routes/v1/index.ts index d283fdb..ad282fa 100644 --- a/src/routes/v1/index.ts +++ b/src/routes/v1/index.ts @@ -6,6 +6,10 @@ import { getUserRepoStars, getFriendsCount, } from "@/services/index"; +import { + getMost3UsedLanguageInCommit, + getMostCommitDay, +} from "@/services/commit"; const router = express.Router(); @@ -55,21 +59,26 @@ router.get("/data", async (req, res) => { const user = await getUser(accessToken); const userName = user.login; - const commits = await getUserCommits(accessToken, userName, { + const commitsByRepo = await getUserCommits(accessToken, userName, { since: "2023-01-01T00:00:00Z", until: "2024-01-01T00:00:00Z", per_page: 100, }); - console.log(commits); + const commits = Object.values(commitsByRepo).flat(Infinity); const starCount = await getUserRepoStars(accessToken, userName); const { followerCount, followingCount } = await getFriendsCount(accessToken); - const mostUsedLanguage = ["JavaScript", "TypeScript", "Python"]; // string[] - const moreThan = "high"; // high, middle, low - const commitCount = 1234; // number - const commitDate = "월요일"; // 월요일, 화요일, 수요일, 목요일, 금요일, 토요일, 일요일 + const mostUsedLanguage = getMost3UsedLanguageInCommit(commits); + let moreThan = "high"; + const commitCount = commits.length; // number + if (commitCount > 100) moreThan = "high"; + else if (commitCount > 50) moreThan = "middle"; + else moreThan = "low"; + + const mostCommitDay = getMostCommitDay(commits); + const commitDate = mostCommitDay; // 월요일, 화요일, 수요일, 목요일, 금요일, 토요일, 일요일 const mostCommunication = { // 여기 줄때 github profile 주소도 주면 좋지 않을까 ? name: "bsy1141", // string diff --git a/src/services/commit/index.ts b/src/services/commit/index.ts index c57310e..77528fb 100644 --- a/src/services/commit/index.ts +++ b/src/services/commit/index.ts @@ -1,5 +1,4 @@ -import { getGithubAxiosInstance } from '@/utils/github'; -import qs from 'query-string'; +import { Octokit } from "octokit"; type TQuery = { [key: string]: any; @@ -11,18 +10,135 @@ export const getRepoCommits = async ( repoName: string, query: TQuery = {}, ) => { - const instance = getGithubAxiosInstance(accessToken); - const url = qs.stringifyUrl( - { - url: `/repos/${ownerName}/${repoName}/commits`, - query, - }, - { - skipNull: true, - skipEmptyString: true, - }, - ); - const { data } = await instance.get(url); - - return data; + const octokit = new Octokit({ + auth: accessToken, + }); + + const { data } = await octokit.request("GET /repos/{owner}/{repo}/commits", { + owner: ownerName, + repo: repoName, + ...query, + }); + + const myCommits = data.filter((commit) => commit.author?.login === ownerName); + + const details = []; + for (const commit of myCommits) { + const { sha } = commit; + const { data } = await octokit.request( + "GET /repos/{owner}/{repo}/commits/{commit_sha}", + { + owner: ownerName, + repo: repoName, + commit_sha: sha, + }, + ); + details.push({ + files: data.files, + date: data.commit.author.date, + message: data.commit.message, + parents: data.parents, + }); + } + + return details; +}; + +const extensionToLanguage = (extension: string) => { + const map = { + ts: "typescript", + js: "javascript", + py: "python", + go: "go", + java: "java", + rb: "ruby", + php: "php", + html: "html", + css: "css", + scss: "scss", + sass: "sass", + less: "less", + tsx: "typescript", + jsx: "javascript", + json: "json", + yml: "yaml", + yaml: "yaml", + md: "markdown", + sh: "shell", + sql: "sql", + kt: "kotlin", + cs: "csharp", + swift: "swift", + dart: "dart", + rs: "rust", + fs: "fsharp", + fsx: "fsharp", + fsi: "fsharp", + hs: "haskell", + ex: "elixir", + exs: "elixir", + erl: "erlang", + clj: "clojure", + cljs: "clojure", + cljc: "clojure", + edn: "clojure", + lua: "lua", + scala: "scala", + sc: "scala", + vue: "vue", + cpp: "cpp", + c: "c", + h: "c", + m: "objectivec", + mm: "objectivec", + }; + return (map as { [key: string]: string })[extension]; +}; + +export const getMost3UsedLanguageInCommit = (commits: any[]) => { + const languageMap = new Map(); + for (const commit of commits) { + const { files } = commit; + for (const file of files) { + const { filename } = file; + const extension = filename.split(".").slice(-1)[0]; + const language = extensionToLanguage(extension); + if (!language) continue; + if (languageMap.has(language)) { + languageMap.set(language, languageMap.get(language) + 1); + } else { + languageMap.set(language, 1); + } + } + } + + const sorted = [...languageMap.entries()].sort((a, b) => b[1] - a[1]); + const mostUsedLanguage = sorted.slice(0, 3).map((item) => item[0]); + return mostUsedLanguage; +}; + +export const getMostCommitDay = (commits: any[]) => { + const dayMap = new Map(); + for (const commit of commits) { + const { date } = commit; + const day = new Date(date).getDay(); + if (dayMap.has(day)) { + dayMap.set(day, dayMap.get(day) + 1); + } else { + dayMap.set(day, 1); + } + } + + const sorted = [...dayMap.entries()].sort((a, b) => b[1] - a[1]); + const mostCommitDay = sorted[0][0]; + const dayMap2 = new Map([ + [0, "일요일"], + [1, "월요일"], + [2, "화요일"], + [3, "수요일"], + [4, "목요일"], + [5, "금요일"], + [6, "토요일"], + ]); + return dayMap2.get(mostCommitDay); }; diff --git a/src/services/index.ts b/src/services/index.ts index ad0c944..c8b6293 100644 --- a/src/services/index.ts +++ b/src/services/index.ts @@ -1,6 +1,6 @@ -import { getRepos, getRepoStars } from './repo'; -import { getRepoCommits } from './commit/'; -import { getUser } from './user'; +import { getRepos, getRepoStars } from "./repo"; +import { getRepoCommits } from "./commit/"; +import { getUser } from "./user"; async function getTotalRepoCommits({ ownerName, @@ -91,7 +91,6 @@ export const getUserRepoStars = async ( const jobs = Promise.all(queue); return (await jobs).reduce((acc, cur) => { - console.log(acc, cur); return acc + cur; }, 0); }; From 979ac81434fd436d7b0ded4882c6c788ca067579 Mon Sep 17 00:00:00 2001 From: gitdog01 Date: Sun, 7 Jan 2024 22:00:03 +0900 Subject: [PATCH 2/2] =?UTF-8?q?=EB=8B=A4=EB=A5=B8=20=EB=A0=88=ED=8F=AC?= =?UTF-8?q?=EB=8F=84=20=EA=B0=80=EC=A0=B8=EC=98=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/routes/v1/index.ts | 6 +++- src/services/commit/index.ts | 62 +++++++++++++++++++++++++++++++++++- 2 files changed, 66 insertions(+), 2 deletions(-) diff --git a/src/routes/v1/index.ts b/src/routes/v1/index.ts index ad282fa..a8b8de2 100644 --- a/src/routes/v1/index.ts +++ b/src/routes/v1/index.ts @@ -9,6 +9,7 @@ import { import { getMost3UsedLanguageInCommit, getMostCommitDay, + getMyRepoCommits, } from "@/services/commit"; const router = express.Router(); @@ -59,13 +60,16 @@ router.get("/data", async (req, res) => { const user = await getUser(accessToken); const userName = user.login; + /* const commitsByRepo = await getUserCommits(accessToken, userName, { since: "2023-01-01T00:00:00Z", until: "2024-01-01T00:00:00Z", per_page: 100, }); + */ + const commits = await getMyRepoCommits(accessToken, userName); - const commits = Object.values(commitsByRepo).flat(Infinity); + // const commits = Object.values(commitsByRepo).flat(Infinity); const starCount = await getUserRepoStars(accessToken, userName); const { followerCount, followingCount } = await getFriendsCount(accessToken); diff --git a/src/services/commit/index.ts b/src/services/commit/index.ts index 77528fb..aa69179 100644 --- a/src/services/commit/index.ts +++ b/src/services/commit/index.ts @@ -14,13 +14,20 @@ export const getRepoCommits = async ( auth: accessToken, }); + /* const { data } = await octokit.request("GET /repos/{owner}/{repo}/commits", { owner: ownerName, repo: repoName, ...query, }); + */ + const { data } = await octokit.request("GET /search/commits", { + q: `author:${ownerName} author-date:2023-01-01..2023-12-31`, + }); + + const myCommits = data.items; - const myCommits = data.filter((commit) => commit.author?.login === ownerName); + console.log(myCommits); const details = []; for (const commit of myCommits) { @@ -44,6 +51,59 @@ export const getRepoCommits = async ( return details; }; +export const getMyRepoCommits = async ( + accessToken: string, + userName: string, +) => { + let pagesRemaining = true; + let data: any[] = []; + let count = 1; + const octokit = new Octokit({ + auth: accessToken, + }); + + while (pagesRemaining) { + const response = await octokit.request("GET /search/commits", { + q: `author:${userName} author-date:2023-01-01..2023-12-31`, + per_page: 100, + page: count, + }); + + data = [...data, ...response.data.items]; + + const linkHeader = response.headers.link; + + pagesRemaining = !!(linkHeader && linkHeader.includes(`rel=\"next\"`)); + + if (pagesRemaining) { + count++; + } + } + console.log(data.length); + const details = []; + let remaining = data.length; + for (const commit of data) { + console.log(remaining--); + const { sha, repository } = commit; + const { data } = await octokit.request( + "GET /repos/{owner}/{repo}/commits/{commit_sha}", + { + owner: repository.full_name.split("/")[0], + repo: repository.full_name.split("/")[1], + commit_sha: sha, + }, + ); + details.push({ + files: data.files, + date: data.commit.author.date, + message: data.commit.message, + parents: data.parents, + }); + } + + return details; +}; + const extensionToLanguage = (extension: string) => { const map = { ts: "typescript",