- commit
- 9a1eafa
- parent
- b3a222b
- author
- Neale Pickett
- date
- 2016-01-18 22:01:29 -0700 MST
New non-cgi client
10 files changed,
+245,
-15
+171,
-0
1@@ -0,0 +1,171 @@
2+package main
3+
4+import (
5+ "bufio"
6+ "fmt"
7+ "github.com/go-fsnotify/fsnotify"
8+ "io/ioutil"
9+ "os"
10+ "path"
11+ "strconv"
12+ "strings"
13+ "time"
14+)
15+
16+const eventIdSep = "/"
17+
18+type Network struct {
19+ running bool
20+
21+ Name string
22+ currentLog string
23+ lineno int64
24+
25+ basePath string
26+ seq int
27+}
28+
29+func NewNetwork(basePath string) (*Network) {
30+ return &Network{
31+ running: true,
32+ Name: path.Base(basePath),
33+ basePath: basePath,
34+ }
35+}
36+
37+func (nw *Network) Close() {
38+ nw.running = false
39+}
40+
41+func (nw *Network) ReadLastEventId(lastEventId string) {
42+ for _, eventId := range strings.Split(lastEventId, " ") {
43+ parts := strings.Split(eventId, eventIdSep)
44+ if len(parts) != 3 {
45+ continue
46+ }
47+
48+ if parts[0] != nw.Name {
49+ continue
50+ }
51+ nw.currentLog = parts[1]
52+ nw.lineno, _ = strconv.ParseInt(parts[2], 10, 64)
53+ return
54+ }
55+}
56+
57+func (nw *Network) LastEventId() string {
58+ parts := []string{nw.Name, nw.currentLog, strconv.FormatInt(nw.lineno, 10)}
59+ return strings.Join(parts, eventIdSep)
60+}
61+
62+func (nw *Network) errmsg(err error) string {
63+ return fmt.Sprintf("ERROR: %s", err.Error())
64+}
65+
66+func (nw *Network) Tail(out chan<- string) {
67+ if nw.currentLog == "" {
68+ var err error
69+
70+ currentfn := path.Join(nw.basePath, "log", "current")
71+ nw.currentLog, err = os.Readlink(currentfn)
72+ if err != nil {
73+ out <- nw.errmsg(err)
74+ return
75+ }
76+ }
77+
78+ filepath := path.Join(nw.basePath, "log", nw.currentLog)
79+ f, err := os.Open(filepath)
80+ if err != nil {
81+ out <- nw.errmsg(err)
82+ return
83+ }
84+ defer f.Close()
85+
86+ watcher, err := fsnotify.NewWatcher()
87+ if err != nil {
88+ out <- nw.errmsg(err)
89+ return
90+ }
91+ defer watcher.Close()
92+
93+ watcher.Add(filepath)
94+ lineno := int64(0)
95+
96+ // XXX: some way to stop this?
97+ for nw.running {
98+ bf := bufio.NewScanner(f)
99+ for bf.Scan() {
100+ lineno += 1
101+ if lineno <= nw.lineno {
102+ continue
103+ } else {
104+ nw.lineno = lineno
105+ }
106+
107+ t := bf.Text()
108+
109+ parts := strings.Split(t, " ")
110+ if (len(parts) >= 3) && (parts[1] == "NEXTLOG") {
111+ watcher.Remove(filepath)
112+ filename := parts[2]
113+ filepath = path.Join(nw.basePath, "log", filename)
114+ f.Close()
115+ f, err = os.Open(filepath)
116+ if err != nil {
117+ out <- nw.errmsg(err)
118+ return
119+ }
120+ watcher.Add(filepath)
121+ lineno = 0
122+ nw.lineno = 0
123+ }
124+ out <- t
125+ }
126+
127+ select {
128+ case _ = <-watcher.Events:
129+ // Somethin' happened!
130+ case err := <-watcher.Errors:
131+ out <- nw.errmsg(err)
132+ return
133+ }
134+ }
135+}
136+
137+func (nw *Network) Write(data []byte) {
138+ epoch := time.Now().Unix()
139+ pid := os.Getpid()
140+ filename := fmt.Sprintf("%d-%d-%d.txt", epoch, pid, nw.seq)
141+
142+ filepath := path.Join(nw.basePath, "outq", filename)
143+ ioutil.WriteFile(filepath, data, 0750)
144+ nw.seq += 1
145+}
146+
147+
148+func Networks(basePath string) (found []*Network) {
149+
150+ dir, err := os.Open(basePath)
151+ if err != nil {
152+ return
153+ }
154+ defer dir.Close()
155+
156+
157+ entities, _ := dir.Readdirnames(0)
158+ for _, fn := range entities {
159+ netdir := path.Join(basePath, fn)
160+
161+ _, err = os.Stat(path.Join(netdir, "nick"))
162+ if err != nil {
163+ continue
164+ }
165+
166+ nw := NewNetwork(netdir)
167+ found = append(found, nw)
168+ }
169+
170+ return
171+}
172+
+55,
-0
1@@ -0,0 +1,55 @@
2+package main
3+
4+import (
5+ "bufio"
6+ "fmt"
7+ "flag"
8+ "log"
9+ "os"
10+ "path/filepath"
11+)
12+
13+var playback int
14+var running bool = true
15+
16+func inputLoop(nw *Network) {
17+ bf := bufio.NewScanner(os.Stdin)
18+ for bf.Scan() {
19+ line := bf.Bytes()
20+ nw.Write(line)
21+ }
22+}
23+
24+func usage() {
25+ fmt.Fprintf(os.Stderr, "Usage: %s [OPTIONS] NETDIR\n", os.Args[0])
26+ fmt.Fprintf(os.Stderr, "\n")
27+ fmt.Fprintf(os.Stderr, "NETDIR is the path to your IRC directory (see README)\n")
28+ fmt.Fprintf(os.Stderr, "\n")
29+ fmt.Fprintf(os.Stderr, "OPTIONS:\n")
30+ flag.PrintDefaults()
31+}
32+
33+func main() {
34+ flag.Usage = usage
35+ flag.IntVar(&playback, "playback", 0, "Number of lines to play back on startup")
36+
37+ flag.Parse()
38+ if flag.NArg() != 1 {
39+ usage()
40+ os.Exit(2)
41+ }
42+ netDir, err := filepath.Abs(flag.Arg(0))
43+ if err != nil {
44+ log.Fatal(err)
45+ }
46+
47+ nw := NewNetwork(netDir)
48+ defer nw.Close()
49+ go inputLoop(nw)
50+
51+ outq := make(chan string, 50) // to stdout
52+ go nw.Tail(outq)
53+ for line := range outq {
54+ fmt.Println(line)
55+ }
56+}
R spongy/irc.go =>
spongyd/irc.go
+0,
-0
R spongy/logfile.go =>
spongyd/logfile.go
+4,
-12
1@@ -64,14 +64,6 @@ func (lf *Logfile) processQueue() {
2 lf.file.Close()
3 }
4
5-func (lf *Logfile) writeln(s string) error {
6- _, err := fmt.Fprintf(lf.file, "%d %s\n", time.Now().Unix(), s)
7- if err == nil {
8- lf.nlines += 1
9- }
10- return err
11-}
12-
13 func (lf *Logfile) rotate() error {
14 fn := fmt.Sprintf("%s.log", time.Now().UTC().Format(time.RFC3339))
15 pathn := path.Join(lf.baseDir, "log", fn)
16@@ -83,15 +75,15 @@ func (lf *Logfile) rotate() error {
17 currentPath := path.Join(lf.baseDir, "log", "current")
18
19 if lf.file == nil {
20- // Set lf.file just so we can write out NEXTLOG.
21- // If this fails, that's okay
22+ // Open "current" to append a NEXTLOG line.
23+ // If there's no "current", that's okay
24 lf.file, _ = os.OpenFile(currentPath, os.O_WRONLY|os.O_APPEND, 0666)
25 }
26
27 if lf.file != nil {
28 // Note location of new log
29 logmsg := fmt.Sprintf("NEXTLOG %s", fn)
30- lf.writeln(timestamp(logmsg))
31+ fmt.Fprintln(lf.file, timestamp(logmsg))
32
33 // All done with the current log
34 lf.file.Close()
35@@ -105,7 +97,7 @@ func (lf *Logfile) rotate() error {
36 os.Symlink(fn, currentPath)
37
38 logmsg := fmt.Sprintf("PREVLOG %s", lf.name)
39- lf.writeln(timestamp(logmsg))
40+ fmt.Fprintln(lf.file, timestamp(logmsg))
41
42 lf.name = fn
43
R spongy/network.go =>
spongyd/network.go
+15,
-3
1@@ -200,7 +200,9 @@ func (nw *Network) messageDispatchLoop() {
2 if len(out) > 0 {
3 outlines := strings.Split(string(out), "\n")
4 for _, line := range outlines {
5- nw.outq <- line
6+ if len(line) > 0 {
7+ nw.outq <- line
8+ }
9 }
10 }
11 }
12@@ -244,6 +246,14 @@ func (nw *Network) ConnectToNextServer() bool {
13
14 func (nw *Network) login() {
15 var name string
16+ var username string
17+
18+ usernames, err := ReadLines(path.Join(nw.basePath, "username"))
19+ if err == nil {
20+ username = usernames[0]
21+ } else {
22+ username = "sponge"
23+ }
24
25 names, err := ReadLines(path.Join(nw.basePath, "name"))
26 if err == nil {
27@@ -258,10 +268,12 @@ func (nw *Network) login() {
28 }
29
30 if name == "" {
31- name = "Charlie"
32+ // Rogue used "Rodney" if you didn't give it a name.
33+ // This one works for the ladies, too.
34+ name = "Ronnie"
35 }
36
37- nw.outq <- "USER g g g :" + name
38+ nw.outq <- "USER " + username + " g g :" + name
39 nw.NextNick()
40 }
41
R spongy/network_test.go =>
spongyd/network_test.go
+0,
-0
R spongy/readwritecloserwrapper.go =>
spongyd/readwritecloserwrapper.go
+0,
-0
R spongy/readwritecloserwrapper_test.go =>
spongyd/readwritecloserwrapper_test.go
+0,
-0
R spongy/spongy_test.go =>
spongyd/spongy_test.go
+0,
-0
R spongy/spongy.go =>
spongyd/spongyd.go
+0,
-0