commit e56baed
Hubert Hirtz
·
2020-08-05 20:04:50 +0000 UTC
parent 713dd4a
Add a -debug flag and show raw messages
6 files changed,
+128,
-35
M
app.go
+8,
-1
1@@ -44,6 +44,7 @@ func NewApp(cfg Config) (app *App, err error) {
2 Username: cfg.User,
3 RealName: cfg.Real,
4 Auth: auth,
5+ Debug: cfg.Debug,
6 })
7 if err != nil {
8 return
9@@ -79,8 +80,14 @@ func (app *App) Run() {
10
11 func (app *App) handleIRCEvent(ev irc.Event) {
12 switch ev := ev.(type) {
13+ case irc.RawMessageEvent:
14+ head := "DEBUG IN --"
15+ if ev.Outgoing {
16+ head = "DEBUG OUT --"
17+ }
18+ app.win.AddLine(ui.Home, ui.NewLineNow(head, ev.Message), false)
19 case irc.RegisteredEvent:
20- app.win.AddLine("", ui.NewLineNow("--", "Connected to the server"), false)
21+ app.win.AddLine(ui.Home, ui.NewLineNow("--", "Connected to the server"), false)
22 if app.cfg.Highlights == nil {
23 app.highlights[0] = app.s.LNick()
24 }
+4,
-0
1@@ -19,7 +19,9 @@ func main() {
2 tcell.SetEncodingFallback(tcell.EncodingFallbackASCII)
3
4 var configPath string
5+ var debug bool
6 flag.StringVar(&configPath, "config", "", "path to the configuration file")
7+ flag.BoolVar(&debug, "debug", false, "show raw protocol data in the home buffer")
8 flag.Parse()
9
10 if configPath == "" {
11@@ -35,6 +37,8 @@ func main() {
12 log.Panicln(err)
13 }
14
15+ cfg.Debug = cfg.Debug || debug
16+
17 app, err := senpai.NewApp(cfg)
18 if err != nil {
19 log.Panicln(err)
+2,
-0
1@@ -13,6 +13,8 @@ type Config struct {
2 User string
3 Password *string
4 Highlights []string
5+
6+ Debug bool
7 }
8
9 func ParseConfig(buf []byte) (cfg Config, err error) {
+5,
-0
1@@ -7,6 +7,11 @@ import (
2
3 type Event interface{}
4
5+type RawMessageEvent struct {
6+ Message string
7+ Outgoing bool
8+}
9+
10 type RegisteredEvent struct{}
11
12 type UserEvent struct {
+29,
-31
1@@ -120,6 +120,8 @@ type SessionParams struct {
2 RealName string
3
4 Auth SASLClient
5+
6+ Debug bool
7 }
8
9 type Session struct {
10@@ -128,6 +130,8 @@ type Session struct {
11 acts chan action
12 evts chan Event
13
14+ debug bool
15+
16 running atomic.Value // bool
17 state ConnectionState
18 typingStamps map[string]time.Time
19@@ -140,9 +144,6 @@ type Session struct {
20 host string
21 auth SASLClient
22
23- mode string
24- motd string
25-
26 availableCaps map[string]string
27 enabledCaps map[string]struct{}
28 features map[string]string
29@@ -158,6 +159,7 @@ func NewSession(conn io.ReadWriteCloser, params SessionParams) (s Session, err e
30 msgs: make(chan Message, 16),
31 acts: make(chan action, 16),
32 evts: make(chan Event, 16),
33+ debug: params.Debug,
34 typingStamps: map[string]time.Time{},
35 nick: params.Nickname,
36 lNick: strings.ToLower(params.Nickname),
37@@ -360,6 +362,10 @@ func (s *Session) run() {
38 }
39
40 func (s *Session) handleStart(msg Message) (err error) {
41+ if s.debug {
42+ s.evts <- RawMessageEvent{Message: msg.String()}
43+ }
44+
45 switch msg.Command {
46 case "AUTHENTICATE":
47 if s.auth != nil {
48@@ -445,8 +451,6 @@ func (s *Session) handleStart(msg Message) (err error) {
49 }
50 }
51 }
52- case errNomotd:
53- s.motd += "\n" + strings.TrimPrefix(msg.Params[1], "- ")
54 case errNicknameinuse:
55 s.nick = s.nick + "_"
56
57@@ -455,13 +459,20 @@ func (s *Session) handleStart(msg Message) (err error) {
58 return
59 }
60 default:
61- err = s.handle(msg)
62+ err = s.handleInner(msg)
63 }
64
65 return
66 }
67
68 func (s *Session) handle(msg Message) (err error) {
69+ if s.debug {
70+ s.evts <- RawMessageEvent{Message: msg.String()}
71+ }
72+ return s.handleInner(msg)
73+}
74+
75+func (s *Session) handleInner(msg Message) (err error) {
76 if id, ok := msg.Tags["batch"]; ok {
77 if b, ok := s.chBatches[id]; ok {
78 s.chBatches[id] = HistoryEvent{
79@@ -745,6 +756,7 @@ func (s *Session) handle(msg Message) (err error) {
80 s.state = ConnQuit
81 default:
82 }
83+
84 return
85 }
86
87@@ -812,34 +824,20 @@ func (s *Session) updateFeatures(features []string) {
88 }
89 }
90
91-/*
92-func (cli *Session) send(format string, args ...interface{}) (err error) {
93+func (s *Session) send(format string, args ...interface{}) (err error) {
94 msg := fmt.Sprintf(format, args...)
95-
96- for _, line := range strings.Split(msg, "\r\n") {
97- if line != "" {
98- fmt.Println("< ", line)
99+ _, err = s.conn.Write([]byte(msg))
100+
101+ if s.debug {
102+ for _, line := range strings.Split(msg, "\r\n") {
103+ if line != "" {
104+ s.evts <- RawMessageEvent{
105+ Message: line,
106+ Outgoing: true,
107+ }
108+ }
109 }
110 }
111
112- _, err = cli.conn.Write([]byte(msg))
113-
114- return
115-}
116-
117-// */
118-
119-//*
120-func (s *Session) send(format string, args ...interface{}) (err error) {
121- _, err = fmt.Fprintf(s.conn, format, args...)
122- return
123-}
124-
125-// */
126-
127-/*
128-func (s *Session) send(format string, args ...interface{}) (err error) {
129- go fmt.Fprintf(s.conn, format, args...)
130 return
131 }
132-// */
+80,
-3
1@@ -38,7 +38,7 @@ func tagEscape(c rune) (escape rune) {
2 return
3 }
4
5-func unescapeTagValue(escaped string) (unescaped string) {
6+func unescapeTagValue(escaped string) string {
7 var builder strings.Builder
8 builder.Grow(len(escaped))
9 escape := false
10@@ -60,8 +60,36 @@ func unescapeTagValue(escaped string) (unescaped string) {
11 }
12 }
13
14- unescaped = builder.String()
15- return
16+ return builder.String()
17+}
18+
19+func escapeTagValue(unescaped string) string {
20+ var sb strings.Builder
21+ sb.Grow(len(unescaped) * 2)
22+
23+ for _, c := range unescaped {
24+ switch c {
25+ case ';':
26+ sb.WriteRune('\\')
27+ sb.WriteRune(':')
28+ case ' ':
29+ sb.WriteRune('\\')
30+ sb.WriteRune('s')
31+ case '\r':
32+ sb.WriteRune('\\')
33+ sb.WriteRune('r')
34+ case '\n':
35+ sb.WriteRune('\\')
36+ sb.WriteRune('n')
37+ case '\\':
38+ sb.WriteRune('\\')
39+ sb.WriteRune('\\')
40+ default:
41+ sb.WriteRune(c)
42+ }
43+ }
44+
45+ return sb.String()
46 }
47
48 func parseTags(s string) (tags map[string]string) {
49@@ -154,6 +182,55 @@ func Tokenize(line string) (msg Message, err error) {
50 return
51 }
52
53+func (msg *Message) IsReply() bool {
54+ if len(msg.Command) != 3 {
55+ return false
56+ }
57+ for _, r := range msg.Command {
58+ if !('0' <= r && r <= '9') {
59+ return false
60+ }
61+ }
62+ return true
63+}
64+
65+func (msg *Message) String() string {
66+ var sb strings.Builder
67+
68+ if msg.Tags != nil {
69+ sb.WriteRune('@')
70+ for k, v := range msg.Tags {
71+ sb.WriteString(k)
72+ if v != "" {
73+ sb.WriteRune('=')
74+ sb.WriteString(escapeTagValue(v))
75+ }
76+ sb.WriteRune(';')
77+ }
78+ sb.WriteRune(' ')
79+ }
80+
81+ if msg.Prefix != "" {
82+ sb.WriteRune(':')
83+ sb.WriteString(msg.Prefix)
84+ sb.WriteRune(' ')
85+ }
86+
87+ sb.WriteString(msg.Command)
88+
89+ if len(msg.Params) != 0 {
90+ for _, p := range msg.Params[:len(msg.Params)-1] {
91+ sb.WriteRune(' ')
92+ sb.WriteString(p)
93+ }
94+ sb.WriteRune(' ')
95+ sb.WriteRune(':')
96+ sb.WriteString(msg.Params[len(msg.Params)-1])
97+ }
98+
99+ return sb.String()
100+}
101+
102 func (msg *Message) Validate() (err error) {
103 switch msg.Command {
104 case rplWelcome: