2013-08-15 21:11:07 +02:00
|
|
|
var stream_data = (function () {
|
|
|
|
|
|
|
|
var exports = {};
|
|
|
|
|
2013-09-16 23:47:05 +02:00
|
|
|
|
|
|
|
// The stream_info variable maps stream names to stream properties objects
|
|
|
|
// Call clear_subscriptions() to initialize it.
|
|
|
|
var stream_info;
|
2014-02-05 20:35:16 +01:00
|
|
|
var subs_by_stream_id;
|
2013-09-16 23:47:05 +02:00
|
|
|
|
|
|
|
exports.clear_subscriptions = function () {
|
|
|
|
stream_info = new Dict({fold_case: true});
|
2014-02-05 20:35:16 +01:00
|
|
|
subs_by_stream_id = new Dict();
|
2013-09-16 23:47:05 +02:00
|
|
|
};
|
2016-06-04 22:40:25 +02:00
|
|
|
|
|
|
|
exports.recent_subjects = new Dict({fold_case: true});
|
2013-09-16 23:47:05 +02:00
|
|
|
exports.clear_subscriptions();
|
2013-08-15 21:11:07 +02:00
|
|
|
|
|
|
|
|
|
|
|
exports.add_sub = function (stream_name, sub) {
|
2013-09-16 23:47:05 +02:00
|
|
|
stream_info.set(stream_name, sub);
|
2014-02-05 20:35:16 +01:00
|
|
|
subs_by_stream_id.set(sub.stream_id, sub);
|
2013-08-15 21:11:07 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
exports.get_sub = function (stream_name) {
|
2013-09-16 23:47:05 +02:00
|
|
|
return stream_info.get(stream_name);
|
2013-08-15 21:11:07 +02:00
|
|
|
};
|
|
|
|
|
2014-02-05 20:35:16 +01:00
|
|
|
exports.get_sub_by_id = function (stream_id) {
|
|
|
|
return subs_by_stream_id.get(stream_id);
|
|
|
|
};
|
|
|
|
|
2013-08-21 23:21:31 +02:00
|
|
|
exports.delete_sub = function (stream_name) {
|
2013-09-16 23:47:05 +02:00
|
|
|
stream_info.del(stream_name);
|
2013-08-21 23:21:31 +02:00
|
|
|
};
|
|
|
|
|
2013-10-25 16:59:52 +02:00
|
|
|
exports.subscribed_subs = function () {
|
2013-08-15 21:11:07 +02:00
|
|
|
return _.where(stream_info.values(), {subscribed: true});
|
2013-10-25 16:59:52 +02:00
|
|
|
};
|
2013-08-15 21:11:07 +02:00
|
|
|
|
|
|
|
exports.subscribed_streams = function () {
|
2013-10-25 16:59:52 +02:00
|
|
|
return _.pluck(exports.subscribed_subs(), 'name');
|
2013-08-15 21:11:07 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
exports.get_colors = function () {
|
2013-10-25 16:59:52 +02:00
|
|
|
return _.pluck(exports.subscribed_subs(), 'color');
|
2013-08-15 21:11:07 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
exports.all_subscribed_streams_are_in_home_view = function () {
|
2013-10-25 16:59:52 +02:00
|
|
|
return _.every(exports.subscribed_subs(), function (sub) {
|
2013-08-15 21:11:07 +02:00
|
|
|
return sub.in_home_view; }
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
2014-01-15 20:59:31 +01:00
|
|
|
exports.home_view_stream_names = function () {
|
|
|
|
var home_view_subs = _.filter(exports.subscribed_subs(), function (sub) {
|
|
|
|
return sub.in_home_view;
|
|
|
|
}
|
|
|
|
);
|
|
|
|
return _.map(home_view_subs, function (sub) {
|
|
|
|
return sub.name;
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2013-08-15 21:11:07 +02:00
|
|
|
exports.canonicalized_name = function (stream_name) {
|
|
|
|
return stream_name.toString().toLowerCase();
|
|
|
|
};
|
|
|
|
|
|
|
|
exports.get_color = function (stream_name) {
|
|
|
|
var sub = exports.get_sub(stream_name);
|
|
|
|
if (sub === undefined) {
|
|
|
|
return stream_color.default_color;
|
|
|
|
}
|
|
|
|
return sub.color;
|
|
|
|
};
|
|
|
|
|
|
|
|
exports.in_home_view = function (stream_name) {
|
|
|
|
var sub = exports.get_sub(stream_name);
|
|
|
|
return sub !== undefined && sub.in_home_view;
|
|
|
|
};
|
|
|
|
|
|
|
|
exports.is_subscribed = function (stream_name) {
|
|
|
|
var sub = exports.get_sub(stream_name);
|
|
|
|
return sub !== undefined && sub.subscribed;
|
|
|
|
};
|
|
|
|
|
|
|
|
exports.get_invite_only = function (stream_name) {
|
|
|
|
var sub = exports.get_sub(stream_name);
|
|
|
|
if (sub === undefined) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return sub.invite_only;
|
|
|
|
};
|
|
|
|
|
2013-08-19 19:25:44 +02:00
|
|
|
exports.get_name = function (stream_name) {
|
|
|
|
// This returns the actual name of a stream if we are subscribed to
|
|
|
|
// it (i.e "Denmark" vs. "denmark"), while falling thru to
|
|
|
|
// stream_name if we don't have a subscription. (Stream names
|
|
|
|
// are case-insensitive, but we try to display the actual name
|
|
|
|
// when we know it.)
|
|
|
|
var sub = exports.get_sub(stream_name);
|
|
|
|
if (sub === undefined) {
|
|
|
|
return stream_name;
|
|
|
|
}
|
|
|
|
return sub.name;
|
|
|
|
};
|
|
|
|
|
2013-09-16 22:26:53 +02:00
|
|
|
exports.set_subscribers = function (sub, emails) {
|
2013-09-16 23:40:57 +02:00
|
|
|
sub.subscribers = Dict.from_array(emails || [], {fold_case: true});
|
2013-09-16 22:26:53 +02:00
|
|
|
};
|
|
|
|
|
2013-09-07 03:24:12 +02:00
|
|
|
// NOTE: If you do anything with the `subscribers` attribute on the stream
|
|
|
|
// properties object, first make sure `is_subscribed` is true (i.e., the local
|
|
|
|
// user is subscribed). Otherwise we don't and can't update the subscribers
|
|
|
|
// list.
|
|
|
|
//
|
|
|
|
// The accessor functions below know to check for that case.
|
|
|
|
|
2013-09-07 02:48:44 +02:00
|
|
|
exports.add_subscriber = function (stream_name, user_email) {
|
|
|
|
var sub = exports.get_sub(stream_name);
|
2013-09-10 23:13:02 +02:00
|
|
|
if (typeof sub === 'undefined' || !sub.subscribed) {
|
2013-09-07 03:10:08 +02:00
|
|
|
// If we're not subscribed, we don't track this, and shouldn't
|
2013-09-10 23:13:02 +02:00
|
|
|
// get these events. Likewise, if we don't know about the stream,
|
|
|
|
// we don't want to track this.
|
2013-09-24 00:13:02 +02:00
|
|
|
blueslip.warn("We got an add_subscriber call for a non-existent or unsubscribed stream.");
|
2013-09-07 03:10:08 +02:00
|
|
|
return;
|
2013-09-07 02:48:44 +02:00
|
|
|
}
|
|
|
|
sub.subscribers.set(user_email, true);
|
|
|
|
};
|
|
|
|
|
|
|
|
exports.remove_subscriber = function (stream_name, user_email) {
|
|
|
|
var sub = exports.get_sub(stream_name);
|
2013-09-10 23:13:02 +02:00
|
|
|
if (typeof sub === 'undefined' || !sub.subscribed) {
|
2013-09-07 03:10:08 +02:00
|
|
|
// If we're not subscribed, we don't track this, and shouldn't
|
2013-09-10 23:13:02 +02:00
|
|
|
// get these events. Likewise, if we don't know about the stream,
|
|
|
|
// we don't want to track this.
|
2013-09-24 00:13:02 +02:00
|
|
|
blueslip.warn("We got a remove_subscriber call for a non-existent or unsubscribed stream.");
|
2013-09-07 02:48:44 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
sub.subscribers.del(user_email);
|
|
|
|
};
|
|
|
|
|
|
|
|
exports.user_is_subscribed = function (stream_name, user_email) {
|
|
|
|
var sub = exports.get_sub(stream_name);
|
2013-09-07 04:22:18 +02:00
|
|
|
if (typeof sub === 'undefined' || !sub.subscribed) {
|
|
|
|
// If we don't know about the stream, or we ourselves are not
|
|
|
|
// subscribed, we can't keep track of the subscriber list in general,
|
|
|
|
// so we return undefined (treated as falsy if not explicitly handled).
|
2013-09-24 00:13:02 +02:00
|
|
|
blueslip.warn("We got a user_is_subscribed call for a non-existent or unsubscribed stream.");
|
2013-09-07 02:48:44 +02:00
|
|
|
return undefined;
|
|
|
|
}
|
|
|
|
return sub.subscribers.has(user_email);
|
|
|
|
};
|
|
|
|
|
2016-10-15 20:17:32 +02:00
|
|
|
exports.create_sub_from_server_data = function (stream_name, attrs) {
|
|
|
|
var sub = exports.get_sub(stream_name);
|
|
|
|
if (sub !== undefined) {
|
|
|
|
// We've already created this subscription, no need to continue.
|
|
|
|
return sub;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!attrs.stream_id) {
|
|
|
|
// fail fast (blueslip.fatal will throw an error on our behalf)
|
|
|
|
blueslip.fatal("We cannot create a sub without a stream_id");
|
|
|
|
return; // this line is never actually reached
|
|
|
|
}
|
|
|
|
|
|
|
|
// Our internal data structure for subscriptions is mostly plain dictionaries,
|
|
|
|
// so we just reuse the attrs that are passed in to us, but we encapsulate how
|
|
|
|
// we handle subscribers.
|
|
|
|
var subscriber_emails = attrs.subscribers;
|
|
|
|
var raw_attrs = _.omit(attrs, 'subscribers');
|
|
|
|
|
|
|
|
sub = _.defaults(raw_attrs, {
|
|
|
|
name: stream_name,
|
|
|
|
render_subscribers: !page_params.is_zephyr_mirror_realm || attrs.invite_only === true,
|
|
|
|
subscribed: true,
|
|
|
|
in_home_view: true,
|
|
|
|
invite_only: false,
|
|
|
|
desktop_notifications: page_params.stream_desktop_notifications_enabled,
|
|
|
|
audible_notifications: page_params.stream_sounds_enabled,
|
|
|
|
description: ''
|
|
|
|
});
|
|
|
|
|
|
|
|
exports.set_subscribers(sub, subscriber_emails);
|
|
|
|
|
|
|
|
if (!sub.color) {
|
|
|
|
var used_colors = exports.get_colors();
|
|
|
|
sub.color = stream_color.pick_color(used_colors);
|
|
|
|
}
|
|
|
|
|
|
|
|
exports.add_sub(stream_name, sub);
|
|
|
|
|
|
|
|
return sub;
|
|
|
|
};
|
|
|
|
|
2013-08-15 21:11:07 +02:00
|
|
|
return exports;
|
|
|
|
|
|
|
|
}());
|
|
|
|
if (typeof module !== 'undefined') {
|
|
|
|
module.exports = stream_data;
|
|
|
|
}
|