|
@@ -4,8 +4,11 @@
|
4
|
4
|
package irc
|
5
|
5
|
|
6
|
6
|
import (
|
|
7
|
+ "bytes"
|
7
|
8
|
"fmt"
|
|
9
|
+ "hash/crc32"
|
8
|
10
|
"sort"
|
|
11
|
+ "strconv"
|
9
|
12
|
"strings"
|
10
|
13
|
|
11
|
14
|
"github.com/goshuirc/irc-go/ircfmt"
|
|
@@ -22,6 +25,10 @@ To see in-depth help for a specific ChanServ command, try:
|
22
|
25
|
Here are the commands you can use:
|
23
|
26
|
%s`
|
24
|
27
|
|
|
28
|
+func chanregEnabled(server *Server) bool {
|
|
29
|
+ return server.ChannelRegistrationEnabled()
|
|
30
|
+}
|
|
31
|
+
|
25
|
32
|
var (
|
26
|
33
|
chanservCommands = map[string]*serviceCommand{
|
27
|
34
|
"op": {
|
|
@@ -32,6 +39,7 @@ OP makes the given nickname, or yourself, a channel admin. You can only use
|
32
|
39
|
this command if you're the founder of the channel.`,
|
33
|
40
|
helpShort: `$bOP$b makes the given user (or yourself) a channel admin.`,
|
34
|
41
|
authRequired: true,
|
|
42
|
+ enabled: chanregEnabled,
|
35
|
43
|
},
|
36
|
44
|
"register": {
|
37
|
45
|
handler: csRegisterHandler,
|
|
@@ -42,6 +50,17 @@ given admin privs on it. Modes set on the channel and the topic will also be
|
42
|
50
|
remembered.`,
|
43
|
51
|
helpShort: `$bREGISTER$b lets you own a given channel.`,
|
44
|
52
|
authRequired: true,
|
|
53
|
+ enabled: chanregEnabled,
|
|
54
|
+ },
|
|
55
|
+ "unregister": {
|
|
56
|
+ handler: csUnregisterHandler,
|
|
57
|
+ help: `Syntax: $bUNREGISTER #channel [code]$b
|
|
58
|
+
|
|
59
|
+UNREGISTER deletes a channel registration, allowing someone else to claim it.
|
|
60
|
+To prevent accidental unregistrations, a verification code is required;
|
|
61
|
+invoking the command without a code will display the necessary code.`,
|
|
62
|
+ helpShort: `$bUNREGISTER$b deletes a channel registration.`,
|
|
63
|
+ enabled: chanregEnabled,
|
45
|
64
|
},
|
46
|
65
|
"amode": {
|
47
|
66
|
handler: csAmodeHandler,
|
|
@@ -53,6 +72,7 @@ account the +o operator mode every time they join #channel. To list current
|
53
|
72
|
accounts and modes, use $bAMODE #channel$b. Note that users are always
|
54
|
73
|
referenced by their registered account names, not their nicknames.`,
|
55
|
74
|
helpShort: `$bAMODE$b modifies persistent mode settings for channel members.`,
|
|
75
|
+ enabled: chanregEnabled,
|
56
|
76
|
},
|
57
|
77
|
}
|
58
|
78
|
)
|
|
@@ -197,11 +217,6 @@ func csOpHandler(server *Server, client *Client, command, params string, rb *Res
|
197
|
217
|
}
|
198
|
218
|
|
199
|
219
|
func csRegisterHandler(server *Server, client *Client, command, params string, rb *ResponseBuffer) {
|
200
|
|
- if !server.channelRegistrationEnabled {
|
201
|
|
- csNotice(rb, client.t("Channel registration is not enabled"))
|
202
|
|
- return
|
203
|
|
- }
|
204
|
|
-
|
205
|
220
|
channelName := strings.TrimSpace(params)
|
206
|
221
|
if channelName == "" {
|
207
|
222
|
csNotice(rb, ircfmt.Unescape(client.t("Syntax: $bREGISTER #channel$b")))
|
|
@@ -246,3 +261,45 @@ func csRegisterHandler(server *Server, client *Client, command, params string, r
|
246
|
261
|
}
|
247
|
262
|
}
|
248
|
263
|
}
|
|
264
|
+
|
|
265
|
+func csUnregisterHandler(server *Server, client *Client, command, params string, rb *ResponseBuffer) {
|
|
266
|
+ channelName, verificationCode := utils.ExtractParam(params)
|
|
267
|
+ channelKey, err := CasefoldChannel(channelName)
|
|
268
|
+ if channelKey == "" || err != nil {
|
|
269
|
+ csNotice(rb, client.t("Channel name is not valid"))
|
|
270
|
+ return
|
|
271
|
+ }
|
|
272
|
+
|
|
273
|
+ channel := server.channels.Get(channelKey)
|
|
274
|
+ if channel == nil {
|
|
275
|
+ csNotice(rb, client.t("No such channel"))
|
|
276
|
+ return
|
|
277
|
+ }
|
|
278
|
+
|
|
279
|
+ hasPrivs := client.HasRoleCapabs("chanreg")
|
|
280
|
+ if !hasPrivs {
|
|
281
|
+ founder := channel.Founder()
|
|
282
|
+ hasPrivs = founder != "" && founder == client.Account()
|
|
283
|
+ }
|
|
284
|
+ if !hasPrivs {
|
|
285
|
+ csNotice(rb, client.t("Insufficient privileges"))
|
|
286
|
+ return
|
|
287
|
+ }
|
|
288
|
+
|
|
289
|
+ info := channel.ExportRegistration(0)
|
|
290
|
+ // verification code is the crc32 of the name, plus the registration time
|
|
291
|
+ var codeInput bytes.Buffer
|
|
292
|
+ codeInput.WriteString(info.Name)
|
|
293
|
+ codeInput.WriteString(strconv.FormatInt(info.RegisteredAt.Unix(), 16))
|
|
294
|
+ expectedCode := int(crc32.ChecksumIEEE(codeInput.Bytes()))
|
|
295
|
+ receivedCode, err := strconv.Atoi(verificationCode)
|
|
296
|
+ if err != nil || expectedCode != receivedCode {
|
|
297
|
+ csNotice(rb, client.t("$bWarning:$b Unregistering this channel will remove all stored channel attributes."))
|
|
298
|
+ csNotice(rb, fmt.Sprintf(client.t("To confirm channel unregistration, type: /CS UNREGISTER %s %d"), channelKey, expectedCode))
|
|
299
|
+ return
|
|
300
|
+ }
|
|
301
|
+
|
|
302
|
+ channel.SetUnregistered()
|
|
303
|
+ go server.channelRegistry.Delete(channelKey, info)
|
|
304
|
+ csNotice(rb, fmt.Sprintf(client.t("Channel %s is now unregistered"), channelKey))
|
|
305
|
+}
|