This repository was archived by the owner on Mar 11, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgithubinfocard.go
128 lines (104 loc) · 2.8 KB
/
githubinfocard.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
package githubinfocard
import (
"context"
"encoding/json"
"fmt"
"os"
"strings"
// "github.com/davecgh/go-spew/spew"
"github.com/shurcooL/githubv4"
"golang.org/x/oauth2"
)
const (
githubPrefix = "https://github.com/"
)
// Card defines a repository info card
type Card struct {
Forks int
LastRelease string
Languages []Language
Name string
OpenIssues int
Owner string
URL string
Stars int
}
// Language defines a single programming language
type Language struct {
Name string
Color string
}
// Load tries to load a Card for given repository URL
func Load(url, token string) (*Card, int, error) {
c := Card{
URL: url,
}
if !strings.HasPrefix(url, githubPrefix) {
return &c, 0, fmt.Errorf("URL has to start with \"%s\"", githubPrefix)
}
// Extract owner and repo name from url
var err error
c.Owner, c.Name, err = parseURL(url)
if err != nil {
return &c, 0, err
}
// API call
graph, err := fetchGraph(token, c.Owner, c.Name)
if err != nil {
return &c, 0, err
}
// printJSON(graph)
// Extract from graph
c.Forks = int(graph.Repository.Forks.TotalCount)
c.OpenIssues = int(graph.Repository.Issues.TotalCount)
c.Stars = int(graph.Repository.Stargazers.TotalCount)
if len(graph.Repository.Releases.Nodes) >= 1 {
c.LastRelease = string(graph.Repository.Releases.Nodes[0].Name)
}
for _, lang := range graph.Repository.Languages.Nodes {
c.Languages = append(c.Languages, Language{
Name: string(lang.Name),
Color: string(lang.Color),
})
}
return &c, int(graph.RateLimit.Remaining), nil
}
func parseURL(url string) (string, string, error) {
tmp := strings.Replace(url, githubPrefix, "", -1)
tmp = strings.TrimRight(tmp, "/")
parts := strings.Split(tmp, "/")
if len(parts) != 2 {
return "", "", fmt.Errorf("URL invalid, expected \"ownerName/repoName\", got \"%s\"", tmp)
}
if parts[0] == "" || parts[1] == "" {
return "", "", fmt.Errorf("URL invalid, expected \"ownerName/repoName\", got \"%s\"", tmp)
}
return parts[0], parts[1], nil
}
func fetchGraph(token, owner, repo string) (*Graph, error) {
src := oauth2.StaticTokenSource(
&oauth2.Token{AccessToken: token},
)
httpClient := oauth2.NewClient(context.Background(), src)
client := githubv4.NewClient(httpClient)
gqlVars := map[string]interface{}{
"repositoryOwner": githubv4.String(owner),
"repositoryName": githubv4.String(repo),
}
var graph Graph
err := client.Query(context.Background(), &graph, gqlVars)
if err != nil {
return &graph, fmt.Errorf("could not query GitHub API: \"%s\"", err.Error())
}
return &graph, nil
}
// printJSON prints v as JSON encoded with indent to stdout. It panics on any error.
// only for testing.
func printJSON(v interface{}) {
w := json.NewEncoder(os.Stdout)
w.SetIndent("", "\t")
err := w.Encode(v)
if err != nil {
panic(err)
}
}