From 36843252b4f059161f36cd9fa54284fb8e39e0c0 Mon Sep 17 00:00:00 2001 From: Andrey Petrov Date: Wed, 24 Jun 2020 12:36:02 -0400 Subject: [PATCH 1/3] chat, main: Add /rename op command --- chat/message/user.go | 10 ++++++++ host.go | 56 +++++++++++++++++++++++++++++++++++--------- 2 files changed, 55 insertions(+), 11 deletions(-) diff --git a/chat/message/user.go b/chat/message/user.go index 0fc8cc1..1d1a4f0 100644 --- a/chat/message/user.go +++ b/chat/message/user.go @@ -23,6 +23,8 @@ var ErrUserClosed = errors.New("user closed") type User struct { Identifier Ignored *set.Set + OnChange func() + colorIdx int joined time.Time msg chan Message @@ -72,12 +74,20 @@ func (u *User) SetConfig(cfg UserConfig) { u.mu.Lock() u.config = cfg u.mu.Unlock() + + if u.OnChange != nil { + u.OnChange() + } } // Rename the user with a new Identifier. func (u *User) SetID(id string) { u.Identifier.SetID(id) u.setColorIdx(rand.Int()) + + if u.OnChange != nil { + u.OnChange() + } } // ReplyTo returns the last user that messaged this user. diff --git a/host.go b/host.go index 8973229..a943ff6 100644 --- a/host.go +++ b/host.go @@ -13,6 +13,7 @@ import ( "github.com/shazow/ssh-chat/chat" "github.com/shazow/ssh-chat/chat/message" "github.com/shazow/ssh-chat/internal/humantime" + "github.com/shazow/ssh-chat/internal/sanitize" "github.com/shazow/ssh-chat/sshd" ) @@ -92,6 +93,10 @@ func (h *Host) isOp(conn sshd.Connection) bool { func (h *Host) Connect(term *sshd.Terminal) { id := NewIdentity(term.Conn) user := message.NewUserScreen(id, term) + user.OnChange = func() { + term.SetPrompt(GetPrompt(user)) + user.SetHighlight(user.Name()) + } cfg := user.Config() apiMode := strings.ToLower(term.Term()) == "bot" @@ -216,17 +221,6 @@ func (h *Host) Connect(term *sshd.Terminal) { // Skip the remaining rendering workarounds continue } - - 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) @@ -619,4 +613,44 @@ func (h *Host) InitCommands(c *chat.Commands) { return nil }, }) + + c.Add(chat.Command{ + Op: true, + Prefix: "/rename", + PrefixHelp: "USER NEW_NAME [SYMBOL]", + Help: "Rename USER to NEW_NAME, add optional SYMBOL prefix", + Handler: func(room *chat.Room, msg message.CommandMsg) error { + if !room.IsOp(msg.From()) { + return errors.New("must be op") + } + + args := msg.Args() + if len(args) < 2 { + return errors.New("must specify user and new name") + } + + member, ok := room.MemberByID(args[0]) + if !ok { + return errors.New("user not found") + } + + oldID := member.ID() + newID := sanitize.Name(args[1]) + if newID == oldID { + return errors.New("new name is the same as the original") + } + + member.SetID(newID) + err := room.Rename(oldID, member) + if err != nil { + member.SetID(oldID) + return err + } + + body := fmt.Sprintf("%s was renamed by %s.", oldID, msg.From().Name()) + room.Send(message.NewAnnounceMsg(body)) + + return nil + }, + }) } From cb0bdc8e0e99cceb65e329bb69b0bec5dc279b4a Mon Sep 17 00:00:00 2001 From: Andrey Petrov Date: Wed, 24 Jun 2020 13:53:14 -0400 Subject: [PATCH 2/3] chat: Use user.ID() instead of user.Name() --- chat/message/user.go | 4 ++-- chat/room.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/chat/message/user.go b/chat/message/user.go index 1d1a4f0..305de10 100644 --- a/chat/message/user.go +++ b/chat/message/user.go @@ -206,7 +206,7 @@ func (u *User) writeMsg(m Message) error { r := u.render(m) _, err := u.screen.Write([]byte(r)) if err != nil { - logger.Printf("Write failed to %s, closing: %s", u.Name(), err) + logger.Printf("Write failed to %s, closing: %s", u.ID(), err) u.Close() } return err @@ -227,7 +227,7 @@ func (u *User) Send(m Message) error { return ErrUserClosed case u.msg <- m: case <-time.After(messageTimeout): - logger.Printf("Message buffer full, closing: %s", u.Name()) + logger.Printf("Message buffer full, closing: %s", u.ID()) u.Close() return ErrUserClosed } diff --git a/chat/room.go b/chat/room.go index 5b34508..b126845 100644 --- a/chat/room.go +++ b/chat/room.go @@ -239,7 +239,7 @@ func (r *Room) NamesPrefix(prefix string) []string { // Pull out names names := make([]string, 0, len(items)) for _, user := range users { - names = append(names, user.Name()) + names = append(names, user.ID()) } return names } From ced5767bbbf10612d3c1b129c5fe6e862fad40c9 Mon Sep 17 00:00:00 2001 From: Andrey Petrov Date: Wed, 24 Jun 2020 13:53:24 -0400 Subject: [PATCH 3/3] main: Add symbol support --- host.go | 23 +++++++++++++++++++++-- identity.go | 8 ++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/host.go b/host.go index a943ff6..96331d8 100644 --- a/host.go +++ b/host.go @@ -95,7 +95,7 @@ func (h *Host) Connect(term *sshd.Terminal) { user := message.NewUserScreen(id, term) user.OnChange = func() { term.SetPrompt(GetPrompt(user)) - user.SetHighlight(user.Name()) + user.SetHighlight(user.ID()) } cfg := user.Config() @@ -283,7 +283,7 @@ func (h *Host) AutoCompleteFunction(u *message.User) func(line string, pos int, if completed == "/reply" { replyTo := u.ReplyTo() if replyTo != nil { - name := replyTo.Name() + name := replyTo.ID() _, found := h.GetUser(name) if found { completed = "/msg " + name @@ -634,10 +634,29 @@ func (h *Host) InitCommands(c *chat.Commands) { return errors.New("user not found") } + symbolSet := false + if len(args) == 3 { + s := args[2] + if id, ok := member.Identifier.(*Identity); ok { + id.SetSymbol(s) + } else { + return errors.New("user does not support setting symbol") + } + + body := fmt.Sprintf("Assigned symbol %q by %s.", s, msg.From().Name()) + room.Send(message.NewSystemMsg(body, member.User)) + symbolSet = true + } + oldID := member.ID() newID := sanitize.Name(args[1]) if newID == oldID { return errors.New("new name is the same as the original") + } else if newID == "" && symbolSet { + if member.User.OnChange != nil { + member.User.OnChange() + } + return nil } member.SetID(newID) diff --git a/identity.go b/identity.go index 0817792..148a6dd 100644 --- a/identity.go +++ b/identity.go @@ -14,6 +14,7 @@ import ( type Identity struct { sshd.Connection id string + symbol string // symbol is displayed as a prefix to the name created time.Time } @@ -41,8 +42,15 @@ func (i *Identity) SetName(name string) { i.SetID(name) } +func (i *Identity) SetSymbol(symbol string) { + i.symbol = symbol +} + // Name returns the name for the Identity func (i Identity) Name() string { + if i.symbol != "" { + return i.symbol + " " + i.id + } return i.id }