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