From 0338cb824d6537d20affa49b145237cf31d84c53 Mon Sep 17 00:00:00 2001 From: Akshay Date: Sat, 13 Mar 2021 08:34:49 -0800 Subject: [PATCH] chat: Added support for user away status, fixes #377 made away toggle status, like irc updated /away feature * added away message * added broadcast away message as emote * updated names list to show away users on the same line, with colors added /away -> back message Update away time to be time since marked away reverted changes made for /list --- chat/command.go | 26 ++++++++++++++++++++++++++ chat/message/user.go | 34 ++++++++++++++++++++++++++++++++-- host.go | 4 ++-- identity.go | 14 +++++++++++--- 4 files changed, 71 insertions(+), 7 deletions(-) diff --git a/chat/command.go b/chat/command.go index db88011..5f84dad 100644 --- a/chat/command.go +++ b/chat/command.go @@ -458,4 +458,30 @@ func InitCommands(c *Commands) { return nil }, }) + + c.Add(Command{ + Prefix: "/away", + PrefixHelp: "[AWAY MESSAGE]", + Handler: func(room *Room, msg message.CommandMsg) error { + awayMsg := strings.TrimSpace(strings.TrimLeft(msg.Body(), "/away")) + isAway, _, _ := msg.From().GetAway() + if awayMsg == "" { + if isAway { + msg.From().SetActive() + room.Send(message.NewSystemMsg("You are marked as active, welcome back!", msg.From())) + room.Send(message.NewEmoteMsg("is back", msg.From())) + return nil + } + + room.Send(message.NewSystemMsg("Not away. Add an away message to set away.", msg.From())) + return nil + } + + msg.From().SetAway(awayMsg) + room.Send(message.NewSystemMsg("You are marked as away, enjoy your excursion!", msg.From())) + + room.Send(message.NewEmoteMsg("has gone away: "+awayMsg, msg.From())) + return nil + }, + }) } diff --git a/chat/message/user.go b/chat/message/user.go index d2ffb80..d00fdb1 100644 --- a/chat/message/user.go +++ b/chat/message/user.go @@ -35,8 +35,11 @@ type User struct { mu sync.Mutex config UserConfig - replyTo *User // Set when user gets a /msg, for replying. - lastMsg time.Time // When the last message was rendered + replyTo *User // Set when user gets a /msg, for replying. + + lastMsg time.Time // When the last message was rendered + awayStatus string // user's away status + awaySince time.Time } func NewUser(identity Identifier) *User { @@ -71,6 +74,33 @@ func (u *User) LastMsg() time.Time { return u.lastMsg } +// SetAway sets the users availablity state +func (u *User) SetAway(msg string) { + u.mu.Lock() + defer u.mu.Unlock() + u.awayStatus = msg + if msg != "" { + u.awaySince = time.Now() + } +} + +// SetActive sets the users as active +func (u *User) SetActive() { + u.mu.Lock() + defer u.mu.Unlock() + u.awayStatus = "" +} + +// GetAway returns if the user is away, when they went away and if they set a message +func (u *User) GetAway() (bool, time.Time, string) { + u.mu.Lock() + defer u.mu.Unlock() + if u.awayStatus == "" { + return false, time.Time{}, "" + } + return true, u.awaySince, u.awayStatus +} + func (u *User) Config() UserConfig { u.mu.Lock() defer u.mu.Unlock() diff --git a/host.go b/host.go index 2ec576e..da03ed3 100644 --- a/host.go +++ b/host.go @@ -415,7 +415,7 @@ func (h *Host) InitCommands(c *chat.Commands) { case true: whois = id.WhoisAdmin(room) case false: - whois = id.Whois() + whois = id.Whois(room) } room.Send(message.NewSystemMsg(whois, msg.From())) @@ -508,7 +508,7 @@ func (h *Host) InitCommands(c *chat.Commands) { room.Send(message.NewAnnounceMsg(body)) target.Close() - logger.Debugf("Banned: \n-> %s", id.Whois()) + logger.Debugf("Banned: \n-> %s", id.Whois(room)) return nil }, diff --git a/identity.go b/identity.go index 7b3277f..8dd02ea 100644 --- a/identity.go +++ b/identity.go @@ -1,6 +1,7 @@ package sshchat import ( + "fmt" "net" "strings" "time" @@ -57,16 +58,23 @@ func (i Identity) Name() string { } // Whois returns a whois description for non-admin users. -// TODO: Add optional room context? -func (i Identity) Whois() string { +func (i Identity) Whois(room *chat.Room) string { fingerprint := "(no public key)" if i.PublicKey() != nil { fingerprint = sshd.Fingerprint(i.PublicKey()) } + awayMsg := "" + if m, ok := room.MemberByID(i.ID()); ok { + isAway, awaySince, awayMessage := m.GetAway() + if isAway { + awayMsg = fmt.Sprintf("%s > away since: (%s) %s", message.Newline, humantime.Since(awaySince), awayMessage) + } + } return "name: " + i.Name() + message.Newline + " > fingerprint: " + fingerprint + message.Newline + " > client: " + sanitize.Data(string(i.ClientVersion()), 64) + message.Newline + - " > joined: " + humantime.Since(i.created) + " ago" + " > joined: " + humantime.Since(i.created) + " ago" + + awayMsg } // WhoisAdmin returns a whois description for admin users.