xirc: move over Membership

This commit is contained in:
Simon Ser 2022-05-30 09:12:28 +02:00
parent f3b06f4236
commit f9c4ba636f
4 changed files with 65 additions and 64 deletions

View File

@ -76,8 +76,8 @@ func sendNames(dc *downstreamConn, ch *upstreamChannel) {
var members []string var members []string
for _, entry := range ch.Members.innerMap { for _, entry := range ch.Members.innerMap {
nick := entry.originalKey nick := entry.originalKey
memberships := entry.value.(*memberships) memberships := entry.value.(*xirc.MembershipSet)
s := memberships.Format(dc) + dc.marshalEntity(ch.conn.network, nick) s := formatMemberPrefix(*memberships, dc) + dc.marshalEntity(ch.conn.network, nick)
members = append(members, s) members = append(members, s)
} }

62
irc.go
View File

@ -180,12 +180,7 @@ func (cm channelModes) Format() (modeString string, parameters []string) {
const stdChannelTypes = "#&+!" const stdChannelTypes = "#&+!"
type membership struct { var stdMemberships = []xirc.Membership{
Mode byte
Prefix byte
}
var stdMemberships = []membership{
{'q', '~'}, // founder {'q', '~'}, // founder
{'a', '&'}, // protected {'a', '&'}, // protected
{'o', '@'}, // operator {'o', '@'}, // operator
@ -193,55 +188,16 @@ var stdMemberships = []membership{
{'v', '+'}, // voice {'v', '+'}, // voice
} }
// memberships always sorted by descending membership rank func formatMemberPrefix(ms xirc.MembershipSet, dc *downstreamConn) string {
type memberships []membership
func (m *memberships) Add(availableMemberships []membership, newMembership membership) {
l := *m
i := 0
for _, availableMembership := range availableMemberships {
if i >= len(l) {
break
}
if l[i] == availableMembership {
if availableMembership == newMembership {
// we already have this membership
return
}
i++
continue
}
if availableMembership == newMembership {
break
}
}
// insert newMembership at i
l = append(l, membership{})
copy(l[i+1:], l[i:])
l[i] = newMembership
*m = l
}
func (m *memberships) Remove(oldMembership membership) {
l := *m
for i, currentMembership := range l {
if currentMembership == oldMembership {
*m = append(l[:i], l[i+1:]...)
return
}
}
}
func (m memberships) Format(dc *downstreamConn) string {
if !dc.caps.IsEnabled("multi-prefix") { if !dc.caps.IsEnabled("multi-prefix") {
if len(m) == 0 { if len(ms) == 0 {
return "" return ""
} }
return string(m[0].Prefix) return string(ms[0].Prefix)
} }
prefixes := make([]byte, len(m)) prefixes := make([]byte, len(ms))
for i, membership := range m { for i, m := range ms {
prefixes[i] = membership.Prefix prefixes[i] = m.Prefix
} }
return string(prefixes) return string(prefixes)
} }
@ -439,12 +395,12 @@ func (cm *channelCasemapMap) Value(name string) *database.Channel {
type membershipsCasemapMap struct{ casemapMap } type membershipsCasemapMap struct{ casemapMap }
func (cm *membershipsCasemapMap) Value(name string) *memberships { func (cm *membershipsCasemapMap) Value(name string) *xirc.MembershipSet {
entry, ok := cm.innerMap[cm.casemap(name)] entry, ok := cm.innerMap[cm.casemap(name)]
if !ok { if !ok {
return nil return nil
} }
return entry.value.(*memberships) return entry.value.(*xirc.MembershipSet)
} }
type deliveredCasemapMap struct{ casemapMap } type deliveredCasemapMap struct{ casemapMap }

View File

@ -119,7 +119,7 @@ type upstreamConn struct {
availableUserModes string availableUserModes string
availableChannelModes map[byte]channelModeType availableChannelModes map[byte]channelModeType
availableChannelTypes string availableChannelTypes string
availableMemberships []membership availableMemberships []xirc.Membership
isupport map[string]*string isupport map[string]*string
registered bool registered bool
@ -413,8 +413,8 @@ func (uc *upstreamConn) cancelPendingCommandsByDownstreamID(downstreamID uint64)
} }
} }
func (uc *upstreamConn) parseMembershipPrefix(s string) (ms *memberships, nick string) { func (uc *upstreamConn) parseMembershipPrefix(s string) (ms xirc.MembershipSet, nick string) {
memberships := make(memberships, 0, 4) var memberships xirc.MembershipSet
i := 0 i := 0
for _, m := range uc.availableMemberships { for _, m := range uc.availableMemberships {
if i >= len(s) { if i >= len(s) {
@ -425,7 +425,7 @@ func (uc *upstreamConn) parseMembershipPrefix(s string) (ms *memberships, nick s
i++ i++
} }
} }
return &memberships, s[i:] return memberships, s[i:]
} }
func (uc *upstreamConn) handleMessage(ctx context.Context, msg *irc.Message) error { func (uc *upstreamConn) handleMessage(ctx context.Context, msg *irc.Message) error {
@ -1021,7 +1021,7 @@ func (uc *upstreamConn) handleMessage(ctx context.Context, msg *irc.Message) err
if err != nil { if err != nil {
return err return err
} }
ch.Members.SetValue(msg.Prefix.Name, &memberships{}) ch.Members.SetValue(msg.Prefix.Name, &xirc.MembershipSet{})
} }
chMsg := msg.Copy() chMsg := msg.Copy()
@ -1340,7 +1340,7 @@ func (uc *upstreamConn) handleMessage(ctx context.Context, msg *irc.Message) err
members := splitSpace(members) members := splitSpace(members)
for i, member := range members { for i, member := range members {
memberships, nick := uc.parseMembershipPrefix(member) memberships, nick := uc.parseMembershipPrefix(member)
members[i] = memberships.Format(dc) + dc.marshalEntity(uc.network, nick) members[i] = formatMemberPrefix(memberships, dc) + dc.marshalEntity(uc.network, nick)
} }
memberStr := strings.Join(members, " ") memberStr := strings.Join(members, " ")
@ -1484,7 +1484,7 @@ func (uc *upstreamConn) handleMessage(ctx context.Context, msg *irc.Message) err
for i, channel := range channels { for i, channel := range channels {
prefix, channel := uc.parseMembershipPrefix(channel) prefix, channel := uc.parseMembershipPrefix(channel)
channel = dc.marshalEntity(uc.network, channel) channel = dc.marshalEntity(uc.network, channel)
l[i] = prefix.Format(dc) + channel l[i] = formatMemberPrefix(prefix, dc) + channel
} }
channelList = strings.Join(l, " ") channelList = strings.Join(l, " ")
dc.SendMessage(&irc.Message{ dc.SendMessage(&irc.Message{
@ -1842,9 +1842,9 @@ func (uc *upstreamConn) handleMemberships(s string) error {
if sep < 0 || len(s) != sep*2 { if sep < 0 || len(s) != sep*2 {
return fmt.Errorf("malformed ISUPPORT PREFIX value: %v", s) return fmt.Errorf("malformed ISUPPORT PREFIX value: %v", s)
} }
memberships := make([]membership, len(s)/2-1) memberships := make([]xirc.Membership, len(s)/2-1)
for i := range memberships { for i := range memberships {
memberships[i] = membership{ memberships[i] = xirc.Membership{
Mode: s[i+1], Mode: s[i+1],
Prefix: s[sep+i+1], Prefix: s[sep+i+1],
} }

View File

@ -86,3 +86,48 @@ func ParseChannelStatus(s string) (ChannelStatus, error) {
return 0, fmt.Errorf("invalid channel status %q: unknown status", s) return 0, fmt.Errorf("invalid channel status %q: unknown status", s)
} }
} }
// Membership is a channel member rank.
type Membership struct {
Mode byte
Prefix byte
}
// MembershipSet is a set of memberships sorted by descending rank.
type MembershipSet []Membership
func (ms *MembershipSet) Add(availableMemberships []Membership, newMembership Membership) {
l := *ms
i := 0
for _, availableMembership := range availableMemberships {
if i >= len(l) {
break
}
if l[i] == availableMembership {
if availableMembership == newMembership {
// we already have this membership
return
}
i++
continue
}
if availableMembership == newMembership {
break
}
}
// insert newMembership at i
l = append(l, Membership{})
copy(l[i+1:], l[i:])
l[i] = newMembership
*ms = l
}
func (ms *MembershipSet) Remove(membership Membership) {
l := *ms
for i, m := range l {
if m == membership {
*ms = append(l[:i], l[i+1:]...)
return
}
}
}