summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--irc/rpl.go1
-rw-r--r--irc/session.go29
2 files changed, 25 insertions, 5 deletions
diff --git a/irc/rpl.go b/irc/rpl.go
index 398b5b3..1e50938 100644
--- a/irc/rpl.go
+++ b/irc/rpl.go
@@ -43,6 +43,7 @@ const (
rplVersion = "351" // <version> <servername> :<comments>
rplWhoreply = "352" // <channel> <user> <host> <server> <nick> "H"/"G" ["*"] [("@"/"+")] :<hop count> <nick>
rplNamreply = "353" // <=/*/@> <channel> :1*(@/ /+user)
+ rplWhospecialreply = "354" // [token] [channel] [user] [ip] [host] [server] [nick] [flags] [hopcount] [idle] [account] [oplevel] [:realname]
rplEndofnames = "366" // <channel> :End of names list
rplBanlist = "367" // <channel> <ban mask>
rplEndofbanlist = "368" // <channel> :End of ban list
diff --git a/irc/session.go b/irc/session.go
index 0776436..3a6d4e1 100644
--- a/irc/session.go
+++ b/irc/session.go
@@ -134,6 +134,7 @@ type Session struct {
prefixSymbols string
prefixModes string
monitor bool
+ whox bool
users map[string]*User // known users.
channels map[string]Channel // joined channels.
@@ -359,6 +360,15 @@ func (s *Session) ChangeNick(nick string) {
s.out <- NewMessage("NICK", nick)
}
+func (s *Session) Who(target string) {
+ if s.whox {
+ // only request what we need, to optimize server who cache hits and reduce traffic
+ s.out <- NewMessage("WHO", target, "%uhnf")
+ } else {
+ s.out <- NewMessage("WHO", target)
+ }
+}
+
func (s *Session) ChangeMode(channel, flags string, args []string) {
if flags != "" {
args = append([]string{channel, flags}, args...)
@@ -693,7 +703,7 @@ func (s *Session) handleMessageRegistered(msg Message, playback bool) (Event, er
Name: s.nick, User: s.user, Host: s.host,
}}
if s.host == "" {
- s.out <- NewMessage("WHO", s.nick)
+ s.Who(s.nick)
}
case rplIsupport:
if len(msg.Params) < 3 {
@@ -701,14 +711,21 @@ func (s *Session) handleMessageRegistered(msg Message, playback bool) (Event, er
}
s.updateFeatures(msg.Params[1 : len(msg.Params)-1])
return RegisteredEvent{}, nil
- case rplWhoreply:
+ case rplWhoreply, rplWhospecialreply:
var nick, host, flags, username string
- if err := msg.ParseParams(nil, nil, &username, &host, nil, &nick, &flags, nil); err != nil {
+ var err error
+ if msg.Command == rplWhoreply {
+ err = msg.ParseParams(nil, nil, &username, &host, nil, &nick, &flags, nil)
+ } else {
+ // we always request WHOX with %uhnf
+ err = msg.ParseParams(nil, &username, &host, &nick, &flags)
+ }
+ if err != nil {
return nil, err
}
nickCf := s.Casemap(nick)
- away := flags[0] == 'G' // flags is not empty because it's not the trailing parameter
+ away := strings.ContainsRune(flags, 'G')
if s.nickCf == nickCf {
s.user = username
@@ -794,7 +811,7 @@ func (s *Session) handleMessageRegistered(msg Message, playback bool) (Event, er
// Only try to know who is away if the list is
// updated by the server via away-notify.
// Otherwise, it'll become outdated over time.
- s.out <- NewMessage("WHO", channel)
+ s.Who(channel)
}
} else if c, ok := s.channels[channelCf]; ok {
if _, ok := s.users[nickCf]; !ok {
@@ -1525,6 +1542,8 @@ func (s *Session) updateFeatures(features []string) {
numPrefixes := len(value)/2 - 1
s.prefixModes = value[1 : numPrefixes+1]
s.prefixSymbols = value[numPrefixes+2:]
+ case "WHOX":
+ s.whox = true
}
}
}