mirror of https://github.com/zulip/zulip.git
message_fetch: Add include_anchor parameter.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
This commit is contained in:
parent
dae4633745
commit
ee2cb855f0
|
@ -20,6 +20,12 @@ format used by the Zulip server that they are interacting with.
|
|||
|
||||
## Changes in Zulip 6.0
|
||||
|
||||
**Feature level 155**
|
||||
|
||||
* [`GET /messages`](/api/get-messages): The new `include_anchor`
|
||||
parameter controls whether a message with ID matching the specified
|
||||
`anchor` should be included.
|
||||
|
||||
**Feature level 154**
|
||||
|
||||
* [`POST /streams/{stream_id}/delete_topic`](/api/delete-topic):
|
||||
|
|
|
@ -33,7 +33,7 @@ DESKTOP_WARNING_VERSION = "5.4.3"
|
|||
# Changes should be accompanied by documentation explaining what the
|
||||
# new level means in templates/zerver/api/changelog.md, as well as
|
||||
# "**Changes**" entries in the endpoint's documentation in `zulip.yaml`.
|
||||
API_FEATURE_LEVEL = 154
|
||||
API_FEATURE_LEVEL = 155
|
||||
|
||||
# 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
|
||||
|
|
|
@ -994,6 +994,7 @@ def limit_query_to_range(
|
|||
num_before: int,
|
||||
num_after: int,
|
||||
anchor: int,
|
||||
include_anchor: bool,
|
||||
anchored_to_left: bool,
|
||||
anchored_to_right: bool,
|
||||
id_col: ColumnElement[Integer],
|
||||
|
@ -1010,10 +1011,10 @@ def limit_query_to_range(
|
|||
|
||||
# The semantics of our flags are as follows:
|
||||
#
|
||||
# num_after = number of rows < anchor
|
||||
# num_before = number of rows < anchor
|
||||
# num_after = number of rows > anchor
|
||||
#
|
||||
# But we also want the row where id == anchor (if it exists),
|
||||
# But we may also want the row where id == anchor (if it exists),
|
||||
# and we don't want to union up to 3 queries. So in some cases
|
||||
# we do things like `after_limit = num_after + 1` to grab the
|
||||
# anchor row in the "after" query.
|
||||
|
@ -1026,13 +1027,13 @@ def limit_query_to_range(
|
|||
before_limit = num_before
|
||||
after_limit = num_after + 1
|
||||
elif need_before_query:
|
||||
before_anchor = anchor
|
||||
before_anchor = anchor - (not include_anchor)
|
||||
before_limit = num_before
|
||||
if not anchored_to_right:
|
||||
before_limit += 1
|
||||
before_limit += include_anchor
|
||||
elif need_after_query:
|
||||
after_anchor = max(anchor, first_visible_message_id)
|
||||
after_limit = num_after + 1
|
||||
after_anchor = max(anchor + (not include_anchor), first_visible_message_id)
|
||||
after_limit = num_after + include_anchor
|
||||
|
||||
if need_before_query:
|
||||
before_query = query
|
||||
|
@ -1163,6 +1164,7 @@ def fetch_messages(
|
|||
realm: Realm,
|
||||
is_web_public_query: bool,
|
||||
anchor: Optional[int],
|
||||
include_anchor: bool,
|
||||
num_before: int,
|
||||
num_after: int,
|
||||
) -> FetchedMessages:
|
||||
|
@ -1228,6 +1230,7 @@ def fetch_messages(
|
|||
num_before=num_before,
|
||||
num_after=num_after,
|
||||
anchor=anchor,
|
||||
include_anchor=include_anchor,
|
||||
anchored_to_left=anchored_to_left,
|
||||
anchored_to_right=anchored_to_right,
|
||||
id_col=inner_msg_id_col,
|
||||
|
|
|
@ -1044,12 +1044,14 @@ Output:
|
|||
num_before: int = 100,
|
||||
num_after: int = 100,
|
||||
use_first_unread_anchor: bool = False,
|
||||
include_anchor: bool = True,
|
||||
) -> Dict[str, List[Dict[str, Any]]]:
|
||||
post_params = {
|
||||
"anchor": anchor,
|
||||
"num_before": num_before,
|
||||
"num_after": num_after,
|
||||
"use_first_unread_anchor": orjson.dumps(use_first_unread_anchor).decode(),
|
||||
"include_anchor": orjson.dumps(include_anchor).decode(),
|
||||
}
|
||||
result = self.client_get("/json/messages", dict(post_params))
|
||||
data = result.json()
|
||||
|
|
|
@ -5057,6 +5057,7 @@ paths:
|
|||
- client_gravatar
|
||||
- apply_markdown
|
||||
- use_first_unread_anchor
|
||||
- include_anchor
|
||||
parameters:
|
||||
- name: anchor
|
||||
in: query
|
||||
|
@ -5086,6 +5087,17 @@ paths:
|
|||
- type: string
|
||||
- type: integer
|
||||
example: 43
|
||||
- name: include_anchor
|
||||
in: query
|
||||
description: |
|
||||
Whether a message with the specified ID matching the narrow
|
||||
should be included.
|
||||
|
||||
**Changes**: New in Zulip 6.0 (feature level 155).
|
||||
schema:
|
||||
type: boolean
|
||||
default: true
|
||||
example: false
|
||||
- name: num_before
|
||||
in: query
|
||||
description: |
|
||||
|
@ -5220,8 +5232,9 @@ paths:
|
|||
description: |
|
||||
Whether the anchor message is included in the
|
||||
response. If the message with the ID specified
|
||||
in the request does not exist or did not match
|
||||
the narrow, this will be false.
|
||||
in the request does not exist, did not match
|
||||
the narrow, or was excluded via
|
||||
`include_anchor=false`, this will be false.
|
||||
history_limited:
|
||||
type: boolean
|
||||
description: |
|
||||
|
|
|
@ -2864,6 +2864,28 @@ class GetOldMessagesTest(ZulipTestCase):
|
|||
self.assertEqual(data["found_newest"], True)
|
||||
self.assertEqual(data["history_limited"], False)
|
||||
|
||||
data = self.get_messages_response(
|
||||
anchor=message_ids[5], num_before=3, num_after=0, include_anchor=False
|
||||
)
|
||||
|
||||
messages = data["messages"]
|
||||
self.assertEqual(data["found_anchor"], False)
|
||||
self.assertEqual(data["found_oldest"], False)
|
||||
self.assertEqual(data["found_newest"], False)
|
||||
self.assertEqual(data["history_limited"], False)
|
||||
messages_matches_ids(messages, message_ids[2:5])
|
||||
|
||||
data = self.get_messages_response(
|
||||
anchor=message_ids[5], num_before=0, num_after=3, include_anchor=False
|
||||
)
|
||||
|
||||
messages = data["messages"]
|
||||
self.assertEqual(data["found_anchor"], False)
|
||||
self.assertEqual(data["found_oldest"], False)
|
||||
self.assertEqual(data["found_newest"], False)
|
||||
self.assertEqual(data["history_limited"], False)
|
||||
messages_matches_ids(messages, message_ids[6:9])
|
||||
|
||||
def test_missing_params(self) -> None:
|
||||
"""
|
||||
anchor, num_before, and num_after are all required
|
||||
|
@ -2914,6 +2936,13 @@ class GetOldMessagesTest(ZulipTestCase):
|
|||
result = self.client_get("/json/messages", post_params)
|
||||
self.assert_json_error(result, f"Bad value for '{param}': {type}")
|
||||
|
||||
def test_bad_include_anchor(self) -> None:
|
||||
self.login("hamlet")
|
||||
result = self.client_get(
|
||||
"/json/messages", dict(anchor=1, num_before=1, num_after=1, include_anchor="false")
|
||||
)
|
||||
self.assert_json_error(result, "The anchor can only be excluded at an end of the range")
|
||||
|
||||
def test_bad_narrow_type(self) -> None:
|
||||
"""
|
||||
narrow must be a list of string pairs.
|
||||
|
|
|
@ -819,6 +819,7 @@ class TestCurlExampleGeneration(ZulipTestCase):
|
|||
"curl -sSX GET -G http://localhost:9991/api/v1/messages \\",
|
||||
" -u BOT_EMAIL_ADDRESS:BOT_API_KEY \\",
|
||||
" --data-urlencode anchor=43 \\",
|
||||
" --data-urlencode include_anchor=false \\",
|
||||
" --data-urlencode num_before=4 \\",
|
||||
" --data-urlencode num_after=8 \\",
|
||||
' --data-urlencode \'narrow=[{"operand": "Denmark", "operator": "stream"}]\' \\',
|
||||
|
@ -893,6 +894,7 @@ class TestCurlExampleGeneration(ZulipTestCase):
|
|||
"curl -sSX GET -G http://localhost:9991/api/v1/messages \\",
|
||||
" -u BOT_EMAIL_ADDRESS:BOT_API_KEY \\",
|
||||
" --data-urlencode anchor=43 \\",
|
||||
" --data-urlencode include_anchor=false \\",
|
||||
" --data-urlencode num_before=4 \\",
|
||||
" --data-urlencode num_after=8 \\",
|
||||
' --data-urlencode \'narrow=[{"operand": "Denmark", "operator": "stream"}]\' \\',
|
||||
|
|
|
@ -84,6 +84,7 @@ def get_messages_backend(
|
|||
request: HttpRequest,
|
||||
maybe_user_profile: Union[UserProfile, AnonymousUser],
|
||||
anchor_val: Optional[str] = REQ("anchor", default=None),
|
||||
include_anchor: bool = REQ(json_validator=check_bool, default=True),
|
||||
num_before: int = REQ(converter=to_non_negative_int),
|
||||
num_after: int = REQ(converter=to_non_negative_int),
|
||||
narrow: OptionalNarrowListT = REQ("narrow", converter=narrow_parameter, default=None),
|
||||
|
@ -100,6 +101,8 @@ def get_messages_backend(
|
|||
MAX_MESSAGES_PER_FETCH,
|
||||
)
|
||||
)
|
||||
if num_before > 0 and num_after > 0 and not include_anchor:
|
||||
raise JsonableError(_("The anchor can only be excluded at an end of the range"))
|
||||
|
||||
realm = get_valid_realm_from_request(request)
|
||||
if not maybe_user_profile.is_authenticated:
|
||||
|
@ -160,6 +163,7 @@ def get_messages_backend(
|
|||
realm=realm,
|
||||
is_web_public_query=is_web_public_query,
|
||||
anchor=anchor,
|
||||
include_anchor=include_anchor,
|
||||
num_before=num_before,
|
||||
num_after=num_after,
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue