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
This commit is contained in:
Akshay 2021-03-13 08:34:49 -08:00 committed by Andrey Petrov
parent c8bfc34704
commit 0338cb824d
4 changed files with 71 additions and 7 deletions

View File

@ -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
},
})
}

View File

@ -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()

View File

@ -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
},

View File

@ -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.