예제 #1
0
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)
	}
}
예제 #2
0
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)
	}
}
예제 #3
0
파일: host.go 프로젝트: dream1986/ssh-chat
// 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
	}
}