mirror of
https://github.com/zulip/zulip.git
synced 2025-10-23 04:52:12 +00:00
api: Rename edit typing endpoint to /messages/{message_id}/typing
.
This is more consistent with how other URLs work in Zulip. Replaces `/message_edit_typing` with `/messages/{message_id}/typing`. The `message_id` parameter, previously passed in the request body, is now included in the URL path.
This commit is contained in:
@@ -20,6 +20,13 @@ format used by the Zulip server that they are interacting with.
|
||||
|
||||
## Changes in Zulip 10.0
|
||||
|
||||
**Feature level 361**
|
||||
|
||||
* [`POST /messages/{message_id}/typing`](/api/set-typing-status-for-message-edit):
|
||||
Renamed `POST /messages/{message_id}/typing` to
|
||||
`POST /message_edit_typing`, passing the one `message_id` parameter
|
||||
in the URL path, for consistency with the rest of the API.
|
||||
|
||||
**Feature level 360**
|
||||
|
||||
* [`GET /messages/{message_id}`](/api/get-message), [`GET
|
||||
|
@@ -34,7 +34,7 @@ DESKTOP_WARNING_VERSION = "5.9.3"
|
||||
# new level means in api_docs/changelog.md, as well as "**Changes**"
|
||||
# entries in the endpoint's documentation in `zulip.yaml`.
|
||||
|
||||
API_FEATURE_LEVEL = 360 # Last bumped for allowing access to archived channel messages on read.
|
||||
API_FEATURE_LEVEL = 361
|
||||
|
||||
# Bump the minor PROVISION_VERSION to indicate that folks should provision
|
||||
# only when going from an old version of the code to a newer version. Bump
|
||||
|
@@ -51,11 +51,10 @@ function send_message_edit_typing_notification_ajax(
|
||||
operation: "start" | "stop",
|
||||
): void {
|
||||
const data = {
|
||||
message_id: JSON.stringify(message_id),
|
||||
op: operation,
|
||||
};
|
||||
void channel.post({
|
||||
url: "/json/message_edit_typing",
|
||||
url: `/json/messages/${message_id}/typing`,
|
||||
data,
|
||||
error(xhr) {
|
||||
if (xhr.readyState !== 0) {
|
||||
|
@@ -1608,43 +1608,35 @@ def set_typing_status(client: Client) -> None:
|
||||
validate_against_openapi_schema(result, "/typing", "post", "200")
|
||||
|
||||
|
||||
@openapi_test_function("/message_edit_typing:post")
|
||||
def set_message_edit_typing_status(client: Client) -> None:
|
||||
message = {"type": "stream", "to": "Verona", "topic": "test_topic", "content": "test content"}
|
||||
response = client.send_message(message)
|
||||
message_id = response["id"]
|
||||
@openapi_test_function("/messages/{message_id}/typing:post")
|
||||
def set_message_edit_typing_status(client: Client, message_id: int) -> None:
|
||||
# {code_example|start}
|
||||
# The user has started typing while editing a message
|
||||
# The user has started typing while editing a message.
|
||||
request = {
|
||||
"op": "start",
|
||||
"message_id": message_id,
|
||||
}
|
||||
result = client.call_endpoint(
|
||||
"message_edit_typing",
|
||||
f"/messages/{message_id}/typing",
|
||||
method="POST",
|
||||
request=request,
|
||||
)
|
||||
# {code_example|end}
|
||||
assert_success_response(result)
|
||||
validate_against_openapi_schema(result, "/message_edit_typing", "post", "200")
|
||||
validate_against_openapi_schema(result, f"/messages/{message_id}/typing", "post", "200")
|
||||
|
||||
message = {"type": "stream", "to": "Verona", "topic": "test_topic", "content": "test content"}
|
||||
response = client.send_message(message)
|
||||
message_id = response["id"]
|
||||
# {code_example|start}
|
||||
# The user has stopped typing while editing a message.
|
||||
request = {
|
||||
"op": "stop",
|
||||
"message_id": message_id,
|
||||
}
|
||||
result = client.call_endpoint(
|
||||
"message_edit_typing",
|
||||
f"/messages/{message_id}/typing",
|
||||
method="POST",
|
||||
request=request,
|
||||
)
|
||||
# {code_example|end}
|
||||
assert_success_response(result)
|
||||
validate_against_openapi_schema(result, "/message_edit_typing", "post", "200")
|
||||
validate_against_openapi_schema(result, "/messages/{message_id}/typing", "post", "200")
|
||||
|
||||
|
||||
@openapi_test_function("/realm/emoji/{emoji_name}:post")
|
||||
@@ -1794,7 +1786,7 @@ def test_invalid_stream_error(client: Client) -> None:
|
||||
def test_messages(client: Client, nonadmin_client: Client) -> None:
|
||||
render_message(client)
|
||||
message_id = send_message(client)
|
||||
set_message_edit_typing_status(client)
|
||||
set_message_edit_typing_status(client, message_id)
|
||||
add_reaction(client, message_id)
|
||||
remove_reaction(client, message_id)
|
||||
update_message(client, message_id)
|
||||
|
@@ -21320,7 +21320,7 @@ paths:
|
||||
description: |
|
||||
An example JSON error response when the user composes a channel message
|
||||
and `stream_id` is not specified:
|
||||
/message_edit_typing:
|
||||
/messages/{message_id}/typing:
|
||||
post:
|
||||
operationId: set-typing-status-for-message-edit
|
||||
summary: Set "typing" status for message editing
|
||||
@@ -21329,10 +21329,25 @@ paths:
|
||||
Notify other users whether the current user is editing a message.
|
||||
|
||||
Typing notifications for editing messages follow the same protocol as
|
||||
[set-typing-status](/api/set-typing-status), see that endpoint for details.
|
||||
[set-typing-status](/api/set-typing-status), see that endpoint for
|
||||
details.
|
||||
|
||||
**Changes**: New in Zulip 10.0 (feature level 351). Previously,
|
||||
typing notifications were not available when editing messages.
|
||||
**Changes**: Before Zulip 10.0 (feature level 361), the endpoint was
|
||||
named `/message_edit_typing` with `message_id` a required parameter in
|
||||
the request body. Clients are recommended to start using sending these
|
||||
typing notifications starting from this feature level.
|
||||
|
||||
New in Zulip 10.0 (feature level 351). Previously, typing notifications were
|
||||
not available when editing messages.
|
||||
parameters:
|
||||
- name: message_id
|
||||
in: path
|
||||
description: |
|
||||
The target message's ID.
|
||||
schema:
|
||||
type: integer
|
||||
example: 47
|
||||
required: true
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
@@ -21348,14 +21363,8 @@ paths:
|
||||
- start
|
||||
- stop
|
||||
example: start
|
||||
message_id:
|
||||
description: |
|
||||
Describes the message id of the message being edited.
|
||||
type: integer
|
||||
example: 47
|
||||
required:
|
||||
- op
|
||||
- message_id
|
||||
responses:
|
||||
"200":
|
||||
$ref: "#/components/responses/SimpleSuccess"
|
||||
|
@@ -41,12 +41,13 @@ class TypingValidateOperatorTest(ZulipTestCase):
|
||||
|
||||
def test_invalid_parameter_message_edit(self) -> None:
|
||||
sender = self.example_user("hamlet")
|
||||
|
||||
msg_id = self.send_stream_message(
|
||||
sender, "Denmark", topic_name="editing", content="before edit"
|
||||
)
|
||||
params = dict(
|
||||
op="foo",
|
||||
message_id=7,
|
||||
)
|
||||
result = self.api_post(sender, "/api/v1/message_edit_typing", params)
|
||||
result = self.api_post(sender, f"/api/v1/messages/{msg_id}/typing", params)
|
||||
self.assert_json_error(result, "Invalid op")
|
||||
|
||||
|
||||
@@ -112,10 +113,9 @@ class TypingValidateToArgumentsTest(ZulipTestCase):
|
||||
)
|
||||
result = self.api_post(
|
||||
sender,
|
||||
"/api/v1/message_edit_typing",
|
||||
f"/api/v1/messages/{msg_id}/typing",
|
||||
{
|
||||
"op": "start",
|
||||
"message_id": str(msg_id),
|
||||
},
|
||||
)
|
||||
self.assert_json_error(result, "You don't have permission to edit this message")
|
||||
@@ -569,7 +569,6 @@ class TypingHappyPathTestStreams(ZulipTestCase):
|
||||
|
||||
params = dict(
|
||||
op="start",
|
||||
message_id=msg_id,
|
||||
)
|
||||
|
||||
with self.settings(MAX_STREAM_SIZE_FOR_TYPING_NOTIFICATIONS=5):
|
||||
@@ -577,7 +576,7 @@ class TypingHappyPathTestStreams(ZulipTestCase):
|
||||
self.assert_database_query_count(5),
|
||||
self.capture_send_event_calls(expected_num_events=0) as events,
|
||||
):
|
||||
result = self.api_post(sender, "/api/v1/message_edit_typing", params)
|
||||
result = self.api_post(sender, f"/api/v1/messages/{msg_id}/typing", params)
|
||||
self.assert_json_success(result)
|
||||
self.assert_length(events, 0)
|
||||
|
||||
@@ -747,13 +746,13 @@ class TestSendTypingNotificationsSettings(ZulipTestCase):
|
||||
)
|
||||
expected_user_ids = self.not_long_term_idle_subscriber_ids(channel_name, sender.realm)
|
||||
|
||||
params = dict(op="start", message_id=msg_id)
|
||||
params = dict(op="start")
|
||||
|
||||
# Test typing events sent when `send_stream_typing_notifications` set to `True`.
|
||||
self.assertTrue(sender.send_stream_typing_notifications)
|
||||
|
||||
with self.capture_send_event_calls(expected_num_events=1) as events:
|
||||
result = self.api_post(sender, "/api/v1/message_edit_typing", params)
|
||||
result = self.api_post(sender, f"/api/v1/messages/{msg_id}/typing", params)
|
||||
self.assert_json_success(result)
|
||||
self.assert_length(events, 1)
|
||||
self.assertEqual(orjson.loads(result.content)["msg"], "")
|
||||
@@ -763,7 +762,7 @@ class TestSendTypingNotificationsSettings(ZulipTestCase):
|
||||
do_deactivate_stream(channel, acting_user=sender)
|
||||
# No events should be sent if stream is deactivated.
|
||||
with self.capture_send_event_calls(expected_num_events=0) as events:
|
||||
result = self.api_post(sender, "/api/v1/message_edit_typing", params)
|
||||
result = self.api_post(sender, f"/api/v1/messages/{msg_id}/typing", params)
|
||||
self.assert_json_error(result, "Invalid message(s)")
|
||||
self.assertEqual(events, [])
|
||||
do_unarchive_stream(channel, channel_name, acting_user=sender)
|
||||
@@ -773,7 +772,7 @@ class TestSendTypingNotificationsSettings(ZulipTestCase):
|
||||
|
||||
# No events should be sent now
|
||||
with self.capture_send_event_calls(expected_num_events=0) as events:
|
||||
result = self.api_post(sender, "/api/v1/message_edit_typing", params)
|
||||
result = self.api_post(sender, f"/api/v1/messages/{msg_id}/typing", params)
|
||||
self.assert_json_error(
|
||||
result, "User has disabled typing notifications for channel messages"
|
||||
)
|
||||
@@ -786,7 +785,7 @@ class TestSendTypingNotificationsSettings(ZulipTestCase):
|
||||
aaron.save()
|
||||
|
||||
with self.capture_send_event_calls(expected_num_events=1) as events:
|
||||
result = self.api_post(sender, "/api/v1/message_edit_typing", params)
|
||||
result = self.api_post(sender, f"/api/v1/messages/{msg_id}/typing", params)
|
||||
self.assert_json_success(result)
|
||||
self.assert_length(events, 1)
|
||||
|
||||
@@ -805,14 +804,13 @@ class TestSendTypingNotificationsSettings(ZulipTestCase):
|
||||
|
||||
params = dict(
|
||||
op="start",
|
||||
message_id=msg_id,
|
||||
)
|
||||
|
||||
# Test typing events sent when `send_private_typing_notifications` set to `True`.
|
||||
self.assertTrue(sender.send_private_typing_notifications)
|
||||
|
||||
with self.capture_send_event_calls(expected_num_events=1) as events:
|
||||
result = self.api_post(sender, "/api/v1/message_edit_typing", params)
|
||||
result = self.api_post(sender, f"/api/v1/messages/{msg_id}/typing", params)
|
||||
|
||||
self.assert_json_success(result)
|
||||
self.assert_length(events, 1)
|
||||
@@ -825,7 +823,7 @@ class TestSendTypingNotificationsSettings(ZulipTestCase):
|
||||
|
||||
# No events should be sent now
|
||||
with self.capture_send_event_calls(expected_num_events=0) as events:
|
||||
result = self.api_post(sender, "/api/v1/message_edit_typing", params)
|
||||
result = self.api_post(sender, f"/api/v1/messages/{msg_id}/typing", params)
|
||||
|
||||
self.assert_json_error(result, "User has disabled typing notifications for direct messages")
|
||||
self.assertEqual(events, [])
|
||||
@@ -837,7 +835,7 @@ class TestSendTypingNotificationsSettings(ZulipTestCase):
|
||||
recipient_user.save()
|
||||
|
||||
with self.capture_send_event_calls(expected_num_events=1) as events:
|
||||
result = self.api_post(sender, "/api/v1/message_edit_typing", params)
|
||||
result = self.api_post(sender, f"/api/v1/messages/{msg_id}/typing", params)
|
||||
self.assert_json_success(result)
|
||||
self.assert_length(events, 1)
|
||||
|
||||
@@ -858,12 +856,11 @@ class TestSendTypingNotificationsSettings(ZulipTestCase):
|
||||
|
||||
params = dict(
|
||||
op="start",
|
||||
message_id=str(msg_id),
|
||||
)
|
||||
# Test typing events sent when `send_private_typing_notifications` set to `True`.
|
||||
self.assertTrue(sender.send_private_typing_notifications)
|
||||
with self.capture_send_event_calls(expected_num_events=1) as events:
|
||||
result = self.api_post(sender, "/api/v1/message_edit_typing", params)
|
||||
result = self.api_post(sender, f"/api/v1/messages/{msg_id}/typing", params)
|
||||
|
||||
self.assert_json_success(result)
|
||||
self.assert_length(events, 1)
|
||||
@@ -876,7 +873,7 @@ class TestSendTypingNotificationsSettings(ZulipTestCase):
|
||||
|
||||
# No events should be sent now
|
||||
with self.capture_send_event_calls(expected_num_events=0) as events:
|
||||
result = self.api_post(sender, "/api/v1/message_edit_typing", params)
|
||||
result = self.api_post(sender, f"/api/v1/messages/{msg_id}/typing", params)
|
||||
|
||||
self.assert_json_error(result, "User has disabled typing notifications for direct messages")
|
||||
self.assertEqual(events, [])
|
||||
@@ -891,7 +888,7 @@ class TestSendTypingNotificationsSettings(ZulipTestCase):
|
||||
expected_recipient_ids = {hamlet.id, cordelia.id}
|
||||
|
||||
with self.capture_send_event_calls(expected_num_events=1) as events:
|
||||
result = self.api_post(sender, "/api/v1/message_edit_typing", params)
|
||||
result = self.api_post(sender, f"/api/v1/messages/{msg_id}/typing", params)
|
||||
self.assert_json_success(result)
|
||||
self.assert_length(events, 1)
|
||||
event_user_ids = set(events[0]["users"])
|
||||
|
@@ -2,7 +2,7 @@ from typing import Annotated, Literal
|
||||
|
||||
from django.http import HttpRequest, HttpResponse
|
||||
from django.utils.translation import gettext as _
|
||||
from pydantic import Json
|
||||
from pydantic import Json, NonNegativeInt
|
||||
|
||||
from zerver.actions.message_edit import validate_user_can_edit_message
|
||||
from zerver.actions.typing import (
|
||||
@@ -16,7 +16,7 @@ from zerver.lib.message import access_message
|
||||
from zerver.lib.response import json_success
|
||||
from zerver.lib.streams import access_stream_by_id_for_message, access_stream_for_send_message
|
||||
from zerver.lib.topic import maybe_rename_general_chat_to_empty_topic
|
||||
from zerver.lib.typed_endpoint import ApiParamConfig, OptionalTopic, typed_endpoint
|
||||
from zerver.lib.typed_endpoint import ApiParamConfig, OptionalTopic, PathOnly, typed_endpoint
|
||||
from zerver.models import Recipient, UserProfile
|
||||
from zerver.models.recipients import get_direct_message_group_user_ids
|
||||
|
||||
@@ -77,8 +77,8 @@ def send_message_edit_notification_backend(
|
||||
request: HttpRequest,
|
||||
user_profile: UserProfile,
|
||||
*,
|
||||
message_id: PathOnly[NonNegativeInt],
|
||||
operator: Annotated[Literal["start", "stop"], ApiParamConfig("op")],
|
||||
message_id: Json[int],
|
||||
) -> HttpResponse:
|
||||
# Technically, this endpoint doesn't modify the message, but we're
|
||||
# attempting to send a typing notification that we're editing the
|
||||
|
@@ -399,7 +399,7 @@ v1_api_and_json_patterns = [
|
||||
# POST sends a typing notification event to recipients
|
||||
rest_path("typing", POST=send_notification_backend),
|
||||
# POST sends a message edit typing notification
|
||||
rest_path("message_edit_typing", POST=send_message_edit_notification_backend),
|
||||
rest_path("messages/<int:message_id>/typing", POST=send_message_edit_notification_backend),
|
||||
# user_uploads -> zerver.views.upload
|
||||
rest_path("user_uploads", POST=upload_file_backend),
|
||||
rest_path(
|
||||
|
Reference in New Issue
Block a user