Skip to content

Commit

Permalink
(0.4v) Chat Version
Browse files Browse the repository at this point in the history
  • Loading branch information
MuhmdHsn313 committed Nov 10, 2020
2 parents 09f3350 + 307f433 commit 0fbf82b
Show file tree
Hide file tree
Showing 87 changed files with 1,602 additions and 336 deletions.
3 changes: 2 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ ENV PYTHONUNBUFFERED 1
COPY ./requirements.txt /requirements.txt
RUN apk add --update --no-cache postgresql-client jpeg-dev
RUN apk add --update --no-cache --virtual .tmp-build-deps \
gcc libc-dev linux-headers postgresql-dev musl-dev zlib zlib-dev
gcc libc-dev linux-headers postgresql-dev musl-dev zlib zlib-dev libffi libffi-dev

RUN pip install -r /requirements.txt
RUN apk del .tmp-build-deps

Expand Down
5 changes: 2 additions & 3 deletions app/app/asgi.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,8 @@
"""

import os

from django.core.asgi import get_asgi_application
from channels.routing import get_default_application

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'app.settings')

application = get_asgi_application()
application = get_default_application()
19 changes: 19 additions & 0 deletions app/app/routing.py
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()),
])
)
),
})
10 changes: 9 additions & 1 deletion app/app/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = []
ALLOWED_HOSTS = ['*']

# Application definition

Expand All @@ -41,6 +41,7 @@
'user',
'post_sys',
'media',
'channels',
]

MIDDLEWARE = [
Expand Down Expand Up @@ -136,3 +137,10 @@
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
'PAGE_SIZE': 10,
}
ASGI_APPLICATION = 'app.routing.application'

CHANNEL_LAYERS = {
"default": {
"BACKEND": "channels.layers.InMemoryChannelLayer"
},
}
3 changes: 2 additions & 1 deletion app/app/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@

urlpatterns = [
path('admin/', admin.site.urls),
path('api/user/', include('user.urls')),
path('user/', include('user.urls')),
path('api/post_sys/', include('post_sys.urls')),
path('api/media/', include('media.urls')),
path('api/chat/', include('chat.urls')),
path('', include('core.urls')),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
Empty file added app/chat/__init__.py
Empty file.
5 changes: 5 additions & 0 deletions app/chat/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from django.apps import AppConfig


class ChatConfig(AppConfig):
name = 'chat'
66 changes: 66 additions & 0 deletions app/chat/consumers.py
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)
170 changes: 170 additions & 0 deletions app/chat/serializers.py
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
16 changes: 16 additions & 0 deletions app/chat/tests/__init__.py
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)
Loading

0 comments on commit 0fbf82b

Please sign in to comment.