continue work reorganising and redoing EVERYTHING

This commit is contained in:
Daniel Oaks 2016-06-19 10:01:30 +10:00
parent 31c1df55a3
commit 08225c201d
11 changed files with 261 additions and 270 deletions

View File

@ -6,17 +6,8 @@ package irc
import (
"strings"
)
type CapSubCommand string
const (
CAP_LS CapSubCommand = "LS"
CAP_LIST CapSubCommand = "LIST"
CAP_REQ CapSubCommand = "REQ"
CAP_ACK CapSubCommand = "ACK"
CAP_NAK CapSubCommand = "NAK"
CAP_END CapSubCommand = "END"
"github.com/DanielOaks/girc-go/ircmsg"
)
// Capabilities are optional features a client may request from a server.
@ -81,65 +72,56 @@ func (set CapabilitySet) DisableString() string {
return strings.Join(parts, " ")
}
func (msg *CapCommand) HandleRegServer(server *Server) {
client := msg.Client()
// CAP <subcmd> [<caps>]
func capHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
subCommand := strings.ToUpper(msg.Params[0])
capabilities := make(CapabilitySet)
var capString string
switch msg.subCommand {
case CAP_LS:
if len(msg.Params) > 1 {
capString = msg.Params[1]
strs := strings.Split(capString, " ")
for _, str := range strs {
if len(str) > 0 {
capabilities[Capability(str)] = true
}
}
}
switch subCommand {
case "LS":
if !client.registered {
client.capState = CapNegotiating
client.Reply(RplCap(client, CAP_LS, SupportedCapabilities))
}
// client.server needs to be here to workaround a parsing bug in weechat 1.4
// and let it connect to the server (otherwise it doesn't respond to the CAP
// message with anything and just hangs on connection)
client.Send(nil, server.name, "CAP", client.nickString, subCommand, SupportedCapabilities.String())
case CAP_LIST:
client.Reply(RplCap(client, CAP_LIST, client.capabilities))
case "LIST":
client.Send(nil, server.name, "CAP", client.nickString, subCommand, client.capabilities.String())
case CAP_REQ:
for capability := range msg.capabilities {
case "REQ":
// make sure all capabilities actually exist
for capability := range capabilities {
if !SupportedCapabilities[capability] {
client.Reply(RplCap(client, CAP_NAK, msg.capabilities))
return
client.Send(nil, server.name, "CAP", client.nickString, subCommand, capString)
return false
}
}
for capability := range msg.capabilities {
for capability := range capabilities {
client.capabilities[capability] = true
}
client.Reply(RplCap(client, CAP_ACK, msg.capabilities))
client.Send(nil, server.name, "CAP", client.nickString, subCommand, capString)
case CAP_END:
case "END":
if !client.registered {
client.capState = CapNegotiated
server.tryRegister(client)
}
default:
client.ErrInvalidCapCmd(msg.subCommand)
}
}
func (msg *CapCommand) HandleServer(server *Server) {
client := msg.Client()
switch msg.subCommand {
case CAP_LS:
client.Reply(RplCap(client, CAP_LS, SupportedCapabilities))
case CAP_LIST:
client.Reply(RplCap(client, CAP_LIST, client.capabilities))
case CAP_REQ:
for capability := range msg.capabilities {
if !SupportedCapabilities[capability] {
client.Reply(RplCap(client, CAP_NAK, msg.capabilities))
return
}
}
for capability := range msg.capabilities {
client.capabilities[capability] = true
}
client.Reply(RplCap(client, CAP_ACK, msg.capabilities))
case CAP_END:
// no-op after registration performed
return
default:
client.ErrInvalidCapCmd(msg.subCommand)
client.Send(nil, server.name, ERR_INVALIDCAPCMD, client.nickString, subCommand, "Invalid CAP subcommand")
}
return false
}

View File

@ -32,12 +32,14 @@ type Client struct {
hostname Name
idleTimer *time.Timer
nick Name
nickString string // cache for nick string since it's used with every reply
quitTimer *time.Timer
realname Text
registered bool
server *Server
socket *Socket
username Name
isDestroyed bool
}
func NewClient(server *Server, conn net.Conn) *Client {
@ -83,20 +85,26 @@ func (client *Client) run() {
break
}
msg, err = ParseLine(line)
msg, err = ircmsg.ParseLine(line)
if err != nil {
client.Quit("received malformed command")
break
}
isExiting = Run(client.server, client, msg)
cmd, exists := Commands[msg.Command]
if !exists {
//TODO(dan): Reply with 400 or whatever unknown cmd is
client.Quit("Received unknown command")
}
isExiting = cmd.Run(client.server, client, msg)
if isExiting {
break
}
}
// ensure client connection gets closed
client.Destroy()
client.destroy()
}
//
@ -246,8 +254,9 @@ func (client *Client) Reply(reply string) error {
return client.socket.WriteLine(reply)
}
func (client *Client) Quit(message Text) {
client.Send("QUIT", message)
func (client *Client) Quit(message string) {
client.Send(nil, client.nickString, "QUIT", message)
client.Send(nil, client.nickString, "ERROR", message)
}
func (client *Client) destroy() {
@ -277,11 +286,24 @@ func (client *Client) destroy() {
}
client.socket.Close()
if len(friends) > 0 {
reply := RplQuit(client, message)
for friend := range friends {
friend.Reply(reply)
}
for friend := range client.Friends() {
//TODO(dan): store quit message in user, if exists use that instead here
friend.Send(nil, client.nickString, "QUIT", "Exited")
}
}
// Send sends an IRC line to the client.
func (client *Client) Send(tags *map[string]ircmsg.TagValue, prefix string, command string, params ...string) error {
ircmsg := ircmsg.MakeMessage(tags, prefix, command, params...)
line, err := ircmsg.Line()
if err != nil {
return err
}
client.socket.Write(line)
return nil
}
// Notice sends the client a notice from the server.
func (client *Client) Notice(text string) {
client.Send(nil, client.server.name, "NOTICE", client.nickString, text)
}

View File

@ -120,7 +120,7 @@ func (cs *ClientSocket) processIncomingLine(line string) bool {
command, canBeParsed := Commands[msg.Command]
if canBeParsed {
return command.Run(cs, msg)
return command.Run(cs.client.server, &cs.client, msg)
}
//TODO(dan): This is an error+disconnect purely for reasons of testing.
// Later it may be downgraded to not-that-bad.

View File

@ -5,19 +5,7 @@
package irc
import (
"fmt"
"github.com/DanielOaks/girc-go/ircmsg"
)
// NICK <nickname>
func nickHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
// check NICK validity
// send NICK change to primary server thread for processing
// |-> ensure no other client exists with that nickname
return true
}
import "fmt"
type ModeChange struct {
mode UserMode

View File

@ -9,35 +9,26 @@ import "github.com/DanielOaks/girc-go/ircmsg"
// Command represents a command accepted on a listener.
type Command struct {
handler func(client *Client, msg ircmsg.IrcMessage) bool
handler func(server *Server, client *Client, msg ircmsg.IrcMessage) bool
usablePreReg bool
minParams int
}
// Run runs this command with the given listener/message.
func (cmd *Command) Run(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
if !client.Registered && !cmd.usablePreReg {
if !client.registered && !cmd.usablePreReg {
// command silently ignored
return false
}
if len(msg.Params) < cmd.minParams {
listener.Send(nil, "", "461", client.Nick, msg.Command, "Not enough parameters")
client.Send(nil, server.name, ERR_NEEDMOREPARAMS, client.nickString, msg.Command, "Not enough parameters")
return false
}
exiting := cmd.handler(server, client, msg)
// after each command, see if we can send registration to the client
if !client.Registered {
isRegistered := true
for _, fulfilled := range client.regLocks {
if !fulfilled {
isRegistered = false
break
}
}
if isRegistered {
client.DumpRegistration()
}
if !client.registered {
server.tryRegister(client)
}
return exiting
@ -82,10 +73,11 @@ var Commands = map[string]Command{
handler: listHandler,
minParams: 0,
},
/*TODO(dan): ADD THIS BACK.
"MODE": Command{
handler: modeHandler,
minParams: 1,
},
},*/
"MOTD": Command{
handler: motdHandler,
minParams: 0,
@ -103,10 +95,11 @@ var Commands = map[string]Command{
handler: noticeHandler,
minParams: 2,
},
/*TODO(dan): ADD THIS BACK
"ONICK": Command{
handler: onickHandler,
minParams: 2,
},
},*/
"OPER": Command{
handler: operHandler,
minParams: 2,
@ -144,10 +137,11 @@ var Commands = map[string]Command{
usablePreReg: true,
minParams: 0,
},
/*TODO(dan): ADD THIS BACK IN
"THEATRE": Command{
handler: theatreHandler,
minParams: 1,
},
},*/
"TIME": Command{
handler: timeHandler,
minParams: 0,

View File

@ -4,6 +4,7 @@
package irc
import (
"fmt"
"os"
"runtime"
"runtime/debug"
@ -13,9 +14,10 @@ import (
"github.com/DanielOaks/girc-go/ircmsg"
)
// DEBUG GCSTATS/NUMGOROUTINE/etc
func debugHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
if !client.flags[Operator] {
return
return false
}
switch msg.Params[0] {
@ -26,47 +28,48 @@ func debugHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
}
debug.ReadGCStats(&stats)
server.Replyf(client, "last GC: %s", stats.LastGC.Format(time.RFC1123))
server.Replyf(client, "num GC: %d", stats.NumGC)
server.Replyf(client, "pause total: %s", stats.PauseTotal)
server.Replyf(client, "pause quantiles min%%: %s", stats.PauseQuantiles[0])
server.Replyf(client, "pause quantiles 25%%: %s", stats.PauseQuantiles[1])
server.Replyf(client, "pause quantiles 50%%: %s", stats.PauseQuantiles[2])
server.Replyf(client, "pause quantiles 75%%: %s", stats.PauseQuantiles[3])
server.Replyf(client, "pause quantiles max%%: %s", stats.PauseQuantiles[4])
client.Notice(fmt.Sprintf("last GC: %s", stats.LastGC.Format(time.RFC1123)))
client.Notice(fmt.Sprintf("num GC: %d", stats.NumGC))
client.Notice(fmt.Sprintf("pause total: %s", stats.PauseTotal))
client.Notice(fmt.Sprintf("pause quantiles min%%: %s", stats.PauseQuantiles[0]))
client.Notice(fmt.Sprintf("pause quantiles 25%%: %s", stats.PauseQuantiles[1]))
client.Notice(fmt.Sprintf("pause quantiles 50%%: %s", stats.PauseQuantiles[2]))
client.Notice(fmt.Sprintf("pause quantiles 75%%: %s", stats.PauseQuantiles[3]))
client.Notice(fmt.Sprintf("pause quantiles max%%: %s", stats.PauseQuantiles[4]))
case "NUMGOROUTINE":
count := runtime.NumGoroutine()
server.Replyf(client, "num goroutines: %d", count)
client.Notice(fmt.Sprintf("num goroutines: %d", count))
case "PROFILEHEAP":
profFile := "ergonomadic.mprof"
file, err := os.Create(profFile)
if err != nil {
server.Replyf(client, "error: %s", err)
client.Notice(fmt.Sprintf("error: %s", err))
break
}
defer file.Close()
pprof.Lookup("heap").WriteTo(file, 0)
server.Replyf(client, "written to %s", profFile)
client.Notice(fmt.Sprintf("written to %s", profFile))
case "STARTCPUPROFILE":
profFile := "ergonomadic.prof"
file, err := os.Create(profFile)
if err != nil {
server.Replyf(client, "error: %s", err)
client.Notice(fmt.Sprintf("error: %s", err))
break
}
if err := pprof.StartCPUProfile(file); err != nil {
defer file.Close()
server.Replyf(client, "error: %s", err)
client.Notice(fmt.Sprintf("error: %s", err))
break
}
server.Replyf(client, "CPU profile writing to %s", profFile)
client.Notice(fmt.Sprintf("CPU profile writing to %s", profFile))
case "STOPCPUPROFILE":
pprof.StopCPUProfile()
server.Reply(client, "CPU profiling stopped")
client.Notice(fmt.Sprintf("CPU profiling stopped"))
}
return false
}

View File

@ -4,6 +4,17 @@
package irc
import "github.com/DanielOaks/girc-go/ircmsg"
// NICK <nickname>
func nickHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
// check NICK validity
// send NICK change to primary server thread for processing
// |-> ensure no other client exists with that nickname
//TODO(dan): SET client.nickString APPROPRIATELY
return true
}
/*
type NickCommand struct {
BaseCommand
@ -17,6 +28,7 @@ func (m *NickCommand) HandleRegServer(s *Server) {
client.Quit("bad password")
return
}
//TODO(dan): SET client.nickString APPROPRIATELY
if m.nickname == "" {
client.ErrNoNicknameGiven()
@ -39,6 +51,7 @@ func (m *NickCommand) HandleRegServer(s *Server) {
func (msg *NickCommand) HandleServer(server *Server) {
client := msg.Client()
//TODO(dan): SET client.nickString APPROPRIATELY
if msg.nickname == "" {
client.ErrNoNicknameGiven()
@ -71,6 +84,7 @@ type OperNickCommand struct {
func (msg *OperNickCommand) HandleServer(server *Server) {
client := msg.Client()
//TODO(dan): SET client.nickString APPROPRIATELY
if !client.flags[Operator] {
client.ErrNoPrivileges()

View File

@ -6,142 +6,142 @@
package irc
const (
RPL_WELCOME NumericCode = 1
RPL_YOURHOST NumericCode = 2
RPL_CREATED NumericCode = 3
RPL_MYINFO NumericCode = 4
RPL_ISUPPORT NumericCode = 5
RPL_BOUNCE NumericCode = 10
RPL_TRACELINK NumericCode = 200
RPL_TRACECONNECTING NumericCode = 201
RPL_TRACEHANDSHAKE NumericCode = 202
RPL_TRACEUNKNOWN NumericCode = 203
RPL_TRACEOPERATOR NumericCode = 204
RPL_TRACEUSER NumericCode = 205
RPL_TRACESERVER NumericCode = 206
RPL_TRACESERVICE NumericCode = 207
RPL_TRACENEWTYPE NumericCode = 208
RPL_TRACECLASS NumericCode = 209
RPL_TRACERECONNECT NumericCode = 210
RPL_STATSLINKINFO NumericCode = 211
RPL_STATSCOMMANDS NumericCode = 212
RPL_ENDOFSTATS NumericCode = 219
RPL_UMODEIS NumericCode = 221
RPL_SERVLIST NumericCode = 234
RPL_SERVLISTEND NumericCode = 235
RPL_STATSUPTIME NumericCode = 242
RPL_STATSOLINE NumericCode = 243
RPL_LUSERCLIENT NumericCode = 251
RPL_LUSEROP NumericCode = 252
RPL_LUSERUNKNOWN NumericCode = 253
RPL_LUSERCHANNELS NumericCode = 254
RPL_LUSERME NumericCode = 255
RPL_ADMINME NumericCode = 256
RPL_ADMINLOC1 NumericCode = 257
RPL_ADMINLOC2 NumericCode = 258
RPL_ADMINEMAIL NumericCode = 259
RPL_TRACELOG NumericCode = 261
RPL_TRACEEND NumericCode = 262
RPL_TRYAGAIN NumericCode = 263
RPL_AWAY NumericCode = 301
RPL_USERHOST NumericCode = 302
RPL_ISON NumericCode = 303
RPL_UNAWAY NumericCode = 305
RPL_NOWAWAY NumericCode = 306
RPL_WHOISUSER NumericCode = 311
RPL_WHOISSERVER NumericCode = 312
RPL_WHOISOPERATOR NumericCode = 313
RPL_WHOWASUSER NumericCode = 314
RPL_ENDOFWHO NumericCode = 315
RPL_WHOISIDLE NumericCode = 317
RPL_ENDOFWHOIS NumericCode = 318
RPL_WHOISCHANNELS NumericCode = 319
RPL_LIST NumericCode = 322
RPL_LISTEND NumericCode = 323
RPL_CHANNELMODEIS NumericCode = 324
RPL_UNIQOPIS NumericCode = 325
RPL_NOTOPIC NumericCode = 331
RPL_TOPIC NumericCode = 332
RPL_INVITING NumericCode = 341
RPL_SUMMONING NumericCode = 342
RPL_INVITELIST NumericCode = 346
RPL_ENDOFINVITELIST NumericCode = 347
RPL_EXCEPTLIST NumericCode = 348
RPL_ENDOFEXCEPTLIST NumericCode = 349
RPL_VERSION NumericCode = 351
RPL_WHOREPLY NumericCode = 352
RPL_NAMREPLY NumericCode = 353
RPL_LINKS NumericCode = 364
RPL_ENDOFLINKS NumericCode = 365
RPL_ENDOFNAMES NumericCode = 366
RPL_BANLIST NumericCode = 367
RPL_ENDOFBANLIST NumericCode = 368
RPL_ENDOFWHOWAS NumericCode = 369
RPL_INFO NumericCode = 371
RPL_MOTD NumericCode = 372
RPL_ENDOFINFO NumericCode = 374
RPL_MOTDSTART NumericCode = 375
RPL_ENDOFMOTD NumericCode = 376
RPL_YOUREOPER NumericCode = 381
RPL_REHASHING NumericCode = 382
RPL_YOURESERVICE NumericCode = 383
RPL_TIME NumericCode = 391
RPL_USERSSTART NumericCode = 392
RPL_USERS NumericCode = 393
RPL_ENDOFUSERS NumericCode = 394
RPL_NOUSERS NumericCode = 395
ERR_NOSUCHNICK NumericCode = 401
ERR_NOSUCHSERVER NumericCode = 402
ERR_NOSUCHCHANNEL NumericCode = 403
ERR_CANNOTSENDTOCHAN NumericCode = 404
ERR_TOOMANYCHANNELS NumericCode = 405
ERR_WASNOSUCHNICK NumericCode = 406
ERR_TOOMANYTARGETS NumericCode = 407
ERR_NOSUCHSERVICE NumericCode = 408
ERR_NOORIGIN NumericCode = 409
ERR_INVALIDCAPCMD NumericCode = 410
ERR_NORECIPIENT NumericCode = 411
ERR_NOTEXTTOSEND NumericCode = 412
ERR_NOTOPLEVEL NumericCode = 413
ERR_WILDTOPLEVEL NumericCode = 414
ERR_BADMASK NumericCode = 415
ERR_UNKNOWNCOMMAND NumericCode = 421
ERR_NOMOTD NumericCode = 422
ERR_NOADMININFO NumericCode = 423
ERR_FILEERROR NumericCode = 424
ERR_NONICKNAMEGIVEN NumericCode = 431
ERR_ERRONEUSNICKNAME NumericCode = 432
ERR_NICKNAMEINUSE NumericCode = 433
ERR_NICKCOLLISION NumericCode = 436
ERR_UNAVAILRESOURCE NumericCode = 437
ERR_USERNOTINCHANNEL NumericCode = 441
ERR_NOTONCHANNEL NumericCode = 442
ERR_USERONCHANNEL NumericCode = 443
ERR_NOLOGIN NumericCode = 444
ERR_SUMMONDISABLED NumericCode = 445
ERR_USERSDISABLED NumericCode = 446
ERR_NOTREGISTERED NumericCode = 451
ERR_NEEDMOREPARAMS NumericCode = 461
ERR_ALREADYREGISTRED NumericCode = 462
ERR_NOPERMFORHOST NumericCode = 463
ERR_PASSWDMISMATCH NumericCode = 464
ERR_YOUREBANNEDCREEP NumericCode = 465
ERR_YOUWILLBEBANNED NumericCode = 466
ERR_KEYSET NumericCode = 467
ERR_CHANNELISFULL NumericCode = 471
ERR_UNKNOWNMODE NumericCode = 472
ERR_INVITEONLYCHAN NumericCode = 473
ERR_BANNEDFROMCHAN NumericCode = 474
ERR_BADCHANNELKEY NumericCode = 475
ERR_BADCHANMASK NumericCode = 476
ERR_NOCHANMODES NumericCode = 477
ERR_BANLISTFULL NumericCode = 478
ERR_NOPRIVILEGES NumericCode = 481
ERR_CHANOPRIVSNEEDED NumericCode = 482
ERR_CANTKILLSERVER NumericCode = 483
ERR_RESTRICTED NumericCode = 484
ERR_UNIQOPPRIVSNEEDED NumericCode = 485
ERR_NOOPERHOST NumericCode = 491
ERR_UMODEUNKNOWNFLAG NumericCode = 501
ERR_USERSDONTMATCH NumericCode = 502
RPL_WELCOME = "001"
RPL_YOURHOST = "002"
RPL_CREATED = "003"
RPL_MYINFO = "004"
RPL_ISUPPORT = "005"
RPL_BOUNCE = "010"
RPL_TRACELINK = "200"
RPL_TRACECONNECTING = "201"
RPL_TRACEHANDSHAKE = "202"
RPL_TRACEUNKNOWN = "203"
RPL_TRACEOPERATOR = "204"
RPL_TRACEUSER = "205"
RPL_TRACESERVER = "206"
RPL_TRACESERVICE = "207"
RPL_TRACENEWTYPE = "208"
RPL_TRACECLASS = "209"
RPL_TRACERECONNECT = "210"
RPL_STATSLINKINFO = "211"
RPL_STATSCOMMANDS = "212"
RPL_ENDOFSTATS = "219"
RPL_UMODEIS = "221"
RPL_SERVLIST = "234"
RPL_SERVLISTEND = "235"
RPL_STATSUPTIME = "242"
RPL_STATSOLINE = "243"
RPL_LUSERCLIENT = "251"
RPL_LUSEROP = "252"
RPL_LUSERUNKNOWN = "253"
RPL_LUSERCHANNELS = "254"
RPL_LUSERME = "255"
RPL_ADMINME = "256"
RPL_ADMINLOC1 = "257"
RPL_ADMINLOC2 = "258"
RPL_ADMINEMAIL = "259"
RPL_TRACELOG = "261"
RPL_TRACEEND = "262"
RPL_TRYAGAIN = "263"
RPL_AWAY = "301"
RPL_USERHOST = "302"
RPL_ISON = "303"
RPL_UNAWAY = "305"
RPL_NOWAWAY = "306"
RPL_WHOISUSER = "311"
RPL_WHOISSERVER = "312"
RPL_WHOISOPERATOR = "313"
RPL_WHOWASUSER = "314"
RPL_ENDOFWHO = "315"
RPL_WHOISIDLE = "317"
RPL_ENDOFWHOIS = "318"
RPL_WHOISCHANNELS = "319"
RPL_LIST = "322"
RPL_LISTEND = "323"
RPL_CHANNELMODEIS = "324"
RPL_UNIQOPIS = "325"
RPL_NOTOPIC = "331"
RPL_TOPIC = "332"
RPL_INVITING = "341"
RPL_SUMMONING = "342"
RPL_INVITELIST = "346"
RPL_ENDOFINVITELIST = "347"
RPL_EXCEPTLIST = "348"
RPL_ENDOFEXCEPTLIST = "349"
RPL_VERSION = "351"
RPL_WHOREPLY = "352"
RPL_NAMREPLY = "353"
RPL_LINKS = "364"
RPL_ENDOFLINKS = "365"
RPL_ENDOFNAMES = "366"
RPL_BANLIST = "367"
RPL_ENDOFBANLIST = "368"
RPL_ENDOFWHOWAS = "369"
RPL_INFO = "371"
RPL_MOTD = "372"
RPL_ENDOFINFO = "374"
RPL_MOTDSTART = "375"
RPL_ENDOFMOTD = "376"
RPL_YOUREOPER = "381"
RPL_REHASHING = "382"
RPL_YOURESERVICE = "383"
RPL_TIME = "391"
RPL_USERSSTART = "392"
RPL_USERS = "393"
RPL_ENDOFUSERS = "394"
RPL_NOUSERS = "395"
ERR_NOSUCHNICK = "401"
ERR_NOSUCHSERVER = "402"
ERR_NOSUCHCHANNEL = "403"
ERR_CANNOTSENDTOCHAN = "404"
ERR_TOOMANYCHANNELS = "405"
ERR_WASNOSUCHNICK = "406"
ERR_TOOMANYTARGETS = "407"
ERR_NOSUCHSERVICE = "408"
ERR_NOORIGIN = "409"
ERR_INVALIDCAPCMD = "410"
ERR_NORECIPIENT = "411"
ERR_NOTEXTTOSEND = "412"
ERR_NOTOPLEVEL = "413"
ERR_WILDTOPLEVEL = "414"
ERR_BADMASK = "415"
ERR_UNKNOWNCOMMAND = "421"
ERR_NOMOTD = "422"
ERR_NOADMININFO = "423"
ERR_FILEERROR = "424"
ERR_NONICKNAMEGIVEN = "431"
ERR_ERRONEUSNICKNAME = "432"
ERR_NICKNAMEINUSE = "433"
ERR_NICKCOLLISION = "436"
ERR_UNAVAILRESOURCE = "437"
ERR_USERNOTINCHANNEL = "441"
ERR_NOTONCHANNEL = "442"
ERR_USERONCHANNEL = "443"
ERR_NOLOGIN = "444"
ERR_SUMMONDISABLED = "445"
ERR_USERSDISABLED = "446"
ERR_NOTREGISTERED = "451"
ERR_NEEDMOREPARAMS = "461"
ERR_ALREADYREGISTRED = "462"
ERR_NOPERMFORHOST = "463"
ERR_PASSWDMISMATCH = "464"
ERR_YOUREBANNEDCREEP = "465"
ERR_YOUWILLBEBANNED = "466"
ERR_KEYSET = "467"
ERR_CHANNELISFULL = "471"
ERR_UNKNOWNMODE = "472"
ERR_INVITEONLYCHAN = "473"
ERR_BANNEDFROMCHAN = "474"
ERR_BADCHANNELKEY = "475"
ERR_BADCHANMASK = "476"
ERR_NOCHANMODES = "477"
ERR_BANLISTFULL = "478"
ERR_NOPRIVILEGES = "481"
ERR_CHANOPRIVSNEEDED = "482"
ERR_CANTKILLSERVER = "483"
ERR_RESTRICTED = "484"
ERR_UNIQOPPRIVSNEEDED = "485"
ERR_NOOPERHOST = "491"
ERR_UMODEUNKNOWNFLAG = "501"
ERR_USERSDONTMATCH = "502"
)

View File

@ -5,11 +5,7 @@
package irc
import (
"fmt"
"strings"
"time"
)
/*
type ReplyCode interface {
String() string
@ -585,3 +581,4 @@ func (target *Client) ErrInviteOnlyChan(channel *Channel) {
target.NumericReply(ERR_INVITEONLYCHAN,
"%s :Cannot join channel (+i)", channel)
}
*/

View File

@ -31,7 +31,7 @@ type Server struct {
db *sql.DB
idle chan *Client
motdLines []string
name Name
name string
newConns chan net.Conn
operators map[Name][]byte
password []byte
@ -324,6 +324,7 @@ func (s *Server) tryRegister(c *Client) {
(c.capState == CapNegotiating) {
return
}
c.registered = true
c.Send("Intro to the network")
c.Register()
@ -1015,7 +1016,6 @@ func whowasHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
client.Send("send")
}
}
client.RplEndOfWhoWas(nickname)
client.Send("send")
client.Send(nil, server.Name, RPL_ENDOFWHOWAS, nickname, "End of WHOWAS")
}
}

View File

@ -14,17 +14,7 @@ func (c TheaterClient) Nick() Name {
return Name(c)
}
type TheaterSubCommand string
type theaterSubCommand interface {
String() string
}
type TheaterIdentifyCommand struct {
PassCommand
channel Name
}
/*
func (m *TheaterIdentifyCommand) LoadPassword(s *Server) {
m.hash = s.theaters[m.channel]
}
@ -118,3 +108,4 @@ func (m *TheaterActionCommand) HandleServer(s *Server) {
member.Reply(reply)
}
}
*/