diff --git a/command.go b/command.go index 069ed56..96a780e 100644 --- a/command.go +++ b/command.go @@ -29,6 +29,7 @@ const ( CommandBoard = "board" // Print current board state in human-readable form. CommandPong = "pong" // Response to server ping. CommandDisconnect = "disconnect" // Disconnect from server. + CommandMOTD = "motd" // Read (or write) the message of the day. CommandBroadcast = "broadcast" // Send a message to all players. CommandShutdown = "shutdown" // Prevent the creation of new matches. ) diff --git a/pkg/server/server.go b/pkg/server/server.go index 6db2c4e..d71c36d 100644 --- a/pkg/server/server.go +++ b/pkg/server/server.go @@ -76,6 +76,8 @@ type server struct { leaderboardCacheTime [12]time.Time leaderboardCacheLock sync.Mutex + motd string + mailServer string passwordSalt string resetSalt string @@ -413,7 +415,7 @@ func (s *server) handleConnection(conn net.Conn) { commands: commands, Client: newSocketClient(conn, commands, events, s.verbose), } - s.sendHello(c) + s.sendWelcome(c) s.handleClient(c) } @@ -478,13 +480,21 @@ func (s *server) randomUsername() []byte { } } -func (s *server) sendHello(c *serverClient) { +func (s *server) sendWelcome(c *serverClient) { if c.json { return } c.Write(s.welcome) } +func (s *server) sendMOTD(c *serverClient) { + motd := s.motd + if motd == "" { + motd = fmt.Sprintf(gotext.GetD(c.language, "Connect with other players and stay up to date on the latest changes. Visit %s"), "bgammon.org/community") + } + c.sendNotice(motd) +} + func (s *server) gameByClient(c *serverClient) *serverGame { s.gamesLock.RLock() defer s.gamesLock.RUnlock() diff --git a/pkg/server/server_command.go b/pkg/server/server_command.go index 9d040b4..1404bdf 100644 --- a/pkg/server/server_command.go +++ b/pkg/server/server_command.go @@ -12,6 +12,8 @@ import ( "github.com/leonelquinteros/gotext" ) +var clearBytes = []byte("clear") + func (s *server) handleCommands() { var cmd serverCommand COMMANDS: @@ -214,7 +216,7 @@ COMMANDS: } // Send message of the day. - cmd.client.sendNotice(fmt.Sprintf(gotext.GetD(cmd.client.language, "Connect with other players and stay up to date on the latest changes. Visit %s"), "bgammon.org/community")) + s.sendMOTD(cmd.client) // Rejoin match in progress. s.gamesLock.RLock() @@ -245,7 +247,7 @@ COMMANDS: clientGame := s.gameByClient(cmd.client) if clientGame != nil && clientGame.client1 != cmd.client && clientGame.client2 != cmd.client { switch keyword { - case bgammon.CommandHelp, "h", bgammon.CommandJSON, bgammon.CommandList, "ls", bgammon.CommandBoard, "b", bgammon.CommandLeave, "l", bgammon.CommandReplay, bgammon.CommandSet, bgammon.CommandPong, bgammon.CommandDisconnect, bgammon.CommandBroadcast, bgammon.CommandShutdown: + case bgammon.CommandHelp, "h", bgammon.CommandJSON, bgammon.CommandList, "ls", bgammon.CommandBoard, "b", bgammon.CommandLeave, "l", bgammon.CommandReplay, bgammon.CommandSet, bgammon.CommandPong, bgammon.CommandDisconnect, bgammon.CommandMOTD, bgammon.CommandBroadcast, bgammon.CommandShutdown: // These commands are allowed to be used by spectators. default: cmd.client.sendNotice(gotext.GetD(cmd.client.language, "Command ignored: You are spectating this match.")) @@ -1243,6 +1245,22 @@ COMMANDS: clientGame.removeClient(cmd.client) } cmd.client.Terminate("Client disconnected") + case bgammon.CommandMOTD: + if len(params) == 0 { + cmd.client.sendNotice("Message of the day:") + s.sendMOTD(cmd.client) + continue + } else if !cmd.client.Admin() { + cmd.client.sendNotice("Access denied.") + continue + } + + motd := bytes.Join(params, []byte(" ")) + if bytes.Equal(bytes.ToLower(motd), clearBytes) { + motd = nil + } + s.motd = string(motd) + cmd.client.sendNotice("MOTD updated.") case bgammon.CommandBroadcast: if !cmd.client.Admin() { cmd.client.sendNotice("Access denied.")