forked from MirrorHub/synapse
Format presence events on the edges instead of reformatting them multiple times
This commit is contained in:
parent
0ad44acb5a
commit
6c82de5100
7 changed files with 80 additions and 39 deletions
|
@ -13,6 +13,7 @@
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
from synapse.api.errors import SynapseError
|
from synapse.api.errors import SynapseError
|
||||||
|
from synapse.storage.presence import UserPresenceState
|
||||||
from synapse.types import UserID, RoomID
|
from synapse.types import UserID, RoomID
|
||||||
|
|
||||||
from twisted.internet import defer
|
from twisted.internet import defer
|
||||||
|
@ -253,19 +254,30 @@ class Filter(object):
|
||||||
Returns:
|
Returns:
|
||||||
bool: True if the event matches
|
bool: True if the event matches
|
||||||
"""
|
"""
|
||||||
|
if isinstance(event, UserPresenceState):
|
||||||
|
sender = event.user_id
|
||||||
|
room_id = None
|
||||||
|
ev_type = "m.presence"
|
||||||
|
is_url = False
|
||||||
|
else:
|
||||||
sender = event.get("sender", None)
|
sender = event.get("sender", None)
|
||||||
if not sender:
|
if not sender:
|
||||||
# Presence events have their 'sender' in content.user_id
|
# Presence events have their 'sender' in content.user_id
|
||||||
content = event.get("content")
|
content = event.get("content")
|
||||||
# account_data has been allowed to have non-dict content, so check type first
|
# account_data has been allowed to have non-dict content, so
|
||||||
|
# check type first
|
||||||
if isinstance(content, dict):
|
if isinstance(content, dict):
|
||||||
sender = content.get("user_id")
|
sender = content.get("user_id")
|
||||||
|
|
||||||
|
room_id = event.get("room_id", None)
|
||||||
|
ev_type = event.get("type", None)
|
||||||
|
is_url = "url" in event.get("content", {})
|
||||||
|
|
||||||
return self.check_fields(
|
return self.check_fields(
|
||||||
event.get("room_id", None),
|
room_id,
|
||||||
sender,
|
sender,
|
||||||
event.get("type", None),
|
ev_type,
|
||||||
"url" in event.get("content", {})
|
is_url,
|
||||||
)
|
)
|
||||||
|
|
||||||
def check_fields(self, room_id, sender, event_type, contains_url):
|
def check_fields(self, room_id, sender, event_type, contains_url):
|
||||||
|
|
|
@ -19,6 +19,7 @@ from synapse.api.constants import EventTypes, Membership
|
||||||
from synapse.api.errors import AuthError, Codes
|
from synapse.api.errors import AuthError, Codes
|
||||||
from synapse.events.utils import serialize_event
|
from synapse.events.utils import serialize_event
|
||||||
from synapse.events.validator import EventValidator
|
from synapse.events.validator import EventValidator
|
||||||
|
from synapse.handlers.presence import format_user_presence_state
|
||||||
from synapse.streams.config import PaginationConfig
|
from synapse.streams.config import PaginationConfig
|
||||||
from synapse.types import (
|
from synapse.types import (
|
||||||
UserID, StreamToken,
|
UserID, StreamToken,
|
||||||
|
@ -225,9 +226,17 @@ class InitialSyncHandler(BaseHandler):
|
||||||
"content": content,
|
"content": content,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
now = self.clock.time_msec()
|
||||||
|
|
||||||
ret = {
|
ret = {
|
||||||
"rooms": rooms_ret,
|
"rooms": rooms_ret,
|
||||||
"presence": presence,
|
"presence": [
|
||||||
|
{
|
||||||
|
"type": "m.presence",
|
||||||
|
"content": format_user_presence_state(event, now),
|
||||||
|
}
|
||||||
|
for event in presence
|
||||||
|
],
|
||||||
"account_data": account_data_events,
|
"account_data": account_data_events,
|
||||||
"receipts": receipt,
|
"receipts": receipt,
|
||||||
"end": now_token.to_string(),
|
"end": now_token.to_string(),
|
||||||
|
|
|
@ -719,9 +719,7 @@ class PresenceHandler(object):
|
||||||
for state in updates
|
for state in updates
|
||||||
])
|
])
|
||||||
else:
|
else:
|
||||||
defer.returnValue([
|
defer.returnValue(updates)
|
||||||
format_user_presence_state(state, now) for state in updates
|
|
||||||
])
|
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
def set_state(self, target_user, state, ignore_status_msg=False):
|
def set_state(self, target_user, state, ignore_status_msg=False):
|
||||||
|
@ -795,6 +793,9 @@ class PresenceHandler(object):
|
||||||
as_event=False,
|
as_event=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
now = self.clock.time_msec()
|
||||||
|
results[:] = [format_user_presence_state(r, now) for r in results]
|
||||||
|
|
||||||
is_accepted = {
|
is_accepted = {
|
||||||
row["observed_user_id"]: row["accepted"] for row in presence_list
|
row["observed_user_id"]: row["accepted"] for row in presence_list
|
||||||
}
|
}
|
||||||
|
@ -847,6 +848,7 @@ class PresenceHandler(object):
|
||||||
)
|
)
|
||||||
|
|
||||||
state_dict = yield self.get_state(observed_user, as_event=False)
|
state_dict = yield self.get_state(observed_user, as_event=False)
|
||||||
|
state_dict = format_user_presence_state(state_dict, self.clock.time_msec())
|
||||||
|
|
||||||
self.federation.send_edu(
|
self.federation.send_edu(
|
||||||
destination=observer_user.domain,
|
destination=observer_user.domain,
|
||||||
|
@ -979,14 +981,15 @@ def should_notify(old_state, new_state):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def format_user_presence_state(state, now):
|
def format_user_presence_state(state, now, include_user_id=True):
|
||||||
"""Convert UserPresenceState to a format that can be sent down to clients
|
"""Convert UserPresenceState to a format that can be sent down to clients
|
||||||
and to other servers.
|
and to other servers.
|
||||||
"""
|
"""
|
||||||
content = {
|
content = {
|
||||||
"presence": state.state,
|
"presence": state.state,
|
||||||
"user_id": state.user_id,
|
|
||||||
}
|
}
|
||||||
|
if include_user_id:
|
||||||
|
content["user_id"] = state.user_id
|
||||||
if state.last_active_ts:
|
if state.last_active_ts:
|
||||||
content["last_active_ago"] = now - state.last_active_ts
|
content["last_active_ago"] = now - state.last_active_ts
|
||||||
if state.status_msg and state.state != PresenceState.OFFLINE:
|
if state.status_msg and state.state != PresenceState.OFFLINE:
|
||||||
|
@ -1073,15 +1076,12 @@ class PresenceEventSource(object):
|
||||||
|
|
||||||
updates = yield presence.current_state_for_users(user_ids_changed)
|
updates = yield presence.current_state_for_users(user_ids_changed)
|
||||||
|
|
||||||
now = self.clock.time_msec()
|
if include_offline:
|
||||||
|
defer.returnValue((updates.values(), max_token))
|
||||||
|
else:
|
||||||
defer.returnValue(([
|
defer.returnValue(([
|
||||||
{
|
s for s in updates.itervalues()
|
||||||
"type": "m.presence",
|
if s.state != PresenceState.OFFLINE
|
||||||
"content": format_user_presence_state(s, now),
|
|
||||||
}
|
|
||||||
for s in updates.values()
|
|
||||||
if include_offline or s.state != PresenceState.OFFLINE
|
|
||||||
], max_token))
|
], max_token))
|
||||||
|
|
||||||
def get_current_key(self):
|
def get_current_key(self):
|
||||||
|
|
|
@ -721,14 +721,14 @@ class SyncHandler(object):
|
||||||
extra_users_ids.update(users)
|
extra_users_ids.update(users)
|
||||||
extra_users_ids.discard(user.to_string())
|
extra_users_ids.discard(user.to_string())
|
||||||
|
|
||||||
|
if extra_users_ids:
|
||||||
states = yield self.presence_handler.get_states(
|
states = yield self.presence_handler.get_states(
|
||||||
extra_users_ids,
|
extra_users_ids,
|
||||||
as_event=True,
|
|
||||||
)
|
)
|
||||||
presence.extend(states)
|
presence.extend(states)
|
||||||
|
|
||||||
# Deduplicate the presence entries so that there's at most one per user
|
# Deduplicate the presence entries so that there's at most one per user
|
||||||
presence = {p["content"]["user_id"]: p for p in presence}.values()
|
presence = {p.user_id: p for p in presence}.values()
|
||||||
|
|
||||||
presence = sync_config.filter_collection.filter_presence(
|
presence = sync_config.filter_collection.filter_presence(
|
||||||
presence
|
presence
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
from twisted.internet import defer
|
from twisted.internet import defer
|
||||||
from synapse.api.constants import EventTypes, Membership
|
from synapse.api.constants import EventTypes, Membership
|
||||||
from synapse.api.errors import AuthError
|
from synapse.api.errors import AuthError
|
||||||
|
from synapse.handlers.presence import format_user_presence_state
|
||||||
|
|
||||||
from synapse.util import DeferredTimedOutError
|
from synapse.util import DeferredTimedOutError
|
||||||
from synapse.util.logutils import log_function
|
from synapse.util.logutils import log_function
|
||||||
|
@ -412,6 +413,15 @@ class Notifier(object):
|
||||||
new_events,
|
new_events,
|
||||||
is_peeking=is_peeking,
|
is_peeking=is_peeking,
|
||||||
)
|
)
|
||||||
|
elif name == "presence":
|
||||||
|
now = self.clock.time_msec()
|
||||||
|
new_events[:] = [
|
||||||
|
{
|
||||||
|
"type": "m.presence",
|
||||||
|
"content": format_user_presence_state(event, now),
|
||||||
|
}
|
||||||
|
for event in new_events
|
||||||
|
]
|
||||||
|
|
||||||
events.extend(new_events)
|
events.extend(new_events)
|
||||||
end_token = end_token.copy_and_replace(keyname, new_key)
|
end_token = end_token.copy_and_replace(keyname, new_key)
|
||||||
|
|
|
@ -19,6 +19,7 @@ from twisted.internet import defer
|
||||||
|
|
||||||
from synapse.api.errors import SynapseError, AuthError
|
from synapse.api.errors import SynapseError, AuthError
|
||||||
from synapse.types import UserID
|
from synapse.types import UserID
|
||||||
|
from synapse.handlers.presence import format_user_presence_state
|
||||||
from synapse.http.servlet import parse_json_object_from_request
|
from synapse.http.servlet import parse_json_object_from_request
|
||||||
from .base import ClientV1RestServlet, client_path_patterns
|
from .base import ClientV1RestServlet, client_path_patterns
|
||||||
|
|
||||||
|
@ -33,6 +34,7 @@ class PresenceStatusRestServlet(ClientV1RestServlet):
|
||||||
def __init__(self, hs):
|
def __init__(self, hs):
|
||||||
super(PresenceStatusRestServlet, self).__init__(hs)
|
super(PresenceStatusRestServlet, self).__init__(hs)
|
||||||
self.presence_handler = hs.get_presence_handler()
|
self.presence_handler = hs.get_presence_handler()
|
||||||
|
self.clock = hs.get_clock()
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
def on_GET(self, request, user_id):
|
def on_GET(self, request, user_id):
|
||||||
|
@ -48,6 +50,7 @@ class PresenceStatusRestServlet(ClientV1RestServlet):
|
||||||
raise AuthError(403, "You are not allowed to see their presence.")
|
raise AuthError(403, "You are not allowed to see their presence.")
|
||||||
|
|
||||||
state = yield self.presence_handler.get_state(target_user=user)
|
state = yield self.presence_handler.get_state(target_user=user)
|
||||||
|
state = format_user_presence_state(state, self.clock.time_msec())
|
||||||
|
|
||||||
defer.returnValue((200, state))
|
defer.returnValue((200, state))
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ from twisted.internet import defer
|
||||||
from synapse.http.servlet import (
|
from synapse.http.servlet import (
|
||||||
RestServlet, parse_string, parse_integer, parse_boolean
|
RestServlet, parse_string, parse_integer, parse_boolean
|
||||||
)
|
)
|
||||||
|
from synapse.handlers.presence import format_user_presence_state
|
||||||
from synapse.handlers.sync import SyncConfig
|
from synapse.handlers.sync import SyncConfig
|
||||||
from synapse.types import StreamToken
|
from synapse.types import StreamToken
|
||||||
from synapse.events.utils import (
|
from synapse.events.utils import (
|
||||||
|
@ -194,12 +195,18 @@ class SyncRestServlet(RestServlet):
|
||||||
defer.returnValue((200, response_content))
|
defer.returnValue((200, response_content))
|
||||||
|
|
||||||
def encode_presence(self, events, time_now):
|
def encode_presence(self, events, time_now):
|
||||||
formatted = []
|
return {
|
||||||
for event in events:
|
"events": [
|
||||||
event = copy.deepcopy(event)
|
{
|
||||||
event['sender'] = event['content'].pop('user_id')
|
"type": "m.presence",
|
||||||
formatted.append(event)
|
"sender": event.user_id,
|
||||||
return {"events": formatted}
|
"content": format_user_presence_state(
|
||||||
|
event, time_now, include_user_id=False
|
||||||
|
),
|
||||||
|
}
|
||||||
|
for event in events
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
def encode_joined(self, rooms, time_now, token_id, event_fields):
|
def encode_joined(self, rooms, time_now, token_id, event_fields):
|
||||||
"""
|
"""
|
||||||
|
|
Loading…
Reference in a new issue