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. 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 ### +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). 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 accountName string // display name of the account: uncasefolded, '*' if not logged in
accountRegDate time.Time accountRegDate time.Time
accountSettings AccountSettings accountSettings AccountSettings
away bool
autoAway bool
awayMessage string awayMessage string
brbTimer BrbTimer brbTimer BrbTimer
channels ChannelSet channels ChannelSet
@ -177,6 +175,9 @@ type Session struct {
quitMessage string quitMessage string
awayMessage string
awayAt time.Time
capabilities caps.Set capabilities caps.Set
capState caps.State capState caps.State
capVersion caps.Version capVersion caps.Version
@ -486,9 +487,7 @@ func (server *Server) AddAlwaysOnClient(account ClientAccount, channelToStatus m
} }
if persistenceEnabled(config.Accounts.Multiclient.AutoAway, client.accountSettings.AutoAway) { if persistenceEnabled(config.Accounts.Multiclient.AutoAway, client.accountSettings.AutoAway) {
client.autoAway = true client.setAutoAwayNoMutex(config)
client.away = true
client.awayMessage = client.t("User is currently disconnected")
} }
} }
@ -675,7 +674,7 @@ func (client *Client) run(session *Session) {
session.playResume() session.playResume()
session.resumeDetails = nil session.resumeDetails = nil
client.brbTimer.Disable() client.brbTimer.Disable()
client.SetAway(false, "") // clear BRB message if any session.SetAway("") // clear BRB message if any
} else { } else {
client.playReattachMessages(session) client.playReattachMessages(session)
} }
@ -1459,15 +1458,13 @@ func (client *Client) destroy(session *Session) {
client.dirtyBits |= IncludeLastSeen client.dirtyBits |= IncludeLastSeen
} }
autoAway := false becameAutoAway := false
var awayMessage string var awayMessage string
if alwaysOn && !client.away && remainingSessions == 0 && if alwaysOn && persistenceEnabled(config.Accounts.Multiclient.AutoAway, client.accountSettings.AutoAway) {
persistenceEnabled(config.Accounts.Multiclient.AutoAway, client.accountSettings.AutoAway) { wasAway := client.awayMessage != ""
autoAway = true client.setAutoAwayNoMutex(config)
client.autoAway = true awayMessage = client.awayMessage
client.away = true becameAutoAway = !wasAway && awayMessage != ""
awayMessage = config.languageManager.Translate(client.languages, `User is currently disconnected`)
client.awayMessage = awayMessage
} }
if client.registrationTimer != nil { if client.registrationTimer != nil {
@ -1524,7 +1521,7 @@ func (client *Client) destroy(session *Session) {
client.server.stats.Remove(registered, invisible, operator) client.server.stats.Remove(registered, invisible, operator)
} }
if autoAway { if becameAutoAway {
dispatchAwayNotify(client, true, awayMessage) 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) { func (client *Client) AddSession(session *Session) (success bool, numSessions int, lastSeen time.Time, back bool) {
config := client.server.Config()
client.stateMutex.Lock() client.stateMutex.Lock()
defer client.stateMutex.Unlock() 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.setLastSeen(time.Now().UTC(), session.deviceID)
} }
client.sessions = newSessions client.sessions = newSessions
if client.autoAway { // TODO(#1551) there should be a cap to opt out of this behavior on a session
back = true if persistenceEnabled(config.Accounts.Multiclient.AutoAway, client.accountSettings.AutoAway) {
client.autoAway = false
client.away = false
client.awayMessage = "" client.awayMessage = ""
if len(client.sessions) == 1 {
back = true
}
} }
return true, len(client.sessions), lastSeen, back return true, len(client.sessions), lastSeen, back
} }
@ -196,20 +198,54 @@ func (client *Client) Hostname() string {
func (client *Client) Away() (result bool, message string) { func (client *Client) Away() (result bool, message string) {
client.stateMutex.Lock() client.stateMutex.Lock()
result, message = client.away, client.awayMessage message = client.awayMessage
client.stateMutex.Unlock() client.stateMutex.Unlock()
result = client.awayMessage != ""
return 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() client.stateMutex.Lock()
changed = away != client.away defer client.stateMutex.Unlock()
client.away = away
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 client.awayMessage = awayMessage
client.stateMutex.Unlock() }
return 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) { func (client *Client) AlwaysOn() (alwaysOn bool) {
client.stateMutex.RLock() client.stateMutex.RLock()
alwaysOn = client.registered && client.alwaysOn alwaysOn = client.registered && client.alwaysOn
@ -269,12 +305,6 @@ func (client *Client) AwayMessage() (result string) {
return return
} }
func (client *Client) SetAwayMessage(message string) {
client.stateMutex.Lock()
client.awayMessage = message
client.stateMutex.Unlock()
}
func (client *Client) Account() string { func (client *Client) Account() string {
client.stateMutex.RLock() client.stateMutex.RLock()
defer client.stateMutex.RUnlock() 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 { if isAway {
rb.Add(nil, server.name, RPL_NOWAWAY, client.nick, client.t("You have been marked as being away")) 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 { if len(client.Sessions()) == 1 {
// true BRB // true BRB
client.SetAway(true, message) rb.session.SetAway(message)
} }
return true return true