mirror of
https://github.com/zulip/zulip.git
synced 2025-11-05 22:43:42 +00:00
Send client information for initial presence and process time differential
(imported from commit 99a51b7cc8b6c51c4e82757a984d07603b2980e3)
This commit is contained in:
@@ -23,7 +23,7 @@ from django.utils import timezone
|
|||||||
from zephyr.lib.create_user import create_user
|
from zephyr.lib.create_user import create_user
|
||||||
from zephyr.lib import bugdown
|
from zephyr.lib import bugdown
|
||||||
from zephyr.lib.cache import cache_with_key, user_profile_by_id_cache_key, \
|
from zephyr.lib.cache import cache_with_key, user_profile_by_id_cache_key, \
|
||||||
user_profile_by_email_cache_key
|
user_profile_by_email_cache_key, status_dict_cache_key
|
||||||
from zephyr.decorator import get_user_profile_by_email, json_to_list, JsonableError
|
from zephyr.decorator import get_user_profile_by_email, json_to_list, JsonableError
|
||||||
from zephyr.lib.event_queue import request_event_queue, get_user_events
|
from zephyr.lib.event_queue import request_event_queue, get_user_events
|
||||||
|
|
||||||
@@ -38,6 +38,7 @@ import datetime
|
|||||||
import os
|
import os
|
||||||
import platform
|
import platform
|
||||||
import logging
|
import logging
|
||||||
|
from collections import defaultdict
|
||||||
from os import path
|
from os import path
|
||||||
|
|
||||||
# Store an event in the log for re-importing messages
|
# Store an event in the log for re-importing messages
|
||||||
@@ -581,8 +582,9 @@ def process_user_activity_event(event):
|
|||||||
return do_update_user_activity(user_profile, client, query, log_time)
|
return do_update_user_activity(user_profile, client, query, log_time)
|
||||||
|
|
||||||
def send_presence_changed(user_profile, presence):
|
def send_presence_changed(user_profile, presence):
|
||||||
|
presence_dict = presence.to_dict()
|
||||||
notice = dict(event=dict(type="presence", email=user_profile.email,
|
notice = dict(event=dict(type="presence", email=user_profile.email,
|
||||||
presence=presence.to_dict()),
|
presence={presence_dict['client']: presence.to_dict()}),
|
||||||
users=[up.id for up in
|
users=[up.id for up in
|
||||||
UserProfile.objects.select_related()
|
UserProfile.objects.select_related()
|
||||||
.filter(realm=user_profile.realm,
|
.filter(realm=user_profile.realm,
|
||||||
@@ -602,8 +604,9 @@ def do_update_user_presence(user_profile, client, log_time, status):
|
|||||||
client = client)
|
client = client)
|
||||||
created = False
|
created = False
|
||||||
|
|
||||||
became_online = (status == UserPresence.ACTIVE and
|
stale_status = (log_time - presence.timestamp) > datetime.timedelta(minutes=10)
|
||||||
presence.status == UserPresence.IDLE)
|
was_idle = presence.status == UserPresence.IDLE
|
||||||
|
became_online = (status == UserPresence.ACTIVE) and (stale_status or was_idle)
|
||||||
|
|
||||||
presence.timestamp = log_time
|
presence.timestamp = log_time
|
||||||
presence.status = status
|
presence.status = status
|
||||||
@@ -765,6 +768,21 @@ def gather_subscriptions(user_profile):
|
|||||||
|
|
||||||
return sorted(result)
|
return sorted(result)
|
||||||
|
|
||||||
|
@cache_with_key(status_dict_cache_key, timeout=60)
|
||||||
|
def get_status_dict(requesting_user_profile):
|
||||||
|
user_statuses = defaultdict(dict)
|
||||||
|
|
||||||
|
# Return no status info for MIT
|
||||||
|
if requesting_user_profile.realm.domain == 'mit.edu':
|
||||||
|
return user_statuses
|
||||||
|
|
||||||
|
for presence in UserPresence.objects.filter(user_profile__realm=requesting_user_profile.realm) \
|
||||||
|
.select_related('user_profile', 'client'):
|
||||||
|
user_statuses[presence.user_profile.email][presence.client.name] = presence.to_dict()
|
||||||
|
|
||||||
|
return user_statuses
|
||||||
|
|
||||||
|
|
||||||
def do_events_register(user_profile, apply_markdown=True, event_types=None):
|
def do_events_register(user_profile, apply_markdown=True, event_types=None):
|
||||||
queue_id = request_event_queue(user_profile, apply_markdown, event_types)
|
queue_id = request_event_queue(user_profile, apply_markdown, event_types)
|
||||||
if queue_id is None:
|
if queue_id is None:
|
||||||
@@ -796,11 +814,7 @@ def do_events_register(user_profile, apply_markdown=True, event_types=None):
|
|||||||
if event_types is None or "subscription" in event_types:
|
if event_types is None or "subscription" in event_types:
|
||||||
ret['subscriptions'] = gather_subscriptions(user_profile)
|
ret['subscriptions'] = gather_subscriptions(user_profile)
|
||||||
if event_types is None or "presence" in event_types:
|
if event_types is None or "presence" in event_types:
|
||||||
presences = dict((presence.user_profile.email, presence.to_dict())
|
ret['presences'] = get_status_dict(user_profile)
|
||||||
for presence in UserPresence.objects.select_related()
|
|
||||||
.filter(user_profile__realm=user_profile.realm,
|
|
||||||
user_profile__is_active=True))
|
|
||||||
ret['presences'] = presences
|
|
||||||
|
|
||||||
# Apply events that came in while we were fetching initial data
|
# Apply events that came in while we were fetching initial data
|
||||||
events = get_user_events(user_profile, queue_id, -1)
|
events = get_user_events(user_profile, queue_id, -1)
|
||||||
@@ -824,7 +838,7 @@ def do_events_register(user_profile, apply_markdown=True, event_types=None):
|
|||||||
ret['subscriptions'] = filter(lambda s: s['name'] != sub['name'],
|
ret['subscriptions'] = filter(lambda s: s['name'] != sub['name'],
|
||||||
ret['subscriptions'])
|
ret['subscriptions'])
|
||||||
elif event['type'] == "presence":
|
elif event['type'] == "presence":
|
||||||
ret['presences'][event['email']] = event['presence']
|
ret['presences'][event['email']][event['presence']['client']] = event['presence']
|
||||||
|
|
||||||
if events:
|
if events:
|
||||||
ret['last_event_id'] = events[-1]['id']
|
ret['last_event_id'] = events[-1]['id']
|
||||||
|
|||||||
@@ -73,3 +73,10 @@ def update_user_profile_cache(sender, **kwargs):
|
|||||||
items_for_memcached[user_profile_by_email_cache_key(user_profile.email)] = (user_profile,)
|
items_for_memcached[user_profile_by_email_cache_key(user_profile.email)] = (user_profile,)
|
||||||
items_for_memcached[user_profile_by_id_cache_key(user_profile.id)] = (user_profile,)
|
items_for_memcached[user_profile_by_id_cache_key(user_profile.id)] = (user_profile,)
|
||||||
djcache.set_many(items_for_memcached)
|
djcache.set_many(items_for_memcached)
|
||||||
|
|
||||||
|
def status_dict_cache_key(user_profile):
|
||||||
|
return "status_dict:%d" % (user_profile.realm_id,)
|
||||||
|
|
||||||
|
def update_user_presence_cache(sender, **kwargs):
|
||||||
|
user_profile = kwargs['instance'].user_profile
|
||||||
|
djcache.delete(status_dict_cache_key(user_profile))
|
||||||
|
|||||||
@@ -2,7 +2,8 @@ from django.db import models
|
|||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.auth.models import AbstractBaseUser, UserManager
|
from django.contrib.auth.models import AbstractBaseUser, UserManager
|
||||||
from zephyr.lib.cache import cache_with_key, update_user_profile_cache, \
|
from zephyr.lib.cache import cache_with_key, update_user_profile_cache, \
|
||||||
user_profile_by_id_cache_key, user_profile_by_email_cache_key
|
user_profile_by_id_cache_key, user_profile_by_email_cache_key, \
|
||||||
|
update_user_presence_cache
|
||||||
from zephyr.lib.utils import make_safe_digest
|
from zephyr.lib.utils import make_safe_digest
|
||||||
import os
|
import os
|
||||||
from django.db import transaction, IntegrityError
|
from django.db import transaction, IntegrityError
|
||||||
@@ -444,7 +445,8 @@ class UserPresence(models.Model):
|
|||||||
elif self.status == UserPresence.IDLE:
|
elif self.status == UserPresence.IDLE:
|
||||||
presence_val = 'idle'
|
presence_val = 'idle'
|
||||||
|
|
||||||
return {'status' : presence_val,
|
return {'client' : self.client.name,
|
||||||
|
'status' : presence_val,
|
||||||
'timestamp': datetime_to_timestamp(self.timestamp)}
|
'timestamp': datetime_to_timestamp(self.timestamp)}
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@@ -461,6 +463,10 @@ class UserPresence(models.Model):
|
|||||||
class Meta:
|
class Meta:
|
||||||
unique_together = ("user_profile", "client")
|
unique_together = ("user_profile", "client")
|
||||||
|
|
||||||
|
# Flush the cached user status_dict whenever a user's presence
|
||||||
|
# changes
|
||||||
|
post_save.connect(update_user_presence_cache, sender=UserPresence)
|
||||||
|
|
||||||
class DefaultStream(models.Model):
|
class DefaultStream(models.Model):
|
||||||
realm = models.ForeignKey(Realm)
|
realm = models.ForeignKey(Realm)
|
||||||
stream = models.ForeignKey(Stream)
|
stream = models.ForeignKey(Stream)
|
||||||
|
|||||||
@@ -72,6 +72,24 @@ function update_users() {
|
|||||||
ui.set_presence_list(users, user_info);
|
ui.set_presence_list(users, user_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function status_from_timestamp(time_now, presence) {
|
||||||
|
if (presence.website === undefined) {
|
||||||
|
return 'idle';
|
||||||
|
}
|
||||||
|
|
||||||
|
var age = time_now - presence.website.timestamp;
|
||||||
|
|
||||||
|
var status = 'idle';
|
||||||
|
if (presence.website.status === ACTIVE && age >= 0) {
|
||||||
|
if (age < AWAY_THRESHOLD_SECS) {
|
||||||
|
status = 'active';
|
||||||
|
} else if (age < IDLE_THRESHOLD_SECS) {
|
||||||
|
status = 'away';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
function focus_ping() {
|
function focus_ping() {
|
||||||
if (!has_focus) {
|
if (!has_focus) {
|
||||||
return;
|
return;
|
||||||
@@ -90,23 +108,8 @@ function focus_ping() {
|
|||||||
|
|
||||||
// Ping returns the active peer list
|
// Ping returns the active peer list
|
||||||
$.each(data.presences, function (this_email, presence) {
|
$.each(data.presences, function (this_email, presence) {
|
||||||
var age = -1;
|
|
||||||
|
|
||||||
if (presence.website !== undefined && presence.website.timestamp !== undefined) {
|
|
||||||
age = now - presence.website.timestamp;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (page_params.email !== this_email) {
|
if (page_params.email !== this_email) {
|
||||||
var status = 'idle';
|
user_info[this_email] = status_from_timestamp(now, presence);
|
||||||
if (presence.website !== undefined
|
|
||||||
&& presence.website.status === ACTIVE && age >= 0) {
|
|
||||||
if (age < AWAY_THRESHOLD_SECS) {
|
|
||||||
status = 'active';
|
|
||||||
} else if (age < IDLE_THRESHOLD_SECS) {
|
|
||||||
status = 'away';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
user_info[this_email] = status;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
update_users();
|
update_users();
|
||||||
@@ -130,14 +133,17 @@ exports.initialize = function () {
|
|||||||
keepTracking: true});
|
keepTracking: true});
|
||||||
|
|
||||||
ping_timer = setInterval(focus_ping, ACTIVE_PING_INTERVAL_MS);
|
ping_timer = setInterval(focus_ping, ACTIVE_PING_INTERVAL_MS);
|
||||||
|
|
||||||
|
focus_ping();
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.set_user_status = function (user_email, status) {
|
exports.set_user_status = function (user_email, presence) {
|
||||||
if (user_email === page_params.email) {
|
if (user_email === page_params.email) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
var now = new Date().getTime() / 1000;
|
||||||
|
user_info[user_email] = status_from_timestamp(now, presence);
|
||||||
|
|
||||||
user_info[user_email] = status;
|
|
||||||
update_users();
|
update_users();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ $(function () {
|
|||||||
"full_name": "Humbug Feedback Bot"}]);
|
"full_name": "Humbug Feedback Bot"}]);
|
||||||
|
|
||||||
$.each(page_params.initial_presences, function (email, presence) {
|
$.each(page_params.initial_presences, function (email, presence) {
|
||||||
activity.set_user_status(email, presence.status);
|
activity.set_user_status(email, presence);
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
@@ -694,7 +694,7 @@ function get_updates(options) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'presence':
|
case 'presence':
|
||||||
activity.set_user_status(event.email, event.presence.status);
|
activity.set_user_status(event.email, event.presence);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -26,7 +26,8 @@ from zephyr.lib.actions import do_add_subscription, do_remove_subscription, \
|
|||||||
log_subscription_property_change, internal_send_message, \
|
log_subscription_property_change, internal_send_message, \
|
||||||
create_stream_if_needed, gather_subscriptions, subscribed_to_stream, \
|
create_stream_if_needed, gather_subscriptions, subscribed_to_stream, \
|
||||||
update_user_presence, set_stream_color, get_stream_colors, update_message_flags, \
|
update_user_presence, set_stream_color, get_stream_colors, update_message_flags, \
|
||||||
recipient_for_emails, extract_recipients, do_events_register, do_finish_tutorial
|
recipient_for_emails, extract_recipients, do_events_register, do_finish_tutorial, \
|
||||||
|
get_status_dict
|
||||||
from zephyr.forms import RegistrationForm, HomepageForm, ToSForm, is_unique, \
|
from zephyr.forms import RegistrationForm, HomepageForm, ToSForm, is_unique, \
|
||||||
is_inactive, isnt_mit
|
is_inactive, isnt_mit
|
||||||
from django.views.decorators.csrf import csrf_exempt
|
from django.views.decorators.csrf import csrf_exempt
|
||||||
@@ -1459,21 +1460,8 @@ def api_beanstalk_webhook(request, user_profile, payload=POST(converter=json_to_
|
|||||||
return json_error(ret)
|
return json_error(ret)
|
||||||
return json_success()
|
return json_success()
|
||||||
|
|
||||||
@cache_with_key(lambda user_profile: user_profile.realm_id, timeout=60)
|
|
||||||
def get_status_list(requesting_user_profile):
|
def get_status_list(requesting_user_profile):
|
||||||
user_statuses = defaultdict(dict)
|
return {'presences': get_status_dict(requesting_user_profile)}
|
||||||
|
|
||||||
# Return no status info for MIT
|
|
||||||
if requesting_user_profile.realm.domain == 'mit.edu':
|
|
||||||
return {'presences': user_statuses}
|
|
||||||
|
|
||||||
for presence in UserPresence.objects.filter(
|
|
||||||
user_profile__realm=requesting_user_profile.realm).select_related(
|
|
||||||
'user_profile', 'client'):
|
|
||||||
|
|
||||||
user_statuses[presence.user_profile.email][presence.client.name] = presence.to_dict()
|
|
||||||
|
|
||||||
return {'presences': user_statuses}
|
|
||||||
|
|
||||||
@authenticated_json_post_view
|
@authenticated_json_post_view
|
||||||
@has_request_variables
|
@has_request_variables
|
||||||
|
|||||||
Reference in New Issue
Block a user