67 lines
1.7 KiB
Go
67 lines
1.7 KiB
Go
// Package github provides a Go API for the GitHub issue tracker.
|
||
// See https://developer.github.com/v3/search/#search-issues.
|
||
package github
|
||
|
||
import (
|
||
"encoding/json"
|
||
"fmt"
|
||
"net/http"
|
||
"net/url"
|
||
"strings"
|
||
"time"
|
||
)
|
||
|
||
const IssuesURL = "https://api.github.com/search/issues"
|
||
|
||
type IssuesSearchResult struct {
|
||
TotalCount int `json:"total_count"`
|
||
Items []*Issue
|
||
}
|
||
|
||
type Issue struct {
|
||
Number int
|
||
HTMLURL string `json:"html_url"`
|
||
Title string
|
||
State string
|
||
User *User
|
||
CreatedAt time.Time `json:"created_at"`
|
||
Body string // in Markdown format
|
||
}
|
||
|
||
type User struct {
|
||
Login string
|
||
HTMLURL string `json:"html_url"`
|
||
}
|
||
|
||
// 和前面一样,即使对应的JSON对象名是小写字母,
|
||
// 每个结构体的成员名也是声明为大写字母开头的。
|
||
// 因为有些JSON成员名字和Go结构体成员名字并不相同,
|
||
// 因此需要Go语言结构体成员Tag来指定对应的JSON名字。
|
||
// 同样,在解码的时候也需要做同样的处理,
|
||
// GitHub服务返回的信息比我们定义的要多很多。
|
||
|
||
// SearchIssues queries the GitHub issue tracker.
|
||
|
||
func SearchIssues(terms []string) (*IssuesSearchResult, error) {
|
||
q := url.QueryEscape(strings.Join(terms, " "))
|
||
resp, err := http.Get(IssuesURL + "?q=" + q)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
// We must close resp.Body on all execution paths.
|
||
// (Chapter 5 presents 'defer', which makes this simpler.)
|
||
if resp.StatusCode != http.StatusOK {
|
||
resp.Body.Close()
|
||
return nil, fmt.Errorf("search query failed: %s", resp.Status)
|
||
}
|
||
|
||
var result IssuesSearchResult
|
||
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
|
||
resp.Body.Close()
|
||
return nil, err
|
||
}
|
||
resp.Body.Close()
|
||
return &result, nil
|
||
}
|