mirror of
https://github.com/zulip/zulip.git
synced 2025-11-08 07:52:19 +00:00
Add /submessage endpoint.
This commit is contained in:
@@ -64,7 +64,7 @@ from zerver.lib.topic_mutes import (
|
||||
from zerver.lib.users import bulk_get_users, check_full_name, user_ids_to_users
|
||||
from zerver.lib.user_groups import create_user_group, access_user_group_by_id
|
||||
from zerver.models import Realm, RealmEmoji, Stream, UserProfile, UserActivity, \
|
||||
RealmDomain, Service, \
|
||||
RealmDomain, Service, SubMessage, \
|
||||
Subscription, Recipient, Message, Attachment, UserMessage, RealmAuditLog, \
|
||||
UserHotspot, MultiuseInvite, ScheduledMessage, \
|
||||
Client, DefaultStream, DefaultStreamGroup, UserPresence, PushDeviceToken, \
|
||||
@@ -1424,6 +1424,32 @@ def bulk_insert_ums(ums: List[UserMessageLite]) -> None:
|
||||
with connection.cursor() as cursor:
|
||||
cursor.execute(query)
|
||||
|
||||
def do_add_submessage(sender_id: int,
|
||||
message_id: int,
|
||||
msg_type: str,
|
||||
content: str,
|
||||
data: Any,
|
||||
) -> None:
|
||||
submessage = SubMessage(
|
||||
sender_id=sender_id,
|
||||
message_id=message_id,
|
||||
msg_type=msg_type,
|
||||
content=content,
|
||||
)
|
||||
submessage.save()
|
||||
|
||||
event = dict(
|
||||
type="submessage",
|
||||
msg_type=msg_type,
|
||||
message_id=message_id,
|
||||
sender_id=sender_id,
|
||||
data=data,
|
||||
)
|
||||
ums = UserMessage.objects.filter(message_id=message_id)
|
||||
target_user_ids = [um.user_profile_id for um in ums]
|
||||
|
||||
send_event(event, target_user_ids)
|
||||
|
||||
def notify_reaction_update(user_profile: UserProfile, message: Message,
|
||||
reaction: Reaction, op: str) -> None:
|
||||
user_dict = {'user_id': user_profile.id,
|
||||
|
||||
@@ -560,6 +560,9 @@ def apply_event(state: Dict[str, Any],
|
||||
elif event['type'] == "reaction":
|
||||
# The client will get the message with the reactions directly
|
||||
pass
|
||||
elif event['type'] == "submessage":
|
||||
# The client will get submessages with their messages
|
||||
pass
|
||||
elif event['type'] == 'typing':
|
||||
# Typing notification events are transient and thus ignored
|
||||
pass
|
||||
|
||||
@@ -33,6 +33,7 @@ from zerver.lib.actions import (
|
||||
do_add_realm_domain,
|
||||
do_add_realm_filter,
|
||||
do_add_streams_to_default_stream_group,
|
||||
do_add_submessage,
|
||||
do_change_avatar_fields,
|
||||
do_change_bot_owner,
|
||||
do_change_default_all_public_streams,
|
||||
@@ -867,6 +868,34 @@ class EventsRegisterTest(ZulipTestCase):
|
||||
error = schema_checker('events[0]', events[0])
|
||||
self.assert_on_error(error)
|
||||
|
||||
def test_add_submessage(self) -> None:
|
||||
schema_checker = self.check_events_dict([
|
||||
('type', equals('submessage')),
|
||||
('message_id', check_int),
|
||||
('sender_id', check_int),
|
||||
('msg_type', check_string),
|
||||
('data', check_string),
|
||||
])
|
||||
|
||||
cordelia = self.example_user('cordelia')
|
||||
stream_name = 'Verona'
|
||||
message_id = self.send_stream_message(
|
||||
sender_email=cordelia.email,
|
||||
stream_name=stream_name,
|
||||
)
|
||||
events = self.do_test(
|
||||
lambda: do_add_submessage(
|
||||
sender_id=cordelia.id,
|
||||
message_id=message_id,
|
||||
msg_type='whatever',
|
||||
content='"stuff"',
|
||||
data='stuff',
|
||||
),
|
||||
state_change_expected=False,
|
||||
)
|
||||
error = schema_checker('events[0]', events[0])
|
||||
self.assert_on_error(error)
|
||||
|
||||
def test_remove_reaction(self) -> None:
|
||||
schema_checker = self.check_events_dict([
|
||||
('type', equals('reaction')),
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import mock
|
||||
|
||||
from zerver.lib.test_classes import ZulipTestCase
|
||||
|
||||
from zerver.lib.message import (
|
||||
@@ -73,3 +75,83 @@ class TestBasics(ZulipTestCase):
|
||||
rows = msg_rows[0]['submessages']
|
||||
rows.sort(key=lambda r: r['id'])
|
||||
self.assertEqual(rows, expected_data)
|
||||
|
||||
def test_endpoint_errors(self) -> None:
|
||||
cordelia = self.example_user('cordelia')
|
||||
stream_name = 'Verona'
|
||||
message_id = self.send_stream_message(
|
||||
sender_email=cordelia.email,
|
||||
stream_name=stream_name,
|
||||
)
|
||||
self.login(cordelia.email)
|
||||
|
||||
payload = dict(
|
||||
message_id=message_id,
|
||||
msg_type='whatever',
|
||||
content='not json',
|
||||
)
|
||||
result = self.client_post('/json/submessage', payload)
|
||||
self.assert_json_error(result, 'Invalid json for submessage')
|
||||
|
||||
hamlet = self.example_user('hamlet')
|
||||
bad_message_id = self.send_personal_message(
|
||||
from_email=hamlet.email,
|
||||
to_email=hamlet.email,
|
||||
)
|
||||
payload = dict(
|
||||
message_id=bad_message_id,
|
||||
msg_type='whatever',
|
||||
content='does not matter',
|
||||
)
|
||||
result = self.client_post('/json/submessage', payload)
|
||||
self.assert_json_error(result, 'Invalid message(s)')
|
||||
|
||||
def test_endpoint_success(self) -> None:
|
||||
cordelia = self.example_user('cordelia')
|
||||
hamlet = self.example_user('hamlet')
|
||||
stream_name = 'Verona'
|
||||
message_id = self.send_stream_message(
|
||||
sender_email=cordelia.email,
|
||||
stream_name=stream_name,
|
||||
)
|
||||
self.login(cordelia.email)
|
||||
|
||||
payload = dict(
|
||||
message_id=message_id,
|
||||
msg_type='whatever',
|
||||
content='{"name": "alice", "salary": 20}'
|
||||
)
|
||||
with mock.patch('zerver.lib.actions.send_event') as m:
|
||||
result = self.client_post('/json/submessage', payload)
|
||||
self.assert_json_success(result)
|
||||
|
||||
expected_data = dict(
|
||||
message_id=message_id,
|
||||
data=dict(
|
||||
name='alice',
|
||||
salary=20,
|
||||
),
|
||||
msg_type='whatever',
|
||||
sender_id=cordelia.id,
|
||||
type='submessage',
|
||||
)
|
||||
|
||||
self.assertEqual(m.call_count, 1)
|
||||
data = m.call_args[0][0]
|
||||
self.assertEqual(data, expected_data)
|
||||
users = m.call_args[0][1]
|
||||
self.assertIn(cordelia.id, users)
|
||||
self.assertIn(hamlet.id, users)
|
||||
|
||||
rows = SubMessage.get_raw_db_rows([message_id])
|
||||
self.assertEqual(len(rows), 1)
|
||||
row = rows[0]
|
||||
|
||||
expected_data = dict(
|
||||
id=row['id'],
|
||||
message_id=message_id,
|
||||
content='{"name": "alice", "salary": 20}',
|
||||
msg_type='whatever',
|
||||
sender_id=cordelia.id,
|
||||
)
|
||||
self.assertEqual(row, expected_data)
|
||||
|
||||
46
zerver/views/submessage.py
Normal file
46
zerver/views/submessage.py
Normal file
@@ -0,0 +1,46 @@
|
||||
import logging
|
||||
import ujson
|
||||
|
||||
from django.http import HttpRequest, HttpResponse
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.conf import settings
|
||||
|
||||
from zerver.decorator import (
|
||||
has_request_variables,
|
||||
REQ,
|
||||
)
|
||||
from zerver.lib.actions import do_add_submessage
|
||||
from zerver.lib.message import access_message
|
||||
from zerver.lib.validator import check_int
|
||||
from zerver.lib.response import (
|
||||
json_error,
|
||||
json_success
|
||||
)
|
||||
from zerver.models import UserProfile
|
||||
|
||||
@has_request_variables
|
||||
def process_submessage(request: HttpRequest,
|
||||
user_profile: UserProfile,
|
||||
message_id: int=REQ(validator=check_int),
|
||||
msg_type: str=REQ(),
|
||||
content: str=REQ(),
|
||||
) -> HttpResponse:
|
||||
message, user_message = access_message(user_profile, message_id)
|
||||
|
||||
if not settings.ALLOW_SUB_MESSAGES: # nocoverage
|
||||
msg = 'Feature not enabled'
|
||||
return json_error(msg)
|
||||
|
||||
try:
|
||||
data = ujson.loads(content)
|
||||
except Exception:
|
||||
return json_error(_("Invalid json for submessage"))
|
||||
|
||||
do_add_submessage(
|
||||
sender_id=user_profile.id,
|
||||
message_id=message.id,
|
||||
msg_type=msg_type,
|
||||
content=content,
|
||||
data=data,
|
||||
)
|
||||
return json_success()
|
||||
@@ -187,6 +187,10 @@ v1_api_and_json_patterns = [
|
||||
url(r'users/me/subscriptions/(?P<stream_id>\d+)$', rest_dispatch,
|
||||
{'PATCH': 'zerver.views.streams.update_subscriptions_property'}),
|
||||
|
||||
url(r'^submessage$',
|
||||
rest_dispatch,
|
||||
{'POST': 'zerver.views.submessage.process_submessage'}),
|
||||
|
||||
# New endpoint for handling reactions.
|
||||
url(r'^messages/(?P<message_id>[0-9]+)/reactions$',
|
||||
rest_dispatch,
|
||||
|
||||
Reference in New Issue
Block a user