Преглед на файлове

Refactor chanserv.go to match nickserv.go, unify the two

tags/v0.11.0-beta
Daniel Oaks преди 6 години
родител
ревизия
6fb4284e32
променени са 2 файла, в които са добавени 146 реда и са изтрити 46 реда
  1. 143
    45
      irc/chanserv.go
  2. 3
    1
      irc/nickserv.go

+ 143
- 45
irc/chanserv.go Целия файл

@@ -5,16 +5,62 @@ package irc
5 5
 
6 6
 import (
7 7
 	"fmt"
8
+	"sort"
8 9
 	"strings"
9 10
 
10 11
 	"github.com/goshuirc/irc-go/ircfmt"
11 12
 	"github.com/oragono/oragono/irc/modes"
12 13
 	"github.com/oragono/oragono/irc/sno"
14
+	"github.com/oragono/oragono/irc/utils"
13 15
 )
14 16
 
15
-// ChanServNotice sends the client a notice from ChanServ.
16
-func (rb *ResponseBuffer) ChanServNotice(text string) {
17
-	rb.Add(nil, fmt.Sprintf("ChanServ!services@%s", rb.target.server.name), "NOTICE", rb.target.nick, text)
17
+const chanservHelp = `ChanServ lets you register and manage channels.
18
+
19
+To see in-depth help for a specific ChanServ command, try:
20
+    $b/CS HELP <command>$b
21
+
22
+Here are the commands you can use:
23
+%s`
24
+
25
+type csCommand struct {
26
+	capabs    []string // oper capabs the given user has to have to access this command
27
+	handler   func(server *Server, client *Client, command, params string, rb *ResponseBuffer)
28
+	help      string
29
+	helpShort string
30
+	oper      bool // true if the user has to be an oper to use this command
31
+}
32
+
33
+var (
34
+	chanservCommands = map[string]*csCommand{
35
+		"help": {
36
+			help: `Syntax: $bHELP [command]$b
37
+
38
+HELP returns information on the given command.`,
39
+			helpShort: `$bHELP$b shows in-depth information about commands.`,
40
+		},
41
+		"op": {
42
+			handler: csOpHandler,
43
+			help: `Syntax: $bOP #channel [nickname]$b
44
+
45
+OP makes the given nickname, or yourself, a channel admin. You can only use
46
+this command if you're the founder of the channel.`,
47
+			helpShort: `$bOP$b makes the given user (or yourself) a channel admin.`,
48
+		},
49
+		"register": {
50
+			handler: csRegisterHandler,
51
+			help: `Syntax: $bREGISTER #channel$b
52
+
53
+REGISTER lets you own the given channel. If you rejoin this channel, you'll be
54
+given admin privs on it. Modes set on the channel and the topic will also be
55
+remembered.`,
56
+			helpShort: `$bREGISTER$b lets you own a given channel.`,
57
+		},
58
+	}
59
+)
60
+
61
+// csNotice sends the client a notice from ChanServ
62
+func csNotice(rb *ResponseBuffer, text string) {
63
+	rb.Add(nil, "ChanServ", "NOTICE", rb.target.Nick(), text)
18 64
 }
19 65
 
20 66
 // chanservReceiveNotice handles NOTICEs that ChanServ receives.
@@ -24,68 +70,115 @@ func (server *Server) chanservNoticeHandler(client *Client, message string, rb *
24 70
 
25 71
 // chanservReceiveNotice handles NOTICEs that ChanServ receives.
26 72
 func (server *Server) chanservPrivmsgHandler(client *Client, message string, rb *ResponseBuffer) {
27
-	var params []string
28
-	for _, p := range strings.Split(message, " ") {
29
-		if len(p) > 0 {
30
-			params = append(params, p)
31
-		}
73
+	commandName, params := utils.ExtractParam(message)
74
+	commandName = strings.ToLower(commandName)
75
+
76
+	commandInfo := chanservCommands[commandName]
77
+	if commandInfo == nil {
78
+		csNotice(rb, client.t("Unknown command. To see available commands, run /CS HELP"))
79
+		return
32 80
 	}
33
-	if len(params) < 1 {
34
-		rb.ChanServNotice(client.t("You need to run a command"))
35
-		//TODO(dan): dump CS help here
81
+
82
+	if commandInfo.oper && !client.HasMode(modes.Operator) {
83
+		csNotice(rb, client.t("Command restricted"))
36 84
 		return
37 85
 	}
38 86
 
39
-	command := strings.ToLower(params[0])
40
-	server.logger.Debug("chanserv", fmt.Sprintf("Client %s ran command %s", client.nick, command))
87
+	if 0 < len(commandInfo.capabs) && !client.HasRoleCapabs(commandInfo.capabs...) {
88
+		csNotice(rb, client.t("Command restricted"))
89
+		return
90
+	}
41 91
 
42
-	if command == "register" {
43
-		if len(params) < 2 {
44
-			rb.ChanServNotice(client.t("Syntax: REGISTER <channel>"))
45
-			return
46
-		}
92
+	// custom help handling here to prevent recursive init loop
93
+	if commandName == "help" {
94
+		csHelpHandler(server, client, commandName, params, rb)
95
+		return
96
+	}
47 97
 
48
-		server.chanservRegisterHandler(client, params[1], rb)
49
-	} else if command == "op" {
50
-		if len(params) < 2 {
51
-			rb.ChanServNotice(client.t("Syntax: OP <channel> [<nick>]"))
52
-			return
53
-		}
98
+	if commandInfo.handler == nil {
99
+		csNotice(rb, client.t("Command error. Please report this to the developers"))
100
+		return
101
+	}
102
+
103
+	server.logger.Debug("chanserv", fmt.Sprintf("Client %s ran command %s", client.Nick(), commandName))
104
+
105
+	commandInfo.handler(server, client, commandName, params, rb)
106
+}
54 107
 
55
-		var clientToOp string
56
-		if 2 < len(params) {
57
-			clientToOp = params[2]
108
+func csHelpHandler(server *Server, client *Client, command, params string, rb *ResponseBuffer) {
109
+	csNotice(rb, ircfmt.Unescape(client.t("*** $bChanServ HELP$b ***")))
110
+
111
+	if params == "" {
112
+		// show general help
113
+		var shownHelpLines sort.StringSlice
114
+		for _, commandInfo := range chanservCommands {
115
+			// skip commands user can't access
116
+			if commandInfo.oper && !client.HasMode(modes.Operator) {
117
+				continue
118
+			}
119
+			if 0 < len(commandInfo.capabs) && !client.HasRoleCapabs(commandInfo.capabs...) {
120
+				continue
121
+			}
122
+
123
+			shownHelpLines = append(shownHelpLines, "    "+client.t(commandInfo.helpShort))
58 124
 		}
59 125
 
60
-		server.chanservOpHandler(client, params[1], clientToOp, rb)
126
+		// sort help lines
127
+		sort.Sort(shownHelpLines)
128
+
129
+		// assemble help text
130
+		assembledHelpLines := strings.Join(shownHelpLines, "\n")
131
+		fullHelp := ircfmt.Unescape(fmt.Sprintf(client.t(chanservHelp), assembledHelpLines))
132
+
133
+		// push out help text
134
+		for _, line := range strings.Split(fullHelp, "\n") {
135
+			csNotice(rb, line)
136
+		}
61 137
 	} else {
62
-		rb.ChanServNotice(client.t("Sorry, I don't know that command"))
138
+		commandInfo := chanservCommands[strings.ToLower(strings.TrimSpace(params))]
139
+		if commandInfo == nil {
140
+			csNotice(rb, client.t("Unknown command. To see available commands, run /cs HELP"))
141
+		} else {
142
+			for _, line := range strings.Split(ircfmt.Unescape(client.t(commandInfo.help)), "\n") {
143
+				csNotice(rb, line)
144
+			}
145
+		}
63 146
 	}
147
+
148
+	csNotice(rb, ircfmt.Unescape(client.t("*** $bEnd of ChanServ HELP$b ***")))
64 149
 }
65 150
 
66
-// chanservOpHandler handles the ChanServ OP subcommand.
67
-func (server *Server) chanservOpHandler(client *Client, channelName, clientToOp string, rb *ResponseBuffer) {
151
+func csOpHandler(server *Server, client *Client, command, params string, rb *ResponseBuffer) {
152
+	channelName, clientToOp := utils.ExtractParam(params)
153
+
154
+	if channelName == "" {
155
+		csNotice(rb, ircfmt.Unescape(client.t("Syntax: $bOP #channel [nickname]$b")))
156
+		return
157
+	}
158
+
159
+	clientToOp = strings.TrimSpace(clientToOp)
160
+
68 161
 	channelKey, err := CasefoldChannel(channelName)
69 162
 	if err != nil {
70
-		rb.ChanServNotice(client.t("Channel name is not valid"))
163
+		csNotice(rb, client.t("Channel name is not valid"))
71 164
 		return
72 165
 	}
73 166
 
74 167
 	channelInfo := server.channels.Get(channelKey)
75 168
 	if channelInfo == nil {
76
-		rb.ChanServNotice(client.t("Channel does not exist"))
169
+		csNotice(rb, client.t("Channel does not exist"))
77 170
 		return
78 171
 	}
79 172
 
80 173
 	clientAccount := client.Account()
81 174
 
82 175
 	if clientAccount == "" {
83
-		rb.ChanServNotice(client.t("You must be logged in to op on a channel"))
176
+		csNotice(rb, client.t("You must be logged in to op on a channel"))
84 177
 		return
85 178
 	}
86 179
 
87 180
 	if clientAccount != channelInfo.Founder() {
88
-		rb.ChanServNotice(client.t("You must be the channel founder to op"))
181
+		csNotice(rb, client.t("You must be the channel founder to op"))
89 182
 		return
90 183
 	}
91 184
 
@@ -94,7 +187,7 @@ func (server *Server) chanservOpHandler(client *Client, channelName, clientToOp
94 187
 		casefoldedNickname, err := CasefoldName(clientToOp)
95 188
 		target = server.clients.Get(casefoldedNickname)
96 189
 		if err != nil || target == nil {
97
-			rb.ChanServNotice(client.t("Could not find given client"))
190
+			csNotice(rb, client.t("Could not find given client"))
98 191
 			return
99 192
 		}
100 193
 	} else {
@@ -116,47 +209,52 @@ func (server *Server) chanservOpHandler(client *Client, channelName, clientToOp
116 209
 		}
117 210
 	}
118 211
 
119
-	rb.ChanServNotice(fmt.Sprintf(client.t("Successfully op'd in channel %s"), channelName))
212
+	csNotice(rb, fmt.Sprintf(client.t("Successfully op'd in channel %s"), channelName))
120 213
 
121 214
 	server.logger.Info("chanserv", fmt.Sprintf("Client %s op'd [%s] in channel %s", client.nick, clientToOp, channelName))
122 215
 	server.snomasks.Send(sno.LocalChannels, fmt.Sprintf(ircfmt.Unescape("Client $c[grey][$r%s$c[grey]] CS OP'd $c[grey][$r%s$c[grey]] in channel $c[grey][$r%s$c[grey]]"), client.nickMaskString, clientToOp, channelName))
123 216
 }
124 217
 
125
-// chanservRegisterHandler handles the ChanServ REGISTER subcommand.
126
-func (server *Server) chanservRegisterHandler(client *Client, channelName string, rb *ResponseBuffer) {
218
+func csRegisterHandler(server *Server, client *Client, command, params string, rb *ResponseBuffer) {
127 219
 	if !server.channelRegistrationEnabled {
128
-		rb.ChanServNotice(client.t("Channel registration is not enabled"))
220
+		csNotice(rb, client.t("Channel registration is not enabled"))
221
+		return
222
+	}
223
+
224
+	channelName := strings.TrimSpace(params)
225
+	if channelName == "" {
226
+		csNotice(rb, ircfmt.Unescape(client.t("Syntax: $bREGISTER #channel$b")))
129 227
 		return
130 228
 	}
131 229
 
132 230
 	channelKey, err := CasefoldChannel(channelName)
133 231
 	if err != nil {
134
-		rb.ChanServNotice(client.t("Channel name is not valid"))
232
+		csNotice(rb, client.t("Channel name is not valid"))
135 233
 		return
136 234
 	}
137 235
 
138 236
 	channelInfo := server.channels.Get(channelKey)
139 237
 	if channelInfo == nil || !channelInfo.ClientIsAtLeast(client, modes.ChannelOperator) {
140
-		rb.ChanServNotice(client.t("You must be an oper on the channel to register it"))
238
+		csNotice(rb, client.t("You must be an oper on the channel to register it"))
141 239
 		return
142 240
 	}
143 241
 
144 242
 	if client.Account() == "" {
145
-		rb.ChanServNotice(client.t("You must be logged in to register a channel"))
243
+		csNotice(rb, client.t("You must be logged in to register a channel"))
146 244
 		return
147 245
 	}
148 246
 
149 247
 	// this provides the synchronization that allows exactly one registration of the channel:
150 248
 	err = channelInfo.SetRegistered(client.Account())
151 249
 	if err != nil {
152
-		rb.ChanServNotice(err.Error())
250
+		csNotice(rb, err.Error())
153 251
 		return
154 252
 	}
155 253
 
156 254
 	// registration was successful: make the database reflect it
157 255
 	go server.channelRegistry.StoreChannel(channelInfo, true)
158 256
 
159
-	rb.ChanServNotice(fmt.Sprintf(client.t("Channel %s successfully registered"), channelName))
257
+	csNotice(rb, fmt.Sprintf(client.t("Channel %s successfully registered"), channelName))
160 258
 
161 259
 	server.logger.Info("chanserv", fmt.Sprintf("Client %s registered channel %s", client.nick, channelName))
162 260
 	server.snomasks.Send(sno.LocalChannels, fmt.Sprintf(ircfmt.Unescape("Channel registered $c[grey][$r%s$c[grey]] by $c[grey][$r%s$c[grey]]"), channelName, client.nickMaskString))

+ 3
- 1
irc/nickserv.go Целия файл

@@ -120,7 +120,7 @@ or other verification.`,
120 120
 	}
121 121
 )
122 122
 
123
-// send a notice from the NickServ "nick"
123
+// csNotice sends the client a notice from NickServ
124 124
 func nsNotice(rb *ResponseBuffer, text string) {
125 125
 	rb.Add(nil, "NickServ", "NOTICE", rb.target.Nick(), text)
126 126
 }
@@ -167,6 +167,8 @@ func (server *Server) nickservPrivmsgHandler(client *Client, message string, rb
167 167
 		return
168 168
 	}
169 169
 
170
+	server.logger.Debug("nickserv", fmt.Sprintf("Client %s ran command %s", client.Nick(), commandName))
171
+
170 172
 	commandInfo.handler(server, client, commandName, params, rb)
171 173
 }
172 174
 

Loading…
Отказ
Запис