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 "
|
||||
"skills. Or, try clicking on some of the stream names to your left!")
|
||||
|
||||
def render_incoming_message(message, content, user_ids, realm):
|
||||
# type: (Message, Text, Set[int], Realm) -> Text
|
||||
def render_incoming_message(message, content, user_ids, realm, mention_data=None):
|
||||
# type: (Message, Text, Set[int], Realm, Optional[bugdown.MentionData]) -> Text
|
||||
realm_alert_words = alert_words_in_realm(realm)
|
||||
try:
|
||||
rendered_content = render_markdown(
|
||||
@@ -772,6 +772,7 @@ def render_incoming_message(message, content, user_ids, realm):
|
||||
realm=realm,
|
||||
realm_alert_words=realm_alert_words,
|
||||
user_ids=user_ids,
|
||||
mention_data=mention_data,
|
||||
)
|
||||
except BugdownRenderingException:
|
||||
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)
|
||||
|
||||
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:
|
||||
stream_id = message['message'].recipient.type_id
|
||||
stream_topic = StreamTopicTarget(
|
||||
@@ -1047,11 +1054,14 @@ def do_send_messages(messages_maybe_none):
|
||||
# Render our messages.
|
||||
for message in messages:
|
||||
assert message['message'].rendered_content is None
|
||||
|
||||
rendered_content = render_incoming_message(
|
||||
message['message'],
|
||||
message['message'].content,
|
||||
message['active_user_ids'],
|
||||
message['realm'])
|
||||
message['realm'],
|
||||
mention_data=message['mention_data'],
|
||||
)
|
||||
message['message'].rendered_content = rendered_content
|
||||
message['message'].rendered_content_version = bugdown_version
|
||||
links_for_embed |= message['message'].links_for_preview
|
||||
|
||||
@@ -1148,7 +1148,7 @@ class UserMentionPattern(markdown.inlinepatterns.Pattern):
|
||||
name = match
|
||||
|
||||
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:
|
||||
current_message.mentions_wildcard = True
|
||||
@@ -1549,6 +1549,16 @@ def get_full_name_info(realm_id, full_names):
|
||||
}
|
||||
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):
|
||||
# type: (Realm, Set[Text]) -> Dict[Text, FullNameInfo]
|
||||
if not stream_names:
|
||||
@@ -1575,8 +1585,8 @@ def get_stream_name_info(realm, stream_names):
|
||||
return dct
|
||||
|
||||
|
||||
def do_convert(content, message=None, message_realm=None, possible_words=None, sent_by_bot=False):
|
||||
# type: (Text, Optional[Message], Optional[Realm], Optional[Set[Text]], Optional[bool]) -> Text
|
||||
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], Optional[MentionData]) -> Text
|
||||
"""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:
|
||||
# * 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
|
||||
# the fetches are somewhat expensive and these types of syntax
|
||||
# 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)
|
||||
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 = {
|
||||
'possible_words': possible_words,
|
||||
'email_info': email_info,
|
||||
'full_name_info': full_name_info,
|
||||
'mention_data': mention_data,
|
||||
'realm_emoji': realm_emoji,
|
||||
'sent_by_bot': sent_by_bot,
|
||||
'stream_names': stream_name_info,
|
||||
@@ -1694,9 +1705,9 @@ def bugdown_stats_finish():
|
||||
bugdown_total_requests += 1
|
||||
bugdown_total_time += (time.time() - bugdown_time_start)
|
||||
|
||||
def convert(content, message=None, message_realm=None, possible_words=None, sent_by_bot=False):
|
||||
# type: (Text, Optional[Message], Optional[Realm], Optional[Set[Text]], Optional[bool]) -> Text
|
||||
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], Optional[MentionData]) -> Text
|
||||
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()
|
||||
return ret
|
||||
|
||||
@@ -461,8 +461,8 @@ def access_message(user_profile, message_id):
|
||||
# stream in your realm, so return the message, user_message pair
|
||||
return (message, user_message)
|
||||
|
||||
def render_markdown(message, content, realm=None, realm_alert_words=None, user_ids=None):
|
||||
# type: (Message, Text, Optional[Realm], Optional[RealmAlertWords], Optional[Set[int]]) -> Text
|
||||
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]], Optional[bugdown.MentionData]) -> Text
|
||||
"""Return HTML for given markdown. Bugdown may add properties to the
|
||||
message object such as `mentions_user_ids` and `mentions_wildcard`.
|
||||
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
|
||||
|
||||
# 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,
|
||||
sent_by_bot=sent_by_bot)
|
||||
sent_by_bot=sent_by_bot,
|
||||
mention_data=mention_data,
|
||||
)
|
||||
|
||||
if message is not None:
|
||||
message.user_ids_with_alert_words = set()
|
||||
|
||||
Reference in New Issue
Block a user