diff --git a/cmd/mothd/common.go b/cmd/mothd/common.go index 16cf575..f773d3c 100644 --- a/cmd/mothd/common.go +++ b/cmd/mothd/common.go @@ -17,8 +17,8 @@ type ReadSeekCloser interface { } type PuzzleProvider interface { - Metadata(cat string, points int) (io.ReadCloser, error) - Open(cat string, points int, path string) (io.ReadCloser, error) + Open(cat string, points int, path string) (ReadSeekCloser, error) + ModTime(cat string, points int, path string) (time.Time, error) Inventory() []Category } @@ -35,6 +35,7 @@ type StateExport struct { type StateProvider interface { Export(teamId string) *StateExport + TeamName(teamId string) (string, error) SetTeamName(teamId, teamName string) error } diff --git a/cmd/mothd/httpd.go b/cmd/mothd/httpd.go index 51bd254..50c6af7 100644 --- a/cmd/mothd/httpd.go +++ b/cmd/mothd/httpd.go @@ -4,6 +4,7 @@ import ( "log" "net/http" "strings" + "strconv" ) type HTTPServer struct { @@ -11,16 +12,18 @@ type HTTPServer struct { Puzzles PuzzleProvider Theme ThemeProvider State StateProvider + Base string } func NewHTTPServer(base string, theme ThemeProvider, state StateProvider, puzzles PuzzleProvider) *HTTPServer { + base = strings.TrimRight(base, "/") h := &HTTPServer{ ServeMux: http.NewServeMux(), Puzzles: puzzles, Theme: theme, State: state, + Base: base, } - base = strings.TrimRight(base, "/") h.HandleFunc(base+"/", h.ThemeHandler) h.HandleFunc(base+"/state", h.StateHandler) h.HandleFunc(base+"/register", h.RegisterHandler) @@ -137,9 +140,36 @@ func (h *HTTPServer) AnswerHandler(w http.ResponseWriter, req *http.Request) { } func (h *HTTPServer) ContentHandler(w http.ResponseWriter, req *http.Request) { - path := req.URL.Path - if path == "/" { - path = "/puzzle.json" + teamId := req.FormValue("id") + if _, err := h.State.TeamName(teamId); err != nil { + http.Error(w, "Team Not Found", http.StatusNotFound) + return } - JSendf(w, JSendFail, "unimplemented", "I haven't written this yet") + + trimLen := len(h.Base) + len("/content/") + parts := strings.SplitN(req.URL.Path[trimLen:], "/", 3) + if len(parts) < 3 { + http.Error(w, "Not Found", http.StatusNotFound) + return + } + + cat := parts[0] + pointsStr := parts[1] + filename := parts[2] + + if (filename == "") { + filename = "puzzles.json" + } + + points, _ := strconv.Atoi(pointsStr) + + mf, err := h.Puzzles.Open(cat, points, filename) + if err != nil { + http.Error(w, err.Error(), http.StatusNotFound) + return + } + defer mf.Close() + + mt, _ := h.Puzzles.ModTime(cat, points, filename) + http.ServeContent(w, req, filename, mt, mf) } diff --git a/cmd/mothd/mothballs.go b/cmd/mothd/mothballs.go index 543475c..b57a537 100644 --- a/cmd/mothd/mothballs.go +++ b/cmd/mothd/mothballs.go @@ -2,11 +2,12 @@ package main import ( "github.com/spf13/afero" - "io" "log" "strings" "bufio" "strconv" + "time" + "fmt" ) type Mothballs struct { @@ -21,14 +22,23 @@ func NewMothballs(fs afero.Fs) *Mothballs { } } -func (m *Mothballs) Metadata(cat string, points int) (io.ReadCloser, error) { - f, err := m.Fs.Open("/dev/null") - return f, err +func (m *Mothballs) Open(cat string, points int, filename string) (ReadSeekCloser, error) { + mb, ok := m.categories[cat] + if ! ok { + return nil, fmt.Errorf("No such category: %s", cat) + } + + path := fmt.Sprintf("content/%d/%s", points, filename) + return mb.Open(path) } -func (m *Mothballs) Open(cat string, points int, filename string) (io.ReadCloser, error) { - f, err := m.Fs.Open("/dev/null") - return f, err +func (m *Mothballs) ModTime(cat string, points int, filename string) (mt time.Time, err error) { + mb, ok := m.categories[cat] + if ! ok { + return mt, fmt.Errorf("No such category: %s", cat) + } + mt = mb.ModTime() + return } func (m *Mothballs) Inventory() []Category { diff --git a/cmd/mothd/zipfs.go b/cmd/mothd/zipfs.go index ed26d4a..e9d21fe 100644 --- a/cmd/mothd/zipfs.go +++ b/cmd/mothd/zipfs.go @@ -164,6 +164,10 @@ func (zfs *Zipfs) Refresh() error { return nil } +func (zfs *Zipfs) ModTime() (time.Time) { + return zfs.mtime +} + func (zfs *Zipfs) get(filename string) (*zip.File, error) { for _, f := range zfs.zf.File { if filename == f.Name {