spongy

A Unixy IRC client
git clone https://git.woozle.org/neale/spongy.git

spongy / spongy.cgi
Neale Pickett  ·  2015-02-22

spongy.cgi.go

  1package main
  2
  3import (
  4	"fmt"
  5	"log"
  6	"strings"
  7	"net/http"
  8	"net/http/cgi"
  9	"os"
 10	"path"
 11)
 12
 13type Handler struct {
 14	cgi.Handler
 15}
 16
 17func (h Handler) handleCommand(cfg *Config, w http.ResponseWriter, r *http.Request) {
 18	network := r.FormValue("network")
 19	text := r.FormValue("text")
 20	target := r.FormValue("target")
 21	
 22	nw := NewNetwork(path.Join(cfg.BaseDir, network))
 23	
 24	var out string
 25	switch {
 26	case strings.HasPrefix(text, "/quote "):
 27		out = text[7:]
 28	case strings.HasPrefix(text, "/me "):
 29		out = fmt.Sprintf("PRIVMSG %s :\001ACTION %s\001", target, text[4:])
 30	default:
 31		out = fmt.Sprintf("PRIVMSG %s :%s", target, text)
 32	}
 33	nw.Write([]byte(out))
 34
 35	fmt.Fprintln(w, "OK")
 36}
 37
 38func (h Handler) handleTail(cfg *Config, w http.ResponseWriter, r *http.Request) {
 39	w.Header().Set("Content-Type", "text/event-stream")
 40	nws := Networks(cfg.BaseDir)
 41	
 42	lastEventId := r.FormValue("HTTP_LAST_EVENT_ID")
 43	updates := make(chan []string, 100)
 44	
 45	for _, nw := range nws {
 46		nw.ReadLastEventId(lastEventId)
 47		go nw.Tail(updates)
 48		defer nw.Close()
 49	}
 50		
 51	for lines := range updates {
 52		for _, line := range lines {
 53			fmt.Fprintf(w, "data: %s\n", line)
 54		}
 55		
 56		ids := make([]string, 0)
 57		for _, nw := range nws {
 58			ids = append(ids, nw.LastEventId())
 59		}
 60		idstring := strings.Join(ids, " ")
 61		_, err := fmt.Fprintf(w, "id: %s\n\n", idstring)
 62		if err != nil {
 63			// Can't write anymore, guess they hung up.
 64			return
 65		}
 66		w.(http.Flusher).Flush()
 67	}
 68}
 69
 70func (h Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 71	cfg, err := ReadConfig(h.Dir)
 72	if err != nil {
 73		http.Error(w, err.Error(), 500)
 74		return
 75	}
 76	
 77	// Validate authtok
 78	authtok, err := cfg.Get("authtok")
 79	if err != nil {
 80		http.Error(w, err.Error(), 500)
 81		return
 82	}
 83	if r.FormValue("auth") != authtok {
 84		w.Header().Set("Content-Type", "text/plain")
 85		fmt.Fprintln(w, "NO: Invalid authtok")
 86		return
 87	}
 88	
 89	// Switch based on type
 90	switch r.FormValue("type") {
 91	case "command":
 92		h.handleCommand(cfg, w, r)
 93	default:
 94		h.handleTail(cfg, w, r)
 95	}
 96}
 97
 98func main() {
 99	log.SetOutput(os.Stdout)
100	log.SetFlags(0)
101	log.SetPrefix("Status: 500 CGI Go Boom\nContent-type: text/plain\n\nERROR: ")
102	h := Handler{}
103	if err := cgi.Serve(h); err != nil {
104		log.Fatal(err)
105	}
106}
107