diff options
Diffstat (limited to 'cmd/gen-imworkingon/main.go')
-rw-r--r-- | cmd/gen-imworkingon/main.go | 189 |
1 files changed, 189 insertions, 0 deletions
diff --git a/cmd/gen-imworkingon/main.go b/cmd/gen-imworkingon/main.go new file mode 100644 index 0000000..c0c9723 --- /dev/null +++ b/cmd/gen-imworkingon/main.go @@ -0,0 +1,189 @@ +package main + +import ( + "bytes" + _ "embed" + "fmt" + "html/template" + "os" + "reflect" + "slices" + "sort" + "strings" + "time" + + "github.com/yuin/goldmark" + + "git.lukeshu.com/www/lib/httpcache" +) + +func MarkdownToHTML(md string) (template.HTML, error) { + var html strings.Builder + if err := goldmark.Convert([]byte(md), &html); err != nil { + return template.HTML(""), err + } + return template.HTML(html.String()), nil +} + +func main() { + if err := mainWithError(); err != nil { + fmt.Fprintf(os.Stderr, "%s: error: %v\n", os.Args[0], err) + os.Exit(1) + } +} + +//go:embed imworkingon.html.tmpl +var htmlTmplStr string + +var timeTagTmpl = template.Must(template.New("time.tag.tmpl"). + Parse(`<time datetime="{{ .Machine }}" title="{{ .HumanVerbose }}">{{ .HumanPretty }}</time>`)) + +func mainWithError() error { + httpcache.UserAgent = "https://git.lukeshu.com/www/tree/cmd/gen-imworkingon" + + standups, err := ReadStandups("https://social.coop", "lukeshu") + if err != nil { + return err + } + _standups, err := ReadStandups("https://fosstodon.org", "lukeshu") + if err != nil { + return err + } + standups = append(standups, _standups...) + standupIgnoreList := []string{ + "https://fosstodon.org/@lukeshu/112198267818432116", + "https://fosstodon.org/@lukeshu/112198241414760456", + } + standups = slices.DeleteFunc(standups, func(status *MastodonStatus) bool { + return slices.Contains(standupIgnoreList, status.URL) + }) + + contribs, err := ReadContribs("imworkingon/contribs.yml") + if err != nil { + return err + } + tags, err := ReadTags("imworkingon/tags.yml") + if err != nil { + return err + } + upstreams, err := ReadUpstreams("imworkingon/upstreams.yml") + if err != nil { + return err + } + + sort.Slice(contribs, func(i, j int) bool { + iDate := contribs[i].LastUpdatedAt + if iDate.IsZero() { + iDate = contribs[i].SubmittedAt + } + jDate := contribs[j].LastUpdatedAt + if jDate.IsZero() { + jDate = contribs[j].SubmittedAt + } + return iDate.After(jDate) + }) + + tmpl := template.Must(template.New("imworkingon.html.tmpl"). + Funcs(template.FuncMap{ + "time": func() map[string]time.Weekday { + return map[string]time.Weekday{ + "Sunday": time.Sunday, + "Monday": time.Monday, + "Tuesday": time.Tuesday, + "Wednesday": time.Wednesday, + "Thursday": time.Thursday, + "Friday": time.Friday, + "Saturday": time.Saturday, + } + }, + "reverse": func(x any) any { + in := reflect.ValueOf(x) + l := in.Len() + out := reflect.MakeSlice(in.Type(), l, l) + for i := 0; i < l; i++ { + out.Index(l - (i + 1)).Set(in.Index(i)) + } + return out.Interface() + }, + "timeTag": func(ts time.Time, prettyFmt string) (template.HTML, error) { + ts = ts.Local() + var out strings.Builder + err := timeTagTmpl.Execute(&out, map[string]string{ + "Machine": ts.Format(time.RFC3339), + "HumanVerbose": ts.Format("2006-01-02 15:04:05Z07:00"), + "HumanPretty": ts.Format(prettyFmt), + }) + return template.HTML(out.String()), err + }, + "monthClass": func(m time.Month) string { + if m%2 == 0 { + return "even-month" + } else { + return "odd-month" + } + }, + "md2html": MarkdownToHTML, + "getUpstream": func(c Contribution) Upstream { + // First try any of the documented upstreams. + for _, cURL := range c.URLs { + for _, upstream := range upstreams { + for _, uURL := range upstream.URLs { + prefix := uURL + if !strings.HasSuffix(prefix, "/") { + prefix += "/" + } + if cURL == uURL || strings.HasPrefix(cURL, prefix) { + return upstream + } + } + } + } + // Now try to synthesize an upstream. + if m := reGitHubPR.FindStringSubmatch(c.URLs[0]); m != nil { + user := m[1] + repo := m[2] + return Upstream{ + URLs: []string{"https://github.com/" + user + "/" + repo}, + Name: user + "/" + repo, + } + } + if m := reGitLabMR.FindStringSubmatch(c.URLs[0]); m != nil { + authority := m[1] + projectID := m[2] + if authority == "gitlab.archlinux.org" && strings.HasPrefix(projectID, "archlinux/packaging/packages/") { + return Upstream{ + URLs: []string{"https://" + authority + "/" + projectID}, + Name: strings.Replace(projectID, "/packages/", "/", 1), + } + } + return Upstream{ + URLs: []string{"https://" + authority + "/" + projectID}, + Name: projectID, + } + } + // :( + return Upstream{ + URLs: []string{c.URLs[0]}, + Name: "???", + } + }, + }). + Parse(htmlTmplStr)) + var out bytes.Buffer + if err := tmpl.Execute(&out, map[string]any{ + "Contribs": contribs, + "Tags": tags, + "Upstreams": upstreams, + "Standups": standups, + "StandupCalendar": BuildCalendar(standups, func(status *MastodonStatus) Date { return DateOf(status.CreatedAt.Local()) }), + }); err != nil { + return err + } + if err := os.WriteFile("public/imworkingon/index.new.html", out.Bytes(), 0666); err != nil { + return err + } + if err := os.Rename("public/imworkingon/index.new.html", "public/imworkingon/index.html"); err != nil { + return err + } + return nil +} |