Changeset 139 in code for trunk/irc.go
- Timestamp:
- Mar 25, 2020, 8:40:08 AM (5 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/irc.go
r128 r139 16 16 ) 17 17 18 type modeSetstring18 type userModes string 19 19 20 func (ms modeSet) Has(c byte) bool {20 func (ms userModes) Has(c byte) bool { 21 21 return strings.IndexByte(string(ms), c) >= 0 22 22 } 23 23 24 func (ms * modeSet) Add(c byte) {24 func (ms *userModes) Add(c byte) { 25 25 if !ms.Has(c) { 26 *ms += modeSet(c)26 *ms += userModes(c) 27 27 } 28 28 } 29 29 30 func (ms * modeSet) Del(c byte) {30 func (ms *userModes) Del(c byte) { 31 31 i := strings.IndexByte(string(*ms), c) 32 32 if i >= 0 { … … 35 35 } 36 36 37 func (ms * modeSet) Apply(s string) error {37 func (ms *userModes) Apply(s string) error { 38 38 var plusMinus byte 39 39 for i := 0; i < len(s); i++ { … … 54 54 return nil 55 55 } 56 57 type channelModeType byte 58 59 // standard channel mode types, as explained in https://modern.ircdocs.horse/#mode-message 60 const ( 61 // modes that add or remove an address to or from a list 62 modeTypeA channelModeType = iota 63 // modes that change a setting on a channel, and must always have a parameter 64 modeTypeB 65 // modes that change a setting on a channel, and must have a parameter when being set, and no parameter when being unset 66 modeTypeC 67 // modes that change a setting on a channel, and must not have a parameter 68 modeTypeD 69 ) 70 71 var stdChannelModes = map[byte]channelModeType{ 72 'b': modeTypeA, // ban list 73 'e': modeTypeA, // ban exception list 74 'I': modeTypeA, // invite exception list 75 'k': modeTypeB, // channel key 76 'l': modeTypeC, // channel user limit 77 'i': modeTypeD, // channel is invite-only 78 'm': modeTypeD, // channel is moderated 79 'n': modeTypeD, // channel has no external messages 80 's': modeTypeD, // channel is secret 81 't': modeTypeD, // channel has protected topic 82 } 83 84 type channelModes map[byte]string 85 86 func (cm channelModes) Apply(modeTypes map[byte]channelModeType, modeStr string, arguments ...string) error { 87 nextArgument := 0 88 var plusMinus byte 89 for i := 0; i < len(modeStr); i++ { 90 mode := modeStr[i] 91 if mode == '+' || mode == '-' { 92 plusMinus = mode 93 continue 94 } 95 if plusMinus != '+' && plusMinus != '-' { 96 return fmt.Errorf("malformed modestring %q: missing plus/minus", modeStr) 97 } 98 99 mt, ok := modeTypes[mode] 100 if !ok { 101 continue 102 } 103 if mt == modeTypeB || (mt == modeTypeC && plusMinus == '+') { 104 if plusMinus == '+' { 105 var argument string 106 // some sentitive arguments (such as channel keys) can be omitted for privacy 107 // (this will only happen for RPL_CHANNELMODEIS, never for MODE messages) 108 if nextArgument < len(arguments) { 109 argument = arguments[nextArgument] 110 } 111 cm[mode] = argument 112 } else { 113 delete(cm, mode) 114 } 115 nextArgument++ 116 } else if mt == modeTypeC || mt == modeTypeD { 117 if plusMinus == '+' { 118 cm[mode] = "" 119 } else { 120 delete(cm, mode) 121 } 122 } 123 } 124 return nil 125 } 126 127 func (cm channelModes) Format() (modeString string, parameters []string) { 128 var modesWithValues strings.Builder 129 var modesWithoutValues strings.Builder 130 parameters = make([]string, 0, 16) 131 for mode, value := range cm { 132 if value != "" { 133 modesWithValues.WriteString(string(mode)) 134 parameters = append(parameters, value) 135 } else { 136 modesWithoutValues.WriteString(string(mode)) 137 } 138 } 139 modeString = "+" + modesWithValues.String() + modesWithoutValues.String() 140 return 141 } 142 143 const stdChannelTypes = "#&+!" 56 144 57 145 type channelStatus byte … … 75 163 } 76 164 77 type membership byte 165 type membership struct { 166 Mode byte 167 Prefix byte 168 } 78 169 79 const ( 80 membershipFounder membership = '~'81 membershipProtected membership = '&'82 membershipOperator membership = '@'83 membershipHalfOp membership = '%'84 membershipVoice membership = '+'85 ) 170 var stdMemberships = []membership{ 171 {'q', '~'}, // founder 172 {'a', '&'}, // protected 173 {'o', '@'}, // operator 174 {'h', '%'}, // halfop 175 {'v', '+'}, // voice 176 } 86 177 87 const stdMembershipPrefixes = "~&@%+" 88 89 func (m membership) String() string { 90 if m == 0 { 178 func (m *membership) String() string { 179 if m == nil { 91 180 return "" 92 181 } 93 return string(m) 94 } 95 96 func parseMembershipPrefix(s string) (prefix membership, nick string) { 97 // TODO: any prefix from PREFIX RPL_ISUPPORT 98 if strings.IndexByte(stdMembershipPrefixes, s[0]) >= 0 { 99 return membership(s[0]), s[1:] 100 } else { 101 return 0, s 102 } 182 return string(m.Prefix) 103 183 } 104 184
Note:
See TracChangeset
for help on using the changeset viewer.