commit 190343e
Hubert Hirtz
·
2020-08-17 18:21:03 +0000 UTC
parent ba679ce
Add /names command
3 files changed,
+95,
-42
M
app.go
+18,
-0
1@@ -320,6 +320,24 @@ func (app *App) handleInput(buffer, content string) {
2 }
3
4 app.s.Part(args)
5+ case "NAMES":
6+ if buffer == ui.Home {
7+ return
8+ }
9+
10+ var sb strings.Builder
11+ sb.WriteString("\x0314Names: ")
12+ for _, name := range app.s.Names(buffer) {
13+ if name.PowerLevel != "" {
14+ sb.WriteString("\x033")
15+ sb.WriteString(name.PowerLevel)
16+ sb.WriteString("\x0314")
17+ }
18+ sb.WriteString(name.Nick)
19+ sb.WriteRune(' ')
20+ }
21+ line := sb.String()
22+ app.win.AddLine(buffer, ui.NewLineNow("--", line[:len(line)-1]))
23 case "TOPIC":
24 if buffer == ui.Home {
25 return
+76,
-41
1@@ -111,17 +111,13 @@ type User struct {
2
3 type Channel struct {
4 Name string
5- Members map[string]string
6+ Members map[*User]string
7 Topic string
8 TopicWho string
9 TopicTime time.Time
10 Secret bool
11 }
12
13-func (c *Channel) SetTopic(topic string) {
14- c.Topic = topic
15-}
16-
17 type SessionParams struct {
18 Nickname string
19 Username string
20@@ -156,7 +152,7 @@ type Session struct {
21 enabledCaps map[string]struct{}
22 features map[string]string
23
24- users map[string]User
25+ users map[string]*User
26 channels map[string]Channel
27 chBatches map[string]HistoryEvent
28 }
29@@ -177,7 +173,7 @@ func NewSession(conn io.ReadWriteCloser, params SessionParams) (s Session, err e
30 availableCaps: map[string]string{},
31 enabledCaps: map[string]struct{}{},
32 features: map[string]string{},
33- users: map[string]User{},
34+ users: map[string]*User{},
35 channels: map[string]Channel{},
36 chBatches: map[string]HistoryEvent{},
37 }
38@@ -243,6 +239,20 @@ func (s *Session) IsChannel(name string) bool {
39 return strings.IndexAny(name, "#&") == 0 // TODO compute CHANTYPES
40 }
41
42+func (s *Session) Names(channel string) []Name {
43+ var names []Name
44+ if c, ok := s.channels[strings.ToLower(channel)]; ok {
45+ names = make([]Name, 0, len(c.Members))
46+ for u, pl := range c.Members {
47+ names = append(names, Name{
48+ PowerLevel: pl,
49+ Nick: u.Nick,
50+ })
51+ }
52+ }
53+ return names
54+}
55+
56 func (s *Session) Topic(channel string) (topic string, who string, at time.Time) {
57 channelCf := strings.ToLower(channel)
58 if c, ok := s.channels[channelCf]; ok {
59@@ -505,6 +515,7 @@ func (s *Session) handle(msg Message) (err error) {
60 s.nick = msg.Params[0]
61 s.nickCf = strings.ToLower(s.nick)
62 s.registered = true
63+ s.users[s.nickCf] = &User{Nick: s.nick}
64 s.evts <- RegisteredEvent{}
65
66 if s.host == "" {
67@@ -604,13 +615,13 @@ func (s *Session) handle(msg Message) (err error) {
68 if nickCf == s.nickCf {
69 s.channels[channelCf] = Channel{
70 Name: msg.Params[0],
71- Members: map[string]string{},
72+ Members: map[*User]string{},
73 }
74 } else if c, ok := s.channels[channelCf]; ok {
75 if _, ok := s.users[nickCf]; !ok {
76- s.users[nickCf] = User{Nick: nick}
77+ s.users[nickCf] = &User{Nick: nick}
78 }
79- c.Members[nickCf] = ""
80+ c.Members[s.users[nickCf]] = ""
81
82 t, ok := msg.Time()
83 if !ok {
84@@ -629,61 +640,72 @@ func (s *Session) handle(msg Message) (err error) {
85 channelCf := strings.ToLower(msg.Params[0])
86
87 if nickCf == s.nickCf {
88- delete(s.channels, channelCf)
89- s.evts <- SelfPartEvent{Channel: msg.Params[0]}
90+ if c, ok := s.channels[channelCf]; ok {
91+ delete(s.channels, channelCf)
92+ for u := range c.Members {
93+ s.cleanUser(u)
94+ }
95+ s.evts <- SelfPartEvent{Channel: msg.Params[0]}
96+ }
97 } else if c, ok := s.channels[channelCf]; ok {
98- delete(c.Members, nickCf)
99+ if u, ok := s.users[nickCf]; ok {
100+ delete(c.Members, u)
101+ s.cleanUser(u)
102
103- t, ok := msg.Time()
104- if !ok {
105- t = time.Now()
106- }
107+ t, ok := msg.Time()
108+ if !ok {
109+ t = time.Now()
110+ }
111
112- s.evts <- UserPartEvent{
113- Channels: []string{c.Name},
114- Nick: nick,
115- Time: t,
116+ s.evts <- UserPartEvent{
117+ Channels: []string{c.Name},
118+ Nick: nick,
119+ Time: t,
120+ }
121 }
122 }
123 case "QUIT":
124 nick, _, _ := FullMask(msg.Prefix)
125 nickCf := strings.ToLower(nick)
126
127- t, ok := msg.Time()
128- if !ok {
129- t = time.Now()
130- }
131-
132- var channels []string
133+ if u, ok := s.users[nickCf]; ok {
134+ t, ok := msg.Time()
135+ if !ok {
136+ t = time.Now()
137+ }
138
139- for _, c := range s.channels {
140- if _, ok := c.Members[nickCf]; !ok {
141- continue
142+ var channels []string
143+ for _, c := range s.channels {
144+ if _, ok := c.Members[u]; ok {
145+ channels = append(channels, c.Name)
146+ delete(c.Members, u)
147+ s.cleanUser(u)
148+ }
149 }
150- channels = append(channels, c.Name)
151- }
152
153- s.evts <- UserPartEvent{
154- Channels: channels,
155- Nick: nick,
156- Time: t,
157+ s.evts <- UserPartEvent{
158+ Channels: channels,
159+ Nick: nick,
160+ Time: t,
161+ }
162 }
163 case rplNamreply:
164 channelCf := strings.ToLower(msg.Params[2])
165
166 if c, ok := s.channels[channelCf]; ok {
167 c.Secret = msg.Params[1] == "@"
168- names := TokenizeNames(msg.Params[3], "~&@%+") // TODO compute prefixes
169
170- for _, name := range names {
171+ for _, name := range TokenizeNames(msg.Params[3], "~&@%+") {
172 nick := name.Nick
173 nickCf := strings.ToLower(nick)
174
175 if _, ok := s.users[nickCf]; !ok {
176- s.users[nickCf] = User{Nick: nick}
177+ s.users[nickCf] = &User{Nick: nick}
178 }
179- c.Members[nickCf] = name.PowerLevel
180+ c.Members[s.users[nickCf]] = name.PowerLevel
181 }
182+
183+ s.channels[channelCf] = c
184 }
185 case rplEndofnames:
186 channelCf := strings.ToLower(msg.Params[1])
187@@ -782,6 +804,11 @@ func (s *Session) handle(msg Message) (err error) {
188 t = time.Now()
189 }
190
191+ formerUser := s.users[nickCf]
192+ formerUser.Nick = newNick
193+ delete(s.users, nickCf)
194+ s.users[newNickCf] = formerUser
195+
196 if nickCf == s.nickCf {
197 s.evts <- SelfNickEvent{
198 FormerNick: s.nick,
199@@ -796,7 +823,6 @@ func (s *Session) handle(msg Message) (err error) {
200 NewNick: newNick,
201 Time: t,
202 }
203- // TODO update state
204 }
205 case "FAIL":
206 fmt.Println("FAIL", msg.Params)
207@@ -848,6 +874,15 @@ func (s *Session) privmsgToEvent(msg Message) (ev Event) {
208 return
209 }
210
211+func (s *Session) cleanUser(parted *User) {
212+ for _, c := range s.channels {
213+ if _, ok := c.Members[parted]; ok {
214+ return
215+ }
216+ }
217+ delete(s.users, strings.ToLower(parted.Nick))
218+}
219+
220 func (s *Session) updateFeatures(features []string) {
221 for _, f := range features {
222 if f == "" || f == "-" || f == "=" || f == "-=" {
+1,
-1
1@@ -244,7 +244,7 @@ func (msg *Message) IsValid() bool {
2 return 4 <= len(msg.Params)
3 case rplWhoreply:
4 return 8 <= len(msg.Params)
5- case "JOIN", "PART", "TAGMSG":
6+ case "JOIN", "NICK", "PART", "TAGMSG":
7 return 1 <= len(msg.Params) && msg.Prefix != ""
8 case "PRIVMSG", "NOTICE", "TOPIC":
9 return 2 <= len(msg.Params) && msg.Prefix != ""