2022-04-14 23:31:40 +02:00
|
|
|
from django.utils.translation import gettext as _
|
|
|
|
|
2023-06-17 17:37:04 +02:00
|
|
|
from zerver.actions.user_topics import do_set_user_topic_visibility_policy
|
2022-04-14 23:31:40 +02:00
|
|
|
from zerver.lib.exceptions import JsonableError
|
2023-06-17 17:37:04 +02:00
|
|
|
from zerver.lib.message import (
|
|
|
|
set_visibility_policy_possible,
|
|
|
|
should_change_visibility_policy,
|
|
|
|
visibility_policy_for_participation,
|
|
|
|
)
|
|
|
|
from zerver.lib.streams import access_stream_by_id
|
|
|
|
from zerver.models import Realm, SubMessage, UserMessage, UserProfile
|
django_api: Extract send_event_on_commit helper.
django-stubs 4.2.1 gives transaction.on_commit a more accurate type
annotation, but this exposed that mypy can’t handle the lambda default
parameters that we use to recapture loop variables such as
for stream_id in public_stream_ids:
peer_user_ids = …
event = …
transaction.on_commit(
lambda event=event, peer_user_ids=peer_user_ids: send_event(
realm, event, peer_user_ids
)
)
https://github.com/python/mypy/issues/15459
A workaround that mypy accepts is
transaction.on_commit(
(
lambda event, peer_user_ids: lambda: send_event(
realm, event, peer_user_ids
)
)(event, peer_user_ids)
)
But that’s kind of ugly and potentially error-prone, so let’s make a
helper function for this very common pattern.
send_event_on_commit(realm, event, peer_user_ids)
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2023-06-17 20:53:07 +02:00
|
|
|
from zerver.tornado.django_api import send_event_on_commit
|
2022-04-14 23:31:40 +02:00
|
|
|
|
|
|
|
|
|
|
|
def verify_submessage_sender(
|
|
|
|
*,
|
|
|
|
message_id: int,
|
|
|
|
message_sender_id: int,
|
|
|
|
submessage_sender_id: int,
|
|
|
|
) -> None:
|
|
|
|
"""Even though our submessage architecture is geared toward
|
|
|
|
collaboration among all message readers, we still enforce
|
2024-05-20 22:16:21 +02:00
|
|
|
the first person to attach a submessage to the message
|
2022-04-14 23:31:40 +02:00
|
|
|
must be the original sender of the message.
|
|
|
|
"""
|
|
|
|
|
|
|
|
if message_sender_id == submessage_sender_id:
|
|
|
|
return
|
|
|
|
|
|
|
|
if SubMessage.objects.filter(
|
|
|
|
message_id=message_id,
|
|
|
|
sender_id=message_sender_id,
|
|
|
|
).exists():
|
|
|
|
return
|
|
|
|
|
|
|
|
raise JsonableError(_("You cannot attach a submessage to this message."))
|
|
|
|
|
|
|
|
|
|
|
|
def do_add_submessage(
|
|
|
|
realm: Realm,
|
|
|
|
sender_id: int,
|
|
|
|
message_id: int,
|
|
|
|
msg_type: str,
|
|
|
|
content: str,
|
|
|
|
) -> None:
|
|
|
|
"""Should be called while holding a SELECT FOR UPDATE lock
|
|
|
|
(e.g. via access_message(..., lock_message=True)) on the
|
|
|
|
Message row, to prevent race conditions.
|
|
|
|
"""
|
|
|
|
submessage = SubMessage(
|
|
|
|
sender_id=sender_id,
|
|
|
|
message_id=message_id,
|
|
|
|
msg_type=msg_type,
|
|
|
|
content=content,
|
|
|
|
)
|
|
|
|
submessage.save()
|
|
|
|
|
2023-06-17 17:37:04 +02:00
|
|
|
# Determine and set the visibility_policy depending on 'automatically_follow_topics_policy'
|
|
|
|
# and 'automatically_unmute_topics_policy'.
|
|
|
|
sender = submessage.sender
|
|
|
|
if set_visibility_policy_possible(
|
|
|
|
sender, submessage.message
|
|
|
|
) and UserProfile.AUTOMATICALLY_CHANGE_VISIBILITY_POLICY_ON_PARTICIPATION in [
|
|
|
|
sender.automatically_follow_topics_policy,
|
|
|
|
sender.automatically_unmute_topics_in_muted_streams_policy,
|
|
|
|
]:
|
|
|
|
stream_id = submessage.message.recipient.type_id
|
|
|
|
(stream, sub) = access_stream_by_id(sender, stream_id)
|
|
|
|
assert stream is not None
|
|
|
|
if sub:
|
|
|
|
new_visibility_policy = visibility_policy_for_participation(sender, sub.is_muted)
|
|
|
|
if new_visibility_policy and should_change_visibility_policy(
|
|
|
|
new_visibility_policy,
|
|
|
|
sender,
|
|
|
|
stream_id,
|
|
|
|
topic_name=submessage.message.topic_name(),
|
|
|
|
):
|
|
|
|
do_set_user_topic_visibility_policy(
|
|
|
|
user_profile=sender,
|
|
|
|
stream=stream,
|
2024-01-13 09:55:16 +01:00
|
|
|
topic_name=submessage.message.topic_name(),
|
2023-06-17 17:37:04 +02:00
|
|
|
visibility_policy=new_visibility_policy,
|
|
|
|
)
|
|
|
|
|
2022-04-14 23:31:40 +02:00
|
|
|
event = dict(
|
|
|
|
type="submessage",
|
|
|
|
msg_type=msg_type,
|
|
|
|
message_id=message_id,
|
|
|
|
submessage_id=submessage.id,
|
|
|
|
sender_id=sender_id,
|
|
|
|
content=content,
|
|
|
|
)
|
|
|
|
ums = UserMessage.objects.filter(message_id=message_id)
|
|
|
|
target_user_ids = [um.user_profile_id for um in ums]
|
|
|
|
|
django_api: Extract send_event_on_commit helper.
django-stubs 4.2.1 gives transaction.on_commit a more accurate type
annotation, but this exposed that mypy can’t handle the lambda default
parameters that we use to recapture loop variables such as
for stream_id in public_stream_ids:
peer_user_ids = …
event = …
transaction.on_commit(
lambda event=event, peer_user_ids=peer_user_ids: send_event(
realm, event, peer_user_ids
)
)
https://github.com/python/mypy/issues/15459
A workaround that mypy accepts is
transaction.on_commit(
(
lambda event, peer_user_ids: lambda: send_event(
realm, event, peer_user_ids
)
)(event, peer_user_ids)
)
But that’s kind of ugly and potentially error-prone, so let’s make a
helper function for this very common pattern.
send_event_on_commit(realm, event, peer_user_ids)
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2023-06-17 20:53:07 +02:00
|
|
|
send_event_on_commit(realm, event, target_user_ids)
|