diff --git a/downstream.go b/downstream.go index f48653e..0c02201 100644 --- a/downstream.go +++ b/downstream.go @@ -2230,6 +2230,23 @@ func (dc *downstreamConn) handleMessageRegistered(ctx context.Context, msg *irc. } if uc.isChannel(mask) { info.Channel = mask + + // Set channel membership prefixes from cached NAMES reply + ch := uc.channels.Get(info.Channel) + memberships := ch.Members.Get(info.Nickname) + prefixes := formatMemberPrefix(*memberships, dc) + + // Channel membership prefixes are listed after away status ('G'/'H') + // and optional server operator indicator ('*') + i := strings.IndexFunc(info.Flags, func(f rune) bool { + return f != 'G' && f != 'H' && f != '*' + }) + + if i == -1 { + info.Flags = prefixes + info.Flags + } else { + info.Flags = info.Flags[:i] + prefixes + info.Flags[i:] + } } dc.SendMessage(ctx, xirc.GenerateWHOXReply(fields, &info)) } diff --git a/irc.go b/irc.go index 12732c4..9a7735b 100644 --- a/irc.go +++ b/irc.go @@ -194,6 +194,19 @@ func formatMemberPrefix(ms xirc.MembershipSet, dc *downstreamConn) string { return string(prefixes) } +// Remove channel membership prefixes from flags +func stripMemberPrefixes(flags string, uc *upstreamConn) string { + return strings.Map(func(r rune) rune { + for _, v := range uc.availableMemberships { + if byte(r) == v.Prefix { + return -1 + } + } + + return r + }, flags) +} + func parseMessageParams(msg *irc.Message, out ...*string) error { if len(msg.Params) < len(out) { return newNeedMoreParamsError(msg.Command) diff --git a/upstream.go b/upstream.go index 9173c3a..025646e 100644 --- a/upstream.go +++ b/upstream.go @@ -1541,7 +1541,7 @@ func (uc *upstreamConn) handleMessage(ctx context.Context, msg *irc.Message) err Hostname: host, Server: server, Nickname: nick, - Flags: flags, + Flags: stripMemberPrefixes(flags, uc), Realname: realname, }) } @@ -1564,13 +1564,14 @@ func (uc *upstreamConn) handleMessage(ctx context.Context, msg *irc.Message) err if err != nil { return err } + if uc.shouldCacheUserInfo(info.Nickname) { uc.cacheUserInfo(info.Nickname, &upstreamUser{ Nickname: info.Nickname, Username: info.Username, Hostname: info.Hostname, Server: info.Server, - Flags: info.Flags, + Flags: stripMemberPrefixes(info.Flags, uc), Account: info.Account, Realname: info.Realname, })