xirc: move over Membership
This commit is contained in:
parent
f3b06f4236
commit
f9c4ba636f
@ -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
62
irc.go
@ -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 }
|
||||||
|
18
upstream.go
18
upstream.go
@ -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],
|
||||||
}
|
}
|
||||||
|
45
xirc/xirc.go
45
xirc/xirc.go
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user