func TestQuietToggleDisplayState(t *testing.T) { var expected, actual []byte s := &MockScreen{} u := message.NewUser(message.SimpleId("foo")) ch := NewRoom() go ch.Serve() defer ch.Close() _, err := ch.Join(u) if err != nil { t.Fatal(err) } // Drain the initial Join message <-ch.broadcast ch.Send(message.ParseInput("/quiet", u)) u.HandleMsg(<-u.ConsumeChan(), s) expected = []byte("-> Quiet mode is toggled ON" + message.Newline) s.Read(&actual) if !reflect.DeepEqual(actual, expected) { t.Errorf("Got: `%s`; Expected: `%s`", actual, expected) } ch.Send(message.ParseInput("/quiet", u)) u.HandleMsg(<-u.ConsumeChan(), s) expected = []byte("-> Quiet mode is toggled OFF" + message.Newline) s.Read(&actual) if !reflect.DeepEqual(actual, expected) { t.Errorf("Got: `%s`; Expected: `%s`", actual, expected) } }
func TestRoomJoin(t *testing.T) { var expected, actual []byte s := &MockScreen{} u := message.NewUser(message.SimpleId("foo")) ch := NewRoom() go ch.Serve() defer ch.Close() _, err := ch.Join(u) if err != nil { t.Fatal(err) } u.HandleMsg(<-u.ConsumeChan(), s) expected = []byte(" * foo joined. (Connected: 1)" + message.Newline) s.Read(&actual) if !reflect.DeepEqual(actual, expected) { t.Errorf("Got: `%s`; Expected: `%s`", actual, expected) } ch.Send(message.NewSystemMsg("hello", u)) u.HandleMsg(<-u.ConsumeChan(), s) expected = []byte("-> hello" + message.Newline) s.Read(&actual) if !reflect.DeepEqual(actual, expected) { t.Errorf("Got: `%s`; Expected: `%s`", actual, expected) } ch.Send(message.ParseInput("/me says hello.", u)) u.HandleMsg(<-u.ConsumeChan(), s) expected = []byte("** foo says hello." + message.Newline) s.Read(&actual) if !reflect.DeepEqual(actual, expected) { t.Errorf("Got: `%s`; Expected: `%s`", actual, expected) } }
// Connect a specific Terminal to this host and its room. func (h *Host) Connect(term *sshd.Terminal) { id := NewIdentity(term.Conn) user := message.NewUserScreen(id, term) user.Config.Theme = &h.theme go func() { // Close term once user is closed. user.Wait() term.Close() }() defer user.Close() // Send MOTD if h.motd != "" { user.Send(message.NewAnnounceMsg(h.motd)) } member, err := h.Join(user) if err != nil { // Try again... id.SetName(fmt.Sprintf("Guest%d", h.count)) member, err = h.Join(user) } if err != nil { logger.Errorf("Failed to join: %s", err) return } // Successfully joined. term.SetPrompt(GetPrompt(user)) term.AutoCompleteCallback = h.AutoCompleteFunction(user) user.SetHighlight(user.Name()) h.count++ // Should the user be op'd on join? member.Op = h.isOp(term.Conn) ratelimit := rateio.NewSimpleLimiter(3, time.Second*3) for { line, err := term.ReadLine() if err == io.EOF { // Closed break } else if err != nil { logger.Errorf("Terminal reading error: %s", err) break } err = ratelimit.Count(1) if err != nil { user.Send(message.NewSystemMsg("Message rejected: Rate limiting is in effect.", user)) continue } if len(line) > maxInputLength { user.Send(message.NewSystemMsg("Message rejected: Input too long.", user)) continue } if line == "" { // Silently ignore empty lines. continue } m := message.ParseInput(line, user) // FIXME: Any reason to use h.room.Send(m) instead? h.HandleMsg(m) cmd := m.Command() if cmd == "/nick" || cmd == "/theme" { // Hijack /nick command to update terminal synchronously. Wouldn't // work if we use h.room.Send(m) above. // // FIXME: This is hacky, how do we improve the API to allow for // this? Chat module shouldn't know about terminals. term.SetPrompt(GetPrompt(user)) user.SetHighlight(user.Name()) } } err = h.Leave(user) if err != nil { logger.Errorf("Failed to leave: %s", err) return } }