From 9a1eafac3127b746f1cc66c30cb9d4f83e5d0d7a Mon Sep 17 00:00:00 2001 From: Neale Pickett Date: Mon, 18 Jan 2016 22:01:29 -0700 Subject: [PATCH] New non-cgi client --- spongycli/network.go | 171 ++++++++++++++++++ spongycli/spongycli.go | 55 ++++++ {spongy => spongyd}/irc.go | 0 {spongy => spongyd}/logfile.go | 16 +- {spongy => spongyd}/network.go | 18 +- {spongy => spongyd}/network_test.go | 0 {spongy => spongyd}/readwritecloserwrapper.go | 0 .../readwritecloserwrapper_test.go | 0 {spongy => spongyd}/spongy_test.go | 0 spongy/spongy.go => spongyd/spongyd.go | 0 10 files changed, 245 insertions(+), 15 deletions(-) create mode 100644 spongycli/network.go create mode 100644 spongycli/spongycli.go rename {spongy => spongyd}/irc.go (100%) rename {spongy => spongyd}/logfile.go (85%) rename {spongy => spongyd}/network.go (93%) rename {spongy => spongyd}/network_test.go (100%) rename {spongy => spongyd}/readwritecloserwrapper.go (100%) rename {spongy => spongyd}/readwritecloserwrapper_test.go (100%) rename {spongy => spongyd}/spongy_test.go (100%) rename spongy/spongy.go => spongyd/spongyd.go (100%) diff --git a/spongycli/network.go b/spongycli/network.go new file mode 100644 index 0000000..15929d1 --- /dev/null +++ b/spongycli/network.go @@ -0,0 +1,171 @@ +package main + +import ( + "bufio" + "fmt" + "github.com/go-fsnotify/fsnotify" + "io/ioutil" + "os" + "path" + "strconv" + "strings" + "time" +) + +const eventIdSep = "/" + +type Network struct { + running bool + + Name string + currentLog string + lineno int64 + + basePath string + seq int +} + +func NewNetwork(basePath string) (*Network) { + return &Network{ + running: true, + Name: path.Base(basePath), + basePath: basePath, + } +} + +func (nw *Network) Close() { + nw.running = false +} + +func (nw *Network) ReadLastEventId(lastEventId string) { + for _, eventId := range strings.Split(lastEventId, " ") { + parts := strings.Split(eventId, eventIdSep) + if len(parts) != 3 { + continue + } + + if parts[0] != nw.Name { + continue + } + nw.currentLog = parts[1] + nw.lineno, _ = strconv.ParseInt(parts[2], 10, 64) + return + } +} + +func (nw *Network) LastEventId() string { + parts := []string{nw.Name, nw.currentLog, strconv.FormatInt(nw.lineno, 10)} + return strings.Join(parts, eventIdSep) +} + +func (nw *Network) errmsg(err error) string { + return fmt.Sprintf("ERROR: %s", err.Error()) +} + +func (nw *Network) Tail(out chan<- string) { + if nw.currentLog == "" { + var err error + + currentfn := path.Join(nw.basePath, "log", "current") + nw.currentLog, err = os.Readlink(currentfn) + if err != nil { + out <- nw.errmsg(err) + return + } + } + + filepath := path.Join(nw.basePath, "log", nw.currentLog) + f, err := os.Open(filepath) + if err != nil { + out <- nw.errmsg(err) + return + } + defer f.Close() + + watcher, err := fsnotify.NewWatcher() + if err != nil { + out <- nw.errmsg(err) + return + } + defer watcher.Close() + + watcher.Add(filepath) + lineno := int64(0) + + // XXX: some way to stop this? + for nw.running { + bf := bufio.NewScanner(f) + for bf.Scan() { + lineno += 1 + if lineno <= nw.lineno { + continue + } else { + nw.lineno = lineno + } + + t := bf.Text() + + parts := strings.Split(t, " ") + if (len(parts) >= 3) && (parts[1] == "NEXTLOG") { + watcher.Remove(filepath) + filename := parts[2] + filepath = path.Join(nw.basePath, "log", filename) + f.Close() + f, err = os.Open(filepath) + if err != nil { + out <- nw.errmsg(err) + return + } + watcher.Add(filepath) + lineno = 0 + nw.lineno = 0 + } + out <- t + } + + select { + case _ = <-watcher.Events: + // Somethin' happened! + case err := <-watcher.Errors: + out <- nw.errmsg(err) + return + } + } +} + +func (nw *Network) Write(data []byte) { + epoch := time.Now().Unix() + pid := os.Getpid() + filename := fmt.Sprintf("%d-%d-%d.txt", epoch, pid, nw.seq) + + filepath := path.Join(nw.basePath, "outq", filename) + ioutil.WriteFile(filepath, data, 0750) + 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 +} + diff --git a/spongycli/spongycli.go b/spongycli/spongycli.go new file mode 100644 index 0000000..23edfcd --- /dev/null +++ b/spongycli/spongycli.go @@ -0,0 +1,55 @@ +package main + +import ( + "bufio" + "fmt" + "flag" + "log" + "os" + "path/filepath" +) + +var playback int +var running bool = true + +func inputLoop(nw *Network) { + bf := bufio.NewScanner(os.Stdin) + for bf.Scan() { + line := bf.Bytes() + nw.Write(line) + } +} + +func usage() { + fmt.Fprintf(os.Stderr, "Usage: %s [OPTIONS] NETDIR\n", os.Args[0]) + fmt.Fprintf(os.Stderr, "\n") + fmt.Fprintf(os.Stderr, "NETDIR is the path to your IRC directory (see README)\n") + fmt.Fprintf(os.Stderr, "\n") + fmt.Fprintf(os.Stderr, "OPTIONS:\n") + flag.PrintDefaults() +} + +func main() { + flag.Usage = usage + flag.IntVar(&playback, "playback", 0, "Number of lines to play back on startup") + + flag.Parse() + if flag.NArg() != 1 { + usage() + os.Exit(2) + } + netDir, err := filepath.Abs(flag.Arg(0)) + if err != nil { + log.Fatal(err) + } + + nw := NewNetwork(netDir) + defer nw.Close() + go inputLoop(nw) + + outq := make(chan string, 50) // to stdout + go nw.Tail(outq) + for line := range outq { + fmt.Println(line) + } +} diff --git a/spongy/irc.go b/spongyd/irc.go similarity index 100% rename from spongy/irc.go rename to spongyd/irc.go diff --git a/spongy/logfile.go b/spongyd/logfile.go similarity index 85% rename from spongy/logfile.go rename to spongyd/logfile.go index 6e6da2d..bde06a2 100644 --- a/spongy/logfile.go +++ b/spongyd/logfile.go @@ -64,14 +64,6 @@ func (lf *Logfile) processQueue() { lf.file.Close() } -func (lf *Logfile) writeln(s string) error { - _, err := fmt.Fprintf(lf.file, "%d %s\n", time.Now().Unix(), s) - if err == nil { - lf.nlines += 1 - } - return err -} - func (lf *Logfile) rotate() error { fn := fmt.Sprintf("%s.log", time.Now().UTC().Format(time.RFC3339)) pathn := path.Join(lf.baseDir, "log", fn) @@ -83,15 +75,15 @@ func (lf *Logfile) rotate() error { currentPath := path.Join(lf.baseDir, "log", "current") if lf.file == nil { - // Set lf.file just so we can write out NEXTLOG. - // If this fails, that's okay + // Open "current" to append a NEXTLOG line. + // If there's no "current", that's okay lf.file, _ = os.OpenFile(currentPath, os.O_WRONLY|os.O_APPEND, 0666) } if lf.file != nil { // Note location of new log logmsg := fmt.Sprintf("NEXTLOG %s", fn) - lf.writeln(timestamp(logmsg)) + fmt.Fprintln(lf.file, timestamp(logmsg)) // All done with the current log lf.file.Close() @@ -105,7 +97,7 @@ func (lf *Logfile) rotate() error { os.Symlink(fn, currentPath) logmsg := fmt.Sprintf("PREVLOG %s", lf.name) - lf.writeln(timestamp(logmsg)) + fmt.Fprintln(lf.file, timestamp(logmsg)) lf.name = fn diff --git a/spongy/network.go b/spongyd/network.go similarity index 93% rename from spongy/network.go rename to spongyd/network.go index 1b445fb..6bbc320 100644 --- a/spongy/network.go +++ b/spongyd/network.go @@ -200,7 +200,9 @@ func (nw *Network) messageDispatchLoop() { if len(out) > 0 { outlines := strings.Split(string(out), "\n") for _, line := range outlines { - nw.outq <- line + if len(line) > 0 { + nw.outq <- line + } } } } @@ -244,6 +246,14 @@ func (nw *Network) ConnectToNextServer() bool { func (nw *Network) login() { var name string + var username string + + usernames, err := ReadLines(path.Join(nw.basePath, "username")) + if err == nil { + username = usernames[0] + } else { + username = "sponge" + } names, err := ReadLines(path.Join(nw.basePath, "name")) if err == nil { @@ -258,10 +268,12 @@ func (nw *Network) login() { } if name == "" { - name = "Charlie" + // Rogue used "Rodney" if you didn't give it a name. + // This one works for the ladies, too. + name = "Ronnie" } - nw.outq <- "USER g g g :" + name + nw.outq <- "USER " + username + " g g :" + name nw.NextNick() } diff --git a/spongy/network_test.go b/spongyd/network_test.go similarity index 100% rename from spongy/network_test.go rename to spongyd/network_test.go diff --git a/spongy/readwritecloserwrapper.go b/spongyd/readwritecloserwrapper.go similarity index 100% rename from spongy/readwritecloserwrapper.go rename to spongyd/readwritecloserwrapper.go diff --git a/spongy/readwritecloserwrapper_test.go b/spongyd/readwritecloserwrapper_test.go similarity index 100% rename from spongy/readwritecloserwrapper_test.go rename to spongyd/readwritecloserwrapper_test.go diff --git a/spongy/spongy_test.go b/spongyd/spongy_test.go similarity index 100% rename from spongy/spongy_test.go rename to spongyd/spongy_test.go diff --git a/spongy/spongy.go b/spongyd/spongyd.go similarity index 100% rename from spongy/spongy.go rename to spongyd/spongyd.go