diff options
Diffstat (limited to 'cmd/generate/src_contribs.go')
-rw-r--r-- | cmd/generate/src_contribs.go | 103 |
1 files changed, 103 insertions, 0 deletions
diff --git a/cmd/generate/src_contribs.go b/cmd/generate/src_contribs.go new file mode 100644 index 0000000..eaff24b --- /dev/null +++ b/cmd/generate/src_contribs.go @@ -0,0 +1,103 @@ +package main + +import ( + "encoding/json" + "fmt" + "io" + "net/http" + "os" + "regexp" + "strings" + "time" + + "sigs.k8s.io/yaml" +) + +type Contribution struct { + URLs []string `json:"urls"` + Tags []string `json:"tags"` + SponsoredBy string `json:"sponsored-by"` + Desc string `json:"desc"` + + SubmittedAt time.Time `json:"submitted-at"` +} + +func ReadContribs(filename string) ([]Contribution, error) { + bs, err := os.ReadFile(filename) + if err != nil { + return nil, err + } + var ret []Contribution + if err := yaml.UnmarshalStrict(bs, &ret); err != nil { + return nil, err + } + for i := range ret { + contrib := ret[i] + if err := contrib.Fill(); err != nil { + return nil, err + } + ret[i] = contrib + } + return ret, nil +} + +func (c *Contribution) Fill() error { + var err error + if c.SubmittedAt.IsZero() { + c.SubmittedAt, err = c.getSubmittedAt() + if err != nil { + return err + } + } + return nil +} + +var ( + reGitHubPR = regexp.MustCompile(`^https://github.com/([^/?#]+)/([^/?#]+)/pull/([0-9]+)(?:\?[^#]*)?(?:#.*)?$`) + rePiperMailDate = regexp.MustCompile(`^\s*<I>([^<]+)</I>\s*$`) +) + +func (c Contribution) getSubmittedAt() (time.Time, error) { + if m := reGitHubPR.FindStringSubmatch(c.URLs[0]); m != nil { + user := m[1] + repo := m[2] + prnum := m[3] + resp, err := http.Get("https://api.github.com/repos/" + user + "/" + repo + "/pulls/" + prnum) + if err != nil { + return time.Time{}, err + } + if resp.StatusCode != http.StatusOK { + return time.Time{}, fmt.Errorf("unexpected HTTP status: %v", resp.Status) + } + jsonBytes, err := io.ReadAll(resp.Body) + if err != nil { + return time.Time{}, err + } + var obj struct { + CreatedAt time.Time `json:"created_at"` + } + if err := json.Unmarshal(jsonBytes, &obj); err != nil { + return time.Time{}, err + } + return obj.CreatedAt, nil + } + if strings.Contains(c.URLs[0], "/pipermail/") { + resp, err := http.Get(c.URLs[0]) + if err != nil { + return time.Time{}, err + } + if resp.StatusCode != http.StatusOK { + return time.Time{}, fmt.Errorf("unexpected HTTP status: %v", resp.Status) + } + htmlBytes, err := io.ReadAll(resp.Body) + if err != nil { + return time.Time{}, err + } + for _, line := range strings.Split(string(htmlBytes), "\n") { + if m := rePiperMailDate.FindStringSubmatch(line); m != nil { + return time.Parse(time.UnixDate, m[1]) + } + } + } + return time.Time{}, fmt.Errorf("idk how to get timestamps for %q", c.URLs[0]) +} |