initial commit
This commit is contained in:
0
backend/websocket/__init__.py
Normal file
0
backend/websocket/__init__.py
Normal file
BIN
backend/websocket/__pycache__/__init__.cpython-312.pyc
Normal file
BIN
backend/websocket/__pycache__/__init__.cpython-312.pyc
Normal file
Binary file not shown.
BIN
backend/websocket/__pycache__/admin.cpython-312.pyc
Normal file
BIN
backend/websocket/__pycache__/admin.cpython-312.pyc
Normal file
Binary file not shown.
BIN
backend/websocket/__pycache__/apps.cpython-312.pyc
Normal file
BIN
backend/websocket/__pycache__/apps.cpython-312.pyc
Normal file
Binary file not shown.
BIN
backend/websocket/__pycache__/consumers.cpython-312.pyc
Normal file
BIN
backend/websocket/__pycache__/consumers.cpython-312.pyc
Normal file
Binary file not shown.
BIN
backend/websocket/__pycache__/middleware.cpython-312.pyc
Normal file
BIN
backend/websocket/__pycache__/middleware.cpython-312.pyc
Normal file
Binary file not shown.
BIN
backend/websocket/__pycache__/models.cpython-312.pyc
Normal file
BIN
backend/websocket/__pycache__/models.cpython-312.pyc
Normal file
Binary file not shown.
BIN
backend/websocket/__pycache__/routing.cpython-312.pyc
Normal file
BIN
backend/websocket/__pycache__/routing.cpython-312.pyc
Normal file
Binary file not shown.
3
backend/websocket/admin.py
Normal file
3
backend/websocket/admin.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from django.contrib import admin
|
||||
|
||||
# Register your models here.
|
||||
6
backend/websocket/apps.py
Normal file
6
backend/websocket/apps.py
Normal file
@@ -0,0 +1,6 @@
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class WebsocketConfig(AppConfig):
|
||||
default_auto_field = 'django.db.models.BigAutoField'
|
||||
name = 'websocket'
|
||||
93
backend/websocket/consumers.py
Normal file
93
backend/websocket/consumers.py
Normal file
@@ -0,0 +1,93 @@
|
||||
from channels.generic.websocket import AsyncWebsocketConsumer, WebsocketConsumer
|
||||
from asgiref.sync import async_to_sync, sync_to_async
|
||||
from rest.serializers import MessageSerializer
|
||||
from hub.models import Hub, Message, HubChannel
|
||||
from django.contrib.auth.models import User
|
||||
import json, base64
|
||||
from django.core.files.base import ContentFile
|
||||
|
||||
class ChatConsumer(AsyncWebsocketConsumer):
|
||||
async def connect(self):
|
||||
if not self.channel_layer:
|
||||
print("Channel layer is not configured!")
|
||||
await self.close()
|
||||
return
|
||||
|
||||
|
||||
self.hub_channel_name = self.scope['url_route']['kwargs']['channel_id']
|
||||
self.hub_group_name = f"channel_{self.hub_channel_name}"
|
||||
|
||||
print(f"Connecting to group: {self.hub_group_name}")
|
||||
print(f"Channel name: {self.hub_channel_name}")
|
||||
|
||||
# Join the hub group
|
||||
await self.channel_layer.group_add(
|
||||
self.hub_group_name,
|
||||
self.channel_name
|
||||
)
|
||||
|
||||
await self.accept()
|
||||
|
||||
print(f"Added {self.hub_channel_name} to group {self.hub_group_name}")
|
||||
|
||||
async def disconnect(self, close_code):
|
||||
print("DISCONNECTED!!!!!!!!!!!!!1")
|
||||
await self.channel_layer.group_discard(
|
||||
self.hub_group_name,
|
||||
self.channel_name
|
||||
)
|
||||
|
||||
|
||||
# await self.accept()
|
||||
|
||||
async def receive(self, text_data):
|
||||
text_data_json = json.loads(text_data)
|
||||
# print(text_data_json)
|
||||
user = await sync_to_async(User.objects.get)(username=self.scope["user"])
|
||||
# user = self.scope["user"] # Assuming authenticated user is available
|
||||
channel_name = text_data_json["channel"]
|
||||
content = text_data_json.get("content", "")
|
||||
image_data = text_data_json.get("image", None)
|
||||
|
||||
# Ensure the hub exists asynchronously
|
||||
mchannel = await sync_to_async(HubChannel.objects.get)(id=channel_name)
|
||||
# print("Image data: ", image_data)
|
||||
|
||||
image = None
|
||||
if image_data:
|
||||
format, imgstr = image_data.split(';base64,') # Decode base64
|
||||
ext = format.split('/')[-1]
|
||||
image = ContentFile(base64.b64decode(imgstr), name=f"{user.username}_{channel_name}.{ext}")
|
||||
|
||||
if image != None or content != "":
|
||||
# Save the message to the database
|
||||
new_message = await sync_to_async(Message.objects.create)(
|
||||
hubChannels=mchannel, user=user, content=content, image=image
|
||||
)
|
||||
|
||||
# Serialize the saved message
|
||||
serialized_message = await sync_to_async(MessageSerializer)(new_message)
|
||||
message_data = serialized_message.data
|
||||
|
||||
await self.channel_layer.group_send(
|
||||
self.hub_group_name,
|
||||
{
|
||||
'type': "chat.message",
|
||||
'hubChannels': mchannel.id,
|
||||
'user': user.username,
|
||||
'content': content,
|
||||
'image': message_data.get("image"), # Include image URL
|
||||
'created_at': message_data["created_at"],
|
||||
}
|
||||
)
|
||||
print("Broadcasted!")
|
||||
|
||||
async def chat_message(self, event):
|
||||
# Send the message to WebSocket
|
||||
print("sent!")
|
||||
await self.send(text_data=json.dumps({
|
||||
'hubChannels': event.get('channel_id'),
|
||||
'user': event['user'],
|
||||
'content': event['content'],
|
||||
'image': event.get('image'), # Add image URL to frontend
|
||||
}))
|
||||
28
backend/websocket/middleware.py
Normal file
28
backend/websocket/middleware.py
Normal file
@@ -0,0 +1,28 @@
|
||||
# your_app/middleware.py
|
||||
from channels.db import database_sync_to_async
|
||||
from rest_framework.authtoken.models import Token
|
||||
from django.contrib.auth.models import AnonymousUser
|
||||
from urllib.parse import parse_qs
|
||||
|
||||
class QueryAuthMiddleware:
|
||||
"""
|
||||
Custom middleware to authenticate users using a token passed in the WebSocket URL query string.
|
||||
"""
|
||||
def __init__(self, inner):
|
||||
self.inner = inner
|
||||
|
||||
async def __call__(self, scope, receive, send):
|
||||
query_string = scope["query_string"].decode()
|
||||
query_params = parse_qs(query_string)
|
||||
token_key = query_params.get("token", [None])[0]
|
||||
|
||||
if token_key:
|
||||
try:
|
||||
token = await database_sync_to_async(Token.objects.get)(key=token_key)
|
||||
scope["user"] = token.user
|
||||
except Token.DoesNotExist:
|
||||
scope["user"] = AnonymousUser()
|
||||
else:
|
||||
scope["user"] = AnonymousUser()
|
||||
|
||||
return await self.inner(scope, receive, send)
|
||||
0
backend/websocket/migrations/__init__.py
Normal file
0
backend/websocket/migrations/__init__.py
Normal file
Binary file not shown.
3
backend/websocket/models.py
Normal file
3
backend/websocket/models.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from django.db import models
|
||||
|
||||
# Create your models here.
|
||||
6
backend/websocket/routing.py
Normal file
6
backend/websocket/routing.py
Normal file
@@ -0,0 +1,6 @@
|
||||
from django.urls import re_path, path
|
||||
from . import consumers
|
||||
|
||||
websocket_urlpatterns = [
|
||||
re_path(r"ws/channel/(?P<channel_id>[\w-]+)/$", consumers.ChatConsumer.as_asgi()),
|
||||
]
|
||||
3
backend/websocket/tests.py
Normal file
3
backend/websocket/tests.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
||||
3
backend/websocket/views.py
Normal file
3
backend/websocket/views.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from django.shortcuts import render
|
||||
|
||||
# Create your views here.
|
||||
Reference in New Issue
Block a user