-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
87 changed files
with
1,602 additions
and
336 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
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,19 @@ | ||
from channels.auth import AuthMiddlewareStack | ||
from channels.security.websocket import AllowedHostsOriginValidator | ||
from channels.routing import ProtocolTypeRouter, URLRouter | ||
from django.conf.urls import url | ||
|
||
from chat import consumers | ||
|
||
application = ProtocolTypeRouter({ | ||
"websocket": AllowedHostsOriginValidator( | ||
AuthMiddlewareStack( | ||
URLRouter([ | ||
url(r"^chat/session/(?P<chat_session>[\w.@+-]+)/$", | ||
consumers.ManageChatSessionConsumer.as_asgi()), | ||
url(r"^chat/messages/(?P<chat_session>[\w.@+-]+)/$", | ||
consumers.ChatMessageConsumer.as_asgi()), | ||
]) | ||
) | ||
), | ||
}) |
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
Empty file.
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,5 @@ | ||
from django.apps import AppConfig | ||
|
||
|
||
class ChatConfig(AppConfig): | ||
name = 'chat' |
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,66 @@ | ||
from core import models | ||
from core import consumers | ||
from . import serializers | ||
|
||
|
||
class ManageChatSessionConsumer(consumers.GenericWebsocketConsumer): | ||
"""List my chat session consumer.""" | ||
|
||
queryset = models.ChatSession.objects.all() | ||
serializer_class = serializers.ChatSessionSerializer | ||
|
||
def __init__(self, *args, **kwargs): | ||
super().__init__(*args, **kwargs) | ||
self.chat_session_id = None | ||
|
||
def register_groups(self, kwargs): | ||
self.chat_session_id = kwargs['chat_session'] | ||
return [ | ||
self.chat_session_id, | ||
] | ||
|
||
def receive_json(self, content, **kwargs): | ||
serializer = self.get_serializer(id=self.chat_session_id) | ||
data = serializer.data | ||
|
||
self.group_send_json( | ||
event_type='chat.session', | ||
group=self.chat_session_id, | ||
content=data, | ||
) | ||
|
||
def chat_session(self, event): | ||
self.send_json(event) | ||
|
||
|
||
class ChatMessageConsumer(consumers.GenericWebsocketConsumer): | ||
"""For chat messages.""" | ||
|
||
queryset = models.ChatMessage.objects.all() | ||
serializer_class = serializers.ChatMessageSerializer | ||
|
||
def __init__(self, *args, **kwargs): | ||
super().__init__(*args, **kwargs) | ||
self.chat_session_id = None | ||
|
||
def register_groups(self, kwargs): | ||
self.chat_session_id = kwargs['chat_session'] | ||
return [ | ||
self.chat_session_id, | ||
] | ||
|
||
def receive_json(self, content, **kwargs): | ||
message = content['message'] | ||
message['chat_session'] = self.chat_session_id | ||
if message['body']: | ||
serializer = self.serializer_class(data=message) | ||
if serializer.is_valid(): | ||
serializer.save(user=self.user) | ||
self.group_send_json( | ||
event_type='chat.message', | ||
group=self.chat_session_id, | ||
content=serializer.data, | ||
) | ||
|
||
def chat_message(self, event): | ||
self.send_json(event) |
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,170 @@ | ||
from rest_framework.serializers import ModelSerializer, \ | ||
ListField, PrimaryKeyRelatedField | ||
|
||
from core import models | ||
from user import serializers | ||
|
||
|
||
# ChatRole section | ||
class ChatRoleSerializer(ModelSerializer): | ||
"""The class serializer of chat role.""" | ||
|
||
class Meta: | ||
model = models.ChatRole | ||
fields = '__all__' | ||
read_only_fields = ('id',) | ||
|
||
|
||
# ChatSession section | ||
def add_members(chat_session, members): | ||
"""Add member to chat session.""" | ||
for member in members: | ||
user = models.User.objects.get( | ||
id=member, | ||
) | ||
models.ChatMember.objects.get_or_create( | ||
user=user, | ||
chat_session=chat_session, | ||
) | ||
|
||
|
||
def remove_members(chat_session, members): | ||
"""Remove member from chat session.""" | ||
for member in members: | ||
removed_member = models.ChatMember.objects.get( | ||
id=member, | ||
chat_session=chat_session, | ||
) | ||
removed_member.delete() | ||
|
||
|
||
class _ChatMemberSerializerForChatSessionSerializer(ModelSerializer): | ||
"""This serializer only for ChatSessionSerializer""" | ||
user = serializers.UserSerializer( | ||
read_only=True | ||
) | ||
|
||
class Meta: | ||
model = models.ChatMember | ||
exclude = ['chat_session', ] | ||
read_only_fields = ('id', 'chat_session') | ||
|
||
|
||
class _LimitChatRoleSerializer(ModelSerializer): | ||
"""The class serializer of chat role.""" | ||
|
||
class Meta: | ||
model = models.ChatRole | ||
exclude = ['chat_session', ] | ||
read_only_fields = ('id',) | ||
|
||
|
||
class ChatSessionSerializer(ModelSerializer): | ||
"""The serializer class of chat session.""" | ||
owner = serializers.UserSerializer( | ||
read_only=True | ||
) | ||
|
||
members = _ChatMemberSerializerForChatSessionSerializer( | ||
read_only=True, | ||
many=True, | ||
) | ||
roles = _LimitChatRoleSerializer( | ||
read_only=True, | ||
many=True, | ||
) | ||
|
||
# custom serializer field to control session members. | ||
# @add_members for adding new members to session. | ||
add_members = ListField( | ||
write_only=True, | ||
required=False, | ||
) | ||
# @remove_members for removing members from session. | ||
remove_members = ListField( | ||
write_only=True, | ||
required=False, | ||
) | ||
|
||
class Meta: | ||
model = models.ChatSession | ||
fields = '__all__' | ||
read_only_fields = ('id',) | ||
|
||
def create(self, validated_data): | ||
members = validated_data.pop('add_members', None) | ||
chat_session = models.ChatSession.objects.create(**validated_data) | ||
if members: | ||
add_members( | ||
chat_session=chat_session, | ||
members=members | ||
) | ||
return chat_session | ||
|
||
def update(self, instance, validated_data): | ||
# Add new members to chat session. | ||
members = validated_data.pop('add_members', None) | ||
if members: | ||
add_members( | ||
chat_session=instance, | ||
members=members | ||
) | ||
|
||
# Remove members from chat session. | ||
members = validated_data.pop('remove_members', None) | ||
if validated_data.get('remove_members'): | ||
remove_members( | ||
chat_session=instance, | ||
members=members | ||
) | ||
|
||
return super().update(instance, validated_data) | ||
|
||
|
||
# ChatMember section | ||
class _ChatSessionSerializerForMember(ModelSerializer): | ||
"""This serializer only for ChatMemberSerializer""" | ||
roles = PrimaryKeyRelatedField( | ||
read_only=True, | ||
many=True, | ||
) | ||
|
||
class Meta: | ||
model = models.ChatSession | ||
fields = '__all__' | ||
read_only_fields = ('id', 'owner') | ||
|
||
|
||
class ChatMemberSerializer(ModelSerializer): | ||
"""The serializer class of chat member.""" | ||
chat_session = _ChatSessionSerializerForMember( | ||
read_only=True, | ||
) | ||
role = _LimitChatRoleSerializer( | ||
read_only=True, | ||
) | ||
|
||
class Meta: | ||
model = models.ChatMember | ||
fields = '__all__' | ||
read_only_fields = ('id', 'user',) | ||
|
||
|
||
# ChatMessage section | ||
class ChatMessageSerializer(ModelSerializer): | ||
"""The serializer class of chat message.""" | ||
user = serializers.UserSerializer( | ||
read_only=True | ||
) | ||
|
||
class Meta: | ||
model = models.ChatMessage | ||
fields = '__all__' | ||
read_only_fields = ('id', 'user') | ||
|
||
def update(self, instance, validated_data): | ||
validated_data.pop('parent', None) | ||
validated_data.pop('chat_session', None) | ||
chat_message = super().update(instance, validated_data) | ||
|
||
return chat_message |
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,16 @@ | ||
from django.urls import reverse | ||
from django.contrib.auth import get_user_model | ||
|
||
LIST_CHAT_SESSION_URL = reverse('chat:session') | ||
CREATE_CHAT_SESSION_URL = reverse('chat:create') | ||
|
||
|
||
def MANAGE_CHAT_SESSION_URL(args): | ||
return reverse('chat:session', args=args) | ||
|
||
|
||
def create_user(email='user@test.com', username='testuser', | ||
first_name='test', password='1234abcd'): | ||
return get_user_model().objects. \ | ||
create_user(email=email, username=username, | ||
first_name=first_name, password=password) |
Oops, something went wrong.