mirror of https://github.com/zulip/zulip.git
76 lines
3.2 KiB
Python
76 lines
3.2 KiB
Python
|
from django.http.request import HttpRequest
|
||
|
from django.http.response import HttpResponse
|
||
|
from django.utils.translation import gettext as _
|
||
|
|
||
|
from zerver.lib.exceptions import JsonableError
|
||
|
from zerver.lib.message import access_message
|
||
|
from zerver.lib.request import REQ, has_request_variables
|
||
|
from zerver.lib.response import json_success
|
||
|
from zerver.lib.validator import to_non_negative_int
|
||
|
from zerver.models import UserMessage, UserProfile
|
||
|
|
||
|
|
||
|
@has_request_variables
|
||
|
def read_receipts(
|
||
|
request: HttpRequest,
|
||
|
user_profile: UserProfile,
|
||
|
message_id: int = REQ(converter=to_non_negative_int, path_only=True),
|
||
|
) -> HttpResponse:
|
||
|
message = access_message(user_profile, message_id)[0]
|
||
|
|
||
|
if not user_profile.realm.enable_read_receipts:
|
||
|
raise JsonableError(_("Read receipts are disabled in this organization."))
|
||
|
|
||
|
# This query implements a few decisions:
|
||
|
# * Most importantly, this is where we enforce the
|
||
|
# send_read_receipts privacy setting.
|
||
|
#
|
||
|
# * The message sender is never included, since presumably they
|
||
|
# read the message before sending it, and showing the sender as
|
||
|
# having read their own message is likely to be confusing.
|
||
|
#
|
||
|
# * Deactivated users are excluded. While in theory someone
|
||
|
# could be interested in the information, not including them
|
||
|
# is a cleaner policy, and usually read receipts are only of
|
||
|
# interest shortly after a message was sent.
|
||
|
#
|
||
|
# * We do not filter on the historical flag. This means that a user
|
||
|
# who stars a public stream message that they did not originally
|
||
|
# receive will appear in read receipts for that message.
|
||
|
#
|
||
|
# * Marking a message as unread causes it to appear as not read
|
||
|
# via read receipts, as well. This is consistent with the fact
|
||
|
# that users can view a message without leaving it marked as
|
||
|
# read in other ways (desktop/email/push notifications).
|
||
|
#
|
||
|
# * Bots are included. Most bots never mark any messages as read,
|
||
|
# but one could imagine having them to do so via the API to
|
||
|
# communicate useful information. For example, the `read` flag
|
||
|
# could be used by a bot to track which messages have been
|
||
|
# bridged to another chat system or otherwise processed
|
||
|
# successfully by the bot, and users might find it useful to be
|
||
|
# able to inspect that in the UI. If this behavior is not
|
||
|
# desired for a bot, it can be disabled using the
|
||
|
# send_read_receipts privacy setting.
|
||
|
#
|
||
|
# Note that we do not attempt to present how many users received a
|
||
|
# message but have NOT marked the message as read. There are
|
||
|
# tricky corner cases involved in doing so, such as the
|
||
|
# `historical` flag for public stream messages; but the most
|
||
|
# important one is how to handle users who read a message and then
|
||
|
# later unsubscribed from a stream.
|
||
|
user_ids = (
|
||
|
UserMessage.objects.filter(
|
||
|
message_id=message.id,
|
||
|
user_profile__is_active=True,
|
||
|
user_profile__send_read_receipts=True,
|
||
|
)
|
||
|
.exclude(user_profile_id=message.sender_id)
|
||
|
.extra(
|
||
|
where=[UserMessage.where_read()],
|
||
|
)
|
||
|
.values_list("user_profile_id", flat=True)
|
||
|
)
|
||
|
|
||
|
return json_success(request, {"user_ids": list(user_ids)})
|