2014-07-14 19:30:47 -06:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
2014-07-23 21:41:55 -06:00
|
|
|
"io/ioutil"
|
2014-07-14 19:30:47 -06:00
|
|
|
"log"
|
|
|
|
"os"
|
|
|
|
"bufio"
|
|
|
|
"strconv"
|
2014-07-23 21:41:55 -06:00
|
|
|
"strings"
|
2014-07-14 19:30:47 -06:00
|
|
|
"net/http"
|
|
|
|
"net/http/cgi"
|
|
|
|
"time"
|
2014-08-05 15:53:03 -06:00
|
|
|
"path"
|
2014-07-14 19:30:47 -06:00
|
|
|
)
|
|
|
|
|
|
|
|
type Handler struct {
|
|
|
|
cgi.Handler
|
|
|
|
}
|
|
|
|
|
2014-08-12 21:41:54 -06:00
|
|
|
var ServerDir string
|
2014-08-05 15:53:03 -06:00
|
|
|
|
|
|
|
func ReadString(fn string) string {
|
|
|
|
octets, err := ioutil.ReadFile(fn)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
return strings.TrimSpace(string(octets))
|
|
|
|
}
|
2014-07-14 19:30:47 -06:00
|
|
|
|
|
|
|
func tail(w http.ResponseWriter, pos int) {
|
2014-08-12 21:41:54 -06:00
|
|
|
f, err := os.Open(path.Join(ServerDir, "log"))
|
2014-07-14 19:30:47 -06:00
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
defer f.Close()
|
|
|
|
|
2014-08-05 16:35:51 -06:00
|
|
|
for {
|
|
|
|
printid := false
|
|
|
|
|
|
|
|
_, err = f.Seek(int64(pos), 0)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
bf := bufio.NewScanner(f)
|
|
|
|
for bf.Scan() {
|
|
|
|
t := bf.Text()
|
|
|
|
pos += len(t) + 1 // XXX: this breaks if we ever see \r\n
|
|
|
|
fmt.Fprintf(w, "data: %s\n", t)
|
|
|
|
printid = true
|
|
|
|
}
|
|
|
|
if printid {
|
|
|
|
_, err = fmt.Fprintf(w, "id: %d\n\n", pos)
|
|
|
|
}
|
|
|
|
if err != nil {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
w.(http.Flusher).Flush()
|
|
|
|
time.Sleep(350 * time.Millisecond)
|
2014-07-14 19:30:47 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-05 15:53:03 -06:00
|
|
|
func handleCommand(w http.ResponseWriter, text string, target string) {
|
2014-08-12 21:41:54 -06:00
|
|
|
fn := path.Join(ServerDir, fmt.Sprintf("outq/cgi.%d", time.Now().Unix()))
|
2014-07-14 19:30:47 -06:00
|
|
|
f, err := os.Create(fn)
|
|
|
|
if err != nil {
|
|
|
|
fmt.Fprintln(w, "NO")
|
|
|
|
fmt.Fprintln(w, err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
defer f.Close()
|
2014-08-05 15:53:03 -06:00
|
|
|
|
|
|
|
switch {
|
|
|
|
case strings.HasPrefix(text, "/quote "):
|
|
|
|
fmt.Fprintln(f, text[7:])
|
|
|
|
case strings.HasPrefix(text, "/me "):
|
|
|
|
fmt.Fprintf(f, "PRIVMSG %s :\001ACTION %s\001\n", target, text[4:])
|
|
|
|
default:
|
|
|
|
fmt.Fprintf(f, "PRIVMSG %s :%s\n", target, text)
|
|
|
|
}
|
2014-07-14 19:30:47 -06:00
|
|
|
|
|
|
|
fmt.Fprintln(w, "OK")
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (h Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
2014-08-12 21:41:54 -06:00
|
|
|
// XXX: I'm not happy with this irc.basedir file
|
|
|
|
BaseDir := ReadString("irc.basedir")
|
|
|
|
ServerDir = path.Join(BaseDir, r.FormValue("server"))
|
|
|
|
|
|
|
|
if m, _ := path.Match(path.Join(BaseDir, "*"), ServerDir); ! m {
|
|
|
|
ServerDir = path.Join(BaseDir, "default")
|
|
|
|
}
|
|
|
|
|
|
|
|
authtok := ReadString(path.Join(ServerDir, "authtok"))
|
2014-07-23 21:41:55 -06:00
|
|
|
if r.FormValue("auth") != authtok {
|
|
|
|
w.Header().Set("Content-Type", "text/plain")
|
|
|
|
fmt.Fprintln(w, "NO")
|
|
|
|
return
|
|
|
|
}
|
2014-07-14 19:30:47 -06:00
|
|
|
switch r.FormValue("type") {
|
|
|
|
case "command":
|
|
|
|
w.Header().Set("Content-Type", "text/plain")
|
2014-08-05 15:53:03 -06:00
|
|
|
handleCommand(w, r.Form.Get("text"), r.FormValue("target"))
|
2014-07-14 19:30:47 -06:00
|
|
|
default:
|
|
|
|
w.Header().Set("Content-Type", "text/event-stream")
|
|
|
|
id, _ := strconv.Atoi(os.Getenv("HTTP_LAST_EVENT_ID"))
|
|
|
|
tail(w, id)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func main() {
|
|
|
|
h := Handler{}
|
|
|
|
if err := cgi.Serve(h); err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|