mirror of
https://github.com/shazow/ssh-chat.git
synced 2025-06-02 08:31:12 +03:00
Merge pull request #352 from shazow/sponsor-prefix
chat, main: Add /rename op command, optional symbol prefix
This commit is contained in:
commit
32a3860ea2
@ -22,6 +22,7 @@ var ErrUserClosed = errors.New("user closed")
|
|||||||
// User definition, implemented set Item interface and io.Writer
|
// User definition, implemented set Item interface and io.Writer
|
||||||
type User struct {
|
type User struct {
|
||||||
Identifier
|
Identifier
|
||||||
|
OnChange func()
|
||||||
Ignored set.Interface
|
Ignored set.Interface
|
||||||
Focused set.Interface
|
Focused set.Interface
|
||||||
colorIdx int
|
colorIdx int
|
||||||
@ -80,12 +81,20 @@ func (u *User) SetConfig(cfg UserConfig) {
|
|||||||
u.mu.Lock()
|
u.mu.Lock()
|
||||||
u.config = cfg
|
u.config = cfg
|
||||||
u.mu.Unlock()
|
u.mu.Unlock()
|
||||||
|
|
||||||
|
if u.OnChange != nil {
|
||||||
|
u.OnChange()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rename the user with a new Identifier.
|
// Rename the user with a new Identifier.
|
||||||
func (u *User) SetID(id string) {
|
func (u *User) SetID(id string) {
|
||||||
u.Identifier.SetID(id)
|
u.Identifier.SetID(id)
|
||||||
u.setColorIdx(rand.Int())
|
u.setColorIdx(rand.Int())
|
||||||
|
|
||||||
|
if u.OnChange != nil {
|
||||||
|
u.OnChange()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReplyTo returns the last user that messaged this user.
|
// ReplyTo returns the last user that messaged this user.
|
||||||
@ -211,7 +220,7 @@ func (u *User) writeMsg(m Message) error {
|
|||||||
r := u.render(m)
|
r := u.render(m)
|
||||||
_, err := u.screen.Write([]byte(r))
|
_, err := u.screen.Write([]byte(r))
|
||||||
if err != nil {
|
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()
|
u.Close()
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
@ -229,7 +238,7 @@ func (u *User) Send(m Message) error {
|
|||||||
return ErrUserClosed
|
return ErrUserClosed
|
||||||
case u.msg <- m:
|
case u.msg <- m:
|
||||||
case <-time.After(messageTimeout):
|
case <-time.After(messageTimeout):
|
||||||
logger.Printf("Message buffer full, closing: %s", u.Name())
|
logger.Printf("Message buffer full, closing: %s", u.ID())
|
||||||
u.Close()
|
u.Close()
|
||||||
return ErrUserClosed
|
return ErrUserClosed
|
||||||
}
|
}
|
||||||
|
@ -239,7 +239,7 @@ func (r *Room) NamesPrefix(prefix string) []string {
|
|||||||
// Pull out names
|
// Pull out names
|
||||||
names := make([]string, 0, len(items))
|
names := make([]string, 0, len(items))
|
||||||
for _, user := range users {
|
for _, user := range users {
|
||||||
names = append(names, user.Name())
|
names = append(names, user.ID())
|
||||||
}
|
}
|
||||||
return names
|
return names
|
||||||
}
|
}
|
||||||
|
77
host.go
77
host.go
@ -13,6 +13,7 @@ import (
|
|||||||
"github.com/shazow/ssh-chat/chat"
|
"github.com/shazow/ssh-chat/chat"
|
||||||
"github.com/shazow/ssh-chat/chat/message"
|
"github.com/shazow/ssh-chat/chat/message"
|
||||||
"github.com/shazow/ssh-chat/internal/humantime"
|
"github.com/shazow/ssh-chat/internal/humantime"
|
||||||
|
"github.com/shazow/ssh-chat/internal/sanitize"
|
||||||
"github.com/shazow/ssh-chat/sshd"
|
"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) {
|
func (h *Host) Connect(term *sshd.Terminal) {
|
||||||
id := NewIdentity(term.Conn)
|
id := NewIdentity(term.Conn)
|
||||||
user := message.NewUserScreen(id, term)
|
user := message.NewUserScreen(id, term)
|
||||||
|
user.OnChange = func() {
|
||||||
|
term.SetPrompt(GetPrompt(user))
|
||||||
|
user.SetHighlight(user.ID())
|
||||||
|
}
|
||||||
cfg := user.Config()
|
cfg := user.Config()
|
||||||
|
|
||||||
apiMode := strings.ToLower(term.Term()) == "bot"
|
apiMode := strings.ToLower(term.Term()) == "bot"
|
||||||
@ -216,17 +221,6 @@ func (h *Host) Connect(term *sshd.Terminal) {
|
|||||||
// Skip the remaining rendering workarounds
|
// Skip the remaining rendering workarounds
|
||||||
continue
|
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)
|
err = h.Leave(user)
|
||||||
@ -294,7 +288,7 @@ func (h *Host) AutoCompleteFunction(u *message.User) func(line string, pos int,
|
|||||||
if completed == "/reply" {
|
if completed == "/reply" {
|
||||||
replyTo := u.ReplyTo()
|
replyTo := u.ReplyTo()
|
||||||
if replyTo != nil {
|
if replyTo != nil {
|
||||||
name := replyTo.Name()
|
name := replyTo.ID()
|
||||||
_, found := h.GetUser(name)
|
_, found := h.GetUser(name)
|
||||||
if found {
|
if found {
|
||||||
completed = "/msg " + name
|
completed = "/msg " + name
|
||||||
@ -623,4 +617,63 @@ func (h *Host) InitCommands(c *chat.Commands) {
|
|||||||
return nil
|
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")
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
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
|
||||||
|
},
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@ import (
|
|||||||
type Identity struct {
|
type Identity struct {
|
||||||
sshd.Connection
|
sshd.Connection
|
||||||
id string
|
id string
|
||||||
|
symbol string // symbol is displayed as a prefix to the name
|
||||||
created time.Time
|
created time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,8 +44,15 @@ func (i *Identity) SetName(name string) {
|
|||||||
i.SetID(name)
|
i.SetID(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (i *Identity) SetSymbol(symbol string) {
|
||||||
|
i.symbol = symbol
|
||||||
|
}
|
||||||
|
|
||||||
// Name returns the name for the Identity
|
// Name returns the name for the Identity
|
||||||
func (i Identity) Name() string {
|
func (i Identity) Name() string {
|
||||||
|
if i.symbol != "" {
|
||||||
|
return i.symbol + " " + i.id
|
||||||
|
}
|
||||||
return i.id
|
return i.id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user