mirror of https://github.com/dirtbags/moth.git
Getting files
This commit is contained in:
parent
7a5b2aa3c1
commit
fbba5ac004
|
@ -17,8 +17,8 @@ type ReadSeekCloser interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
type PuzzleProvider interface {
|
type PuzzleProvider interface {
|
||||||
Metadata(cat string, points int) (io.ReadCloser, error)
|
Open(cat string, points int, path string) (ReadSeekCloser, error)
|
||||||
Open(cat string, points int, path string) (io.ReadCloser, error)
|
ModTime(cat string, points int, path string) (time.Time, error)
|
||||||
Inventory() []Category
|
Inventory() []Category
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,6 +35,7 @@ type StateExport struct {
|
||||||
|
|
||||||
type StateProvider interface {
|
type StateProvider interface {
|
||||||
Export(teamId string) *StateExport
|
Export(teamId string) *StateExport
|
||||||
|
TeamName(teamId string) (string, error)
|
||||||
SetTeamName(teamId, teamName string) error
|
SetTeamName(teamId, teamName string) error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
type HTTPServer struct {
|
type HTTPServer struct {
|
||||||
|
@ -11,16 +12,18 @@ type HTTPServer struct {
|
||||||
Puzzles PuzzleProvider
|
Puzzles PuzzleProvider
|
||||||
Theme ThemeProvider
|
Theme ThemeProvider
|
||||||
State StateProvider
|
State StateProvider
|
||||||
|
Base string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewHTTPServer(base string, theme ThemeProvider, state StateProvider, puzzles PuzzleProvider) *HTTPServer {
|
func NewHTTPServer(base string, theme ThemeProvider, state StateProvider, puzzles PuzzleProvider) *HTTPServer {
|
||||||
|
base = strings.TrimRight(base, "/")
|
||||||
h := &HTTPServer{
|
h := &HTTPServer{
|
||||||
ServeMux: http.NewServeMux(),
|
ServeMux: http.NewServeMux(),
|
||||||
Puzzles: puzzles,
|
Puzzles: puzzles,
|
||||||
Theme: theme,
|
Theme: theme,
|
||||||
State: state,
|
State: state,
|
||||||
|
Base: base,
|
||||||
}
|
}
|
||||||
base = strings.TrimRight(base, "/")
|
|
||||||
h.HandleFunc(base+"/", h.ThemeHandler)
|
h.HandleFunc(base+"/", h.ThemeHandler)
|
||||||
h.HandleFunc(base+"/state", h.StateHandler)
|
h.HandleFunc(base+"/state", h.StateHandler)
|
||||||
h.HandleFunc(base+"/register", h.RegisterHandler)
|
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) {
|
func (h *HTTPServer) ContentHandler(w http.ResponseWriter, req *http.Request) {
|
||||||
path := req.URL.Path
|
teamId := req.FormValue("id")
|
||||||
if path == "/" {
|
if _, err := h.State.TeamName(teamId); err != nil {
|
||||||
path = "/puzzle.json"
|
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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,11 +2,12 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/spf13/afero"
|
"github.com/spf13/afero"
|
||||||
"io"
|
|
||||||
"log"
|
"log"
|
||||||
"strings"
|
"strings"
|
||||||
"bufio"
|
"bufio"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"time"
|
||||||
|
"fmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Mothballs struct {
|
type Mothballs struct {
|
||||||
|
@ -21,14 +22,23 @@ func NewMothballs(fs afero.Fs) *Mothballs {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Mothballs) Metadata(cat string, points int) (io.ReadCloser, error) {
|
func (m *Mothballs) Open(cat string, points int, filename string) (ReadSeekCloser, error) {
|
||||||
f, err := m.Fs.Open("/dev/null")
|
mb, ok := m.categories[cat]
|
||||||
return f, err
|
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) {
|
func (m *Mothballs) ModTime(cat string, points int, filename string) (mt time.Time, err error) {
|
||||||
f, err := m.Fs.Open("/dev/null")
|
mb, ok := m.categories[cat]
|
||||||
return f, err
|
if ! ok {
|
||||||
|
return mt, fmt.Errorf("No such category: %s", cat)
|
||||||
|
}
|
||||||
|
mt = mb.ModTime()
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Mothballs) Inventory() []Category {
|
func (m *Mothballs) Inventory() []Category {
|
||||||
|
|
|
@ -164,6 +164,10 @@ func (zfs *Zipfs) Refresh() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (zfs *Zipfs) ModTime() (time.Time) {
|
||||||
|
return zfs.mtime
|
||||||
|
}
|
||||||
|
|
||||||
func (zfs *Zipfs) get(filename string) (*zip.File, error) {
|
func (zfs *Zipfs) get(filename string) (*zip.File, error) {
|
||||||
for _, f := range zfs.zf.File {
|
for _, f := range zfs.zf.File {
|
||||||
if filename == f.Name {
|
if filename == f.Name {
|
||||||
|
|
Loading…
Reference in New Issue