package main import ( "code.laria.me/code.laria.me/projects" "flag" "fmt" "html/template" "log" "net/http" "path" "strings" ) var ( HttpLaddr = flag.String("http_laddr", ":8093", "Serve HTTP from this address") DataDir = flag.String("data_dir", "/usr/lib/code.laria.me", "Data directory (static files/templates)") ProjectDir = flag.String("project_dir", "/srv/code.laria.me", "Project directory") ) func main() { flag.Parse() repo := projects.NewProjectRepo(*ProjectDir) repo.ScanProjects() templates := NewTemplates(path.Join(*DataDir, "templates")) if err := templates.LoadAll(); err != nil { log.Fatalln(err) } http.HandleFunc("/", func(resp http.ResponseWriter, req *http.Request) { if req.URL.Query().Get("go-get") == "1" { for _, p := range repo.Projects { if p.GoGet != "" { fmt.Fprintf( resp, "", p.Name, p.GoGet, ) } } return } if req.URL.Path == "/" { var data mainTemplateData data.Projects = repo.Projects data.Tagcloud = repo.Tagcloud data.Tags = []string{"programming", "code", "git", "source", "sourcecode"} templates.Main.Execute(resp, data) return } proj, ok := repo.Projects[req.URL.Path[1:]] if ok { templates.Project.Execute(resp, proj) return } resp.WriteHeader(404) templates.Notfound.Execute(resp, commonTemplateData{}) }) http.Handle("/tags/", http.StripPrefix("/tags/", http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) { tag := req.URL.String() projs, ok := repo.Tags[tag] if !ok { resp.WriteHeader(404) templates.Notfound.Execute(resp, commonTemplateData{}) return } var data tagTemplateData data.Tags = []string{tag} data.Title = tag data.Tag = tag data.Projects = make(map[string]projects.Project) for pname := range projs { p, ok := repo.Projects[pname] if ok { data.Projects[pname] = p } } templates.Tag.Execute(resp, data) }))) http.HandleFunc("/__refresh__", func(resp http.ResponseWriter, req *http.Request) { // Should be shielded from the internet, e.g. by putting this into the nginx config: // location /__refresh__ { return 403; } resp.Header().Add("Content-Type", "text/plain") if err := templates.LoadAll(); err != nil { fmt.Fprintf(resp, "Failed loading templates: %s", err) log.Panicln(err) } repo.ScanProjects() resp.Write([]byte("OK")) }) http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir(path.Join(*DataDir, "static"))))) log.Fatalln(http.ListenAndServe(*HttpLaddr, nil)) } type Templates struct { Main, Project, Tag, Notfound *template.Template dir string } func NewTemplates(dir string) *Templates { return &Templates{ dir: dir, } } func (t *Templates) LoadAll() error { var err error if err = t.loadMain(); err != nil { return err } if t.Project, err = t.loadSub("project"); err != nil { return err } if t.Tag, err = t.loadSub("tag"); err != nil { return err } if t.Notfound, err = t.loadSub("notfound"); err != nil { return err } return nil } func (t *Templates) loadMain() (err error) { t.Main, err = template.New("main.html").Funcs(template.FuncMap{ "join": strings.Join, }).ParseFiles(path.Join(t.dir, "main.html")) if err != nil { return err } t.Main.Funcs(template.FuncMap{ "join": strings.Join, }) return nil } func (t *Templates) loadSub(name string) (*template.Template, error) { return template.Must(t.Main.Clone()).ParseFiles(path.Join(t.dir, name+".html")) } type commonTemplateData struct { Title, Description string Tags []string } type mainTemplateData struct { commonTemplateData Projects map[string]projects.Project Tagcloud map[string]projects.TagcloudElem } type tagTemplateData struct { commonTemplateData Tag string Projects map[string]projects.Project }