package main import ( "fmt" "net" "strings" "time" ) type Client struct { server *Server connection net.Conn nick string registered bool connected bool operator bool } func (c *Client) disconnect() { c.connected = false c.connection.Close() } func (c *Client) sendGlobalMessage(motd string) { c.reply(rplMOTDStart) for len(motd) > 80 { c.reply(rplMOTD, motd[:80]) motd = motd[80:] } if len(motd) > 0 { c.reply(rplMOTD, motd) } c.reply(rplEndOfMOTD) } //Send a reply to a user with the code specified func (c *Client) reply(code replyCode, args ...string) { if c.connected == false { return } switch code { case rplWelcome: c.write(fmt.Sprintf(":%s 001 %s :Welcome to %s", c.server.name, c.nick, c.server.name)) case rplJoin: c.write(fmt.Sprintf(":%s JOIN %s", args[0], args[1])) case rplPart: c.write(fmt.Sprintf(":%s PART %s %s", args[0], args[1], args[2])) case rplTopic: c.write(fmt.Sprintf(":%s 332 %s %s :%s", c.server.name, c.nick, args[0], args[1])) case rplNoTopic: c.write(fmt.Sprintf(":%s 331 %s %s :No topic is set", c.server.name, c.nick, args[0])) case rplNames: c.write(fmt.Sprintf(":%s 353 %s = %s :%s", c.server.name, c.nick, args[0], args[1])) case rplEndOfNames: c.write(fmt.Sprintf(":%s 366 %s %s :End of NAMES list", c.server.name, c.nick, args[0])) case rplNickChange: c.write(fmt.Sprintf(":%s NICK %s", args[0], args[1])) case rplKill: c.write(fmt.Sprintf(":%s KILL %s A %s", args[0], c.nick, args[1])) case rplMsg: for _, itm := range strings.Split(args[2], "\n") { c.write(fmt.Sprintf(":%s PRIVMSG %s %s", args[0], args[1], itm)) } case rplList: c.write(fmt.Sprintf(":%s 322 %s %s", c.server.name, c.nick, args[0])) case rplListEnd: c.write(fmt.Sprintf(":%s 323 %s", c.server.name, c.nick)) case rplOper: c.write(fmt.Sprintf(":%s 381 %s :You are now an operator", c.server.name, c.nick)) case rplChannelModeIs: c.write(fmt.Sprintf(":%s 324 %s %s %s %s", c.server.name, c.nick, args[0], args[1], args[2])) case rplKick: c.write(fmt.Sprintf(":%s KICK %s %s %s", args[0], args[1], args[2], args[3])) case rplInfo: c.write(fmt.Sprintf(":%s 371 %s :%s", c.server.name, c.nick, args[0])) case rplVersion: c.write(fmt.Sprintf(":%s 351 %s %s", c.server.name, c.nick, args[0])) case rplMOTDStart: c.write(fmt.Sprintf(":%s 375 %s :- Message of the day - ", c.server.name, c.nick)) case rplMOTD: c.write(fmt.Sprintf(":%s 372 %s :- %s", c.server.name, c.nick, args[0])) case rplEndOfMOTD: c.write(fmt.Sprintf(":%s 376 %s :End of MOTD Command", c.server.name, c.nick)) case rplPong: c.write(fmt.Sprintf(":%s PONG %s %s", c.server.name, c.nick, c.server.name)) case errMoreArgs: c.write(fmt.Sprintf(":%s 461 %s :Not enough params", c.server.name, c.nick)) case errNoNick: c.write(fmt.Sprintf(":%s 431 %s :No nickname given", c.server.name, c.nick)) case errInvalidNick: c.write(fmt.Sprintf(":%s 432 %s %s :Erronenous nickname", c.server.name, c.nick, args[0])) case errNickInUse: c.write(fmt.Sprintf(":%s 433 %s %s :Nick already in use", c.server.name, c.nick, args[0])) case errAlreadyReg: c.write(fmt.Sprintf(":%s 462 :You need a valid nick first", c.server.name)) case errNoSuchNick: c.write(fmt.Sprintf(":%s 401 %s %s :No such nick/channel", c.server.name, c.nick, args[0])) case errUnknownCommand: c.write(fmt.Sprintf(":%s 421 %s %s :Unknown command", c.server.name, c.nick, args[0])) case errNotReg: c.write(fmt.Sprintf(":%s 451 :You have not registered", c.server.name)) case errPassword: c.write(fmt.Sprintf(":%s 464 %s :Error, password incorrect", c.server.name, c.nick)) case errNoPriv: c.write(fmt.Sprintf(":%s 481 %s :Permission denied", c.server.name, c.nick)) case errCannotSend: c.write(fmt.Sprintf(":%s 404 %s %s :Cannot send to channel", c.server.name, c.nick, args[0])) } } func (c *Client) write(output string) { c.connection.SetWriteDeadline(time.Now().Add(time.Second * 30)) if _, err := fmt.Fprintf(c.connection, "%s\r\n", output); err != nil { c.disconnect() return } }