diff --git a/src/create_character_img.go b/src/funcs/create_character_img.go similarity index 63% rename from src/create_character_img.go rename to src/funcs/create_character_img.go index 449987c..d28496a 100644 --- a/src/create_character_img.go +++ b/src/funcs/create_character_img.go @@ -1,43 +1,41 @@ -package main - +package funcs import ( "fmt" - "github.com/tomoish/readme/funcs" ) func CreateCharacterImg() { // キャラクター画像のパス - characterPath := "funcs/images/character.png" + characterPath := "images/character.png" // ゲージ画像のパス - gaugePath := "funcs/images/gauge.png" + gaugePath := "images/gauge.png" // ゲージ画像生成のためのチャネル gaugeImageChan := make(chan []byte) // ゲージ画像を非同期で生成 go func() { - GaugeBytes, _ := funcs.DrawGauge(0.5) + GaugeBytes, _ := DrawGauge(0.5) gaugeImageChan <- GaugeBytes }() // ゲージ画像をファイルに保存 gaugeBytes := <-gaugeImageChan - err := funcs.SaveImage(gaugePath, gaugeBytes) + err := SaveImage(gaugePath, gaugeBytes) if err != nil { fmt.Println(err) return } // キャラクター画像とゲージ画像を合成 - mergedImage, err := funcs.MergeImages(characterPath, gaugePath) + mergedImage, err := MergeImages(characterPath, gaugePath) if err != nil { fmt.Println(err) return } // 画像をファイルに保存 - err = funcs.SaveImage("funcs/images/merged.png", mergedImage) + err = SaveImage("images/merged.png", mergedImage) if err != nil { fmt.Println(err) return diff --git a/src/create_language_img.go b/src/funcs/create_language_img.go similarity index 84% rename from src/create_language_img.go rename to src/funcs/create_language_img.go index f57f5fa..07a0caf 100644 --- a/src/create_language_img.go +++ b/src/funcs/create_language_img.go @@ -1,4 +1,4 @@ -package main +package funcs import ( "fmt" @@ -6,11 +6,10 @@ import ( "github.com/patrickmn/go-cache" - "github.com/tomoish/readme/funcs" ) func CreateLanguageImg() { - +// 言語ごとの色をここで決める colordict := map[string]string{ "HTML": "#E34F26", "CSS": "#ffffff", @@ -30,7 +29,7 @@ func CreateLanguageImg() { // キャッシュにデータが存在しない場合のみデータを保存 if _, found := c.Get(key); !found { // トークンを取得する - token, newCachedData = funcs.GetTokens(0) + token, newCachedData = GetTokens(0) c.Set(key, newCachedData, cache.DefaultExpiration) } else { @@ -42,7 +41,7 @@ func CreateLanguageImg() { fmt.Println("cachedIntData") fmt.Println(cachedIntData) // トークンを取得する - token, newCachedData = funcs.GetTokens(cachedIntData) + token, newCachedData = GetTokens(cachedIntData) c.Set(key, newCachedData, cache.DefaultExpiration) @@ -51,7 +50,7 @@ func CreateLanguageImg() { // ユーザーのリポジトリ情報を取得 username := "kou7306" - repos, err := funcs.GetRepositories(username, token) + repos, err := GetRepositories(username, token) fmt.Printf("repos: %v\n", repos) if err != nil { fmt.Println(err) @@ -64,7 +63,7 @@ func CreateLanguageImg() { // 各リポジトリの言語別のファイルサイズを取得 for _, repo := range repos { - repoDetails, totalSize, err := funcs.GetRepositoryLanguage(repo.Name, repo.Owner, token) + repoDetails, totalSize, err := GetRepositoryLanguage(repo.Name, repo.Owner, token) if err != nil { // エラーハンドリング @@ -82,7 +81,7 @@ func CreateLanguageImg() { } colorCode := "" - languages := []funcs.LanguageStat{} + languages := []LanguageStat{} // 各言語のファイルサイズをパーセンテージで計算 for language, size := range totalLanguageSize { percentage := float64(size) / allSize * 100.0 @@ -96,7 +95,7 @@ func CreateLanguageImg() { colorCode = colordict["others"] } - languages = append(languages, funcs.LanguageStat{ + languages = append(languages, LanguageStat{ Name: language, Percent: percentage, Color: colorCode, @@ -105,14 +104,16 @@ func CreateLanguageImg() { fmt.Printf("languages: %v\n", languages) - ImgBytes, _ := funcs.GenerateLanguageUsageGraph(languages, 600, 250) + ImgBytes, _ := GenerateLanguageUsageGraph(languages, 600, 250) // 画像をファイルに保存 - err = funcs.SaveImage("funcs/images/language.png", ImgBytes) + err = SaveImage("images/language.png", ImgBytes) if err != nil { fmt.Println(err) } + // return languages + } // func generateSessionKey() string { diff --git a/src/funcs/get_activity.go b/src/funcs/get_activity.go new file mode 100644 index 0000000..f0754f3 --- /dev/null +++ b/src/funcs/get_activity.go @@ -0,0 +1,123 @@ +package funcs + +import ( + "bytes" + "fmt" + "encoding/json" + "net/http" +) + +const ( + // GitHubのアクセストークン + accessToken = "YOUR_GITHUB_ACCESS_TOKEN" + // GitHubのGraphQL APIエンドポイント + apiEndpoint = "https://api.github.com/graphql" +) +// / GraphQLQuery はGraphQLのクエリを格納するための構造体です +type GraphQLQuery struct { + Query string `json:"query"` +} + +// GitHubのGraphQLクエリを定義 +type response struct { + Data struct { + User struct { + ContributionsCollection struct { + TotalCommitContributions int `graphql:"totalCommitContributions"` + TotalIssueContributions int `graphql:"totalIssueContributions"` + TotalPullRequestContributions int `graphql:"totalPullRequestContributions"` + TotalRepositoryContributions int `graphql:"totalRepositoryContributions"` + } `graphql:"contributionsCollection"` + StarredRepositories struct { + TotalCount int `graphql:"totalCount"` + } `graphql:"starredRepositories"` + } `graphql:"user(login: $username)"` + } +} + + +func fetchDataInTimeRange(token string, username string) (int, int, int, int, int, error) { + const query_frame = ` + { + user(login: "%s") { + contributionsCollection { + totalCommitContributions + totalIssueContributions + totalPullRequestContributions + totalRepositoryContributions + } + starredRepositories { + totalCount + } + } + } + ` + + // GraphQLクエリを構築 + query := fmt.Sprintf(query_frame, username) + + // GraphQLクエリを実行して詳細情報を取得 + request := GraphQLQuery{Query: query} + requestBody, err := json.Marshal(request) + if err != nil { + return 0, 0, 0, 0, 0, err + } + + url := "https://api.github.com/graphql" + req, err := http.NewRequest("POST", url, bytes.NewBuffer(requestBody)) + if err != nil { + return 0, 0, 0, 0, 0, err + } + req.Header.Set("Authorization", "Bearer "+token) + + client := &http.Client{} + resp, err := client.Do(req) + if err != nil { + return 0, 0, 0, 0, 0, err + } + defer resp.Body.Close() + + var response response + if err := json.NewDecoder(resp.Body).Decode(&response); err != nil { + return 0, 0, 0, 0, 0, err + } + + // 総コントリビューション数 + totalCommitContributions := response.Data.User.ContributionsCollection.TotalCommitContributions + // 総スター数 + totalStarredRepositories := response.Data.User.StarredRepositories.TotalCount + // 総Issue数 + totalIssueContributions := response.Data.User.ContributionsCollection.TotalIssueContributions + // 総PullRequest数 + totalPullRequestContributions := response.Data.User.ContributionsCollection.TotalPullRequestContributions + // 総コミット数 + totalRepositoryContributions := response.Data.User.ContributionsCollection.TotalRepositoryContributions + + return totalCommitContributions, totalStarredRepositories, totalIssueContributions, totalPullRequestContributions, totalRepositoryContributions, nil +} + + +// func main() { +// // ユーザー名 +// username := "kou7306" + +// // 期間を指定 +// // from := time.Date(2024, 2, 1, 0, 0, 0, 0, time.UTC) +// // to := time.Date(2024, 2, 1, 23, 59, 59, 0, time.UTC) + +// // GitHubのアクセストークンを設定 +// token,_ :=funcs.GetTokens(0) + +// // データを取得 +// totalCommitContributions, totalStarredRepositories, totalIssueContributions, totalPullRequestContributions, totalRepositoryContributions, err := fetchDataInTimeRange(token, username) +// if err != nil { +// fmt.Println(err) +// return +// } + +// fmt.Println("totalCommitContributions: ", totalCommitContributions) +// fmt.Println("totalStarredRepositories: ", totalStarredRepositories) +// fmt.Println("totalIssueContributions: ", totalIssueContributions) +// fmt.Println("totalPullRequestContributions: ", totalPullRequestContributions) +// fmt.Println("totalRepositoryContributions: ", totalRepositoryContributions) +// } \ No newline at end of file diff --git a/src/funcs/get_commit_streak.go b/src/funcs/get_commit_streak.go index 224407d..7684279 100644 --- a/src/funcs/get_commit_streak.go +++ b/src/funcs/get_commit_streak.go @@ -7,6 +7,8 @@ import ( "log" "net/http" "os" + + "github.com/joho/godotenv" ) const query_frame = ` @@ -27,7 +29,7 @@ const query_frame = ` } ` -type response struct { +type res struct { Data struct { User struct { ContributionsCollection struct { @@ -66,6 +68,10 @@ func calculateStreak(weeks []struct { } func GetCommitHistory(username string) (int, []int, int, error) { + err := godotenv.Load() + if err != nil { + log.Fatalf("Error loading .env file") + } query := fmt.Sprintf(query_frame, username) request := GraphQLQuery{Query: query} @@ -87,7 +93,7 @@ func GetCommitHistory(username string) (int, []int, int, error) { // fmt.Println("response1: ", resp) - var res response + var res res if err := json.NewDecoder(resp.Body).Decode(&res); err != nil { log.Fatalf("Decoder failed: %v", err) } @@ -104,7 +110,7 @@ func GetCommitHistory(username string) (int, []int, int, error) { } } - // fmt.Println("response: ", res.Data.User.ContributionsCollection.ContributionCalendar.Weeks) + // fmt.Println("res: ", res.Data.User.ContributionsCollection.ContributionCalendar.Weeks) // fmt.Println("dailyCommits: ", dailyCommits) // fmt.Println("length of dailyCommits: ", len(dailyCommits)) diff --git a/src/funcs/get_repository.go b/src/funcs/get_repository.go index 58a1633..7c34e91 100644 --- a/src/funcs/get_repository.go +++ b/src/funcs/get_repository.go @@ -7,8 +7,8 @@ import ( "net/http" ) -// / GraphQLQuery はGraphQLのクエリを格納するための構造体です -type GraphQLQuery struct { +// / GraphQLQueries はGraphQLのクエリを格納するための構造体です +type GraphQLQueries struct { Query string `json:"query"` } @@ -20,7 +20,7 @@ type Repository struct { } // レポジトリ取得の際のGraphQLのレスポンスを格納するための構造体です -type GraphQLResponse struct { +type GraphQLResponses struct { Data struct { User struct { RepositoriesContributedTo struct { @@ -76,7 +76,7 @@ func GetRepositories(username, token string) ([]Repository, error) { // GraphQL APIにリクエストを送信 url := "https://api.github.com/graphql" - reqBody := GraphQLQuery{Query: query} + reqBody := GraphQLQueries{Query: query} reqBodyJSON, err := json.Marshal(reqBody) if err != nil { fmt.Println("JSON Marshal Error:", err) @@ -100,7 +100,7 @@ func GetRepositories(username, token string) ([]Repository, error) { defer resp.Body.Close() // レスポンスをパース - var response GraphQLResponse + var response GraphQLResponses err = json.NewDecoder(resp.Body).Decode(&response) if err != nil { fmt.Println("JSON Decode Error:", err) diff --git a/src/funcs/judge_rank.go b/src/funcs/judge_rank.go new file mode 100644 index 0000000..c7bda43 --- /dev/null +++ b/src/funcs/judge_rank.go @@ -0,0 +1,92 @@ +package funcs + +// import ( +// "fmt" + +// ) + +// func JudgeRank()[ +// // データを取得 +// totalCommitContributions, totalStarredRepositories, totalIssueContributions, totalPullRequestContributions, totalRepositoryContributions, err := fetchDataInTimeRange(token, username) +// rank := "C-" + +// switch { +// case rank < 25: +// rank="C-" +// case rank < 100: +// rank="C" +// case rank < 400: +// rank="C+" +// case rank < 625: +// rank="B-" +// case rank < 1225: +// rank="B" +// case rank < 2500: +// rank="B+" +// case rank < 4900: +// rank="A-" +// case rank < 8100: +// rank="A" +// case rank < 10000: +// rank="A+" +// case 10000 <= rank: +// rank="S" +// default: +// rank="C-" + +// } + +// // 言語ごとの割合を持ってくる +// languages, err := funcs.CreateLanguageImg(username, token) + +// // Percent の大きい順にソート +// sort.Slice(languages, func(i, j int) bool { +// return languages[i].Percent > languages[j].Percent +// }) + +// //上位2つの言語を保持 +// topLanguage := []funcs.LanguageStat{} +// // 一時的に保持する +// temp := []funcs.LanguageStat{} + +// // ソートされた languages を使用する +// // 一位がHTML,CSS,JavaScript,TypeScriptじゃない場合 +// if languages[0].Name != "HTML" && languages[0].Name != "CSS" && languages[0].Name != "JavaScript" && languages[0].Name != "TypeScript"{ +// topLanguage = append(topLanguage, languages[0]) + +// } else { +// temp = append(temp, languages[0]) +// } + +// if topLanguage != [] { +// topLanguage = append(topLanguage, languages[1]) +// } +// else{ +// if languages[1].Name != "HTML" && languages[1].Name != "CSS" && languages[1].Name != "JavaScript" && languages[1].Name != "TypeScript"{ +// topLanguage = append(topLanguage, languages[1]) +// topLanguage = append(topLanguage, temp[0]) +// } + +// // 上位2つの言語がHTML,CSS,JavaScript,TypeScriptの場合 +// else{ +// temp = append(temp, languages[1]) +// // HTML,CSS,JavaScript,TypeScriptじゃない中の一位の言語を探す +// for i, language := range languages[2:] { +// if language.Name != "HTML" && language.Name != "CSS" && language.Name != "JavaScript" && language.Name != "TypeScript"{ +// if language.Percent >= 15.0{ +// topLanguage = append(topLanguage, language) +// topLanguage = append(topLanguage, temp[0]) +// } +// else{ +// topLanguage = append(topLanguage, temp[0]) +// topLanguage = append(topLanguage, temp[1]) +// } + +// } +// } +// } +// } + +// return rank +// ] + diff --git a/src/go.mod b/src/go.mod index db7fddc..ba1832f 100644 --- a/src/go.mod +++ b/src/go.mod @@ -23,4 +23,6 @@ require ( github.com/pmezard/go-difflib v1.0.0 // indirect golang.org/x/image v0.15.0 // indirect golang.org/x/text v0.14.0 // indirect + gonum.org/v1/plot v0.14.0 // indirect + ) diff --git a/src/go.sum b/src/go.sum index 9415736..c1754d3 100644 --- a/src/go.sum +++ b/src/go.sum @@ -1,3 +1,4 @@ + git.sr.ht/~sbinet/cmpimg v0.1.0 h1:E0zPRk2muWuCqSKSVZIWsgtU9pjsw3eKHi8VmQeScxo= git.sr.ht/~sbinet/cmpimg v0.1.0/go.mod h1:FU12psLbF4TfNXkKH2ZZQ29crIqoiqTZmeQ7dkp/pxE= git.sr.ht/~sbinet/gg v0.5.0 h1:6V43j30HM623V329xA9Ntq+WJrMjDxRjuAB1LFWF5m8= @@ -43,6 +44,7 @@ github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9dec golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= + golang.org/x/exp v0.0.0-20230801115018-d63ba01acd4b h1:r+vk0EmXNmekl0S0BascoeeoHk/L7wmaW2QF90K+kYI= golang.org/x/exp v0.0.0-20230801115018-d63ba01acd4b/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= golang.org/x/image v0.15.0 h1:kOELfmgrmJlw4Cdb7g/QGuB3CvDrXbqEIww/pNtNBm8= @@ -73,5 +75,3 @@ gonum.org/v1/gonum v0.14.0/go.mod h1:AoWeoz0becf9QMWtE8iWXNXc27fK4fNeHNf/oMejGfU gonum.org/v1/plot v0.14.0 h1:+LBDVFYwFe4LHhdP8coW6296MBEY4nQ+Y4vuUpJopcE= gonum.org/v1/plot v0.14.0/go.mod h1:MLdR9424SJed+5VqC6MsouEpig9pZX2VZ57H9ko2bXU= honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las= -rsc.io/pdf v0.1.1 h1:k1MczvYDUvJBe93bYd7wrZLLUEcLZAuF824/I4e5Xr4= -rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= diff --git a/src/images/gauge.png b/src/images/gauge.png new file mode 100644 index 0000000..4b5f9cf Binary files /dev/null and b/src/images/gauge.png differ diff --git a/src/main.go b/src/main.go index dbeabeb..81b8d7f 100644 --- a/src/main.go +++ b/src/main.go @@ -34,11 +34,11 @@ func handler(w http.ResponseWriter, r *http.Request) { } func getLanguageHandler(w http.ResponseWriter, r *http.Request) { - CreateLanguageImg() + funcs.CreateLanguageImg() } func getCharacterHandler(w http.ResponseWriter, r *http.Request) { - CreateCharacterImg() + funcs.CreateCharacterImg() } func getCommitStreakHandler(w http.ResponseWriter, r *http.Request) {