diff --git a/irc/capability.go b/irc/capability.go index 89378af1..c837cb48 100644 --- a/irc/capability.go +++ b/irc/capability.go @@ -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 [] +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: - client.capState = CapNegotiating - 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 + 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 } } - for capability := range msg.capabilities { - client.capabilities[capability] = true - } - client.Reply(RplCap(client, CAP_ACK, msg.capabilities)) - - case CAP_END: - client.capState = CapNegotiated - server.tryRegister(client) - - default: - client.ErrInvalidCapCmd(msg.subCommand) } -} -func (msg *CapCommand) HandleServer(server *Server) { - client := msg.Client() + switch subCommand { + case "LS": + if !client.registered { + client.capState = CapNegotiating + } + // 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()) - switch msg.subCommand { - case CAP_LS: - client.Reply(RplCap(client, CAP_LS, SupportedCapabilities)) + case "LIST": + client.Send(nil, server.name, "CAP", client.nickString, subCommand, client.capabilities.String()) - case CAP_LIST: - client.Reply(RplCap(client, CAP_LIST, client.capabilities)) - - 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: - // no-op after registration performed - return + case "END": + if !client.registered { + client.capState = CapNegotiated + server.tryRegister(client) + } default: - client.ErrInvalidCapCmd(msg.subCommand) + client.Send(nil, server.name, ERR_INVALIDCAPCMD, client.nickString, subCommand, "Invalid CAP subcommand") } + return false } diff --git a/irc/client.go b/irc/client.go index c872f5f0..08bd5b6c 100644 --- a/irc/client.go +++ b/irc/client.go @@ -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) +} diff --git a/irc/clientsocket.go b/irc/clientsocket.go index 49e95a68..4ec3cff2 100644 --- a/irc/clientsocket.go +++ b/irc/clientsocket.go @@ -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. diff --git a/irc/commandhandlers.go b/irc/commandhandlers.go index 948f482d..e8f8fb13 100644 --- a/irc/commandhandlers.go +++ b/irc/commandhandlers.go @@ -5,19 +5,7 @@ package irc -import ( - "fmt" - - "github.com/DanielOaks/girc-go/ircmsg" -) - -// NICK -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 diff --git a/irc/commands.go b/irc/commands.go index a7cec543..5f427594 100644 --- a/irc/commands.go +++ b/irc/commands.go @@ -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, diff --git a/irc/debug.go b/irc/debug.go index 7903ef8a..1ab22e7e 100644 --- a/irc/debug.go +++ b/irc/debug.go @@ -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 } diff --git a/irc/nickname.go b/irc/nickname.go index 85f43eaf..44a932dd 100644 --- a/irc/nickname.go +++ b/irc/nickname.go @@ -4,6 +4,17 @@ package irc +import "github.com/DanielOaks/girc-go/ircmsg" + +// NICK +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() diff --git a/irc/numerics.go b/irc/numerics.go index 7bbdff6c..1fca0632 100644 --- a/irc/numerics.go +++ b/irc/numerics.go @@ -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" ) diff --git a/irc/reply.go b/irc/reply.go index 061f0625..88bc161e 100644 --- a/irc/reply.go +++ b/irc/reply.go @@ -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) } +*/ diff --git a/irc/server.go b/irc/server.go index bf0cf100..5dc4f046 100644 --- a/irc/server.go +++ b/irc/server.go @@ -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") } } diff --git a/irc/theater.go b/irc/theater.go index e3a06860..59091ac2 100644 --- a/irc/theater.go +++ b/irc/theater.go @@ -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) } } +*/