Skip to content
This repository has been archived by the owner on Apr 26, 2024. It is now read-only.

Commit

Permalink
Merge pull request #9644 from matrix-org/babolivier/msc3026
Browse files Browse the repository at this point in the history
Implement MSC3026: busy presence state
  • Loading branch information
babolivier authored Mar 22, 2021
2 parents 066068f + b6ed4f5 commit e09838c
Show file tree
Hide file tree
Showing 7 changed files with 43 additions and 4 deletions.
1 change: 1 addition & 0 deletions changelog.d/9644.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Implement the busy presence state as described in [MSC3026](https://github.com/matrix-org/matrix-doc/pull/3026).
1 change: 1 addition & 0 deletions synapse/api/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ class PresenceState:
OFFLINE = "offline"
UNAVAILABLE = "unavailable"
ONLINE = "online"
BUSY = "org.matrix.msc3026.busy"


class JoinRules:
Expand Down
8 changes: 7 additions & 1 deletion synapse/app/generic_worker.py
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,8 @@ def __init__(self, hs):
self.send_stop_syncing, UPDATE_SYNCING_USERS_MS
)

self._busy_presence_enabled = hs.config.experimental.msc3026_enabled

hs.get_reactor().addSystemEventTrigger(
"before",
"shutdown",
Expand Down Expand Up @@ -439,8 +441,12 @@ async def set_state(self, target_user, state, ignore_status_msg=False):
PresenceState.ONLINE,
PresenceState.UNAVAILABLE,
PresenceState.OFFLINE,
PresenceState.BUSY,
)
if presence not in valid_presence:

if presence not in valid_presence or (
presence == PresenceState.BUSY and not self._busy_presence_enabled
):
raise SynapseError(400, "Invalid presence state")

user_id = target_user.to_string()
Expand Down
3 changes: 2 additions & 1 deletion synapse/config/experimental.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ def read_config(self, config: JsonDict, **kwargs):

# MSC2858 (multiple SSO identity providers)
self.msc2858_enabled = experimental.get("msc2858_enabled", False) # type: bool

# Spaces (MSC1772, MSC2946, etc)
self.spaces_enabled = experimental.get("spaces_enabled", False) # type: bool
# MSC3026 (busy presence state)
self.msc3026_enabled = experimental.get("msc3026_enabled", False) # type: bool
12 changes: 10 additions & 2 deletions synapse/handlers/presence.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,8 @@ def __init__(self, hs: "HomeServer"):
self.clock = hs.get_clock()
self.store = hs.get_datastore()

self._busy_presence_enabled = hs.config.experimental.msc3026_enabled

active_presence = self.store.take_presence_startup_info()
self.user_to_current_state = {state.user_id: state for state in active_presence}

Expand Down Expand Up @@ -730,8 +732,12 @@ async def set_state(self, target_user, state, ignore_status_msg=False):
PresenceState.ONLINE,
PresenceState.UNAVAILABLE,
PresenceState.OFFLINE,
PresenceState.BUSY,
)
if presence not in valid_presence:

if presence not in valid_presence or (
presence == PresenceState.BUSY and not self._busy_presence_enabled
):
raise SynapseError(400, "Invalid presence state")

user_id = target_user.to_string()
Expand All @@ -744,7 +750,9 @@ async def set_state(self, target_user, state, ignore_status_msg=False):
msg = status_msg if presence != PresenceState.OFFLINE else None
new_fields["status_msg"] = msg

if presence == PresenceState.ONLINE:
if presence == PresenceState.ONLINE or (
presence == PresenceState.BUSY and self._busy_presence_enabled
):
new_fields["last_active_ts"] = self.clock.time_msec()

await self._update_states([prev_state.copy_and_replace(**new_fields)])
Expand Down
2 changes: 2 additions & 0 deletions synapse/rest/client/versions.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ def on_GET(self, request):
"io.element.e2ee_forced.public": self.e2ee_forced_public,
"io.element.e2ee_forced.private": self.e2ee_forced_private,
"io.element.e2ee_forced.trusted_private": self.e2ee_forced_trusted_private,
# Supports the busy presence state described in MSC3026.
"org.matrix.msc3026.busy_presence": self.config.experimental.msc3026_enabled,
},
},
)
Expand Down
20 changes: 20 additions & 0 deletions tests/handlers/test_presence.py
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,26 @@ def test_idle_timer(self):
self.assertIsNotNone(new_state)
self.assertEquals(new_state.state, PresenceState.UNAVAILABLE)

def test_busy_no_idle(self):
"""
Tests that a user setting their presence to busy but idling doesn't turn their
presence state into unavailable.
"""
user_id = "@foo:bar"
now = 5000000

state = UserPresenceState.default(user_id)
state = state.copy_and_replace(
state=PresenceState.BUSY,
last_active_ts=now - IDLE_TIMER - 1,
last_user_sync_ts=now,
)

new_state = handle_timeout(state, is_mine=True, syncing_user_ids=set(), now=now)

self.assertIsNotNone(new_state)
self.assertEquals(new_state.state, PresenceState.BUSY)

def test_sync_timeout(self):
user_id = "@foo:bar"
now = 5000000
Expand Down

0 comments on commit e09838c

Please sign in to comment.