mention: Send notifications for @topic wildcard mentions.

This commit completes the notifications part of the @topic
wildcard mention feature.

Notifications are sent to the topic participants for the
@topic wildcard mention.
This commit is contained in:
Prakhar Pratyush 2023-06-07 22:49:33 +05:30 committed by Tim Abbott
parent 67cdf1a7b4
commit 4c9d26ce17
24 changed files with 1033 additions and 33 deletions

View File

@ -29,8 +29,12 @@
{% trans %}You are receiving this because you were personally mentioned.{% endtrans %}<br /> {% trans %}You are receiving this because you were personally mentioned.{% endtrans %}<br />
{% elif mentioned_user_group_name %} {% elif mentioned_user_group_name %}
{% trans %}You are receiving this because @{{ mentioned_user_group_name }} was mentioned.{% endtrans %}<br /> {% trans %}You are receiving this because @{{ mentioned_user_group_name }} was mentioned.{% endtrans %}<br />
{% elif topic_wildcard_mentioned_in_followed_topic %}
{% trans %}You are receiving this because all topic participants were mentioned in #{{ stream_name }} > {{ topic_name }}.{% endtrans %}<br />
{% elif stream_wildcard_mentioned_in_followed_topic %} {% elif stream_wildcard_mentioned_in_followed_topic %}
{% trans %}You are receiving this because you have wildcard mention notifications enabled for topics you follow.{% endtrans %}<br /> {% trans %}You are receiving this because you have wildcard mention notifications enabled for topics you follow.{% endtrans %}<br />
{% elif topic_wildcard_mentioned %}
{% trans %}You are receiving this because all topic participants were mentioned in #{{ stream_name }} > {{ topic_name }}.{% endtrans %}<br />
{% elif stream_wildcard_mentioned %} {% elif stream_wildcard_mentioned %}
{% trans %}You are receiving this because everyone was mentioned in #{{ stream_name }}.{% endtrans %}<br /> {% trans %}You are receiving this because everyone was mentioned in #{{ stream_name }}.{% endtrans %}<br />
{% elif followed_topic_email_notify %} {% elif followed_topic_email_notify %}

View File

@ -25,8 +25,12 @@ See {{ alert_notif_url }} for more details.
{% trans %}You are receiving this because you were personally mentioned.{% endtrans %} {% trans %}You are receiving this because you were personally mentioned.{% endtrans %}
{% elif mentioned_user_group_name %} {% elif mentioned_user_group_name %}
{% trans %}You are receiving this because @{{ mentioned_user_group_name }} was mentioned.{% endtrans %} {% trans %}You are receiving this because @{{ mentioned_user_group_name }} was mentioned.{% endtrans %}
{% elif topic_wildcard_mentioned_in_followed_topic %}
{% trans %}You are receiving this because all topic participants were mentioned in #{{ stream_name }} > {{ topic_name }}.{% endtrans %}
{% elif stream_wildcard_mentioned_in_followed_topic %} {% elif stream_wildcard_mentioned_in_followed_topic %}
{% trans %}You are receiving this because you have wildcard mention notifications enabled for topics you follow.{% endtrans %} {% trans %}You are receiving this because you have wildcard mention notifications enabled for topics you follow.{% endtrans %}
{% elif topic_wildcard_mentioned %}
{% trans %}You are receiving this because all topic participants were mentioned in #{{ stream_name }} > {{ topic_name }}.{% endtrans %}
{% elif stream_wildcard_mentioned %} {% elif stream_wildcard_mentioned %}
{% trans %}You are receiving this because everyone was mentioned in #{{ stream_name }}.{% endtrans %} {% trans %}You are receiving this because everyone was mentioned in #{{ stream_name }}.{% endtrans %}
{% elif followed_topic_email_notify %} {% elif followed_topic_email_notify %}

View File

@ -133,6 +133,7 @@ function parse_with_options({raw_content, helper_config, options}) {
display_text = mention; display_text = mention;
} else { } else {
// Topic Wildcard mention // Topic Wildcard mention
mentioned_wildcard = true;
display_text = "@" + mention; display_text = "@" + mention;
classes = "topic-mention"; classes = "topic-mention";
} }

View File

@ -711,10 +711,10 @@ test("message_flags", () => {
input = "testing this @**all** @**Cordelia, Lear's daughter**"; input = "testing this @**all** @**Cordelia, Lear's daughter**";
message = {topic: "No links here", raw_content: input}; message = {topic: "No links here", raw_content: input};
markdown.apply_markdown(message); markdown.apply_markdown(message);
assert.equal(message.is_me_message, false); assert.equal(message.is_me_message, false);
assert.equal(message.flags.includes("mentioned"), true); assert.equal(message.flags.includes("mentioned"), true);
assert.equal(message.flags.includes("wildcard_mentioned"), true); assert.equal(message.flags.includes("wildcard_mentioned"), true);
input = "test @**everyone**"; input = "test @**everyone**";
message = {topic: "No links here", raw_content: input}; message = {topic: "No links here", raw_content: input};
markdown.apply_markdown(message); markdown.apply_markdown(message);
@ -729,6 +729,13 @@ test("message_flags", () => {
assert.equal(message.flags.includes("wildcard_mentioned"), true); assert.equal(message.flags.includes("wildcard_mentioned"), true);
assert.equal(message.flags.includes("mentioned"), false); assert.equal(message.flags.includes("mentioned"), false);
input = "test @**topic**";
message = {topic: "No links here", raw_content: input};
markdown.apply_markdown(message);
assert.equal(message.is_me_message, false);
assert.equal(message.flags.includes("wildcard_mentioned"), true);
assert.equal(message.flags.includes("mentioned"), false);
input = "test @all"; input = "test @all";
message = {topic: "No links here", raw_content: input}; message = {topic: "No links here", raw_content: input};
markdown.apply_markdown(message); markdown.apply_markdown(message);
@ -741,6 +748,12 @@ test("message_flags", () => {
assert.equal(message.flags.includes("wildcard_mentioned"), false); assert.equal(message.flags.includes("wildcard_mentioned"), false);
assert.equal(message.flags.includes("mentioned"), false); assert.equal(message.flags.includes("mentioned"), false);
input = "test @topic";
message = {topic: "No links here", raw_content: input};
markdown.apply_markdown(message);
assert.equal(message.flags.includes("wildcard_mentioned"), false);
assert.equal(message.flags.includes("mentioned"), false);
input = "test @any"; input = "test @any";
message = {topic: "No links here", raw_content: input}; message = {topic: "No links here", raw_content: input};
markdown.apply_markdown(message); markdown.apply_markdown(message);
@ -783,6 +796,18 @@ test("message_flags", () => {
assert.equal(message.flags.includes("wildcard_mentioned"), false); assert.equal(message.flags.includes("wildcard_mentioned"), false);
assert.equal(message.flags.includes("mentioned"), false); assert.equal(message.flags.includes("mentioned"), false);
input = "test @_**topic**";
message = {topic: "No links here", raw_content: input};
markdown.apply_markdown(message);
assert.equal(message.flags.includes("wildcard_mentioned"), false);
assert.equal(message.flags.includes("mentioned"), false);
input = "> test @**topic**";
message = {topic: "No links here", raw_content: input};
markdown.apply_markdown(message);
assert.equal(message.flags.includes("wildcard_mentioned"), false);
assert.equal(message.flags.includes("mentioned"), false);
input = "test @_*hamletcharacters*"; input = "test @_*hamletcharacters*";
message = {topic: "No links here", raw_content: input}; message = {topic: "No links here", raw_content: input};
markdown.apply_markdown(message); markdown.apply_markdown(message);

View File

@ -258,7 +258,7 @@ def get_mentions_for_message_updates(message_id: int) -> Set[int]:
def update_user_message_flags( def update_user_message_flags(
rendering_result: MessageRenderingResult, ums: Iterable[UserMessage] rendering_result: MessageRenderingResult, ums: Iterable[UserMessage]
) -> None: ) -> None:
wildcard = rendering_result.mentions_stream_wildcard wildcard_mentioned = rendering_result.has_wildcard_mention()
mentioned_ids = rendering_result.mentions_user_ids mentioned_ids = rendering_result.mentions_user_ids
ids_with_alert_words = rendering_result.user_ids_with_alert_words ids_with_alert_words = rendering_result.user_ids_with_alert_words
changed_ums: Set[UserMessage] = set() changed_ums: Set[UserMessage] = set()
@ -280,7 +280,7 @@ def update_user_message_flags(
mentioned = um.user_profile_id in mentioned_ids mentioned = um.user_profile_id in mentioned_ids
update_flag(um, mentioned, UserMessage.flags.mentioned) update_flag(um, mentioned, UserMessage.flags.mentioned)
update_flag(um, wildcard, UserMessage.flags.wildcard_mentioned) update_flag(um, wildcard_mentioned, UserMessage.flags.wildcard_mentioned)
for um in changed_ums: for um in changed_ums:
um.save(update_fields=["flags"]) um.save(update_fields=["flags"])
@ -490,6 +490,15 @@ def do_update_message(
event["stream_wildcard_mention_user_ids"] = [] event["stream_wildcard_mention_user_ids"] = []
event["stream_wildcard_mention_in_followed_topic_user_ids"] = [] event["stream_wildcard_mention_in_followed_topic_user_ids"] = []
if rendering_result.mentions_topic_wildcard:
event["topic_wildcard_mention_user_ids"] = list(info.topic_wildcard_mention_user_ids)
event["topic_wildcard_mention_in_followed_topic_user_ids"] = list(
info.topic_wildcard_mention_in_followed_topic_user_ids
)
else:
event["topic_wildcard_mention_user_ids"] = []
event["topic_wildcard_mention_in_followed_topic_user_ids"] = []
do_update_mobile_push_notification( do_update_mobile_push_notification(
target_message, target_message,
prior_mention_user_ids, prior_mention_user_ids,
@ -1249,7 +1258,7 @@ def check_update_message(
) )
links_for_embed |= rendering_result.links_for_preview links_for_embed |= rendering_result.links_for_preview
if message.is_stream_message() and rendering_result.mentions_stream_wildcard: if message.is_stream_message() and rendering_result.has_wildcard_mention():
stream = access_stream_by_id(user_profile, message.recipient.type_id)[0] stream = access_stream_by_id(user_profile, message.recipient.type_id)[0]
if not wildcard_mention_allowed(message.sender, stream): if not wildcard_mention_allowed(message.sender, stream):
raise JsonableError( raise JsonableError(

View File

@ -609,9 +609,9 @@ def build_message_send_dict(
members = mention_data.get_group_members(group_id) members = mention_data.get_group_members(group_id)
rendering_result.mentions_user_ids.update(members) rendering_result.mentions_user_ids.update(members)
# Only send data to Tornado about stream wildcard mentions if message # Only send data to Tornado about stream or topic wildcard mentions if message
# rendering determined the message had an actual stream wildcard # rendering determined the message had an actual stream or topic wildcard
# mention in it (and not e.g. stream wildcard mention syntax inside a # mention in it (and not e.g. stream or topic wildcard mention syntax inside a
# code block). # code block).
if rendering_result.mentions_stream_wildcard: if rendering_result.mentions_stream_wildcard:
stream_wildcard_mention_user_ids = info.stream_wildcard_mention_user_ids stream_wildcard_mention_user_ids = info.stream_wildcard_mention_user_ids
@ -622,6 +622,14 @@ def build_message_send_dict(
stream_wildcard_mention_user_ids = set() stream_wildcard_mention_user_ids = set()
stream_wildcard_mention_in_followed_topic_user_ids = set() stream_wildcard_mention_in_followed_topic_user_ids = set()
if rendering_result.mentions_topic_wildcard:
topic_wildcard_mention_user_ids = info.topic_wildcard_mention_user_ids
topic_wildcard_mention_in_followed_topic_user_ids = (
info.topic_wildcard_mention_in_followed_topic_user_ids
)
else:
topic_wildcard_mention_user_ids = set()
topic_wildcard_mention_in_followed_topic_user_ids = set()
""" """
Once we have the actual list of mentioned ids from message Once we have the actual list of mentioned ids from message
rendering, we can patch in "default bots" (aka normal bots) rendering, we can patch in "default bots" (aka normal bots)
@ -656,7 +664,9 @@ def build_message_send_dict(
default_bot_user_ids=info.default_bot_user_ids, default_bot_user_ids=info.default_bot_user_ids,
service_bot_tuples=info.service_bot_tuples, service_bot_tuples=info.service_bot_tuples,
all_bot_user_ids=info.all_bot_user_ids, all_bot_user_ids=info.all_bot_user_ids,
topic_wildcard_mention_user_ids=topic_wildcard_mention_user_ids,
stream_wildcard_mention_user_ids=stream_wildcard_mention_user_ids, stream_wildcard_mention_user_ids=stream_wildcard_mention_user_ids,
topic_wildcard_mention_in_followed_topic_user_ids=topic_wildcard_mention_in_followed_topic_user_ids,
stream_wildcard_mention_in_followed_topic_user_ids=stream_wildcard_mention_in_followed_topic_user_ids, stream_wildcard_mention_in_followed_topic_user_ids=stream_wildcard_mention_in_followed_topic_user_ids,
links_for_embed=links_for_embed, links_for_embed=links_for_embed,
widget_content=widget_content_dict, widget_content=widget_content_dict,
@ -680,12 +690,17 @@ def create_user_messages(
mark_as_read_user_ids: Set[int], mark_as_read_user_ids: Set[int],
limit_unread_user_ids: Optional[Set[int]], limit_unread_user_ids: Optional[Set[int]],
scheduled_message_to_self: bool, scheduled_message_to_self: bool,
topic_wildcard_mention_user_ids: Set[int],
topic_wildcard_mention_in_followed_topic_user_ids: Set[int],
) -> List[UserMessageLite]: ) -> List[UserMessageLite]:
# These properties on the Message are set via # These properties on the Message are set via
# render_markdown by code in the Markdown inline patterns # render_markdown by code in the Markdown inline patterns
ids_with_alert_words = rendering_result.user_ids_with_alert_words ids_with_alert_words = rendering_result.user_ids_with_alert_words
sender_id = message.sender.id sender_id = message.sender.id
is_stream_message = message.is_stream_message() is_stream_message = message.is_stream_message()
all_topic_wildcard_mention_user_ids = topic_wildcard_mention_user_ids.union(
topic_wildcard_mention_in_followed_topic_user_ids
)
base_flags = 0 base_flags = 0
if rendering_result.mentions_stream_wildcard: if rendering_result.mentions_stream_wildcard:
@ -732,6 +747,11 @@ def create_user_messages(
flags |= UserMessage.flags.mentioned flags |= UserMessage.flags.mentioned
if user_profile_id in ids_with_alert_words: if user_profile_id in ids_with_alert_words:
flags |= UserMessage.flags.has_alert_word flags |= UserMessage.flags.has_alert_word
if (
rendering_result.mentions_topic_wildcard
and user_profile_id in all_topic_wildcard_mention_user_ids
):
flags |= UserMessage.flags.wildcard_mentioned
if ( if (
user_profile_id in long_term_idle_user_ids user_profile_id in long_term_idle_user_ids
@ -857,6 +877,8 @@ def do_send_messages(
mark_as_read_user_ids=mark_as_read_user_ids, mark_as_read_user_ids=mark_as_read_user_ids,
limit_unread_user_ids=send_request.limit_unread_user_ids, limit_unread_user_ids=send_request.limit_unread_user_ids,
scheduled_message_to_self=scheduled_message_to_self, scheduled_message_to_self=scheduled_message_to_self,
topic_wildcard_mention_user_ids=send_request.topic_wildcard_mention_user_ids,
topic_wildcard_mention_in_followed_topic_user_ids=send_request.topic_wildcard_mention_in_followed_topic_user_ids,
) )
for um in user_messages: for um in user_messages:
@ -953,9 +975,11 @@ def do_send_messages(
pm_mention_email_disabled_user_ids=send_request.pm_mention_email_disabled_user_ids, pm_mention_email_disabled_user_ids=send_request.pm_mention_email_disabled_user_ids,
stream_push_user_ids=send_request.stream_push_user_ids, stream_push_user_ids=send_request.stream_push_user_ids,
stream_email_user_ids=send_request.stream_email_user_ids, stream_email_user_ids=send_request.stream_email_user_ids,
topic_wildcard_mention_user_ids=send_request.topic_wildcard_mention_user_ids,
stream_wildcard_mention_user_ids=send_request.stream_wildcard_mention_user_ids, stream_wildcard_mention_user_ids=send_request.stream_wildcard_mention_user_ids,
followed_topic_push_user_ids=send_request.followed_topic_push_user_ids, followed_topic_push_user_ids=send_request.followed_topic_push_user_ids,
followed_topic_email_user_ids=send_request.followed_topic_email_user_ids, followed_topic_email_user_ids=send_request.followed_topic_email_user_ids,
topic_wildcard_mention_in_followed_topic_user_ids=send_request.topic_wildcard_mention_in_followed_topic_user_ids,
stream_wildcard_mention_in_followed_topic_user_ids=send_request.stream_wildcard_mention_in_followed_topic_user_ids, stream_wildcard_mention_in_followed_topic_user_ids=send_request.stream_wildcard_mention_in_followed_topic_user_ids,
muted_sender_user_ids=send_request.muted_sender_user_ids, muted_sender_user_ids=send_request.muted_sender_user_ids,
all_bot_user_ids=send_request.all_bot_user_ids, all_bot_user_ids=send_request.all_bot_user_ids,
@ -981,9 +1005,13 @@ def do_send_messages(
), ),
stream_push_user_ids=list(send_request.stream_push_user_ids), stream_push_user_ids=list(send_request.stream_push_user_ids),
stream_email_user_ids=list(send_request.stream_email_user_ids), stream_email_user_ids=list(send_request.stream_email_user_ids),
topic_wildcard_mention_user_ids=list(send_request.topic_wildcard_mention_user_ids),
stream_wildcard_mention_user_ids=list(send_request.stream_wildcard_mention_user_ids), stream_wildcard_mention_user_ids=list(send_request.stream_wildcard_mention_user_ids),
followed_topic_push_user_ids=list(send_request.followed_topic_push_user_ids), followed_topic_push_user_ids=list(send_request.followed_topic_push_user_ids),
followed_topic_email_user_ids=list(send_request.followed_topic_email_user_ids), followed_topic_email_user_ids=list(send_request.followed_topic_email_user_ids),
topic_wildcard_mention_in_followed_topic_user_ids=list(
send_request.topic_wildcard_mention_in_followed_topic_user_ids
),
stream_wildcard_mention_in_followed_topic_user_ids=list( stream_wildcard_mention_in_followed_topic_user_ids=list(
send_request.stream_wildcard_mention_in_followed_topic_user_ids send_request.stream_wildcard_mention_in_followed_topic_user_ids
), ),
@ -1522,7 +1550,7 @@ def check_message(
if ( if (
stream is not None stream is not None
and message_send_dict.rendering_result.mentions_stream_wildcard and message_send_dict.rendering_result.has_wildcard_mention()
and not wildcard_mention_allowed(sender, stream) and not wildcard_mention_allowed(sender, stream)
): ):
raise JsonableError( raise JsonableError(

View File

@ -455,14 +455,23 @@ def do_send_missedmessage_events_reply_in_zulip(
for message in missed_messages for message in missed_messages
) )
context.update( mention = (
mention="mentioned" in unique_triggers "mentioned" in unique_triggers
or "topic_wildcard_mentioned" in unique_triggers
or "stream_wildcard_mentioned" in unique_triggers or "stream_wildcard_mentioned" in unique_triggers
or "stream_wildcard_mentioned_in_followed_topic" in unique_triggers, or "topic_wildcard_mentioned_in_followed_topic" in unique_triggers
or "stream_wildcard_mentioned_in_followed_topic" in unique_triggers
)
context.update(
mention=mention,
personal_mentioned=personal_mentioned, personal_mentioned=personal_mentioned,
topic_wildcard_mentioned="topic_wildcard_mentioned" in unique_triggers,
stream_wildcard_mentioned="stream_wildcard_mentioned" in unique_triggers, stream_wildcard_mentioned="stream_wildcard_mentioned" in unique_triggers,
stream_email_notify="stream_email_notify" in unique_triggers, stream_email_notify="stream_email_notify" in unique_triggers,
followed_topic_email_notify="followed_topic_email_notify" in unique_triggers, followed_topic_email_notify="followed_topic_email_notify" in unique_triggers,
topic_wildcard_mentioned_in_followed_topic="topic_wildcard_mentioned_in_followed_topic"
in unique_triggers,
stream_wildcard_mentioned_in_followed_topic="stream_wildcard_mentioned_in_followed_topic" stream_wildcard_mentioned_in_followed_topic="stream_wildcard_mentioned_in_followed_topic"
in unique_triggers, in unique_triggers,
mentioned_user_group_name=mentioned_user_group_name, mentioned_user_group_name=mentioned_user_group_name,
@ -526,10 +535,14 @@ def do_send_missedmessage_events_reply_in_zulip(
{ {
m["message"].sender m["message"].sender
for m in missed_messages for m in missed_messages
if m["trigger"] == NotificationTriggers.MENTION if m["trigger"]
or m["trigger"] == NotificationTriggers.STREAM_WILDCARD_MENTION in [
or m["trigger"] NotificationTriggers.MENTION,
== NotificationTriggers.STREAM_WILDCARD_MENTION_IN_FOLLOWED_TOPIC NotificationTriggers.TOPIC_WILDCARD_MENTION,
NotificationTriggers.STREAM_WILDCARD_MENTION,
NotificationTriggers.TOPIC_WILDCARD_MENTION_IN_FOLLOWED_TOPIC,
NotificationTriggers.STREAM_WILDCARD_MENTION_IN_FOLLOWED_TOPIC,
]
} }
) )
message = missed_messages[0]["message"] message = missed_messages[0]["message"]

View File

@ -128,6 +128,9 @@ class MessageRenderingResult:
user_ids_with_alert_words: Set[int] user_ids_with_alert_words: Set[int]
potential_attachment_path_ids: List[str] potential_attachment_path_ids: List[str]
def has_wildcard_mention(self) -> bool:
return self.mentions_stream_wildcard or self.mentions_topic_wildcard
@dataclass @dataclass
class DbData: class DbData:

View File

@ -158,9 +158,11 @@ class SendMessageRequest:
pm_mention_email_disabled_user_ids: Set[int] pm_mention_email_disabled_user_ids: Set[int]
stream_push_user_ids: Set[int] stream_push_user_ids: Set[int]
stream_email_user_ids: Set[int] stream_email_user_ids: Set[int]
# IDs of users who have followed the topic the message is being sent to, and have the followed topic push notifications setting ON. # IDs of users who have followed the topic the message is being sent to,
# and have the followed topic push notifications setting ON.
followed_topic_push_user_ids: Set[int] followed_topic_push_user_ids: Set[int]
# IDs of users who have followed the topic the message is being sent to, and have the followed topic email notifications setting ON. # IDs of users who have followed the topic the message is being sent to,
# and have the followed topic email notifications setting ON.
followed_topic_email_user_ids: Set[int] followed_topic_email_user_ids: Set[int]
muted_sender_user_ids: Set[int] muted_sender_user_ids: Set[int]
um_eligible_user_ids: Set[int] um_eligible_user_ids: Set[int]
@ -168,8 +170,26 @@ class SendMessageRequest:
default_bot_user_ids: Set[int] default_bot_user_ids: Set[int]
service_bot_tuples: List[Tuple[int, int]] service_bot_tuples: List[Tuple[int, int]]
all_bot_user_ids: Set[int] all_bot_user_ids: Set[int]
# IDs of topic participants who should be notified of topic wildcard mention.
# The 'user_allows_notifications_in_StreamTopic' with 'wildcard_mentions_notify'
# setting ON should return True.
# A user_id can exist in either or both of the 'topic_wildcard_mention_user_ids'
# and 'topic_wildcard_mention_in_followed_topic_user_ids' sets.
topic_wildcard_mention_user_ids: Set[int]
# IDs of users subscribed to the stream who should be notified of
# stream wildcard mention.
# The 'user_allows_notifications_in_StreamTopic' with 'wildcard_mentions_notify'
# setting ON should return True.
# A user_id can exist in either or both of the 'stream_wildcard_mention_user_ids'
# and 'stream_wildcard_mention_in_followed_topic_user_ids' sets.
stream_wildcard_mention_user_ids: Set[int] stream_wildcard_mention_user_ids: Set[int]
# IDs of users who have followed the topic the message (having stream wildcard) is being sent to, and have the followed topic wildcard mentions notify setting ON. # IDs of topic participants who have followed the topic the message
# (having topic wildcard) is being sent to, and have the
# 'followed_topic_wildcard_mentions_notify' setting ON.
topic_wildcard_mention_in_followed_topic_user_ids: Set[int]
# IDs of users who have followed the topic the message
# (having stream wildcard) is being sent to, and have the
# 'followed_topic_wildcard_mentions_notify' setting ON.
stream_wildcard_mention_in_followed_topic_user_ids: Set[int] stream_wildcard_mention_in_followed_topic_user_ids: Set[int]
links_for_embed: Set[str] links_for_embed: Set[str]
widget_content: Optional[Dict[str, Any]] widget_content: Optional[Dict[str, Any]]

View File

@ -15,12 +15,16 @@ class UserMessageNotificationsData:
pm_push_notify: bool pm_push_notify: bool
mention_email_notify: bool mention_email_notify: bool
mention_push_notify: bool mention_push_notify: bool
topic_wildcard_mention_email_notify: bool
topic_wildcard_mention_push_notify: bool
stream_wildcard_mention_email_notify: bool stream_wildcard_mention_email_notify: bool
stream_wildcard_mention_push_notify: bool stream_wildcard_mention_push_notify: bool
stream_push_notify: bool stream_push_notify: bool
stream_email_notify: bool stream_email_notify: bool
followed_topic_push_notify: bool followed_topic_push_notify: bool
followed_topic_email_notify: bool followed_topic_email_notify: bool
topic_wildcard_mention_in_followed_topic_push_notify: bool
topic_wildcard_mention_in_followed_topic_email_notify: bool
stream_wildcard_mention_in_followed_topic_push_notify: bool stream_wildcard_mention_in_followed_topic_push_notify: bool
stream_wildcard_mention_in_followed_topic_email_notify: bool stream_wildcard_mention_in_followed_topic_email_notify: bool
sender_is_muted: bool sender_is_muted: bool
@ -57,9 +61,11 @@ class UserMessageNotificationsData:
pm_mention_email_disabled_user_ids: Set[int], pm_mention_email_disabled_user_ids: Set[int],
stream_push_user_ids: Set[int], stream_push_user_ids: Set[int],
stream_email_user_ids: Set[int], stream_email_user_ids: Set[int],
topic_wildcard_mention_user_ids: Set[int],
stream_wildcard_mention_user_ids: Set[int], stream_wildcard_mention_user_ids: Set[int],
followed_topic_push_user_ids: Set[int], followed_topic_push_user_ids: Set[int],
followed_topic_email_user_ids: Set[int], followed_topic_email_user_ids: Set[int],
topic_wildcard_mention_in_followed_topic_user_ids: Set[int],
stream_wildcard_mention_in_followed_topic_user_ids: Set[int], stream_wildcard_mention_in_followed_topic_user_ids: Set[int],
muted_sender_user_ids: Set[int], muted_sender_user_ids: Set[int],
all_bot_user_ids: Set[int], all_bot_user_ids: Set[int],
@ -70,33 +76,48 @@ class UserMessageNotificationsData:
user_id=user_id, user_id=user_id,
pm_email_notify=False, pm_email_notify=False,
mention_email_notify=False, mention_email_notify=False,
topic_wildcard_mention_email_notify=False,
stream_wildcard_mention_email_notify=False, stream_wildcard_mention_email_notify=False,
pm_push_notify=False, pm_push_notify=False,
mention_push_notify=False, mention_push_notify=False,
topic_wildcard_mention_push_notify=False,
stream_wildcard_mention_push_notify=False, stream_wildcard_mention_push_notify=False,
online_push_enabled=False, online_push_enabled=False,
stream_push_notify=False, stream_push_notify=False,
stream_email_notify=False, stream_email_notify=False,
followed_topic_push_notify=False, followed_topic_push_notify=False,
followed_topic_email_notify=False, followed_topic_email_notify=False,
topic_wildcard_mention_in_followed_topic_push_notify=False,
topic_wildcard_mention_in_followed_topic_email_notify=False,
stream_wildcard_mention_in_followed_topic_push_notify=False, stream_wildcard_mention_in_followed_topic_push_notify=False,
stream_wildcard_mention_in_followed_topic_email_notify=False, stream_wildcard_mention_in_followed_topic_email_notify=False,
sender_is_muted=False, sender_is_muted=False,
disable_external_notifications=False, disable_external_notifications=False,
) )
# `stream_wildcard_mention_user_ids` are those user IDs for whom stream wildcard # `stream_wildcard_mention_user_ids`, `topic_wildcard_mention_user_ids`,
# mentions should obey notification settings of personal mentions. Hence, it isn't an # `stream_wildcard_mention_in_followed_topic_user_ids` and `topic_wildcard_mention_in_followed_topic_user_ids`
# independent notification setting and acts as a wrapper. # are those user IDs for whom stream or topic wildcard mentions should obey notification
# settings for personal mentions. Hence, it isn't an independent notification setting and acts as a wrapper.
pm_email_notify = user_id not in pm_mention_email_disabled_user_ids and private_message pm_email_notify = user_id not in pm_mention_email_disabled_user_ids and private_message
mention_email_notify = ( mention_email_notify = (
user_id not in pm_mention_email_disabled_user_ids and "mentioned" in flags user_id not in pm_mention_email_disabled_user_ids and "mentioned" in flags
) )
topic_wildcard_mention_email_notify = (
user_id in topic_wildcard_mention_user_ids
and user_id not in pm_mention_email_disabled_user_ids
and "wildcard_mentioned" in flags
)
stream_wildcard_mention_email_notify = ( stream_wildcard_mention_email_notify = (
user_id in stream_wildcard_mention_user_ids user_id in stream_wildcard_mention_user_ids
and user_id not in pm_mention_email_disabled_user_ids and user_id not in pm_mention_email_disabled_user_ids
and "wildcard_mentioned" in flags and "wildcard_mentioned" in flags
) )
topic_wildcard_mention_in_followed_topic_email_notify = (
user_id in topic_wildcard_mention_in_followed_topic_user_ids
and user_id not in pm_mention_email_disabled_user_ids
and "wildcard_mentioned" in flags
)
stream_wildcard_mention_in_followed_topic_email_notify = ( stream_wildcard_mention_in_followed_topic_email_notify = (
user_id in stream_wildcard_mention_in_followed_topic_user_ids user_id in stream_wildcard_mention_in_followed_topic_user_ids
and user_id not in pm_mention_email_disabled_user_ids and user_id not in pm_mention_email_disabled_user_ids
@ -107,11 +128,21 @@ class UserMessageNotificationsData:
mention_push_notify = ( mention_push_notify = (
user_id not in pm_mention_push_disabled_user_ids and "mentioned" in flags user_id not in pm_mention_push_disabled_user_ids and "mentioned" in flags
) )
topic_wildcard_mention_push_notify = (
user_id in topic_wildcard_mention_user_ids
and user_id not in pm_mention_push_disabled_user_ids
and "wildcard_mentioned" in flags
)
stream_wildcard_mention_push_notify = ( stream_wildcard_mention_push_notify = (
user_id in stream_wildcard_mention_user_ids user_id in stream_wildcard_mention_user_ids
and user_id not in pm_mention_push_disabled_user_ids and user_id not in pm_mention_push_disabled_user_ids
and "wildcard_mentioned" in flags and "wildcard_mentioned" in flags
) )
topic_wildcard_mention_in_followed_topic_push_notify = (
user_id in topic_wildcard_mention_in_followed_topic_user_ids
and user_id not in pm_mention_push_disabled_user_ids
and "wildcard_mentioned" in flags
)
stream_wildcard_mention_in_followed_topic_push_notify = ( stream_wildcard_mention_in_followed_topic_push_notify = (
user_id in stream_wildcard_mention_in_followed_topic_user_ids user_id in stream_wildcard_mention_in_followed_topic_user_ids
and user_id not in pm_mention_push_disabled_user_ids and user_id not in pm_mention_push_disabled_user_ids
@ -121,15 +152,19 @@ class UserMessageNotificationsData:
user_id=user_id, user_id=user_id,
pm_email_notify=pm_email_notify, pm_email_notify=pm_email_notify,
mention_email_notify=mention_email_notify, mention_email_notify=mention_email_notify,
topic_wildcard_mention_email_notify=topic_wildcard_mention_email_notify,
stream_wildcard_mention_email_notify=stream_wildcard_mention_email_notify, stream_wildcard_mention_email_notify=stream_wildcard_mention_email_notify,
pm_push_notify=pm_push_notify, pm_push_notify=pm_push_notify,
mention_push_notify=mention_push_notify, mention_push_notify=mention_push_notify,
topic_wildcard_mention_push_notify=topic_wildcard_mention_push_notify,
stream_wildcard_mention_push_notify=stream_wildcard_mention_push_notify, stream_wildcard_mention_push_notify=stream_wildcard_mention_push_notify,
online_push_enabled=(user_id in online_push_user_ids), online_push_enabled=(user_id in online_push_user_ids),
stream_push_notify=(user_id in stream_push_user_ids), stream_push_notify=(user_id in stream_push_user_ids),
stream_email_notify=(user_id in stream_email_user_ids), stream_email_notify=(user_id in stream_email_user_ids),
followed_topic_push_notify=(user_id in followed_topic_push_user_ids), followed_topic_push_notify=(user_id in followed_topic_push_user_ids),
followed_topic_email_notify=(user_id in followed_topic_email_user_ids), followed_topic_email_notify=(user_id in followed_topic_email_user_ids),
topic_wildcard_mention_in_followed_topic_push_notify=topic_wildcard_mention_in_followed_topic_push_notify,
topic_wildcard_mention_in_followed_topic_email_notify=topic_wildcard_mention_in_followed_topic_email_notify,
stream_wildcard_mention_in_followed_topic_push_notify=stream_wildcard_mention_in_followed_topic_push_notify, stream_wildcard_mention_in_followed_topic_push_notify=stream_wildcard_mention_in_followed_topic_push_notify,
stream_wildcard_mention_in_followed_topic_email_notify=stream_wildcard_mention_in_followed_topic_email_notify, stream_wildcard_mention_in_followed_topic_email_notify=stream_wildcard_mention_in_followed_topic_email_notify,
sender_is_muted=(user_id in muted_sender_user_ids), sender_is_muted=(user_id in muted_sender_user_ids),
@ -177,8 +212,12 @@ class UserMessageNotificationsData:
return NotificationTriggers.PRIVATE_MESSAGE return NotificationTriggers.PRIVATE_MESSAGE
elif self.mention_push_notify: elif self.mention_push_notify:
return NotificationTriggers.MENTION return NotificationTriggers.MENTION
elif self.topic_wildcard_mention_in_followed_topic_push_notify:
return NotificationTriggers.TOPIC_WILDCARD_MENTION_IN_FOLLOWED_TOPIC
elif self.stream_wildcard_mention_in_followed_topic_push_notify: elif self.stream_wildcard_mention_in_followed_topic_push_notify:
return NotificationTriggers.STREAM_WILDCARD_MENTION_IN_FOLLOWED_TOPIC return NotificationTriggers.STREAM_WILDCARD_MENTION_IN_FOLLOWED_TOPIC
elif self.topic_wildcard_mention_push_notify:
return NotificationTriggers.TOPIC_WILDCARD_MENTION
elif self.stream_wildcard_mention_push_notify: elif self.stream_wildcard_mention_push_notify:
return NotificationTriggers.STREAM_WILDCARD_MENTION return NotificationTriggers.STREAM_WILDCARD_MENTION
elif self.followed_topic_push_notify: elif self.followed_topic_push_notify:
@ -205,8 +244,12 @@ class UserMessageNotificationsData:
return NotificationTriggers.PRIVATE_MESSAGE return NotificationTriggers.PRIVATE_MESSAGE
elif self.mention_email_notify: elif self.mention_email_notify:
return NotificationTriggers.MENTION return NotificationTriggers.MENTION
elif self.topic_wildcard_mention_in_followed_topic_email_notify:
return NotificationTriggers.TOPIC_WILDCARD_MENTION_IN_FOLLOWED_TOPIC
elif self.stream_wildcard_mention_in_followed_topic_email_notify: elif self.stream_wildcard_mention_in_followed_topic_email_notify:
return NotificationTriggers.STREAM_WILDCARD_MENTION_IN_FOLLOWED_TOPIC return NotificationTriggers.STREAM_WILDCARD_MENTION_IN_FOLLOWED_TOPIC
elif self.topic_wildcard_mention_email_notify:
return NotificationTriggers.TOPIC_WILDCARD_MENTION
elif self.stream_wildcard_mention_email_notify: elif self.stream_wildcard_mention_email_notify:
return NotificationTriggers.STREAM_WILDCARD_MENTION return NotificationTriggers.STREAM_WILDCARD_MENTION
elif self.followed_topic_email_notify: elif self.followed_topic_email_notify:

View File

@ -672,11 +672,18 @@ def get_gcm_alert(
return f"{sender_str} mentioned you in #{display_recipient}" return f"{sender_str} mentioned you in #{display_recipient}"
else: else:
return f"{sender_str} mentioned @{mentioned_user_group_name} in #{display_recipient}" return f"{sender_str} mentioned @{mentioned_user_group_name} in #{display_recipient}"
elif (
message.is_stream_message()
and trigger == NotificationTriggers.TOPIC_WILDCARD_MENTION_IN_FOLLOWED_TOPIC
):
return "TODO - 2"
elif ( elif (
message.is_stream_message() message.is_stream_message()
and trigger == NotificationTriggers.STREAM_WILDCARD_MENTION_IN_FOLLOWED_TOPIC and trigger == NotificationTriggers.STREAM_WILDCARD_MENTION_IN_FOLLOWED_TOPIC
): ):
return "TODO" return "TODO"
elif message.is_stream_message() and trigger == NotificationTriggers.TOPIC_WILDCARD_MENTION:
return f"{sender_str} mentioned all topic participants in #{display_recipient} > {message.topic_name()}"
elif message.is_stream_message() and trigger == NotificationTriggers.STREAM_WILDCARD_MENTION: elif message.is_stream_message() and trigger == NotificationTriggers.STREAM_WILDCARD_MENTION:
return f"{sender_str} mentioned everyone in #{display_recipient}" return f"{sender_str} mentioned everyone in #{display_recipient}"
else: else:
@ -842,8 +849,14 @@ def get_apns_alert_subtitle(
) )
else: else:
return _("{full_name} mentioned you:").format(full_name=message.sender.full_name) return _("{full_name} mentioned you:").format(full_name=message.sender.full_name)
elif trigger == NotificationTriggers.TOPIC_WILDCARD_MENTION_IN_FOLLOWED_TOPIC:
return _("TODO - 2")
elif trigger == NotificationTriggers.STREAM_WILDCARD_MENTION_IN_FOLLOWED_TOPIC: elif trigger == NotificationTriggers.STREAM_WILDCARD_MENTION_IN_FOLLOWED_TOPIC:
return _("TODO") return _("TODO")
elif trigger == NotificationTriggers.TOPIC_WILDCARD_MENTION:
return _("{full_name} mentioned all topic participants:").format(
full_name=message.sender.full_name
)
elif trigger == NotificationTriggers.STREAM_WILDCARD_MENTION: elif trigger == NotificationTriggers.STREAM_WILDCARD_MENTION:
return _("{full_name} mentioned everyone:").format(full_name=message.sender.full_name) return _("{full_name} mentioned everyone:").format(full_name=message.sender.full_name)
elif message.recipient.type == Recipient.PERSONAL: elif message.recipient.type == Recipient.PERSONAL:

View File

@ -1704,6 +1704,12 @@ Output:
pm_push_notify=kwargs.get("pm_push_notify", False), pm_push_notify=kwargs.get("pm_push_notify", False),
mention_email_notify=kwargs.get("mention_email_notify", False), mention_email_notify=kwargs.get("mention_email_notify", False),
mention_push_notify=kwargs.get("mention_push_notify", False), mention_push_notify=kwargs.get("mention_push_notify", False),
topic_wildcard_mention_email_notify=kwargs.get(
"topic_wildcard_mention_email_notify", False
),
topic_wildcard_mention_push_notify=kwargs.get(
"topic_wildcard_mention_push_notify", False
),
stream_wildcard_mention_email_notify=kwargs.get( stream_wildcard_mention_email_notify=kwargs.get(
"stream_wildcard_mention_email_notify", False "stream_wildcard_mention_email_notify", False
), ),
@ -1714,6 +1720,12 @@ Output:
stream_push_notify=kwargs.get("stream_push_notify", False), stream_push_notify=kwargs.get("stream_push_notify", False),
followed_topic_email_notify=kwargs.get("followed_topic_email_notify", False), followed_topic_email_notify=kwargs.get("followed_topic_email_notify", False),
followed_topic_push_notify=kwargs.get("followed_topic_push_notify", False), followed_topic_push_notify=kwargs.get("followed_topic_push_notify", False),
topic_wildcard_mention_in_followed_topic_email_notify=kwargs.get(
"topic_wildcard_mention_in_followed_topic_email_notify", False
),
topic_wildcard_mention_in_followed_topic_push_notify=kwargs.get(
"topic_wildcard_mention_in_followed_topic_push_notify", False
),
stream_wildcard_mention_in_followed_topic_email_notify=kwargs.get( stream_wildcard_mention_in_followed_topic_email_notify=kwargs.get(
"stream_wildcard_mention_in_followed_topic_email_notify", False "stream_wildcard_mention_in_followed_topic_email_notify", False
), ),

View File

@ -26,9 +26,14 @@ class Migration(migrations.Migration):
choices=[ choices=[
("private_message", "Private message"), ("private_message", "Private message"),
("mentioned", "Mention"), ("mentioned", "Mention"),
("topic_wildcard_mentioned", "Topic wildcard mention"),
("stream_wildcard_mentioned", "Stream wildcard mention"), ("stream_wildcard_mentioned", "Stream wildcard mention"),
("stream_email_notify", "Stream notifications enabled"), ("stream_email_notify", "Stream notifications enabled"),
("followed_topic_email_notify", "Followed topic notifications enabled"), ("followed_topic_email_notify", "Followed topic notifications enabled"),
(
"topic_wildcard_mentioned_in_followed_topic",
"Topic wildcard mention in followed topic",
),
( (
"stream_wildcard_mentioned_in_followed_topic", "stream_wildcard_mentioned_in_followed_topic",
"Stream wildcard mention in followed topic", "Stream wildcard mention in followed topic",

View File

@ -4268,11 +4268,13 @@ class NotificationTriggers:
# "private_message" is for 1:1 direct messages as well as huddles # "private_message" is for 1:1 direct messages as well as huddles
PRIVATE_MESSAGE = "private_message" PRIVATE_MESSAGE = "private_message"
MENTION = "mentioned" MENTION = "mentioned"
TOPIC_WILDCARD_MENTION = "topic_wildcard_mentioned"
STREAM_WILDCARD_MENTION = "stream_wildcard_mentioned" STREAM_WILDCARD_MENTION = "stream_wildcard_mentioned"
STREAM_PUSH = "stream_push_notify" STREAM_PUSH = "stream_push_notify"
STREAM_EMAIL = "stream_email_notify" STREAM_EMAIL = "stream_email_notify"
FOLLOWED_TOPIC_PUSH = "followed_topic_push_notify" FOLLOWED_TOPIC_PUSH = "followed_topic_push_notify"
FOLLOWED_TOPIC_EMAIL = "followed_topic_email_notify" FOLLOWED_TOPIC_EMAIL = "followed_topic_email_notify"
TOPIC_WILDCARD_MENTION_IN_FOLLOWED_TOPIC = "topic_wildcard_mentioned_in_followed_topic"
STREAM_WILDCARD_MENTION_IN_FOLLOWED_TOPIC = "stream_wildcard_mentioned_in_followed_topic" STREAM_WILDCARD_MENTION_IN_FOLLOWED_TOPIC = "stream_wildcard_mentioned_in_followed_topic"
@ -4289,9 +4291,14 @@ class ScheduledMessageNotificationEmail(models.Model):
EMAIL_NOTIFICATION_TRIGGER_CHOICES = [ EMAIL_NOTIFICATION_TRIGGER_CHOICES = [
(NotificationTriggers.PRIVATE_MESSAGE, "Private message"), (NotificationTriggers.PRIVATE_MESSAGE, "Private message"),
(NotificationTriggers.MENTION, "Mention"), (NotificationTriggers.MENTION, "Mention"),
(NotificationTriggers.TOPIC_WILDCARD_MENTION, "Topic wildcard mention"),
(NotificationTriggers.STREAM_WILDCARD_MENTION, "Stream wildcard mention"), (NotificationTriggers.STREAM_WILDCARD_MENTION, "Stream wildcard mention"),
(NotificationTriggers.STREAM_EMAIL, "Stream notifications enabled"), (NotificationTriggers.STREAM_EMAIL, "Stream notifications enabled"),
(NotificationTriggers.FOLLOWED_TOPIC_EMAIL, "Followed topic notifications enabled"), (NotificationTriggers.FOLLOWED_TOPIC_EMAIL, "Followed topic notifications enabled"),
(
NotificationTriggers.TOPIC_WILDCARD_MENTION_IN_FOLLOWED_TOPIC,
"Topic wildcard mention in followed topic",
),
( (
NotificationTriggers.STREAM_WILDCARD_MENTION_IN_FOLLOWED_TOPIC, NotificationTriggers.STREAM_WILDCARD_MENTION_IN_FOLLOWED_TOPIC,
"Stream wildcard mention in followed topic", "Stream wildcard mention in followed topic",

View File

@ -705,6 +705,47 @@ class TestMissedMessages(ZulipTestCase):
trigger="mentioned", trigger="mentioned",
) )
def _extra_context_in_missed_stream_messages_topic_wildcard_mention_in_followed_topic(
self, send_as_user: bool, show_message_content: bool = True
) -> None:
for i in range(1, 6):
self.send_stream_message(self.example_user("othello"), "Denmark", content=str(i))
self.send_stream_message(self.example_user("othello"), "Denmark", "11", topic_name="test2")
msg_id = self.send_stream_message(self.example_user("othello"), "Denmark", "@**topic**")
if show_message_content:
verify_body_include = [
"Othello, the Moor of Venice: > 1 > 2 > 3 > 4 > 5 > @**topic** -- ",
"You are receiving this because all topic participants were mentioned in #Denmark > test.",
]
email_subject = "#Denmark > test"
verify_body_does_not_include: List[str] = []
else:
# Test in case if message content in missed email message are disabled.
verify_body_include = [
"This email does not include message content because you have disabled message ",
"http://zulip.testserver/help/pm-mention-alert-notifications ",
"View or reply in Zulip Dev Zulip",
" Manage email preferences: http://zulip.testserver/#settings/notifications",
]
email_subject = "New messages"
verify_body_does_not_include = [
"Othello, the Moor of Venice",
"1 2 3 4 5 @**topic**",
"private",
"group",
"Reply to this email directly, or view it in Zulip Dev Zulip",
]
self._test_cases(
msg_id,
verify_body_include,
email_subject,
send_as_user,
show_message_content=show_message_content,
verify_body_does_not_include=verify_body_does_not_include,
trigger="topic_wildcard_mentioned_in_followed_topic",
)
def _extra_context_in_missed_stream_messages_stream_wildcard_mention_in_followed_topic( def _extra_context_in_missed_stream_messages_stream_wildcard_mention_in_followed_topic(
self, send_as_user: bool, show_message_content: bool = True self, send_as_user: bool, show_message_content: bool = True
) -> None: ) -> None:
@ -730,6 +771,7 @@ class TestMissedMessages(ZulipTestCase):
] ]
email_subject = "New messages" email_subject = "New messages"
verify_body_does_not_include = [ verify_body_does_not_include = [
"Denmark > test",
"Othello, the Moor of Venice", "Othello, the Moor of Venice",
"1 2 3 4 5 @**all**", "1 2 3 4 5 @**all**",
"private", "private",
@ -746,6 +788,47 @@ class TestMissedMessages(ZulipTestCase):
trigger="stream_wildcard_mentioned_in_followed_topic", trigger="stream_wildcard_mentioned_in_followed_topic",
) )
def _extra_context_in_missed_stream_messages_topic_wildcard_mention(
self, send_as_user: bool, show_message_content: bool = True
) -> None:
for i in range(1, 6):
self.send_stream_message(self.example_user("othello"), "Denmark", content=str(i))
self.send_stream_message(self.example_user("othello"), "Denmark", "11", topic_name="test2")
msg_id = self.send_stream_message(self.example_user("othello"), "denmark", "@**topic**")
if show_message_content:
verify_body_include = [
"Othello, the Moor of Venice: > 1 > 2 > 3 > 4 > 5 > @**topic** -- ",
"You are receiving this because all topic participants were mentioned in #Denmark > test.",
]
email_subject = "#Denmark > test"
verify_body_does_not_include: List[str] = []
else:
# Test in case if message content in missed email message are disabled.
verify_body_include = [
"This email does not include message content because you have disabled message ",
"http://zulip.testserver/help/pm-mention-alert-notifications ",
"View or reply in Zulip Dev Zulip",
" Manage email preferences: http://zulip.testserver/#settings/notifications",
]
email_subject = "New messages"
verify_body_does_not_include = [
"Othello, the Moor of Venice",
"1 2 3 4 5 @**topic**",
"private",
"group",
"Reply to this email directly, or view it in Zulip Dev Zulip",
]
self._test_cases(
msg_id,
verify_body_include,
email_subject,
send_as_user,
show_message_content=show_message_content,
verify_body_does_not_include=verify_body_does_not_include,
trigger="topic_wildcard_mentioned",
)
def _extra_context_in_missed_stream_messages_stream_wildcard_mention( def _extra_context_in_missed_stream_messages_stream_wildcard_mention(
self, send_as_user: bool, show_message_content: bool = True self, send_as_user: bool, show_message_content: bool = True
) -> None: ) -> None:
@ -1110,7 +1193,7 @@ class TestMissedMessages(ZulipTestCase):
for text in expected_email_include: for text in expected_email_include:
self.assertIn(text, self.normalize_string(mail.outbox[0].body)) self.assertIn(text, self.normalize_string(mail.outbox[0].body))
def test_user_group_over_stream_wildcard_mention_in_followed_topic_priority(self) -> None: def test_user_group_over_topic_wildcard_mention_in_followed_topic_priority(self) -> None:
hamlet = self.example_user("hamlet") hamlet = self.example_user("hamlet")
cordelia = self.example_user("cordelia") cordelia = self.example_user("cordelia")
othello = self.example_user("othello") othello = self.example_user("othello")
@ -1119,8 +1202,8 @@ class TestMissedMessages(ZulipTestCase):
get_realm("zulip"), "hamlet_and_cordelia", [hamlet, cordelia], acting_user=None get_realm("zulip"), "hamlet_and_cordelia", [hamlet, cordelia], acting_user=None
) )
stream_wildcard_mentioned_in_followed_topic_message_id = self.send_stream_message( topic_wildcard_mentioned_in_followed_topic_message_id = self.send_stream_message(
othello, "Denmark", "@**all**" othello, "Denmark", "@**topic**"
) )
user_group_mentioned_message_id = self.send_stream_message( user_group_mentioned_message_id = self.send_stream_message(
othello, "Denmark", "@*hamlet_and_cordelia*" othello, "Denmark", "@*hamlet_and_cordelia*"
@ -1129,8 +1212,8 @@ class TestMissedMessages(ZulipTestCase):
handle_missedmessage_emails( handle_missedmessage_emails(
hamlet.id, hamlet.id,
{ {
stream_wildcard_mentioned_in_followed_topic_message_id: MissedMessageData( topic_wildcard_mentioned_in_followed_topic_message_id: MissedMessageData(
trigger="stream_wildcard_mentioned_in_followed_topic" trigger="topic_wildcard_mentioned_in_followed_topic"
), ),
user_group_mentioned_message_id: MissedMessageData( user_group_mentioned_message_id: MissedMessageData(
trigger="mentioned", mentioned_user_group_id=hamlet_and_cordelia.id trigger="mentioned", mentioned_user_group_id=hamlet_and_cordelia.id
@ -1139,19 +1222,52 @@ class TestMissedMessages(ZulipTestCase):
) )
expected_email_include = [ expected_email_include = [
"Othello, the Moor of Venice: > @**all** > @*hamlet_and_cordelia* -- ", "Othello, the Moor of Venice: > @**topic** > @*hamlet_and_cordelia* -- ",
"You are receiving this because @hamlet_and_cordelia was mentioned.", "You are receiving this because @hamlet_and_cordelia was mentioned.",
] ]
for text in expected_email_include: for text in expected_email_include:
self.assertIn(text, self.normalize_string(mail.outbox[0].body)) self.assertIn(text, self.normalize_string(mail.outbox[0].body))
def test_stream_wildcard_in_followed_topic_over_stream_wildcard_mention_priority(self) -> None: def test_topic_wildcard_in_followed_topic_over_stream_wildcard_mention_in_followed_topic_priority(
self,
) -> None:
hamlet = self.example_user("hamlet") hamlet = self.example_user("hamlet")
othello = self.example_user("othello") othello = self.example_user("othello")
stream_wildcard_mentioned_message_id = self.send_stream_message( stream_wildcard_mentioned_in_followed_topic_message_id = self.send_stream_message(
othello, "Denmark", "@**all**" othello, "Denmark", "@**stream**"
)
topic_wildcard_mentioned_in_followed_topic_message_id = self.send_stream_message(
othello, "Denmark", "@**topic**"
)
handle_missedmessage_emails(
hamlet.id,
{
stream_wildcard_mentioned_in_followed_topic_message_id: MissedMessageData(
trigger="stream_wildcard_mentioned_in_followed_topic"
),
topic_wildcard_mentioned_in_followed_topic_message_id: MissedMessageData(
trigger="topic_wildcard_mentioned_in_followed_topic"
),
},
)
expected_email_include = [
"Othello, the Moor of Venice: > @**stream** > @**topic** -- ",
"You are receiving this because all topic participants were mentioned in #Denmark > test.",
]
for text in expected_email_include:
self.assertIn(text, self.normalize_string(mail.outbox[0].body))
def test_stream_wildcard_in_followed_topic_over_topic_wildcard_mention_priority(self) -> None:
hamlet = self.example_user("hamlet")
othello = self.example_user("othello")
topic_wildcard_mentioned_message_id = self.send_stream_message(
othello, "Denmark", "@**topic**"
) )
stream_wildcard_mentioned_in_followed_topic_message_id = self.send_stream_message( stream_wildcard_mentioned_in_followed_topic_message_id = self.send_stream_message(
othello, "Denmark", "@**all**" othello, "Denmark", "@**all**"
@ -1160,8 +1276,8 @@ class TestMissedMessages(ZulipTestCase):
handle_missedmessage_emails( handle_missedmessage_emails(
hamlet.id, hamlet.id,
{ {
stream_wildcard_mentioned_message_id: MissedMessageData( topic_wildcard_mentioned_message_id: MissedMessageData(
trigger="stream_wildcard_mentioned" trigger="topic_wildcard_mentioned"
), ),
stream_wildcard_mentioned_in_followed_topic_message_id: MissedMessageData( stream_wildcard_mentioned_in_followed_topic_message_id: MissedMessageData(
trigger="stream_wildcard_mentioned_in_followed_topic" trigger="stream_wildcard_mentioned_in_followed_topic"
@ -1170,13 +1286,44 @@ class TestMissedMessages(ZulipTestCase):
) )
expected_email_include = [ expected_email_include = [
"Othello, the Moor of Venice: > @**all** > @**all** -- ", "Othello, the Moor of Venice: > @**topic** > @**all** -- ",
"You are receiving this because you have wildcard mention notifications enabled for topics you follow.", "You are receiving this because you have wildcard mention notifications enabled for topics you follow.",
] ]
for text in expected_email_include: for text in expected_email_include:
self.assertIn(text, self.normalize_string(mail.outbox[0].body)) self.assertIn(text, self.normalize_string(mail.outbox[0].body))
def test_topic_wildcard_over_stream_wildcard_mention_priority(self) -> None:
hamlet = self.example_user("hamlet")
othello = self.example_user("othello")
stream_wildcard_mentioned_message_id = self.send_stream_message(
othello, "Denmark", "@**all**"
)
topic_wildcard_mentioned_message_id = self.send_stream_message(
othello, "Denmark", "@**topic**"
)
handle_missedmessage_emails(
hamlet.id,
{
stream_wildcard_mentioned_message_id: MissedMessageData(
trigger="stream_wildcard_mentioned"
),
topic_wildcard_mentioned_message_id: MissedMessageData(
trigger="topic_wildcard_mentioned"
),
},
)
expected_email_include = [
"Othello, the Moor of Venice: > @**all** > @**topic** -- ",
"You are receiving this because all topic participants were mentioned in #Denmark > test.",
]
for text in expected_email_include:
self.assertIn(text, self.normalize_string(mail.outbox[0].body))
def test_stream_wildcard_mention_over_followed_topic_notify_priority(self) -> None: def test_stream_wildcard_mention_over_followed_topic_notify_priority(self) -> None:
hamlet = self.example_user("hamlet") hamlet = self.example_user("hamlet")
othello = self.example_user("othello") othello = self.example_user("othello")
@ -1316,10 +1463,18 @@ class TestMissedMessages(ZulipTestCase):
) )
self._extra_context_in_missed_stream_messages_mention(False, show_message_content=False) self._extra_context_in_missed_stream_messages_mention(False, show_message_content=False)
mail.outbox = [] mail.outbox = []
self._extra_context_in_missed_stream_messages_topic_wildcard_mention_in_followed_topic(
False, show_message_content=False
)
mail.outbox = []
self._extra_context_in_missed_stream_messages_stream_wildcard_mention_in_followed_topic( self._extra_context_in_missed_stream_messages_stream_wildcard_mention_in_followed_topic(
False, show_message_content=False False, show_message_content=False
) )
mail.outbox = [] mail.outbox = []
self._extra_context_in_missed_stream_messages_topic_wildcard_mention(
False, show_message_content=False
)
mail.outbox = []
self._extra_context_in_missed_stream_messages_stream_wildcard_mention( self._extra_context_in_missed_stream_messages_stream_wildcard_mention(
False, show_message_content=False False, show_message_content=False
) )
@ -1337,6 +1492,19 @@ class TestMissedMessages(ZulipTestCase):
def test_extra_context_in_missed_stream_messages(self) -> None: def test_extra_context_in_missed_stream_messages(self) -> None:
self._extra_context_in_missed_stream_messages_mention(False) self._extra_context_in_missed_stream_messages_mention(False)
@override_settings(SEND_MISSED_MESSAGE_EMAILS_AS_USER=True)
def test_extra_context_in_missed_stream_messages_as_user_topic_wildcard_in_followed_topic(
self,
) -> None:
self._extra_context_in_missed_stream_messages_topic_wildcard_mention_in_followed_topic(True)
def test_extra_context_in_missed_stream_messages_topic_wildcard_in_followed_topic(
self,
) -> None:
self._extra_context_in_missed_stream_messages_topic_wildcard_mention_in_followed_topic(
False
)
@override_settings(SEND_MISSED_MESSAGE_EMAILS_AS_USER=True) @override_settings(SEND_MISSED_MESSAGE_EMAILS_AS_USER=True)
def test_extra_context_in_missed_stream_messages_as_user_stream_wildcard_in_followed_topic( def test_extra_context_in_missed_stream_messages_as_user_stream_wildcard_in_followed_topic(
self, self,
@ -1352,6 +1520,13 @@ class TestMissedMessages(ZulipTestCase):
False False
) )
@override_settings(SEND_MISSED_MESSAGE_EMAILS_AS_USER=True)
def test_extra_context_in_missed_stream_messages_as_user_topic_wildcard(self) -> None:
self._extra_context_in_missed_stream_messages_topic_wildcard_mention(True)
def test_extra_context_in_missed_stream_messages_topic_wildcard(self) -> None:
self._extra_context_in_missed_stream_messages_topic_wildcard_mention(False)
@override_settings(SEND_MISSED_MESSAGE_EMAILS_AS_USER=True) @override_settings(SEND_MISSED_MESSAGE_EMAILS_AS_USER=True)
def test_extra_context_in_missed_stream_messages_as_user_stream_wildcard(self) -> None: def test_extra_context_in_missed_stream_messages_as_user_stream_wildcard(self) -> None:
self._extra_context_in_missed_stream_messages_stream_wildcard_mention(True) self._extra_context_in_missed_stream_messages_stream_wildcard_mention(True)

View File

@ -298,6 +298,69 @@ class MissedMessageHookTest(ZulipTestCase):
already_notified={"email_notified": True, "push_notified": False}, already_notified={"email_notified": True, "push_notified": False},
) )
def test_topic_wildcard_mention(self) -> None:
# By default, topic wildcard mentions should send notifications, just like regular mentions
self.send_stream_message(self.user_profile, "Denmark")
msg_id = self.send_stream_message(self.iago, "Denmark", content="@**topic** what's up?")
with mock.patch("zerver.tornado.event_queue.maybe_enqueue_notifications") as mock_enqueue:
missedmessage_hook(self.user_profile.id, self.client_descriptor, True)
mock_enqueue.assert_called()
args_dict = mock_enqueue.call_args_list[1][1]
self.assert_maybe_enqueue_notifications_call_args(
args_dict=args_dict,
message_id=msg_id,
user_id=self.user_profile.id,
topic_wildcard_mention_email_notify=True,
topic_wildcard_mention_push_notify=True,
already_notified={"email_notified": True, "push_notified": True},
)
def test_topic_wildcard_mention_in_muted_stream(self) -> None:
# Topic wildcard mentions in muted streams don't notify.
self.change_subscription_properties({"is_muted": True})
self.send_stream_message(self.user_profile, "Denmark")
msg_id = self.send_stream_message(self.iago, "Denmark", content="@**topic** what's up?")
with mock.patch("zerver.tornado.event_queue.maybe_enqueue_notifications") as mock_enqueue:
missedmessage_hook(self.user_profile.id, self.client_descriptor, True)
mock_enqueue.assert_called()
args_dict = mock_enqueue.call_args_list[1][1]
self.assert_maybe_enqueue_notifications_call_args(
args_dict=args_dict,
message_id=msg_id,
user_id=self.user_profile.id,
topic_wildcard_mention_email_notify=False,
topic_wildcard_mention_push_notify=False,
already_notified={"email_notified": False, "push_notified": False},
)
def test_topic_wildcard_mention_in_muted_topic(self) -> None:
# Topic wildcard mentions in muted topics don't notify.
do_set_user_topic_visibility_policy(
self.user_profile,
get_stream("Denmark", self.user_profile.realm),
"mutingtest",
visibility_policy=UserTopic.VisibilityPolicy.MUTED,
)
self.send_stream_message(self.user_profile, "Denmark")
msg_id = self.send_stream_message(
self.iago, "Denmark", topic_name="mutingtest", content="@**topic** what's up?"
)
with mock.patch("zerver.tornado.event_queue.maybe_enqueue_notifications") as mock_enqueue:
missedmessage_hook(self.user_profile.id, self.client_descriptor, True)
mock_enqueue.assert_called()
args_dict = mock_enqueue.call_args_list[1][1]
self.assert_maybe_enqueue_notifications_call_args(
args_dict=args_dict,
message_id=msg_id,
user_id=self.user_profile.id,
topic_wildcard_mention_email_notify=False,
topic_wildcard_mention_push_notify=False,
already_notified={"email_notified": False, "push_notified": False},
)
def test_stream_wildcard_mention(self) -> None: def test_stream_wildcard_mention(self) -> None:
# By default, stream wildcard mentions should send notifications, just like regular mentions # By default, stream wildcard mentions should send notifications, just like regular mentions
msg_id = self.send_stream_message(self.iago, "Denmark", content="@**all** what's up?") msg_id = self.send_stream_message(self.iago, "Denmark", content="@**all** what's up?")
@ -842,6 +905,42 @@ class MissedMessageHookTest(ZulipTestCase):
already_notified={"email_notified": True, "push_notified": False}, already_notified={"email_notified": True, "push_notified": False},
) )
def test_topic_wildcard_mention_in_followed_topic_notify(self) -> None:
do_change_user_setting(
self.user_profile, "wildcard_mentions_notify", False, acting_user=None
)
do_change_user_setting(
self.user_profile, "enable_followed_topic_email_notifications", False, acting_user=None
)
do_change_user_setting(
self.user_profile, "enable_followed_topic_push_notifications", False, acting_user=None
)
# By default, wildcard mentions in followed topics should send notifications, just like regular mentions.
do_set_user_topic_visibility_policy(
self.user_profile,
get_stream("Denmark", self.user_profile.realm),
"followed_topic_test",
visibility_policy=UserTopic.VisibilityPolicy.FOLLOWED,
)
self.send_stream_message(self.user_profile, "Denmark", topic_name="followed_topic_test")
msg_id = self.send_stream_message(
self.iago, "Denmark", content="@**topic** what's up?", topic_name="followed_topic_test"
)
with mock.patch("zerver.tornado.event_queue.maybe_enqueue_notifications") as mock_enqueue:
missedmessage_hook(self.user_profile.id, self.client_descriptor, True)
mock_enqueue.assert_called()
args_dict = mock_enqueue.call_args_list[1][1]
self.assert_maybe_enqueue_notifications_call_args(
args_dict=args_dict,
message_id=msg_id,
user_id=self.user_profile.id,
topic_wildcard_mention_in_followed_topic_email_notify=True,
topic_wildcard_mention_in_followed_topic_push_notify=True,
already_notified={"email_notified": True, "push_notified": True},
)
def test_stream_wildcard_mention_in_followed_topic_notify(self) -> None: def test_stream_wildcard_mention_in_followed_topic_notify(self) -> None:
do_change_user_setting( do_change_user_setting(
self.user_profile, "wildcard_mentions_notify", False, acting_user=None self.user_profile, "wildcard_mentions_notify", False, acting_user=None
@ -877,6 +976,42 @@ class MissedMessageHookTest(ZulipTestCase):
already_notified={"email_notified": True, "push_notified": True}, already_notified={"email_notified": True, "push_notified": True},
) )
def test_topic_wildcard_mention_in_followed_topic_muted_stream(self) -> None:
# By default, topic wildcard mentions in a followed topic with muted stream DO notify.
do_change_user_setting(
self.user_profile, "wildcard_mentions_notify", False, acting_user=None
)
do_change_user_setting(
self.user_profile, "enable_followed_topic_email_notifications", False, acting_user=None
)
do_change_user_setting(
self.user_profile, "enable_followed_topic_push_notifications", False, acting_user=None
)
self.change_subscription_properties({"is_muted": True})
do_set_user_topic_visibility_policy(
self.user_profile,
get_stream("Denmark", self.user_profile.realm),
"test",
visibility_policy=UserTopic.VisibilityPolicy.FOLLOWED,
)
self.send_stream_message(self.user_profile, "Denmark")
msg_id = self.send_stream_message(self.iago, "Denmark", content="@**topic** what's up?")
with mock.patch("zerver.tornado.event_queue.maybe_enqueue_notifications") as mock_enqueue:
missedmessage_hook(self.user_profile.id, self.client_descriptor, True)
mock_enqueue.assert_called()
args_dict = mock_enqueue.call_args_list[1][1]
self.assert_maybe_enqueue_notifications_call_args(
args_dict=args_dict,
message_id=msg_id,
user_id=self.user_profile.id,
topic_wildcard_mention_in_followed_topic_email_notify=True,
topic_wildcard_mention_in_followed_topic_push_notify=True,
already_notified={"email_notified": True, "push_notified": True},
)
def test_stream_wildcard_mention_in_followed_topic_muted_stream(self) -> None: def test_stream_wildcard_mention_in_followed_topic_muted_stream(self) -> None:
# By default, stream wildcard mentions in a followed topic with muted stream DO notify. # By default, stream wildcard mentions in a followed topic with muted stream DO notify.
do_change_user_setting( do_change_user_setting(

View File

@ -456,6 +456,13 @@ class NormalActionsTest(BaseAction):
lambda: self.send_stream_message(self.example_user("cordelia"), "Verona", content), lambda: self.send_stream_message(self.example_user("cordelia"), "Verona", content),
) )
def test_topic_wildcard_mentioned_send_message_events(self) -> None:
for i in range(3):
content = "mentioning... @**topic** hello " + str(i)
self.verify_action(
lambda: self.send_stream_message(self.example_user("cordelia"), "Verona", content),
)
def test_stream_wildcard_mentioned_send_message_events(self) -> None: def test_stream_wildcard_mentioned_send_message_events(self) -> None:
for i in range(3): for i in range(3):
content = "mentioning... @**all** hello " + str(i) content = "mentioning... @**all** hello " + str(i)

View File

@ -2038,6 +2038,58 @@ class EditMessageTest(EditMessageTestCase):
original_topic_state=UserTopic.VisibilityPolicy.UNMUTED, original_topic_state=UserTopic.VisibilityPolicy.UNMUTED,
) )
@mock.patch("zerver.actions.message_edit.send_event")
def test_topic_wildcard_mention_in_followed_topic(
self, mock_send_event: mock.MagicMock
) -> None:
stream_name = "Macbeth"
hamlet = self.example_user("hamlet")
cordelia = self.example_user("cordelia")
self.make_stream(stream_name, history_public_to_subscribers=True)
self.subscribe(hamlet, stream_name)
self.subscribe(cordelia, stream_name)
self.login_user(hamlet)
do_set_user_topic_visibility_policy(
user_profile=hamlet,
stream=get_stream(stream_name, cordelia.realm),
topic="test",
visibility_policy=UserTopic.VisibilityPolicy.FOLLOWED,
)
message_id = self.send_stream_message(hamlet, stream_name, "Hello everyone")
def notify(user_id: int) -> Dict[str, Any]:
return {
"id": user_id,
"flags": ["wildcard_mentioned"],
}
users_to_be_notified = sorted(map(notify, [cordelia.id, hamlet.id]), key=itemgetter("id"))
result = self.client_patch(
f"/json/messages/{message_id}",
{
"content": "Hello @**topic**",
},
)
self.assert_json_success(result)
# Extract the send_event call where event type is 'update_message'.
# Here we assert 'topic_wildcard_mention_in_followed_topic_user_ids'
# has been set properly.
called = False
for call_args in mock_send_event.call_args_list:
(arg_realm, arg_event, arg_notified_users) = call_args[0]
if arg_event["type"] == "update_message":
self.assertEqual(arg_event["type"], "update_message")
self.assertEqual(
arg_event["topic_wildcard_mention_in_followed_topic_user_ids"], [hamlet.id]
)
self.assertEqual(
sorted(arg_notified_users, key=itemgetter("id")), users_to_be_notified
)
called = True
self.assertTrue(called)
@mock.patch("zerver.actions.message_edit.send_event") @mock.patch("zerver.actions.message_edit.send_event")
def test_stream_wildcard_mention_in_followed_topic( def test_stream_wildcard_mention_in_followed_topic(
self, mock_send_event: mock.MagicMock self, mock_send_event: mock.MagicMock
@ -2090,6 +2142,95 @@ class EditMessageTest(EditMessageTestCase):
called = True called = True
self.assertTrue(called) self.assertTrue(called)
@mock.patch("zerver.actions.message_edit.send_event")
def test_topic_wildcard_mention(self, mock_send_event: mock.MagicMock) -> None:
stream_name = "Macbeth"
hamlet = self.example_user("hamlet")
cordelia = self.example_user("cordelia")
self.make_stream(stream_name, history_public_to_subscribers=True)
self.subscribe(hamlet, stream_name)
self.subscribe(cordelia, stream_name)
self.login_user(hamlet)
message_id = self.send_stream_message(hamlet, stream_name, "Hello everyone")
def notify(user_id: int) -> Dict[str, Any]:
return {
"id": user_id,
"flags": ["wildcard_mentioned"],
}
users_to_be_notified = sorted(map(notify, [cordelia.id, hamlet.id]), key=itemgetter("id"))
result = self.client_patch(
f"/json/messages/{message_id}",
{
"content": "Hello @**topic**",
},
)
self.assert_json_success(result)
# Extract the send_event call where event type is 'update_message'.
# Here we assert topic_wildcard_mention_user_ids has been set properly.
called = False
for call_args in mock_send_event.call_args_list:
(arg_realm, arg_event, arg_notified_users) = call_args[0]
if arg_event["type"] == "update_message":
self.assertEqual(arg_event["type"], "update_message")
self.assertEqual(arg_event["topic_wildcard_mention_user_ids"], [hamlet.id])
self.assertEqual(
sorted(arg_notified_users, key=itemgetter("id")), users_to_be_notified
)
called = True
self.assertTrue(called)
def test_topic_wildcard_mention_restrictions_when_editing(self) -> None:
cordelia = self.example_user("cordelia")
shiva = self.example_user("shiva")
self.login("cordelia")
stream_name = "Macbeth"
self.make_stream(stream_name, history_public_to_subscribers=True)
self.subscribe(cordelia, stream_name)
self.subscribe(shiva, stream_name)
message_id = self.send_stream_message(cordelia, stream_name, "Hello everyone")
realm = cordelia.realm
do_set_realm_property(
realm,
"wildcard_mention_policy",
Realm.WILDCARD_MENTION_POLICY_MODERATORS,
acting_user=None,
)
with mock.patch("zerver.lib.message.num_subscribers_for_stream_id", return_value=17):
result = self.client_patch(
"/json/messages/" + str(message_id),
{
"content": "Hello @**topic**",
},
)
self.assert_json_error(
result, "You do not have permission to use wildcard mentions in this stream."
)
with mock.patch("zerver.lib.message.num_subscribers_for_stream_id", return_value=14):
result = self.client_patch(
"/json/messages/" + str(message_id),
{
"content": "Hello @**topic**",
},
)
self.assert_json_success(result)
self.login("shiva")
message_id = self.send_stream_message(shiva, stream_name, "Hi everyone")
with mock.patch("zerver.lib.message.num_subscribers_for_stream_id", return_value=17):
result = self.client_patch(
"/json/messages/" + str(message_id),
{
"content": "Hello @**topic**",
},
)
self.assert_json_success(result)
@mock.patch("zerver.actions.message_edit.send_event") @mock.patch("zerver.actions.message_edit.send_event")
def test_stream_wildcard_mention(self, mock_send_event: mock.MagicMock) -> None: def test_stream_wildcard_mention(self, mock_send_event: mock.MagicMock) -> None:
stream_name = "Macbeth" stream_name = "Macbeth"

View File

@ -398,6 +398,56 @@ class EditMessageSideEffectsTest(ZulipTestCase):
# actual content of these messages.) # actual content of these messages.)
self.assert_length(info["queue_messages"], 2) self.assert_length(info["queue_messages"], 2)
def test_updates_with_topic_wildcard_mention_in_followed_topic(self) -> None:
cordelia = self.example_user("cordelia")
hamlet = self.example_user("hamlet")
self.subscribe(cordelia, "Scotland")
do_change_user_setting(
cordelia, "enable_followed_topic_email_notifications", False, acting_user=None
)
do_change_user_setting(
cordelia, "enable_followed_topic_push_notifications", False, acting_user=None
)
do_change_user_setting(cordelia, "wildcard_mentions_notify", False, acting_user=None)
do_set_user_topic_visibility_policy(
user_profile=cordelia,
stream=get_stream("Scotland", cordelia.realm),
topic="test",
visibility_policy=UserTopic.VisibilityPolicy.FOLLOWED,
)
# Only users who either sent or reacted to messages in the topic
# are considered for @topic mention notifications.
self.send_stream_message(cordelia, "Scotland")
# We will simulate that the user still has an active client,
# but they don't have UserPresence rows, so we will still
# send offline notifications.
original_content = "no mention"
updated_content = "now we mention @**topic**"
notification_message_data = self._send_and_update_message(
original_content,
updated_content,
connected_to_zulip=True,
)
message_id = notification_message_data["message_id"]
info = notification_message_data["info"]
expected_enqueue_kwargs = self.get_maybe_enqueue_notifications_parameters(
user_id=cordelia.id,
acting_user_id=hamlet.id,
message_id=message_id,
topic_wildcard_mention_in_followed_topic_email_notify=True,
topic_wildcard_mention_in_followed_topic_push_notify=True,
already_notified={},
)
self.assertEqual(info["enqueue_kwargs"], expected_enqueue_kwargs)
# messages will get enqueued.
self.assert_length(info["queue_messages"], 2)
def test_updates_with_stream_wildcard_mention_in_followed_topic(self) -> None: def test_updates_with_stream_wildcard_mention_in_followed_topic(self) -> None:
cordelia = self.example_user("cordelia") cordelia = self.example_user("cordelia")
hamlet = self.example_user("hamlet") hamlet = self.example_user("hamlet")
@ -444,6 +494,42 @@ class EditMessageSideEffectsTest(ZulipTestCase):
# messages will get enqueued. # messages will get enqueued.
self.assert_length(info["queue_messages"], 2) self.assert_length(info["queue_messages"], 2)
def test_updates_with_topic_wildcard_mention(self) -> None:
cordelia = self.example_user("cordelia")
hamlet = self.example_user("hamlet")
# Only users who either sent or reacted to messages in the topic
# are considered for @topic mention notifications.
self.subscribe(cordelia, "Scotland")
self.send_stream_message(cordelia, "Scotland")
# We will simulate that the user still has an active client,
# but they don't have UserPresence rows, so we will still
# send offline notifications.
original_content = "no mention"
updated_content = "now we mention @**topic**"
notification_message_data = self._send_and_update_message(
original_content,
updated_content,
connected_to_zulip=True,
)
message_id = notification_message_data["message_id"]
info = notification_message_data["info"]
expected_enqueue_kwargs = self.get_maybe_enqueue_notifications_parameters(
user_id=cordelia.id,
acting_user_id=hamlet.id,
message_id=message_id,
topic_wildcard_mention_email_notify=True,
topic_wildcard_mention_push_notify=True,
already_notified={},
)
self.assertEqual(info["enqueue_kwargs"], expected_enqueue_kwargs)
# messages will get enqueued.
self.assert_length(info["queue_messages"], 2)
def test_updates_with_stream_wildcard_mention(self) -> None: def test_updates_with_stream_wildcard_mention(self) -> None:
cordelia = self.example_user("cordelia") cordelia = self.example_user("cordelia")
hamlet = self.example_user("hamlet") hamlet = self.example_user("hamlet")

View File

@ -1621,6 +1621,105 @@ class StreamMessagesTest(ZulipTestCase):
self.assertEqual(user_message.message.content, content) self.assertEqual(user_message.message.content, content)
self.assertTrue(user_message.flags.mentioned) self.assertTrue(user_message.flags.mentioned)
def send_and_verify_topic_wildcard_mention_message(
self, sender_name: str, test_fails: bool = False, sub_count: int = 16
) -> None:
sender = self.example_user(sender_name)
content = "@**topic** test topic wildcard mention"
with mock.patch("zerver.lib.message.num_subscribers_for_stream_id", return_value=sub_count):
if not test_fails:
msg_id = self.send_stream_message(sender, "test_stream", content)
result = self.api_get(sender, "/api/v1/messages/" + str(msg_id))
self.assert_json_success(result)
else:
with self.assertRaisesRegex(
JsonableError,
"You do not have permission to use wildcard mentions in this stream.",
):
self.send_stream_message(sender, "test_stream", content)
def test_topic_wildcard_mention_restrictions(self) -> None:
cordelia = self.example_user("cordelia")
iago = self.example_user("iago")
polonius = self.example_user("polonius")
shiva = self.example_user("shiva")
realm = cordelia.realm
stream_name = "test_stream"
self.subscribe(cordelia, stream_name)
self.subscribe(iago, stream_name)
self.subscribe(polonius, stream_name)
self.subscribe(shiva, stream_name)
do_set_realm_property(
realm,
"wildcard_mention_policy",
Realm.WILDCARD_MENTION_POLICY_EVERYONE,
acting_user=None,
)
self.send_and_verify_topic_wildcard_mention_message("polonius")
do_set_realm_property(
realm,
"wildcard_mention_policy",
Realm.WILDCARD_MENTION_POLICY_MEMBERS,
acting_user=None,
)
self.send_and_verify_topic_wildcard_mention_message("polonius", test_fails=True)
# There is no restriction on small streams.
self.send_and_verify_topic_wildcard_mention_message("polonius", sub_count=10)
self.send_and_verify_topic_wildcard_mention_message("cordelia")
do_set_realm_property(
realm,
"wildcard_mention_policy",
Realm.WILDCARD_MENTION_POLICY_FULL_MEMBERS,
acting_user=None,
)
do_set_realm_property(realm, "waiting_period_threshold", 10, acting_user=None)
iago.date_joined = timezone_now()
iago.save()
shiva.date_joined = timezone_now()
shiva.save()
cordelia.date_joined = timezone_now()
cordelia.save()
self.send_and_verify_topic_wildcard_mention_message("cordelia", test_fails=True)
self.send_and_verify_topic_wildcard_mention_message("cordelia", sub_count=10)
# Administrators and moderators can use wildcard mentions even if they are new.
self.send_and_verify_topic_wildcard_mention_message("iago")
self.send_and_verify_topic_wildcard_mention_message("shiva")
cordelia.date_joined = timezone_now() - datetime.timedelta(days=11)
cordelia.save()
self.send_and_verify_topic_wildcard_mention_message("cordelia")
do_set_realm_property(
realm,
"wildcard_mention_policy",
Realm.WILDCARD_MENTION_POLICY_MODERATORS,
acting_user=None,
)
self.send_and_verify_topic_wildcard_mention_message("cordelia", test_fails=True)
self.send_and_verify_topic_wildcard_mention_message("cordelia", sub_count=10)
self.send_and_verify_topic_wildcard_mention_message("shiva")
cordelia.date_joined = timezone_now()
cordelia.save()
do_set_realm_property(
realm, "wildcard_mention_policy", Realm.WILDCARD_MENTION_POLICY_ADMINS, acting_user=None
)
self.send_and_verify_topic_wildcard_mention_message("shiva", test_fails=True)
# There is no restriction on small streams.
self.send_and_verify_topic_wildcard_mention_message("shiva", sub_count=10)
self.send_and_verify_topic_wildcard_mention_message("iago")
do_set_realm_property(
realm, "wildcard_mention_policy", Realm.WILDCARD_MENTION_POLICY_NOBODY, acting_user=None
)
self.send_and_verify_topic_wildcard_mention_message("iago", test_fails=True)
self.send_and_verify_topic_wildcard_mention_message("iago", sub_count=10)
def send_and_verify_stream_wildcard_mention_message( def send_and_verify_stream_wildcard_mention_message(
self, sender_name: str, test_fails: bool = False, sub_count: int = 16 self, sender_name: str, test_fails: bool = False, sub_count: int = 16
) -> None: ) -> None:

View File

@ -40,6 +40,16 @@ class TestNotificationData(ZulipTestCase):
) )
self.assertTrue(user_data.is_push_notifiable(acting_user_id=acting_user_id, idle=True)) self.assertTrue(user_data.is_push_notifiable(acting_user_id=acting_user_id, idle=True))
# Topic Wildcard mention
user_data = self.create_user_notifications_data_object(
user_id=user_id, topic_wildcard_mention_push_notify=True
)
self.assertEqual(
user_data.get_push_notification_trigger(acting_user_id=acting_user_id, idle=True),
"topic_wildcard_mentioned",
)
self.assertTrue(user_data.is_push_notifiable(acting_user_id=acting_user_id, idle=True))
# Stream Wildcard mention # Stream Wildcard mention
user_data = self.create_user_notifications_data_object( user_data = self.create_user_notifications_data_object(
user_id=user_id, stream_wildcard_mention_push_notify=True user_id=user_id, stream_wildcard_mention_push_notify=True
@ -70,6 +80,16 @@ class TestNotificationData(ZulipTestCase):
) )
self.assertTrue(user_data.is_push_notifiable(acting_user_id=acting_user_id, idle=True)) self.assertTrue(user_data.is_push_notifiable(acting_user_id=acting_user_id, idle=True))
# Topic wildcard mention in followed topic
user_data = self.create_user_notifications_data_object(
user_id=user_id, topic_wildcard_mention_in_followed_topic_push_notify=True
)
self.assertEqual(
user_data.get_push_notification_trigger(acting_user_id=acting_user_id, idle=True),
"topic_wildcard_mentioned_in_followed_topic",
)
self.assertTrue(user_data.is_push_notifiable(acting_user_id=acting_user_id, idle=True))
# Stream wildcard mention in followed topic # Stream wildcard mention in followed topic
user_data = self.create_user_notifications_data_object( user_data = self.create_user_notifications_data_object(
user_id=user_id, stream_wildcard_mention_in_followed_topic_push_notify=True user_id=user_id, stream_wildcard_mention_in_followed_topic_push_notify=True
@ -108,6 +128,8 @@ class TestNotificationData(ZulipTestCase):
pm_email_notify=True, pm_email_notify=True,
mention_push_notify=True, mention_push_notify=True,
mention_email_notify=True, mention_email_notify=True,
topic_wildcard_mention_push_notify=True,
topic_wildcard_mention_email_notify=True,
stream_wildcard_mention_push_notify=True, stream_wildcard_mention_push_notify=True,
stream_wildcard_mention_email_notify=True, stream_wildcard_mention_email_notify=True,
) )
@ -124,6 +146,8 @@ class TestNotificationData(ZulipTestCase):
pm_email_notify=True, pm_email_notify=True,
mention_push_notify=True, mention_push_notify=True,
mention_email_notify=True, mention_email_notify=True,
topic_wildcard_mention_push_notify=True,
topic_wildcard_mention_email_notify=True,
stream_wildcard_mention_push_notify=True, stream_wildcard_mention_push_notify=True,
stream_wildcard_mention_email_notify=True, stream_wildcard_mention_email_notify=True,
) )
@ -140,6 +164,8 @@ class TestNotificationData(ZulipTestCase):
pm_email_notify=True, pm_email_notify=True,
mention_push_notify=True, mention_push_notify=True,
mention_email_notify=True, mention_email_notify=True,
topic_wildcard_mention_push_notify=True,
topic_wildcard_mention_email_notify=True,
stream_wildcard_mention_push_notify=True, stream_wildcard_mention_push_notify=True,
stream_wildcard_mention_email_notify=True, stream_wildcard_mention_email_notify=True,
disable_external_notifications=True, disable_external_notifications=True,
@ -182,6 +208,16 @@ class TestNotificationData(ZulipTestCase):
) )
self.assertTrue(user_data.is_email_notifiable(acting_user_id=acting_user_id, idle=True)) self.assertTrue(user_data.is_email_notifiable(acting_user_id=acting_user_id, idle=True))
# Topic Wildcard mention
user_data = self.create_user_notifications_data_object(
user_id=user_id, topic_wildcard_mention_email_notify=True
)
self.assertEqual(
user_data.get_email_notification_trigger(acting_user_id=acting_user_id, idle=True),
"topic_wildcard_mentioned",
)
self.assertTrue(user_data.is_email_notifiable(acting_user_id=acting_user_id, idle=True))
# Stream Wildcard mention # Stream Wildcard mention
user_data = self.create_user_notifications_data_object( user_data = self.create_user_notifications_data_object(
user_id=user_id, stream_wildcard_mention_email_notify=True user_id=user_id, stream_wildcard_mention_email_notify=True
@ -212,6 +248,16 @@ class TestNotificationData(ZulipTestCase):
) )
self.assertTrue(user_data.is_email_notifiable(acting_user_id=acting_user_id, idle=True)) self.assertTrue(user_data.is_email_notifiable(acting_user_id=acting_user_id, idle=True))
# Topic wildcard mention in followed topic
user_data = self.create_user_notifications_data_object(
user_id=user_id, topic_wildcard_mention_in_followed_topic_email_notify=True
)
self.assertEqual(
user_data.get_email_notification_trigger(acting_user_id=acting_user_id, idle=True),
"topic_wildcard_mentioned_in_followed_topic",
)
self.assertTrue(user_data.is_email_notifiable(acting_user_id=acting_user_id, idle=True))
# Stream wildcard mention in followed topic # Stream wildcard mention in followed topic
user_data = self.create_user_notifications_data_object( user_data = self.create_user_notifications_data_object(
user_id=user_id, stream_wildcard_mention_in_followed_topic_email_notify=True user_id=user_id, stream_wildcard_mention_in_followed_topic_email_notify=True
@ -241,6 +287,8 @@ class TestNotificationData(ZulipTestCase):
pm_email_notify=True, pm_email_notify=True,
mention_push_notify=True, mention_push_notify=True,
mention_email_notify=True, mention_email_notify=True,
topic_wildcard_mention_push_notify=True,
topic_wildcard_mention_email_notify=True,
stream_wildcard_mention_push_notify=True, stream_wildcard_mention_push_notify=True,
stream_wildcard_mention_email_notify=True, stream_wildcard_mention_email_notify=True,
) )
@ -257,6 +305,8 @@ class TestNotificationData(ZulipTestCase):
pm_email_notify=True, pm_email_notify=True,
mention_push_notify=True, mention_push_notify=True,
mention_email_notify=True, mention_email_notify=True,
topic_wildcard_mention_push_notify=True,
topic_wildcard_mention_email_notify=True,
stream_wildcard_mention_push_notify=True, stream_wildcard_mention_push_notify=True,
stream_wildcard_mention_email_notify=True, stream_wildcard_mention_email_notify=True,
) )
@ -273,6 +323,8 @@ class TestNotificationData(ZulipTestCase):
pm_email_notify=True, pm_email_notify=True,
mention_push_notify=True, mention_push_notify=True,
mention_email_notify=True, mention_email_notify=True,
topic_wildcard_mention_push_notify=True,
topic_wildcard_mention_email_notify=True,
stream_wildcard_mention_push_notify=True, stream_wildcard_mention_push_notify=True,
stream_wildcard_mention_email_notify=True, stream_wildcard_mention_email_notify=True,
disable_external_notifications=True, disable_external_notifications=True,
@ -306,9 +358,11 @@ class TestNotificationData(ZulipTestCase):
muted_sender_user_ids=set(), muted_sender_user_ids=set(),
stream_email_user_ids=set(), stream_email_user_ids=set(),
stream_push_user_ids=set(), stream_push_user_ids=set(),
topic_wildcard_mention_user_ids=set(),
stream_wildcard_mention_user_ids=set(), stream_wildcard_mention_user_ids=set(),
followed_topic_email_user_ids=set(), followed_topic_email_user_ids=set(),
followed_topic_push_user_ids=set(), followed_topic_push_user_ids=set(),
topic_wildcard_mention_in_followed_topic_user_ids=set(),
stream_wildcard_mention_in_followed_topic_user_ids=set(), stream_wildcard_mention_in_followed_topic_user_ids=set(),
) )
self.assertEqual(user_data.is_notifiable(acting_user_id=1000, idle=True), notifiable) self.assertEqual(user_data.is_notifiable(acting_user_id=1000, idle=True), notifiable)

View File

@ -2094,6 +2094,41 @@ class TestGetAPNsPayload(PushNotificationTest):
} }
self.assertDictEqual(payload, expected) self.assertDictEqual(payload, expected)
def test_get_message_payload_apns_topic_wildcard_mention_in_followed_topic(self) -> None:
user_profile = self.example_user("othello")
stream = Stream.objects.filter(name="Verona").get()
message = self.get_message(Recipient.STREAM, stream.id, stream.realm_id)
payload = get_message_payload_apns(
user_profile,
message,
NotificationTriggers.TOPIC_WILDCARD_MENTION_IN_FOLLOWED_TOPIC,
)
expected = {
"alert": {
"title": "#Verona > Test topic",
"subtitle": "TODO - 2",
"body": message.content,
},
"sound": "default",
"badge": 0,
"custom": {
"zulip": {
"message_ids": [message.id],
"recipient_type": "stream",
"sender_email": self.sender.email,
"sender_id": self.sender.id,
"stream": get_display_recipient(message.recipient),
"stream_id": stream.id,
"topic": message.topic_name(),
"server": settings.EXTERNAL_HOST,
"realm_id": self.sender.realm.id,
"realm_uri": self.sender.realm.uri,
"user_id": user_profile.id,
},
},
}
self.assertDictEqual(payload, expected)
def test_get_message_payload_apns_stream_wildcard_mention_in_followed_topic(self) -> None: def test_get_message_payload_apns_stream_wildcard_mention_in_followed_topic(self) -> None:
user_profile = self.example_user("othello") user_profile = self.example_user("othello")
stream = Stream.objects.filter(name="Verona").get() stream = Stream.objects.filter(name="Verona").get()
@ -2127,6 +2162,39 @@ class TestGetAPNsPayload(PushNotificationTest):
} }
self.assertDictEqual(payload, expected) self.assertDictEqual(payload, expected)
def test_get_message_payload_apns_topic_wildcard_mention(self) -> None:
user_profile = self.example_user("othello")
stream = Stream.objects.filter(name="Verona").get()
message = self.get_message(Recipient.STREAM, stream.id, stream.realm_id)
payload = get_message_payload_apns(
user_profile, message, NotificationTriggers.TOPIC_WILDCARD_MENTION
)
expected = {
"alert": {
"title": "#Verona > Test topic",
"subtitle": "King Hamlet mentioned all topic participants:",
"body": message.content,
},
"sound": "default",
"badge": 0,
"custom": {
"zulip": {
"message_ids": [message.id],
"recipient_type": "stream",
"sender_email": self.sender.email,
"sender_id": self.sender.id,
"stream": get_display_recipient(message.recipient),
"stream_id": stream.id,
"topic": message.topic_name(),
"server": settings.EXTERNAL_HOST,
"realm_id": self.sender.realm.id,
"realm_uri": self.sender.realm.uri,
"user_id": user_profile.id,
},
},
}
self.assertDictEqual(payload, expected)
def test_get_message_payload_apns_stream_wildcard_mention(self) -> None: def test_get_message_payload_apns_stream_wildcard_mention(self) -> None:
user_profile = self.example_user("othello") user_profile = self.example_user("othello")
stream = Stream.objects.filter(name="Verona").get() stream = Stream.objects.filter(name="Verona").get()
@ -2267,11 +2335,22 @@ class TestGetGCMPayload(PushNotificationTest):
mentioned_user_group_name="mobile_team", mentioned_user_group_name="mobile_team",
) )
def test_get_message_payload_gcm_topic_wildcard_mention_in_followed_topic(self) -> None:
self._test_get_message_payload_gcm_mentions(
"topic_wildcard_mentioned_in_followed_topic", "TODO - 2"
)
def test_get_message_payload_gcm_stream_wildcard_mention_in_followed_topic(self) -> None: def test_get_message_payload_gcm_stream_wildcard_mention_in_followed_topic(self) -> None:
self._test_get_message_payload_gcm_mentions( self._test_get_message_payload_gcm_mentions(
"stream_wildcard_mentioned_in_followed_topic", "TODO" "stream_wildcard_mentioned_in_followed_topic", "TODO"
) )
def test_get_message_payload_gcm_topic_wildcard_mention(self) -> None:
self._test_get_message_payload_gcm_mentions(
"topic_wildcard_mentioned",
"King Hamlet mentioned all topic participants in #Verona > Test topic",
)
def test_get_message_payload_gcm_stream_wildcard_mention(self) -> None: def test_get_message_payload_gcm_stream_wildcard_mention(self) -> None:
self._test_get_message_payload_gcm_mentions( self._test_get_message_payload_gcm_mentions(
"stream_wildcard_mentioned", "King Hamlet mentioned everyone in #Verona" "stream_wildcard_mentioned", "King Hamlet mentioned everyone in #Verona"

View File

@ -645,11 +645,13 @@ class SoftDeactivationMessageTest(ZulipTestCase):
content: str, content: str,
*, *,
possible_stream_wildcard_mention: bool = False, possible_stream_wildcard_mention: bool = False,
topic_participant_user_ids: AbstractSet[int] = set(),
possibly_mentioned_user_ids: AbstractSet[int] = set(), possibly_mentioned_user_ids: AbstractSet[int] = set(),
) -> None: ) -> None:
assert_num_possible_users( assert_num_possible_users(
expected_count=3, expected_count=3,
possible_stream_wildcard_mention=possible_stream_wildcard_mention, possible_stream_wildcard_mention=possible_stream_wildcard_mention,
topic_participant_user_ids=topic_participant_user_ids,
possibly_mentioned_user_ids=possibly_mentioned_user_ids, possibly_mentioned_user_ids=possibly_mentioned_user_ids,
) )
general_user_msg_count = len(get_user_messages(cordelia)) general_user_msg_count = len(get_user_messages(cordelia))
@ -770,6 +772,17 @@ class SoftDeactivationMessageTest(ZulipTestCase):
) )
assert_stream_message_not_sent_to_idle_user("Test @**bogus** mention") assert_stream_message_not_sent_to_idle_user("Test @**bogus** mention")
# Test UserMessage row is created while user is deactivated if
# there is a topic wildcard mention i.e. @topic
do_soft_activate_users([long_term_idle_user])
self.send_stream_message(long_term_idle_user, stream_name, "Hi", topic_name)
topic_participant_user_ids = {long_term_idle_user.id}
do_soft_deactivate_users([long_term_idle_user])
assert_stream_message_sent_to_idle_user(
"Test @**topic** mention", topic_participant_user_ids=topic_participant_user_ids
)
# Test UserMessage row is created while user is deactivated if there # Test UserMessage row is created while user is deactivated if there
# is a alert word in message. # is a alert word in message.
do_add_alert_words(long_term_idle_user, ["test_alert_word"]) do_add_alert_words(long_term_idle_user, ["test_alert_word"])

View File

@ -805,12 +805,24 @@ def missedmessage_hook(
pm_email_notify=internal_data.get("pm_email_notify", False), pm_email_notify=internal_data.get("pm_email_notify", False),
mention_push_notify=internal_data.get("mention_push_notify", False), mention_push_notify=internal_data.get("mention_push_notify", False),
mention_email_notify=internal_data.get("mention_email_notify", False), mention_email_notify=internal_data.get("mention_email_notify", False),
topic_wildcard_mention_push_notify=internal_data.get(
"topic_wildcard_mention_push_notify", False
),
topic_wildcard_mention_email_notify=internal_data.get(
"topic_wildcard_mention_email_notify", False
),
stream_wildcard_mention_push_notify=stream_wildcard_mention_push_notify, stream_wildcard_mention_push_notify=stream_wildcard_mention_push_notify,
stream_wildcard_mention_email_notify=stream_wildcard_mention_email_notify, stream_wildcard_mention_email_notify=stream_wildcard_mention_email_notify,
stream_push_notify=internal_data.get("stream_push_notify", False), stream_push_notify=internal_data.get("stream_push_notify", False),
stream_email_notify=internal_data.get("stream_email_notify", False), stream_email_notify=internal_data.get("stream_email_notify", False),
followed_topic_push_notify=internal_data.get("followed_topic_push_notify", False), followed_topic_push_notify=internal_data.get("followed_topic_push_notify", False),
followed_topic_email_notify=internal_data.get("followed_topic_email_notify", False), followed_topic_email_notify=internal_data.get("followed_topic_email_notify", False),
topic_wildcard_mention_in_followed_topic_push_notify=internal_data.get(
"topic_wildcard_mention_in_followed_topic_push_notify", False
),
topic_wildcard_mention_in_followed_topic_email_notify=internal_data.get(
"topic_wildcard_mention_in_followed_topic_email_notify", False
),
stream_wildcard_mention_in_followed_topic_push_notify=internal_data.get( stream_wildcard_mention_in_followed_topic_push_notify=internal_data.get(
"stream_wildcard_mention_in_followed_topic_push_notify", False "stream_wildcard_mention_in_followed_topic_push_notify", False
), ),
@ -969,6 +981,7 @@ def process_message_event(
) )
stream_push_user_ids = set(event_template.get("stream_push_user_ids", [])) stream_push_user_ids = set(event_template.get("stream_push_user_ids", []))
stream_email_user_ids = set(event_template.get("stream_email_user_ids", [])) stream_email_user_ids = set(event_template.get("stream_email_user_ids", []))
topic_wildcard_mention_user_ids = set(event_template.get("topic_wildcard_mention_user_ids", []))
# TODO/compatibility: Translation code for the rename of # TODO/compatibility: Translation code for the rename of
# `wildcard_mention_user_ids` to `stream_wildcard_mention_user_ids`. # `wildcard_mention_user_ids` to `stream_wildcard_mention_user_ids`.
@ -983,6 +996,9 @@ def process_message_event(
followed_topic_push_user_ids = set(event_template.get("followed_topic_push_user_ids", [])) followed_topic_push_user_ids = set(event_template.get("followed_topic_push_user_ids", []))
followed_topic_email_user_ids = set(event_template.get("followed_topic_email_user_ids", [])) followed_topic_email_user_ids = set(event_template.get("followed_topic_email_user_ids", []))
topic_wildcard_mention_in_followed_topic_user_ids = set(
event_template.get("topic_wildcard_mention_in_followed_topic_user_ids", [])
)
stream_wildcard_mention_in_followed_topic_user_ids = set( stream_wildcard_mention_in_followed_topic_user_ids = set(
event_template.get("stream_wildcard_mention_in_followed_topic_user_ids", []) event_template.get("stream_wildcard_mention_in_followed_topic_user_ids", [])
) )
@ -1035,9 +1051,11 @@ def process_message_event(
pm_mention_email_disabled_user_ids=pm_mention_email_disabled_user_ids, pm_mention_email_disabled_user_ids=pm_mention_email_disabled_user_ids,
stream_push_user_ids=stream_push_user_ids, stream_push_user_ids=stream_push_user_ids,
stream_email_user_ids=stream_email_user_ids, stream_email_user_ids=stream_email_user_ids,
topic_wildcard_mention_user_ids=topic_wildcard_mention_user_ids,
stream_wildcard_mention_user_ids=stream_wildcard_mention_user_ids, stream_wildcard_mention_user_ids=stream_wildcard_mention_user_ids,
followed_topic_push_user_ids=followed_topic_push_user_ids, followed_topic_push_user_ids=followed_topic_push_user_ids,
followed_topic_email_user_ids=followed_topic_email_user_ids, followed_topic_email_user_ids=followed_topic_email_user_ids,
topic_wildcard_mention_in_followed_topic_user_ids=topic_wildcard_mention_in_followed_topic_user_ids,
stream_wildcard_mention_in_followed_topic_user_ids=stream_wildcard_mention_in_followed_topic_user_ids, stream_wildcard_mention_in_followed_topic_user_ids=stream_wildcard_mention_in_followed_topic_user_ids,
muted_sender_user_ids=muted_sender_user_ids, muted_sender_user_ids=muted_sender_user_ids,
all_bot_user_ids=all_bot_user_ids, all_bot_user_ids=all_bot_user_ids,
@ -1189,6 +1207,7 @@ def process_message_update_event(
) )
stream_push_user_ids = set(event_template.pop("stream_push_user_ids", [])) stream_push_user_ids = set(event_template.pop("stream_push_user_ids", []))
stream_email_user_ids = set(event_template.pop("stream_email_user_ids", [])) stream_email_user_ids = set(event_template.pop("stream_email_user_ids", []))
topic_wildcard_mention_user_ids = set(event_template.pop("topic_wildcard_mention_user_ids", []))
# TODO/compatibility: Translation code for the rename of # TODO/compatibility: Translation code for the rename of
# `wildcard_mention_user_ids` to `stream_wildcard_mention_user_ids`. # `wildcard_mention_user_ids` to `stream_wildcard_mention_user_ids`.
@ -1203,6 +1222,9 @@ def process_message_update_event(
followed_topic_push_user_ids = set(event_template.pop("followed_topic_push_user_ids", [])) followed_topic_push_user_ids = set(event_template.pop("followed_topic_push_user_ids", []))
followed_topic_email_user_ids = set(event_template.pop("followed_topic_email_user_ids", [])) followed_topic_email_user_ids = set(event_template.pop("followed_topic_email_user_ids", []))
topic_wildcard_mention_in_followed_topic_user_ids = set(
event_template.pop("topic_wildcard_mention_in_followed_topic_user_ids", [])
)
stream_wildcard_mention_in_followed_topic_user_ids = set( stream_wildcard_mention_in_followed_topic_user_ids = set(
event_template.pop("stream_wildcard_mention_in_followed_topic_user_ids", []) event_template.pop("stream_wildcard_mention_in_followed_topic_user_ids", [])
) )
@ -1265,9 +1287,11 @@ def process_message_update_event(
pm_mention_email_disabled_user_ids=pm_mention_email_disabled_user_ids, pm_mention_email_disabled_user_ids=pm_mention_email_disabled_user_ids,
stream_push_user_ids=stream_push_user_ids, stream_push_user_ids=stream_push_user_ids,
stream_email_user_ids=stream_email_user_ids, stream_email_user_ids=stream_email_user_ids,
topic_wildcard_mention_user_ids=topic_wildcard_mention_user_ids,
stream_wildcard_mention_user_ids=stream_wildcard_mention_user_ids, stream_wildcard_mention_user_ids=stream_wildcard_mention_user_ids,
followed_topic_push_user_ids=followed_topic_push_user_ids, followed_topic_push_user_ids=followed_topic_push_user_ids,
followed_topic_email_user_ids=followed_topic_email_user_ids, followed_topic_email_user_ids=followed_topic_email_user_ids,
topic_wildcard_mention_in_followed_topic_user_ids=topic_wildcard_mention_in_followed_topic_user_ids,
stream_wildcard_mention_in_followed_topic_user_ids=stream_wildcard_mention_in_followed_topic_user_ids, stream_wildcard_mention_in_followed_topic_user_ids=stream_wildcard_mention_in_followed_topic_user_ids,
muted_sender_user_ids=muted_sender_user_ids, muted_sender_user_ids=muted_sender_user_ids,
all_bot_user_ids=all_bot_user_ids, all_bot_user_ids=all_bot_user_ids,