|
@@ -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(`
|