-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add discussion messages actions
- Loading branch information
1 parent
a7b2f2b
commit 3cc8681
Showing
8 changed files
with
289 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,6 @@ | ||
from .discussion_messages import DiscussionCreateMessageSerializer # noqa | ||
from .discussion_messages import DiscussionReadMessageSerializer # noqa | ||
from .discussion_messages import MessageAndMediaSimpleSerializer # noqa | ||
from .discussions import DiscussionCreateSerializer # noqa | ||
from .discussions import DiscussionDetailSerializer # noqa | ||
from .discussions import DiscussionListSerializer # noqa |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
from rest_framework import serializers | ||
|
||
from chats.apps.api.v1.accounts.serializers import UserNameEmailSerializer | ||
|
||
from ..models import DiscussionMessage, DiscussionMessageMedia | ||
|
||
|
||
class DiscussionCreateMessageSerializer(serializers.Serializer): | ||
text = serializers.CharField(required=True) | ||
|
||
|
||
""" | ||
{ | ||
"content_type": "audio/wav", | ||
"created_on": "2022-12-15T18:06:45.654327-03:00", | ||
"message": "28e04b5a-9e70-4826-bd24-fed837661495", | ||
"url": "http://domain.com/recording.wav" | ||
} | ||
""" | ||
|
||
|
||
class MessageMediaSimpleSerializer(serializers.ModelSerializer): | ||
url = serializers.SerializerMethodField(read_only=True) | ||
|
||
class Meta: | ||
model = DiscussionMessageMedia | ||
fields = [ | ||
"content_type", | ||
"url", | ||
"created_on", | ||
] | ||
|
||
def get_url(self, media: DiscussionMessageMedia): | ||
return media.url | ||
|
||
|
||
class DiscussionReadMessageSerializer(serializers.ModelSerializer): | ||
user = UserNameEmailSerializer(many=False, required=False, read_only=True) | ||
media = MessageMediaSimpleSerializer(many=True, required=False) | ||
|
||
class Meta: | ||
model = DiscussionMessage | ||
fields = [ | ||
"uuid", | ||
"user", | ||
"discussion", | ||
"text", | ||
"media", | ||
"created_on", | ||
] | ||
|
||
|
||
class MessageAndMediaSimpleSerializer(serializers.Serializer): | ||
text = serializers.CharField(required=False) | ||
content_type = serializers.CharField(required=True) | ||
media_file = serializers.FileField(required=True) |
111 changes: 111 additions & 0 deletions
111
chats/apps/discussions/tests/test_discussion_msgs_actions.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
from django.urls import reverse | ||
from parameterized import parameterized | ||
from rest_framework import status | ||
from rest_framework.test import APITestCase | ||
|
||
|
||
class CreateDiscussionMessageViewActionTests(APITestCase): | ||
# ("Scenario description", room, queue, subject, initial_message, user_token, expected_response_status) | ||
fixtures = [ | ||
"chats/fixtures/fixture_app.json", | ||
"chats/fixtures/fixture_discussion.json", | ||
] | ||
|
||
parameters = [ | ||
# Success parameters | ||
( | ||
"Added user can send messages to the discussion", | ||
"3c2d1694-8db9-4f09-976b-e263f9d79c99", | ||
"super large giant text phrase very cool v2", | ||
"d7fddba0b1dfaad72aa9e21876cbc93caa9ce3fa", | ||
status.HTTP_201_CREATED, | ||
), | ||
( | ||
"Outside room user cannot send messages to the discussion", | ||
"3c2d1694-8db9-4f09-976b-e263f9d79c99", | ||
"super large giant text phrase very cool v2", | ||
"a0358e20c8755568189d3a7e688ac3ec771317e2", | ||
status.HTTP_403_FORBIDDEN, | ||
), | ||
( | ||
"Outside room admin cannot send messages to the discussion", | ||
"3c2d1694-8db9-4f09-976b-e263f9d79c99", | ||
"super large giant text phrase very cool v2", | ||
"4215e6d6666e54f7db9f98100533aa68909fd855", | ||
status.HTTP_403_FORBIDDEN, | ||
), | ||
] | ||
|
||
def _create_discussion_user(self, token, discussion, body): | ||
url = ( | ||
reverse("discussion-detail", kwargs={"uuid": discussion}) + "send_messages/" | ||
) | ||
client = self.client | ||
client.credentials(HTTP_AUTHORIZATION="Token " + token) | ||
response = client.post(url, format="json", data=body) | ||
return response | ||
|
||
@parameterized.expand(parameters) | ||
def test_send_messages_to_discussion( | ||
self, _, discussion, text, token, expected_status | ||
): | ||
discussion_data = { | ||
"text": text, | ||
} | ||
|
||
response = self._create_discussion_user(token, discussion, discussion_data) | ||
self.assertEqual(response.status_code, expected_status) | ||
|
||
|
||
class ListDiscussionMsgsViewActionTests(APITestCase): | ||
fixtures = [ | ||
"chats/fixtures/fixture_app.json", | ||
"chats/fixtures/fixture_discussion.json", | ||
] | ||
parameters = [ | ||
( | ||
"Creator can list all msgs on the discussions", | ||
"d7fddba0b1dfaad72aa9e21876cbc93caa9ce3fa", | ||
"3c2d1694-8db9-4f09-976b-e263f9d79c99", | ||
status.HTTP_200_OK, | ||
1, | ||
), | ||
( | ||
"Admin can list all msgs on the discussions", | ||
"4215e6d6666e54f7db9f98100533aa68909fd855", | ||
"3c2d1694-8db9-4f09-976b-e263f9d79c99", | ||
status.HTTP_200_OK, | ||
1, | ||
), | ||
( | ||
"Added user can list all msgs on the discussions", | ||
"a0358e20c8755568189d3a7e688ac3ec771317e2", | ||
"36584c70-aaf9-4f5c-b0c3-0547bb23879d", | ||
status.HTTP_200_OK, | ||
1, | ||
), | ||
( | ||
"Outside project user cannot list discussion msgs", | ||
"1218da72b087b8be7f0e2520a515e968ab866fdd", | ||
"3c2d1694-8db9-4f09-976b-e263f9d79c99", | ||
status.HTTP_403_FORBIDDEN, | ||
None, | ||
), | ||
] | ||
|
||
def _list_discussion_user(self, token, discussion, params={}): | ||
url = ( | ||
reverse("discussion-detail", kwargs={"uuid": discussion}) + "list_messages/" | ||
) | ||
client = self.client | ||
client.credentials(HTTP_AUTHORIZATION="Token " + token) | ||
response = client.get(url, data=params) | ||
return response | ||
|
||
@parameterized.expand(parameters) | ||
def test_discussion_msgs( | ||
self, _, token, discussion, expected_status, expected_count | ||
): | ||
response = self._list_discussion_user(token=token, discussion=discussion) | ||
self.assertEqual(response.status_code, expected_status) | ||
self.assertEqual(response.json().get("count"), expected_count) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,2 @@ | ||
from .create_discussion import CreateDiscussionUseCase # noqa | ||
from .create_message_with_media import CreateMessageWithMediaUseCase # noqa |
22 changes: 22 additions & 0 deletions
22
chats/apps/discussions/usecases/create_message_with_media.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
from ..models import DiscussionMessage | ||
|
||
|
||
class CreateMessageWithMediaUseCase: | ||
def __init__(self, discussion, user, msg_content: dict, notify: bool = True): | ||
self.discussion = discussion | ||
self.user = user | ||
self.msg_content = msg_content | ||
self.notify = notify | ||
|
||
def _create_message(self, text): | ||
return DiscussionMessage.objects.create( | ||
discussion=self.discussion, user=self.user, text=text | ||
) | ||
|
||
def execute(self): | ||
text = self.msg_content.pop("text", "") | ||
msg = self._create_message(text) | ||
media = msg.medias.create(**self.msg_content) | ||
if self.notify: | ||
msg.notify("create") | ||
return media |
89 changes: 89 additions & 0 deletions
89
chats/apps/discussions/views/_discussion_message_actions.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
from rest_framework import parsers, status | ||
from rest_framework.decorators import action | ||
from rest_framework.response import Response | ||
|
||
from ..models import DiscussionMessage | ||
from ..serializers import ( | ||
DiscussionCreateMessageSerializer, | ||
DiscussionReadMessageSerializer, | ||
MessageAndMediaSimpleSerializer, | ||
) | ||
from ..usecases import CreateMessageWithMediaUseCase | ||
|
||
|
||
class DiscussionMessageActionsMixin: | ||
"""This should be used with a Discussion model viewset""" | ||
|
||
@action( | ||
detail=True, methods=["POST"], url_name="send_messages", filterset_class=None | ||
) | ||
def send_messages(self, request, *args, **kwargs): | ||
user = request.user | ||
discussion = self.get_object() | ||
try: | ||
serializer = DiscussionCreateMessageSerializer(data=request.data) | ||
serializer.is_valid(raise_exception=True) | ||
msg = discussion.create_discussion_message( | ||
message=serializer.validated_data.get("text"), user=user | ||
) | ||
serialized_msg = DiscussionReadMessageSerializer(instance=msg) | ||
|
||
return Response( | ||
serialized_msg.data, | ||
status=status.HTTP_201_CREATED, | ||
) | ||
except Exception as error: | ||
return Response( | ||
{"detail": f"{type(error)}: {error}"}, | ||
status=status.HTTP_400_BAD_REQUEST, | ||
) | ||
|
||
@action( | ||
detail=True, methods=["GET"], url_name="list_messages", filterset_class=None | ||
) | ||
def list_messages(self, request, *args, **kwargs): | ||
discussion = self.get_object() | ||
|
||
queryset = DiscussionMessage.objects.filter(discussion=discussion) | ||
ordering = request.GET.get("ordering") | ||
if ordering: | ||
order_list = ordering.split(",") | ||
|
||
queryset = queryset.order_by(*order_list) | ||
|
||
page = self.paginate_queryset(queryset) | ||
reverse_page = request.GET.get("reverse_results") | ||
if reverse_page: | ||
page.reverse() | ||
|
||
if page is not None: | ||
serializer = DiscussionReadMessageSerializer(page, many=True) | ||
return self.get_paginated_response(serializer.data) | ||
|
||
serializer = DiscussionReadMessageSerializer(queryset, many=True) | ||
return Response(serializer.data) | ||
|
||
@action( | ||
methods=["POST"], | ||
detail=True, | ||
url_name="create_media", | ||
parser_classes=[parsers.MultiPartParser], | ||
) | ||
def send_media_messages(self, request, *args, **kwargs): | ||
serializer = MessageAndMediaSimpleSerializer(data=request.data) | ||
serializer.is_valid(raise_exception=True) | ||
|
||
discussion = self.get_object() | ||
user = request.user | ||
|
||
message_media = CreateMessageWithMediaUseCase( | ||
discussion, user, serializer.validated_data | ||
).execute() | ||
serialized_message = DiscussionReadMessageSerializer( | ||
instance=message_media.message | ||
) | ||
headers = self.get_success_headers(serialized_message.data) | ||
|
||
return Response( | ||
serialized_message.data, status=status.HTTP_201_CREATED, headers=headers | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters