diff --git a/irc/commands.go b/irc/commands.go index 77224e4b..2716eac9 100644 --- a/irc/commands.go +++ b/irc/commands.go @@ -23,6 +23,7 @@ var ( "ISON": NewIsOnCommand, "JOIN": NewJoinCommand, "MODE": NewModeCommand, + "MOTD": NewMOTDCommand, "NICK": NewNickCommand, "OPER": NewOperCommand, "PART": NewPartCommand, @@ -651,3 +652,16 @@ func NewIsOnCommand(args []string) (editableCommand, error) { nicks: args, }, nil } + +type MOTDCommand struct { + BaseCommand + target string +} + +func NewMOTDCommand(args []string) (editableCommand, error) { + cmd := &MOTDCommand{} + if len(args) > 0 { + cmd.target = args[0] + } + return cmd, nil +} diff --git a/irc/config.go b/irc/config.go index fa5465e6..3e394a04 100644 --- a/irc/config.go +++ b/irc/config.go @@ -6,11 +6,12 @@ import ( ) type Config struct { - Name string - Listeners []ListenerConfig - Password string - Operators []OperatorConfig Debug map[string]bool + Listeners []ListenerConfig + MOTD string + Name string + Operators []OperatorConfig + Password string } type OperatorConfig struct { diff --git a/irc/reply.go b/irc/reply.go index 5b7c5072..3d5992bb 100644 --- a/irc/reply.go +++ b/irc/reply.go @@ -276,6 +276,21 @@ func RplIsOn(server *Server, nicks []string) Reply { ":%s", strings.Join(nicks, " ")) } +func RplMOTDStart(server *Server) Reply { + return NewNumericReply(server, RPL_MOTDSTART, + ":- %s Message of the day - ", server.name) +} + +func RplMOTD(server *Server, line string) Reply { + return NewNumericReply(server, RPL_MOTD, + ":- %s", line) +} + +func RplMOTDEnd(server *Server) Reply { + return NewNumericReply(server, RPL_ENDOFMOTD, + ":End of MOTD command") +} + // // errors (also numeric) // diff --git a/irc/server.go b/irc/server.go index 11b96f5d..c698387c 100644 --- a/irc/server.go +++ b/irc/server.go @@ -1,12 +1,14 @@ package irc import ( + "bufio" "crypto/rand" "crypto/tls" "encoding/binary" "fmt" "log" "net" + "os" "time" ) @@ -14,6 +16,7 @@ type Server struct { channels ChannelNameMap commands chan<- Command ctime time.Time + motdFile string name string operators map[string]string password string @@ -27,6 +30,7 @@ func NewServer(config *Config) *Server { clients: make(ClientNameMap), commands: commands, ctime: time.Now(), + motdFile: config.MOTD, name: config.Name, operators: make(map[string]string), password: config.Password, @@ -152,7 +156,39 @@ func (s *Server) tryRegister(c *Client) { } func (server *Server) MOTD(client *Client) { - client.Reply(ErrNoMOTD(server)) + if server.motdFile == "" { + client.Reply(ErrNoMOTD(server)) + return + } + + file, err := os.Open(server.motdFile) + if err != nil { + client.Reply(ErrNoMOTD(server)) + return + } + defer file.Close() + + client.Reply(RplMOTDStart(server)) + reader := bufio.NewReader(file) + for { + line, err := reader.ReadString('\n') + if err != nil { + break + } + + if len(line) > 80 { + for len(line) > 80 { + client.Reply(RplMOTD(server, line[0:80])) + line = line[80:] + } + if len(line) > 0 { + client.Reply(RplMOTD(server, line)) + } + } else { + client.Reply(RplMOTD(server, line)) + } + } + client.Reply(RplMOTDEnd(server)) } func (s *Server) Id() string { @@ -435,3 +471,7 @@ func (msg *IsOnCommand) HandleServer(server *Server) { client.Reply(RplIsOn(server, ison)) } + +func (msg *MOTDCommand) HandleServer(server *Server) { + server.MOTD(msg.Client()) +}