/
chanserv.go
168 lines (137 loc) · 4.27 KB
/
chanserv.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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
package atheme
import (
"strconv"
"strings"
)
// ChanServ implements a Golang client to Atheme's ChanServ. This is
// mostly a port of Cod's string parsing code.
type ChanServ struct {
a *Atheme
}
// Flagset is a simple flagset wrapper.
type Flagset struct {
Id int `json:"id"`
Nick string `json:"nick"`
Flags string `json:"flags"`
}
// ChannelInfo is the information Atheme has on a channel.
type ChannelInfo struct {
Name string `json:"name"` // Channel name
Mlock string `json:"mlock"` // Channel mode lock
Flags []string `json:"flags"` // Channel SET flags
Founder string `json:"founder"` // Channel founder
Registered string `json:"registered"` // Channel age
Description string `json:"description"` // Channel description
}
// Kick sends a ChanServ KICK command to channel on victim with the denoted
// reason. You must have a reason for calls made with this function.
func (cs *ChanServ) Kick(channel, victim, reason string) (res string, err error) {
return cs.a.Command("ChanServ", "KICK", channel, victim, reason)
}
// GetAccessList returns a slice of Flagsets representing the access
// list of the channel you are requesting. This will fail if the Atheme call
// fails.
func (cs *ChanServ) GetAccessList(channel string) (res []Flagset, err error) {
var output string
output, err = cs.a.Command("ChanServ", "FLAGS", channel)
if err != nil {
return nil, err
}
lines := strings.Split(output, "\n")
for _, line := range lines {
line = strings.Replace(line, " ", "", -1)
data := strings.Split(line, " ")
id, _ := strconv.Atoi(data[0])
res = append(res, Flagset{
Id: id,
Nick: data[1],
Flags: data[2],
})
}
return
}
// SetAccessList commits a flag change on a channel with a given flagset.
func (cs *ChanServ) SetAccessList(channel, target, flags string) (err error) {
_, err = cs.a.Command("ChanServ", "FLAGS", channel, target, flags)
return
}
// List lists all channels returning a slice of ChannelInfo structs
// or an error describing the fault.
func (cs *ChanServ) List() (res []*ChannelInfo, err error) {
var output string
output, err = cs.a.Command("ChanServ", "LIST")
if err != nil {
return nil, err
}
lines := strings.Split(output, "\n")
lines = lines[1 : len(lines)-1] // Shuck off the first and last lines as they are not useful.
for _, line := range lines {
// TODO: parse flags
// - #lobby ($oper) [held]
name := strings.Split(line, " ")[1]
founder := strings.Split(strings.Split(line, "(")[1], ")")[0]
res = append(res, &ChannelInfo{
Name: name,
Founder: founder,
})
}
return
}
// Info gets information on a channel, returning a ChannelInfo struct
// or an error describing the fault.
func (cs *ChanServ) Info(channel string) (ci *ChannelInfo, err error) {
// I am sorry.
var output string
output, err = cs.a.Command("ChanServ", "INFO", channel, "FOO")
if err != nil {
return nil, err
}
/*
Information on #niichan:
Registered : Nov 06 10:01:32 2013 (40w 2d 12h ago)
Mode lock : +n
Flags : HOLD SECURE VERBOSE KEEPTOPIC GUARD FANTASY PRIVATE
Prefix : ! (default)
*** End of Info ***
*/
ci = &ChannelInfo{
Name: channel,
}
for _, line := range strings.Split(output, "\n") {
if strings.HasPrefix(line, "Information on #") || strings.HasPrefix(line, "*") {
continue
}
line = strings.Replace(line, " ", "", -1)
data := strings.Split(line, ":")
key := strings.TrimSpace(strings.ToLower(data[0]))
value := strings.TrimSpace(strings.Join(data[1:], ":"))
// TODO: replace this with reflect
switch key {
case "mode lock":
ci.Mlock = value
case "flags":
ci.Flags = strings.Split(value, " ")
case "founder":
ci.Founder = value
case "registered":
ci.Registered = value
case "entrymsg":
ci.Description = value
}
}
return
}
// GetChannelFlags returns the SET flags of a channel as a string slice.
func (cs *ChanServ) GetChannelFlags(channel string) (flags []string, err error) {
var ci *ChannelInfo
ci, err = cs.Info(channel)
if err != nil {
return nil, err
}
return ci.Flags, err
}
// SetChannelFlag sets a channel SET flag or returns an error.
func (cs *ChanServ) SetChannelFlag(channel, flag, value string) (err error) {
_, err = cs.a.Command("ChanServ", "SET", channel, flag, value)
return
}