blob: 7483afc055bd4f84f4f38e61b43828b265d5e756 [file] [log] [blame]
package main
import (
"encoding/json"
"fmt"
"html/template"
"net/http"
"strings"
"github.com/golang/glog"
"code.hackerspace.pl/hscloud/hswaw/site/calendar"
"code.hackerspace.pl/hscloud/hswaw/site/templates"
)
// parseTemplates parses a set of templates from
// //hswaw/site/templates/$name.html into a Go HTML template. Typical Go text
// templating ordering behaviour applies (this basically replicates
// template.ParseFiles, but for statically embedded files instead).
func parseTemplates(names ...string) (*template.Template, error) {
if len(names) == 0 {
return nil, fmt.Errorf("at least one template must be given")
}
var t *template.Template
for _, n := range names {
path := fmt.Sprintf("hswaw/site/templates/%s.html", n)
data, ok := templates.Data[path]
if !ok {
return nil, fmt.Errorf("template %q (%s) not found", n, path)
}
s := string(data)
if t == nil {
t = template.New(n)
}
_, err := t.Parse(s)
if err != nil {
return nil, fmt.Errorf("template %q could not be parsed: %w", n, err)
}
}
return t, nil
}
var (
tmplIndex = template.Must(parseTemplates("index"))
)
// render attempts to render a given Go template with data into the HTTP
// response writer, and logs a warning if anything goes wrong.
func render(w http.ResponseWriter, t *template.Template, data interface{}) {
if err := t.Execute(w, data); err != nil {
glog.Warningf("Rendering %v failed: %v", t, err)
}
}
// handleIndex handles rendering the main page at /.
func (s *service) handleIndex(w http.ResponseWriter, r *http.Request) {
// Necessary as "/" is a catch-all in net/http.
if r.URL.Path != "/" {
http.NotFound(w, r)
return
}
ctx := r.Context()
atStatus, atError := getAt(ctx)
render(w, tmplIndex, map[string]interface{}{
"Entries": s.getFeeds(),
"Events": s.getEvents(),
"AtStatus": atStatus,
"AtError": atError,
})
}
func (s *service) handleRobotsTxt(w http.ResponseWriter, r *http.Request) {
// Allow everyone everywhere. We don't really host much on hackerspace.pl anyway.
fmt.Fprintf(w, "User-agent: *\n")
fmt.Fprintf(w, "Allow: /\n")
}
func (s *service) handleJSONEvents(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(s.getEvents())
}
// handleEvent is a fallback HTML-only event render view.
// TODO(q3k): make this pretty by either making a template or redirecting to a
// pretty viewer.
func (s *service) handleEvent(w http.ResponseWriter, r *http.Request) {
parts := strings.Split(r.URL.Path, "/")
uid := parts[len(parts)-1]
events := s.getEvents()
var event *calendar.UpcomingEvent
for _, ev := range events {
if ev.UID == uid {
event = ev
break
}
}
if event == nil {
http.NotFound(w, r)
return
}
render(w, template.Must(template.New("event").Parse(`<!DOCTYPE html>
<meta charset="utf-8">
<title>Event details: {{ .Summary }}</title>
<body>
<i>this interface intentionally left ugly...</i><br/>
<b>summary:</b> {{ .Summary }}<br />
<b>date:</b> {{ .WarsawDate }}<br />
<pre>{{ .Description }}</pre>`)), event)
}
func (s *service) handleSpaceAPI(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(generateSpaceAPIResponse(ctx))
}