oboeru

a collection of simple, scriptable flashcard programs
git clone anongit@rnpnr.xyz:oboeru.git
Log | Files | Refs | Feed | README | LICENSE

oboeruhttp.go (3296B)


      1 package main
      2 
      3 import (
      4 	"bufio"
      5 	"context"
      6 	"flag"
      7 	"fmt"
      8 	"net/http"
      9 	"os"
     10 	"strings"
     11 )
     12 
     13 var ctx context.Context
     14 var cancel context.CancelFunc
     15 
     16 var front, back string
     17 var cardlock = false
     18 
     19 var html_midf, html_midb, html_quit string 
     20 const html_head = "<!DOCTYPE html><html><head><meta charset='utf-8' />" +
     21 		  "<link rel='stylesheet' type='text/css' href='/_/style.css'>" +
     22 		  "<title>oboeru</title></head><body><div>"
     23 const html_foot = "</div></body></html>"
     24 
     25 func usage() {
     26 	fmt.Fprintf(os.Stderr, "usage: %s [-p port] [-FPQS label]\n", os.Args[0])
     27 	flag.PrintDefaults()
     28 }
     29 
     30 func create_req_map() map[string]string {
     31 	return map[string]string {
     32 		"/fail": "fail",
     33 		"/pass": "pass",
     34 		"/quit": "quit",
     35 		"/show": "show",
     36 	}
     37 }
     38 
     39 func format_page(head string, body string, mid string, foot string) string {
     40 	return strings.Join([]string{head, body, mid, foot}, "")
     41 }
     42 
     43 func get_next_card() []string {
     44 	stdin := bufio.NewScanner(os.Stdin)
     45 	stdin.Scan()
     46 	return strings.Split(stdin.Text(), "\t")
     47 }
     48 
     49 func show_card(w http.ResponseWriter, card string, mid string) {
     50 	html := format_page(html_head, card, mid, html_foot)
     51 	w.Header().Set("Content-Type", "text/html; charset=utf-8")
     52 	fmt.Fprint(w, html)
     53 }
     54 
     55 func quit(w http.ResponseWriter) {
     56 	show_card(w, html_quit, "")
     57 	fmt.Fprintln(os.Stdout, "quit")
     58 	cancel() /* send signal to shutdown srv */
     59 }
     60 
     61 func response(w http.ResponseWriter, r *http.Request) {
     62 	req_map := create_req_map()
     63 
     64 	/* won't err since all invalid reqs have been rerouted to "/" */
     65 	str, _ := req_map[r.RequestURI]
     66 
     67 	switch str {
     68 	case "show":
     69 		show_card(w, back, html_midb)
     70 	case "quit":
     71 		quit(w)
     72 	case "fail":
     73 		fallthrough
     74 	case "pass":
     75 		cardlock = false
     76 		fmt.Fprintln(os.Stdout, str)
     77 		http.Redirect(w, r, "/", http.StatusSeeOther)
     78 	}
     79 }
     80 
     81 func serve(w http.ResponseWriter, r *http.Request) {
     82 	if cardlock == false {
     83 		card := get_next_card()
     84 		if len(card) != 2 {
     85 			quit(w)
     86 		}
     87 
     88 		cardlock = true
     89 		front = card[0]
     90 		back = card[1]
     91 	}
     92 
     93 	show_card(w, front, html_midf)
     94 }
     95 
     96 func main() {
     97 	var (
     98 		port = flag.Uint("p", 6969, "port number")
     99 		fail = flag.String("F", "fail", "fail label")
    100 		pass = flag.String("P", "pass", "pass label")
    101 		show = flag.String("S", "show", "show label")
    102 		quit = flag.String("Q", "quit", "quit label")
    103 		bye = flag.String("q", "Goodbye!", "text to display before quitting")
    104 	)
    105 
    106 	flag.Usage = usage
    107 	flag.Parse()
    108 
    109 	html_midf = strings.Join([]string{"<div class='link'><a href='/quit'>",
    110 				*quit, "</a> · <a href='/show'>", *show,
    111 				"</a></div>"}, "")
    112 	html_midb = strings.Join([]string{"<div class='link'><a href='/fail'>",
    113 				*fail, "</a> · <a href='/quit'>", *quit,
    114 				"</a> · <a href='/pass'>", *pass, "</a></div>"}, "")
    115 	html_quit = *bye
    116 
    117 	ctx, cancel = context.WithCancel(context.Background())
    118 
    119 	wd, _ := os.Getwd()
    120 	fs := http.FileServer(http.Dir(wd))
    121 
    122 	http.HandleFunc("/", serve)
    123 	
    124 	/* pretend requested files are in wd/_/ so that they can
    125 	 * be accessed on the fly */
    126 	http.Handle("/_/", http.StripPrefix("/_/", fs))
    127 	
    128 	/* map allowed reqs to the handler fn response() */
    129 	for k, _ := range create_req_map() {
    130 		http.HandleFunc(k, response)
    131 	}
    132 
    133 	server := fmt.Sprintf(":%d", *port)
    134 	srv := &http.Server{Addr: server}
    135 	go func() {
    136 		srv.ListenAndServe()
    137 	}()
    138 	<- ctx.Done() /* wait for signal to shutdown */
    139 
    140 	srv.Shutdown(ctx)
    141 }