Merge pull request #1597 from slingamn/away_session.1

fix #1531
This commit is contained in:
Shivaram Lingamneni 2021-03-18 03:28:03 -04:00 committed by GitHub
commit cd43fae478
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 60 additions and 37 deletions

View File

@ -621,10 +621,6 @@ In this section, we give an overview of the modes Oragono supports.
These are the modes which can be set on you when you're connected.
### +a - Away
If this mode is set, you're marked as being away. This mode is set with the /AWAY command.
### +i - Invisible
If this mode is set, you're marked as 'invisible'. This means that your channels won't be shown when users `/WHOIS` you (except for IRC operators, they can see all the channels you're in).

View File

@ -78,8 +78,6 @@ type Client struct {
accountName string // display name of the account: uncasefolded, '*' if not logged in
accountRegDate time.Time
accountSettings AccountSettings
away bool
autoAway bool
awayMessage string
brbTimer BrbTimer
channels ChannelSet
@ -177,6 +175,9 @@ type Session struct {
quitMessage string
awayMessage string
awayAt time.Time
capabilities caps.Set
capState caps.State
capVersion caps.Version
@ -486,9 +487,7 @@ func (server *Server) AddAlwaysOnClient(account ClientAccount, channelToStatus m
}
if persistenceEnabled(config.Accounts.Multiclient.AutoAway, client.accountSettings.AutoAway) {
client.autoAway = true
client.away = true
client.awayMessage = client.t("User is currently disconnected")
client.setAutoAwayNoMutex(config)
}
}
@ -675,7 +674,7 @@ func (client *Client) run(session *Session) {
session.playResume()
session.resumeDetails = nil
client.brbTimer.Disable()
client.SetAway(false, "") // clear BRB message if any
session.SetAway("") // clear BRB message if any
} else {
client.playReattachMessages(session)
}
@ -1459,15 +1458,13 @@ func (client *Client) destroy(session *Session) {
client.dirtyBits |= IncludeLastSeen
}
autoAway := false
becameAutoAway := false
var awayMessage string
if alwaysOn && !client.away && remainingSessions == 0 &&
persistenceEnabled(config.Accounts.Multiclient.AutoAway, client.accountSettings.AutoAway) {
autoAway = true
client.autoAway = true
client.away = true
awayMessage = config.languageManager.Translate(client.languages, `User is currently disconnected`)
client.awayMessage = awayMessage
if alwaysOn && persistenceEnabled(config.Accounts.Multiclient.AutoAway, client.accountSettings.AutoAway) {
wasAway := client.awayMessage != ""
client.setAutoAwayNoMutex(config)
awayMessage = client.awayMessage
becameAutoAway = !wasAway && awayMessage != ""
}
if client.registrationTimer != nil {
@ -1524,7 +1521,7 @@ func (client *Client) destroy(session *Session) {
client.server.stats.Remove(registered, invisible, operator)
}
if autoAway {
if becameAutoAway {
dispatchAwayNotify(client, true, awayMessage)
}

View File

@ -107,6 +107,7 @@ func (client *Client) AllSessionData(currentSession *Session, hasPrivs bool) (da
}
func (client *Client) AddSession(session *Session) (success bool, numSessions int, lastSeen time.Time, back bool) {
config := client.server.Config()
client.stateMutex.Lock()
defer client.stateMutex.Unlock()
@ -126,11 +127,12 @@ func (client *Client) AddSession(session *Session) (success bool, numSessions in
client.setLastSeen(time.Now().UTC(), session.deviceID)
}
client.sessions = newSessions
if client.autoAway {
back = true
client.autoAway = false
client.away = false
// TODO(#1551) there should be a cap to opt out of this behavior on a session
if persistenceEnabled(config.Accounts.Multiclient.AutoAway, client.accountSettings.AutoAway) {
client.awayMessage = ""
if len(client.sessions) == 1 {
back = true
}
}
return true, len(client.sessions), lastSeen, back
}
@ -196,20 +198,54 @@ func (client *Client) Hostname() string {
func (client *Client) Away() (result bool, message string) {
client.stateMutex.Lock()
result, message = client.away, client.awayMessage
message = client.awayMessage
client.stateMutex.Unlock()
result = client.awayMessage != ""
return
}
func (client *Client) SetAway(away bool, awayMessage string) (changed bool) {
func (session *Session) SetAway(awayMessage string) {
client := session.client
config := client.server.Config()
client.stateMutex.Lock()
changed = away != client.away
client.away = away
client.awayMessage = awayMessage
client.stateMutex.Unlock()
defer client.stateMutex.Unlock()
session.awayMessage = awayMessage
session.awayAt = time.Now().UTC()
autoAway := client.registered && client.alwaysOn && persistenceEnabled(config.Accounts.Multiclient.AutoAway, client.accountSettings.AutoAway)
if autoAway {
client.setAutoAwayNoMutex(config)
} else {
client.awayMessage = awayMessage
}
return
}
func (client *Client) setAutoAwayNoMutex(config *Config) {
// aggregate the away statuses of the individual sessions:
var globalAwayState string
var awaySetAt time.Time
for _, cSession := range client.sessions {
if cSession.awayMessage == "" {
// a session is active, we are not auto-away
client.awayMessage = ""
return
} else if cSession.awayAt.After(awaySetAt) {
// choose the latest available away message from any session
globalAwayState = cSession.awayMessage
awaySetAt = cSession.awayAt
}
}
if awaySetAt.IsZero() {
// no sessions, enable auto-away
client.awayMessage = config.languageManager.Translate(client.languages, `User is currently disconnected`)
} else {
client.awayMessage = globalAwayState
}
}
func (client *Client) AlwaysOn() (alwaysOn bool) {
client.stateMutex.RLock()
alwaysOn = client.registered && client.alwaysOn
@ -269,12 +305,6 @@ func (client *Client) AwayMessage() (result string) {
return
}
func (client *Client) SetAwayMessage(message string) {
client.stateMutex.Lock()
client.awayMessage = message
client.stateMutex.Unlock()
}
func (client *Client) Account() string {
client.stateMutex.RLock()
defer client.stateMutex.RUnlock()

View File

@ -352,7 +352,7 @@ func awayHandler(server *Server, client *Client, msg ircmsg.Message, rb *Respons
}
}
client.SetAway(isAway, awayMessage)
rb.session.SetAway(awayMessage)
if isAway {
rb.Add(nil, server.name, RPL_NOWAWAY, client.nick, client.t("You have been marked as being away"))
@ -440,7 +440,7 @@ func brbHandler(server *Server, client *Client, msg ircmsg.Message, rb *Response
if len(client.Sessions()) == 1 {
// true BRB
client.SetAway(true, message)
rb.session.SetAway(message)
}
return true