commit a3fb513

Hubert Hirtz  ·  2021-10-23 17:10:49 +0000 UTC
parent 0dc0542
Make use of away-notify
3 files changed,  +42, -7
+31, -5
 1@@ -71,8 +71,8 @@ const (
 2 
 3 // User is a known IRC user (we share a channel with it).
 4 type User struct {
 5-	Name    *Prefix // the nick, user and hostname of the user if known.
 6-	AwayMsg string  // the away message if the user is away, "" otherwise.
 7+	Name *Prefix // the nick, user and hostname of the user if known.
 8+	Away bool    // whether the user is away or not
 9 }
10 
11 // Channel is a joined channel.
12@@ -217,6 +217,7 @@ func (s *Session) Names(channel string) []Member {
13 			names = append(names, Member{
14 				PowerLevel: pl,
15 				Name:       u.Name.Copy(),
16+				Away:       u.Away,
17 			})
18 		}
19 	}
20@@ -581,14 +582,23 @@ func (s *Session) handleRegistered(msg Message) (Event, error) {
21 		}
22 		s.updateFeatures(msg.Params[1 : len(msg.Params)-1])
23 	case rplWhoreply:
24-		var nick, host string
25-		if err := msg.ParseParams(nil, nil, nil, &host, nil, &nick); err != nil {
26+		var nick, host, stats string
27+		if err := msg.ParseParams(nil, nil, nil, &host, nil, &nick, &stats, nil); err != nil {
28 			return nil, err
29 		}
30 
31-		if s.nickCf == s.Casemap(nick) {
32+		nickCf := s.Casemap(nick)
33+		away := stats[0] == 'G' // stats is not empty because it's not the trailing parameter
34+
35+		if s.nickCf == nickCf {
36 			s.host = host
37 		}
38+
39+		if u, ok := s.users[nickCf]; ok {
40+			u.Away = away
41+		}
42+	case rplEndofwho:
43+		// do nothing
44 	case "CAP":
45 		var subcommand, caps string
46 		if err := msg.ParseParams(nil, &subcommand, &caps); err != nil {
47@@ -654,6 +664,12 @@ func (s *Session) handleRegistered(msg Message) (Event, error) {
48 				Name:    msg.Params[0],
49 				Members: map[*User]string{},
50 			}
51+			if _, ok := s.enabledCaps["away-notify"]; ok {
52+				// Only try to know who is away if the list is
53+				// updated by the server via away-notify.
54+				// Otherwise, it'll become outdated over time.
55+				s.out <- NewMessage("WHO", channel)
56+			}
57 		} else if c, ok := s.channels[channelCf]; ok {
58 			if _, ok := s.users[nickCf]; !ok {
59 				s.users[nickCf] = &User{Name: msg.Prefix.Copy()}
60@@ -893,6 +909,16 @@ func (s *Session) handleRegistered(msg Message) (Event, error) {
61 			Invitee: nick,
62 			Channel: channel,
63 		}, nil
64+	case "AWAY":
65+		if msg.Prefix == nil {
66+			return nil, errMissingPrefix
67+		}
68+
69+		nickCf := s.Casemap(msg.Prefix.Name)
70+
71+		if u, ok := s.users[nickCf]; ok {
72+			u.Away = len(msg.Params) == 1
73+		}
74 	case "PRIVMSG", "NOTICE":
75 		if msg.Prefix == nil {
76 			return nil, errMissingPrefix
+1, -0
1@@ -463,6 +463,7 @@ func ParseCaps(caps string) (diff []Cap) {
2 type Member struct {
3 	PowerLevel string
4 	Name       *Prefix
5+	Away       bool
6 }
7 
8 type members []Member
+10, -2
 1@@ -370,7 +370,15 @@ func drawVerticalMemberList(screen tcell.Screen, x0, y0, width, height int, memb
 2 		} else {
 3 			x++
 4 		}
 5-		name := truncate(m.Name.Name, width-1, "\u2026")
 6-		printString(screen, &x, y, PlainString(name))
 7+
 8+		var name StyledString
 9+		nameText := truncate(m.Name.Name, width-1, "\u2026")
10+		if m.Away {
11+			name = Styled(nameText, tcell.StyleDefault.Foreground(tcell.ColorGray))
12+		} else {
13+			name = PlainString(nameText)
14+		}
15+
16+		printString(screen, &x, y, name)
17 	}
18 }