Pārlūkot izejas kodu

modes: Fix modes, re-add channel modes

tags/v0.1.0
Daniel Oaks 8 gadus atpakaļ
vecāks
revīzija
e19c1527a4
3 mainītis faili ar 185 papildinājumiem un 160 dzēšanām
  1. 31
    144
      irc/channel.go
  2. 153
    16
      irc/modes.go
  3. 1
    0
      irc/numerics.go

+ 31
- 144
irc/channel.go Parādīt failu

@@ -6,7 +6,6 @@
6 6
 package irc
7 7
 
8 8
 import (
9
-	"fmt"
10 9
 	"log"
11 10
 	"strconv"
12 11
 )
@@ -66,7 +65,7 @@ func (channel *Channel) Names(client *Client) {
66 65
 		}
67 66
 
68 67
 		if len(buffer)+1+len(nick) > maxNamLen {
69
-			client.Send(nil, client.server.nameString, RPL_NAMREPLY, "=", channel.nameString, buffer)
68
+			client.Send(nil, client.server.nameString, RPL_NAMREPLY, client.nickString, "=", channel.nameString, buffer)
70 69
 			buffer = nick
71 70
 			continue
72 71
 		}
@@ -75,8 +74,8 @@ func (channel *Channel) Names(client *Client) {
75 74
 		buffer += nick
76 75
 	}
77 76
 
78
-	client.Send(nil, client.server.nameString, RPL_NAMREPLY, "=", channel.nameString, buffer)
79
-	client.Send(nil, client.server.nameString, RPL_ENDOFNAMES, channel.nameString, "End of NAMES list")
77
+	client.Send(nil, client.server.nameString, RPL_NAMREPLY, client.nickString, "=", channel.nameString, buffer)
78
+	client.Send(nil, client.server.nameString, RPL_ENDOFNAMES, client.nickString, channel.nameString, "End of NAMES list")
80 79
 }
81 80
 
82 81
 func (channel *Channel) ClientIsOperator(client *Client) bool {
@@ -158,7 +157,7 @@ func (channel *Channel) ModeString(client *Client) (str string) {
158 157
 		str += " " + strconv.FormatUint(channel.userLimit, 10)
159 158
 	}
160 159
 
161
-	return
160
+	return str
162 161
 }
163 162
 
164 163
 func (channel *Channel) IsFull() bool {
@@ -199,6 +198,10 @@ func (channel *Channel) Join(client *Client, key string) {
199 198
 		return
200 199
 	}
201 200
 
201
+	for member := range channel.members {
202
+		member.Send(nil, client.nickMaskString, "JOIN", channel.nameString)
203
+	}
204
+
202 205
 	client.channels.Add(channel)
203 206
 	channel.members.Add(client)
204 207
 	if !channel.flags[Persistent] && (len(channel.members) == 1) {
@@ -207,16 +210,8 @@ func (channel *Channel) Join(client *Client, key string) {
207 210
 	}
208 211
 
209 212
 	client.Send(nil, client.nickMaskString, "JOIN", channel.nameString)
210
-	return
211
-	//TODO(dan): should we be continuing here????
212
-	// return was above this originally, is it required?
213
-	/*
214
-		for member := range channel.members {
215
-			member.Reply(reply)
216
-		}
217
-		channel.GetTopic(client)
218
-		channel.Names(client)
219
-	*/
213
+	channel.GetTopic(client)
214
+	channel.Names(client)
220 215
 }
221 216
 
222 217
 func (channel *Channel) Part(client *Client, message string) {
@@ -233,17 +228,17 @@ func (channel *Channel) Part(client *Client, message string) {
233 228
 
234 229
 func (channel *Channel) GetTopic(client *Client) {
235 230
 	if !channel.members.Has(client) {
236
-		client.Send(nil, client.server.nameString, ERR_NOTONCHANNEL, channel.nameString, "You're not on that channel")
231
+		client.Send(nil, client.server.nameString, ERR_NOTONCHANNEL, client.nickString, channel.nameString, "You're not on that channel")
237 232
 		return
238 233
 	}
239 234
 
240 235
 	if channel.topic == "" {
241
-		// clients appear not to expect this
242
-		//replier.Reply(RplNoTopic(channel))
236
+		client.Send(nil, client.server.nameString, RPL_NOTOPIC, client.nickString, channel.nameString, "No topic is set")
243 237
 		return
244 238
 	}
245 239
 
246
-	client.Send(nil, client.server.nameString, RPL_TOPIC, channel.nameString, channel.topic)
240
+	client.Send(nil, client.server.nameString, RPL_TOPIC, client.nickString, channel.nameString, channel.topic)
241
+	//TODO(dan): show topic time and setter here too
247 242
 }
248 243
 
249 244
 func (channel *Channel) SetTopic(client *Client, topic string) {
@@ -322,16 +317,11 @@ func (channel *Channel) applyModeFlag(client *Client, mode ChannelMode,
322 317
 }
323 318
 
324 319
 func (channel *Channel) applyModeMember(client *Client, mode ChannelMode,
325
-	op ModeOp, nick string) bool {
326
-	if !channel.ClientIsOperator(client) {
327
-		client.Send(nil, client.server.nameString, ERR_CHANOPRIVSNEEDED, channel.nameString, "You're not a channel operator")
328
-		return false
329
-	}
330
-
320
+	op ModeOp, nick string) *ChannelModeChange {
331 321
 	if nick == "" {
332 322
 		//TODO(dan): shouldn't this be handled before it reaches this function?
333 323
 		client.Send(nil, client.server.nameString, ERR_NEEDMOREPARAMS, "MODE", "Not enough parameters")
334
-		return false
324
+		return nil
335 325
 	}
336 326
 
337 327
 	target := channel.server.clients.Get(Name(nick))
@@ -339,30 +329,38 @@ func (channel *Channel) applyModeMember(client *Client, mode ChannelMode,
339 329
 		//TODO(dan): investigate using NOSUCHNICK and NOSUCHCHANNEL specifically as that other IRCd (insp?) does,
340 330
 		// since I think that would make sense
341 331
 		client.Send(nil, client.server.nameString, ERR_NOSUCHNICK, nick, "No such nick")
342
-		return false
332
+		return nil
343 333
 	}
344 334
 
345 335
 	if !channel.members.Has(target) {
346 336
 		client.Send(nil, client.server.nameString, ERR_USERNOTINCHANNEL, client.nickString, channel.nameString, "They aren't on that channel")
347
-		return false
337
+		return nil
348 338
 	}
349 339
 
350 340
 	switch op {
351 341
 	case Add:
352 342
 		if channel.members[target][mode] {
353
-			return false
343
+			return nil
354 344
 		}
355 345
 		channel.members[target][mode] = true
356
-		return true
346
+		return &ChannelModeChange{
347
+			op:   Add,
348
+			mode: mode,
349
+			arg:  nick,
350
+		}
357 351
 
358 352
 	case Remove:
359 353
 		if !channel.members[target][mode] {
360
-			return false
354
+			return nil
361 355
 		}
362 356
 		channel.members[target][mode] = false
363
-		return true
357
+		return &ChannelModeChange{
358
+			op:   Remove,
359
+			mode: mode,
360
+			arg:  nick,
361
+		}
364 362
 	}
365
-	return false
363
+	return nil
366 364
 }
367 365
 
368 366
 func (channel *Channel) ShowMaskList(client *Client, mode ChannelMode) {
@@ -404,117 +402,6 @@ func (channel *Channel) applyModeMask(client *Client, mode ChannelMode, op ModeO
404 402
 	return false
405 403
 }
406 404
 
407
-func (channel *Channel) applyMode(client *Client, change *ChannelModeChange) bool {
408
-	switch change.mode {
409
-	case BanMask, ExceptMask, InviteMask:
410
-		return channel.applyModeMask(client, change.mode, change.op,
411
-			NewName(change.arg))
412
-
413
-	case InviteOnly, Moderated, NoOutside, OpOnlyTopic, Persistent, Secret:
414
-		return channel.applyModeFlag(client, change.mode, change.op)
415
-
416
-	case Key:
417
-		if !channel.ClientIsOperator(client) {
418
-			client.Send(nil, client.server.nameString, ERR_CHANOPRIVSNEEDED, channel.nameString, "You're not a channel operator")
419
-			return false
420
-		}
421
-
422
-		switch change.op {
423
-		case Add:
424
-			if change.arg == "" {
425
-				client.Send(nil, client.server.nameString, ERR_NEEDMOREPARAMS, "MODE", "Not enough parameters")
426
-				return false
427
-			}
428
-			key := change.arg
429
-			if key == channel.key {
430
-				return false
431
-			}
432
-
433
-			channel.key = key
434
-			return true
435
-
436
-		case Remove:
437
-			channel.key = ""
438
-			return true
439
-		}
440
-
441
-	case UserLimit:
442
-		limit, err := strconv.ParseUint(change.arg, 10, 64)
443
-		if err != nil {
444
-			client.Send(nil, client.server.nameString, ERR_NEEDMOREPARAMS, "MODE", "Not enough parameters")
445
-			return false
446
-		}
447
-		if (limit == 0) || (limit == channel.userLimit) {
448
-			return false
449
-		}
450
-
451
-		channel.userLimit = limit
452
-		return true
453
-
454
-	case ChannelFounder, ChannelAdmin, ChannelOperator, Halfop, Voice:
455
-		var hasPrivs bool
456
-
457
-		// make sure client has privs to edit the given prefix
458
-		for _, mode := range ChannelPrivModes {
459
-			if channel.members[client][mode] {
460
-				hasPrivs = true
461
-
462
-				// Admins can't give other people Admin or remove it from others,
463
-				// standard for that channel mode, we worry about this later
464
-				if mode == ChannelAdmin && change.mode == ChannelAdmin {
465
-					hasPrivs = false
466
-				}
467
-
468
-				break
469
-			} else if mode == change.mode {
470
-				break
471
-			}
472
-		}
473
-
474
-		name := NewName(change.arg)
475
-
476
-		if !hasPrivs {
477
-			if change.op == Remove && name.ToLower() == client.nick.ToLower() {
478
-				// success!
479
-			} else {
480
-				client.Send(nil, client.server.nameString, ERR_CHANOPRIVSNEEDED, channel.nameString, "You're not a channel operator")
481
-				return false
482
-			}
483
-		}
484
-
485
-		return channel.applyModeMember(client, change.mode, change.op, name.String())
486
-
487
-	default:
488
-		client.Send(nil, client.server.nameString, ERR_UNKNOWNMODE, change.mode.String(), fmt.Sprintf(":is an unknown mode char to me for %s", channel))
489
-	}
490
-	return false
491
-}
492
-
493
-func (channel *Channel) Mode(client *Client, changes ChannelModeChanges) {
494
-	if len(changes) == 0 {
495
-		client.Send(nil, client.server.nameString, RPL_CHANNELMODEIS, channel.nameString, channel.ModeString(client))
496
-		return
497
-	}
498
-
499
-	applied := make(ChannelModeChanges, 0)
500
-	for _, change := range changes {
501
-		if channel.applyMode(client, change) {
502
-			applied = append(applied, change)
503
-		}
504
-	}
505
-
506
-	if len(applied) > 0 {
507
-		appliedString := applied.String()
508
-		for member := range channel.members {
509
-			member.Send(nil, client.nickMaskString, "MODE", channel.nameString, appliedString)
510
-		}
511
-
512
-		if err := channel.Persist(); err != nil {
513
-			log.Println("Channel.Persist:", channel, err)
514
-		}
515
-	}
516
-}
517
-
518 405
 func (channel *Channel) Persist() (err error) {
519 406
 	if channel.flags[Persistent] {
520 407
 		_, err = channel.server.db.Exec(`

+ 153
- 16
irc/modes.go Parādīt failu

@@ -132,9 +132,7 @@ var (
132 132
 func modeHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
133 133
 	name := NewName(msg.Params[0])
134 134
 	if name.IsChannel() {
135
-		// return cmodeHandler(server, client, msg)
136
-		client.Notice("CMODEs are not yet supported!")
137
-		return false
135
+		return cmodeHandler(server, client, msg)
138 136
 	} else {
139 137
 		return umodeHandler(server, client, msg)
140 138
 	}
@@ -164,14 +162,15 @@ func umodeHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
164 162
 
165 163
 	// assemble changes
166 164
 	changes := make(ModeChanges, 0)
165
+	applied := make(ModeChanges, 0)
167 166
 
168 167
 	if len(msg.Params) > 1 {
169
-		modeArg := msg.Params[0]
168
+		modeArg := msg.Params[1]
170 169
 		op := ModeOp(modeArg[0])
171 170
 		if (op == Add) || (op == Remove) {
172 171
 			modeArg = modeArg[1:]
173 172
 		} else {
174
-			client.Send(nil, server.nameString, ERR_UNKNOWNERROR, client.nickString, "MODE", "Mode string could not be parsed correctly")
173
+			client.Send(nil, server.nameString, ERR_UNKNOWNMODE, client.nickString, string(modeArg[1]), "is an unknown mode character to me")
175 174
 			return false
176 175
 		}
177 176
 
@@ -195,14 +194,14 @@ func umodeHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
195 194
 						continue
196 195
 					}
197 196
 					target.flags[change.mode] = true
198
-					changes = append(changes, change)
197
+					applied = append(applied, change)
199 198
 
200 199
 				case Remove:
201 200
 					if !target.flags[change.mode] {
202 201
 						continue
203 202
 					}
204 203
 					delete(target.flags, change.mode)
205
-					changes = append(changes, change)
204
+					applied = append(applied, change)
206 205
 				}
207 206
 
208 207
 			case Operator, LocalOperator:
@@ -211,7 +210,7 @@ func umodeHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
211 210
 						continue
212 211
 					}
213 212
 					delete(target.flags, change.mode)
214
-					changes = append(changes, change)
213
+					applied = append(applied, change)
215 214
 				}
216 215
 			}
217 216
 		}
@@ -225,15 +224,153 @@ func umodeHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
225 224
 	return false
226 225
 }
227 226
 
228
-/*
229
-func (msg *ChannelModeCommand) HandleServer(server *Server) {
230
-	client := msg.Client()
231
-	channel := server.channels.Get(msg.channel)
227
+// MODE <target> [<modestring> [<mode arguments>...]]
228
+func cmodeHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
229
+	channelName := NewName(msg.Params[0])
230
+	channel := server.channels.Get(channelName)
231
+
232 232
 	if channel == nil {
233
-		client.ErrNoSuchChannel(msg.channel)
234
-		return
233
+		client.Send(nil, server.nameString, ERR_NOSUCHCHANNEL, client.nickString, msg.Params[0], "No such channel")
234
+		return false
235 235
 	}
236 236
 
237
-	channel.Mode(client, msg.changes)
237
+	// assemble changes
238
+	//TODO(dan): split out assembling changes into func that returns changes, err
239
+	changes := make(ChannelModeChanges, 0)
240
+	applied := make(ChannelModeChanges, 0)
241
+
242
+	if len(msg.Params) > 1 {
243
+		modeArg := msg.Params[1]
244
+		op := ModeOp(modeArg[0])
245
+		if (op == Add) || (op == Remove) {
246
+			modeArg = modeArg[1:]
247
+		} else {
248
+			client.Send(nil, server.nameString, ERR_UNKNOWNMODE, client.nickString, string(modeArg[1]), "is an unknown mode character to me")
249
+			return false
250
+		}
251
+
252
+		skipArgs := 2
253
+		for _, mode := range modeArg {
254
+			if mode == '-' || mode == '+' {
255
+				op = ModeOp(mode)
256
+				continue
257
+			}
258
+			change := ChannelModeChange{
259
+				mode: ChannelMode(mode),
260
+				op:   op,
261
+			}
262
+
263
+			// put arg into modechange if needed
264
+			switch ChannelMode(mode) {
265
+			case BanMask, ExceptMask, InviteMask:
266
+				if len(msg.Params) > skipArgs {
267
+					change.arg = msg.Params[skipArgs]
268
+					skipArgs += 1
269
+				} else {
270
+					change.op = List
271
+				}
272
+			case Key, UserLimit, ChannelFounder, ChannelAdmin, ChannelOperator, Halfop, Voice:
273
+				if len(msg.Params) > skipArgs {
274
+					change.arg = msg.Params[skipArgs]
275
+					skipArgs += 1
276
+				} else {
277
+					continue
278
+				}
279
+			}
280
+
281
+			applied = append(applied, &change)
282
+		}
283
+
284
+		for _, change := range changes {
285
+			switch change.mode {
286
+			case BanMask, ExceptMask, InviteMask:
287
+				mask := change.arg
288
+				list := channel.lists[change.mode]
289
+				if list == nil {
290
+					// This should never happen, but better safe than panicky.
291
+					client.Send(nil, server.nameString, ERR_UNKNOWNERROR, client.nickString, "MODE", "Could not complete MODE command")
292
+					return false
293
+				}
294
+
295
+				if (change.op == List) || (mask == "") {
296
+					channel.ShowMaskList(client, change.mode)
297
+					continue
298
+				}
299
+
300
+				switch change.op {
301
+				case Add:
302
+					list.Add(Name(mask))
303
+					applied = append(applied, change)
304
+
305
+				case Remove:
306
+					list.Remove(Name(mask))
307
+					applied = append(applied, change)
308
+				}
309
+
310
+			case InviteOnly, Moderated, NoOutside, OpOnlyTopic, Persistent, Secret:
311
+				switch change.op {
312
+				case Add:
313
+					if channel.flags[change.mode] {
314
+						continue
315
+					}
316
+					channel.flags[change.mode] = true
317
+					applied = append(applied, change)
318
+
319
+				case Remove:
320
+					if !channel.flags[change.mode] {
321
+						continue
322
+					}
323
+					delete(channel.flags, change.mode)
324
+					applied = append(applied, change)
325
+				}
326
+
327
+			case ChannelFounder, ChannelAdmin, ChannelOperator, Halfop, Voice:
328
+				// make sure client has privs to edit the given prefix
329
+				var hasPrivs bool
330
+
331
+				for _, mode := range ChannelPrivModes {
332
+					if channel.members[client][mode] {
333
+						hasPrivs = true
334
+
335
+						// Admins can't give other people Admin or remove it from others,
336
+						// standard for that channel mode, we worry about this later
337
+						if mode == ChannelAdmin && change.mode == ChannelAdmin {
338
+							hasPrivs = false
339
+						}
340
+
341
+						break
342
+					} else if mode == change.mode {
343
+						break
344
+					}
345
+				}
346
+
347
+				name := NewName(change.arg)
348
+
349
+				if !hasPrivs {
350
+					if change.op == Remove && name.ToLower() == client.nick.ToLower() {
351
+						// success!
352
+					} else {
353
+						client.Send(nil, client.server.nameString, ERR_CHANOPRIVSNEEDED, channel.nameString, "You're not a channel operator")
354
+						continue
355
+					}
356
+				}
357
+
358
+				change := channel.applyModeMember(client, change.mode, change.op, change.arg)
359
+				if change != nil {
360
+					applied = append(changes, change)
361
+				}
362
+			}
363
+		}
364
+	}
365
+
366
+	if len(applied) > 0 {
367
+		//TODO(dan): we should change the name of String and make it return a slice here
368
+		args := append([]string{channel.nameString}, strings.Split(applied.String(), " ")...)
369
+		client.Send(nil, client.nickMaskString, "MODE", args...)
370
+	} else {
371
+		//TODO(dan): we should just make ModeString return a slice here
372
+		args := append([]string{client.nickString, channel.nameString}, strings.Split(channel.ModeString(client), " ")...)
373
+		client.Send(nil, client.nickMaskString, RPL_CHANNELMODEIS, args...)
374
+	}
375
+	return false
238 376
 }
239
-*/

+ 1
- 0
irc/numerics.go Parādīt failu

@@ -60,6 +60,7 @@ const (
60 60
 	RPL_LISTEND           = "323"
61 61
 	RPL_CHANNELMODEIS     = "324"
62 62
 	RPL_UNIQOPIS          = "325"
63
+	RPL_CREATIONTIME      = "329"
63 64
 	RPL_NOTOPIC           = "331"
64 65
 	RPL_TOPIC             = "332"
65 66
 	RPL_INVITING          = "341"

Notiek ielāde…
Atcelt
Saglabāt