package handlers import ( "encoding/json" "fmt" "net/http" "strings" "time" "ascii-live/frames" "github.com/golang/glog" "github.com/gorilla/mux" ) var NotFoundMessage = map[string]string{ "error": "Frames not found. Navigate to /ascii/list for list of frames. Navigate to https://github.com/hugomd/ascii-live to submit new frames.", } var NotCurledMessage = map[string]string{ "error": "You almost ruined a good surprise. Come on, curl it in terminal.", } var availableFrames []string func init() { for k := range frames.FrameMap { availableFrames = append(availableFrames, k) } } func writeJson(w http.ResponseWriter, r *http.Request, res interface{}, status int) { w.Header().Set("Content-Type", "application/json") data, err := json.Marshal(res) if err != nil { return } w.WriteHeader(status) fmt.Fprint(w, string(data)) } func ListHandler(w http.ResponseWriter, r *http.Request) { writeJson(w, r, map[string][]string{"frames": availableFrames}, http.StatusOK) } func NotFoundHandler(w http.ResponseWriter, r *http.Request) { writeJson(w, r, NotFoundMessage, http.StatusNotFound) } func NotCurledHandler(w http.ResponseWriter, r *http.Request) { writeJson(w, r, NotCurledMessage, http.StatusExpectationFailed) } func Handler(w http.ResponseWriter, r *http.Request) { ctx := r.Context() flusher := w.(http.Flusher) vars := mux.Vars(r) frameSource := vars["frameSource"] glog.Infof("Frame source %s", frameSource) frames, ok := frames.FrameMap[frameSource] if !ok { NotFoundHandler(w, r) return } userAgent := r.Header.Get("User-Agent") if !strings.Contains(userAgent, "curl") { NotCurledHandler(w, r) return } w.Header().Set("Transfer-Encoding", "chunked") w.WriteHeader(http.StatusOK) i := 0 for { select { // Handle client disconnects case <-ctx.Done(): glog.Infof("Client stopped listening") return default: if i >= frames.GetLength() { i = 0 } // Artificially wait between reponses. time.Sleep(frames.GetSleep()) // Clear screen clearScreen := "\033[2J\033[H" newLine := "\n" // Write frames fmt.Fprint(w, clearScreen+frames.GetFrame(i)+newLine) i++ // Send some data. flusher.Flush() } } }