126 lines
3.7 KiB
Go
126 lines
3.7 KiB
Go
// Client to Github APIs
|
|
package github
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"net/url"
|
|
"strconv"
|
|
"time"
|
|
|
|
"sirherobrine23.com.br/go-bds/request/v3"
|
|
)
|
|
|
|
var (
|
|
GithubAPI = &url.URL{Scheme: "https", Host: "api.github.com", Path: "/"} // Defaut github api
|
|
|
|
ErrToken error = errors.New("require Token to request")
|
|
|
|
err500 = request.ProcessRequest(func(req *request.RequestStatus) (res *http.Response, err error) {
|
|
buffLog, _ := io.ReadAll(req.Res.Body)
|
|
if res.Body != nil {
|
|
res.Body.Close()
|
|
}
|
|
if len(buffLog) == 0 {
|
|
buffLog = []byte("not body response")
|
|
}
|
|
return nil, fmt.Errorf("cannot process request (%s), github api is down: %s", res.Request.URL.String(), buffLog)
|
|
})
|
|
|
|
processCodes = request.CodeProcess{
|
|
500: err500,
|
|
501: err500,
|
|
401: func(req *request.RequestStatus) (res *http.Response, err error) {
|
|
if res.Body != nil {
|
|
res.Body.Close()
|
|
}
|
|
return nil, ErrToken
|
|
},
|
|
403: func(req *request.RequestStatus) (res *http.Response, err error) {
|
|
if res.Body != nil {
|
|
res.Body.Close()
|
|
}
|
|
if retryAfter := res.Header.Get("retry-after"); retryAfter != "" && retryAfter != "0" {
|
|
if dateSec, err := strconv.ParseInt(retryAfter, 10, 64); err == nil {
|
|
<-time.After(time.Until(time.Unix(dateSec, dateSec*int64(time.Second))))
|
|
return request.Request(req.URL, req.Options)
|
|
}
|
|
} else if remining := res.Header.Get("x-ratelimit-remaining"); remining == "0" {
|
|
if reset := res.Header.Get("x-ratelimit-reset"); reset != "" {
|
|
if dateSec, err := strconv.ParseInt(reset, 10, 64); err == nil {
|
|
<-time.After(time.Until(time.Unix(dateSec, dateSec*int64(time.Second))))
|
|
return request.Request(req.URL, req.Options)
|
|
}
|
|
}
|
|
}
|
|
return nil, errors.New("cannot process request, authorization or not have permission")
|
|
},
|
|
429: func(req *request.RequestStatus) (res *http.Response, err error) {
|
|
if res.Body != nil {
|
|
res.Body.Close()
|
|
}
|
|
if retryAfter := res.Header.Get("retry-after"); retryAfter != "" && retryAfter != "0" {
|
|
if dateSec, err := strconv.ParseInt(retryAfter, 10, 64); err == nil {
|
|
<-time.After(time.Until(time.Unix(dateSec, dateSec*int64(time.Second))))
|
|
return request.Request(req.URL, req.Options)
|
|
}
|
|
} else if remining := res.Header.Get("x-ratelimit-remaining"); remining == "0" {
|
|
if reset := res.Header.Get("x-ratelimit-reset"); reset != "" {
|
|
if dateSec, err := strconv.ParseInt(reset, 10, 64); err == nil {
|
|
<-time.After(time.Until(time.Unix(dateSec, dateSec*int64(time.Second))))
|
|
return request.Request(req.URL, req.Options)
|
|
}
|
|
}
|
|
}
|
|
return nil, errors.New("many requests to github api")
|
|
},
|
|
}
|
|
)
|
|
|
|
// Create new Github Client with Github.com API host
|
|
func NewClient(Username, Repository, Token string) *Github {
|
|
return &Github{
|
|
Host: GithubAPI,
|
|
Repository: Repository,
|
|
Username: Username,
|
|
Token: Token,
|
|
}
|
|
}
|
|
|
|
// Create new Github Client
|
|
func NewClientHost(apiHost, Username, Repository, Token string) (*Github, error) {
|
|
hostUrl, err := url.Parse(apiHost)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &Github{
|
|
Host: hostUrl,
|
|
Repository: Repository,
|
|
Username: Username,
|
|
Token: Token,
|
|
}, nil
|
|
}
|
|
|
|
// Basic client to Github APIs
|
|
type Github struct {
|
|
Host *url.URL // Github API host
|
|
Token string // Github Token
|
|
|
|
// User and Repository name
|
|
Username, Repository string
|
|
}
|
|
|
|
// Return escapated Owner+/+Repository
|
|
func (client Github) repoPath() string {
|
|
return fmt.Sprintf("%s/%s", url.PathEscape(client.Username), url.PathEscape(client.Repository))
|
|
}
|
|
|
|
// Set token to header
|
|
func (client Github) authHeader(header *http.Header) {
|
|
if client.Token != "" {
|
|
(*header)["Authorization"] = []string{fmt.Sprintf("Bearer %s", client.Token)}
|
|
}
|
|
}
|