mirror of https://github.com/zulip/zulip.git
refactor: Add MentionBackend.
We will eventually use this to avoid redundant queries. The diff is slightly noisy here, but there are no logic changes.
This commit is contained in:
parent
a22f49bf83
commit
c6448263c3
|
@ -100,7 +100,7 @@ from zerver.lib.hotspots import get_next_hotspots
|
||||||
from zerver.lib.i18n import get_language_name
|
from zerver.lib.i18n import get_language_name
|
||||||
from zerver.lib.markdown import MessageRenderingResult, topic_links
|
from zerver.lib.markdown import MessageRenderingResult, topic_links
|
||||||
from zerver.lib.markdown import version as markdown_version
|
from zerver.lib.markdown import version as markdown_version
|
||||||
from zerver.lib.mention import MentionData, silent_mention_syntax_for_user
|
from zerver.lib.mention import MentionBackend, MentionData, silent_mention_syntax_for_user
|
||||||
from zerver.lib.message import (
|
from zerver.lib.message import (
|
||||||
MessageDict,
|
MessageDict,
|
||||||
SendMessageRequest,
|
SendMessageRequest,
|
||||||
|
@ -1863,8 +1863,9 @@ def build_message_send_dict(
|
||||||
if realm is None:
|
if realm is None:
|
||||||
realm = message.sender.realm
|
realm = message.sender.realm
|
||||||
|
|
||||||
|
mention_backend = MentionBackend(realm.id)
|
||||||
mention_data = MentionData(
|
mention_data = MentionData(
|
||||||
realm_id=realm.id,
|
mention_backend=mention_backend,
|
||||||
content=message.content,
|
content=message.content,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -3065,8 +3066,9 @@ def check_update_message(
|
||||||
content = "(deleted)"
|
content = "(deleted)"
|
||||||
content = normalize_body(content)
|
content = normalize_body(content)
|
||||||
|
|
||||||
|
mention_backend = MentionBackend(user_profile.realm_id)
|
||||||
mention_data = MentionData(
|
mention_data = MentionData(
|
||||||
realm_id=user_profile.realm.id,
|
mention_backend=mention_backend,
|
||||||
content=content,
|
content=content,
|
||||||
)
|
)
|
||||||
user_info = get_user_info_for_message_updates(message.id)
|
user_info = get_user_info_for_message_updates(message.id)
|
||||||
|
|
|
@ -54,7 +54,7 @@ from zerver.lib.emoji import EMOTICON_RE, codepoint_to_name, name_to_codepoint,
|
||||||
from zerver.lib.exceptions import MarkdownRenderingException
|
from zerver.lib.exceptions import MarkdownRenderingException
|
||||||
from zerver.lib.markdown import fenced_code
|
from zerver.lib.markdown import fenced_code
|
||||||
from zerver.lib.markdown.fenced_code import FENCE_RE
|
from zerver.lib.markdown.fenced_code import FENCE_RE
|
||||||
from zerver.lib.mention import FullNameInfo, MentionData, get_stream_name_map
|
from zerver.lib.mention import FullNameInfo, MentionBackend, MentionData, get_stream_name_map
|
||||||
from zerver.lib.outgoing_http import OutgoingSession
|
from zerver.lib.outgoing_http import OutgoingSession
|
||||||
from zerver.lib.subdomains import is_static_or_current_realm_url
|
from zerver.lib.subdomains import is_static_or_current_realm_url
|
||||||
from zerver.lib.tex import render_tex
|
from zerver.lib.tex import render_tex
|
||||||
|
@ -2508,7 +2508,8 @@ def do_convert(
|
||||||
# are uncommon enough that it's a useful optimization.
|
# are uncommon enough that it's a useful optimization.
|
||||||
|
|
||||||
if mention_data is None:
|
if mention_data is None:
|
||||||
mention_data = MentionData(message_realm.id, content)
|
mention_backend = MentionBackend(message_realm.id)
|
||||||
|
mention_data = MentionData(mention_backend, content)
|
||||||
|
|
||||||
stream_names = possible_linked_stream_names(content)
|
stream_names = possible_linked_stream_names(content)
|
||||||
stream_name_info = get_stream_name_map(message_realm, stream_names)
|
stream_name_info = get_stream_name_map(message_realm, stream_names)
|
||||||
|
|
|
@ -37,6 +37,29 @@ class UserFilter:
|
||||||
raise AssertionError("totally empty filter makes no sense")
|
raise AssertionError("totally empty filter makes no sense")
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class MentionBackend:
|
||||||
|
realm_id: int
|
||||||
|
|
||||||
|
def get_full_name_info_list(self, user_filters: List[UserFilter]) -> List[FullNameInfo]:
|
||||||
|
q_list = [user_filter.Q() for user_filter in user_filters]
|
||||||
|
|
||||||
|
rows = (
|
||||||
|
UserProfile.objects.filter(
|
||||||
|
realm_id=self.realm_id,
|
||||||
|
is_active=True,
|
||||||
|
)
|
||||||
|
.filter(
|
||||||
|
functools.reduce(lambda a, b: a | b, q_list),
|
||||||
|
)
|
||||||
|
.only(
|
||||||
|
"id",
|
||||||
|
"full_name",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return [FullNameInfo(id=row.id, full_name=row.full_name) for row in rows]
|
||||||
|
|
||||||
|
|
||||||
def user_mention_matches_wildcard(mention: str) -> bool:
|
def user_mention_matches_wildcard(mention: str) -> bool:
|
||||||
return mention in wildcards
|
return mention in wildcards
|
||||||
|
|
||||||
|
@ -65,7 +88,9 @@ def possible_user_group_mentions(content: str) -> Set[str]:
|
||||||
return {m.group("match") for m in USER_GROUP_MENTIONS_RE.finditer(content)}
|
return {m.group("match") for m in USER_GROUP_MENTIONS_RE.finditer(content)}
|
||||||
|
|
||||||
|
|
||||||
def get_possible_mentions_info(realm_id: int, mention_texts: Set[str]) -> List[FullNameInfo]:
|
def get_possible_mentions_info(
|
||||||
|
mention_backend: MentionBackend, mention_texts: Set[str]
|
||||||
|
) -> List[FullNameInfo]:
|
||||||
if not mention_texts:
|
if not mention_texts:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
@ -88,28 +113,14 @@ def get_possible_mentions_info(realm_id: int, mention_texts: Set[str]) -> List[F
|
||||||
# For **name** syntax.
|
# For **name** syntax.
|
||||||
user_filters.append(UserFilter(full_name=mention_text, id=None))
|
user_filters.append(UserFilter(full_name=mention_text, id=None))
|
||||||
|
|
||||||
q_list = [user_filter.Q() for user_filter in user_filters]
|
return mention_backend.get_full_name_info_list(user_filters)
|
||||||
|
|
||||||
rows = (
|
|
||||||
UserProfile.objects.filter(
|
|
||||||
realm_id=realm_id,
|
|
||||||
is_active=True,
|
|
||||||
)
|
|
||||||
.filter(
|
|
||||||
functools.reduce(lambda a, b: a | b, q_list),
|
|
||||||
)
|
|
||||||
.only(
|
|
||||||
"id",
|
|
||||||
"full_name",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
return [FullNameInfo(id=row.id, full_name=row.full_name) for row in rows]
|
|
||||||
|
|
||||||
|
|
||||||
class MentionData:
|
class MentionData:
|
||||||
def __init__(self, realm_id: int, content: str) -> None:
|
def __init__(self, mention_backend: MentionBackend, content: str) -> None:
|
||||||
|
realm_id = mention_backend.realm_id
|
||||||
mention_texts, has_wildcards = possible_mentions(content)
|
mention_texts, has_wildcards = possible_mentions(content)
|
||||||
possible_mentions_info = get_possible_mentions_info(realm_id, mention_texts)
|
possible_mentions_info = get_possible_mentions_info(mention_backend, mention_texts)
|
||||||
self.full_name_info = {row.full_name.lower(): row for row in possible_mentions_info}
|
self.full_name_info = {row.full_name.lower(): row for row in possible_mentions_info}
|
||||||
self.user_id_info = {row.id: row for row in possible_mentions_info}
|
self.user_id_info = {row.id: row for row in possible_mentions_info}
|
||||||
self.init_user_group_data(realm_id=realm_id, content=content)
|
self.init_user_group_data(realm_id=realm_id, content=content)
|
||||||
|
|
|
@ -171,7 +171,7 @@ from zerver.lib.events import (
|
||||||
fetch_initial_state_data,
|
fetch_initial_state_data,
|
||||||
post_process_state,
|
post_process_state,
|
||||||
)
|
)
|
||||||
from zerver.lib.mention import MentionData
|
from zerver.lib.mention import MentionBackend, MentionData
|
||||||
from zerver.lib.message import render_markdown
|
from zerver.lib.message import render_markdown
|
||||||
from zerver.lib.test_classes import ZulipTestCase
|
from zerver.lib.test_classes import ZulipTestCase
|
||||||
from zerver.lib.test_helpers import (
|
from zerver.lib.test_helpers import (
|
||||||
|
@ -437,8 +437,9 @@ class NormalActionsTest(BaseAction):
|
||||||
content = "new content"
|
content = "new content"
|
||||||
rendering_result = render_markdown(pm, content)
|
rendering_result = render_markdown(pm, content)
|
||||||
prior_mention_user_ids: Set[int] = set()
|
prior_mention_user_ids: Set[int] = set()
|
||||||
|
mention_backend = MentionBackend(self.user_profile.realm_id)
|
||||||
mention_data = MentionData(
|
mention_data = MentionData(
|
||||||
realm_id=self.user_profile.realm_id,
|
mention_backend=mention_backend,
|
||||||
content=content,
|
content=content,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -496,8 +497,9 @@ class NormalActionsTest(BaseAction):
|
||||||
content = "new content"
|
content = "new content"
|
||||||
rendering_result = render_markdown(message, content)
|
rendering_result = render_markdown(message, content)
|
||||||
prior_mention_user_ids: Set[int] = set()
|
prior_mention_user_ids: Set[int] = set()
|
||||||
|
mention_backend = MentionBackend(self.user_profile.realm_id)
|
||||||
mention_data = MentionData(
|
mention_data = MentionData(
|
||||||
realm_id=self.user_profile.realm_id,
|
mention_backend=mention_backend,
|
||||||
content=content,
|
content=content,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,7 @@ from zerver.lib.markdown.fenced_code import FencedBlockPreprocessor
|
||||||
from zerver.lib.mdiff import diff_strings
|
from zerver.lib.mdiff import diff_strings
|
||||||
from zerver.lib.mention import (
|
from zerver.lib.mention import (
|
||||||
FullNameInfo,
|
FullNameInfo,
|
||||||
|
MentionBackend,
|
||||||
MentionData,
|
MentionData,
|
||||||
get_possible_mentions_info,
|
get_possible_mentions_info,
|
||||||
possible_mentions,
|
possible_mentions,
|
||||||
|
@ -232,8 +233,9 @@ class MarkdownMiscTest(ZulipTestCase):
|
||||||
|
|
||||||
fred4 = make_user("fred4@example.com", "Fred Flintstone")
|
fred4 = make_user("fred4@example.com", "Fred Flintstone")
|
||||||
|
|
||||||
|
mention_backend = MentionBackend(realm.id)
|
||||||
lst = get_possible_mentions_info(
|
lst = get_possible_mentions_info(
|
||||||
realm.id, {"Fred Flintstone", "Cordelia, LEAR's daughter", "Not A User"}
|
mention_backend, {"Fred Flintstone", "Cordelia, LEAR's daughter", "Not A User"}
|
||||||
)
|
)
|
||||||
set_of_names = set(map(lambda x: x.full_name.lower(), lst))
|
set_of_names = set(map(lambda x: x.full_name.lower(), lst))
|
||||||
self.assertEqual(set_of_names, {"fred flintstone", "cordelia, lear's daughter"})
|
self.assertEqual(set_of_names, {"fred flintstone", "cordelia, lear's daughter"})
|
||||||
|
@ -259,7 +261,8 @@ class MarkdownMiscTest(ZulipTestCase):
|
||||||
hamlet = self.example_user("hamlet")
|
hamlet = self.example_user("hamlet")
|
||||||
cordelia = self.example_user("cordelia")
|
cordelia = self.example_user("cordelia")
|
||||||
content = "@**King Hamlet** @**Cordelia, lear's daughter**"
|
content = "@**King Hamlet** @**Cordelia, lear's daughter**"
|
||||||
mention_data = MentionData(realm.id, content)
|
mention_backend = MentionBackend(realm.id)
|
||||||
|
mention_data = MentionData(mention_backend, content)
|
||||||
self.assertEqual(mention_data.get_user_ids(), {hamlet.id, cordelia.id})
|
self.assertEqual(mention_data.get_user_ids(), {hamlet.id, cordelia.id})
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
mention_data.get_user_by_id(hamlet.id),
|
mention_data.get_user_by_id(hamlet.id),
|
||||||
|
@ -275,7 +278,7 @@ class MarkdownMiscTest(ZulipTestCase):
|
||||||
|
|
||||||
self.assertFalse(mention_data.message_has_wildcards())
|
self.assertFalse(mention_data.message_has_wildcards())
|
||||||
content = "@**King Hamlet** @**Cordelia, lear's daughter** @**all**"
|
content = "@**King Hamlet** @**Cordelia, lear's daughter** @**all**"
|
||||||
mention_data = MentionData(realm.id, content)
|
mention_data = MentionData(mention_backend, content)
|
||||||
self.assertTrue(mention_data.message_has_wildcards())
|
self.assertTrue(mention_data.message_has_wildcards())
|
||||||
|
|
||||||
def test_invalid_katex_path(self) -> None:
|
def test_invalid_katex_path(self) -> None:
|
||||||
|
|
|
@ -21,7 +21,7 @@ from zerver.lib.actions import (
|
||||||
)
|
)
|
||||||
from zerver.lib.avatar import avatar_url
|
from zerver.lib.avatar import avatar_url
|
||||||
from zerver.lib.exceptions import JsonableError
|
from zerver.lib.exceptions import JsonableError
|
||||||
from zerver.lib.mention import MentionData
|
from zerver.lib.mention import MentionBackend, MentionData
|
||||||
from zerver.lib.message import (
|
from zerver.lib.message import (
|
||||||
MessageDict,
|
MessageDict,
|
||||||
get_first_visible_message_id,
|
get_first_visible_message_id,
|
||||||
|
@ -3776,7 +3776,8 @@ class MessageHasKeywordsTest(ZulipTestCase):
|
||||||
hamlet = self.example_user("hamlet")
|
hamlet = self.example_user("hamlet")
|
||||||
realm_id = hamlet.realm.id
|
realm_id = hamlet.realm.id
|
||||||
rendering_result = render_markdown(msg, content)
|
rendering_result = render_markdown(msg, content)
|
||||||
mention_data = MentionData(realm_id, content)
|
mention_backend = MentionBackend(realm_id)
|
||||||
|
mention_data = MentionData(mention_backend, content)
|
||||||
do_update_message(
|
do_update_message(
|
||||||
hamlet,
|
hamlet,
|
||||||
msg,
|
msg,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
from zerver.lib.mention import MentionData
|
from zerver.lib.mention import MentionBackend, MentionData
|
||||||
from zerver.lib.notification_data import get_user_group_mentions_data
|
from zerver.lib.notification_data import get_user_group_mentions_data
|
||||||
from zerver.lib.test_classes import ZulipTestCase
|
from zerver.lib.test_classes import ZulipTestCase
|
||||||
from zerver.lib.user_groups import create_user_group
|
from zerver.lib.user_groups import create_user_group
|
||||||
|
@ -220,11 +220,13 @@ class TestNotificationData(ZulipTestCase):
|
||||||
hamlet_only = create_user_group("hamlet_only", [hamlet], realm)
|
hamlet_only = create_user_group("hamlet_only", [hamlet], realm)
|
||||||
hamlet_and_cordelia = create_user_group("hamlet_and_cordelia", [hamlet, cordelia], realm)
|
hamlet_and_cordelia = create_user_group("hamlet_and_cordelia", [hamlet, cordelia], realm)
|
||||||
|
|
||||||
|
mention_backend = MentionBackend(realm.id)
|
||||||
|
|
||||||
# Base case. No user/user group mentions
|
# Base case. No user/user group mentions
|
||||||
result = get_user_group_mentions_data(
|
result = get_user_group_mentions_data(
|
||||||
mentioned_user_ids=set(),
|
mentioned_user_ids=set(),
|
||||||
mentioned_user_group_ids=[],
|
mentioned_user_group_ids=[],
|
||||||
mention_data=MentionData(realm.id, "no group mentioned"),
|
mention_data=MentionData(mention_backend, "no group mentioned"),
|
||||||
)
|
)
|
||||||
self.assertDictEqual(result, {})
|
self.assertDictEqual(result, {})
|
||||||
|
|
||||||
|
@ -232,7 +234,7 @@ class TestNotificationData(ZulipTestCase):
|
||||||
result = get_user_group_mentions_data(
|
result = get_user_group_mentions_data(
|
||||||
mentioned_user_ids=set(),
|
mentioned_user_ids=set(),
|
||||||
mentioned_user_group_ids=[hamlet_and_cordelia.id],
|
mentioned_user_group_ids=[hamlet_and_cordelia.id],
|
||||||
mention_data=MentionData(realm.id, "hey @*hamlet_and_cordelia*!"),
|
mention_data=MentionData(mention_backend, "hey @*hamlet_and_cordelia*!"),
|
||||||
)
|
)
|
||||||
self.assertDictEqual(
|
self.assertDictEqual(
|
||||||
result,
|
result,
|
||||||
|
@ -247,7 +249,9 @@ class TestNotificationData(ZulipTestCase):
|
||||||
result = get_user_group_mentions_data(
|
result = get_user_group_mentions_data(
|
||||||
mentioned_user_ids=set(),
|
mentioned_user_ids=set(),
|
||||||
mentioned_user_group_ids=[hamlet_and_cordelia.id, hamlet_only.id],
|
mentioned_user_group_ids=[hamlet_and_cordelia.id, hamlet_only.id],
|
||||||
mention_data=MentionData(realm.id, "hey @*hamlet_and_cordelia* and @*hamlet_only*"),
|
mention_data=MentionData(
|
||||||
|
mention_backend, "hey @*hamlet_and_cordelia* and @*hamlet_only*"
|
||||||
|
),
|
||||||
)
|
)
|
||||||
self.assertDictEqual(
|
self.assertDictEqual(
|
||||||
result,
|
result,
|
||||||
|
@ -262,7 +266,9 @@ class TestNotificationData(ZulipTestCase):
|
||||||
result = get_user_group_mentions_data(
|
result = get_user_group_mentions_data(
|
||||||
mentioned_user_ids=set(),
|
mentioned_user_ids=set(),
|
||||||
mentioned_user_group_ids=[hamlet_only.id, hamlet_and_cordelia.id],
|
mentioned_user_group_ids=[hamlet_only.id, hamlet_and_cordelia.id],
|
||||||
mention_data=MentionData(realm.id, "hey @*hamlet_only* and @*hamlet_and_cordelia*"),
|
mention_data=MentionData(
|
||||||
|
mention_backend, "hey @*hamlet_only* and @*hamlet_and_cordelia*"
|
||||||
|
),
|
||||||
)
|
)
|
||||||
self.assertDictEqual(
|
self.assertDictEqual(
|
||||||
result,
|
result,
|
||||||
|
@ -277,7 +283,7 @@ class TestNotificationData(ZulipTestCase):
|
||||||
result = get_user_group_mentions_data(
|
result = get_user_group_mentions_data(
|
||||||
mentioned_user_ids={hamlet.id},
|
mentioned_user_ids={hamlet.id},
|
||||||
mentioned_user_group_ids=[hamlet_and_cordelia.id],
|
mentioned_user_group_ids=[hamlet_and_cordelia.id],
|
||||||
mention_data=MentionData(realm.id, "hey @*hamlet_and_cordelia*!"),
|
mention_data=MentionData(mention_backend, "hey @*hamlet_and_cordelia*!"),
|
||||||
)
|
)
|
||||||
self.assertDictEqual(
|
self.assertDictEqual(
|
||||||
result,
|
result,
|
||||||
|
|
Loading…
Reference in New Issue