go-repo/main.go

115 lines
2.5 KiB
Go

package main
import (
"fmt"
"html/template"
"io/ioutil"
"net/http"
"path"
"github.com/gomarkdown/markdown"
"github.com/gomarkdown/markdown/parser"
"github.com/sirupsen/logrus"
"go.uber.org/multierr"
)
type Module struct {
Package string
Repository string
Readme template.HTML
}
func (m *Module) LoadReadme() error {
url := path.Join(m.Repository, "/raw/master/README.md")
res, err := http.Get("https://" + url)
if err != nil {
return err
}
defer res.Body.Close()
if res.StatusCode > 300 {
return fmt.Errorf("request failed: %s (%d)", res.Status, res.StatusCode)
}
b, err := ioutil.ReadAll(res.Body)
if err != nil {
return err
}
extensions := parser.CommonExtensions | parser.AutoHeadingIDs
mdParser := parser.NewWithExtensions(extensions)
m.Readme = template.HTML(markdown.ToHTML(b, mdParser, nil))
return nil
}
type Modules []*Module
func (m *Modules) Find(pkg string) (*Module, bool) {
for _, v := range *m {
if v.Package == pkg {
return v, true
}
}
return nil, false
}
func (m *Modules) LoadReadme() error {
errs := make(chan error, len(*m))
for _, v := range *m {
go func(mod *Module) {
errs <- mod.LoadReadme()
}(v)
}
var err error
for range *m {
multierr.Append(err, <-errs)
}
return err
}
var (
modules = Modules{
{
Package: "go.adphi.net/gonextcloud",
Repository: "git.adphi.net/adphi/gonextcloud",
},
{
Package: "go.adphi.net/gogs-cli",
Repository: "git.adphi.net/adphi/gogs-cli",
},
}
indexTemplate = template.Must(template.New("index.gohtml").ParseFiles("./index.gohtml"))
moduleTemplate = template.Must(template.New("package.gohtml").ParseFiles("./package.gohtml"))
)
func main() {
go func() {
if err := modules.LoadReadme(); err != nil {
logrus.WithError(err).Error("failed to load all readme")
}
}()
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet {
w.Header().Set("content-type", "text/html")
w.WriteHeader(http.StatusMethodNotAllowed)
return
}
switch r.URL.Path {
case "/":
if err := indexTemplate.Execute(w, modules); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
default:
m, ok := modules.Find("go.adphi.net" + r.URL.Path)
if !ok {
w.WriteHeader(http.StatusNotFound)
return
}
w.Header().Set("content-type", "text/html")
if err := moduleTemplate.Execute(w, m); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
}
})
if err := http.ListenAndServe(":8888", nil); err != nil {
logrus.Fatal(err)
}
}