-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathmode.go
122 lines (108 loc) · 2.11 KB
/
mode.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
package etcdircd
import (
"bytes"
)
type modeSet map[byte]struct{}
type modePerms struct {
all modeSet
add modeSet
del modeSet
}
var userModePerms = modePerms{
all: modeSet{
// Away
'a': {},
// Invisible
'i': {},
// Local operator
'o': {},
// OTR encrypted
'E': {},
// Global operator
'O': {},
},
add: modeSet{
'i': {},
'E': {},
},
del: modeSet{
'a': {},
'i': {},
'o': {},
'E': {},
'O': {},
},
}
var chanModes = modeSet{
// need op or voice to send message on channel
'm': {},
// need op or voice to set topic
't': {},
// do not display in LIST output
's': {},
}
var chanModePerms = modePerms{
all: chanModes,
add: chanModes,
del: chanModes,
}
type ModeValue []byte
func newModeValue(modes string) ModeValue { return ModeValue(modes) }
func (mv ModeValue) has(m byte) bool { return bytes.IndexByte(mv, m) >= 0 }
func (mv ModeValue) add(m byte) ModeValue {
if mv.has(m) {
return mv
}
return append(mv, m)
}
func (mv ModeValue) del(m byte) ModeValue {
idx := bytes.IndexByte(mv, m)
if idx < 0 {
return mv
}
return append(mv[:idx], mv[idx+1:]...)
}
// update interprets mode updates of form '+whatever' and '-whatever'.
// Returns a list of uninterpreted modes.
func (mv ModeValue) update(modeStr string, mp modePerms) (_ ModeValue, bad []byte) {
ms := []byte(modeStr)
if len(ms) == 0 {
return mv, nil
}
switch ms[0] {
case '+':
for _, m := range ms[1:] {
if _, ok := mp.add[m]; ok {
mv = mv.add(m)
} else {
bad = append(bad, m)
}
}
case '-':
for _, m := range ms[1:] {
if _, ok := mp.del[m]; ok {
mv = mv.del(m)
} else {
bad = append(bad, m)
}
}
default:
for _, m := range ms {
if _, ok := mp.all[m]; !ok {
bad = append(bad, m)
}
}
}
return mv, bad
}
func (mv ModeValue) updateSlice(modes []string, mp modePerms) (ModeValue, []byte, bool) {
bad := []byte{}
oldMode, ret := mv, mv
for _, m := range modes {
newMode, newBad := ret.update(m, mp)
ret = newMode
bad = append(bad, newBad...)
}
return ret, bad, !oldMode.Equal(ret)
}
func (mv ModeValue) Equal(mv2 ModeValue) bool { return bytes.Equal(mv, mv2) }