refactor: Rename `huddle` to `direct_message_group` in non API.

This commit performs a sweep on the first batch of non API
files to rename "huddle" to "direct_message_group`.

It also renames variables and methods of type -
"huddle_message" to "group_direct_message".

This is a part of #28640
This commit is contained in:
roanster007 2024-07-04 17:35:48 +05:30 committed by Tim Abbott
parent fa2f86ff80
commit 52692a6448
50 changed files with 647 additions and 548 deletions

View File

@ -10,7 +10,7 @@ from django.utils.translation import override as override_language
from confirmation import settings as confirmation_settings from confirmation import settings as confirmation_settings
from zerver.actions.message_send import ( from zerver.actions.message_send import (
internal_send_huddle_message, internal_send_group_direct_message,
internal_send_private_message, internal_send_private_message,
internal_send_stream_message, internal_send_stream_message,
) )
@ -87,7 +87,7 @@ def send_message_to_signup_notification_stream(
def send_group_direct_message_to_admins(sender: UserProfile, realm: Realm, content: str) -> None: def send_group_direct_message_to_admins(sender: UserProfile, realm: Realm, content: str) -> None:
administrators = list(realm.get_human_admin_users()) administrators = list(realm.get_human_admin_users())
internal_send_huddle_message( internal_send_group_direct_message(
realm, realm,
sender, sender,
content, content,

View File

@ -105,7 +105,7 @@ from zerver.models import (
from zerver.models.clients import get_client from zerver.models.clients import get_client
from zerver.models.groups import SystemGroups from zerver.models.groups import SystemGroups
from zerver.models.realms import PrivateMessagePolicyEnum from zerver.models.realms import PrivateMessagePolicyEnum
from zerver.models.recipients import get_huddle_user_ids from zerver.models.recipients import get_direct_message_group_user_ids
from zerver.models.scheduled_jobs import NotificationTriggers from zerver.models.scheduled_jobs import NotificationTriggers
from zerver.models.streams import get_stream, get_stream_by_id_in_realm from zerver.models.streams import get_stream, get_stream_by_id_in_realm
from zerver.models.users import get_system_bot, get_user_by_delivery_email, is_cross_realm_bot_email from zerver.models.users import get_system_bot, get_user_by_delivery_email, is_cross_realm_bot_email
@ -374,7 +374,7 @@ def get_recipient_info(
) )
elif recipient.type == Recipient.DIRECT_MESSAGE_GROUP: elif recipient.type == Recipient.DIRECT_MESSAGE_GROUP:
message_to_user_id_set = set(get_huddle_user_ids(recipient)) message_to_user_id_set = set(get_direct_message_group_user_ids(recipient))
else: else:
raise ValueError("Bad recipient type") raise ValueError("Bad recipient type")
@ -547,7 +547,7 @@ def get_service_bot_events(
# Mention triggers, for stream messages # Mention triggers, for stream messages
if is_stream and user_profile_id in mentioned_user_ids: if is_stream and user_profile_id in mentioned_user_ids:
trigger = "mention" trigger = "mention"
# Direct message triggers for personal and huddle messages # Direct message triggers for personal and group direct messages
elif not is_stream and user_profile_id in active_user_ids: elif not is_stream and user_profile_id in active_user_ids:
trigger = NotificationTriggers.DIRECT_MESSAGE trigger = NotificationTriggers.DIRECT_MESSAGE
else: else:
@ -1222,9 +1222,9 @@ def do_send_messages(
def already_sent_mirrored_message_id(message: Message) -> Optional[int]: def already_sent_mirrored_message_id(message: Message) -> Optional[int]:
if message.recipient.type == Recipient.DIRECT_MESSAGE_GROUP: if message.recipient.type == Recipient.DIRECT_MESSAGE_GROUP:
# For huddle messages, we use a 10-second window because the # For group direct messages, we use a 10-second window because
# timestamps aren't guaranteed to actually match between two # the timestamps aren't guaranteed to actually match between
# copies of the same message. # two copies of the same message.
time_window = timedelta(seconds=10) time_window = timedelta(seconds=10)
else: else:
time_window = timedelta(seconds=0) time_window = timedelta(seconds=0)
@ -1989,7 +1989,7 @@ def internal_send_stream_message_by_name(
return sent_message_result.message_id return sent_message_result.message_id
def internal_prep_huddle_message( def internal_prep_group_direct_message(
realm: Realm, realm: Realm,
sender: UserProfile, sender: UserProfile,
content: str, content: str,
@ -2011,7 +2011,7 @@ def internal_prep_huddle_message(
) )
def internal_send_huddle_message( def internal_send_group_direct_message(
realm: Realm, realm: Realm,
sender: UserProfile, sender: UserProfile,
content: str, content: str,
@ -2019,7 +2019,7 @@ def internal_send_huddle_message(
emails: Optional[List[str]] = None, emails: Optional[List[str]] = None,
recipient_users: Optional[List[UserProfile]] = None, recipient_users: Optional[List[UserProfile]] = None,
) -> Optional[int]: ) -> Optional[int]:
message = internal_prep_huddle_message( message = internal_prep_group_direct_message(
realm, sender, content, emails=emails, recipient_users=recipient_users realm, sender, content, emails=emails, recipient_users=recipient_users
) )

View File

@ -47,15 +47,15 @@ def check_send_typing_notification(sender: UserProfile, user_ids: List[int], ope
# If any of the user_ids being sent in are invalid, we will # If any of the user_ids being sent in are invalid, we will
# just reject the whole request, since a partial list of user_ids # just reject the whole request, since a partial list of user_ids
# can create confusion related to huddles. Plus it's a good # can create confusion related to direct message groups. Plus it's
# sign that a client is confused (or possibly even malicious) if # a good sign that a client is confused (or possibly even malicious)
# we get bad user_ids. # if we get bad user_ids.
user_profiles = [] user_profiles = []
for user_id in user_ids: for user_id in user_ids:
try: try:
# We include cross-bot realms as possible recipients, # We include cross-bot realms as possible recipients,
# so that clients can know which huddle conversation # so that clients can know which direct message group
# is relevant here. # conversation is relevant here.
user_profile = get_user_by_id_in_realm_including_cross_realm(user_id, sender.realm) user_profile = get_user_by_id_in_realm_including_cross_realm(user_id, sender.realm)
except UserProfile.DoesNotExist: except UserProfile.DoesNotExist:
raise JsonableError(_("Invalid user ID {user_id}").format(user_id=user_id)) raise JsonableError(_("Invalid user ID {user_id}").format(user_id=user_id))

View File

@ -50,30 +50,30 @@ ZerverFieldsT: TypeAlias = Dict[str, Any]
class SubscriberHandler: class SubscriberHandler:
def __init__(self) -> None: def __init__(self) -> None:
self.stream_info: Dict[int, Set[int]] = {} self.stream_info: Dict[int, Set[int]] = {}
self.huddle_info: Dict[int, Set[int]] = {} self.direct_message_group_info: Dict[int, Set[int]] = {}
def set_info( def set_info(
self, self,
users: Set[int], users: Set[int],
stream_id: Optional[int] = None, stream_id: Optional[int] = None,
huddle_id: Optional[int] = None, direct_message_group_id: Optional[int] = None,
) -> None: ) -> None:
if stream_id is not None: if stream_id is not None:
self.stream_info[stream_id] = users self.stream_info[stream_id] = users
elif huddle_id is not None: elif direct_message_group_id is not None:
self.huddle_info[huddle_id] = users self.direct_message_group_info[direct_message_group_id] = users
else: else:
raise AssertionError("stream_id or huddle_id is required") raise AssertionError("stream_id or direct_message_group_id is required")
def get_users( def get_users(
self, stream_id: Optional[int] = None, huddle_id: Optional[int] = None self, stream_id: Optional[int] = None, direct_message_group_id: Optional[int] = None
) -> Set[int]: ) -> Set[int]:
if stream_id is not None: if stream_id is not None:
return self.stream_info[stream_id] return self.stream_info[stream_id]
elif huddle_id is not None: elif direct_message_group_id is not None:
return self.huddle_info[huddle_id] return self.direct_message_group_info[direct_message_group_id]
else: else:
raise AssertionError("stream_id or huddle_id is required") raise AssertionError("stream_id or direct_message_group_id is required")
def build_zerver_realm( def build_zerver_realm(
@ -214,7 +214,7 @@ def build_subscription(recipient_id: int, user_id: int, subscription_id: int) ->
class GetUsers(Protocol): class GetUsers(Protocol):
def __call__(self, stream_id: int = ..., huddle_id: int = ...) -> Set[int]: ... def __call__(self, stream_id: int = ..., direct_message_group_id: int = ...) -> Set[int]: ...
def build_stream_subscriptions( def build_stream_subscriptions(
@ -245,24 +245,26 @@ def build_stream_subscriptions(
return subscriptions return subscriptions
def build_huddle_subscriptions( def build_direct_message_group_subscriptions(
get_users: GetUsers, get_users: GetUsers,
zerver_recipient: List[ZerverFieldsT], zerver_recipient: List[ZerverFieldsT],
zerver_huddle: List[ZerverFieldsT], zerver_direct_message_group: List[ZerverFieldsT],
) -> List[ZerverFieldsT]: ) -> List[ZerverFieldsT]:
subscriptions: List[ZerverFieldsT] = [] subscriptions: List[ZerverFieldsT] = []
huddle_ids = {huddle["id"] for huddle in zerver_huddle} direct_message_group_ids = {
direct_message_group["id"] for direct_message_group in zerver_direct_message_group
}
recipient_map = { recipient_map = {
recipient["id"]: recipient["type_id"] # recipient_id -> stream_id recipient["id"]: recipient["type_id"] # recipient_id -> stream_id
for recipient in zerver_recipient for recipient in zerver_recipient
if recipient["type"] == Recipient.DIRECT_MESSAGE_GROUP if recipient["type"] == Recipient.DIRECT_MESSAGE_GROUP
and recipient["type_id"] in huddle_ids and recipient["type_id"] in direct_message_group_ids
} }
for recipient_id, huddle_id in recipient_map.items(): for recipient_id, direct_message_group_id in recipient_map.items():
user_ids = get_users(huddle_id=huddle_id) user_ids = get_users(direct_message_group_id=direct_message_group_id)
for user_id in user_ids: for user_id in user_ids:
subscription = build_subscription( subscription = build_subscription(
recipient_id=recipient_id, recipient_id=recipient_id,
@ -307,7 +309,7 @@ def build_recipient(type_id: int, recipient_id: int, type: int) -> ZerverFieldsT
def build_recipients( def build_recipients(
zerver_userprofile: Iterable[ZerverFieldsT], zerver_userprofile: Iterable[ZerverFieldsT],
zerver_stream: Iterable[ZerverFieldsT], zerver_stream: Iterable[ZerverFieldsT],
zerver_huddle: Iterable[ZerverFieldsT] = [], zerver_direct_message_group: Iterable[ZerverFieldsT] = [],
) -> List[ZerverFieldsT]: ) -> List[ZerverFieldsT]:
""" """
This function was only used HipChat import, this function may be This function was only used HipChat import, this function may be
@ -339,8 +341,8 @@ def build_recipients(
recipient_dict = model_to_dict(recipient) recipient_dict = model_to_dict(recipient)
recipients.append(recipient_dict) recipients.append(recipient_dict)
for huddle in zerver_huddle: for direct_message_group in zerver_direct_message_group:
type_id = huddle["id"] type_id = direct_message_group["id"]
type = Recipient.DIRECT_MESSAGE_GROUP type = Recipient.DIRECT_MESSAGE_GROUP
recipient = Recipient( recipient = Recipient(
type_id=type_id, type_id=type_id,
@ -482,11 +484,11 @@ def build_stream(
return stream_dict return stream_dict
def build_huddle(huddle_id: int) -> ZerverFieldsT: def build_direct_message_group(direct_message_group_id: int) -> ZerverFieldsT:
huddle = Huddle( direct_message_group = Huddle(
id=huddle_id, id=direct_message_group_id,
) )
return model_to_dict(huddle) return model_to_dict(direct_message_group)
def build_message( def build_message(

View File

@ -21,8 +21,8 @@ from zerver.data_import.import_util import (
SubscriberHandler, SubscriberHandler,
ZerverFieldsT, ZerverFieldsT,
build_attachment, build_attachment,
build_huddle, build_direct_message_group,
build_huddle_subscriptions, build_direct_message_group_subscriptions,
build_message, build_message,
build_personal_subscriptions, build_personal_subscriptions,
build_realm, build_realm,
@ -232,17 +232,18 @@ def convert_channel_data(
return streams return streams
def generate_huddle_name(huddle_members: List[str]) -> str: def generate_direct_message_group_name(direct_message_group_members: List[str]) -> str:
# Simple hash function to generate a unique hash key for the # Simple hash function to generate a unique hash key for the
# members of a huddle. Needs to be consistent only within the # members of a direct_message_group. Needs to be consistent
# lifetime of export tool run, as it doesn't appear in the output. # only within the lifetime of export tool run, as it doesn't
# appear in the output.
import hashlib import hashlib
return hashlib.md5("".join(sorted(huddle_members)).encode()).hexdigest() return hashlib.md5("".join(sorted(direct_message_group_members)).encode()).hexdigest()
def convert_huddle_data( def convert_direct_message_group_data(
huddle_data: List[ZerverFieldsT], direct_message_group_data: List[ZerverFieldsT],
user_data_map: Dict[str, Dict[str, Any]], user_data_map: Dict[str, Dict[str, Any]],
subscriber_handler: SubscriberHandler, subscriber_handler: SubscriberHandler,
huddle_id_mapper: IdMapper, huddle_id_mapper: IdMapper,
@ -250,21 +251,23 @@ def convert_huddle_data(
realm_id: int, realm_id: int,
team_name: str, team_name: str,
) -> List[ZerverFieldsT]: ) -> List[ZerverFieldsT]:
zerver_huddle = [] zerver_direct_message_group = []
for huddle in huddle_data: for direct_message_group in direct_message_group_data:
if len(huddle["members"]) > 2: if len(direct_message_group["members"]) > 2:
huddle_name = generate_huddle_name(huddle["members"]) direct_message_group_name = generate_direct_message_group_name(
huddle_id = huddle_id_mapper.get(huddle_name) direct_message_group["members"]
huddle_dict = build_huddle(huddle_id)
huddle_user_ids = set()
for username in huddle["members"]:
huddle_user_ids.add(user_id_mapper.get(username))
subscriber_handler.set_info(
users=huddle_user_ids,
huddle_id=huddle_id,
) )
zerver_huddle.append(huddle_dict) direct_message_group_id = huddle_id_mapper.get(direct_message_group_name)
return zerver_huddle direct_message_group_dict = build_direct_message_group(direct_message_group_id)
direct_message_group_user_ids = set()
for username in direct_message_group["members"]:
direct_message_group_user_ids.add(user_id_mapper.get(username))
subscriber_handler.set_info(
users=direct_message_group_user_ids,
direct_message_group_id=direct_message_group_id,
)
zerver_direct_message_group.append(direct_message_group_dict)
return zerver_direct_message_group
def build_reactions( def build_reactions(
@ -591,12 +594,12 @@ def process_posts(
if "channel" in post_dict: if "channel" in post_dict:
message_dict["channel_name"] = post_dict["channel"] message_dict["channel_name"] = post_dict["channel"]
elif "channel_members" in post_dict: elif "channel_members" in post_dict:
# This case is for handling posts from direct messages and huddles, # This case is for handling posts from direct messages and direct message,
# not channels. Direct messages and huddles are known as direct_channels # groups not channels. Direct messages and direct message groups are known
# in Slack and hence the name channel_members. # as direct_channels in Slack and hence the name channel_members.
channel_members = post_dict["channel_members"] channel_members = post_dict["channel_members"]
if len(channel_members) > 2: if len(channel_members) > 2:
message_dict["huddle_name"] = generate_huddle_name(channel_members) message_dict["huddle_name"] = generate_direct_message_group_name(channel_members)
elif len(channel_members) == 2: elif len(channel_members) == 2:
message_dict["pm_members"] = channel_members message_dict["pm_members"] = channel_members
else: else:
@ -697,7 +700,7 @@ def write_message_data(
else: else:
post_types = ["channel_post"] post_types = ["channel_post"]
logging.warning( logging.warning(
"Skipping importing huddles and DMs since there are multiple teams in the export" "Skipping importing direct message groups and DMs since there are multiple teams in the export"
) )
for post_type in post_types: for post_type in post_types:
@ -924,10 +927,10 @@ def do_convert_data(mattermost_data_dir: str, output_dir: str, masking_content:
) )
realm["zerver_stream"] = zerver_stream realm["zerver_stream"] = zerver_stream
zerver_huddle: List[ZerverFieldsT] = [] zerver_direct_message_group: List[ZerverFieldsT] = []
if len(mattermost_data["team"]) == 1: if len(mattermost_data["team"]) == 1:
zerver_huddle = convert_huddle_data( zerver_direct_message_group = convert_direct_message_group_data(
huddle_data=mattermost_data["direct_channel"], direct_message_group_data=mattermost_data["direct_channel"],
user_data_map=username_to_user, user_data_map=username_to_user,
subscriber_handler=subscriber_handler, subscriber_handler=subscriber_handler,
huddle_id_mapper=huddle_id_mapper, huddle_id_mapper=huddle_id_mapper,
@ -935,14 +938,14 @@ def do_convert_data(mattermost_data_dir: str, output_dir: str, masking_content:
realm_id=realm_id, realm_id=realm_id,
team_name=team_name, team_name=team_name,
) )
realm["zerver_huddle"] = zerver_huddle realm["zerver_huddle"] = zerver_direct_message_group
all_users = user_handler.get_all_users() all_users = user_handler.get_all_users()
zerver_recipient = build_recipients( zerver_recipient = build_recipients(
zerver_userprofile=all_users, zerver_userprofile=all_users,
zerver_stream=zerver_stream, zerver_stream=zerver_stream,
zerver_huddle=zerver_huddle, zerver_direct_message_group=zerver_direct_message_group,
) )
realm["zerver_recipient"] = zerver_recipient realm["zerver_recipient"] = zerver_recipient
@ -952,10 +955,10 @@ def do_convert_data(mattermost_data_dir: str, output_dir: str, masking_content:
zerver_stream=zerver_stream, zerver_stream=zerver_stream,
) )
huddle_subscriptions = build_huddle_subscriptions( direct_message_group_subscriptions = build_direct_message_group_subscriptions(
get_users=subscriber_handler.get_users, get_users=subscriber_handler.get_users,
zerver_recipient=zerver_recipient, zerver_recipient=zerver_recipient,
zerver_huddle=zerver_huddle, zerver_direct_message_group=zerver_direct_message_group,
) )
personal_subscriptions = build_personal_subscriptions( personal_subscriptions = build_personal_subscriptions(
@ -963,8 +966,10 @@ def do_convert_data(mattermost_data_dir: str, output_dir: str, masking_content:
) )
# Mattermost currently supports only exporting messages from channels. # Mattermost currently supports only exporting messages from channels.
# Personal messages and huddles are not exported. # Personal and Group Direct messages are not exported.
zerver_subscription = personal_subscriptions + stream_subscriptions + huddle_subscriptions zerver_subscription = (
personal_subscriptions + stream_subscriptions + direct_message_group_subscriptions
)
realm["zerver_subscription"] = zerver_subscription realm["zerver_subscription"] = zerver_subscription
zerver_realmemoji = write_emoticon_data( zerver_realmemoji = write_emoticon_data(

View File

@ -14,8 +14,8 @@ from zerver.data_import.import_util import (
SubscriberHandler, SubscriberHandler,
ZerverFieldsT, ZerverFieldsT,
build_attachment, build_attachment,
build_huddle, build_direct_message_group,
build_huddle_subscriptions, build_direct_message_group_subscriptions,
build_message, build_message,
build_personal_subscriptions, build_personal_subscriptions,
build_realm, build_realm,
@ -238,29 +238,29 @@ def convert_stream_subscription_data(
subscriber_handler.set_info(users=users, stream_id=stream["id"]) subscriber_handler.set_info(users=users, stream_id=stream["id"])
def convert_huddle_data( def convert_direct_message_group_data(
huddle_id_to_huddle_map: Dict[str, Dict[str, Any]], huddle_id_to_huddle_map: Dict[str, Dict[str, Any]],
huddle_id_mapper: IdMapper, huddle_id_mapper: IdMapper,
user_id_mapper: IdMapper, user_id_mapper: IdMapper,
subscriber_handler: SubscriberHandler, subscriber_handler: SubscriberHandler,
) -> List[ZerverFieldsT]: ) -> List[ZerverFieldsT]:
zerver_huddle: List[ZerverFieldsT] = [] zerver_direct_message_group: List[ZerverFieldsT] = []
for rc_huddle_id in huddle_id_to_huddle_map: for rc_huddle_id in huddle_id_to_huddle_map:
huddle_id = huddle_id_mapper.get(rc_huddle_id) direct_message_group_id = huddle_id_mapper.get(rc_huddle_id)
huddle = build_huddle(huddle_id) direct_message_group = build_direct_message_group(direct_message_group_id)
zerver_huddle.append(huddle) zerver_direct_message_group.append(direct_message_group)
huddle_dict = huddle_id_to_huddle_map[rc_huddle_id] direct_message_group_dict = huddle_id_to_huddle_map[rc_huddle_id]
huddle_user_ids = set() direct_message_group_user_ids = set()
for rc_user_id in huddle_dict["uids"]: for rc_user_id in direct_message_group_dict["uids"]:
huddle_user_ids.add(user_id_mapper.get(rc_user_id)) direct_message_group_user_ids.add(user_id_mapper.get(rc_user_id))
subscriber_handler.set_info( subscriber_handler.set_info(
users=huddle_user_ids, users=direct_message_group_user_ids,
huddle_id=huddle_id, direct_message_group_id=direct_message_group_id,
) )
return zerver_huddle return zerver_direct_message_group
def build_custom_emoji( def build_custom_emoji(
@ -679,8 +679,8 @@ def process_messages(
# Message is in a 1:1 or group direct message. # Message is in a 1:1 or group direct message.
rc_channel_id = message["rid"] rc_channel_id = message["rid"]
if rc_channel_id in huddle_id_to_huddle_map: if rc_channel_id in huddle_id_to_huddle_map:
huddle_id = huddle_id_mapper.get(rc_channel_id) direct_message_group_id = huddle_id_mapper.get(rc_channel_id)
message_dict["recipient_id"] = huddle_id_to_recipient_id[huddle_id] message_dict["recipient_id"] = huddle_id_to_recipient_id[direct_message_group_id]
else: else:
rc_member_ids = direct_id_to_direct_map[rc_channel_id]["uids"] rc_member_ids = direct_id_to_direct_map[rc_channel_id]["uids"]
@ -876,7 +876,7 @@ def map_receiver_id_to_recipient_id(
huddle_id_to_recipient_id: Dict[int, int], huddle_id_to_recipient_id: Dict[int, int],
user_id_to_recipient_id: Dict[int, int], user_id_to_recipient_id: Dict[int, int],
) -> None: ) -> None:
# receiver_id represents stream_id/huddle_id/user_id # receiver_id represents stream_id/direct_message_group_id/user_id
for recipient in zerver_recipient: for recipient in zerver_recipient:
if recipient["type"] == Recipient.STREAM: if recipient["type"] == Recipient.STREAM:
stream_id_to_recipient_id[recipient["type_id"]] = recipient["id"] stream_id_to_recipient_id[recipient["type_id"]] = recipient["id"]
@ -886,16 +886,18 @@ def map_receiver_id_to_recipient_id(
user_id_to_recipient_id[recipient["type_id"]] = recipient["id"] user_id_to_recipient_id[recipient["type_id"]] = recipient["id"]
# This is inspired by get_huddle_hash from zerver/models/recipients.py. It # This is inspired by get_direct_message_group_hash
# expects strings identifying Rocket.Chat users, like # from zerver/models/recipients.py. It expects strings
# `LdBZ7kPxtKESyHPEe`, not integer IDs. # identifying Rocket.Chat users, like `LdBZ7kPxtKESyHPEe`,
# not integer IDs.
# #
# Its purpose is to be a stable map usable for deduplication/merging # Its purpose is to be a stable map usable for deduplication/merging
# of Rocket.Chat threads involving the same set of people. Thus, its # of Rocket.Chat threads involving the same set of people. Thus, its
# only important property is that if two sets of users S and T are # only important property is that if two sets of users S and T are
# equal and thus will have the same actual huddle hash once imported, # equal and thus will have the same actual direct message group hash
# that get_string_huddle_hash(S) = get_string_huddle_hash(T). # once imported, that get_string_direct_message_group_hash(S) =
def get_string_huddle_hash(id_list: List[str]) -> str: # get_string_direct_message_group_hash(T).
def get_string_direct_message_group_hash(id_list: List[str]) -> str:
id_list = sorted(set(id_list)) id_list = sorted(set(id_list))
hash_key = ",".join(str(x) for x in id_list) hash_key = ",".join(str(x) for x in id_list)
return hashlib.sha1(hash_key.encode()).hexdigest() return hashlib.sha1(hash_key.encode()).hexdigest()
@ -910,15 +912,17 @@ def categorize_channels_and_map_with_id(
huddle_id_to_huddle_map: Dict[str, Dict[str, Any]], huddle_id_to_huddle_map: Dict[str, Dict[str, Any]],
livechat_id_to_livechat_map: Dict[str, Dict[str, Any]], livechat_id_to_livechat_map: Dict[str, Dict[str, Any]],
) -> None: ) -> None:
huddle_hashed_channels: Dict[str, Any] = {} direct_message_group_hashed_channels: Dict[str, Any] = {}
for channel in channel_data: for channel in channel_data:
if channel.get("prid"): if channel.get("prid"):
dsc_id_to_dsc_map[channel["_id"]] = channel dsc_id_to_dsc_map[channel["_id"]] = channel
elif channel["t"] == "d": elif channel["t"] == "d":
if len(channel["uids"]) > 2: if len(channel["uids"]) > 2:
huddle_hash = get_string_huddle_hash(channel["uids"]) direct_message_group_hash = get_string_direct_message_group_hash(channel["uids"])
logging.info( logging.info(
"Huddle channel found. UIDs: %s -> hash %s", channel["uids"], huddle_hash "Huddle channel found. UIDs: %s -> hash %s",
channel["uids"],
direct_message_group_hash,
) )
if channel["msgs"] == 0: # nocoverage if channel["msgs"] == 0: # nocoverage
@ -926,25 +930,29 @@ def categorize_channels_and_map_with_id(
# contain duplicates of real huddles, with no # contain duplicates of real huddles, with no
# messages in the duplicate. We ignore these # messages in the duplicate. We ignore these
# minor database corruptions in the Rocket.Chat # minor database corruptions in the Rocket.Chat
# export. Doing so is safe, because a huddle with no # export. Doing so is safe, because a direct
# message history has no value in Zulip's data # message group with no message history has no
# model. # value in Zulip's data model.
logging.debug("Skipping huddle with 0 messages: %s", channel) logging.debug("Skipping direct message group with 0 messages: %s", channel)
elif huddle_hash in huddle_hashed_channels: # nocoverage elif (
direct_message_group_hash in direct_message_group_hashed_channels
): # nocoverage
logging.info( logging.info(
"Mapping huddle hash %s to existing channel: %s", "Mapping direct message group hash %s to existing channel: %s",
huddle_hash, direct_message_group_hash,
huddle_hashed_channels[huddle_hash], direct_message_group_hashed_channels[direct_message_group_hash],
) )
huddle_id_to_huddle_map[channel["_id"]] = huddle_hashed_channels[huddle_hash] huddle_id_to_huddle_map[channel["_id"]] = direct_message_group_hashed_channels[
direct_message_group_hash
]
# Ideally, we'd merge the duplicate huddles. Doing # Ideally, we'd merge the duplicate direct message
# so correctly requires special handling in # groups. Doing so correctly requires special
# convert_huddle_data() and on the message import # handling in convert_direct_message_group_data()
# side as well, since those appear to be mapped # and on the message import side as well, since
# via rocketchat channel IDs and not all of that # those appear to be mapped via rocketchat channel
# information is resolved via the # IDs and not all of that information is resolved
# huddle_id_to_huddle_map. # via the huddle_id_to_huddle_map.
# #
# For now, just throw an exception here rather # For now, just throw an exception here rather
# than during the import process. # than during the import process.
@ -953,7 +961,7 @@ def categorize_channels_and_map_with_id(
) )
else: else:
huddle_id_to_huddle_map[channel["_id"]] = channel huddle_id_to_huddle_map[channel["_id"]] = channel
huddle_hashed_channels[huddle_hash] = channel direct_message_group_hashed_channels[direct_message_group_hash] = channel
else: else:
direct_id_to_direct_map[channel["_id"]] = channel direct_id_to_direct_map[channel["_id"]] = channel
elif channel["t"] == "l": elif channel["t"] == "l":
@ -1114,20 +1122,20 @@ def do_convert_data(rocketchat_data_dir: str, output_dir: str) -> None:
subscriber_handler=subscriber_handler, subscriber_handler=subscriber_handler,
) )
zerver_huddle = convert_huddle_data( zerver_direct_message_group = convert_direct_message_group_data(
huddle_id_to_huddle_map=huddle_id_to_huddle_map, huddle_id_to_huddle_map=huddle_id_to_huddle_map,
huddle_id_mapper=huddle_id_mapper, huddle_id_mapper=huddle_id_mapper,
user_id_mapper=user_id_mapper, user_id_mapper=user_id_mapper,
subscriber_handler=subscriber_handler, subscriber_handler=subscriber_handler,
) )
realm["zerver_huddle"] = zerver_huddle realm["zerver_huddle"] = zerver_direct_message_group
all_users = user_handler.get_all_users() all_users = user_handler.get_all_users()
zerver_recipient = build_recipients( zerver_recipient = build_recipients(
zerver_userprofile=all_users, zerver_userprofile=all_users,
zerver_stream=zerver_stream, zerver_stream=zerver_stream,
zerver_huddle=zerver_huddle, zerver_direct_message_group=zerver_direct_message_group,
) )
realm["zerver_recipient"] = zerver_recipient realm["zerver_recipient"] = zerver_recipient
@ -1137,17 +1145,19 @@ def do_convert_data(rocketchat_data_dir: str, output_dir: str) -> None:
zerver_stream=zerver_stream, zerver_stream=zerver_stream,
) )
huddle_subscriptions = build_huddle_subscriptions( direct_message_group_subscriptions = build_direct_message_group_subscriptions(
get_users=subscriber_handler.get_users, get_users=subscriber_handler.get_users,
zerver_recipient=zerver_recipient, zerver_recipient=zerver_recipient,
zerver_huddle=zerver_huddle, zerver_direct_message_group=zerver_direct_message_group,
) )
personal_subscriptions = build_personal_subscriptions( personal_subscriptions = build_personal_subscriptions(
zerver_recipient=zerver_recipient, zerver_recipient=zerver_recipient,
) )
zerver_subscription = personal_subscriptions + stream_subscriptions + huddle_subscriptions zerver_subscription = (
personal_subscriptions + stream_subscriptions + direct_message_group_subscriptions
)
realm["zerver_subscription"] = zerver_subscription realm["zerver_subscription"] = zerver_subscription
zerver_realmemoji = build_custom_emoji( zerver_realmemoji = build_custom_emoji(

View File

@ -24,7 +24,7 @@ from zerver.data_import.import_util import (
build_attachment, build_attachment,
build_avatar, build_avatar,
build_defaultstream, build_defaultstream,
build_huddle, build_direct_message_group,
build_message, build_message,
build_realm, build_realm,
build_recipient, build_recipient,
@ -160,7 +160,7 @@ def slack_workspace_to_realm(
3. slack_recipient_name_to_zulip_recipient_id, which is a dictionary to map from Slack recipient 3. slack_recipient_name_to_zulip_recipient_id, which is a dictionary to map from Slack recipient
name(channel names, mpim names, usernames, etc) to Zulip recipient id name(channel names, mpim names, usernames, etc) to Zulip recipient id
4. added_channels, which is a dictionary to map from channel name to channel id, Zulip stream_id 4. added_channels, which is a dictionary to map from channel name to channel id, Zulip stream_id
5. added_mpims, which is a dictionary to map from MPIM name to MPIM id, Zulip huddle_id 5. added_mpims, which is a dictionary to map from MPIM name to MPIM id, Zulip direct_message_group_id
6. dm_members, which is a dictionary to map from DM id to tuple of DM participants. 6. dm_members, which is a dictionary to map from DM id to tuple of DM participants.
7. avatars, which is list to map avatars to Zulip avatar records.json 7. avatars, which is list to map avatars to Zulip avatar records.json
8. emoji_url_map, which is maps emoji name to its Slack URL 8. emoji_url_map, which is maps emoji name to its Slack URL
@ -507,7 +507,8 @@ def channels_to_zerver_stream(
Returns: Returns:
1. realm, converted realm data 1. realm, converted realm data
2. added_channels, which is a dictionary to map from channel name to channel id, Zulip stream_id 2. added_channels, which is a dictionary to map from channel name to channel id, Zulip stream_id
3. added_mpims, which is a dictionary to map from MPIM(multiparty IM) name to MPIM id, Zulip huddle_id 3. added_mpims, which is a dictionary to map from MPIM(multiparty IM) name to MPIM id, Zulip
direct_message_group_id
4. dm_members, which is a dictionary to map from DM id to tuple of DM participants. 4. dm_members, which is a dictionary to map from DM id to tuple of DM participants.
5. slack_recipient_name_to_zulip_recipient_id, which is a dictionary to map from Slack recipient 5. slack_recipient_name_to_zulip_recipient_id, which is a dictionary to map from Slack recipient
name(channel names, mpim names, usernames etc) to Zulip recipient_id name(channel names, mpim names, usernames etc) to Zulip recipient_id
@ -527,7 +528,7 @@ def channels_to_zerver_stream(
subscription_id_count = recipient_id_count = 0 subscription_id_count = recipient_id_count = 0
stream_id_count = defaultstream_id = 0 stream_id_count = defaultstream_id = 0
huddle_id_count = 0 direct_message_group_id_count = 0
def process_channels(channels: List[Dict[str, Any]], invite_only: bool = False) -> None: def process_channels(channels: List[Dict[str, Any]], invite_only: bool = False) -> None:
nonlocal stream_id_count nonlocal stream_id_count
@ -600,20 +601,20 @@ def channels_to_zerver_stream(
private_channels = [] private_channels = []
process_channels(private_channels, True) process_channels(private_channels, True)
# mpim is the Slack equivalent of huddle. # mpim is the Slack equivalent of direct message group.
def process_mpims(mpims: List[Dict[str, Any]]) -> None: def process_mpims(mpims: List[Dict[str, Any]]) -> None:
nonlocal huddle_id_count nonlocal direct_message_group_id_count
nonlocal recipient_id_count nonlocal recipient_id_count
nonlocal subscription_id_count nonlocal subscription_id_count
for mpim in mpims: for mpim in mpims:
huddle = build_huddle(huddle_id_count) direct_message_group = build_direct_message_group(direct_message_group_id_count)
realm["zerver_huddle"].append(huddle) realm["zerver_huddle"].append(direct_message_group)
added_mpims[mpim["name"]] = (mpim["id"], huddle_id_count) added_mpims[mpim["name"]] = (mpim["id"], direct_message_group_id_count)
recipient = build_recipient( recipient = build_recipient(
huddle_id_count, recipient_id_count, Recipient.DIRECT_MESSAGE_GROUP direct_message_group_id_count, recipient_id_count, Recipient.DIRECT_MESSAGE_GROUP
) )
realm["zerver_recipient"].append(recipient) realm["zerver_recipient"].append(recipient)
slack_recipient_name_to_zulip_recipient_id[mpim["name"]] = recipient_id_count slack_recipient_name_to_zulip_recipient_id[mpim["name"]] = recipient_id_count
@ -626,7 +627,7 @@ def channels_to_zerver_stream(
subscription_id_count, subscription_id_count,
) )
huddle_id_count += 1 direct_message_group_id_count += 1
recipient_id_count += 1 recipient_id_count += 1
logging.info("%s -> created", mpim["name"]) logging.info("%s -> created", mpim["name"])
@ -1267,10 +1268,10 @@ def fetch_shared_channel_users(
except FileNotFoundError: except FileNotFoundError:
private_channels = [] private_channels = []
try: try:
huddles = get_data_file(slack_data_dir + "/mpims.json") direct_message_groups = get_data_file(slack_data_dir + "/mpims.json")
except FileNotFoundError: except FileNotFoundError:
huddles = [] direct_message_groups = []
for channel in public_channels + private_channels + huddles: for channel in public_channels + private_channels + direct_message_groups:
added_channels[channel["name"]] = True added_channels[channel["name"]] = True
for user_id in channel["members"]: for user_id in channel["members"]:
if user_id not in normal_user_ids: if user_id not in normal_user_ids:

View File

@ -7,7 +7,7 @@ from django.utils.translation import gettext as _
from zulip_bots.lib import BotIdentity, RateLimit from zulip_bots.lib import BotIdentity, RateLimit
from zerver.actions.message_send import ( from zerver.actions.message_send import (
internal_send_huddle_message, internal_send_group_direct_message,
internal_send_private_message, internal_send_private_message,
internal_send_stream_message_by_name, internal_send_stream_message_by_name,
) )
@ -109,7 +109,7 @@ class EmbeddedBotHandler:
self.user_profile, recipient_user, message["content"] self.user_profile, recipient_user, message["content"]
) )
else: else:
message_id = internal_send_huddle_message( message_id = internal_send_group_direct_message(
self.user_profile.realm, self.user_profile, message["content"], emails=recipients self.user_profile.realm, self.user_profile, message["content"], emails=recipients
) )
return {"id": message_id} return {"id": message_id}

View File

@ -135,7 +135,7 @@ def bulk_fetch_user_display_recipients(
""" """
from zerver.models import Recipient from zerver.models import Recipient
from zerver.models.recipients import bulk_get_huddle_user_ids from zerver.models.recipients import bulk_get_direct_message_group_user_ids
if len(recipient_tuples) == 0: if len(recipient_tuples) == 0:
return {} return {}
@ -144,12 +144,16 @@ def bulk_fetch_user_display_recipients(
get_type = lambda tup: tup[1] get_type = lambda tup: tup[1]
personal_tuples = [tup for tup in recipient_tuples if get_type(tup) == Recipient.PERSONAL] personal_tuples = [tup for tup in recipient_tuples if get_type(tup) == Recipient.PERSONAL]
huddle_tuples = [ direct_message_group_tuples = [
tup for tup in recipient_tuples if get_type(tup) == Recipient.DIRECT_MESSAGE_GROUP tup for tup in recipient_tuples if get_type(tup) == Recipient.DIRECT_MESSAGE_GROUP
] ]
huddle_recipient_ids = [get_recipient_id(tup) for tup in huddle_tuples] direct_message_group_recipient_ids = [
huddle_recipient_id_to_user_ids = bulk_get_huddle_user_ids(huddle_recipient_ids) get_recipient_id(tup) for tup in direct_message_group_tuples
]
huddle_recipient_id_to_user_ids = bulk_get_direct_message_group_user_ids(
direct_message_group_recipient_ids
)
# Find all user ids whose UserProfiles we will need to fetch: # Find all user ids whose UserProfiles we will need to fetch:
user_ids_to_fetch: Set[int] = set() user_ids_to_fetch: Set[int] = set()
@ -157,9 +161,9 @@ def bulk_fetch_user_display_recipients(
for ignore_recipient_id, ignore_recipient_type, user_id in personal_tuples: for ignore_recipient_id, ignore_recipient_type, user_id in personal_tuples:
user_ids_to_fetch.add(user_id) user_ids_to_fetch.add(user_id)
for recipient_id in huddle_recipient_ids: for recipient_id in direct_message_group_recipient_ids:
huddle_user_ids = huddle_recipient_id_to_user_ids[recipient_id] direct_message_group_user_ids = huddle_recipient_id_to_user_ids[recipient_id]
user_ids_to_fetch |= huddle_user_ids user_ids_to_fetch |= direct_message_group_user_ids
# Fetch the needed user dictionaries. # Fetch the needed user dictionaries.
user_display_recipients = bulk_fetch_single_user_display_recipients(list(user_ids_to_fetch)) user_display_recipients = bulk_fetch_single_user_display_recipients(list(user_ids_to_fetch))
@ -170,7 +174,7 @@ def bulk_fetch_user_display_recipients(
display_recipients = [user_display_recipients[user_id]] display_recipients = [user_display_recipients[user_id]]
result[recipient_id] = display_recipients result[recipient_id] = display_recipients
for recipient_id in huddle_recipient_ids: for recipient_id in direct_message_group_recipient_ids:
user_ids = sorted(huddle_recipient_id_to_user_ids[recipient_id]) user_ids = sorted(huddle_recipient_id_to_user_ids[recipient_id])
display_recipients = [user_display_recipients[user_id] for user_id in user_ids] display_recipients = [user_display_recipients[user_id] for user_id in user_ids]
result[recipient_id] = display_recipients result[recipient_id] = display_recipients
@ -191,15 +195,15 @@ def bulk_fetch_display_recipients(
stream_recipients = { stream_recipients = {
recipient for recipient in recipient_tuples if recipient[1] == Recipient.STREAM recipient for recipient in recipient_tuples if recipient[1] == Recipient.STREAM
} }
personal_and_huddle_recipients = recipient_tuples - stream_recipients direct_message_recipients = recipient_tuples - stream_recipients
stream_display_recipients = bulk_fetch_stream_names(stream_recipients) stream_display_recipients = bulk_fetch_stream_names(stream_recipients)
personal_and_huddle_display_recipients = bulk_fetch_user_display_recipients( direct_message_display_recipients = bulk_fetch_user_display_recipients(
personal_and_huddle_recipients direct_message_recipients
) )
# Glue the dicts together and return: # Glue the dicts together and return:
return {**stream_display_recipients, **personal_and_huddle_display_recipients} return {**stream_display_recipients, **direct_message_display_recipients}
@return_same_value_during_entire_request @return_same_value_during_entire_request

View File

@ -11,7 +11,7 @@ from typing_extensions import override
from zerver.actions.message_send import ( from zerver.actions.message_send import (
check_send_message, check_send_message,
internal_send_huddle_message, internal_send_group_direct_message,
internal_send_private_message, internal_send_private_message,
internal_send_stream_message, internal_send_stream_message,
) )
@ -458,7 +458,7 @@ def process_missed_message(to: str, message: EmailMessage) -> None:
display_recipient = get_display_recipient(recipient) display_recipient = get_display_recipient(recipient)
emails = [user_dict["email"] for user_dict in display_recipient] emails = [user_dict["email"] for user_dict in display_recipient]
recipient_str = ", ".join(emails) recipient_str = ", ".join(emails)
internal_send_huddle_message(user_profile.realm, user_profile, body, emails=emails) internal_send_group_direct_message(user_profile.realm, user_profile, body, emails=emails)
else: else:
raise AssertionError("Invalid recipient type!") raise AssertionError("Invalid recipient type!")

View File

@ -33,7 +33,7 @@ from zerver.lib.tex import change_katex_to_raw_latex
from zerver.lib.timezone import canonicalize_timezone from zerver.lib.timezone import canonicalize_timezone
from zerver.lib.topic import get_topic_resolution_and_bare_name from zerver.lib.topic import get_topic_resolution_and_bare_name
from zerver.lib.url_encoding import ( from zerver.lib.url_encoding import (
huddle_narrow_url, direct_message_group_narrow_url,
personal_narrow_url, personal_narrow_url,
stream_narrow_url, stream_narrow_url,
topic_narrow_url, topic_narrow_url,
@ -262,7 +262,7 @@ def build_message_list(
elif message.recipient.type == Recipient.DIRECT_MESSAGE_GROUP: elif message.recipient.type == Recipient.DIRECT_MESSAGE_GROUP:
grouping = {"huddle": message.recipient_id} grouping = {"huddle": message.recipient_id}
display_recipient = get_display_recipient(message.recipient) display_recipient = get_display_recipient(message.recipient)
narrow_link = huddle_narrow_url( narrow_link = direct_message_group_narrow_url(
user=user, user=user,
display_recipient=display_recipient, display_recipient=display_recipient,
) )
@ -385,8 +385,8 @@ def do_send_missedmessage_events_reply_in_zulip(
The email will have its reply to address set to a limited used email The email will have its reply to address set to a limited used email
address that will send a Zulip message to the correct recipient. This address that will send a Zulip message to the correct recipient. This
allows the user to respond to missed direct messages, huddles, and allows the user to respond to missed direct messages, direct message
@-mentions directly from the email. groups, and @-mentions directly from the email.
`user_profile` is the user to send the reminder to `user_profile` is the user to send the reminder to
`missed_messages` is a list of dictionaries to Message objects and other data `missed_messages` is a list of dictionaries to Message objects and other data
@ -474,7 +474,7 @@ def do_send_missedmessage_events_reply_in_zulip(
senders = list({m["message"].sender for m in missed_messages}) senders = list({m["message"].sender for m in missed_messages})
if missed_messages[0]["message"].recipient.type == Recipient.DIRECT_MESSAGE_GROUP: if missed_messages[0]["message"].recipient.type == Recipient.DIRECT_MESSAGE_GROUP:
display_recipient = get_display_recipient(missed_messages[0]["message"].recipient) display_recipient = get_display_recipient(missed_messages[0]["message"].recipient)
narrow_url = huddle_narrow_url( narrow_url = direct_message_group_narrow_url(
user=user_profile, user=user_profile,
display_recipient=display_recipient, display_recipient=display_recipient,
) )
@ -482,18 +482,18 @@ def do_send_missedmessage_events_reply_in_zulip(
other_recipients = [r["full_name"] for r in display_recipient if r["id"] != user_profile.id] other_recipients = [r["full_name"] for r in display_recipient if r["id"] != user_profile.id]
context.update(group_pm=True) context.update(group_pm=True)
if len(other_recipients) == 2: if len(other_recipients) == 2:
huddle_display_name = " and ".join(other_recipients) direct_message_group_display_name = " and ".join(other_recipients)
context.update(huddle_display_name=huddle_display_name) context.update(huddle_display_name=direct_message_group_display_name)
elif len(other_recipients) == 3: elif len(other_recipients) == 3:
huddle_display_name = ( direct_message_group_display_name = (
f"{other_recipients[0]}, {other_recipients[1]}, and {other_recipients[2]}" f"{other_recipients[0]}, {other_recipients[1]}, and {other_recipients[2]}"
) )
context.update(huddle_display_name=huddle_display_name) context.update(huddle_display_name=direct_message_group_display_name)
else: else:
huddle_display_name = "{}, and {} others".format( direct_message_group_display_name = "{}, and {} others".format(
", ".join(other_recipients[:2]), len(other_recipients) - 2 ", ".join(other_recipients[:2]), len(other_recipients) - 2
) )
context.update(huddle_display_name=huddle_display_name) context.update(huddle_display_name=direct_message_group_display_name)
elif missed_messages[0]["message"].recipient.type == Recipient.PERSONAL: elif missed_messages[0]["message"].recipient.type == Recipient.PERSONAL:
narrow_url = personal_narrow_url( narrow_url = personal_narrow_url(
realm=user_profile.realm, realm=user_profile.realm,

View File

@ -886,7 +886,7 @@ def get_realm_config() -> Config:
"zerver_huddle", "zerver_huddle",
], ],
virtual_parent=user_profile_config, virtual_parent=user_profile_config,
custom_fetch=custom_fetch_huddle_objects, custom_fetch=custom_fetch_direct_message_groups,
) )
# Now build permanent tables from our temp tables. # Now build permanent tables from our temp tables.
@ -1118,7 +1118,7 @@ def fetch_reaction_data(response: TableData, message_ids: Set[int]) -> None:
response["zerver_reaction"] = make_raw(list(query)) response["zerver_reaction"] = make_raw(list(query))
def custom_fetch_huddle_objects(response: TableData, context: Context) -> None: def custom_fetch_direct_message_groups(response: TableData, context: Context) -> None:
realm = context["realm"] realm = context["realm"]
user_profile_ids = { user_profile_ids = {
r["id"] for r in response["zerver_userprofile"] + response["zerver_userprofile_mirrordummy"] r["id"] for r in response["zerver_userprofile"] + response["zerver_userprofile_mirrordummy"]

View File

@ -83,7 +83,7 @@ from zerver.models import (
from zerver.models.groups import SystemGroups from zerver.models.groups import SystemGroups
from zerver.models.presence import PresenceSequence from zerver.models.presence import PresenceSequence
from zerver.models.realms import get_realm from zerver.models.realms import get_realm
from zerver.models.recipients import get_huddle_hash from zerver.models.recipients import get_direct_message_group_hash
from zerver.models.users import get_system_bot, get_user_profile_by_id from zerver.models.users import get_system_bot, get_user_profile_by_id
from zproject.backends import AUTH_BACKEND_NAME_MAP from zproject.backends import AUTH_BACKEND_NAME_MAP
@ -277,19 +277,21 @@ def fix_service_tokens(data: TableData, table: TableName) -> None:
item["token"] = generate_api_key() item["token"] = generate_api_key()
def process_huddle_hash(data: TableData, table: TableName) -> None: def process_direct_message_group_hash(data: TableData, table: TableName) -> None:
""" """
Build new huddle hashes with the updated ids of the users Build new direct message group hashes with the updated ids of the users
""" """
for huddle in data[table]: for direct_message_group in data[table]:
user_id_list = id_map_to_list["huddle_to_user_list"][huddle["id"]] user_id_list = id_map_to_list["huddle_to_user_list"][direct_message_group["id"]]
huddle["huddle_hash"] = get_huddle_hash(user_id_list) direct_message_group["huddle_hash"] = get_direct_message_group_hash(user_id_list)
def get_huddles_from_subscription(data: TableData, table: TableName) -> None: def get_direct_message_groups_from_subscription(data: TableData, table: TableName) -> None:
""" """
Extract the IDs of the user_profiles involved in a huddle from the subscription object Extract the IDs of the user_profiles involved in a direct message group from
This helps to generate a unique huddle hash from the updated user_profile ids the subscription object
This helps to generate a unique direct message group hash from the updated
user_profile ids
""" """
id_map_to_list["huddle_to_user_list"] = { id_map_to_list["huddle_to_user_list"] = {
value: [] for value in ID_MAP["recipient_to_huddle_map"].values() value: [] for value in ID_MAP["recipient_to_huddle_map"].values()
@ -297,8 +299,10 @@ def get_huddles_from_subscription(data: TableData, table: TableName) -> None:
for subscription in data[table]: for subscription in data[table]:
if subscription["recipient"] in ID_MAP["recipient_to_huddle_map"]: if subscription["recipient"] in ID_MAP["recipient_to_huddle_map"]:
huddle_id = ID_MAP["recipient_to_huddle_map"][subscription["recipient"]] direct_message_group_id = ID_MAP["recipient_to_huddle_map"][subscription["recipient"]]
id_map_to_list["huddle_to_user_list"][huddle_id].append(subscription["user_profile_id"]) id_map_to_list["huddle_to_user_list"][direct_message_group_id].append(
subscription["user_profile_id"]
)
def fix_customprofilefield(data: TableData) -> None: def fix_customprofilefield(data: TableData) -> None:
@ -550,10 +554,10 @@ def re_map_foreign_keys_internal(
elif related_table == "user_profile" and item["type"] == 1: elif related_table == "user_profile" and item["type"] == 1:
pass pass
elif related_table == "huddle" and item["type"] == 3: elif related_table == "huddle" and item["type"] == 3:
# save the recipient id with the huddle id, so that we can extract # save the recipient id with the direct message group id, so that
# the user_profile ids involved in a huddle with the help of the # we can extract the user_profile ids involved in a direct message
# subscription object # group with the help of the subscription object
# check function 'get_huddles_from_subscription' # check function 'get_direct_message_groups_from_subscription'
ID_MAP["recipient_to_huddle_map"][item["id"]] = lookup_table[old_id] ID_MAP["recipient_to_huddle_map"][item["id"]] = lookup_table[old_id]
else: else:
continue continue
@ -672,9 +676,9 @@ def remove_denormalized_recipient_column_from_data(data: TableData) -> None:
if "recipient" in user_profile_dict: if "recipient" in user_profile_dict:
del user_profile_dict["recipient"] del user_profile_dict["recipient"]
for huddle_dict in data["zerver_huddle"]: for direct_message_group_dict in data["zerver_huddle"]:
if "recipient" in huddle_dict: if "recipient" in direct_message_group_dict:
del huddle_dict["recipient"] del direct_message_group_dict["recipient"]
def get_db_table(model_class: Any) -> str: def get_db_table(model_class: Any) -> str:
@ -1226,10 +1230,11 @@ def do_import_realm(import_dir: Path, subdomain: str, processes: int = 1) -> Rea
if "zerver_huddle" in data: if "zerver_huddle" in data:
update_model_ids(Huddle, data, "huddle") update_model_ids(Huddle, data, "huddle")
# We don't import Huddle yet, since we don't have the data to # We don't import Huddle yet, since we don't have the data to
# compute huddle hashes until we've imported some of the # compute direct message group hashes until we've imported some
# tables below. # of the tables below.
# We can't get huddle hashes without processing subscriptions # We can't get direct message group hashes without processing
# first, during which get_huddles_from_subscription is called. # subscriptions first, during which
# get_direct_message_groups_from_subscription is called.
re_map_foreign_keys( re_map_foreign_keys(
data, data,
@ -1261,7 +1266,7 @@ def do_import_realm(import_dir: Path, subdomain: str, processes: int = 1) -> Rea
bulk_set_users_or_streams_recipient_fields(UserProfile, UserProfile.objects.filter(realm=realm)) bulk_set_users_or_streams_recipient_fields(UserProfile, UserProfile.objects.filter(realm=realm))
re_map_foreign_keys(data, "zerver_subscription", "user_profile", related_table="user_profile") re_map_foreign_keys(data, "zerver_subscription", "user_profile", related_table="user_profile")
get_huddles_from_subscription(data, "zerver_subscription") get_direct_message_groups_from_subscription(data, "zerver_subscription")
re_map_foreign_keys(data, "zerver_subscription", "recipient", related_table="recipient") re_map_foreign_keys(data, "zerver_subscription", "recipient", related_table="recipient")
update_model_ids(Subscription, data, "subscription") update_model_ids(Subscription, data, "subscription")
fix_subscriptions_is_user_active_column(data, user_profiles, crossrealm_user_ids) fix_subscriptions_is_user_active_column(data, user_profiles, crossrealm_user_ids)
@ -1307,14 +1312,14 @@ def do_import_realm(import_dir: Path, subdomain: str, processes: int = 1) -> Rea
) )
if "zerver_huddle" in data: if "zerver_huddle" in data:
process_huddle_hash(data, "zerver_huddle") process_direct_message_group_hash(data, "zerver_huddle")
bulk_import_model(data, Huddle) bulk_import_model(data, Huddle)
for huddle in Huddle.objects.filter(recipient=None): for direct_message_group in Huddle.objects.filter(recipient=None):
recipient = Recipient.objects.get( recipient = Recipient.objects.get(
type=Recipient.DIRECT_MESSAGE_GROUP, type_id=huddle.id type=Recipient.DIRECT_MESSAGE_GROUP, type_id=direct_message_group.id
) )
huddle.recipient = recipient direct_message_group.recipient = recipient
huddle.save(update_fields=["recipient"]) direct_message_group.save(update_fields=["recipient"])
if "zerver_alertword" in data: if "zerver_alertword" in data:
re_map_foreign_keys(data, "zerver_alertword", "user_profile", related_table="user_profile") re_map_foreign_keys(data, "zerver_alertword", "user_profile", related_table="user_profile")

View File

@ -81,14 +81,14 @@ class RawUnreadDirectMessageDict(TypedDict):
other_user_id: int other_user_id: int
class RawUnreadHuddleDict(TypedDict): class RawUnreadDirectMessageGroupDict(TypedDict):
user_ids_string: str user_ids_string: str
class RawUnreadMessagesResult(TypedDict): class RawUnreadMessagesResult(TypedDict):
pm_dict: Dict[int, RawUnreadDirectMessageDict] pm_dict: Dict[int, RawUnreadDirectMessageDict]
stream_dict: Dict[int, RawUnreadStreamDict] stream_dict: Dict[int, RawUnreadStreamDict]
huddle_dict: Dict[int, RawUnreadHuddleDict] huddle_dict: Dict[int, RawUnreadDirectMessageGroupDict]
mentions: Set[int] mentions: Set[int]
muted_stream_ids: Set[int] muted_stream_ids: Set[int]
unmuted_stream_msgs: Set[int] unmuted_stream_msgs: Set[int]
@ -108,7 +108,7 @@ class UnreadDirectMessageInfo(TypedDict):
unread_message_ids: List[int] unread_message_ids: List[int]
class UnreadHuddleInfo(TypedDict): class UnreadDirectMessageGroupInfo(TypedDict):
user_ids_string: str user_ids_string: str
unread_message_ids: List[int] unread_message_ids: List[int]
@ -116,7 +116,7 @@ class UnreadHuddleInfo(TypedDict):
class UnreadMessagesResult(TypedDict): class UnreadMessagesResult(TypedDict):
pms: List[UnreadDirectMessageInfo] pms: List[UnreadDirectMessageInfo]
streams: List[UnreadStreamInfo] streams: List[UnreadStreamInfo]
huddles: List[UnreadHuddleInfo] huddles: List[UnreadDirectMessageGroupInfo]
mentions: List[int] mentions: List[int]
count: int count: int
old_unreads_missing: bool old_unreads_missing: bool
@ -519,7 +519,7 @@ def get_messages_with_usermessage_rows_for_user(
).values_list("message_id", flat=True) ).values_list("message_id", flat=True)
def huddle_users(recipient_id: int) -> str: def direct_message_group_users(recipient_id: int) -> str:
display_recipient: List[UserDisplayRecipient] = get_display_recipient_by_id( display_recipient: List[UserDisplayRecipient] = get_display_recipient_by_id(
recipient_id, recipient_id,
Recipient.DIRECT_MESSAGE_GROUP, Recipient.DIRECT_MESSAGE_GROUP,
@ -624,7 +624,7 @@ def extract_unread_data_from_um_rows(
stream_dict: Dict[int, RawUnreadStreamDict] = {} stream_dict: Dict[int, RawUnreadStreamDict] = {}
muted_stream_ids: Set[int] = set() muted_stream_ids: Set[int] = set()
unmuted_stream_msgs: Set[int] = set() unmuted_stream_msgs: Set[int] = set()
huddle_dict: Dict[int, RawUnreadHuddleDict] = {} direct_message_group_dict: Dict[int, RawUnreadDirectMessageGroupDict] = {}
mentions: Set[int] = set() mentions: Set[int] = set()
total_unreads = 0 total_unreads = 0
@ -633,7 +633,7 @@ def extract_unread_data_from_um_rows(
stream_dict=stream_dict, stream_dict=stream_dict,
muted_stream_ids=muted_stream_ids, muted_stream_ids=muted_stream_ids,
unmuted_stream_msgs=unmuted_stream_msgs, unmuted_stream_msgs=unmuted_stream_msgs,
huddle_dict=huddle_dict, huddle_dict=direct_message_group_dict,
mentions=mentions, mentions=mentions,
old_unreads_missing=False, old_unreads_missing=False,
) )
@ -668,14 +668,14 @@ def extract_unread_data_from_um_rows(
return False return False
huddle_cache: Dict[int, str] = {} direct_message_group_cache: Dict[int, str] = {}
def get_huddle_users(recipient_id: int) -> str: def get_direct_message_group_users(recipient_id: int) -> str:
if recipient_id in huddle_cache: if recipient_id in direct_message_group_cache:
return huddle_cache[recipient_id] return direct_message_group_cache[recipient_id]
user_ids_string = huddle_users(recipient_id) user_ids_string = direct_message_group_users(recipient_id)
huddle_cache[recipient_id] = user_ids_string direct_message_group_cache[recipient_id] = user_ids_string
return user_ids_string return user_ids_string
for row in rows: for row in rows:
@ -706,8 +706,8 @@ def extract_unread_data_from_um_rows(
) )
elif msg_type == Recipient.DIRECT_MESSAGE_GROUP: elif msg_type == Recipient.DIRECT_MESSAGE_GROUP:
user_ids_string = get_huddle_users(recipient_id) user_ids_string = get_direct_message_group_users(recipient_id)
huddle_dict[message_id] = dict( direct_message_group_dict[message_id] = dict(
user_ids_string=user_ids_string, user_ids_string=user_ids_string,
) )
@ -791,12 +791,14 @@ def aggregate_pms(
return [lookup_dict[k] for k in sorted_keys] return [lookup_dict[k] for k in sorted_keys]
def aggregate_huddles(*, input_dict: Dict[int, RawUnreadHuddleDict]) -> List[UnreadHuddleInfo]: def aggregate_direct_message_groups(
lookup_dict: Dict[str, UnreadHuddleInfo] = {} *, input_dict: Dict[int, RawUnreadDirectMessageGroupDict]
) -> List[UnreadDirectMessageGroupInfo]:
lookup_dict: Dict[str, UnreadDirectMessageGroupInfo] = {}
for message_id, attribute_dict in input_dict.items(): for message_id, attribute_dict in input_dict.items():
user_ids_string = attribute_dict["user_ids_string"] user_ids_string = attribute_dict["user_ids_string"]
if user_ids_string not in lookup_dict: if user_ids_string not in lookup_dict:
obj = UnreadHuddleInfo( obj = UnreadDirectMessageGroupInfo(
user_ids_string=user_ids_string, user_ids_string=user_ids_string,
unread_message_ids=[], unread_message_ids=[],
) )
@ -817,19 +819,19 @@ def aggregate_unread_data(raw_data: RawUnreadMessagesResult) -> UnreadMessagesRe
pm_dict = raw_data["pm_dict"] pm_dict = raw_data["pm_dict"]
stream_dict = raw_data["stream_dict"] stream_dict = raw_data["stream_dict"]
unmuted_stream_msgs = raw_data["unmuted_stream_msgs"] unmuted_stream_msgs = raw_data["unmuted_stream_msgs"]
huddle_dict = raw_data["huddle_dict"] direct_message_group_dict = raw_data["huddle_dict"]
mentions = list(raw_data["mentions"]) mentions = list(raw_data["mentions"])
count = len(pm_dict) + len(unmuted_stream_msgs) + len(huddle_dict) count = len(pm_dict) + len(unmuted_stream_msgs) + len(direct_message_group_dict)
pm_objects = aggregate_pms(input_dict=pm_dict) pm_objects = aggregate_pms(input_dict=pm_dict)
stream_objects = aggregate_streams(input_dict=stream_dict) stream_objects = aggregate_streams(input_dict=stream_dict)
huddle_objects = aggregate_huddles(input_dict=huddle_dict) direct_message_groups = aggregate_direct_message_groups(input_dict=direct_message_group_dict)
result: UnreadMessagesResult = dict( result: UnreadMessagesResult = dict(
pms=pm_objects, pms=pm_objects,
streams=stream_objects, streams=stream_objects,
huddles=huddle_objects, huddles=direct_message_groups,
mentions=mentions, mentions=mentions,
count=count, count=count,
old_unreads_missing=raw_data["old_unreads_missing"], old_unreads_missing=raw_data["old_unreads_missing"],
@ -892,7 +894,7 @@ def apply_unread_message_event(
user_ids = sorted(user_ids) user_ids = sorted(user_ids)
user_ids_string = ",".join(str(uid) for uid in user_ids) user_ids_string = ",".join(str(uid) for uid in user_ids)
state["huddle_dict"][message_id] = RawUnreadHuddleDict( state["huddle_dict"][message_id] = RawUnreadDirectMessageGroupDict(
user_ids_string=user_ids_string, user_ids_string=user_ids_string,
) )
@ -993,7 +995,7 @@ def add_message_to_unread_msgs(
else: else:
user_ids.append(my_user_id) user_ids.append(my_user_id)
user_ids_string = ",".join(str(user_id) for user_id in sorted(user_ids)) user_ids_string = ",".join(str(user_id) for user_id in sorted(user_ids))
state["huddle_dict"][message_id] = RawUnreadHuddleDict( state["huddle_dict"][message_id] = RawUnreadDirectMessageGroupDict(
user_ids_string=user_ids_string, user_ids_string=user_ids_string,
) )
elif message_details["type"] == "stream": elif message_details["type"] == "stream":

View File

@ -648,7 +648,7 @@ class NarrowBuilder:
) )
return query.where(maybe_negate(cond)) return query.where(maybe_negate(cond))
def _get_huddle_recipients(self, other_user: UserProfile) -> Set[int]: def _get_direct_message_group_recipients(self, other_user: UserProfile) -> Set[int]:
self_recipient_ids = [ self_recipient_ids = [
recipient_tuple["recipient_id"] recipient_tuple["recipient_id"]
for recipient_tuple in Subscription.objects.filter( for recipient_tuple in Subscription.objects.filter(
@ -693,7 +693,9 @@ class NarrowBuilder:
return query.where(maybe_negate(cond)) return query.where(maybe_negate(cond))
# all direct messages including another person (group and 1:1) # all direct messages including another person (group and 1:1)
huddle_recipient_ids = self._get_huddle_recipients(narrow_user_profile) direct_message_group_recipient_ids = self._get_direct_message_group_recipients(
narrow_user_profile
)
self_recipient_id = self.user_profile.recipient_id self_recipient_id = self.user_profile.recipient_id
# See note above in `by_dm` about needing bidirectional messages # See note above in `by_dm` about needing bidirectional messages
@ -711,7 +713,7 @@ class NarrowBuilder:
column("recipient_id", Integer) == narrow_user_profile.recipient_id, column("recipient_id", Integer) == narrow_user_profile.recipient_id,
), ),
and_( and_(
column("recipient_id", Integer).in_(huddle_recipient_ids), column("recipient_id", Integer).in_(direct_message_group_recipient_ids),
), ),
), ),
) )
@ -734,7 +736,7 @@ class NarrowBuilder:
except UserProfile.DoesNotExist: except UserProfile.DoesNotExist:
raise BadNarrowOperatorError("unknown user " + str(operand)) raise BadNarrowOperatorError("unknown user " + str(operand))
recipient_ids = self._get_huddle_recipients(narrow_profile) recipient_ids = self._get_direct_message_group_recipients(narrow_profile)
cond = and_( cond = and_(
column("flags", Integer).op("&")(UserMessage.flags.is_private.mask) != 0, column("flags", Integer).op("&")(UserMessage.flags.is_private.mask) != 0,
column("realm_id", Integer) == self.realm.id, column("realm_id", Integer) == self.realm.id,

View File

@ -47,7 +47,7 @@ from zerver.lib.avatar import absolute_avatar_url, get_avatar_for_inaccessible_u
from zerver.lib.display_recipient import get_display_recipient from zerver.lib.display_recipient import get_display_recipient
from zerver.lib.emoji_utils import hex_codepoint_to_emoji from zerver.lib.emoji_utils import hex_codepoint_to_emoji
from zerver.lib.exceptions import ErrorCode, JsonableError from zerver.lib.exceptions import ErrorCode, JsonableError
from zerver.lib.message import access_message_and_usermessage, huddle_users from zerver.lib.message import access_message_and_usermessage, direct_message_group_users
from zerver.lib.notification_data import get_mentioned_user_group from zerver.lib.notification_data import get_mentioned_user_group
from zerver.lib.remote_server import ( from zerver.lib.remote_server import (
record_push_notifications_recently_working, record_push_notifications_recently_working,
@ -1006,7 +1006,7 @@ def get_message_payload(
data["topic"] = message.topic_name() data["topic"] = message.topic_name()
elif message.recipient.type == Recipient.DIRECT_MESSAGE_GROUP: elif message.recipient.type == Recipient.DIRECT_MESSAGE_GROUP:
data["recipient_type"] = "private" data["recipient_type"] = "private"
data["pm_users"] = huddle_users(message.recipient.id) data["pm_users"] = direct_message_group_users(message.recipient.id)
else: # Recipient.PERSONAL else: # Recipient.PERSONAL
data["recipient_type"] = "private" data["recipient_type"] = "private"

View File

@ -4,7 +4,10 @@ from django.core.exceptions import ValidationError
from django.utils.translation import gettext as _ from django.utils.translation import gettext as _
from zerver.models import Huddle, Recipient, UserProfile from zerver.models import Huddle, Recipient, UserProfile
from zerver.models.recipients import get_huddle_hash, get_or_create_huddle from zerver.models.recipients import (
get_direct_message_group_hash,
get_or_create_direct_message_group,
)
from zerver.models.users import is_cross_realm_bot_email from zerver.models.users import is_cross_realm_bot_email
@ -45,21 +48,24 @@ def get_recipient_from_user_profiles(
type_id=user_profile.id, type_id=user_profile.id,
) )
# Otherwise, we need a huddle. Make sure the sender is included in huddle messages # Otherwise, we need a direct message group. Make sure the sender
# is included in the group direct messages
recipient_profiles_map[sender.id] = sender recipient_profiles_map[sender.id] = sender
user_ids = list(recipient_profiles_map) user_ids = list(recipient_profiles_map)
if create: if create:
huddle = get_or_create_huddle(user_ids) direct_message_group = get_or_create_direct_message_group(user_ids)
else: else:
# We intentionally let the Huddle.DoesNotExist escape, in the # We intentionally let the Huddle.DoesNotExist escape, in the
# case that there is no such huddle, and the user passed # case that there is no such direct message group, and the user
# create=False # passed create=False
huddle = Huddle.objects.get(huddle_hash=get_huddle_hash(user_ids)) direct_message_group = Huddle.objects.get(
huddle_hash=get_direct_message_group_hash(user_ids)
)
return Recipient( return Recipient(
id=huddle.recipient_id, id=direct_message_group.recipient_id,
type=Recipient.DIRECT_MESSAGE_GROUP, type=Recipient.DIRECT_MESSAGE_GROUP,
type_id=huddle.id, type_id=direct_message_group.id,
) )

View File

@ -216,7 +216,7 @@ def move_expired_messages_to_archive_by_recipient(
) )
def move_expired_personal_and_huddle_messages_to_archive( def move_expired_direct_messages_to_archive(
realm: Realm, realm: Realm,
chunk_size: int = MESSAGE_BATCH_SIZE, chunk_size: int = MESSAGE_BATCH_SIZE,
) -> int: ) -> int:
@ -226,7 +226,7 @@ def move_expired_personal_and_huddle_messages_to_archive(
recipient_types = (Recipient.PERSONAL, Recipient.DIRECT_MESSAGE_GROUP) recipient_types = (Recipient.PERSONAL, Recipient.DIRECT_MESSAGE_GROUP)
# Archive expired personal and huddle Messages in the realm, including cross-realm messages. # Archive expired direct Messages in the realm, including cross-realm messages.
# Uses index: zerver_message_realm_recipient_date_sent # Uses index: zerver_message_realm_recipient_date_sent
query = SQL( query = SQL(
""" """
@ -356,11 +356,9 @@ def archive_messages_by_recipient(
) )
def archive_personal_and_huddle_messages( def archive_direct_messages(realm: Realm, chunk_size: int = MESSAGE_BATCH_SIZE) -> None:
realm: Realm, chunk_size: int = MESSAGE_BATCH_SIZE logger.info("Archiving personal and group direct messages for realm %s", realm.string_id)
) -> None: message_count = move_expired_direct_messages_to_archive(realm, chunk_size)
logger.info("Archiving personal and huddle messages for realm %s", realm.string_id)
message_count = move_expired_personal_and_huddle_messages_to_archive(realm, chunk_size)
logger.info("Done. Archived %s messages", message_count) logger.info("Done. Archived %s messages", message_count)
@ -400,7 +398,7 @@ def archive_messages(chunk_size: int = MESSAGE_BATCH_SIZE) -> None:
for realm, streams in get_realms_and_streams_for_archiving(): for realm, streams in get_realms_and_streams_for_archiving():
archive_stream_messages(realm, streams, chunk_size=STREAM_MESSAGE_BATCH_SIZE) archive_stream_messages(realm, streams, chunk_size=STREAM_MESSAGE_BATCH_SIZE)
if realm.message_retention_days != -1: if realm.message_retention_days != -1:
archive_personal_and_huddle_messages(realm, chunk_size) archive_direct_messages(realm, chunk_size)
# Messages have been archived for the realm, now we can clean up attachments: # Messages have been archived for the realm, now we can clean up attachments:
delete_expired_attachments(realm) delete_expired_attachments(realm)

View File

@ -1095,7 +1095,7 @@ Output:
) )
return sent_message_result.message_id return sent_message_result.message_id
def send_huddle_message( def send_group_direct_message(
self, self,
from_user: UserProfile, from_user: UserProfile,
to_users: List[UserProfile], to_users: List[UserProfile],
@ -1980,7 +1980,7 @@ Output:
self.send_personal_message(polonius, prospero) self.send_personal_message(polonius, prospero)
self.send_personal_message(shiva, polonius) self.send_personal_message(shiva, polonius)
self.send_huddle_message(aaron, [polonius, zoe]) self.send_group_direct_message(aaron, [polonius, zoe])
members_group = NamedUserGroup.objects.get(name="role:members", realm=realm) members_group = NamedUserGroup.objects.get(name="role:members", realm=realm)
do_change_realm_permission_group_setting( do_change_realm_permission_group_setting(
@ -2069,7 +2069,7 @@ class ZulipTestCase(ZulipTestCaseMixin, TestCase):
return message_id return message_id
@override @override
def send_huddle_message( def send_group_direct_message(
self, self,
from_user: UserProfile, from_user: UserProfile,
to_users: List[UserProfile], to_users: List[UserProfile],
@ -2078,7 +2078,7 @@ class ZulipTestCase(ZulipTestCaseMixin, TestCase):
read_by_sender: bool = True, read_by_sender: bool = True,
skip_capture_on_commit_callbacks: bool = False, skip_capture_on_commit_callbacks: bool = False,
) -> int: ) -> int:
"""This function is a wrapper on 'send_huddle_message', """This function is a wrapper on 'send_group_direct_message',
defined in 'ZulipTestCaseMixin' with an extra parameter defined in 'ZulipTestCaseMixin' with an extra parameter
'skip_capture_on_commit_callbacks'. 'skip_capture_on_commit_callbacks'.
@ -2087,12 +2087,12 @@ class ZulipTestCase(ZulipTestCaseMixin, TestCase):
because they already have 'self.captureOnCommitCallbacks' because they already have 'self.captureOnCommitCallbacks'
(See the comment in 'capture_send_event_calls'). (See the comment in 'capture_send_event_calls').
For all other cases, we should call 'send_huddle_message' with For all other cases, we should call 'send_group_direct_message' with
'self.captureOnCommitCallbacks' for 'send_event_on_commit' or/and 'self.captureOnCommitCallbacks' for 'send_event_on_commit' or/and
'queue_event_on_commit' to work. 'queue_event_on_commit' to work.
""" """
if skip_capture_on_commit_callbacks: if skip_capture_on_commit_callbacks:
message_id = super().send_huddle_message( message_id = super().send_group_direct_message(
from_user, from_user,
to_users, to_users,
content, content,
@ -2100,7 +2100,7 @@ class ZulipTestCase(ZulipTestCaseMixin, TestCase):
) )
else: else:
with self.captureOnCommitCallbacks(execute=True): with self.captureOnCommitCallbacks(execute=True):
message_id = super().send_huddle_message( message_id = super().send_group_direct_message(
from_user, from_user,
to_users, to_users,
content, content,

View File

@ -28,7 +28,9 @@ def personal_narrow_url(*, realm: Realm, sender: UserProfile) -> str:
return base_url + pm_slug return base_url + pm_slug
def huddle_narrow_url(*, user: UserProfile, display_recipient: List[UserDisplayRecipient]) -> str: def direct_message_group_narrow_url(
*, user: UserProfile, display_recipient: List[UserDisplayRecipient]
) -> str:
realm = user.realm realm = user.realm
other_user_ids = [r["id"] for r in display_recipient if r["id"] != user.id] other_user_ids = [r["id"] for r in display_recipient if r["id"] != user.id]
pm_slug = ",".join(str(user_id) for user_id in sorted(other_user_ids)) + "-group" pm_slug = ",".join(str(user_id) for user_id in sorted(other_user_ids)) + "-group"

View File

@ -706,15 +706,13 @@ def get_user_ids_who_can_access_user(target_user: UserProfile) -> List[int]:
active_non_guest_user_ids_in_realm = active_non_guest_user_ids(realm.id) active_non_guest_user_ids_in_realm = active_non_guest_user_ids(realm.id)
users_in_subscribed_streams_or_huddles_dict = get_subscribers_of_target_user_subscriptions( users_sharing_any_subscription = get_subscribers_of_target_user_subscriptions([target_user])
[target_user]
)
users_involved_in_dms_dict = get_users_involved_in_dms_with_target_users([target_user], realm) users_involved_in_dms_dict = get_users_involved_in_dms_with_target_users([target_user], realm)
user_ids_who_can_access_target_user = ( user_ids_who_can_access_target_user = (
{target_user.id} {target_user.id}
| set(active_non_guest_user_ids_in_realm) | set(active_non_guest_user_ids_in_realm)
| users_in_subscribed_streams_or_huddles_dict[target_user.id] | users_sharing_any_subscription[target_user.id]
| users_involved_in_dms_dict[target_user.id] | users_involved_in_dms_dict[target_user.id]
) )
return list(user_ids_who_can_access_target_user) return list(user_ids_who_can_access_target_user)

View File

@ -11,7 +11,7 @@ from django.utils.translation import override as override_language
from zerver.actions.message_send import ( from zerver.actions.message_send import (
do_send_messages, do_send_messages,
internal_prep_huddle_message, internal_prep_group_direct_message,
internal_prep_stream_message, internal_prep_stream_message,
) )
from zerver.lib.message import SendMessageRequest, remove_single_newlines from zerver.lib.message import SendMessageRequest, remove_single_newlines
@ -174,7 +174,7 @@ configuration change), or [turn this feature off]({organization_settings_url}) a
organization_settings_url="/#organization/organization-settings", organization_settings_url="/#organization/organization-settings",
move_content_another_stream_help_url="/help/move-content-to-another-channel", move_content_another_stream_help_url="/help/move-content-to-another-channel",
) )
return internal_prep_huddle_message( return internal_prep_group_direct_message(
realm, sender, remove_single_newlines(content), recipient_users=administrators realm, sender, remove_single_newlines(content), recipient_users=administrators
) )

View File

@ -17,7 +17,7 @@ from zerver.lib.management import ZulipBaseCommand
from zerver.lib.soft_deactivation import reactivate_user_if_soft_deactivated from zerver.lib.soft_deactivation import reactivate_user_if_soft_deactivated
from zerver.lib.upload import save_attachment_contents from zerver.lib.upload import save_attachment_contents
from zerver.models import AbstractUserMessage, Attachment, Message, Recipient, Stream, UserProfile from zerver.models import AbstractUserMessage, Attachment, Message, Recipient, Stream, UserProfile
from zerver.models.recipients import get_or_create_huddle from zerver.models.recipients import get_or_create_direct_message_group
from zerver.models.users import get_user_by_delivery_email from zerver.models.users import get_user_by_delivery_email
@ -176,8 +176,10 @@ This is most often used for legal compliance.
recipient=user_b.recipient, sender=user_a recipient=user_b.recipient, sender=user_a
) )
else: else:
huddle = get_or_create_huddle([user.id for user in user_profiles]) direct_message_group = get_or_create_direct_message_group(
limits &= Q(recipient=huddle.recipient) [user.id for user in user_profiles]
)
limits &= Q(recipient=direct_message_group.recipient)
attachments_written: Set[str] = set() attachments_written: Set[str] = set()
messages_query = Message.objects.filter(limits, realm=realm).order_by("date_sent") messages_query = Message.objects.filter(limits, realm=realm).order_by("date_sent")

View File

@ -73,7 +73,7 @@ class Recipient(models.Model):
return self._type_names[self.type] return self._type_names[self.type]
def get_huddle_user_ids(recipient: Recipient) -> ValuesQuerySet["Subscription", int]: def get_direct_message_group_user_ids(recipient: Recipient) -> ValuesQuerySet["Subscription", int]:
from zerver.models import Subscription from zerver.models import Subscription
assert recipient.type == Recipient.DIRECT_MESSAGE_GROUP assert recipient.type == Recipient.DIRECT_MESSAGE_GROUP
@ -87,7 +87,7 @@ def get_huddle_user_ids(recipient: Recipient) -> ValuesQuerySet["Subscription",
) )
def bulk_get_huddle_user_ids(recipient_ids: List[int]) -> Dict[int, Set[int]]: def bulk_get_direct_message_group_user_ids(recipient_ids: List[int]) -> Dict[int, Set[int]]:
""" """
Takes a list of huddle-type recipient_ids, returns a dict Takes a list of huddle-type recipient_ids, returns a dict
mapping recipient id to list of user ids in the huddle. mapping recipient id to list of user ids in the huddle.
@ -133,13 +133,13 @@ class Huddle(models.Model):
recipient = models.ForeignKey(Recipient, null=True, on_delete=models.SET_NULL) recipient = models.ForeignKey(Recipient, null=True, on_delete=models.SET_NULL)
def get_huddle_hash(id_list: List[int]) -> str: def get_direct_message_group_hash(id_list: List[int]) -> str:
id_list = sorted(set(id_list)) id_list = sorted(set(id_list))
hash_key = ",".join(str(x) for x in id_list) hash_key = ",".join(str(x) for x in id_list)
return hashlib.sha1(hash_key.encode()).hexdigest() return hashlib.sha1(hash_key.encode()).hexdigest()
def get_or_create_huddle(id_list: List[int]) -> Huddle: def get_or_create_direct_message_group(id_list: List[int]) -> Huddle:
""" """
Takes a list of user IDs and returns the Huddle object for the Takes a list of user IDs and returns the Huddle object for the
group consisting of these users. If the Huddle object does not group consisting of these users. If the Huddle object does not
@ -147,15 +147,17 @@ def get_or_create_huddle(id_list: List[int]) -> Huddle:
""" """
from zerver.models import Subscription, UserProfile from zerver.models import Subscription, UserProfile
huddle_hash = get_huddle_hash(id_list) direct_message_group_hash = get_direct_message_group_hash(id_list)
with transaction.atomic(): with transaction.atomic():
(huddle, created) = Huddle.objects.get_or_create(huddle_hash=huddle_hash) (direct_message_group, created) = Huddle.objects.get_or_create(
huddle_hash=direct_message_group_hash
)
if created: if created:
recipient = Recipient.objects.create( recipient = Recipient.objects.create(
type_id=huddle.id, type=Recipient.DIRECT_MESSAGE_GROUP type_id=direct_message_group.id, type=Recipient.DIRECT_MESSAGE_GROUP
) )
huddle.recipient = recipient direct_message_group.recipient = recipient
huddle.save(update_fields=["recipient"]) direct_message_group.save(update_fields=["recipient"])
subs_to_create = [ subs_to_create = [
Subscription( Subscription(
recipient=recipient, recipient=recipient,
@ -167,4 +169,4 @@ def get_or_create_huddle(id_list: List[int]) -> Huddle:
.values_list("id", "is_active") .values_list("id", "is_active")
] ]
Subscription.objects.bulk_create(subs_to_create) Subscription.objects.bulk_create(subs_to_create)
return huddle return direct_message_group

View File

@ -1039,7 +1039,7 @@ class TestMissedMessageEmailMessages(ZulipTestCase):
self.assertEqual(message.recipient.type_id, user_profile.id) self.assertEqual(message.recipient.type_id, user_profile.id)
self.assertEqual(message.recipient.type, Recipient.PERSONAL) self.assertEqual(message.recipient.type, Recipient.PERSONAL)
def test_receive_missed_huddle_message_email_messages(self) -> None: def test_receive_missed_group_direct_message_email_messages(self) -> None:
# Build dummy messages for message notification email reply. # Build dummy messages for message notification email reply.
# Have Othello send Iago and Cordelia a group direct message. # Have Othello send Iago and Cordelia a group direct message.
# Cordelia will reply via email Iago and Othello will receive # Cordelia will reply via email Iago and Othello will receive
@ -1065,9 +1065,9 @@ class TestMissedMessageEmailMessages(ZulipTestCase):
mm_address = create_missed_message_address(user_profile, usermessage.message) mm_address = create_missed_message_address(user_profile, usermessage.message)
incoming_valid_message = EmailMessage() incoming_valid_message = EmailMessage()
incoming_valid_message.set_content("TestMissedHuddleMessageEmailMessages body") incoming_valid_message.set_content("TestMissedGroupDirectMessageEmailMessages body")
incoming_valid_message["Subject"] = "TestMissedHuddleMessageEmailMessages subject" incoming_valid_message["Subject"] = "TestMissedGroupDirectMessageEmailMessages subject"
incoming_valid_message["From"] = self.example_email("cordelia") incoming_valid_message["From"] = self.example_email("cordelia")
incoming_valid_message["To"] = mm_address incoming_valid_message["To"] = mm_address
incoming_valid_message["Reply-to"] = self.example_email("cordelia") incoming_valid_message["Reply-to"] = self.example_email("cordelia")
@ -1079,7 +1079,7 @@ class TestMissedMessageEmailMessages(ZulipTestCase):
user_profile = self.example_user("iago") user_profile = self.example_user("iago")
message = most_recent_message(user_profile) message = most_recent_message(user_profile)
self.assertEqual(message.content, "TestMissedHuddleMessageEmailMessages body") self.assertEqual(message.content, "TestMissedGroupDirectMessageEmailMessages body")
self.assertEqual(message.sender, self.example_user("cordelia")) self.assertEqual(message.sender, self.example_user("cordelia"))
self.assertEqual(message.recipient.type, Recipient.DIRECT_MESSAGE_GROUP) self.assertEqual(message.recipient.type, Recipient.DIRECT_MESSAGE_GROUP)
@ -1087,7 +1087,7 @@ class TestMissedMessageEmailMessages(ZulipTestCase):
user_profile = self.example_user("othello") user_profile = self.example_user("othello")
message = most_recent_message(user_profile) message = most_recent_message(user_profile)
self.assertEqual(message.content, "TestMissedHuddleMessageEmailMessages body") self.assertEqual(message.content, "TestMissedGroupDirectMessageEmailMessages body")
self.assertEqual(message.sender, self.example_user("cordelia")) self.assertEqual(message.sender, self.example_user("cordelia"))
self.assertEqual(message.recipient.type, Recipient.DIRECT_MESSAGE_GROUP) self.assertEqual(message.recipient.type, Recipient.DIRECT_MESSAGE_GROUP)

View File

@ -598,14 +598,17 @@ class NormalActionsTest(BaseAction):
is_embedded_update_only=False, is_embedded_update_only=False,
) )
def test_huddle_send_message_events(self) -> None: def test_direct_message_group_send_message_events(self) -> None:
huddle = [ direct_message_group = [
self.example_user("hamlet"), self.example_user("hamlet"),
self.example_user("othello"), self.example_user("othello"),
] ]
with self.verify_action(): with self.verify_action():
self.send_huddle_message( self.send_group_direct_message(
self.example_user("cordelia"), huddle, "hola", skip_capture_on_commit_callbacks=True self.example_user("cordelia"),
direct_message_group,
"hola",
skip_capture_on_commit_callbacks=True,
) )
def test_user_creation_events_on_sending_messages(self) -> None: def test_user_creation_events_on_sending_messages(self) -> None:
@ -634,7 +637,7 @@ class NormalActionsTest(BaseAction):
desdemona = self.example_user("desdemona") desdemona = self.example_user("desdemona")
with self.verify_action(num_events=3) as events: with self.verify_action(num_events=3) as events:
self.send_huddle_message( self.send_group_direct_message(
othello, [polonius, desdemona, bot], "hola", skip_capture_on_commit_callbacks=True othello, [polonius, desdemona, bot], "hola", skip_capture_on_commit_callbacks=True
) )
check_realm_user_add("events[0]", events[0]) check_realm_user_add("events[0]", events[0])
@ -1068,17 +1071,17 @@ class NormalActionsTest(BaseAction):
do_update_message_flags(user_profile, "remove", "read", [personal_message]) do_update_message_flags(user_profile, "remove", "read", [personal_message])
check_update_message_flags_remove("events[0]", events[0]) check_update_message_flags_remove("events[0]", events[0])
huddle_message = self.send_huddle_message( group_direct_message = self.send_group_direct_message(
from_user=self.example_user("cordelia"), from_user=self.example_user("cordelia"),
to_users=[user_profile, self.example_user("othello")], to_users=[user_profile, self.example_user("othello")],
content=content, content=content,
) )
with self.verify_action(state_change_expected=True): with self.verify_action(state_change_expected=True):
do_update_message_flags(user_profile, "add", "read", [huddle_message]) do_update_message_flags(user_profile, "add", "read", [group_direct_message])
with self.verify_action(state_change_expected=True) as events: with self.verify_action(state_change_expected=True) as events:
do_update_message_flags(user_profile, "remove", "read", [huddle_message]) do_update_message_flags(user_profile, "remove", "read", [group_direct_message])
check_update_message_flags_remove("events[0]", events[0]) check_update_message_flags_remove("events[0]", events[0])
def test_send_message_to_existing_recipient(self) -> None: def test_send_message_to_existing_recipient(self) -> None:

View File

@ -90,7 +90,7 @@ from zerver.models.clients import get_client
from zerver.models.groups import SystemGroups from zerver.models.groups import SystemGroups
from zerver.models.presence import PresenceSequence from zerver.models.presence import PresenceSequence
from zerver.models.realms import get_realm from zerver.models.realms import get_realm
from zerver.models.recipients import get_huddle_hash from zerver.models.recipients import get_direct_message_group_hash
from zerver.models.streams import get_active_streams, get_stream from zerver.models.streams import get_active_streams, get_stream
from zerver.models.users import get_system_bot, get_user_by_delivery_email from zerver.models.users import get_system_bot, get_user_by_delivery_email
@ -127,7 +127,7 @@ def get_user_id(r: Realm, full_name: str) -> int:
return UserProfile.objects.get(realm=r, full_name=full_name).id return UserProfile.objects.get(realm=r, full_name=full_name).id
def get_huddle_hashes(r: Realm) -> str: def get_direct_message_group_hashes(r: Realm) -> str:
cordelia_full_name = "Cordelia, Lear's daughter" cordelia_full_name = "Cordelia, Lear's daughter"
hamlet_full_name = "King Hamlet" hamlet_full_name = "King Hamlet"
othello_full_name = "Othello, the Moor of Venice" othello_full_name = "Othello, the Moor of Venice"
@ -138,8 +138,8 @@ def get_huddle_hashes(r: Realm) -> str:
get_user_id(r, othello_full_name), get_user_id(r, othello_full_name),
] ]
huddle_hash = get_huddle_hash(user_id_list) direct_message_group_hash = get_direct_message_group_hash(user_id_list)
return huddle_hash return direct_message_group_hash
class ExportFile(ZulipTestCase): class ExportFile(ZulipTestCase):
@ -584,18 +584,18 @@ class RealmImportExportTest(ExportFile):
self.subscribe(self.example_user("hamlet"), "Private D") self.subscribe(self.example_user("hamlet"), "Private D")
self.send_stream_message(self.example_user("prospero"), "Private D", "Hello again stream D") self.send_stream_message(self.example_user("prospero"), "Private D", "Hello again stream D")
# Create huddles # Create direct message groups
self.send_huddle_message( self.send_group_direct_message(
self.example_user("iago"), [self.example_user("cordelia"), self.example_user("AARON")] self.example_user("iago"), [self.example_user("cordelia"), self.example_user("AARON")]
) )
huddle_a = Huddle.objects.last() direct_message_group_a = Huddle.objects.last()
self.send_huddle_message( self.send_group_direct_message(
self.example_user("ZOE"), self.example_user("ZOE"),
[self.example_user("hamlet"), self.example_user("AARON"), self.example_user("othello")], [self.example_user("hamlet"), self.example_user("AARON"), self.example_user("othello")],
) )
huddle_b = Huddle.objects.last() direct_message_group_b = Huddle.objects.last()
huddle_c_message_id = self.send_huddle_message( direct_message_group_c_message_id = self.send_group_direct_message(
self.example_user("AARON"), self.example_user("AARON"),
[self.example_user("cordelia"), self.example_user("ZOE"), self.example_user("othello")], [self.example_user("cordelia"), self.example_user("ZOE"), self.example_user("othello")],
) )
@ -720,13 +720,17 @@ class RealmImportExportTest(ExportFile):
.values_list("id", flat=True) .values_list("id", flat=True)
) )
# Third huddle is not exported since none of the members gave consent # Third direct message group is not exported since none of
assert huddle_a is not None and huddle_b is not None # the members gave consent
huddle_recipients = Recipient.objects.filter( assert direct_message_group_a is not None and direct_message_group_b is not None
type_id__in=[huddle_a.id, huddle_b.id], type=Recipient.DIRECT_MESSAGE_GROUP direct_message_group_recipients = Recipient.objects.filter(
type_id__in=[direct_message_group_a.id, direct_message_group_b.id],
type=Recipient.DIRECT_MESSAGE_GROUP,
) )
pm_query = Q(recipient__in=huddle_recipients) | Q(sender__in=consented_user_ids) pm_query = Q(recipient__in=direct_message_group_recipients) | Q(
exported_huddle_ids = ( sender__in=consented_user_ids
)
exported_direct_message_group_ids = (
Message.objects.filter(pm_query, realm=realm.id) Message.objects.filter(pm_query, realm=realm.id)
.values_list("id", flat=True) .values_list("id", flat=True)
.values_list("id", flat=True) .values_list("id", flat=True)
@ -737,14 +741,14 @@ class RealmImportExportTest(ExportFile):
*private_stream_message_ids, *private_stream_message_ids,
stream_b_second_message_id, stream_b_second_message_id,
*exported_pm_ids, *exported_pm_ids,
*exported_huddle_ids, *exported_direct_message_group_ids,
} }
self.assertEqual(self.get_set(data["zerver_message"], "id"), exported_msg_ids) self.assertEqual(self.get_set(data["zerver_message"], "id"), exported_msg_ids)
self.assertNotIn(stream_b_first_message_id, exported_msg_ids) self.assertNotIn(stream_b_first_message_id, exported_msg_ids)
self.assertNotIn(stream_c_message_id, exported_msg_ids) self.assertNotIn(stream_c_message_id, exported_msg_ids)
self.assertNotIn(huddle_c_message_id, exported_msg_ids) self.assertNotIn(direct_message_group_c_message_id, exported_msg_ids)
self.assertNotIn(pm_a_msg_id, exported_msg_ids) self.assertNotIn(pm_a_msg_id, exported_msg_ids)
self.assertIn(pm_b_msg_id, exported_msg_ids) self.assertIn(pm_b_msg_id, exported_msg_ids)
@ -801,15 +805,15 @@ class RealmImportExportTest(ExportFile):
modified_user=hamlet, event_type=RealmAuditLog.USER_CREATED modified_user=hamlet, event_type=RealmAuditLog.USER_CREATED
).update(acting_user_id=cross_realm_bot.id) ).update(acting_user_id=cross_realm_bot.id)
# data to test import of huddles # data to test import of direct message groups
huddle = [ direct_message_group = [
self.example_user("hamlet"), self.example_user("hamlet"),
self.example_user("othello"), self.example_user("othello"),
] ]
self.send_huddle_message( self.send_group_direct_message(
self.example_user("cordelia"), self.example_user("cordelia"),
huddle, direct_message_group,
"test huddle message", "test group direct message",
) )
user_mention_message = "@**King Hamlet** Hello" user_mention_message = "@**King Hamlet** Hello"
@ -991,8 +995,12 @@ class RealmImportExportTest(ExportFile):
self.verify_emoji_code_foreign_keys() self.verify_emoji_code_foreign_keys()
# Our huddle hashes change, because hashes use ids that change. # Our direct message group hashes change, because hashes
self.assertNotEqual(get_huddle_hashes(original_realm), get_huddle_hashes(imported_realm)) # use ids that change.
self.assertNotEqual(
get_direct_message_group_hashes(original_realm),
get_direct_message_group_hashes(imported_realm),
)
# test to highlight that bs4 which we use to do data-**id # test to highlight that bs4 which we use to do data-**id
# replacements modifies the HTML sometimes. eg replacing <br> # replacements modifies the HTML sometimes. eg replacing <br>
@ -1039,13 +1047,11 @@ class RealmImportExportTest(ExportFile):
Recipient.objects.get(type=Recipient.STREAM, type_id=stream.id).id, Recipient.objects.get(type=Recipient.STREAM, type_id=stream.id).id,
) )
for huddle_object in Huddle.objects.all(): for dm_group in Huddle.objects.all():
# Huddles don't have a realm column, so we just test all Huddles for simplicity. # Huddles don't have a realm column, so we just test all Huddles for simplicity.
self.assertEqual( self.assertEqual(
huddle_object.recipient_id, dm_group.recipient_id,
Recipient.objects.get( Recipient.objects.get(type=Recipient.DIRECT_MESSAGE_GROUP, type_id=dm_group.id).id,
type=Recipient.DIRECT_MESSAGE_GROUP, type_id=huddle_object.id
).id,
) )
self.assertEqual(ScheduledMessage.objects.filter(realm=imported_realm).count(), 1) self.assertEqual(ScheduledMessage.objects.filter(realm=imported_realm).count(), 1)
@ -1268,13 +1274,15 @@ class RealmImportExportTest(ExportFile):
return realmauditlog_event_type return realmauditlog_event_type
@getter @getter
def get_huddle_message(r: Realm) -> str: def get_group_direct_message(r: Realm) -> str:
huddle_hash = get_huddle_hashes(r) direct_message_group_hash = get_direct_message_group_hashes(r)
huddle_id = Huddle.objects.get(huddle_hash=huddle_hash).id direct_message_group_id = Huddle.objects.get(huddle_hash=direct_message_group_hash).id
huddle_recipient = Recipient.objects.get(type_id=huddle_id, type=3) direct_message_group_recipient = Recipient.objects.get(
huddle_message = Message.objects.get(recipient=huddle_recipient) type_id=direct_message_group_id, type=3
self.assertEqual(huddle_message.content, "test huddle message") )
return huddle_message.content group_direct_message = Message.objects.get(recipient=direct_message_group_recipient)
self.assertEqual(group_direct_message.content, "test group direct message")
return group_direct_message.content
@getter @getter
def get_alertwords(r: Realm) -> Set[str]: def get_alertwords(r: Realm) -> Set[str]:
@ -1883,12 +1891,16 @@ class SingleUserExportTest(ExportFile):
# Try to fool the export again # Try to fool the export again
self.send_personal_message(othello, hamlet) self.send_personal_message(othello, hamlet)
self.send_huddle_message(othello, [hamlet, polonius]) self.send_group_direct_message(othello, [hamlet, polonius])
hi_hamlet_message_id = self.send_personal_message(cordelia, hamlet, "hi hamlet") hi_hamlet_message_id = self.send_personal_message(cordelia, hamlet, "hi hamlet")
hi_peeps_message_id = self.send_huddle_message(cordelia, [hamlet, othello], "hi peeps") hi_peeps_message_id = self.send_group_direct_message(
bye_peeps_message_id = self.send_huddle_message(othello, [cordelia, hamlet], "bye peeps") cordelia, [hamlet, othello], "hi peeps"
)
bye_peeps_message_id = self.send_group_direct_message(
othello, [cordelia, hamlet], "bye peeps"
)
bye_hamlet_message_id = self.send_personal_message(cordelia, hamlet, "bye hamlet") bye_hamlet_message_id = self.send_personal_message(cordelia, hamlet, "bye hamlet")
@ -1903,7 +1915,9 @@ class SingleUserExportTest(ExportFile):
messages = read_json("messages-000001.json") messages = read_json("messages-000001.json")
huddle_name = "Cordelia, Lear's daughter, King Hamlet, Othello, the Moor of Venice" direct_message_group_name = (
"Cordelia, Lear's daughter, King Hamlet, Othello, the Moor of Venice"
)
excerpt = [ excerpt = [
(rec["id"], rec["content"], rec["recipient_name"]) (rec["id"], rec["content"], rec["recipient_name"])
@ -1915,8 +1929,8 @@ class SingleUserExportTest(ExportFile):
(smile_message_id, "SMILE!", "Denmark"), (smile_message_id, "SMILE!", "Denmark"),
(hi_stream_message_id, "hi stream", "Denmark"), (hi_stream_message_id, "hi stream", "Denmark"),
(hi_hamlet_message_id, "hi hamlet", hamlet.full_name), (hi_hamlet_message_id, "hi hamlet", hamlet.full_name),
(hi_peeps_message_id, "hi peeps", huddle_name), (hi_peeps_message_id, "hi peeps", direct_message_group_name),
(bye_peeps_message_id, "bye peeps", huddle_name), (bye_peeps_message_id, "bye peeps", direct_message_group_name),
(bye_hamlet_message_id, "bye hamlet", hamlet.full_name), (bye_hamlet_message_id, "bye hamlet", hamlet.full_name),
(hi_myself_message_id, "hi myself", cordelia.full_name), (hi_myself_message_id, "hi myself", cordelia.full_name),
(bye_stream_message_id, "bye stream", "Denmark"), (bye_stream_message_id, "bye stream", "Denmark"),

View File

@ -10,11 +10,11 @@ from zerver.data_import.mattermost import (
build_reactions, build_reactions,
check_user_in_team, check_user_in_team,
convert_channel_data, convert_channel_data,
convert_huddle_data, convert_direct_message_group_data,
convert_user_data, convert_user_data,
create_username_to_user_mapping, create_username_to_user_mapping,
do_convert_data, do_convert_data,
generate_huddle_name, generate_direct_message_group_name,
get_mentioned_user_ids, get_mentioned_user_ids,
label_mirror_dummy_users, label_mirror_dummy_users,
mattermost_data_file_to_dict, mattermost_data_file_to_dict,
@ -336,7 +336,7 @@ class MatterMostImporter(ZulipTestCase):
{malfoy_id, pansy_id}, {malfoy_id, pansy_id},
) )
def test_convert_huddle_data(self) -> None: def test_convert_direct_message_group_data(self) -> None:
fixture_file_name = self.fixture_file_name( fixture_file_name = self.fixture_file_name(
"export.json", "mattermost_fixtures/direct_channel" "export.json", "mattermost_fixtures/direct_channel"
) )
@ -358,8 +358,8 @@ class MatterMostImporter(ZulipTestCase):
team_name=team_name, team_name=team_name,
) )
zerver_huddle = convert_huddle_data( zerver_huddle = convert_direct_message_group_data(
huddle_data=mattermost_data["direct_channel"], direct_message_group_data=mattermost_data["direct_channel"],
user_data_map=username_to_user, user_data_map=username_to_user,
subscriber_handler=subscriber_handler, subscriber_handler=subscriber_handler,
huddle_id_mapper=huddle_id_mapper, huddle_id_mapper=huddle_id_mapper,
@ -369,12 +369,15 @@ class MatterMostImporter(ZulipTestCase):
) )
self.assert_length(zerver_huddle, 1) self.assert_length(zerver_huddle, 1)
huddle_members = mattermost_data["direct_channel"][1]["members"] direct_message_group_members = mattermost_data["direct_channel"][1]["members"]
huddle_name = generate_huddle_name(huddle_members) direct_message_group_name = generate_direct_message_group_name(direct_message_group_members)
self.assertTrue(huddle_id_mapper.has(huddle_name)) self.assertTrue(huddle_id_mapper.has(direct_message_group_name))
self.assertEqual( self.assertEqual(
subscriber_handler.get_users(huddle_id=huddle_id_mapper.get(huddle_name)), {1, 2, 3} subscriber_handler.get_users(
direct_message_group_id=huddle_id_mapper.get(direct_message_group_name)
),
{1, 2, 3},
) )
def test_write_emoticon_data(self) -> None: def test_write_emoticon_data(self) -> None:
@ -669,8 +672,8 @@ class MatterMostImporter(ZulipTestCase):
self.assertEqual( self.assertEqual(
warn_log.output, warn_log.output,
[ [
"WARNING:root:Skipping importing huddles and DMs since there are multiple teams in the export", "WARNING:root:Skipping importing direct message groups and DMs since there are multiple teams in the export",
"WARNING:root:Skipping importing huddles and DMs since there are multiple teams in the export", "WARNING:root:Skipping importing direct message groups and DMs since there are multiple teams in the export",
], ],
) )
@ -871,14 +874,16 @@ class MatterMostImporter(ZulipTestCase):
self.assertFalse(stream_messages[3].has_image) self.assertFalse(stream_messages[3].has_image)
self.assertTrue(stream_messages[3].has_link) self.assertTrue(stream_messages[3].has_link)
huddle_messages = messages.filter(recipient__type=Recipient.DIRECT_MESSAGE_GROUP).order_by( group_direct_messages = messages.filter(
"date_sent" recipient__type=Recipient.DIRECT_MESSAGE_GROUP
).order_by("date_sent")
direct_message_group_recipients = group_direct_messages.values_list("recipient", flat=True)
self.assert_length(group_direct_messages, 3)
self.assert_length(set(direct_message_group_recipients), 1)
self.assertEqual(group_direct_messages[0].sender.email, "ginny@zulip.com")
self.assertEqual(
group_direct_messages[0].content, "Who is going to Hogsmeade this weekend?\n\n"
) )
huddle_recipients = huddle_messages.values_list("recipient", flat=True)
self.assert_length(huddle_messages, 3)
self.assert_length(set(huddle_recipients), 1)
self.assertEqual(huddle_messages[0].sender.email, "ginny@zulip.com")
self.assertEqual(huddle_messages[0].content, "Who is going to Hogsmeade this weekend?\n\n")
personal_messages = messages.filter(recipient__type=Recipient.PERSONAL).order_by( personal_messages = messages.filter(recipient__type=Recipient.PERSONAL).order_by(
"date_sent" "date_sent"
@ -909,8 +914,8 @@ class MatterMostImporter(ZulipTestCase):
self.assertEqual( self.assertEqual(
warn_log.output, warn_log.output,
[ [
"WARNING:root:Skipping importing huddles and DMs since there are multiple teams in the export", "WARNING:root:Skipping importing direct message groups and DMs since there are multiple teams in the export",
"WARNING:root:Skipping importing huddles and DMs since there are multiple teams in the export", "WARNING:root:Skipping importing direct message groups and DMs since there are multiple teams in the export",
], ],
) )
@ -936,8 +941,8 @@ class MatterMostImporter(ZulipTestCase):
self.assertEqual( self.assertEqual(
warn_log.output, warn_log.output,
[ [
"WARNING:root:Skipping importing huddles and DMs since there are multiple teams in the export", "WARNING:root:Skipping importing direct message groups and DMs since there are multiple teams in the export",
"WARNING:root:Skipping importing huddles and DMs since there are multiple teams in the export", "WARNING:root:Skipping importing direct message groups and DMs since there are multiple teams in the export",
], ],
) )

View File

@ -581,14 +581,14 @@ class TestMessageForIdsDisplayRecipientFetching(ZulipTestCase):
self.assertEqual(messages[0]["display_recipient"], "Verona") self.assertEqual(messages[0]["display_recipient"], "Verona")
self.assertEqual(messages[1]["display_recipient"], "Denmark") self.assertEqual(messages[1]["display_recipient"], "Denmark")
def test_display_recipient_huddle(self) -> None: def test_display_recipient_direct_message_group(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")
iago = self.example_user("iago") iago = self.example_user("iago")
message_ids = [ message_ids = [
self.send_huddle_message(hamlet, [cordelia, othello], "test"), self.send_group_direct_message(hamlet, [cordelia, othello], "test"),
self.send_huddle_message(cordelia, [hamlet, othello, iago], "test"), self.send_group_direct_message(cordelia, [hamlet, othello, iago], "test"),
] ]
messages = messages_for_ids( messages = messages_for_ids(
@ -619,11 +619,11 @@ class TestMessageForIdsDisplayRecipientFetching(ZulipTestCase):
self.subscribe(hamlet, "Scotland") self.subscribe(hamlet, "Scotland")
message_ids = [ message_ids = [
self.send_huddle_message(hamlet, [cordelia, othello], "test"), self.send_group_direct_message(hamlet, [cordelia, othello], "test"),
self.send_stream_message(cordelia, "Verona", content="test"), self.send_stream_message(cordelia, "Verona", content="test"),
self.send_personal_message(hamlet, cordelia, "test"), self.send_personal_message(hamlet, cordelia, "test"),
self.send_stream_message(cordelia, "Denmark", content="test"), self.send_stream_message(cordelia, "Denmark", content="test"),
self.send_huddle_message(cordelia, [hamlet, othello, iago], "test"), self.send_group_direct_message(cordelia, [hamlet, othello, iago], "test"),
self.send_personal_message(cordelia, othello, "test"), self.send_personal_message(cordelia, othello, "test"),
] ]

View File

@ -63,7 +63,7 @@ from zerver.models import (
UserTopic, UserTopic,
) )
from zerver.models.realms import get_realm from zerver.models.realms import get_realm
from zerver.models.recipients import get_or_create_huddle from zerver.models.recipients import get_or_create_direct_message_group
from zerver.models.streams import get_stream from zerver.models.streams import get_stream
from zerver.views.message_fetch import get_messages_backend from zerver.views.message_fetch import get_messages_backend
@ -385,15 +385,17 @@ class NarrowBuilderTest(ZulipTestCase):
"WHERE (flags & %(flags_1)s) != %(param_1)s AND realm_id = %(realm_id_1)s AND (sender_id = %(sender_id_1)s AND recipient_id = %(recipient_id_1)s OR sender_id = %(sender_id_2)s AND recipient_id = %(recipient_id_2)s)", "WHERE (flags & %(flags_1)s) != %(param_1)s AND realm_id = %(realm_id_1)s AND (sender_id = %(sender_id_1)s AND recipient_id = %(recipient_id_1)s OR sender_id = %(sender_id_2)s AND recipient_id = %(recipient_id_2)s)",
) )
def test_add_term_using_dm_operator_more_than_one_user_as_operand_no_huddle(self) -> None: def test_add_term_using_dm_operator_more_than_one_user_as_operand_no_direct_message_group(
self,
) -> None:
# If the group doesn't exist, it's a flat false # If the group doesn't exist, it's a flat false
two_others = f"{self.example_user('cordelia').email},{self.example_user('othello').email}" two_others = f"{self.example_user('cordelia').email},{self.example_user('othello').email}"
term = NarrowParameter(operator="dm", operand=two_others) term = NarrowParameter(operator="dm", operand=two_others)
self._do_add_term_test(term, "WHERE false") self._do_add_term_test(term, "WHERE false")
def test_add_term_using_dm_operator_more_than_one_user_as_operand(self) -> None: def test_add_term_using_dm_operator_more_than_one_user_as_operand(self) -> None:
# Make the huddle first # Make the direct message group first
get_or_create_huddle( get_or_create_direct_message_group(
[ [
self.example_user("hamlet").id, self.example_user("hamlet").id,
self.example_user("cordelia").id, self.example_user("cordelia").id,
@ -416,7 +418,7 @@ class NarrowBuilderTest(ZulipTestCase):
"WHERE NOT ((flags & %(flags_1)s) != %(param_1)s AND realm_id = %(realm_id_1)s AND (sender_id = %(sender_id_1)s AND recipient_id = %(recipient_id_1)s OR sender_id = %(sender_id_2)s AND recipient_id = %(recipient_id_2)s))", "WHERE NOT ((flags & %(flags_1)s) != %(param_1)s AND realm_id = %(realm_id_1)s AND (sender_id = %(sender_id_1)s AND recipient_id = %(recipient_id_1)s OR sender_id = %(sender_id_2)s AND recipient_id = %(recipient_id_2)s))",
) )
def test_add_term_using_dm_operator_more_than_one_user_as_operand_no_huddle_and_negated( def test_add_term_using_dm_operator_more_than_one_user_as_operand_no_direct_message_group_and_negated(
self, self,
) -> None: # NEGATED ) -> None: # NEGATED
# If the group doesn't exist, it's a flat true # If the group doesn't exist, it's a flat true
@ -427,8 +429,8 @@ class NarrowBuilderTest(ZulipTestCase):
def test_add_term_using_dm_operator_more_than_one_user_as_operand_and_negated( def test_add_term_using_dm_operator_more_than_one_user_as_operand_and_negated(
self, self,
) -> None: # NEGATED ) -> None: # NEGATED
# Make the huddle first # Make the direct message group first
get_or_create_huddle( get_or_create_direct_message_group(
[ [
self.example_user("hamlet").id, self.example_user("hamlet").id,
self.example_user("cordelia").id, self.example_user("cordelia").id,
@ -464,7 +466,7 @@ class NarrowBuilderTest(ZulipTestCase):
) )
# Test with at least one such group direct messages existing # Test with at least one such group direct messages existing
self.send_huddle_message( self.send_group_direct_message(
self.user_profile, [self.example_user("othello"), self.example_user("cordelia")] self.user_profile, [self.example_user("othello"), self.example_user("cordelia")]
) )
@ -2218,7 +2220,7 @@ class GetOldMessagesTest(ZulipTestCase):
self.send_personal_message(me, self.example_user("iago")) self.send_personal_message(me, self.example_user("iago"))
self.send_huddle_message( self.send_group_direct_message(
me, me,
[self.example_user("iago"), self.example_user("cordelia")], [self.example_user("iago"), self.example_user("cordelia")],
) )
@ -2227,7 +2229,7 @@ class GetOldMessagesTest(ZulipTestCase):
# Then deactivate Aaron to test "dm" narrow includes messages # Then deactivate Aaron to test "dm" narrow includes messages
# from deactivated users also. # from deactivated users also.
self.send_personal_message(me, self.example_user("aaron")) self.send_personal_message(me, self.example_user("aaron"))
self.send_huddle_message( self.send_group_direct_message(
me, me,
[self.example_user("iago"), self.example_user("aaron")], [self.example_user("iago"), self.example_user("aaron")],
) )
@ -2257,18 +2259,20 @@ class GetOldMessagesTest(ZulipTestCase):
def test_get_messages_with_nonexistent_group_dm(self) -> None: def test_get_messages_with_nonexistent_group_dm(self) -> None:
me = self.example_user("hamlet") me = self.example_user("hamlet")
# Huddle which doesn't match anything gets no results # Direct message group which doesn't match anything gets no results
non_existent_huddle = [ non_existent_direct_message_group = [
me.id, me.id,
self.example_user("iago").id, self.example_user("iago").id,
self.example_user("othello").id, self.example_user("othello").id,
] ]
self.login_user(me) self.login_user(me)
narrow: List[Dict[str, Any]] = [dict(operator="dm", operand=non_existent_huddle)] narrow: List[Dict[str, Any]] = [
dict(operator="dm", operand=non_existent_direct_message_group)
]
result = self.get_and_check_messages(dict(narrow=orjson.dumps(narrow).decode())) result = self.get_and_check_messages(dict(narrow=orjson.dumps(narrow).decode()))
self.assertEqual(result["messages"], []) self.assertEqual(result["messages"], [])
narrow = [dict(operator="dm", operand=non_existent_huddle, negated=True)] narrow = [dict(operator="dm", operand=non_existent_direct_message_group, negated=True)]
result = self.get_and_check_messages(dict(narrow=orjson.dumps(narrow).decode())) result = self.get_and_check_messages(dict(narrow=orjson.dumps(narrow).decode()))
self.assertEqual([m["id"] for m in result["messages"]], [1, 3]) self.assertEqual([m["id"] for m in result["messages"]], [1, 3])
@ -2295,17 +2299,17 @@ class GetOldMessagesTest(ZulipTestCase):
matching_message_ids = [ matching_message_ids = [
# group direct message, sent by current user # group direct message, sent by current user
self.send_huddle_message( self.send_group_direct_message(
me, me,
[iago, cordelia, othello], [iago, cordelia, othello],
), ),
# group direct message, sent by searched user # group direct message, sent by searched user
self.send_huddle_message( self.send_group_direct_message(
cordelia, cordelia,
[me, othello], [me, othello],
), ),
# group direct message, sent by another user # group direct message, sent by another user
self.send_huddle_message( self.send_group_direct_message(
othello, othello,
[me, cordelia], [me, cordelia],
), ),
@ -2323,12 +2327,12 @@ class GetOldMessagesTest(ZulipTestCase):
# direct 1:1 message, current user to self # direct 1:1 message, current user to self
self.send_personal_message(me, me), self.send_personal_message(me, me),
# group direct message, sent by current user # group direct message, sent by current user
self.send_huddle_message( self.send_group_direct_message(
me, me,
[iago, othello], [iago, othello],
), ),
# group direct message, sent by searched user # group direct message, sent by searched user
self.send_huddle_message( self.send_group_direct_message(
cordelia, cordelia,
[iago, othello], [iago, othello],
), ),
@ -2352,17 +2356,17 @@ class GetOldMessagesTest(ZulipTestCase):
othello = self.example_user("othello") othello = self.example_user("othello")
message_ids = [ message_ids = [
self.send_huddle_message( self.send_group_direct_message(
me, me,
[iago, cordelia, othello], [iago, cordelia, othello],
), ),
self.send_personal_message(me, cordelia), self.send_personal_message(me, cordelia),
self.send_huddle_message( self.send_group_direct_message(
cordelia, cordelia,
[me, othello], [me, othello],
), ),
self.send_personal_message(cordelia, me), self.send_personal_message(cordelia, me),
self.send_huddle_message( self.send_group_direct_message(
iago, iago,
[cordelia, me], [cordelia, me],
), ),
@ -2383,11 +2387,11 @@ class GetOldMessagesTest(ZulipTestCase):
othello = self.example_user("othello") othello = self.example_user("othello")
matching_message_ids = [ matching_message_ids = [
self.send_huddle_message( self.send_group_direct_message(
me, me,
[iago, cordelia, othello], [iago, cordelia, othello],
), ),
self.send_huddle_message( self.send_group_direct_message(
me, me,
[cordelia, othello], [cordelia, othello],
), ),
@ -2395,11 +2399,11 @@ class GetOldMessagesTest(ZulipTestCase):
non_matching_message_ids = [ non_matching_message_ids = [
self.send_personal_message(me, cordelia), self.send_personal_message(me, cordelia),
self.send_huddle_message( self.send_group_direct_message(
me, me,
[iago, othello], [iago, othello],
), ),
self.send_huddle_message( self.send_group_direct_message(
self.example_user("cordelia"), self.example_user("cordelia"),
[iago, othello], [iago, othello],
), ),
@ -2423,15 +2427,15 @@ class GetOldMessagesTest(ZulipTestCase):
othello = self.example_user("othello") othello = self.example_user("othello")
message_ids = [ message_ids = [
self.send_huddle_message( self.send_group_direct_message(
me, me,
[iago, cordelia, othello], [iago, cordelia, othello],
), ),
self.send_huddle_message( self.send_group_direct_message(
me, me,
[cordelia, othello], [cordelia, othello],
), ),
self.send_huddle_message( self.send_group_direct_message(
me, me,
[cordelia, iago], [cordelia, iago],
), ),

View File

@ -1010,22 +1010,22 @@ class GetUnreadMsgsTest(ZulipTestCase):
), ),
) )
def test_raw_unread_huddle(self) -> None: def test_raw_unread_direct_message_group(self) -> None:
cordelia = self.example_user("cordelia") cordelia = self.example_user("cordelia")
othello = self.example_user("othello") othello = self.example_user("othello")
hamlet = self.example_user("hamlet") hamlet = self.example_user("hamlet")
prospero = self.example_user("prospero") prospero = self.example_user("prospero")
huddle1_message_ids = [ direct_message_group1_message_ids = [
self.send_huddle_message( self.send_group_direct_message(
cordelia, cordelia,
[hamlet, othello], [hamlet, othello],
) )
for i in range(3) for i in range(3)
] ]
huddle2_message_ids = [ direct_message_group2_message_ids = [
self.send_huddle_message( self.send_group_direct_message(
cordelia, cordelia,
[hamlet, prospero], [hamlet, prospero],
) )
@ -1036,18 +1036,20 @@ class GetUnreadMsgsTest(ZulipTestCase):
user_profile=hamlet, user_profile=hamlet,
) )
huddle_dict = raw_unread_data["huddle_dict"] direct_message_group_dict = raw_unread_data["huddle_dict"]
self.assertEqual( self.assertEqual(
set(huddle_dict.keys()), set(direct_message_group_dict.keys()),
set(huddle1_message_ids) | set(huddle2_message_ids), set(direct_message_group1_message_ids) | set(direct_message_group2_message_ids),
) )
huddle_string = ",".join(str(uid) for uid in sorted([cordelia.id, hamlet.id, othello.id])) direct_message_group_string = ",".join(
str(uid) for uid in sorted([cordelia.id, hamlet.id, othello.id])
)
self.assertEqual( self.assertEqual(
huddle_dict[huddle1_message_ids[0]], direct_message_group_dict[direct_message_group1_message_ids[0]],
dict(user_ids_string=huddle_string), dict(user_ids_string=direct_message_group_string),
) )
def test_raw_unread_personal(self) -> None: def test_raw_unread_personal(self) -> None:
@ -1205,7 +1207,7 @@ class GetUnreadMsgsTest(ZulipTestCase):
content="hello", content="hello",
) )
huddle_message_id = self.send_huddle_message( group_direct_message_id = self.send_group_direct_message(
sender, sender,
[user_profile, othello], [user_profile, othello],
"hello3", "hello3",
@ -1260,13 +1262,17 @@ class GetUnreadMsgsTest(ZulipTestCase):
unread_stream["unread_message_ids"], [unmuted_topic_muted_stream_message_id] unread_stream["unread_message_ids"], [unmuted_topic_muted_stream_message_id]
) )
huddle_string = ",".join( direct_message_group_string = ",".join(
str(uid) for uid in sorted([sender_id, user_profile.id, othello.id]) str(uid) for uid in sorted([sender_id, user_profile.id, othello.id])
) )
unread_huddle = result["huddles"][0] unread_direct_message_group = result["huddles"][0]
self.assertEqual(unread_huddle["user_ids_string"], huddle_string) self.assertEqual(
self.assertEqual(unread_huddle["unread_message_ids"], [huddle_message_id]) unread_direct_message_group["user_ids_string"], direct_message_group_string
)
self.assertEqual(
unread_direct_message_group["unread_message_ids"], [group_direct_message_id]
)
self.assertEqual(result["mentions"], []) self.assertEqual(result["mentions"], [])
@ -2497,13 +2503,13 @@ class MarkUnreadTest(ZulipTestCase):
) )
self.assertTrue(um.flags.read) self.assertTrue(um.flags.read)
def test_huddle_messages_unread(self) -> None: def test_group_direct_messages_unread(self) -> None:
sender = self.example_user("cordelia") sender = self.example_user("cordelia")
receiver = self.example_user("hamlet") receiver = self.example_user("hamlet")
user1 = self.example_user("othello") user1 = self.example_user("othello")
message_ids = [ message_ids = [
# self.send_huddle_message(sender, receiver, content="Hello") for i in range(4) # self.send_group_direct_message(sender, receiver, content="Hello") for i in range(4)
self.send_huddle_message(sender, [receiver, user1]) self.send_group_direct_message(sender, [receiver, user1])
for i in range(4) for i in range(4)
] ]
self.login("hamlet") self.login("hamlet")
@ -2558,13 +2564,13 @@ class MarkUnreadTest(ZulipTestCase):
) )
self.assertTrue(um.flags.read) self.assertTrue(um.flags.read)
def test_huddle_messages_unread_mention(self) -> None: def test_group_direct_messages_unread_mention(self) -> None:
sender = self.example_user("cordelia") sender = self.example_user("cordelia")
receiver = self.example_user("hamlet") receiver = self.example_user("hamlet")
user1 = self.example_user("othello") user1 = self.example_user("othello")
message_ids = [ message_ids = [
# self.send_huddle_message(sender, receiver, content="Hello") for i in range(4) # self.send_group_direct_message(sender, receiver, content="Hello") for i in range(4)
self.send_huddle_message( self.send_group_direct_message(
from_user=sender, to_users=[receiver, user1], content="@**King Hamlet**" from_user=sender, to_users=[receiver, user1], content="@**King Hamlet**"
) )
for i in range(4) for i in range(4)

View File

@ -544,10 +544,10 @@ class TestMessageNotificationEmails(ZulipTestCase):
email_subject = "DMs with Othello, the Moor of Venice" email_subject = "DMs with Othello, the Moor of Venice"
self._test_cases(msg_id, verify_body_include, email_subject) self._test_cases(msg_id, verify_body_include, email_subject)
def _extra_context_in_missed_huddle_messages_two_others( def _extra_context_in_missed_group_direct_messages_two_others(
self, show_message_content: bool = True self, show_message_content: bool = True
) -> None: ) -> None:
msg_id = self.send_huddle_message( msg_id = self.send_group_direct_message(
self.example_user("othello"), self.example_user("othello"),
[ [
self.example_user("hamlet"), self.example_user("hamlet"),
@ -585,8 +585,8 @@ class TestMessageNotificationEmails(ZulipTestCase):
verify_body_does_not_include=verify_body_does_not_include, verify_body_does_not_include=verify_body_does_not_include,
) )
def _extra_context_in_missed_huddle_messages_three_others(self) -> None: def _extra_context_in_missed_group_direct_messages_three_others(self) -> None:
msg_id = self.send_huddle_message( msg_id = self.send_group_direct_message(
self.example_user("othello"), self.example_user("othello"),
[ [
self.example_user("hamlet"), self.example_user("hamlet"),
@ -602,8 +602,8 @@ class TestMessageNotificationEmails(ZulipTestCase):
) )
self._test_cases(msg_id, verify_body_include, email_subject) self._test_cases(msg_id, verify_body_include, email_subject)
def _extra_context_in_missed_huddle_messages_many_others(self) -> None: def _extra_context_in_missed_group_direct_messages_many_others(self) -> None:
msg_id = self.send_huddle_message( msg_id = self.send_group_direct_message(
self.example_user("othello"), self.example_user("othello"),
[ [
self.example_user("hamlet"), self.example_user("hamlet"),
@ -648,8 +648,8 @@ class TestMessageNotificationEmails(ZulipTestCase):
) )
self.assert_length(mail.outbox, 0) self.assert_length(mail.outbox, 0)
def _deleted_message_in_missed_huddle_messages(self) -> None: def _deleted_message_in_missed_group_direct_messages(self) -> None:
msg_id = self.send_huddle_message( msg_id = self.send_group_direct_message(
self.example_user("othello"), self.example_user("othello"),
[ [
self.example_user("hamlet"), self.example_user("hamlet"),
@ -1042,7 +1042,7 @@ class TestMessageNotificationEmails(ZulipTestCase):
show_message_content=False, message_content_disabled_by_user=True show_message_content=False, message_content_disabled_by_user=True
) )
mail.outbox = [] mail.outbox = []
self._extra_context_in_missed_huddle_messages_two_others(show_message_content=False) self._extra_context_in_missed_group_direct_messages_two_others(show_message_content=False)
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() self._extra_context_in_missed_stream_messages_mention()
@ -1100,14 +1100,14 @@ class TestMessageNotificationEmails(ZulipTestCase):
def test_extra_context_in_missed_personal_messages(self) -> None: def test_extra_context_in_missed_personal_messages(self) -> None:
self._extra_context_in_missed_personal_messages() self._extra_context_in_missed_personal_messages()
def test_extra_context_in_missed_huddle_messages_two_others(self) -> None: def test_extra_context_in_missed_group_direct_messages_two_others(self) -> None:
self._extra_context_in_missed_huddle_messages_two_others() self._extra_context_in_missed_group_direct_messages_two_others()
def test_extra_context_in_missed_huddle_messages_three_others(self) -> None: def test_extra_context_in_missed_group_direct_messages_three_others(self) -> None:
self._extra_context_in_missed_huddle_messages_three_others() self._extra_context_in_missed_group_direct_messages_three_others()
def test_extra_context_in_missed_huddle_messages_many_others(self) -> None: def test_extra_context_in_missed_group_direct_messages_many_others(self) -> None:
self._extra_context_in_missed_huddle_messages_many_others() self._extra_context_in_missed_group_direct_messages_many_others()
def test_deleted_message_in_missed_stream_messages(self) -> None: def test_deleted_message_in_missed_stream_messages(self) -> None:
self._deleted_message_in_missed_stream_messages() self._deleted_message_in_missed_stream_messages()
@ -1115,8 +1115,8 @@ class TestMessageNotificationEmails(ZulipTestCase):
def test_deleted_message_in_missed_personal_messages(self) -> None: def test_deleted_message_in_missed_personal_messages(self) -> None:
self._deleted_message_in_missed_personal_messages() self._deleted_message_in_missed_personal_messages()
def test_deleted_message_in_missed_huddle_messages(self) -> None: def test_deleted_message_in_missed_group_direct_messages(self) -> None:
self._deleted_message_in_missed_huddle_messages() self._deleted_message_in_missed_group_direct_messages()
def test_realm_message_content_allowed_in_email_notifications(self) -> None: def test_realm_message_content_allowed_in_email_notifications(self) -> None:
user = self.example_user("hamlet") user = self.example_user("hamlet")

View File

@ -20,7 +20,7 @@ from zerver.actions.message_send import (
extract_stream_indicator, extract_stream_indicator,
internal_prep_private_message, internal_prep_private_message,
internal_prep_stream_message_by_name, internal_prep_stream_message_by_name,
internal_send_huddle_message, internal_send_group_direct_message,
internal_send_private_message, internal_send_private_message,
internal_send_stream_message, internal_send_stream_message,
internal_send_stream_message_by_name, internal_send_stream_message_by_name,
@ -61,7 +61,7 @@ from zerver.models import (
from zerver.models.constants import MAX_TOPIC_NAME_LENGTH from zerver.models.constants import MAX_TOPIC_NAME_LENGTH
from zerver.models.groups import SystemGroups from zerver.models.groups import SystemGroups
from zerver.models.realms import PrivateMessagePolicyEnum, WildcardMentionPolicyEnum, get_realm from zerver.models.realms import PrivateMessagePolicyEnum, WildcardMentionPolicyEnum, get_realm
from zerver.models.recipients import get_or_create_huddle from zerver.models.recipients import get_or_create_direct_message_group
from zerver.models.streams import get_stream from zerver.models.streams import get_stream
from zerver.models.users import get_system_bot, get_user from zerver.models.users import get_system_bot, get_user
from zerver.views.message_send import InvalidMirrorInputError from zerver.views.message_send import InvalidMirrorInputError
@ -713,14 +713,14 @@ class MessagePOSTTest(ZulipTestCase):
msg = self.get_last_message() msg = self.get_last_message()
self.assertEqual("Test message", msg.content) self.assertEqual("Test message", msg.content)
huddle = get_or_create_huddle( direct_message_group = get_or_create_direct_message_group(
[ [
self.example_user("hamlet").id, self.example_user("hamlet").id,
self.example_user("othello").id, self.example_user("othello").id,
self.example_user("cordelia").id, self.example_user("cordelia").id,
] ]
) )
self.assertEqual(msg.recipient_id, huddle.recipient_id) self.assertEqual(msg.recipient_id, direct_message_group.recipient_id)
def test_personal_message_copying_self(self) -> None: def test_personal_message_copying_self(self) -> None:
""" """
@ -967,9 +967,9 @@ class MessagePOSTTest(ZulipTestCase):
) )
self.assert_json_error(result, "Message must have recipients") self.assert_json_error(result, "Message must have recipients")
def test_mirrored_huddle(self) -> None: def test_mirrored_direct_message_group(self) -> None:
""" """
Sending a mirrored huddle message works Sending a mirrored group direct message works
""" """
result = self.api_post( result = self.api_post(
self.mit_user("starnine"), self.mit_user("starnine"),
@ -1042,9 +1042,9 @@ class MessagePOSTTest(ZulipTestCase):
) )
self.assert_json_error(result, "User not authorized for this query") self.assert_json_error(result, "User not authorized for this query")
def test_duplicated_mirrored_huddle(self) -> None: def test_duplicated_mirrored_direct_message_group(self) -> None:
""" """
Sending two mirrored huddles in the row return the same ID Sending two mirrored direct message groups in the row return the same ID
""" """
msg = { msg = {
"type": "direct", "type": "direct",
@ -2325,7 +2325,7 @@ class StreamMessagesTest(ZulipTestCase):
self.assert_stream_message(non_ascii_stream_name, topic_name="hümbüǵ", content="hümbüǵ") self.assert_stream_message(non_ascii_stream_name, topic_name="hümbüǵ", content="hümbüǵ")
def test_get_raw_unread_data_for_huddle_messages(self) -> None: def test_get_raw_unread_data_for_group_direct_messages(self) -> None:
users = [ users = [
self.example_user("hamlet"), self.example_user("hamlet"),
self.example_user("cordelia"), self.example_user("cordelia"),
@ -2334,8 +2334,8 @@ class StreamMessagesTest(ZulipTestCase):
self.example_user("othello"), self.example_user("othello"),
] ]
message1_id = self.send_huddle_message(users[0], users, "test content 1") message1_id = self.send_group_direct_message(users[0], users, "test content 1")
message2_id = self.send_huddle_message(users[0], users, "test content 2") message2_id = self.send_group_direct_message(users[0], users, "test content 2")
msg_data = get_raw_unread_data(users[1]) msg_data = get_raw_unread_data(users[1])
@ -2580,7 +2580,7 @@ class InternalPrepTest(ZulipTestCase):
) )
with self.assertLogs(level="ERROR") as m: with self.assertLogs(level="ERROR") as m:
internal_send_huddle_message( internal_send_group_direct_message(
realm=realm, realm=realm,
sender=cordelia, sender=cordelia,
emails=[hamlet.email, othello.email], emails=[hamlet.email, othello.email],
@ -2840,23 +2840,24 @@ class TestCrossRealmPMs(ZulipTestCase):
# (We don't particularly need this feature, but since users can # (We don't particularly need this feature, but since users can
# already individually send direct messages to cross-realm bots, # already individually send direct messages to cross-realm bots,
# we shouldn't prevent them from sending multiple bots at once. # we shouldn't prevent them from sending multiple bots at once.
# We may revisit this if it's a nuisance for huddles.) # We may revisit this if it's a nuisance for direct message
self.send_huddle_message(user1, [notification_bot, support_bot]) # groups.)
self.send_group_direct_message(user1, [notification_bot, support_bot])
assert_message_received(notification_bot, user1) assert_message_received(notification_bot, user1)
assert_message_received(support_bot, user1) assert_message_received(support_bot, user1)
# Prevent old loophole where I could send direct messages to other # Prevent old loophole where I could send direct messages to other
# users as long as I copied a cross-realm bot from the same realm. # users as long as I copied a cross-realm bot from the same realm.
with assert_invalid_user(): with assert_invalid_user():
self.send_huddle_message(user1, [user3, support_bot]) self.send_group_direct_message(user1, [user3, support_bot])
# Users on three different realms can't send direct messages to # Users on three different realms can't send direct messages to
# each other, even if one of the users is a cross-realm bot. # each other, even if one of the users is a cross-realm bot.
with assert_invalid_user(): with assert_invalid_user():
self.send_huddle_message(user1, [user2, notification_bot]) self.send_group_direct_message(user1, [user2, notification_bot])
with assert_invalid_user(): with assert_invalid_user():
self.send_huddle_message(notification_bot, [user1, user2]) self.send_group_direct_message(notification_bot, [user1, user2])
# Users on the different realms cannot send direct messages to # Users on the different realms cannot send direct messages to
# each other. # each other.
@ -2871,7 +2872,7 @@ class TestCrossRealmPMs(ZulipTestCase):
# Users on three different realms cannot send direct messages # Users on three different realms cannot send direct messages
# to each other. # to each other.
with assert_invalid_user(): with assert_invalid_user():
self.send_huddle_message(user1, [user2, user3]) self.send_group_direct_message(user1, [user2, user3])
class TestAddressee(ZulipTestCase): class TestAddressee(ZulipTestCase):

View File

@ -6,7 +6,10 @@ from django.utils.timezone import now as timezone_now
from zerver.actions.message_send import get_active_presence_idle_user_ids from zerver.actions.message_send import get_active_presence_idle_user_ids
from zerver.lib.test_classes import ZulipTestCase from zerver.lib.test_classes import ZulipTestCase
from zerver.models import Message, UserPresence, UserProfile from zerver.models import Message, UserPresence, UserProfile
from zerver.models.recipients import bulk_get_huddle_user_ids, get_huddle_user_ids from zerver.models.recipients import (
bulk_get_direct_message_group_user_ids,
get_direct_message_group_user_ids,
)
class MissedMessageTest(ZulipTestCase): class MissedMessageTest(ZulipTestCase):
@ -64,36 +67,46 @@ class MissedMessageTest(ZulipTestCase):
set_presence(hamlet, "website", ago=15) set_presence(hamlet, "website", ago=15)
assert_active_presence_idle_user_ids([]) assert_active_presence_idle_user_ids([])
# Hamlet is active now, so only Othello should be in the list for a huddle # Hamlet is active now, so only Othello should be in the list for a group
# message. # direct message.
hamlet_notifications_data.stream_email_notify = False hamlet_notifications_data.stream_email_notify = False
hamlet_notifications_data.dm_push_notify = False hamlet_notifications_data.dm_push_notify = False
othello_notifications_data.dm_push_notify = True othello_notifications_data.dm_push_notify = True
assert_active_presence_idle_user_ids([othello.id]) assert_active_presence_idle_user_ids([othello.id])
class TestBulkGetHuddleUserIds(ZulipTestCase): class TestBulkGetDirectMessageGroupUserIds(ZulipTestCase):
def test_bulk_get_huddle_user_ids(self) -> None: def test_bulk_get_direct_message_group_user_ids(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")
iago = self.example_user("iago") iago = self.example_user("iago")
message_ids = [ message_ids = [
self.send_huddle_message(hamlet, [cordelia, othello], "test"), self.send_group_direct_message(hamlet, [cordelia, othello], "test"),
self.send_huddle_message(cordelia, [hamlet, othello, iago], "test"), self.send_group_direct_message(cordelia, [hamlet, othello, iago], "test"),
] ]
messages = Message.objects.filter(id__in=message_ids).order_by("id") messages = Message.objects.filter(id__in=message_ids).order_by("id")
first_huddle_recipient = messages[0].recipient first_direct_message_group_recipient = messages[0].recipient
first_huddle_user_ids = set(get_huddle_user_ids(first_huddle_recipient)) first_direct_message_group_user_ids = set(
second_huddle_recipient = messages[1].recipient get_direct_message_group_user_ids(first_direct_message_group_recipient)
second_huddle_user_ids = set(get_huddle_user_ids(second_huddle_recipient)) )
second_direct_message_group_recipient = messages[1].recipient
huddle_user_ids = bulk_get_huddle_user_ids( second_direct_message_group_user_ids = set(
[first_huddle_recipient.id, second_huddle_recipient.id] get_direct_message_group_user_ids(second_direct_message_group_recipient)
) )
self.assertEqual(huddle_user_ids[first_huddle_recipient.id], first_huddle_user_ids)
self.assertEqual(huddle_user_ids[second_huddle_recipient.id], second_huddle_user_ids)
def test_bulk_get_huddle_user_ids_empty_list(self) -> None: direct_message_group_user_ids = bulk_get_direct_message_group_user_ids(
self.assertEqual(bulk_get_huddle_user_ids([]), {}) [first_direct_message_group_recipient.id, second_direct_message_group_recipient.id]
)
self.assertEqual(
direct_message_group_user_ids[first_direct_message_group_recipient.id],
first_direct_message_group_user_ids,
)
self.assertEqual(
direct_message_group_user_ids[second_direct_message_group_recipient.id],
second_direct_message_group_user_ids,
)
def test_bulk_get_direct_message_group_user_ids_empty_list(self) -> None:
self.assertEqual(bulk_get_direct_message_group_user_ids([]), {})

View File

@ -231,18 +231,20 @@ class MutedUsersTests(ZulipTestCase):
# Have Cordelia send messages to Hamlet and Othello. # Have Cordelia send messages to Hamlet and Othello.
stream_message = self.send_stream_message(cordelia, "general", "Spam in stream") stream_message = self.send_stream_message(cordelia, "general", "Spam in stream")
huddle_message = self.send_huddle_message(cordelia, [hamlet, othello], "Spam in huddle") group_direct_message = self.send_group_direct_message(
cordelia, [hamlet, othello], "Spam in direct message group"
)
pm_to_hamlet = self.send_personal_message(cordelia, hamlet, "Spam in direct message") pm_to_hamlet = self.send_personal_message(cordelia, hamlet, "Spam in direct message")
pm_to_othello = self.send_personal_message(cordelia, othello, "Spam in direct message") pm_to_othello = self.send_personal_message(cordelia, othello, "Spam in direct message")
# These should be marked as read for Hamlet, since he has muted Cordelia. # These should be marked as read for Hamlet, since he has muted Cordelia.
self.assert_usermessage_read_flag(hamlet, stream_message, True) self.assert_usermessage_read_flag(hamlet, stream_message, True)
self.assert_usermessage_read_flag(hamlet, huddle_message, True) self.assert_usermessage_read_flag(hamlet, group_direct_message, True)
self.assert_usermessage_read_flag(hamlet, pm_to_hamlet, True) self.assert_usermessage_read_flag(hamlet, pm_to_hamlet, True)
# These messages should be unreads for Othello, since he hasn't muted Cordelia. # These messages should be unreads for Othello, since he hasn't muted Cordelia.
self.assert_usermessage_read_flag(othello, stream_message, False) self.assert_usermessage_read_flag(othello, stream_message, False)
self.assert_usermessage_read_flag(othello, huddle_message, False) self.assert_usermessage_read_flag(othello, group_direct_message, False)
self.assert_usermessage_read_flag(othello, pm_to_othello, False) self.assert_usermessage_read_flag(othello, pm_to_othello, False)
def test_existing_messages_from_muted_user_marked_as_read(self) -> None: def test_existing_messages_from_muted_user_marked_as_read(self) -> None:
@ -258,17 +260,19 @@ class MutedUsersTests(ZulipTestCase):
# Have Cordelia send messages to Hamlet and Othello. # Have Cordelia send messages to Hamlet and Othello.
stream_message = self.send_stream_message(cordelia, "general", "Spam in stream") stream_message = self.send_stream_message(cordelia, "general", "Spam in stream")
huddle_message = self.send_huddle_message(cordelia, [hamlet, othello], "Spam in huddle") group_direct_message = self.send_group_direct_message(
cordelia, [hamlet, othello], "Spam in direct message group"
)
pm_to_hamlet = self.send_personal_message(cordelia, hamlet, "Spam in direct message") pm_to_hamlet = self.send_personal_message(cordelia, hamlet, "Spam in direct message")
pm_to_othello = self.send_personal_message(cordelia, othello, "Spam in direct message") pm_to_othello = self.send_personal_message(cordelia, othello, "Spam in direct message")
# These messages are unreads for both Hamlet and Othello right now. # These messages are unreads for both Hamlet and Othello right now.
self.assert_usermessage_read_flag(hamlet, stream_message, False) self.assert_usermessage_read_flag(hamlet, stream_message, False)
self.assert_usermessage_read_flag(hamlet, huddle_message, False) self.assert_usermessage_read_flag(hamlet, group_direct_message, False)
self.assert_usermessage_read_flag(hamlet, pm_to_hamlet, False) self.assert_usermessage_read_flag(hamlet, pm_to_hamlet, False)
self.assert_usermessage_read_flag(othello, stream_message, False) self.assert_usermessage_read_flag(othello, stream_message, False)
self.assert_usermessage_read_flag(othello, huddle_message, False) self.assert_usermessage_read_flag(othello, group_direct_message, False)
self.assert_usermessage_read_flag(othello, pm_to_othello, False) self.assert_usermessage_read_flag(othello, pm_to_othello, False)
# Hamlet mutes Cordelia. # Hamlet mutes Cordelia.
@ -278,12 +282,12 @@ class MutedUsersTests(ZulipTestCase):
# The messages sent earlier should be marked as read for Hamlet. # The messages sent earlier should be marked as read for Hamlet.
self.assert_usermessage_read_flag(hamlet, stream_message, True) self.assert_usermessage_read_flag(hamlet, stream_message, True)
self.assert_usermessage_read_flag(hamlet, huddle_message, True) self.assert_usermessage_read_flag(hamlet, group_direct_message, True)
self.assert_usermessage_read_flag(hamlet, pm_to_hamlet, True) self.assert_usermessage_read_flag(hamlet, pm_to_hamlet, True)
# These messages are still unreads for Othello, since he did not mute Cordelia. # These messages are still unreads for Othello, since he did not mute Cordelia.
self.assert_usermessage_read_flag(othello, stream_message, False) self.assert_usermessage_read_flag(othello, stream_message, False)
self.assert_usermessage_read_flag(othello, huddle_message, False) self.assert_usermessage_read_flag(othello, group_direct_message, False)
self.assert_usermessage_read_flag(othello, pm_to_othello, False) self.assert_usermessage_read_flag(othello, pm_to_othello, False)
def test_muted_message_send_notifications_not_enqueued(self) -> None: def test_muted_message_send_notifications_not_enqueued(self) -> None:

View File

@ -16,7 +16,7 @@ from zerver.lib.test_classes import ZulipTestCase
from zerver.lib.timezone import canonicalize_timezone from zerver.lib.timezone import canonicalize_timezone
from zerver.models import Message, Recipient, Stream, UserProfile from zerver.models import Message, Recipient, Stream, UserProfile
from zerver.models.realms import get_realm from zerver.models.realms import get_realm
from zerver.models.recipients import get_huddle_user_ids from zerver.models.recipients import get_direct_message_group_user_ids
from zerver.models.streams import get_stream from zerver.models.streams import get_stream
from zerver.models.users import get_system_bot from zerver.models.users import get_system_bot
from zerver.signals import JUST_CREATED_THRESHOLD, get_device_browser, get_device_os from zerver.signals import JUST_CREATED_THRESHOLD, get_device_browser, get_device_os
@ -342,7 +342,7 @@ class TestNotifyNewUser(ZulipTestCase):
) )
# Group DM # Group DM
self.assertEqual( self.assertEqual(
set(get_huddle_user_ids(message.recipient)), set(get_direct_message_group_user_ids(message.recipient)),
expected_group_direct_message_user_ids, expected_group_direct_message_user_ids,
) )
self.assertIn( self.assertIn(

View File

@ -4005,11 +4005,11 @@ class TestGetAPNsPayload(PushNotificationTest):
self.assertDictEqual(payload, expected) self.assertDictEqual(payload, expected)
@mock.patch("zerver.lib.push_notifications.push_notifications_configured", return_value=True) @mock.patch("zerver.lib.push_notifications.push_notifications_configured", return_value=True)
def test_get_message_payload_apns_huddle_message( def test_get_message_payload_apns_group_direct_message(
self, mock_push_notifications: mock.MagicMock self, mock_push_notifications: mock.MagicMock
) -> None: ) -> None:
user_profile = self.example_user("othello") user_profile = self.example_user("othello")
message_id = self.send_huddle_message( message_id = self.send_group_direct_message(
self.sender, [self.example_user("othello"), self.example_user("cordelia")] self.sender, [self.example_user("othello"), self.example_user("cordelia")]
) )
message = Message.objects.get(id=message_id) message = Message.objects.get(id=message_id)
@ -4225,7 +4225,7 @@ class TestGetAPNsPayload(PushNotificationTest):
@override_settings(PUSH_NOTIFICATION_REDACT_CONTENT=True) @override_settings(PUSH_NOTIFICATION_REDACT_CONTENT=True)
def test_get_message_payload_apns_redacted_content(self) -> None: def test_get_message_payload_apns_redacted_content(self) -> None:
user_profile = self.example_user("othello") user_profile = self.example_user("othello")
message_id = self.send_huddle_message( message_id = self.send_group_direct_message(
self.sender, [self.example_user("othello"), self.example_user("cordelia")] self.sender, [self.example_user("othello"), self.example_user("cordelia")]
) )
message = Message.objects.get(id=message_id) message = Message.objects.get(id=message_id)

View File

@ -616,14 +616,14 @@ class ReactionEventTest(ZulipTestCase):
self.assertEqual(event_user_ids, {iago.id, hamlet.id}) self.assertEqual(event_user_ids, {iago.id, hamlet.id})
# Group direct message; event should go to all participants. # Group direct message; event should go to all participants.
huddle_message_id = self.send_huddle_message( group_direct_message_id = self.send_group_direct_message(
hamlet, hamlet,
[polonius, iago], [polonius, iago],
"hello message to multiple receiver", "hello message to multiple receiver",
) )
with self.capture_send_event_calls(expected_num_events=1) as events: with self.capture_send_event_calls(expected_num_events=1) as events:
result = self.api_post( result = self.api_post(
polonius, f"/api/v1/messages/{huddle_message_id}/reactions", reaction_info polonius, f"/api/v1/messages/{group_direct_message_id}/reactions", reaction_info
) )
self.assert_json_success(result) self.assert_json_success(result)
event = events[0]["event"] event = events[0]["event"]

View File

@ -55,12 +55,12 @@ class TestReadReceipts(ZulipTestCase):
self.assertTrue(hamlet.id in result.json()["user_ids"]) self.assertTrue(hamlet.id in result.json()["user_ids"])
self.assertTrue(sender.id not in result.json()["user_ids"]) self.assertTrue(sender.id not in result.json()["user_ids"])
def test_huddle_message(self) -> None: def test_group_direct_message(self) -> None:
hamlet = self.example_user("hamlet") hamlet = self.example_user("hamlet")
sender = self.example_user("othello") sender = self.example_user("othello")
cordelia = self.example_user("cordelia") cordelia = self.example_user("cordelia")
message_id = self.send_huddle_message(sender, [hamlet, cordelia]) message_id = self.send_group_direct_message(sender, [hamlet, cordelia])
self.login("hamlet") self.login("hamlet")
result = self.client_get(f"/json/messages/{message_id}/read_receipts") result = self.client_get(f"/json/messages/{message_id}/read_receipts")

View File

@ -18,7 +18,7 @@ from confirmation.models import Confirmation, create_confirmation_link
from zerver.actions.create_realm import do_change_realm_subdomain, do_create_realm from zerver.actions.create_realm import do_change_realm_subdomain, do_create_realm
from zerver.actions.create_user import do_create_user from zerver.actions.create_user import do_create_user
from zerver.actions.message_send import ( from zerver.actions.message_send import (
internal_send_huddle_message, internal_send_group_direct_message,
internal_send_private_message, internal_send_private_message,
internal_send_stream_message, internal_send_stream_message,
) )
@ -2220,7 +2220,7 @@ class ScrubRealmTest(ZulipTestCase):
notification_bot, get_stream("Scotland", zulip), "test", "test" notification_bot, get_stream("Scotland", zulip), "test", "test"
) )
internal_send_private_message(notification_bot, othello, "test") internal_send_private_message(notification_bot, othello, "test")
internal_send_huddle_message( internal_send_group_direct_message(
zulip, notification_bot, "test", emails=[othello.email, iago.email] zulip, notification_bot, "test", emails=[othello.email, iago.email]
) )
@ -2228,7 +2228,7 @@ class ScrubRealmTest(ZulipTestCase):
notification_bot, get_stream("Shakespeare", lear), "test", "test" notification_bot, get_stream("Shakespeare", lear), "test", "test"
) )
internal_send_private_message(notification_bot, king, "test") internal_send_private_message(notification_bot, king, "test")
internal_send_huddle_message( internal_send_group_direct_message(
lear, notification_bot, "test", emails=[cordelia.email, king.email] lear, notification_bot, "test", emails=[cordelia.email, king.email]
) )

View File

@ -10,7 +10,7 @@ from zerver.data_import.rocketchat import (
build_reactions, build_reactions,
categorize_channels_and_map_with_id, categorize_channels_and_map_with_id,
convert_channel_data, convert_channel_data,
convert_huddle_data, convert_direct_message_group_data,
convert_stream_subscription_data, convert_stream_subscription_data,
do_convert_data, do_convert_data,
map_receiver_id_to_recipient_id, map_receiver_id_to_recipient_id,
@ -227,9 +227,11 @@ class RocketChatImporter(ZulipTestCase):
self.assertIn(direct_id, direct_id_to_direct_map) self.assertIn(direct_id, direct_id_to_direct_map)
self.assertEqual(direct_id_to_direct_map[direct_id], rocketchat_data["room"][4]) self.assertEqual(direct_id_to_direct_map[direct_id], rocketchat_data["room"][4])
huddle_id = rocketchat_data["room"][12]["_id"] direct_message_group_id = rocketchat_data["room"][12]["_id"]
self.assertIn(huddle_id, huddle_id_to_huddle_map) self.assertIn(direct_message_group_id, huddle_id_to_huddle_map)
self.assertEqual(huddle_id_to_huddle_map[huddle_id], rocketchat_data["room"][12]) self.assertEqual(
huddle_id_to_huddle_map[direct_message_group_id], rocketchat_data["room"][12]
)
livechat_id = rocketchat_data["room"][14]["_id"] livechat_id = rocketchat_data["room"][14]["_id"]
self.assertIn(livechat_id, livechat_id_to_livechat_map) self.assertIn(livechat_id, livechat_id_to_livechat_map)
@ -412,7 +414,7 @@ class RocketChatImporter(ZulipTestCase):
self.assert_length(subscriber_handler.get_users(stream_id=zerver_stream[6]["id"]), 0) self.assert_length(subscriber_handler.get_users(stream_id=zerver_stream[6]["id"]), 0)
self.assertTrue(zerver_stream[6]["deactivated"]) self.assertTrue(zerver_stream[6]["deactivated"])
def test_convert_huddle_data(self) -> None: def test_convert_direct_message_group_data(self) -> None:
fixture_dir_name = self.fixture_file_name("", "rocketchat_fixtures") fixture_dir_name = self.fixture_file_name("", "rocketchat_fixtures")
rocketchat_data = rocketchat_data_to_dict(fixture_dir_name) rocketchat_data = rocketchat_data_to_dict(fixture_dir_name)
@ -452,20 +454,22 @@ class RocketChatImporter(ZulipTestCase):
livechat_id_to_livechat_map=livechat_id_to_livechat_map, livechat_id_to_livechat_map=livechat_id_to_livechat_map,
) )
zerver_huddle = convert_huddle_data( zerver_direct_message_group = convert_direct_message_group_data(
huddle_id_to_huddle_map=huddle_id_to_huddle_map, huddle_id_to_huddle_map=huddle_id_to_huddle_map,
huddle_id_mapper=huddle_id_mapper, huddle_id_mapper=huddle_id_mapper,
user_id_mapper=user_id_mapper, user_id_mapper=user_id_mapper,
subscriber_handler=subscriber_handler, subscriber_handler=subscriber_handler,
) )
self.assert_length(zerver_huddle, 1) self.assert_length(zerver_direct_message_group, 1)
rc_huddle_id = rocketchat_data["room"][12]["_id"] rc_huddle_id = rocketchat_data["room"][12]["_id"]
self.assertTrue(huddle_id_mapper.has(rc_huddle_id)) self.assertTrue(huddle_id_mapper.has(rc_huddle_id))
huddle_id = huddle_id_mapper.get(rc_huddle_id) direct_message_group_id = huddle_id_mapper.get(rc_huddle_id)
self.assertEqual(subscriber_handler.get_users(huddle_id=huddle_id), {3, 4, 5}) self.assertEqual(
subscriber_handler.get_users(direct_message_group_id=direct_message_group_id), {3, 4, 5}
)
def test_write_emoticon_data(self) -> None: def test_write_emoticon_data(self) -> None:
fixture_dir_name = self.fixture_file_name("", "rocketchat_fixtures") fixture_dir_name = self.fixture_file_name("", "rocketchat_fixtures")
@ -560,7 +564,7 @@ class RocketChatImporter(ZulipTestCase):
realm_id=realm_id, realm_id=realm_id,
) )
zerver_huddle = convert_huddle_data( zerver_direct_message_group = convert_direct_message_group_data(
huddle_id_to_huddle_map=huddle_id_to_huddle_map, huddle_id_to_huddle_map=huddle_id_to_huddle_map,
huddle_id_mapper=huddle_id_mapper, huddle_id_mapper=huddle_id_mapper,
user_id_mapper=user_id_mapper, user_id_mapper=user_id_mapper,
@ -572,7 +576,7 @@ class RocketChatImporter(ZulipTestCase):
zerver_recipient = build_recipients( zerver_recipient = build_recipients(
zerver_userprofile=all_users, zerver_userprofile=all_users,
zerver_stream=zerver_stream, zerver_stream=zerver_stream,
zerver_huddle=zerver_huddle, zerver_direct_message_group=zerver_direct_message_group,
) )
stream_id_to_recipient_id: Dict[int, int] = {} stream_id_to_recipient_id: Dict[int, int] = {}
@ -659,7 +663,7 @@ class RocketChatImporter(ZulipTestCase):
self.assertIn(rocketchat_data["message"][11], private_messages) self.assertIn(rocketchat_data["message"][11], private_messages)
self.assertIn(rocketchat_data["message"][12], private_messages) self.assertIn(rocketchat_data["message"][12], private_messages)
self.assertIn(rocketchat_data["message"][50], private_messages) # Huddle message self.assertIn(rocketchat_data["message"][50], private_messages) # Group direct message
self.assertIn(rocketchat_data["message"][79], livechat_messages) self.assertIn(rocketchat_data["message"][79], livechat_messages)
self.assertIn(rocketchat_data["message"][83], livechat_messages) self.assertIn(rocketchat_data["message"][83], livechat_messages)
@ -1021,23 +1025,23 @@ class RocketChatImporter(ZulipTestCase):
self.assertTrue(stream_messages[23].has_image) self.assertTrue(stream_messages[23].has_image)
self.assertTrue(stream_messages[23].has_link) self.assertTrue(stream_messages[23].has_link)
huddle_messages = messages.filter(recipient__type=Recipient.DIRECT_MESSAGE_GROUP).order_by( group_direct_messages = messages.filter(
"date_sent" recipient__type=Recipient.DIRECT_MESSAGE_GROUP
) ).order_by("date_sent")
huddle_recipients = huddle_messages.values_list("recipient", flat=True) direct_message_group_recipients = group_direct_messages.values_list("recipient", flat=True)
self.assert_length(huddle_messages, 5) self.assert_length(group_direct_messages, 5)
self.assert_length(set(huddle_recipients), 2) self.assert_length(set(direct_message_group_recipients), 2)
self.assertEqual(huddle_messages[0].sender.email, "hermionegranger@email.com") self.assertEqual(group_direct_messages[0].sender.email, "hermionegranger@email.com")
self.assertEqual(huddle_messages[0].content, "Hey people!") self.assertEqual(group_direct_messages[0].content, "Hey people!")
self.assertEqual(huddle_messages[2].sender.email, "harrypotter@email.com") self.assertEqual(group_direct_messages[2].sender.email, "harrypotter@email.com")
self.assertRegex( self.assertRegex(
huddle_messages[2].content, group_direct_messages[2].content,
"This year's curriculum is out.\n\n\\[Hogwarts Curriculum.pdf\\]\\(.*\\)", "This year's curriculum is out.\n\n\\[Hogwarts Curriculum.pdf\\]\\(.*\\)",
) )
self.assertTrue(huddle_messages[2].has_attachment) self.assertTrue(group_direct_messages[2].has_attachment)
self.assertFalse(huddle_messages[2].has_image) self.assertFalse(group_direct_messages[2].has_image)
self.assertTrue(huddle_messages[2].has_link) self.assertTrue(group_direct_messages[2].has_link)
personal_messages = messages.filter(recipient__type=Recipient.PERSONAL).order_by( personal_messages = messages.filter(recipient__type=Recipient.PERSONAL).order_by(
"date_sent" "date_sent"

View File

@ -566,7 +566,7 @@ class TestServiceBotEventTriggers(ZulipTestCase):
@for_all_bot_types @for_all_bot_types
@patch_queue_publish("zerver.actions.message_send.queue_event_on_commit") @patch_queue_publish("zerver.actions.message_send.queue_event_on_commit")
def test_trigger_on_huddle_message_from_user( def test_trigger_on_group_direct_message_from_user(
self, mock_queue_event_on_commit: mock.Mock self, mock_queue_event_on_commit: mock.Mock
) -> None: ) -> None:
self.second_bot_profile.bot_type = self.bot_profile.bot_type self.second_bot_profile.bot_type = self.bot_profile.bot_type
@ -591,15 +591,15 @@ class TestServiceBotEventTriggers(ZulipTestCase):
mock_queue_event_on_commit.side_effect = check_values_passed mock_queue_event_on_commit.side_effect = check_values_passed
self.send_huddle_message(sender, recipients, "test") self.send_group_direct_message(sender, recipients, "test")
self.assertEqual(mock_queue_event_on_commit.call_count, 2) self.assertEqual(mock_queue_event_on_commit.call_count, 2)
@for_all_bot_types @for_all_bot_types
@patch_queue_publish("zerver.actions.message_send.queue_event_on_commit") @patch_queue_publish("zerver.actions.message_send.queue_event_on_commit")
def test_no_trigger_on_huddle_message_from_bot( def test_no_trigger_on_group_direct_message_from_bot(
self, mock_queue_event_on_commit: mock.Mock self, mock_queue_event_on_commit: mock.Mock
) -> None: ) -> None:
sender = self.second_bot_profile sender = self.second_bot_profile
recipients = [self.user_profile, self.bot_profile] recipients = [self.user_profile, self.bot_profile]
self.send_huddle_message(sender, recipients) self.send_group_direct_message(sender, recipients)
self.assertFalse(mock_queue_event_on_commit.called) self.assertFalse(mock_queue_event_on_commit.called)

View File

@ -78,7 +78,7 @@ from zerver.models import (
UserProfile, UserProfile,
) )
from zerver.models.realms import get_realm from zerver.models.realms import get_realm
from zerver.models.recipients import get_huddle_user_ids from zerver.models.recipients import get_direct_message_group_user_ids
from zerver.models.streams import get_stream from zerver.models.streams import get_stream
from zerver.models.users import get_system_bot, get_user, get_user_by_delivery_email from zerver.models.users import get_system_bot, get_user, get_user_by_delivery_email
from zerver.views.auth import redirect_and_log_into_subdomain, start_two_factor_auth from zerver.views.auth import redirect_and_log_into_subdomain, start_two_factor_auth
@ -2899,7 +2899,7 @@ class UserSignUpTest(ZulipTestCase):
last_message.content, last_message.content,
) )
self.assertEqual( self.assertEqual(
set(get_huddle_user_ids(last_message.recipient)), set(get_direct_message_group_user_ids(last_message.recipient)),
expected_group_direct_message_user_ids, expected_group_direct_message_user_ids,
) )

View File

@ -314,7 +314,7 @@ class SlackImporter(ZulipTestCase):
[ # Private channels ("groups") [ # Private channels ("groups")
{"name": "private", "members": ["U061A1R2R", "U11111111"]}, {"name": "private", "members": ["U061A1R2R", "U11111111"]},
], ],
[ # Huddles ("mpims") [ # Direct message groups ("mpims")
{ {
"name": "mpdm-foo--bar--baz-1", "name": "mpdm-foo--bar--baz-1",
"members": ["U061A1R2R", "U061A5N1G", "U22222222"], "members": ["U061A1R2R", "U061A5N1G", "U22222222"],

View File

@ -58,7 +58,7 @@ class UserSoftDeactivationTests(ZulipTestCase):
# We are sending this message to ensure that users have at least # We are sending this message to ensure that users have at least
# one UserMessage row. # one UserMessage row.
self.send_huddle_message(users[0], users) self.send_group_direct_message(users[0], users)
with self.assertLogs(logger_string, level="INFO") as m: with self.assertLogs(logger_string, level="INFO") as m:
do_soft_deactivate_users(users) do_soft_deactivate_users(users)
@ -112,7 +112,7 @@ class UserSoftDeactivationTests(ZulipTestCase):
self.example_user("iago"), self.example_user("iago"),
self.example_user("cordelia"), self.example_user("cordelia"),
] ]
self.send_huddle_message(users[0], users) self.send_group_direct_message(users[0], users)
with self.assertLogs(logger_string, level="INFO") as m: with self.assertLogs(logger_string, level="INFO") as m:
do_soft_deactivate_users(users) do_soft_deactivate_users(users)

View File

@ -179,7 +179,7 @@ class TutorialTests(ZulipTestCase):
bot = get_system_bot(settings.WELCOME_BOT, user1.realm_id) bot = get_system_bot(settings.WELCOME_BOT, user1.realm_id)
content = "whatever" content = "whatever"
self.login_user(user1) self.login_user(user1)
self.send_huddle_message(user1, [bot, user2], content) self.send_group_direct_message(user1, [bot, user2], content)
user1_messages = message_stream_count(user1) user1_messages = message_stream_count(user1)
self.assertEqual(most_recent_message(user1).content, content) self.assertEqual(most_recent_message(user1).content, content)
# Welcome bot should still respond to initial direct message # Welcome bot should still respond to initial direct message

View File

@ -2,7 +2,7 @@ import orjson
from zerver.lib.test_classes import ZulipTestCase from zerver.lib.test_classes import ZulipTestCase
from zerver.models import Huddle from zerver.models import Huddle
from zerver.models.recipients import get_huddle_hash from zerver.models.recipients import get_direct_message_group_hash
class TypingValidateOperatorTest(ZulipTestCase): class TypingValidateOperatorTest(ZulipTestCase):
@ -202,8 +202,8 @@ class TypingHappyPathTestDirectMessages(ZulipTestCase):
expected_recipient_emails = {user.email for user in expected_recipients} expected_recipient_emails = {user.email for user in expected_recipients}
expected_recipient_ids = {user.id for user in expected_recipients} expected_recipient_ids = {user.id for user in expected_recipients}
huddle_hash = get_huddle_hash(list(expected_recipient_ids)) direct_message_group_hash = get_direct_message_group_hash(list(expected_recipient_ids))
self.assertFalse(Huddle.objects.filter(huddle_hash=huddle_hash).exists()) self.assertFalse(Huddle.objects.filter(huddle_hash=direct_message_group_hash).exists())
params = dict( params = dict(
to=orjson.dumps([user.id for user in recipient_users]).decode(), to=orjson.dumps([user.id for user in recipient_users]).decode(),
@ -216,10 +216,10 @@ class TypingHappyPathTestDirectMessages(ZulipTestCase):
self.assert_json_success(result) self.assert_json_success(result)
self.assert_length(events, 1) self.assert_length(events, 1)
# We should not be adding new Huddles just because # We should not be adding new Direct Message groups
# a user started typing in the compose box. Let's # just because a user started typing in the compose
# wait till they send an actual message. # box. Let's wait till they send an actual message.
self.assertFalse(Huddle.objects.filter(huddle_hash=huddle_hash).exists()) self.assertFalse(Huddle.objects.filter(huddle_hash=direct_message_group_hash).exists())
event = events[0]["event"] event = events[0]["event"]
event_recipient_emails = {user["email"] for user in event["recipients"]} event_recipient_emails = {user["email"] for user in event["recipients"]}

View File

@ -2782,19 +2782,19 @@ class DeleteUserTest(ZulipTestCase):
self.assertGreater(len(personal_message_ids_to_hamlet), 0) self.assertGreater(len(personal_message_ids_to_hamlet), 0)
self.assertTrue(Message.objects.filter(realm_id=realm.id, sender=hamlet).exists()) self.assertTrue(Message.objects.filter(realm_id=realm.id, sender=hamlet).exists())
huddle_message_ids_from_cordelia = [ group_direct_message_ids_from_cordelia = [
self.send_huddle_message(cordelia, [hamlet, othello]) for i in range(3) self.send_group_direct_message(cordelia, [hamlet, othello]) for i in range(3)
] ]
huddle_message_ids_from_hamlet = [ group_direct_message_ids_from_hamlet = [
self.send_huddle_message(hamlet, [cordelia, othello]) for i in range(3) self.send_group_direct_message(hamlet, [cordelia, othello]) for i in range(3)
] ]
huddle_with_hamlet_recipient_ids = list( direct_message_group_with_hamlet_recipient_ids = list(
Subscription.objects.filter( Subscription.objects.filter(
user_profile=hamlet, recipient__type=Recipient.DIRECT_MESSAGE_GROUP user_profile=hamlet, recipient__type=Recipient.DIRECT_MESSAGE_GROUP
).values_list("recipient_id", flat=True) ).values_list("recipient_id", flat=True)
) )
self.assertGreater(len(huddle_with_hamlet_recipient_ids), 0) self.assertGreater(len(direct_message_group_with_hamlet_recipient_ids), 0)
do_delete_user(hamlet, acting_user=None) do_delete_user(hamlet, acting_user=None)
@ -2808,18 +2808,22 @@ class DeleteUserTest(ZulipTestCase):
self.assertEqual(replacement_dummy_user.date_joined, hamlet_date_joined) self.assertEqual(replacement_dummy_user.date_joined, hamlet_date_joined)
self.assertEqual(Message.objects.filter(id__in=personal_message_ids_to_hamlet).count(), 0) self.assertEqual(Message.objects.filter(id__in=personal_message_ids_to_hamlet).count(), 0)
# Huddle messages from hamlet should have been deleted, but messages of other participants should # Group direct messages from hamlet should have been deleted, but messages of other
# be kept. # participants should be kept.
self.assertEqual(Message.objects.filter(id__in=huddle_message_ids_from_hamlet).count(), 0) self.assertEqual(
self.assertEqual(Message.objects.filter(id__in=huddle_message_ids_from_cordelia).count(), 3) Message.objects.filter(id__in=group_direct_message_ids_from_hamlet).count(), 0
)
self.assertEqual(
Message.objects.filter(id__in=group_direct_message_ids_from_cordelia).count(), 3
)
self.assertEqual( self.assertEqual(
Message.objects.filter(realm_id=realm.id, sender_id=hamlet_user_id).count(), 0 Message.objects.filter(realm_id=realm.id, sender_id=hamlet_user_id).count(), 0
) )
# Verify that the dummy user is subscribed to the deleted user's huddles, to keep huddle data # Verify that the dummy user is subscribed to the deleted user's direct message groups,
# in a correct state. # to keep direct message group's data in a correct state.
for recipient_id in huddle_with_hamlet_recipient_ids: for recipient_id in direct_message_group_with_hamlet_recipient_ids:
self.assertTrue( self.assertTrue(
Subscription.objects.filter( Subscription.objects.filter(
user_profile=replacement_dummy_user, recipient_id=recipient_id user_profile=replacement_dummy_user, recipient_id=recipient_id
@ -2849,19 +2853,19 @@ class DeleteUserTest(ZulipTestCase):
self.assertGreater(len(personal_message_ids_to_hamlet), 0) self.assertGreater(len(personal_message_ids_to_hamlet), 0)
self.assertTrue(Message.objects.filter(realm_id=realm.id, sender=hamlet).exists()) self.assertTrue(Message.objects.filter(realm_id=realm.id, sender=hamlet).exists())
huddle_message_ids_from_cordelia = [ group_direct_message_ids_from_cordelia = [
self.send_huddle_message(cordelia, [hamlet, othello]) for i in range(3) self.send_group_direct_message(cordelia, [hamlet, othello]) for i in range(3)
] ]
huddle_message_ids_from_hamlet = [ group_direct_message_ids_from_hamlet = [
self.send_huddle_message(hamlet, [cordelia, othello]) for i in range(3) self.send_group_direct_message(hamlet, [cordelia, othello]) for i in range(3)
] ]
huddle_with_hamlet_recipient_ids = list( direct_message_group_with_hamlet_recipient_ids = list(
Subscription.objects.filter( Subscription.objects.filter(
user_profile=hamlet, recipient__type=Recipient.DIRECT_MESSAGE_GROUP user_profile=hamlet, recipient__type=Recipient.DIRECT_MESSAGE_GROUP
).values_list("recipient_id", flat=True) ).values_list("recipient_id", flat=True)
) )
self.assertGreater(len(huddle_with_hamlet_recipient_ids), 0) self.assertGreater(len(direct_message_group_with_hamlet_recipient_ids), 0)
original_messages_from_hamlet_count = Message.objects.filter( original_messages_from_hamlet_count = Message.objects.filter(
realm_id=realm.id, sender_id=hamlet_user_id realm_id=realm.id, sender_id=hamlet_user_id
@ -2885,12 +2889,12 @@ class DeleteUserTest(ZulipTestCase):
len(personal_message_ids_to_hamlet), len(personal_message_ids_to_hamlet),
) )
self.assertEqual( self.assertEqual(
Message.objects.filter(id__in=huddle_message_ids_from_hamlet).count(), Message.objects.filter(id__in=group_direct_message_ids_from_hamlet).count(),
len(huddle_message_ids_from_hamlet), len(group_direct_message_ids_from_hamlet),
) )
self.assertEqual( self.assertEqual(
Message.objects.filter(id__in=huddle_message_ids_from_cordelia).count(), Message.objects.filter(id__in=group_direct_message_ids_from_cordelia).count(),
len(huddle_message_ids_from_cordelia), len(group_direct_message_ids_from_cordelia),
) )
self.assertEqual( self.assertEqual(
@ -2898,9 +2902,9 @@ class DeleteUserTest(ZulipTestCase):
original_messages_from_hamlet_count, original_messages_from_hamlet_count,
) )
# Verify that the dummy user is subscribed to the deleted user's huddles, to keep huddle data # Verify that the dummy user is subscribed to the deleted user's direct message groups,
# in a correct state. # to keep direct message group's data in a correct state.
for recipient_id in huddle_with_hamlet_recipient_ids: for recipient_id in direct_message_group_with_hamlet_recipient_ids:
self.assertTrue( self.assertTrue(
Subscription.objects.filter( Subscription.objects.filter(
user_profile=replacement_dummy_user, recipient_id=recipient_id user_profile=replacement_dummy_user, recipient_id=recipient_id

View File

@ -19,7 +19,7 @@ from zerver.lib.zulip_update_announcements import (
) )
from zerver.models.messages import Message from zerver.models.messages import Message
from zerver.models.realms import get_realm from zerver.models.realms import get_realm
from zerver.models.recipients import Recipient, get_huddle_user_ids from zerver.models.recipients import Recipient, get_direct_message_group_user_ids
from zerver.models.streams import get_stream from zerver.models.streams import get_stream
from zerver.models.users import get_system_bot from zerver.models.users import get_system_bot
@ -77,7 +77,7 @@ class ZulipUpdateAnnouncementsTest(ZulipTestCase):
self.assertEqual(group_direct_message.sender, notification_bot) self.assertEqual(group_direct_message.sender, notification_bot)
self.assertEqual(group_direct_message.date_sent, now) self.assertEqual(group_direct_message.date_sent, now)
self.assertEqual( self.assertEqual(
set(get_huddle_user_ids(group_direct_message.recipient)), set(get_direct_message_group_user_ids(group_direct_message.recipient)),
expected_group_direct_message_user_ids, expected_group_direct_message_user_ids,
) )
self.assertEqual(realm.zulip_update_announcements_level, 0) self.assertEqual(realm.zulip_update_announcements_level, 0)
@ -270,7 +270,7 @@ class ZulipUpdateAnnouncementsTest(ZulipTestCase):
self.assertEqual(group_direct_message.sender, notification_bot) self.assertEqual(group_direct_message.sender, notification_bot)
self.assertEqual(group_direct_message.date_sent, now) self.assertEqual(group_direct_message.date_sent, now)
self.assertEqual( self.assertEqual(
set(get_huddle_user_ids(group_direct_message.recipient)), set(get_direct_message_group_user_ids(group_direct_message.recipient)),
expected_group_direct_message_user_ids, expected_group_direct_message_user_ids,
) )
self.assertEqual(realm.zulip_update_announcements_level, 0) self.assertEqual(realm.zulip_update_announcements_level, 0)

View File

@ -70,7 +70,7 @@ from zerver.models import (
from zerver.models.alert_words import flush_alert_word from zerver.models.alert_words import flush_alert_word
from zerver.models.clients import get_client from zerver.models.clients import get_client
from zerver.models.realms import WildcardMentionPolicyEnum, get_realm from zerver.models.realms import WildcardMentionPolicyEnum, get_realm
from zerver.models.recipients import get_or_create_huddle from zerver.models.recipients import get_or_create_direct_message_group
from zerver.models.streams import get_stream from zerver.models.streams import get_stream
from zerver.models.users import get_user, get_user_by_delivery_email, get_user_profile_by_id from zerver.models.users import get_user, get_user_by_delivery_email, get_user_profile_by_id
from zilencer.models import RemoteRealm, RemoteZulipServer, RemoteZulipServerAuditLog from zilencer.models import RemoteRealm, RemoteZulipServer, RemoteZulipServerAuditLog
@ -929,7 +929,9 @@ class Command(ZulipBaseCommand):
# Create several initial huddles # Create several initial huddles
for i in range(options["num_huddles"]): for i in range(options["num_huddles"]):
get_or_create_huddle(random.sample(user_profiles_ids, random.randint(3, 4))) get_or_create_direct_message_group(
random.sample(user_profiles_ids, random.randint(3, 4))
)
# Create several initial pairs for personals # Create several initial pairs for personals
personals_pairs = [ personals_pairs = [