2014-01-30 22:42:19 +01:00
|
|
|
var people = (function () {
|
|
|
|
|
|
|
|
var exports = {};
|
|
|
|
|
2016-12-15 22:18:59 +01:00
|
|
|
var people_dict;
|
|
|
|
var people_by_name_dict;
|
|
|
|
var people_by_user_id_dict;
|
|
|
|
var realm_people_dict;
|
|
|
|
var cross_realm_dict;
|
|
|
|
var pm_recipient_count_dict;
|
|
|
|
|
|
|
|
// We have an init() function so that our automated tests
|
|
|
|
// can easily clear data.
|
|
|
|
exports.init = function () {
|
|
|
|
// The following three Dicts point to the same objects
|
|
|
|
// All people we've seen
|
|
|
|
people_dict = new Dict({fold_case: true});
|
|
|
|
people_by_name_dict = new Dict({fold_case: true});
|
|
|
|
people_by_user_id_dict = new Dict();
|
|
|
|
// People in this realm
|
|
|
|
realm_people_dict = new Dict({fold_case: true});
|
|
|
|
cross_realm_dict = new Dict({fold_case: true});
|
|
|
|
pm_recipient_count_dict = new Dict({fold_case: true});
|
|
|
|
};
|
|
|
|
|
|
|
|
// WE INITIALIZE DATA STRUCTURES HERE!
|
|
|
|
exports.init();
|
2014-01-30 22:42:19 +01:00
|
|
|
|
2016-10-31 15:56:57 +01:00
|
|
|
exports.get_person_from_user_id = function (user_id) {
|
|
|
|
return people_by_user_id_dict.get(user_id);
|
|
|
|
};
|
|
|
|
|
2014-01-30 22:42:19 +01:00
|
|
|
exports.get_by_email = function get_by_email(email) {
|
|
|
|
return people_dict.get(email);
|
|
|
|
};
|
|
|
|
|
2016-10-30 15:22:24 +01:00
|
|
|
exports.get_user_id = function (email) {
|
|
|
|
var person = people_dict.get(email);
|
|
|
|
if (person === undefined) {
|
|
|
|
blueslip.error('Unknown email for get_user_id: ' + email);
|
|
|
|
return undefined;
|
|
|
|
}
|
|
|
|
var user_id = person.user_id;
|
|
|
|
if (!user_id) {
|
|
|
|
blueslip.error('No userid found for ' + email);
|
|
|
|
return undefined;
|
|
|
|
}
|
|
|
|
|
|
|
|
return user_id;
|
|
|
|
};
|
|
|
|
|
2016-11-15 22:55:37 +01:00
|
|
|
exports.user_ids_string_to_emails_string = function (user_ids_string) {
|
|
|
|
var user_ids = user_ids_string.split(',');
|
|
|
|
var emails = _.map(user_ids, function (user_id) {
|
|
|
|
var person = people_by_user_id_dict.get(user_id);
|
|
|
|
if (person) {
|
|
|
|
return person.email;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
if (!_.all(emails)) {
|
|
|
|
blueslip.error('Unknown user ids: ' + user_ids_string);
|
|
|
|
return;
|
|
|
|
}
|
2016-11-19 00:33:32 +01:00
|
|
|
|
|
|
|
emails = _.map(emails, function (email) {
|
|
|
|
return email.toLowerCase();
|
|
|
|
});
|
|
|
|
|
|
|
|
emails.sort();
|
|
|
|
|
2016-11-15 22:55:37 +01:00
|
|
|
return emails.join(',');
|
|
|
|
};
|
|
|
|
|
|
|
|
exports.emails_strings_to_user_ids_string = function (emails_string) {
|
|
|
|
var emails = emails_string.split(',');
|
|
|
|
var user_ids = _.map(emails, function (email) {
|
|
|
|
var person = people_dict.get(email);
|
|
|
|
if (person) {
|
|
|
|
return person.user_id;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
if (!_.all(user_ids)) {
|
|
|
|
blueslip.error('Unknown emails: ' + emails_string);
|
|
|
|
return;
|
|
|
|
}
|
2016-11-19 00:33:32 +01:00
|
|
|
|
|
|
|
user_ids.sort();
|
|
|
|
|
2016-11-15 22:55:37 +01:00
|
|
|
return user_ids.join(',');
|
|
|
|
};
|
|
|
|
|
2014-01-30 22:42:19 +01:00
|
|
|
exports.realm_get = function realm_get(email) {
|
|
|
|
return realm_people_dict.get(email);
|
|
|
|
};
|
|
|
|
|
2016-11-01 19:36:50 +01:00
|
|
|
exports.get_all_persons = function () {
|
|
|
|
return people_dict.values();
|
|
|
|
};
|
|
|
|
|
2016-11-01 19:45:53 +01:00
|
|
|
exports.get_realm_persons = function () {
|
|
|
|
return realm_people_dict.values();
|
|
|
|
};
|
|
|
|
|
2016-11-02 23:48:47 +01:00
|
|
|
exports.is_cross_realm_email = function (email) {
|
|
|
|
return cross_realm_dict.has(email);
|
|
|
|
};
|
|
|
|
|
2016-11-03 21:59:18 +01:00
|
|
|
exports.get_recipient_count = function (person) {
|
|
|
|
// We can have fake person objects like the "all"
|
|
|
|
// pseudo-person in at-mentions. They will have
|
|
|
|
// the pm_recipient_count on the object itself.
|
|
|
|
if (person.pm_recipient_count) {
|
|
|
|
return person.pm_recipient_count;
|
|
|
|
}
|
|
|
|
|
|
|
|
var count = pm_recipient_count_dict.get(person.email);
|
|
|
|
|
|
|
|
return count || 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
exports.incr_recipient_count = function (email) {
|
|
|
|
var old_count = pm_recipient_count_dict.get(email) || 0;
|
|
|
|
pm_recipient_count_dict.set(email, old_count + 1);
|
|
|
|
};
|
|
|
|
|
2016-10-18 19:21:38 +02:00
|
|
|
exports.filter_people_by_search_terms = function (users, search_terms) {
|
|
|
|
var filtered_users = {};
|
|
|
|
|
2016-11-14 22:22:02 +01:00
|
|
|
var matchers = _.map(search_terms, function (search_term) {
|
2016-11-14 22:34:46 +01:00
|
|
|
var termlets = search_term.toLowerCase().split(/\s+/);
|
|
|
|
termlets = _.map(termlets, function (termlet) {
|
|
|
|
return termlet.trim();
|
|
|
|
});
|
|
|
|
|
2016-11-14 22:22:02 +01:00
|
|
|
return function (email, names) {
|
|
|
|
if (email.indexOf(search_term.trim()) === 0) {
|
|
|
|
return true;
|
|
|
|
}
|
2016-11-14 22:34:46 +01:00
|
|
|
return _.all(termlets, function (termlet) {
|
|
|
|
return _.any(names, function (name) {
|
|
|
|
if (name.indexOf(termlet) === 0) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
});
|
2016-11-14 22:22:02 +01:00
|
|
|
});
|
|
|
|
};
|
|
|
|
});
|
|
|
|
|
|
|
|
|
2016-10-18 19:21:38 +02:00
|
|
|
// Loop through users and populate filtered_users only
|
|
|
|
// if they include search_terms
|
|
|
|
_.each(users, function (user) {
|
|
|
|
var person = exports.get_by_email(user.email);
|
|
|
|
// Get person object (and ignore errors)
|
|
|
|
if (!person || !person.full_name) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-11-14 22:22:02 +01:00
|
|
|
var email = user.email.toLowerCase();
|
|
|
|
|
2016-10-18 19:21:38 +02:00
|
|
|
// Remove extra whitespace
|
|
|
|
var names = person.full_name.toLowerCase().split(/\s+/);
|
|
|
|
names = _.map(names, function (name) {
|
|
|
|
return name.trim();
|
|
|
|
});
|
|
|
|
|
2016-11-14 21:37:36 +01:00
|
|
|
|
2016-10-18 19:21:38 +02:00
|
|
|
// Return user emails that include search terms
|
2016-11-14 22:22:02 +01:00
|
|
|
var match = _.any(matchers, function (matcher) {
|
|
|
|
return matcher(email, names);
|
2016-10-18 19:21:38 +02:00
|
|
|
});
|
2016-11-14 21:37:36 +01:00
|
|
|
|
2016-11-14 22:22:02 +01:00
|
|
|
if (match) {
|
|
|
|
filtered_users[email] = true;
|
2016-11-14 21:37:36 +01:00
|
|
|
}
|
2016-10-18 19:21:38 +02:00
|
|
|
});
|
|
|
|
return filtered_users;
|
|
|
|
};
|
|
|
|
|
2014-01-30 22:42:19 +01:00
|
|
|
exports.get_by_name = function realm_get(name) {
|
|
|
|
return people_by_name_dict.get(name);
|
|
|
|
};
|
|
|
|
|
|
|
|
function people_cmp(person1, person2) {
|
|
|
|
var name_cmp = util.strcmp(person1.full_name, person2.full_name);
|
|
|
|
if (name_cmp < 0) {
|
|
|
|
return -1;
|
|
|
|
} else if (name_cmp > 0) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return util.strcmp(person1.email, person2.email);
|
|
|
|
}
|
|
|
|
|
|
|
|
exports.get_rest_of_realm = function get_rest_of_realm() {
|
|
|
|
var people_minus_you = [];
|
|
|
|
realm_people_dict.each(function (person) {
|
2016-06-08 05:54:07 +02:00
|
|
|
if (!util.is_current_user(person.email)) {
|
2016-12-03 03:08:47 +01:00
|
|
|
people_minus_you.push({email: person.email,
|
2017-01-07 07:58:08 +01:00
|
|
|
user_id: person.user_id,
|
2016-12-03 03:08:47 +01:00
|
|
|
full_name: person.full_name});
|
2014-01-30 22:42:19 +01:00
|
|
|
}
|
|
|
|
});
|
|
|
|
return people_minus_you.sort(people_cmp);
|
|
|
|
};
|
|
|
|
|
2014-02-01 15:17:17 +01:00
|
|
|
exports.add = function add(person) {
|
2016-10-31 15:56:57 +01:00
|
|
|
if (person.user_id) {
|
|
|
|
people_by_user_id_dict.set(person.user_id, person);
|
|
|
|
} else {
|
|
|
|
// We eventually want to lock this down completely
|
|
|
|
// and report an error and not update other the data
|
|
|
|
// structures here, but we have a lot of edge cases
|
|
|
|
// with cross-realm bots, zephyr users, etc., deactivated
|
|
|
|
// users, where we are probably fine for now not to
|
|
|
|
// find them via user_id lookups.
|
|
|
|
blueslip.warn('No user_id provided for ' + person.email);
|
|
|
|
}
|
|
|
|
|
2014-01-30 22:42:19 +01:00
|
|
|
people_dict.set(person.email, person);
|
|
|
|
people_by_name_dict.set(person.full_name, person);
|
|
|
|
};
|
|
|
|
|
|
|
|
exports.add_in_realm = function add_in_realm(person) {
|
|
|
|
realm_people_dict.set(person.email, person);
|
|
|
|
exports.add(person);
|
|
|
|
};
|
|
|
|
|
2016-12-15 22:44:42 +01:00
|
|
|
exports.deactivate = function (person) {
|
|
|
|
// We don't fully remove a person from all of our data
|
|
|
|
// structures, because deactivated users can be part
|
|
|
|
// of somebody's PM list.
|
2014-01-30 22:42:19 +01:00
|
|
|
realm_people_dict.del(person.email);
|
|
|
|
};
|
|
|
|
|
2016-12-15 23:33:36 +01:00
|
|
|
exports.extract_people_from_message = function (message) {
|
|
|
|
var involved_people;
|
|
|
|
|
|
|
|
switch (message.type) {
|
|
|
|
case 'stream':
|
|
|
|
involved_people = [{full_name: message.sender_full_name,
|
|
|
|
user_id: message.sender_id,
|
|
|
|
email: message.sender_email}];
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'private':
|
|
|
|
involved_people = message.display_recipient;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add new people involved in this message to the people list
|
|
|
|
_.each(involved_people, function (person) {
|
|
|
|
if (!person.unknown_local_echo_user) {
|
|
|
|
if (! exports.get_by_email(person.email)) {
|
|
|
|
exports.add({
|
|
|
|
email: person.email,
|
|
|
|
user_id: person.user_id || person.id,
|
|
|
|
full_name: person.full_name,
|
|
|
|
is_admin: person.is_realm_admin || false,
|
2017-01-12 00:17:43 +01:00
|
|
|
is_bot: person.is_bot || false,
|
2016-12-15 23:33:36 +01:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
if (message.type === 'private' && message.sent_by_me) {
|
|
|
|
// Track the number of PMs we've sent to this person to improve autocomplete
|
|
|
|
exports.incr_recipient_count(person.email);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2014-01-30 22:42:19 +01:00
|
|
|
exports.update = function update(person) {
|
|
|
|
if (! people_dict.has(person.email)) {
|
|
|
|
blueslip.error("Got update_person event for unexpected user",
|
|
|
|
{email: person.email});
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
var person_obj = people_dict.get(person.email);
|
|
|
|
|
|
|
|
if (_.has(person, 'full_name')) {
|
|
|
|
if (people_by_name_dict.has(person_obj.full_name)) {
|
|
|
|
people_by_name_dict.set(person.full_name, person_obj);
|
|
|
|
people_by_name_dict.del(person_obj.full_name);
|
|
|
|
}
|
|
|
|
|
|
|
|
person_obj.full_name = person.full_name;
|
|
|
|
|
2016-06-08 05:54:07 +02:00
|
|
|
if (util.is_current_user(person.email)) {
|
2014-01-30 22:42:19 +01:00
|
|
|
page_params.fullname = person.full_name;
|
|
|
|
}
|
2017-01-04 23:54:59 +01:00
|
|
|
|
|
|
|
activity.redraw();
|
|
|
|
// TODO: update sender names on messages
|
|
|
|
|
2014-01-30 22:42:19 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (_.has(person, 'is_admin')) {
|
|
|
|
person_obj.is_admin = person.is_admin;
|
|
|
|
|
2016-06-08 05:54:07 +02:00
|
|
|
if (util.is_current_user(person.email)) {
|
2014-01-30 22:42:19 +01:00
|
|
|
page_params.is_admin = person.is_admin;
|
|
|
|
admin.show_or_hide_menu_item();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-08-19 00:28:28 +02:00
|
|
|
if (_.has(person, 'avatar_url')) {
|
|
|
|
var url = person.avatar_url + "&y=" + new Date().getTime();
|
|
|
|
person_obj.avatar_url = url;
|
|
|
|
|
|
|
|
if (util.is_current_user(person.email)) {
|
|
|
|
page_params.avatar_url = url;
|
|
|
|
$("#user-settings-avatar").attr("src", url);
|
|
|
|
}
|
|
|
|
|
|
|
|
$(".inline_profile_picture.u-" + person.id).css({
|
2017-01-12 00:17:43 +01:00
|
|
|
"background-image": "url(" + url + ")",
|
2016-08-19 00:28:28 +02:00
|
|
|
});
|
|
|
|
}
|
2014-01-30 22:42:19 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
$(function () {
|
|
|
|
_.each(page_params.people_list, function (person) {
|
2016-11-01 21:01:42 +01:00
|
|
|
exports.add_in_realm(person);
|
2014-01-30 22:42:19 +01:00
|
|
|
});
|
|
|
|
|
2016-11-02 23:48:47 +01:00
|
|
|
_.each(page_params.cross_realm_bots, function (person) {
|
|
|
|
if (!people_dict.has(person.email)) {
|
|
|
|
exports.add(person);
|
|
|
|
}
|
|
|
|
cross_realm_dict.set(person.email, person);
|
|
|
|
});
|
2016-11-01 20:55:18 +01:00
|
|
|
|
2016-11-02 23:48:47 +01:00
|
|
|
delete page_params.people_list; // We are the only consumer of this.
|
|
|
|
delete page_params.cross_realm_bots;
|
2014-01-30 22:42:19 +01:00
|
|
|
});
|
|
|
|
|
|
|
|
return exports;
|
|
|
|
|
|
|
|
}());
|
|
|
|
if (typeof module !== 'undefined') {
|
|
|
|
module.exports = people;
|
|
|
|
}
|