Well, it builds anyway

This commit is contained in:
Neale Pickett 2015-02-20 16:48:52 -07:00
parent 2a0f045f3d
commit 550f0f3385
4 changed files with 95 additions and 122 deletions

37
spongy.cgi/config.go Normal file
View File

@ -0,0 +1,37 @@
package main
import (
"io/ioutil"
"path"
"strings"
)
type Config struct {
BaseDir string
}
func readString(filename string) (string, error) {
octets, err := ioutil.ReadFile(filename)
if err != nil {
return "", err
}
return strings.TrimSpace(string(octets)), nil
}
func ReadConfig(cgiDir string) (*Config, error) {
cfgfn := path.Join(cgiDir, "spongy.cfg")
basePath, err := readString(cfgfn)
if err != nil {
return nil, err
}
return &Config{basePath}, nil
}
func (c *Config) Get(name string) (string, error) {
path := path.Join(c.BaseDir, name)
val, err := readString(path)
return val, err
}

View File

@ -66,6 +66,7 @@ func (nw *Network) Tail(out chan<- *Update) error {
watcher.Add(filepath) watcher.Add(filepath)
// XXX: some way to stop this?
for { for {
lines := make([]string, 0) lines := make([]string, 0)
bf := bufio.NewScanner(f) bf := bufio.NewScanner(f)
@ -77,7 +78,7 @@ func (nw *Network) Tail(out chan<- *Update) error {
if (len(parts) >= 4) && (parts[2] == "NEXTLOG") { if (len(parts) >= 4) && (parts[2] == "NEXTLOG") {
watcher.Remove(filepath) watcher.Remove(filepath)
filename := parts[3] filename := parts[3]
filepath = path.Join(NetworkDir, filename) filepath = path.Join(nw.basePath, "log", filename)
f.Close() f.Close()
f, err = os.Open(filepath) f, err = os.Open(filepath)
if err != nil { if err != nil {
@ -116,3 +117,30 @@ func (nw *Network) Write(data []byte) {
ioutil.WriteFile(filepath, data, 0750) ioutil.WriteFile(filepath, data, 0750)
nw.seq += 1 nw.seq += 1
} }
func Networks(basePath string) (found []*Network) {
dir, err := os.Open(basePath)
if err != nil {
return
}
defer dir.Close()
entities, _ := dir.Readdirnames(0)
for _, fn := range entities {
netdir := path.Join(basePath, fn)
_, err = os.Stat(path.Join(netdir, "nick"))
if err != nil {
continue
}
nw := NewNetwork(netdir)
found = append(found, nw)
}
return
}

Binary file not shown.

View File

@ -2,16 +2,10 @@ package main
import ( import (
"fmt" "fmt"
"github.com/go-fsnotify/fsnotify"
"io/ioutil"
"log" "log"
"os"
"bufio"
"strconv"
"strings" "strings"
"net/http" "net/http"
"net/http/cgi" "net/http/cgi"
"time"
"path" "path"
) )
@ -19,144 +13,58 @@ type Handler struct {
cgi.Handler cgi.Handler
} }
var NetworkDir string func (h Handler) handleCommand(cfg *Config, w http.ResponseWriter, r *http.Request) {
network := r.FormValue("network")
text := r.FormValue("text")
target := r.FormValue("target")
func ReadString(fn string) string { nw := NewNetwork(path.Join(cfg.BaseDir, network))
octets, err := ioutil.ReadFile(fn)
if err != nil {
log.Fatal(err)
}
return strings.TrimSpace(string(octets))
}
func tail(w http.ResponseWriter, filename string, pos int64) {
var err error
currentfn := path.Join(NetworkDir, "current")
if filename == "" {
filename, err = os.Readlink(currentfn)
if err != nil {
log.Fatal(err)
}
}
filepath := path.Join(NetworkDir, filename)
f, err := os.Open(filepath)
if err != nil {
log.Fatal(err)
}
defer f.Close()
watcher, err := fsnotify.NewWatcher()
if err != nil {
log.Fatal(err)
}
defer watcher.Close()
watcher.Add(filepath)
for {
printid := false
newpos, err := f.Seek(pos, 0)
if err != nil {
log.Fatal(err)
}
if newpos != pos {
log.Fatal("Lost my position in the log, somehow (log truncated?)")
}
bf := bufio.NewScanner(f)
for bf.Scan() {
t := bf.Text()
pos += int64(len(t)) + 1 // XXX: this breaks if we ever see \r\n
parts := strings.Split(t, " ")
if (len(parts) >= 4) && (parts[2] == "NEXTLOG") {
watcher.Remove(filepath)
filename = parts[3]
filepath = path.Join(NetworkDir, filename)
f.Close()
f, err = os.Open(filepath)
if err != nil {
log.Fatal(err)
}
watcher.Add(filepath)
pos = 0
}
fmt.Fprintf(w, "data: %s\n", t)
printid = true
}
if printid {
_, err = fmt.Fprintf(w, "id: %s/%d\n\n", filename, pos)
}
if err != nil {
break
}
w.(http.Flusher).Flush()
select {
case _ = <-watcher.Events:
// Somethin' happened!
case err := <-watcher.Errors:
log.Fatal(err)
}
}
}
func handleCommand(w http.ResponseWriter, text string, target string) {
fn := path.Join(NetworkDir, fmt.Sprintf("outq/cgi.%d", time.Now().Unix()))
f, err := os.Create(fn)
if err != nil {
fmt.Fprintln(w, "NO: Cannot create outq file")
fmt.Fprintln(w, err)
return
}
defer f.Close()
var out string
switch { switch {
case strings.HasPrefix(text, "/quote "): case strings.HasPrefix(text, "/quote "):
fmt.Fprintln(f, text[7:]) out = text[7:]
case strings.HasPrefix(text, "/me "): case strings.HasPrefix(text, "/me "):
fmt.Fprintf(f, "PRIVMSG %s :\001ACTION %s\001\n", target, text[4:]) out = fmt.Sprintf("PRIVMSG %s :\001ACTION %s\001", target, text[4:])
default: default:
fmt.Fprintf(f, "PRIVMSG %s :%s\n", target, text) out = fmt.Sprintf("PRIVMSG %s :%s", target, text)
} }
nw.Write([]byte(out))
fmt.Fprintln(w, "OK") fmt.Fprintln(w, "OK")
} }
func (h Handler) handleTail(cfg *Config, w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/plain")
nws := Networks(cfg.BaseDir)
for _, nw := range nws {
fmt.Fprintf(w, "%v\n", nw)
}
}
func (h Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { func (h Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
BaseDir := "networks" cfg, err := ReadConfig(h.Dir)
DefaultDir := path.Join(BaseDir, "default") if err != nil {
NetworkDir = path.Join(BaseDir, r.FormValue("network")) http.Error(w, err.Error(), 500)
if path.Dir(DefaultDir) != path.Dir(NetworkDir) {
NetworkDir = DefaultDir
} }
authtok := ReadString(path.Join(NetworkDir, "authtok")) // Validate authtok
authtok, err := cfg.Get("authtok")
if err != nil {
http.Error(w, err.Error(), 500)
}
if r.FormValue("auth") != authtok { if r.FormValue("auth") != authtok {
w.Header().Set("Content-Type", "text/plain") w.Header().Set("Content-Type", "text/plain")
fmt.Fprintln(w, "NO: Invalid authtok") fmt.Fprintln(w, "NO: Invalid authtok")
return return
} }
// Switch based on type
switch r.FormValue("type") { switch r.FormValue("type") {
case "command": case "command":
w.Header().Set("Content-Type", "text/plain") h.handleCommand(cfg, w, r)
handleCommand(w, r.Form.Get("text"), r.FormValue("target"))
default: default:
w.Header().Set("Content-Type", "text/event-stream") h.handleTail(cfg, w, r)
parts := strings.Split(os.Getenv("HTTP_LAST_EVENT_ID"), "/")
if len(parts) == 2 {
filename := path.Base(parts[0])
pos, _ := strconv.ParseInt(parts[1], 0, 64)
tail(w, filename, pos)
} else {
tail(w, "", 0)
}
} }
} }