mirror of
https://github.com/zulip/zulip.git
synced 2025-11-21 15:09:34 +00:00
refactor: Introduce bugdown.MentionData class.
We now have a MentionData class that encapsulates the users who are possibly mentioned in a message. Not that the rendering code may not keep all the mentions, since things like backticks will suppress the mention. We populate this now in do_send_messages, so that we can use the info earlier in the message-sending process. This info now gets passed down the call stack as an optional parameter. Note that bugdown.convert() still populates the data when its callers decline to pass in a MentionData object. This is mostly a preparatory commit, as we don't take advantage of the data yet in do_send_messages.
This commit is contained in:
@@ -762,8 +762,8 @@ def send_welcome_bot_response(message):
|
|||||||
"Feel free to continue using this space to practice your new messaging "
|
"Feel free to continue using this space to practice your new messaging "
|
||||||
"skills. Or, try clicking on some of the stream names to your left!")
|
"skills. Or, try clicking on some of the stream names to your left!")
|
||||||
|
|
||||||
def render_incoming_message(message, content, user_ids, realm):
|
def render_incoming_message(message, content, user_ids, realm, mention_data=None):
|
||||||
# type: (Message, Text, Set[int], Realm) -> Text
|
# type: (Message, Text, Set[int], Realm, Optional[bugdown.MentionData]) -> Text
|
||||||
realm_alert_words = alert_words_in_realm(realm)
|
realm_alert_words = alert_words_in_realm(realm)
|
||||||
try:
|
try:
|
||||||
rendered_content = render_markdown(
|
rendered_content = render_markdown(
|
||||||
@@ -772,6 +772,7 @@ def render_incoming_message(message, content, user_ids, realm):
|
|||||||
realm=realm,
|
realm=realm,
|
||||||
realm_alert_words=realm_alert_words,
|
realm_alert_words=realm_alert_words,
|
||||||
user_ids=user_ids,
|
user_ids=user_ids,
|
||||||
|
mention_data=mention_data,
|
||||||
)
|
)
|
||||||
except BugdownRenderingException:
|
except BugdownRenderingException:
|
||||||
raise JsonableError(_('Unable to render message'))
|
raise JsonableError(_('Unable to render message'))
|
||||||
@@ -1021,6 +1022,12 @@ def do_send_messages(messages_maybe_none):
|
|||||||
message['realm'] = message.get('realm', message['message'].sender.realm)
|
message['realm'] = message.get('realm', message['message'].sender.realm)
|
||||||
|
|
||||||
for message in messages:
|
for message in messages:
|
||||||
|
mention_data = bugdown.MentionData(
|
||||||
|
realm_id=message['realm'].id,
|
||||||
|
content=message['message'].content,
|
||||||
|
)
|
||||||
|
message['mention_data'] = mention_data
|
||||||
|
|
||||||
if message['message'].recipient.type == Recipient.STREAM:
|
if message['message'].recipient.type == Recipient.STREAM:
|
||||||
stream_id = message['message'].recipient.type_id
|
stream_id = message['message'].recipient.type_id
|
||||||
stream_topic = StreamTopicTarget(
|
stream_topic = StreamTopicTarget(
|
||||||
@@ -1047,11 +1054,14 @@ def do_send_messages(messages_maybe_none):
|
|||||||
# Render our messages.
|
# Render our messages.
|
||||||
for message in messages:
|
for message in messages:
|
||||||
assert message['message'].rendered_content is None
|
assert message['message'].rendered_content is None
|
||||||
|
|
||||||
rendered_content = render_incoming_message(
|
rendered_content = render_incoming_message(
|
||||||
message['message'],
|
message['message'],
|
||||||
message['message'].content,
|
message['message'].content,
|
||||||
message['active_user_ids'],
|
message['active_user_ids'],
|
||||||
message['realm'])
|
message['realm'],
|
||||||
|
mention_data=message['mention_data'],
|
||||||
|
)
|
||||||
message['message'].rendered_content = rendered_content
|
message['message'].rendered_content = rendered_content
|
||||||
message['message'].rendered_content_version = bugdown_version
|
message['message'].rendered_content_version = bugdown_version
|
||||||
links_for_embed |= message['message'].links_for_preview
|
links_for_embed |= message['message'].links_for_preview
|
||||||
|
|||||||
@@ -1148,7 +1148,7 @@ class UserMentionPattern(markdown.inlinepatterns.Pattern):
|
|||||||
name = match
|
name = match
|
||||||
|
|
||||||
wildcard = mention.user_mention_matches_wildcard(name)
|
wildcard = mention.user_mention_matches_wildcard(name)
|
||||||
user = db_data['full_name_info'].get(name.lower(), None)
|
user = db_data['mention_data'].get_user(name)
|
||||||
|
|
||||||
if wildcard:
|
if wildcard:
|
||||||
current_message.mentions_wildcard = True
|
current_message.mentions_wildcard = True
|
||||||
@@ -1549,6 +1549,16 @@ def get_full_name_info(realm_id, full_names):
|
|||||||
}
|
}
|
||||||
return dct
|
return dct
|
||||||
|
|
||||||
|
class MentionData(object):
|
||||||
|
def __init__(self, realm_id, content):
|
||||||
|
# type: (int, Text) -> None
|
||||||
|
full_names = possible_mentions(content)
|
||||||
|
self.full_name_info = get_full_name_info(realm_id, full_names)
|
||||||
|
|
||||||
|
def get_user(self, name):
|
||||||
|
# type: (Text) -> Optional[FullNameInfo]
|
||||||
|
return self.full_name_info.get(name.lower(), None)
|
||||||
|
|
||||||
def get_stream_name_info(realm, stream_names):
|
def get_stream_name_info(realm, stream_names):
|
||||||
# type: (Realm, Set[Text]) -> Dict[Text, FullNameInfo]
|
# type: (Realm, Set[Text]) -> Dict[Text, FullNameInfo]
|
||||||
if not stream_names:
|
if not stream_names:
|
||||||
@@ -1575,8 +1585,8 @@ def get_stream_name_info(realm, stream_names):
|
|||||||
return dct
|
return dct
|
||||||
|
|
||||||
|
|
||||||
def do_convert(content, message=None, message_realm=None, possible_words=None, sent_by_bot=False):
|
def do_convert(content, message=None, message_realm=None, possible_words=None, sent_by_bot=False, mention_data=None):
|
||||||
# type: (Text, Optional[Message], Optional[Realm], Optional[Set[Text]], Optional[bool]) -> Text
|
# type: (Text, Optional[Message], Optional[Realm], Optional[Set[Text]], Optional[bool], Optional[MentionData]) -> Text
|
||||||
"""Convert Markdown to HTML, with Zulip-specific settings and hacks."""
|
"""Convert Markdown to HTML, with Zulip-specific settings and hacks."""
|
||||||
# This logic is a bit convoluted, but the overall goal is to support a range of use cases:
|
# This logic is a bit convoluted, but the overall goal is to support a range of use cases:
|
||||||
# * Nothing is passed in other than content -> just run default options (e.g. for docs)
|
# * Nothing is passed in other than content -> just run default options (e.g. for docs)
|
||||||
@@ -1623,8 +1633,9 @@ def do_convert(content, message=None, message_realm=None, possible_words=None, s
|
|||||||
# if there is syntax in the message that might use them, since
|
# if there is syntax in the message that might use them, since
|
||||||
# the fetches are somewhat expensive and these types of syntax
|
# the fetches are somewhat expensive and these types of syntax
|
||||||
# are uncommon enough that it's a useful optimization.
|
# are uncommon enough that it's a useful optimization.
|
||||||
full_names = possible_mentions(content)
|
|
||||||
full_name_info = get_full_name_info(message_realm.id, full_names)
|
if mention_data is None:
|
||||||
|
mention_data = MentionData(message_realm.id, content)
|
||||||
|
|
||||||
emails = possible_avatar_emails(content)
|
emails = possible_avatar_emails(content)
|
||||||
email_info = get_email_info(message_realm.id, emails)
|
email_info = get_email_info(message_realm.id, emails)
|
||||||
@@ -1640,7 +1651,7 @@ def do_convert(content, message=None, message_realm=None, possible_words=None, s
|
|||||||
db_data = {
|
db_data = {
|
||||||
'possible_words': possible_words,
|
'possible_words': possible_words,
|
||||||
'email_info': email_info,
|
'email_info': email_info,
|
||||||
'full_name_info': full_name_info,
|
'mention_data': mention_data,
|
||||||
'realm_emoji': realm_emoji,
|
'realm_emoji': realm_emoji,
|
||||||
'sent_by_bot': sent_by_bot,
|
'sent_by_bot': sent_by_bot,
|
||||||
'stream_names': stream_name_info,
|
'stream_names': stream_name_info,
|
||||||
@@ -1694,9 +1705,9 @@ def bugdown_stats_finish():
|
|||||||
bugdown_total_requests += 1
|
bugdown_total_requests += 1
|
||||||
bugdown_total_time += (time.time() - bugdown_time_start)
|
bugdown_total_time += (time.time() - bugdown_time_start)
|
||||||
|
|
||||||
def convert(content, message=None, message_realm=None, possible_words=None, sent_by_bot=False):
|
def convert(content, message=None, message_realm=None, possible_words=None, sent_by_bot=False, mention_data=None):
|
||||||
# type: (Text, Optional[Message], Optional[Realm], Optional[Set[Text]], Optional[bool]) -> Text
|
# type: (Text, Optional[Message], Optional[Realm], Optional[Set[Text]], Optional[bool], Optional[MentionData]) -> Text
|
||||||
bugdown_stats_start()
|
bugdown_stats_start()
|
||||||
ret = do_convert(content, message, message_realm, possible_words, sent_by_bot)
|
ret = do_convert(content, message, message_realm, possible_words, sent_by_bot, mention_data)
|
||||||
bugdown_stats_finish()
|
bugdown_stats_finish()
|
||||||
return ret
|
return ret
|
||||||
|
|||||||
@@ -461,8 +461,8 @@ def access_message(user_profile, message_id):
|
|||||||
# stream in your realm, so return the message, user_message pair
|
# stream in your realm, so return the message, user_message pair
|
||||||
return (message, user_message)
|
return (message, user_message)
|
||||||
|
|
||||||
def render_markdown(message, content, realm=None, realm_alert_words=None, user_ids=None):
|
def render_markdown(message, content, realm=None, realm_alert_words=None, user_ids=None, mention_data=None):
|
||||||
# type: (Message, Text, Optional[Realm], Optional[RealmAlertWords], Optional[Set[int]]) -> Text
|
# type: (Message, Text, Optional[Realm], Optional[RealmAlertWords], Optional[Set[int]], Optional[bugdown.MentionData]) -> Text
|
||||||
"""Return HTML for given markdown. Bugdown may add properties to the
|
"""Return HTML for given markdown. Bugdown may add properties to the
|
||||||
message object such as `mentions_user_ids` and `mentions_wildcard`.
|
message object such as `mentions_user_ids` and `mentions_wildcard`.
|
||||||
These are only on this Django object and are not saved in the
|
These are only on this Django object and are not saved in the
|
||||||
@@ -497,9 +497,14 @@ def render_markdown(message, content, realm=None, realm_alert_words=None, user_i
|
|||||||
sent_by_bot = get_user_profile_by_id(message.sender_id).is_bot
|
sent_by_bot = get_user_profile_by_id(message.sender_id).is_bot
|
||||||
|
|
||||||
# DO MAIN WORK HERE -- call bugdown to convert
|
# DO MAIN WORK HERE -- call bugdown to convert
|
||||||
rendered_content = bugdown.convert(content, message=message, message_realm=realm,
|
rendered_content = bugdown.convert(
|
||||||
|
content,
|
||||||
|
message=message,
|
||||||
|
message_realm=realm,
|
||||||
possible_words=possible_words,
|
possible_words=possible_words,
|
||||||
sent_by_bot=sent_by_bot)
|
sent_by_bot=sent_by_bot,
|
||||||
|
mention_data=mention_data,
|
||||||
|
)
|
||||||
|
|
||||||
if message is not None:
|
if message is not None:
|
||||||
message.user_ids_with_alert_words = set()
|
message.user_ids_with_alert_words = set()
|
||||||
|
|||||||
Reference in New Issue
Block a user