mirror of
https://github.com/zulip/zulip.git
synced 2026-06-24 21:08:25 +08:00
user-presence: Add aggregated status to user presence info.
- Add aggregated status to user presence status dict. - Add tests for aggregated presence status. - Fix removing unused keys from status dict with aggregated data for user. Fixes #3692
This commit is contained in:
parent
6a801db1c2
commit
2f251dedaf
@ -1395,8 +1395,8 @@ class UserPresence(models.Model):
|
||||
def get_status_dicts_for_query(query, mobile_user_ids):
|
||||
# type: (QuerySet, List[int]) -> defaultdict[Any, Dict[Any, Any]]
|
||||
user_statuses = defaultdict(dict) # type: defaultdict[Any, Dict[Any, Any]]
|
||||
|
||||
for row in query:
|
||||
# Order of query is important to get a latest status as aggregated status.
|
||||
for row in query.order_by("user_profile__id", "-timestamp"):
|
||||
info = UserPresence.to_presence_dict(
|
||||
row['client__name'],
|
||||
row['status'],
|
||||
@ -1405,8 +1405,13 @@ class UserPresence(models.Model):
|
||||
has_push_devices=row['user_profile__id'] in mobile_user_ids,
|
||||
is_mirror_dummy=row['user_profile__is_mirror_dummy'],
|
||||
)
|
||||
if not user_statuses.get(row['user_profile__email']):
|
||||
# Applying the latest status as aggregated status for user.
|
||||
user_statuses[row['user_profile__email']]['aggregated'] = {
|
||||
'status': info['status'],
|
||||
'timestamp': info['timestamp']
|
||||
}
|
||||
user_statuses[row['user_profile__email']][row['client__name']] = info
|
||||
|
||||
return user_statuses
|
||||
|
||||
@staticmethod
|
||||
|
||||
@ -4,6 +4,7 @@ from __future__ import print_function
|
||||
|
||||
from django.http import HttpResponse
|
||||
from django.utils import timezone
|
||||
from mock import mock
|
||||
|
||||
from typing import Any, Dict
|
||||
from zerver.lib.actions import do_deactivate_user
|
||||
@ -15,6 +16,7 @@ from zerver.lib.test_helpers import (
|
||||
from zerver.lib.test_classes import (
|
||||
ZulipTestCase,
|
||||
)
|
||||
from zerver.lib.timestamp import datetime_to_timestamp
|
||||
from zerver.models import (
|
||||
email_to_domain,
|
||||
Client,
|
||||
@ -200,5 +202,71 @@ class SingleUserPresenceTests(ZulipTestCase):
|
||||
self.login("hamlet@zulip.com")
|
||||
result = self.client_get("/json/users/othello@zulip.com/presence")
|
||||
result_dict = ujson.loads(result.content)
|
||||
self.assertEqual(set(result_dict['presence'].keys()), {"ZulipAndroid", "website"})
|
||||
self.assertEqual(
|
||||
set(result_dict['presence'].keys()),
|
||||
{"ZulipAndroid", "website", "aggregated"})
|
||||
self.assertEqual(set(result_dict['presence']['website'].keys()), {"status", "timestamp"})
|
||||
|
||||
|
||||
class UserPresenceAggregationTests(ZulipTestCase):
|
||||
def _send_presence_for_aggregated_tests(self, email, status, validate_time):
|
||||
# type: (str, str, datetime.datetime) -> Dict[str, Dict[str, Any]]
|
||||
self.login(email)
|
||||
timezone_util = 'django.utils.timezone.now'
|
||||
with mock.patch(timezone_util, return_value=validate_time - datetime.timedelta(seconds=5)):
|
||||
self.client_post("/json/users/me/presence", {'status': status})
|
||||
with mock.patch(timezone_util, return_value=validate_time - datetime.timedelta(seconds=2)):
|
||||
self.client_post("/api/v1/users/me/presence", {'status': status},
|
||||
HTTP_USER_AGENT="ZulipAndroid/1.0",
|
||||
**self.api_auth(email))
|
||||
with mock.patch(timezone_util, return_value=validate_time - datetime.timedelta(seconds=7)):
|
||||
self.client_post("/api/v1/users/me/presence", {'status': status},
|
||||
HTTP_USER_AGENT="ZulipIOS/1.0",
|
||||
**self.api_auth(email))
|
||||
result = self.client_get("/json/users/%s/presence" % (email,))
|
||||
return result.json()
|
||||
|
||||
def test_aggregated_presense_active(self):
|
||||
# type: () -> None
|
||||
validate_time = timezone.now()
|
||||
result_dict = self._send_presence_for_aggregated_tests('othello@zulip.com', 'active',
|
||||
validate_time)
|
||||
self.assertDictEqual(
|
||||
result_dict['presence']['aggregated'],
|
||||
{
|
||||
"status": "active",
|
||||
"timestamp": datetime_to_timestamp(validate_time - datetime.timedelta(seconds=2))
|
||||
}
|
||||
)
|
||||
|
||||
def test_aggregated_presense_idle(self):
|
||||
# type: () -> None
|
||||
validate_time = timezone.now()
|
||||
result_dict = self._send_presence_for_aggregated_tests('othello@zulip.com', 'idle',
|
||||
validate_time)
|
||||
self.assertDictEqual(
|
||||
result_dict['presence']['aggregated'],
|
||||
{
|
||||
"status": "idle",
|
||||
"timestamp": datetime_to_timestamp(validate_time - datetime.timedelta(seconds=2))
|
||||
}
|
||||
)
|
||||
|
||||
def test_aggregated_presense_mixed(self):
|
||||
# type: () -> None
|
||||
email = "othello@zulip.com"
|
||||
self.login(email)
|
||||
validate_time = timezone.now()
|
||||
with mock.patch('django.utils.timezone.now',
|
||||
return_value=validate_time - datetime.timedelta(seconds=3)):
|
||||
self.client_post("/api/v1/users/me/presence", {'status': 'active'},
|
||||
HTTP_USER_AGENT="ZulipTestDev/1.0",
|
||||
**self.api_auth(email))
|
||||
result_dict = self._send_presence_for_aggregated_tests(email, 'idle', validate_time)
|
||||
self.assertDictEqual(
|
||||
result_dict['presence']['aggregated'],
|
||||
{
|
||||
"status": "idle",
|
||||
"timestamp": datetime_to_timestamp(validate_time - datetime.timedelta(seconds=2))
|
||||
}
|
||||
)
|
||||
|
||||
@ -41,8 +41,8 @@ def get_presence_backend(request, user_profile, email):
|
||||
# For initial version, we just include the status and timestamp keys
|
||||
result = dict(presence=presence_dict[target.email])
|
||||
for val in result['presence'].values():
|
||||
del val['client']
|
||||
del val['pushable']
|
||||
val.pop('client', None)
|
||||
val.pop('pushable', None)
|
||||
return json_success(result)
|
||||
|
||||
@has_request_variables
|
||||
|
||||
Loading…
Reference in New Issue
Block a user