Skip to content

Commit e3e766e

Browse files
committed
Add Django backend: core configuration and chat application
1 parent cbf2cf3 commit e3e766e

16 files changed

+316
-0
lines changed

__init__.py

Whitespace-only changes.

asgi.py

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import os
2+
from django.core.asgi import get_asgi_application
3+
from channels.routing import ProtocolTypeRouter, URLRouter
4+
from channels.auth import AuthMiddlewareStack
5+
from channels.security.websocket import AllowedHostsOriginValidator
6+
from chat.routing import websocket_urlpatterns
7+
8+
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'baat_cheet.settings')
9+
10+
django_asgi_app = get_asgi_application()
11+
12+
application = ProtocolTypeRouter({
13+
"http": django_asgi_app,
14+
"websocket": AllowedHostsOriginValidator(
15+
AuthMiddlewareStack(
16+
URLRouter(
17+
websocket_urlpatterns
18+
)
19+
)
20+
),
21+
})

chat/__init__.py

Whitespace-only changes.

chat/admin.py

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from django.contrib import admin
2+
3+
# Register your models here.

chat/apps.py

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
from django.apps import AppConfig
2+
3+
4+
class ChatConfig(AppConfig):
5+
default_auto_field = 'django.db.models.BigAutoField'
6+
name = 'chat'

chat/consumers.py

+94
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
import json
2+
from channels.generic.websocket import AsyncWebsocketConsumer
3+
4+
class ChatConsumer(AsyncWebsocketConsumer):
5+
async def connect(self):
6+
self.room_name = self.scope['url_route']['kwargs']['room_name']
7+
self.room_group_name = f'chat_{self.room_name}'
8+
9+
await self.channel_layer.group_add(
10+
self.room_group_name,
11+
self.channel_name
12+
)
13+
await self.accept()
14+
15+
async def disconnect(self, close_code):
16+
await self.channel_layer.group_discard(
17+
self.room_group_name,
18+
self.channel_name
19+
)
20+
21+
async def receive(self, text_data):
22+
data = json.loads(text_data)
23+
message_type = data.get('type')
24+
25+
if message_type == 'join-room':
26+
await self.channel_layer.group_send(
27+
self.room_group_name,
28+
{
29+
'type': 'user_connected',
30+
'username': data.get('username')
31+
}
32+
)
33+
elif message_type == 'offer':
34+
await self.channel_layer.group_send(
35+
self.room_group_name,
36+
{
37+
'type': 'webrtc_offer',
38+
'offer': data.get('offer')
39+
}
40+
)
41+
elif message_type == 'answer':
42+
await self.channel_layer.group_send(
43+
self.room_group_name,
44+
{
45+
'type': 'webrtc_answer',
46+
'answer': data.get('answer')
47+
}
48+
)
49+
elif message_type == 'ice-candidate':
50+
await self.channel_layer.group_send(
51+
self.room_group_name,
52+
{
53+
'type': 'webrtc_ice',
54+
'candidate': data.get('candidate')
55+
}
56+
)
57+
elif message_type == 'chat-message':
58+
await self.channel_layer.group_send(
59+
self.room_group_name,
60+
{
61+
'type': 'chat_message',
62+
'message': data.get('message')
63+
}
64+
)
65+
66+
async def user_connected(self, event):
67+
await self.send(text_data=json.dumps({
68+
'type': 'user-connected',
69+
'username': event['username']
70+
}))
71+
72+
async def webrtc_offer(self, event):
73+
await self.send(text_data=json.dumps({
74+
'type': 'offer',
75+
'offer': event['offer']
76+
}))
77+
78+
async def webrtc_answer(self, event):
79+
await self.send(text_data=json.dumps({
80+
'type': 'answer',
81+
'answer': event['answer']
82+
}))
83+
84+
async def webrtc_ice(self, event):
85+
await self.send(text_data=json.dumps({
86+
'type': 'ice-candidate',
87+
'candidate': event['candidate']
88+
}))
89+
90+
async def chat_message(self, event):
91+
await self.send(text_data=json.dumps({
92+
'type': 'chat-message',
93+
'message': event['message']
94+
}))

chat/migrations/__init__.py

Whitespace-only changes.

chat/models.py

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from django.db import models
2+
3+
# Create your models here.

chat/routing.py

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
from django.urls import re_path
2+
from . import consumers
3+
4+
websocket_urlpatterns = [
5+
re_path(r'ws/chat/(?P<room_name>\w+)/$', consumers.ChatConsumer.as_asgi()),
6+
]

chat/tests.py

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from django.test import TestCase
2+
3+
# Create your tests here.

chat/urls.py

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
from django.urls import path
2+
from . import views
3+
4+
urlpatterns = [
5+
path('api/room/create/', views.create_room, name='create_room'),
6+
path('api/room/<str:room_id>/check/', views.check_room, name='check_room'),
7+
]

chat/views.py

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
from django.http import JsonResponse
2+
from django.views.decorators.csrf import csrf_exempt
3+
from django.views.decorators.http import require_http_methods
4+
import json
5+
6+
@csrf_exempt
7+
@require_http_methods(["POST"])
8+
def create_room(request):
9+
try:
10+
data = json.loads(request.body)
11+
room_id = data.get('room_id')
12+
if not room_id:
13+
return JsonResponse({'error': 'Room ID is required'}, status=400)
14+
return JsonResponse({'room_id': room_id})
15+
except json.JSONDecodeError:
16+
return JsonResponse({'error': 'Invalid JSON'}, status=400)
17+
18+
@csrf_exempt
19+
@require_http_methods(["GET"])
20+
def check_room(request, room_id):
21+
return JsonResponse({'exists': True})

manage.py

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#!/usr/bin/env python
2+
"""Django's command-line utility for administrative tasks."""
3+
import os
4+
import sys
5+
6+
7+
def main():
8+
"""Run administrative tasks."""
9+
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'baat_cheet.settings')
10+
try:
11+
from django.core.management import execute_from_command_line
12+
except ImportError as exc:
13+
raise ImportError(
14+
"Couldn't import Django. Are you sure it's installed and "
15+
"available on your PYTHONPATH environment variable? Did you "
16+
"forget to activate a virtual environment?"
17+
) from exc
18+
execute_from_command_line(sys.argv)
19+
20+
21+
if __name__ == '__main__':
22+
main()

settings.py

+107
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
from pathlib import Path
2+
import os
3+
4+
BASE_DIR = Path(__file__).resolve().parent.parent
5+
6+
SECRET_KEY = 'django-insecure-your-secret-key-here'
7+
8+
DEBUG = True
9+
10+
ALLOWED_HOSTS = ['*']
11+
12+
INSTALLED_APPS = [
13+
'django.contrib.admin',
14+
'django.contrib.auth',
15+
'django.contrib.contenttypes',
16+
'django.contrib.sessions',
17+
'django.contrib.messages',
18+
'django.contrib.staticfiles',
19+
'channels',
20+
'corsheaders',
21+
'chat',
22+
]
23+
24+
MIDDLEWARE = [
25+
'django.middleware.security.SecurityMiddleware',
26+
'django.contrib.sessions.middleware.SessionMiddleware',
27+
'corsheaders.middleware.CorsMiddleware',
28+
'django.middleware.common.CommonMiddleware',
29+
'django.middleware.csrf.CsrfViewMiddleware',
30+
'django.contrib.auth.middleware.AuthenticationMiddleware',
31+
'django.contrib.messages.middleware.MessageMiddleware',
32+
'django.middleware.clickjacking.XFrameOptionsMiddleware',
33+
]
34+
35+
CORS_ALLOWED_ORIGINS = [
36+
"http://localhost:3000",
37+
]
38+
39+
CORS_ALLOW_CREDENTIALS = True
40+
41+
ROOT_URLCONF = 'baat_cheet.urls'
42+
43+
TEMPLATES = [
44+
{
45+
'BACKEND': 'django.template.backends.django.DjangoTemplates',
46+
'DIRS': [],
47+
'APP_DIRS': True,
48+
'OPTIONS': {
49+
'context_processors': [
50+
'django.template.context_processors.debug',
51+
'django.template.context_processors.request',
52+
'django.contrib.auth.context_processors.auth',
53+
'django.contrib.messages.context_processors.messages',
54+
],
55+
},
56+
},
57+
]
58+
59+
WSGI_APPLICATION = 'baat_cheet.wsgi.application'
60+
ASGI_APPLICATION = 'baat_cheet.asgi.application'
61+
62+
CHANNEL_LAYERS = {
63+
'default': {
64+
'BACKEND': 'channels.layers.InMemoryChannelLayer'
65+
}
66+
}
67+
68+
DATABASES = {
69+
'default': {
70+
'ENGINE': 'django.db.backends.sqlite3',
71+
'NAME': BASE_DIR / 'db.sqlite3',
72+
}
73+
}
74+
75+
AUTH_PASSWORD_VALIDATORS = [
76+
{
77+
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
78+
},
79+
{
80+
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
81+
},
82+
{
83+
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
84+
},
85+
{
86+
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
87+
},
88+
]
89+
90+
LANGUAGE_CODE = 'en-us'
91+
TIME_ZONE = 'UTC'
92+
USE_I18N = True
93+
USE_TZ = True
94+
95+
STATIC_URL = 'static/'
96+
97+
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
98+
99+
# WebSocket settings
100+
CHANNEL_LAYERS = {
101+
"default": {
102+
"BACKEND": "channels_redis.core.RedisChannelLayer",
103+
"CONFIG": {
104+
"hosts": [("127.0.0.1", 6379)],
105+
},
106+
},
107+
}

urls.py

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
from django.contrib import admin
2+
from django.urls import path, include
3+
4+
urlpatterns = [
5+
path('admin/', admin.site.urls),
6+
path('', include('chat.urls')),
7+
]

wsgi.py

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
"""
2+
WSGI config for baat_cheet project.
3+
4+
It exposes the WSGI callable as a module-level variable named ``application``.
5+
6+
For more information on this file, see
7+
https://docs.djangoproject.com/en/5.1/howto/deployment/wsgi/
8+
"""
9+
10+
import os
11+
12+
from django.core.wsgi import get_wsgi_application
13+
14+
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'baat_cheet.settings')
15+
16+
application = get_wsgi_application()

0 commit comments

Comments
 (0)