diff --git a/main.go b/main.go index 8584007..f8d1c3e 100644 --- a/main.go +++ b/main.go @@ -3,6 +3,7 @@ package main import ( "bufio" "encoding/csv" + "encoding/json" "flag" "fmt" "io/ioutil" @@ -11,6 +12,7 @@ import ( "os" "path" "path/filepath" + "strings" "time" ) @@ -29,39 +31,160 @@ func Serve(w http.ResponseWriter, r *http.Request) { ` + title + ` + +

` + title + `

- `)) - if dirs, err := ioutil.ReadDir(rendusDir); err == nil { - w.Write([]byte(``)) - for _, dir := range dirs { - if dir.IsDir() { - w.Write([]byte(``)) - } - } - w.Write([]byte(``)) - for _, student := range students { - login := student[2] - w.Write([]byte(``)) - for _, dir := range dirs { - if dir.IsDir() { - if fi, err := os.Stat(path.Join(rendusDir, dir.Name(), login)); err == nil { - w.Write([]byte(``)) - } else { - w.Write([]byte(``)) - } - } - } - w.Write([]byte(``)) - } - } - w.Write([]byte(`
` + dir.Name() + `
` + login + `` + fi.ModTime().Format(time.UnixDate) + `
+ + + + + + +
+ `)) } +func genStudents() map[string]map[string]*Submission { + ret := map[string]map[string]*Submission{} + + for _, student := range students { + login := student[2] + ret[login] = genStudent(login) + } + + return ret +} + +func ServeJSON(w http.ResponseWriter, r *http.Request) { + log.Printf("Handling %s request from %s: %s [%s]\n", r.Method, r.RemoteAddr, r.URL.Path, r.UserAgent()) + + q := r.URL.Query() + varname := q.Get("var") + funcname := q.Get("func") + + if funcname == "" && varname == "" { + w.Header().Set("Content-Type", "application/json") + } else { + w.Header().Set("Content-Type", "application/javascript") + } + + if j, err := json.Marshal(genStudents()); err != nil { + http.Error(w, fmt.Sprintf("{errmsg:%q}", err), http.StatusInternalServerError) + } else { + w.WriteHeader(http.StatusOK) + if varname != "" { + w.Write([]byte("var ")) + w.Write([]byte(varname)) + w.Write([]byte(" = ")) + } + if funcname != "" { + w.Write([]byte(funcname)) + w.Write([]byte("(")) + } + w.Write(j) + if funcname != "" { + w.Write([]byte(")")) + } else if varname != "" { + w.Write([]byte(";")) + } + } +} + +type Submission struct { + Date time.Time `json:"date"` + Hash string `json:"hash"` +} + +func genStudent(login string) map[string]*Submission { + ret := map[string]*Submission{} + + if dirs, err := ioutil.ReadDir(rendusDir); err == nil { + for _, dir := range dirs { + if dir.IsDir() { + p := path.Join(rendusDir, dir.Name(), login) + if fi, err := os.Stat(p); err == nil { + ret[dir.Name()] = new(Submission) + ret[dir.Name()].Date = fi.ModTime() + if lnk, err := os.Readlink(p); err == nil { + ret[dir.Name()].Hash = strings.TrimPrefix(lnk, login + ".") + } + } else { + ret[dir.Name()] = nil + } + } + } + } + + return ret +} + +func ServeJSONStudent(w http.ResponseWriter, r *http.Request) { + log.Printf("Handling %s request from %s: %s [%s]\n", r.Method, r.RemoteAddr, r.URL.Path, r.UserAgent()) + + w.Header().Set("Content-Type", "application/json") + + login := strings.TrimSuffix(strings.TrimPrefix(r.URL.Path, "/"), ".json") + + q := r.URL.Query() + varname := q.Get("var") + + if j, err := json.Marshal(genStudent(login)); err != nil { + http.Error(w, fmt.Sprintf("{errmsg:%q}", err), http.StatusInternalServerError) + } else { + w.WriteHeader(http.StatusOK) + if varname != "" { + w.Write([]byte("var ")) + w.Write([]byte(varname)) + w.Write([]byte(" = ")) + } + w.Write(j) + if varname != "" { + w.Write([]byte(";")) + } + } +} + func main() { var studentsFile string @@ -105,6 +228,10 @@ func main() { log.Println("Registering handlers...") http.HandleFunc("/", Serve) + http.HandleFunc("/rendus.json", ServeJSON) + for _, student := range students { + http.HandleFunc("/" + student[2] + ".json", ServeJSONStudent) + } log.Println(fmt.Sprintf("Ready, listening on %s", *bind)) if err := http.ListenAndServe(*bind, nil); err != nil { log.Fatal("Unable to listen and serve: ", err)