|
@@ -66,14 +66,6 @@ func NewServer(config *Config) *Server {
|
66
|
66
|
theaters: config.Theaters(),
|
67
|
67
|
}
|
68
|
68
|
|
69
|
|
- // ensure that there is a minimum number of args specified for every command
|
70
|
|
- for name, _ := range parseCommandFuncs {
|
71
|
|
- _, exists := commandMinimumArgs[name]
|
72
|
|
- if !exists {
|
73
|
|
- log.Fatal("commandMinArgs not found for ", name)
|
74
|
|
- }
|
75
|
|
- }
|
76
|
|
-
|
77
|
69
|
if config.Server.MOTD != "" {
|
78
|
70
|
file, err := os.Open(config.Server.MOTD)
|
79
|
71
|
if err == nil {
|
|
@@ -86,6 +78,9 @@ func NewServer(config *Config) *Server {
|
86
|
78
|
break
|
87
|
79
|
}
|
88
|
80
|
line = strings.TrimRight(line, "\r\n")
|
|
81
|
+ // "- " is the required prefix for MOTD, we just add it here to make
|
|
82
|
+ // bursting it out to clients easier
|
|
83
|
+ line = fmt.Sprintf("- %s", line)
|
89
|
84
|
|
90
|
85
|
server.motdLines = append(server.motdLines, line)
|
91
|
86
|
}
|
|
@@ -160,8 +155,8 @@ func (server *Server) loadChannels() {
|
160
|
155
|
for _, flag := range flags {
|
161
|
156
|
channel.flags[ChannelMode(flag)] = true
|
162
|
157
|
}
|
163
|
|
- channel.key = NewText(key)
|
164
|
|
- channel.topic = NewText(topic)
|
|
158
|
+ channel.key = key
|
|
159
|
+ channel.topic = topic
|
165
|
160
|
channel.userLimit = userLimit
|
166
|
161
|
loadChannelList(channel, banList, BanMask)
|
167
|
162
|
loadChannelList(channel, exceptList, ExceptMask)
|
|
@@ -169,51 +164,10 @@ func (server *Server) loadChannels() {
|
169
|
164
|
}
|
170
|
165
|
}
|
171
|
166
|
|
172
|
|
-func (server *Server) processCommand(cmd Command) {
|
173
|
|
- client := cmd.Client()
|
174
|
|
-
|
175
|
|
- numCmd, ok := cmd.(*NeedMoreParamsCommand)
|
176
|
|
- if ok {
|
177
|
|
- client.ErrNeedMoreParams(numCmd.code)
|
178
|
|
- return
|
179
|
|
- }
|
180
|
|
-
|
181
|
|
- if !client.registered {
|
182
|
|
- regCmd, ok := cmd.(RegServerCommand)
|
183
|
|
- if !ok {
|
184
|
|
- client.Quit("unexpected command")
|
185
|
|
- return
|
186
|
|
- }
|
187
|
|
- regCmd.HandleRegServer(server)
|
188
|
|
- return
|
189
|
|
- }
|
190
|
|
-
|
191
|
|
- srvCmd, ok := cmd.(ServerCommand)
|
192
|
|
- if !ok {
|
193
|
|
- client.ErrUnknownCommand(cmd.Code())
|
194
|
|
- return
|
195
|
|
- }
|
196
|
|
-
|
197
|
|
- switch srvCmd.(type) {
|
198
|
|
- case *PingCommand, *PongCommand:
|
199
|
|
- client.Touch()
|
200
|
|
-
|
201
|
|
- case *QuitCommand:
|
202
|
|
- // no-op
|
203
|
|
-
|
204
|
|
- default:
|
205
|
|
- client.Active()
|
206
|
|
- client.Touch()
|
207
|
|
- }
|
208
|
|
-
|
209
|
|
- srvCmd.HandleServer(server)
|
210
|
|
-}
|
211
|
|
-
|
212
|
167
|
func (server *Server) Shutdown() {
|
213
|
168
|
server.db.Close()
|
214
|
169
|
for _, client := range server.clients.byNick {
|
215
|
|
- client.Send("notice")
|
216
|
|
- client.Reply(RplNotice(server, client, "shutting down"))
|
|
170
|
+ client.Notice("Server is shutting down")
|
217
|
171
|
}
|
218
|
172
|
}
|
219
|
173
|
|
|
@@ -228,8 +182,10 @@ func (server *Server) Run() {
|
228
|
182
|
case conn := <-server.newConns:
|
229
|
183
|
NewClient(server, conn)
|
230
|
184
|
|
|
185
|
+ /*TODO(dan): LOOK AT THIS MORE CLOSELY
|
231
|
186
|
case cmd := <-server.commands:
|
232
|
187
|
server.processCommand(cmd)
|
|
188
|
+ */
|
233
|
189
|
|
234
|
190
|
case client := <-server.idle:
|
235
|
191
|
client.Idle()
|
|
@@ -326,32 +282,31 @@ func (s *Server) tryRegister(c *Client) {
|
326
|
282
|
(c.capState == CapNegotiating) {
|
327
|
283
|
return
|
328
|
284
|
}
|
329
|
|
- c.registered = true
|
330
|
|
-
|
331
|
|
- c.Send("Intro to the network")
|
332
|
285
|
c.Register()
|
333
|
|
- c.RplWelcome()
|
334
|
|
- c.RplYourHost()
|
335
|
|
- c.RplCreated()
|
336
|
|
- c.RplMyInfo()
|
|
286
|
+
|
|
287
|
+ // send welcome text
|
|
288
|
+ //NOTE(dan): we specifically use the NICK here instead of the nickmask
|
|
289
|
+ // see http://modern.ircdocs.horse/#rplwelcome-001 for details on why we avoid using the nickmask
|
|
290
|
+ c.Send(nil, s.nameString, RPL_WELCOME, fmt.Sprintf("Welcome to the Internet Relay Network %s", c.nickString))
|
|
291
|
+ c.Send(nil, s.nameString, RPL_YOURHOST, fmt.Sprintf("Your host is %s, running version %s", s.nameString, SEM_VER))
|
|
292
|
+ c.Send(nil, s.nameString, RPL_CREATED, fmt.Sprintf("This server was created %s", s.ctime.Format(time.RFC1123)))
|
|
293
|
+ //TODO(dan): Look at adding last optional [<channel modes with a parameter>] parameter
|
|
294
|
+ c.Send(nil, s.nameString, RPL_MYINFO, s.nameString, SEM_VER, supportedUserModesString, supportedChannelModesString)
|
337
|
295
|
c.RplISupport()
|
338
|
296
|
s.MOTD(c)
|
339
|
297
|
}
|
340
|
298
|
|
341
|
299
|
func (server *Server) MOTD(client *Client) {
|
342
|
300
|
if len(server.motdLines) < 1 {
|
343
|
|
- c.Send("send")
|
344
|
|
- client.ErrNoMOTD()
|
|
301
|
+ client.Send(nil, server.nameString, ERR_NOMOTD, client.nickString, "MOTD File is missing")
|
345
|
302
|
return
|
346
|
303
|
}
|
347
|
304
|
|
348
|
|
- client.RplMOTDStart()
|
|
305
|
+ client.Send(nil, server.nameString, RPL_MOTDSTART, client.nickString, fmt.Sprintf("- %s Message of the day - ", server.nameString))
|
349
|
306
|
for _, line := range server.motdLines {
|
350
|
|
- c.Send("send")
|
351
|
|
- client.RplMOTD(line)
|
|
307
|
+ client.Send(nil, server.nameString, RPL_MOTD, client.nickString, line)
|
352
|
308
|
}
|
353
|
|
- c.Send("send")
|
354
|
|
- client.RplMOTDEnd()
|
|
309
|
+ client.Send(nil, server.nameString, RPL_ENDOFMOTD, client.nickString, "End of MOTD command")
|
355
|
310
|
}
|
356
|
311
|
|
357
|
312
|
func (s *Server) Id() Name {
|
|
@@ -372,17 +327,14 @@ func (s *Server) Nick() Name {
|
372
|
327
|
|
373
|
328
|
// PASS <password>
|
374
|
329
|
func passHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
|
375
|
|
- if client.Registered {
|
376
|
|
- client.Send("send")
|
377
|
|
- client.ErrAlreadyRegistered()
|
|
330
|
+ if client.registered {
|
|
331
|
+ client.Send(nil, server.nameString, ERR_ALREADYREGISTRED, client.nickString, "You may not reregister")
|
378
|
332
|
return false
|
379
|
333
|
}
|
380
|
334
|
|
381
|
335
|
// check the provided password
|
382
|
|
- logger.Fatal("Implement PASS command")
|
383
|
|
- password := []byte(args[0])
|
|
336
|
+ password := []byte(msg.Params[0])
|
384
|
337
|
if ComparePassword(server.password, password) != nil {
|
385
|
|
- logger.Fatal("SEND BACK REJECTION")
|
386
|
338
|
client.Quit("bad password")
|
387
|
339
|
return true
|
388
|
340
|
}
|
|
@@ -410,14 +362,13 @@ func proxyHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
|
410
|
362
|
|
411
|
363
|
// USER <username> * 0 <realname>
|
412
|
364
|
func userHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
|
413
|
|
- if client.Registered {
|
414
|
|
- client.Send("send")
|
415
|
|
- client.ErrAlreadyRegistered()
|
|
365
|
+ if client.registered {
|
|
366
|
+ client.Send(nil, server.nameString, ERR_ALREADYREGISTRED, client.nickString, "You may not reregister")
|
416
|
367
|
return false
|
417
|
368
|
}
|
418
|
369
|
|
419
|
370
|
if !client.authorized {
|
420
|
|
- client.Quit("bad password")
|
|
371
|
+ client.Quit("Bad password")
|
421
|
372
|
return true
|
422
|
373
|
}
|
423
|
374
|
|
|
@@ -433,16 +384,17 @@ func userHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
|
433
|
384
|
server.clients.Remove(client)
|
434
|
385
|
|
435
|
386
|
if client.username != "" {
|
436
|
|
- client.username = msg.username
|
|
387
|
+ client.username = Name(msg.Params[0])
|
|
388
|
+ client.updateNickMask()
|
437
|
389
|
}
|
438
|
390
|
if client.realname != "" {
|
439
|
|
- client.realname = msg.realname
|
|
391
|
+ client.realname = msg.Params[3]
|
440
|
392
|
}
|
441
|
|
- client.updateNickMask()
|
442
|
393
|
|
443
|
394
|
server.clients.Add(client)
|
444
|
|
-
|
445
|
395
|
server.tryRegister(client)
|
|
396
|
+
|
|
397
|
+ return false
|
446
|
398
|
}
|
447
|
399
|
|
448
|
400
|
// QUIT [<reason>]
|
|
@@ -451,7 +403,7 @@ func quitHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
|
451
|
403
|
if len(msg.Params) > 0 {
|
452
|
404
|
reason += ": " + msg.Params[0]
|
453
|
405
|
}
|
454
|
|
- client.Quit(msg.message)
|
|
406
|
+ client.Quit(reason)
|
455
|
407
|
return true
|
456
|
408
|
}
|
457
|
409
|
|
|
@@ -478,7 +430,7 @@ func joinHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
|
478
|
430
|
// handle JOIN 0
|
479
|
431
|
if msg.Params[0] == "0" {
|
480
|
432
|
for channel := range client.channels {
|
481
|
|
- channel.Part(client, client.Nick().Text())
|
|
433
|
+ channel.Part(client, client.nickString)
|
482
|
434
|
}
|
483
|
435
|
return false
|
484
|
436
|
}
|
|
@@ -490,15 +442,17 @@ func joinHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
|
490
|
442
|
keys = strings.Split(msg.Params[1], ",")
|
491
|
443
|
}
|
492
|
444
|
|
493
|
|
- for i, name := range channels {
|
|
445
|
+ var name Name
|
|
446
|
+ for i, nameString := range channels {
|
|
447
|
+ name = Name(nameString)
|
494
|
448
|
if !name.IsChannel() {
|
495
|
|
- log.Fatal("Implement ErrNoSuchChannel")
|
|
449
|
+ client.Send(nil, server.nameString, ERR_NOSUCHCHANNEL, client.nickString, nameString, "No such channel")
|
496
|
450
|
continue
|
497
|
451
|
}
|
498
|
452
|
|
499
|
|
- channel := s.channels.Get(name)
|
|
453
|
+ channel := server.channels.Get(name)
|
500
|
454
|
if channel == nil {
|
501
|
|
- channel = NewChannel(s, name, true)
|
|
455
|
+ channel = NewChannel(server, name, true)
|
502
|
456
|
}
|
503
|
457
|
|
504
|
458
|
var key string
|
|
@@ -508,34 +462,36 @@ func joinHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
|
508
|
462
|
|
509
|
463
|
channel.Join(client, key)
|
510
|
464
|
}
|
|
465
|
+ return false
|
511
|
466
|
}
|
512
|
467
|
|
513
|
468
|
// PART <channel>{,<channel>} [<reason>]
|
514
|
469
|
func partHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
|
515
|
470
|
channels := strings.Split(msg.Params[0], ",")
|
516
|
|
- var reason string //TODO(dan): should this be the user's nickname instead of empty?
|
|
471
|
+ var reason string //TODO(dan): if this isn't supplied here, make sure the param doesn't exist in the PART message sent to other users
|
517
|
472
|
if len(msg.Params) > 1 {
|
518
|
473
|
reason = msg.Params[1]
|
519
|
474
|
}
|
520
|
475
|
|
521
|
476
|
for _, chname := range channels {
|
522
|
|
- channel := server.channels.Get(chname)
|
|
477
|
+ channel := server.channels.Get(Name(chname))
|
523
|
478
|
|
524
|
479
|
if channel == nil {
|
525
|
|
- log.Fatal("Implement ErrNoSuchChannel")
|
|
480
|
+ client.Send(nil, server.nameString, ERR_NOSUCHCHANNEL, client.nickString, chname, "No such channel")
|
526
|
481
|
continue
|
527
|
482
|
}
|
528
|
483
|
|
529
|
|
- channel.Part(client, m.Message())
|
|
484
|
+ channel.Part(client, reason)
|
530
|
485
|
}
|
|
486
|
+ return false
|
531
|
487
|
}
|
532
|
488
|
|
533
|
489
|
// TOPIC <channel> [<topic>]
|
534
|
490
|
func topicHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
|
535
|
|
- channel := server.channels.Get(msg.Params[0])
|
|
491
|
+ channel := server.channels.Get(Name(msg.Params[0]))
|
536
|
492
|
if channel == nil {
|
537
|
|
- log.Fatal("Implement ErrNoSuchChannel")
|
538
|
|
- return
|
|
493
|
+ client.Send(nil, server.nameString, ERR_NOSUCHCHANNEL, client.nickString, msg.Params[0], "No such channel")
|
|
494
|
+ return false
|
539
|
495
|
}
|
540
|
496
|
|
541
|
497
|
if len(msg.Params) > 1 {
|
|
@@ -543,6 +499,7 @@ func topicHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
|
543
|
499
|
} else {
|
544
|
500
|
channel.GetTopic(client)
|
545
|
501
|
}
|
|
502
|
+ return false
|
546
|
503
|
}
|
547
|
504
|
|
548
|
505
|
// PRIVMSG <target>{,<target>} <message>
|
|
@@ -550,28 +507,30 @@ func privmsgHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool
|
550
|
507
|
targets := strings.Split(msg.Params[0], ",")
|
551
|
508
|
message := msg.Params[1]
|
552
|
509
|
|
553
|
|
- for _, target := range targets {
|
|
510
|
+ var target Name
|
|
511
|
+ for _, targetString := range targets {
|
|
512
|
+ target = Name(targetString)
|
554
|
513
|
if target.IsChannel() {
|
555
|
514
|
channel := server.channels.Get(target)
|
556
|
515
|
if channel == nil {
|
557
|
|
- client.Send("send")
|
558
|
|
- client.ErrNoSuchChannel(target)
|
|
516
|
+ client.Send(nil, server.nameString, ERR_NOSUCHCHANNEL, client.nickString, targetString, "No such channel")
|
559
|
517
|
continue
|
560
|
518
|
}
|
561
|
519
|
channel.PrivMsg(client, message)
|
562
|
520
|
} else {
|
563
|
521
|
user := server.clients.Get(target)
|
564
|
522
|
if user == nil {
|
565
|
|
- client.Send("send")
|
566
|
|
- client.ErrNoSuchNick(target)
|
567
|
|
- return
|
|
523
|
+ client.Send(nil, server.nameString, ERR_NOSUCHNICK, targetString, "No such nick")
|
|
524
|
+ continue
|
568
|
525
|
}
|
569
|
|
- user.Send("content here")
|
|
526
|
+ user.Send(nil, client.nickMaskString, "PRIVMSG", user.nickString, message)
|
570
|
527
|
if user.flags[Away] {
|
571
|
|
- client.Send("target is AWAY")
|
|
528
|
+ //TODO(dan): possibly implement cooldown of away notifications to users
|
|
529
|
+ client.Send(nil, server.nameString, RPL_AWAY, user.nickString, user.awayMessage)
|
572
|
530
|
}
|
573
|
531
|
}
|
574
|
532
|
}
|
|
533
|
+ return false
|
575
|
534
|
}
|
576
|
535
|
|
577
|
536
|
func (client *Client) WhoisChannelsNames(target *Client) []string {
|
|
@@ -591,35 +550,79 @@ func (client *Client) WhoisChannelsNames(target *Client) []string {
|
591
|
550
|
|
592
|
551
|
// WHOIS [ <target> ] <mask> *( "," <mask> )
|
593
|
552
|
func whoisHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
|
594
|
|
- var masks string
|
|
553
|
+ var masksString string
|
595
|
554
|
var target string
|
596
|
555
|
|
597
|
556
|
if len(msg.Params) > 1 {
|
598
|
557
|
target = msg.Params[0]
|
599
|
|
- masks = msg.Params[1]
|
|
558
|
+ masksString = msg.Params[1]
|
600
|
559
|
} else {
|
601
|
|
- masks = msg.Params[0]
|
|
560
|
+ masksString = msg.Params[0]
|
602
|
561
|
}
|
603
|
562
|
|
604
|
|
- // TODO implement target query
|
605
|
|
- for _, mask := range masks {
|
606
|
|
- matches := server.clients.FindAll(mask)
|
607
|
|
- if len(matches) == 0 {
|
608
|
|
- client.ErrNoSuchNick(mask)
|
609
|
|
- client.Send("NOSUCHNICK")
|
610
|
|
- continue
|
|
563
|
+ if client.flags[Operator] {
|
|
564
|
+ masks := strings.Split(masksString, ",")
|
|
565
|
+ for _, mask := range masks {
|
|
566
|
+ matches := server.clients.FindAll(Name(mask))
|
|
567
|
+ if len(matches) == 0 {
|
|
568
|
+ client.Send(nil, client.server.nameString, ERR_NOSUCHNICK, mask, "No such nick")
|
|
569
|
+ continue
|
|
570
|
+ }
|
|
571
|
+ for mclient := range matches {
|
|
572
|
+ mclient.getWhoisOf(client)
|
|
573
|
+ }
|
611
|
574
|
}
|
612
|
|
- for mclient := range matches {
|
613
|
|
- client.RplWhois(mclient)
|
614
|
|
- client.Send("WHOIS")
|
|
575
|
+ } else {
|
|
576
|
+ // specifically treat this as a single lookup rather than splitting as we do above
|
|
577
|
+ // this is by design
|
|
578
|
+ mclient := server.clients.Get(Name(masksString))
|
|
579
|
+ if mclient == nil {
|
|
580
|
+ client.Send(nil, client.server.nameString, ERR_NOSUCHNICK, masksString, "No such nick")
|
|
581
|
+ // fall through, ENDOFWHOIS is always sent
|
|
582
|
+ } else {
|
|
583
|
+ client.getWhoisOf(mclient)
|
615
|
584
|
}
|
616
|
585
|
}
|
|
586
|
+ client.Send(nil, server.nameString, RPL_ENDOFWHOIS, client.nickString, masksString, "End of /WHOIS list")
|
|
587
|
+ return false
|
|
588
|
+}
|
|
589
|
+
|
|
590
|
+func (client *Client) getWhoisOf(target *Client) {
|
|
591
|
+ client.Send(nil, client.server.nameString, RPL_WHOISUSER, client.nickString, target.nickString, target.username.String(), target.hostname.String(), "*", target.realname)
|
|
592
|
+ if target.flags[Operator] {
|
|
593
|
+ client.Send(nil, client.server.nameString, RPL_WHOISOPERATOR, client.nickString, target.nickString, "is an IRC operator")
|
|
594
|
+ }
|
|
595
|
+ client.Send(nil, client.server.nameString, RPL_WHOISIDLE, client.nickString, target.nickString, string(target.IdleSeconds()), string(target.SignonTime()), "seconds idle, signon time")
|
|
596
|
+ for _, line := range client.WhoisChannelsNames(target) {
|
|
597
|
+ client.Send(nil, client.server.nameString, RPL_WHOISCHANNELS, client.nickString, target.nickString, line)
|
|
598
|
+ }
|
|
599
|
+}
|
|
600
|
+
|
|
601
|
+// <channel> <user> <host> <server> <nick> ( "H" / "G" ) ["*"] [ ( "@" / "+" ) ]
|
|
602
|
+// :<hopcount> <real name>
|
|
603
|
+func (target *Client) RplWhoReply(channel *Channel, client *Client) {
|
|
604
|
+ channelName := "*"
|
|
605
|
+ flags := ""
|
|
606
|
+
|
|
607
|
+ if client.flags[Away] {
|
|
608
|
+ flags = "G"
|
|
609
|
+ } else {
|
|
610
|
+ flags = "H"
|
|
611
|
+ }
|
|
612
|
+ if client.flags[Operator] {
|
|
613
|
+ flags += "*"
|
|
614
|
+ }
|
|
615
|
+
|
|
616
|
+ if channel != nil {
|
|
617
|
+ flags += channel.members[client].Prefixes(target.capabilities[MultiPrefix])
|
|
618
|
+ channelName = channel.name.String()
|
|
619
|
+ }
|
|
620
|
+ target.Send(nil, target.server.nameString, RPL_WHOREPLY, target.nickString, channelName, client.username.String(), client.hostname.String(), client.server.nameString, client.nickString, flags, string(client.hops), client.realname)
|
617
|
621
|
}
|
618
|
622
|
|
619
|
623
|
func whoChannel(client *Client, channel *Channel, friends ClientSet) {
|
620
|
624
|
for member := range channel.members {
|
621
|
625
|
if !client.flags[Invisible] || friends[client] {
|
622
|
|
- client.Send("send")
|
623
|
626
|
client.RplWhoReply(channel, member)
|
624
|
627
|
}
|
625
|
628
|
}
|
|
@@ -629,15 +632,15 @@ func whoChannel(client *Client, channel *Channel, friends ClientSet) {
|
629
|
632
|
func whoHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
|
630
|
633
|
friends := client.Friends()
|
631
|
634
|
|
632
|
|
- var mask string
|
|
635
|
+ var mask Name
|
633
|
636
|
if len(msg.Params) > 0 {
|
634
|
|
- mask = NewName(msg.Params[0])
|
|
637
|
+ mask = Name(msg.Params[0])
|
635
|
638
|
}
|
636
|
639
|
|
637
|
640
|
//TODO(dan): is this used and would I put this param in the Modern doc?
|
638
|
641
|
// if not, can we remove it?
|
639
|
642
|
var operatorOnly bool
|
640
|
|
- if len(msg.Params) > 1 && msr.Params[1] == "o" {
|
|
643
|
+ if len(msg.Params) > 1 && msg.Params[1] == "o" {
|
641
|
644
|
operatorOnly = true
|
642
|
645
|
}
|
643
|
646
|
|
|
@@ -647,6 +650,7 @@ func whoHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
|
647
|
650
|
}
|
648
|
651
|
} else if mask.IsChannel() {
|
649
|
652
|
// TODO implement wildcard matching
|
|
653
|
+ //TODO(dan): ^ only for opers
|
650
|
654
|
channel := server.channels.Get(mask)
|
651
|
655
|
if channel != nil {
|
652
|
656
|
whoChannel(client, channel, friends)
|
|
@@ -654,37 +658,35 @@ func whoHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
|
654
|
658
|
} else {
|
655
|
659
|
for mclient := range server.clients.FindAll(mask) {
|
656
|
660
|
client.RplWhoReply(nil, mclient)
|
657
|
|
- client.Send("REPLY")
|
658
|
661
|
}
|
659
|
662
|
}
|
660
|
663
|
|
661
|
|
- client.RplEndOfWho(mask)
|
662
|
|
- client.Send("ENDOFWHO")
|
|
664
|
+ client.Send(nil, server.nameString, RPL_ENDOFWHO, client.nickString, mask.String(), "End of WHO list")
|
|
665
|
+ return false
|
663
|
666
|
}
|
664
|
667
|
|
665
|
668
|
// OPER <name> <password>
|
666
|
669
|
func operHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
|
667
|
|
- name = NewName(msg.Params[0])
|
668
|
|
- hash = server.operators[name]
|
669
|
|
- password = []byte(msg.Params[1])
|
|
670
|
+ name := NewName(msg.Params[0])
|
|
671
|
+ hash := server.operators[name]
|
|
672
|
+ password := []byte(msg.Params[1])
|
670
|
673
|
|
671
|
|
- err = ComparePassword(hash, password)
|
|
674
|
+ err := ComparePassword(hash, password)
|
672
|
675
|
|
673
|
676
|
if (hash == nil) || (err != nil) {
|
674
|
|
- client.ErrPasswdMismatch()
|
675
|
|
- client.Send("PASSWDBAD")
|
|
677
|
+ client.Send(nil, server.nameString, ERR_PASSWDMISMATCH, client.nickString, "Password incorrect")
|
676
|
678
|
return true
|
677
|
679
|
}
|
678
|
680
|
|
679
|
|
- //TODO(dan): Split this into client.makeOper() ??
|
680
|
681
|
client.flags[Operator] = true
|
681
|
|
- client.RplYoureOper()
|
682
|
|
- client.Send("YOUROPER")
|
683
|
|
- client.Reply(RplModeChanges(client, client, ModeChanges{&ModeChange{
|
|
682
|
+ client.Send(nil, server.nameString, RPL_YOUREOPER, client.nickString, "You are not an IRC operator")
|
|
683
|
+ //TODO(dan): Should this be sent automagically as part of setting the flag/mode?
|
|
684
|
+ modech := ModeChanges{&ModeChange{
|
684
|
685
|
mode: Operator,
|
685
|
686
|
op: Add,
|
686
|
|
- }}))
|
687
|
|
- client.Send("OPERMODECHANGE")
|
|
687
|
+ }}
|
|
688
|
+ client.Send(nil, server.nameString, "MODE", client.nickString, client.nickString, modech.String())
|
|
689
|
+ return false
|
688
|
690
|
}
|
689
|
691
|
|
690
|
692
|
// AWAY [<message>]
|
|
@@ -692,8 +694,8 @@ func awayHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
|
692
|
694
|
var isAway bool
|
693
|
695
|
var text string
|
694
|
696
|
if len(msg.Params) > 0 {
|
695
|
|
- isAway = True
|
696
|
|
- text = NewText(msg.Params[0])
|
|
697
|
+ isAway = true
|
|
698
|
+ text = msg.Params[0]
|
697
|
699
|
}
|
698
|
700
|
|
699
|
701
|
if isAway {
|
|
@@ -706,33 +708,33 @@ func awayHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
|
706
|
708
|
var op ModeOp
|
707
|
709
|
if client.flags[Away] {
|
708
|
710
|
op = Add
|
709
|
|
- client.Send("imaway")
|
710
|
|
- client.RplNowAway()
|
|
711
|
+ client.Send(nil, server.nameString, RPL_NOWAWAY, client.nickString, "You have been marked as being away")
|
711
|
712
|
} else {
|
712
|
713
|
op = Remove
|
713
|
|
- client.Send("unaway")
|
714
|
|
- client.RplUnAway()
|
|
714
|
+ client.Send(nil, server.nameString, RPL_UNAWAY, client.nickString, "You are no longer marked as being away")
|
715
|
715
|
}
|
716
|
|
- client.Send("mode changes I guess?")
|
717
|
|
- client.Reply(RplModeChanges(client, client, ModeChanges{&ModeChange{
|
|
716
|
+ //TODO(dan): Should this be sent automagically as part of setting the flag/mode?
|
|
717
|
+ modech := ModeChanges{&ModeChange{
|
718
|
718
|
mode: Away,
|
719
|
719
|
op: op,
|
720
|
|
- }}))
|
|
720
|
+ }}
|
|
721
|
+ client.Send(nil, server.nameString, "MODE", client.nickString, client.nickString, modech.String())
|
|
722
|
+ return false
|
721
|
723
|
}
|
722
|
724
|
|
723
|
725
|
// ISON <nick>{ <nick>}
|
724
|
726
|
func isonHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
|
725
|
|
- var nicks = NewNames(msg.Params)
|
|
727
|
+ var nicks = msg.Params
|
726
|
728
|
|
727
|
729
|
ison := make([]string, 0)
|
728
|
730
|
for _, nick := range nicks {
|
729
|
|
- if iclient := server.clients.Get(nick); iclient != nil {
|
|
731
|
+ if iclient := server.clients.Get(Name(nick)); iclient != nil {
|
730
|
732
|
ison = append(ison, iclient.Nick().String())
|
731
|
733
|
}
|
732
|
734
|
}
|
733
|
735
|
|
734
|
|
- client.Send("ISON")
|
735
|
|
- client.RplIsOn(ison)
|
|
736
|
+ client.Send(nil, server.nameString, RPL_ISON, client.nickString, strings.Join(nicks, " "))
|
|
737
|
+ return false
|
736
|
738
|
}
|
737
|
739
|
|
738
|
740
|
// MOTD [<target>]
|
|
@@ -740,51 +742,50 @@ func motdHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
|
740
|
742
|
//TODO(dan): hook this up when we have multiple servers I guess???
|
741
|
743
|
var target string
|
742
|
744
|
if len(msg.Params) > 0 {
|
743
|
|
- target = NewName(msg.Params[0])
|
|
745
|
+ target = msg.Params[0]
|
744
|
746
|
}
|
745
|
747
|
|
746
|
|
- client.Send("MOTD")
|
747
|
|
- server.MOTD(msg.Client())
|
|
748
|
+ server.MOTD(client)
|
|
749
|
+ return false
|
748
|
750
|
}
|
749
|
751
|
|
750
|
752
|
// NOTICE <target>{,<target>} <message>
|
751
|
753
|
func noticeHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
|
752
|
|
- targetName := NewName(msg.Params[0])
|
753
|
|
- message := NewText(msg.Params[1])
|
|
754
|
+ targets := strings.Split(msg.Params[0], ",")
|
|
755
|
+ message := msg.Params[1]
|
754
|
756
|
|
755
|
|
- if targetName.IsChannel() {
|
756
|
|
- channel := server.channels.Get(targetName)
|
757
|
|
- if channel == nil {
|
758
|
|
- client.Send("ERRNOSUCHCHAN")
|
759
|
|
- client.ErrNoSuchChannel(targetName)
|
760
|
|
- return
|
|
757
|
+ var target Name
|
|
758
|
+ for _, targetString := range targets {
|
|
759
|
+ target = Name(targetString)
|
|
760
|
+ if target.IsChannel() {
|
|
761
|
+ channel := server.channels.Get(target)
|
|
762
|
+ if channel == nil {
|
|
763
|
+ // errors silently ignored with NOTICE as per RFC
|
|
764
|
+ continue
|
|
765
|
+ }
|
|
766
|
+ channel.PrivMsg(client, message)
|
|
767
|
+ } else {
|
|
768
|
+ user := server.clients.Get(target)
|
|
769
|
+ if user == nil {
|
|
770
|
+ // errors silently ignored with NOTICE as per RFC
|
|
771
|
+ continue
|
|
772
|
+ }
|
|
773
|
+ user.Send(nil, client.nickMaskString, "NOTICE", user.nickString, message)
|
761
|
774
|
}
|
762
|
|
-
|
763
|
|
- channel.Notice(client, message)
|
764
|
|
- return
|
765
|
|
- }
|
766
|
|
-
|
767
|
|
- target := server.clients.Get(targetName)
|
768
|
|
- if target == nil {
|
769
|
|
- client.Send("ERRNOSUCHNICK")
|
770
|
|
- client.ErrNoSuchNick(targetName)
|
771
|
|
- return
|
772
|
775
|
}
|
773
|
|
- client.Send("NOTICE")
|
774
|
|
- target.Reply(RplNotice(client, target, message))
|
|
776
|
+ return false
|
775
|
777
|
}
|
776
|
778
|
|
777
|
779
|
// KICK <channel>{,<channel>} <user>{,<user>} [<comment>]
|
778
|
780
|
func kickHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
|
779
|
|
- channels := NewNames(strings.Split(msg.Params[0], ","))
|
780
|
|
- users := NewNames(strings.Split(msg.Params[1], ","))
|
|
781
|
+ channels := strings.Split(msg.Params[0], ",")
|
|
782
|
+ users := strings.Split(msg.Params[1], ",")
|
781
|
783
|
if (len(channels) != len(users)) && (len(users) != 1) {
|
782
|
|
- client.Send("NotEnoughArgs??")
|
|
784
|
+ client.Send(nil, server.nameString, ERR_NEEDMOREPARAMS, client.nickString, "KICK", "Not enough parameters")
|
783
|
785
|
return false
|
784
|
|
- // not needed return nil, NotEnoughArgsError
|
785
|
786
|
}
|
786
|
787
|
|
787
|
|
- kicks := make(map[Name]Name)
|
|
788
|
+ kicks := make(map[string]string)
|
788
|
789
|
for index, channel := range channels {
|
789
|
790
|
if len(users) == 1 {
|
790
|
791
|
kicks[channel] = users[0]
|
|
@@ -798,17 +799,15 @@ func kickHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
|
798
|
799
|
comment = msg.Params[2]
|
799
|
800
|
}
|
800
|
801
|
for chname, nickname := range kicks {
|
801
|
|
- channel := server.channels.Get(chname)
|
|
802
|
+ channel := server.channels.Get(Name(chname))
|
802
|
803
|
if channel == nil {
|
803
|
|
- client.ErrNoSuchChannel(chname)
|
804
|
|
- client.Send("send")
|
|
804
|
+ client.Send(nil, server.nameString, ERR_NOSUCHCHANNEL, client.nickString, chname, "No such channel")
|
805
|
805
|
continue
|
806
|
806
|
}
|
807
|
807
|
|
808
|
|
- target := server.clients.Get(nickname)
|
|
808
|
+ target := server.clients.Get(Name(nickname))
|
809
|
809
|
if target == nil {
|
810
|
|
- client.ErrNoSuchNick(nickname)
|
811
|
|
- client.Send("send")
|
|
810
|
+ client.Send(nil, server.nameString, ERR_NOSUCHNICK, nickname, "No such nick")
|
812
|
811
|
continue
|
813
|
812
|
}
|
814
|
813
|
|
|
@@ -836,29 +835,28 @@ func kickHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
|
836
|
835
|
channel.Kick(client, target, comment)
|
837
|
836
|
}
|
838
|
837
|
} else {
|
839
|
|
- client.ErrChanOPrivIsNeeded(channel)
|
840
|
|
- client.Send("send")
|
|
838
|
+ client.Send(nil, client.server.nameString, ERR_CHANOPRIVSNEEDED, chname, "You're not a channel operator")
|
841
|
839
|
}
|
842
|
840
|
}
|
|
841
|
+ return false
|
843
|
842
|
}
|
844
|
843
|
|
845
|
844
|
// LIST [<channel>{,<channel>} [<server>]]
|
846
|
845
|
func listHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
|
847
|
|
- var channels []Name
|
848
|
|
- if len(args) > 0 {
|
849
|
|
- channels = NewNames(strings.Split(args[0], ","))
|
|
846
|
+ var channels []string
|
|
847
|
+ if len(msg.Params) > 0 {
|
|
848
|
+ channels = strings.Split(msg.Params[0], ",")
|
850
|
849
|
}
|
851
|
|
- var target Name
|
852
|
|
- if len(args) > 1 {
|
853
|
|
- target = NewName(args[1])
|
|
850
|
+ var target string
|
|
851
|
+ if len(msg.Params) > 1 {
|
|
852
|
+ target = msg.Params[1]
|
854
|
853
|
}
|
855
|
854
|
|
856
|
855
|
//TODO(dan): target server when we have multiple servers
|
857
|
856
|
//TODO(dan): we should continue just fine if it's this current server though
|
858
|
857
|
if target != "" {
|
859
|
|
- client.ErrNoSuchServer(msg.target)
|
860
|
|
- client.Send("send")
|
861
|
|
- return
|
|
858
|
+ client.Send(nil, server.nameString, ERR_NOSUCHSERVER, client.nickString, target, "No such server")
|
|
859
|
+ return false
|
862
|
860
|
}
|
863
|
861
|
|
864
|
862
|
if len(channels) == 0 {
|
|
@@ -867,33 +865,46 @@ func listHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
|
867
|
865
|
continue
|
868
|
866
|
}
|
869
|
867
|
client.RplList(channel)
|
870
|
|
- client.Send("send")
|
871
|
868
|
}
|
872
|
869
|
} else {
|
873
|
870
|
for _, chname := range channels {
|
874
|
|
- channel := server.channels.Get(chname)
|
|
871
|
+ channel := server.channels.Get(Name(chname))
|
875
|
872
|
if channel == nil || (!client.flags[Operator] && channel.flags[Secret]) {
|
876
|
|
- client.ErrNoSuchChannel(chname)
|
877
|
|
- client.Send("send")
|
|
873
|
+ client.Send(nil, server.nameString, ERR_NOSUCHCHANNEL, client.nickString, chname, "No such channel")
|
878
|
874
|
continue
|
879
|
875
|
}
|
880
|
876
|
client.RplList(channel)
|
881
|
|
- client.Send("send")
|
882
|
877
|
}
|
883
|
878
|
}
|
884
|
|
- client.RplListEnd(server)
|
885
|
|
- client.Send("send")
|
|
879
|
+ client.Send(nil, server.nameString, RPL_LISTEND, client.nickString, "End of LIST")
|
|
880
|
+ return false
|
|
881
|
+}
|
|
882
|
+
|
|
883
|
+func (target *Client) RplList(channel *Channel) {
|
|
884
|
+ // get the correct number of channel members
|
|
885
|
+ var memberCount int
|
|
886
|
+ if target.flags[Operator] || channel.members.Has(target) {
|
|
887
|
+ memberCount = len(channel.members)
|
|
888
|
+ } else {
|
|
889
|
+ for member := range channel.members {
|
|
890
|
+ if !member.flags[Invisible] {
|
|
891
|
+ memberCount += 1
|
|
892
|
+ }
|
|
893
|
+ }
|
|
894
|
+ }
|
|
895
|
+
|
|
896
|
+ target.Send(nil, target.server.nameString, RPL_LIST, target.nickString, channel.nameString, string(memberCount), channel.topic)
|
886
|
897
|
}
|
887
|
898
|
|
888
|
899
|
// NAMES [<channel>{,<channel>}]
|
889
|
900
|
func namesHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
|
890
|
|
- var channels []Name
|
891
|
|
- if len(args) > 0 {
|
892
|
|
- channels = NewNames(strings.Split(args[0], ","))
|
|
901
|
+ var channels []string
|
|
902
|
+ if len(msg.Params) > 0 {
|
|
903
|
+ channels = strings.Split(msg.Params[0], ",")
|
893
|
904
|
}
|
894
|
|
- var target Name
|
895
|
|
- if len(args) > 1 {
|
896
|
|
- target = NewName(args[1])
|
|
905
|
+ var target string
|
|
906
|
+ if len(msg.Params) > 1 {
|
|
907
|
+ target = msg.Params[1]
|
897
|
908
|
}
|
898
|
909
|
|
899
|
910
|
if len(channels) == 0 {
|
|
@@ -904,121 +915,112 @@ func namesHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
|
904
|
915
|
}
|
905
|
916
|
|
906
|
917
|
for _, chname := range channels {
|
907
|
|
- channel := server.channels.Get(chname)
|
|
918
|
+ channel := server.channels.Get(Name(chname))
|
908
|
919
|
if channel == nil {
|
909
|
|
- client.ErrNoSuchChannel(chname)
|
910
|
|
- client.Send("send")
|
|
920
|
+ client.Send(nil, server.nameString, ERR_NOSUCHCHANNEL, client.nickString, chname, "No such channel")
|
911
|
921
|
continue
|
912
|
922
|
}
|
913
|
923
|
channel.Names(client)
|
914
|
|
- client.Send("send")
|
915
|
924
|
}
|
|
925
|
+ return false
|
916
|
926
|
}
|
917
|
927
|
|
918
|
928
|
// VERSION [<server>]
|
919
|
929
|
func versionHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
|
920
|
|
- var target Name
|
921
|
|
- if len(args) > 0 {
|
922
|
|
- target = NewName(args[0])
|
|
930
|
+ var target string
|
|
931
|
+ if len(msg.Params) > 0 {
|
|
932
|
+ target = msg.Params[0]
|
923
|
933
|
}
|
924
|
|
- if (target != "") && (target != server.name) {
|
925
|
|
- client.ErrNoSuchServer(target)
|
926
|
|
- client.Send("send")
|
927
|
|
- return
|
|
934
|
+ if (target != "") && (Name(target) != server.name) {
|
|
935
|
+ client.Send(nil, server.nameString, ERR_NOSUCHSERVER, client.nickString, target, "No such server")
|
|
936
|
+ return false
|
928
|
937
|
}
|
929
|
938
|
|
930
|
|
- client.RplVersion()
|
931
|
|
- client.Send("send")
|
|
939
|
+ client.Send(nil, server.nameString, RPL_VERSION, client.nickString, SEM_VER, server.nameString)
|
932
|
940
|
client.RplISupport()
|
933
|
|
- client.Send("send")
|
|
941
|
+ return false
|
934
|
942
|
}
|
935
|
943
|
|
936
|
944
|
// INVITE <nickname> <channel>
|
937
|
945
|
func inviteHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
|
938
|
|
- nickname := NewName(msg.Params[0])
|
939
|
|
- channelName := NewName(msg.Params[1])
|
|
946
|
+ nickname := msg.Params[0]
|
|
947
|
+ channelName := msg.Params[1]
|
940
|
948
|
|
941
|
|
- target := server.clients.Get(nickname)
|
|
949
|
+ target := server.clients.Get(Name(nickname))
|
942
|
950
|
if target == nil {
|
943
|
|
- client.ErrNoSuchNick(nickname)
|
944
|
|
- client.Send("send")
|
945
|
|
- return
|
|
951
|
+ client.Send(nil, server.nameString, ERR_NOSUCHNICK, client.nickString, nickname, "No such nick")
|
|
952
|
+ return false
|
946
|
953
|
}
|
947
|
954
|
|
948
|
|
- channel := server.channels.Get(channelName)
|
|
955
|
+ channel := server.channels.Get(Name(channelName))
|
949
|
956
|
if channel == nil {
|
950
|
|
- client.RplInviting(target, channelName)
|
951
|
|
- client.Send("send")
|
952
|
|
- target.Reply(RplInviteMsg(client, target, channelName))
|
953
|
|
- client.Send("send")
|
954
|
|
- return
|
|
957
|
+ client.Send(nil, server.nameString, RPL_INVITING, client.nickString, target.nickString, channelName)
|
|
958
|
+ target.Send(nil, client.nickMaskString, "INVITE", target.nickString, channel.nameString)
|
|
959
|
+ return true
|
955
|
960
|
}
|
956
|
961
|
|
957
|
962
|
channel.Invite(target, client)
|
|
963
|
+ return false
|
958
|
964
|
}
|
959
|
965
|
|
960
|
966
|
// TIME [<server>]
|
961
|
967
|
func timeHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
|
962
|
|
- var target Name
|
|
968
|
+ var target string
|
963
|
969
|
if len(msg.Params) > 0 {
|
964
|
|
- target = NewName(msg.Params[0])
|
|
970
|
+ target = msg.Params[0]
|
965
|
971
|
}
|
966
|
|
- if (target != "") && (target != server.name) {
|
967
|
|
- client.ErrNoSuchServer(target)
|
968
|
|
- client.Send("send")
|
969
|
|
- return
|
|
972
|
+ if (target != "") && (Name(target) != server.name) {
|
|
973
|
+ client.Send(nil, server.nameString, ERR_NOSUCHSERVER, client.nickString, target, "No such server")
|
|
974
|
+ return false
|
970
|
975
|
}
|
971
|
|
- client.RplTime()
|
972
|
|
- client.Send("send")
|
|
976
|
+ client.Send(nil, server.nameString, RPL_TIME, client.nickString, server.nameString, time.Now().Format(time.RFC1123))
|
|
977
|
+ return false
|
973
|
978
|
}
|
974
|
979
|
|
975
|
980
|
// KILL <nickname> <comment>
|
976
|
981
|
func killHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
|
977
|
|
- nickname := NewName(msg.Params[0])
|
978
|
|
- comment := NewText(msg.Params[1])
|
|
982
|
+ nickname := msg.Params[0]
|
|
983
|
+ comment := msg.Params[1]
|
979
|
984
|
|
980
|
985
|
if !client.flags[Operator] {
|
981
|
|
- client.ErrNoPrivileges()
|
982
|
|
- client.Send("send")
|
983
|
|
- return
|
|
986
|
+ client.Send(nil, server.nameString, ERR_NOPRIVILEGES, client.nickString, "Permission Denied - You're not an IRC operator")
|
|
987
|
+ return false
|
984
|
988
|
}
|
985
|
989
|
|
986
|
|
- target := server.clients.Get(nickname)
|
|
990
|
+ target := server.clients.Get(Name(nickname))
|
987
|
991
|
if target == nil {
|
988
|
|
- client.ErrNoSuchNick(nickname)
|
989
|
|
- client.Send("send")
|
990
|
|
- return
|
|
992
|
+ client.Send(nil, client.server.nameString, ERR_NOSUCHNICK, nickname, "No such nick")
|
|
993
|
+ return false
|
991
|
994
|
}
|
992
|
995
|
|
993
|
|
- //TODO(dan): make below format match that from other IRCds
|
994
|
|
- quitMsg := fmt.Sprintf("KILLed by %s: %s", client.Nick(), comment)
|
995
|
|
- target.Quit(NewText(quitMsg))
|
996
|
|
- return true
|
|
996
|
+ quitMsg := fmt.Sprintf("Killed (%s (%s))", client.nickString, comment)
|
|
997
|
+ target.Quit(quitMsg)
|
|
998
|
+ target.destroy()
|
|
999
|
+ return false
|
997
|
1000
|
}
|
998
|
1001
|
|
999
|
1002
|
// WHOWAS <nickname> [<count> [<server>]]
|
1000
|
1003
|
func whowasHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
|
1001
|
|
- nicknames := NewNames(strings.Split(msg.Params[0], ","))
|
|
1004
|
+ nicknames := strings.Split(msg.Params[0], ",")
|
1002
|
1005
|
|
1003
|
|
- var count int
|
|
1006
|
+ var count int64
|
1004
|
1007
|
if len(msg.Params) > 1 {
|
1005
|
1008
|
count, _ = strconv.ParseInt(msg.Params[1], 10, 64)
|
1006
|
1009
|
}
|
1007
|
|
- var target Name
|
|
1010
|
+ var target string
|
1008
|
1011
|
if len(msg.Params) > 2 {
|
1009
|
|
- target = NewName(msg.Params[2])
|
|
1012
|
+ target = msg.Params[2]
|
1010
|
1013
|
}
|
1011
|
1014
|
for _, nickname := range nicknames {
|
1012
|
|
- results := server.whoWas.Find(nickname, msg.count)
|
|
1015
|
+ results := server.whoWas.Find(Name(nickname), count)
|
1013
|
1016
|
if len(results) == 0 {
|
1014
|
|
- client.ErrWasNoSuchNick(nickname)
|
1015
|
|
- client.Send("send")
|
|
1017
|
+ client.Send(nil, server.nameString, ERR_WASNOSUCHNICK, client.nickString, nickname, "There was no such nickname")
|
1016
|
1018
|
} else {
|
1017
|
1019
|
for _, whoWas := range results {
|
1018
|
|
- client.RplWhoWasUser(whoWas)
|
1019
|
|
- client.Send("send")
|
|
1020
|
+ client.Send(nil, server.nameString, RPL_WHOWASUSER, client.nickString, whoWas.nickname.String(), whoWas.username.String(), whoWas.hostname.String(), "*", whoWas.realname)
|
1020
|
1021
|
}
|
1021
|
1022
|
}
|
1022
|
|
- client.Send(nil, server.Name, RPL_ENDOFWHOWAS, nickname, "End of WHOWAS")
|
|
1023
|
+ client.Send(nil, server.nameString, RPL_ENDOFWHOWAS, client.nickString, nickname, "End of WHOWAS")
|
1023
|
1024
|
}
|
|
1025
|
+ return false
|
1024
|
1026
|
}
|