commit 9a732d4

Hubert Hirtz  ·  2020-06-03 17:03:58 +0000 UTC
parent 881d634
Part Join Typing
5 files changed,  +114, -29
+27, -13
 1@@ -59,6 +59,8 @@ func main() {
 2 				app.AddLine("home", "Connected to the server", time.Now())
 3 			case irc.SelfJoinEvent:
 4 				app.AddBuffer(ev.Channel)
 5+			case irc.SelfPartEvent:
 6+				app.RemoveBuffer(ev.Channel)
 7 			case irc.ChannelMessageEvent:
 8 				line := formatIRCMessage(ev.Nick, ev.Content)
 9 				app.AddLine(ev.Channel, line, ev.Time)
10@@ -94,11 +96,14 @@ func main() {
11 				case tcell.KeyBackspace2:
12 					app.InputBackspace()
13 				case tcell.KeyEnter:
14-					content := app.InputEnter()
15-					handleInput(app, &s, content)
16+					buffer := app.CurrentBuffer()
17+					input := app.InputEnter()
18+					handleInput(&s, buffer, input)
19 				case tcell.KeyRune:
20 					app.InputRune(ev.Rune())
21-					s.Typing(app.CurrentBuffer())
22+					if app.CurrentBuffer() != "home" && !strings.HasPrefix(app.Input(), "/") {
23+						s.Typing(app.CurrentBuffer())
24+					}
25 				}
26 			}
27 		}
28@@ -117,35 +122,44 @@ func parseCommand(s string) (command, args string) {
29 
30 	i := strings.IndexByte(s, ' ')
31 	if i < 0 {
32-		i = len(s) - 1
33+		i = len(s)
34 	}
35 
36 	command = strings.ToUpper(s[1:i])
37-	args = s[i+1:]
38+	args = strings.TrimLeft(s[i:], " ")
39 
40 	return
41 }
42 
43-func handleInput(app *ui.UI, s *irc.Session, content string) {
44+func handleInput(s *irc.Session, buffer, content string) {
45 	cmd, args := parseCommand(content)
46 
47 	switch cmd {
48 	case "":
49-		ch := app.CurrentBuffer()
50-		if ch == "home" {
51+		if buffer == "home" {
52+			return
53+		}
54+
55+		s.PrivMsg(buffer, args)
56+	case "J", "JOIN":
57+		s.Join(args)
58+	case "PART":
59+		if buffer == "home" {
60 			return
61 		}
62 
63-		s.PrivMsg(ch, args)
64+		if args == "" {
65+			args = buffer
66+		}
67+
68+		s.Part(args)
69 	case "ME":
70-		ch := app.CurrentBuffer()
71-		if ch == "home" {
72+		if buffer == "home" {
73 			return
74 		}
75 
76 		line := fmt.Sprintf("\x01ACTION %s\x01", args)
77-		s.PrivMsg(ch, line)
78-	default:
79+		s.PrivMsg(buffer, line)
80 	}
81 }
82 
+9, -0
 1@@ -34,6 +34,15 @@ type UserJoinEvent struct {
 2 	ChannelEvent
 3 }
 4 
 5+type SelfPartEvent struct {
 6+	ChannelEvent
 7+}
 8+
 9+type UserPartEvent struct {
10+	UserEvent
11+	ChannelEvent
12+}
13+
14 type SelfJoinEvent struct {
15 	ChannelEvent
16 }
+67, -15
  1@@ -84,16 +84,23 @@ type Channel struct {
  2 type action interface{}
  3 
  4 type (
  5+	actionJoin struct {
  6+		Channel string
  7+	}
  8+	actionPart struct {
  9+		Channel string
 10+	}
 11+
 12 	actionPrivMsg struct {
 13-		To      string
 14+		Channel string
 15 		Content string
 16 	}
 17 
 18 	actionTyping struct {
 19-		To string
 20+		Channel string
 21 	}
 22 	actionTypingStop struct {
 23-		To string
 24+		Channel string
 25 	}
 26 )
 27 
 28@@ -137,9 +144,9 @@ type Session struct {
 29 func NewSession(conn io.ReadWriteCloser, params SessionParams) (s Session, err error) {
 30 	s = Session{
 31 		conn:          conn,
 32-		msgs:          make(chan Message, 10),
 33-		acts:          make(chan action, 10),
 34-		evts:          make(chan Event, 10),
 35+		msgs:          make(chan Message, 128),
 36+		acts:          make(chan action, 128),
 37+		evts:          make(chan Event, 128),
 38 		typingStamps:  map[string]time.Time{},
 39 		nick:          params.Nickname,
 40 		lNick:         strings.ToLower(params.Nickname),
 41@@ -205,17 +212,35 @@ func (s *Session) IsChannel(name string) bool {
 42 	return strings.IndexAny(name, "#&") == 0 // TODO compute CHANTYPES
 43 }
 44 
 45-func (s *Session) PrivMsg(to, content string) {
 46-	s.acts <- actionPrivMsg{to, content}
 47+func (s *Session) Join(channel string) {
 48+	s.acts <- actionJoin{channel}
 49+}
 50+
 51+func (s *Session) join(act actionJoin) (err error) {
 52+	err = s.send("JOIN %s\r\n", act.Channel)
 53+	return
 54+}
 55+
 56+func (s *Session) Part(channel string) {
 57+	s.acts <- actionPart{channel}
 58+}
 59+
 60+func (s *Session) part(act actionPart) (err error) {
 61+	err = s.send("PART %s\r\n", act.Channel)
 62+	return
 63+}
 64+
 65+func (s *Session) PrivMsg(channel, content string) {
 66+	s.acts <- actionPrivMsg{channel, content}
 67 }
 68 
 69 func (s *Session) privMsg(act actionPrivMsg) (err error) {
 70-	err = s.send("PRIVMSG %s :%s\r\n", act.To, act.Content)
 71+	err = s.send("PRIVMSG %s :%s\r\n", act.Channel, act.Content)
 72 	return
 73 }
 74 
 75-func (s *Session) Typing(to string) {
 76-	s.acts <- actionTyping{to}
 77+func (s *Session) Typing(channel string) {
 78+	s.acts <- actionTyping{channel}
 79 }
 80 
 81 func (s *Session) typing(act actionTyping) (err error) {
 82@@ -223,13 +248,16 @@ func (s *Session) typing(act actionTyping) (err error) {
 83 		return
 84 	}
 85 
 86-	to := strings.ToLower(act.To)
 87+	to := strings.ToLower(act.Channel)
 88+	now := time.Now()
 89 
 90-	if t, ok := s.typingStamps[to]; ok && time.Now().Sub(t) < 3 {
 91+	if t, ok := s.typingStamps[to]; ok && now.Sub(t).Seconds() < 3.0 {
 92 		return
 93 	}
 94 
 95-	err = s.send("@+typing=active TAGMSG %s\r\n", act.To)
 96+	s.typingStamps[to] = now
 97+
 98+	err = s.send("@+typing=active TAGMSG %s\r\n", act.Channel)
 99 	return
100 }
101 
102@@ -242,7 +270,7 @@ func (s *Session) typingStop(act actionTypingStop) (err error) {
103 		return
104 	}
105 
106-	err = s.send("@+typing=done TAGMSG %s\r\n", act.To)
107+	err = s.send("@+typing=done TAGMSG %s\r\n", act.Channel)
108 	return
109 }
110 
111@@ -256,6 +284,10 @@ func (s *Session) run() {
112 		select {
113 		case act := <-s.acts:
114 			switch act := act.(type) {
115+			case actionJoin:
116+				err = s.join(act)
117+			case actionPart:
118+				err = s.part(act)
119 			case actionPrivMsg:
120 				err = s.privMsg(act)
121 			case actionTyping:
122@@ -497,6 +529,19 @@ func (s *Session) handle(msg Message) (ev Event, err error) {
123 			c.Members[lNick] = ""
124 			ev = UserJoinEvent{ChannelEvent: channelEv, UserEvent: UserEvent{Nick: nick}}
125 		}
126+	case "PART":
127+		nick, _, _ := FullMask(msg.Prefix)
128+		lNick := strings.ToLower(nick)
129+		channel := strings.ToLower(msg.Params[0])
130+		channelEv := ChannelEvent{Channel: msg.Params[0]}
131+
132+		if lNick == s.lNick {
133+			delete(s.channels, channel)
134+			ev = SelfPartEvent{ChannelEvent: channelEv}
135+		} else if c, ok := s.channels[channel]; ok {
136+			delete(c.Members, lNick)
137+			ev = UserPartEvent{ChannelEvent: channelEv, UserEvent: UserEvent{Nick: nick}}
138+		}
139 	case "353": // RPL_NAMREPLY
140 		channel := strings.ToLower(msg.Params[2])
141 
142@@ -623,3 +668,10 @@ func (s *Session) send(format string, args ...interface{}) (err error) {
143 }
144 
145 // */
146+
147+/*
148+func (s *Session) send(format string, args ...interface{}) (err error) {
149+	go fmt.Fprintf(s.conn, format, args...)
150+	return
151+}
152+// */
+6, -0
 1@@ -201,6 +201,12 @@ func (msg *Message) Validate() (err error) {
 2 		} else if msg.Prefix == "" {
 3 			err = errNoPrefix
 4 		}
 5+	case "PART":
 6+		if len(msg.Params) < 1 {
 7+			err = errNotEnoughParams
 8+		} else if msg.Prefix == "" {
 9+			err = errNoPrefix
10+		}
11 	case "353":
12 		if len(msg.Params) < 4 {
13 			err = errNotEnoughParams
+5, -1
 1@@ -34,7 +34,7 @@ func New() (ui *UI, err error) {
 2 	ui.screen.Clear()
 3 	ui.screen.ShowCursor(0, h-2)
 4 
 5-	ui.Events = make(chan tcell.Event)
 6+	ui.Events = make(chan tcell.Event, 128)
 7 	go func() {
 8 		for !ui.ShouldExit() {
 9 			ui.Events <- ui.screen.PollEvent()
10@@ -125,6 +125,10 @@ func (ui *UI) AddLine(buffer string, line string, t time.Time) {
11 	}
12 }
13 
14+func (ui *UI) Input() string {
15+	return string(ui.textInput)
16+}
17+
18 func (ui *UI) InputRune(r rune) {
19 	ui.textInput = append(ui.textInput, r)
20 	ui.textCursor++