Passed
Push — main ( 4f3fcd...16925d )
by Clive
02:36 queued 19s
created

githubapi.FetchRateLimit   B

Complexity

Conditions 6

Size

Total Lines 26
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 16
nop 2
dl 0
loc 26
rs 8.6666
c 0
b 0
f 0
1
package githubapi
2
3
import (
4
	"encoding/json"
5
	"fmt"
6
	"net/http"
7
	"os"
8
	"time"
9
)
10
11
var (
12
	APIURL          = "https://api.github.com/rate_limit"
13
	AuthHeader      = "Authorization"
14
	DefaultTokenEnv = "GITHUB_TOKEN"
15
)
16
17
var TokenEnvNames = []string{
18
	"GITHUB_TOKEN",
19
	"GH_TOKEN",
20
	"GITHUB_ACCESS_TOKEN",
21
	"GH_ACCESS_TOKEN",
22
	"GITHUB_OAUTH_TOKEN",
23
	"GH_OAUTH_TOKEN",
24
	"GITHUB_PAT",
25
	"GH_PAT",
26
	"GITHUB_AUTH_TOKEN",
27
	"GH_AUTH_TOKEN",
28
	"GITHUB_API_TOKEN",
29
	"GH_API_TOKEN",
30
	"GITHUB_API_KEY",
31
	"GH_API_KEY",
32
	"GITHUB_PERSONAL_ACCESS_TOKEN",
33
	"GH_PERSONAL_ACCESS_TOKEN",
34
	"GITHUB_PERSONAL_TOKEN",
35
	"GH_PERSONAL_TOKEN",
36
	"GITHUB_PERSONAL_API_TOKEN",
37
	"GH_PERSONAL_API_TOKEN",
38
	"GITHUB_PERSONAL_API_KEY",
39
	"GH_PERSONAL_API_KEY",
40
	"GITHUB_APP_TOKEN",
41
	"GH_APP_TOKEN",
42
	"GITHUB_APP_KEY",
43
	"GH_APP_KEY",
44
}
45
46
type Rate struct {
47
	Limit     int       `json:"limit"`
48
	Remaining int       `json:"remaining"`
49
	Reset     Timestamp `json:"reset"`
50
}
51
52
type Timestamp struct {
53
	time.Time
54
}
55
56
func (t *Timestamp) UnmarshalJSON(data []byte) error {
57
	var timestamp interface{}
58
	if err := json.Unmarshal(data, &timestamp); err != nil {
59
		return err
60
	}
61
62
	switch v := timestamp.(type) {
63
	case string:
64
		// Handle string representation of Unix timestamp
65
		parsedTime, err := time.Parse(time.RFC3339Nano, v)
66
		if err != nil {
67
			return err
68
		}
69
		t.Time = parsedTime
70
	case float64:
71
		// Handle numeric representation of Unix timestamp
72
		t.Time = time.Unix(int64(v), 0)
73
	default:
74
		return fmt.Errorf("unexpected type for timestamp: %T", v)
75
	}
76
77
	return nil
78
}
79
80
type RateLimit struct {
81
	Core Rate `json:"core"`
82
}
83
84
type RateLimitResponse struct {
85
	Resources RateLimit `json:"resources"`
86
}
87
88
func FetchRateLimit(client *http.Client, token string) (RateLimitResponse, error) {
89
	req, err := http.NewRequest("GET", APIURL, nil)
90
	if err != nil {
91
		return RateLimitResponse{}, err
92
	}
93
94
	if token != "" {
95
		req.Header.Set(AuthHeader, fmt.Sprintf("token %s", token))
96
	}
97
98
	resp, err := client.Do(req)
99
	if err != nil {
100
		return RateLimitResponse{}, err
101
	}
102
	defer resp.Body.Close()
103
104
	if resp.StatusCode != http.StatusOK {
105
		return RateLimitResponse{}, fmt.Errorf("unexpected status code: %d", resp.StatusCode)
106
	}
107
108
	var rateLimitResponse RateLimitResponse
109
	if err := json.NewDecoder(resp.Body).Decode(&rateLimitResponse); err != nil {
110
		return RateLimitResponse{}, err
111
	}
112
113
	return rateLimitResponse, nil
114
}
115
116
func GetGithubTokenFromEnv() string {
117
	for _, envName := range TokenEnvNames {
118
		if token := os.Getenv(envName); token != "" {
119
			return token
120
		}
121
	}
122
	return ""
123
}
124