Skip to content

Commit 592e3d5

Browse files
committed
insta clone
1 parent c505fbb commit 592e3d5

File tree

431 files changed

+92714
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

431 files changed

+92714
-0
lines changed

instagram-clone-Django/chat/__init__.py

Whitespace-only changes.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
from django.contrib import admin
2+
3+
from chat.models import Room, Message
4+
5+
admin.site.register(Room)
6+
admin.site.register(Message)
Lines changed: 6 additions & 0 deletions
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'
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
# chat/consumers.py
2+
import json
3+
from channels.generic.websocket import AsyncWebsocketConsumer
4+
from channels.db import database_sync_to_async
5+
from .models import Room, Message, UserModel
6+
from posts.models import PostModel # agar kerak bo'lsa
7+
8+
class ChatConsumer(AsyncWebsocketConsumer):
9+
async def connect(self):
10+
# room_name from URL, e.g. "private_admin_jamil"
11+
self.room_name = self.scope['url_route']['kwargs']['room_name']
12+
# group name used for channel_layer
13+
self.room_group_name = f"room_{self.room_name}"
14+
15+
await self.channel_layer.group_add(
16+
self.room_group_name,
17+
self.channel_name
18+
)
19+
await self.accept()
20+
21+
async def disconnect(self, code):
22+
# use the group name (not raw room_name)
23+
await self.channel_layer.group_discard(
24+
self.room_group_name,
25+
self.channel_name
26+
)
27+
28+
async def receive(self, text_data):
29+
# data expected: {"message": "...", "room_name": "...", "sender": "..."}
30+
data_json = json.loads(text_data)
31+
32+
event = {"type": "send_message", "message": data_json}
33+
34+
# send to the group (use same group name as added)
35+
await self.channel_layer.group_send(self.room_group_name, event)
36+
37+
async def send_message(self, event):
38+
data = event["message"]
39+
40+
# save to DB (text or post)
41+
await self.create_message(data)
42+
43+
# build response for clients
44+
if data.get("post_id"):
45+
response = {
46+
"sender": data.get("sender"),
47+
"post_id": data.get("post_id"),
48+
"post_type": data.get("post_type"),
49+
"caption": data.get("caption"),
50+
"media_url": data.get("media_url"),
51+
"username": data.get("username"),
52+
}
53+
else:
54+
response = {
55+
"sender": data.get("sender"),
56+
"message": data.get("message"),
57+
}
58+
59+
await self.send(text_data=json.dumps({"message": response}))
60+
61+
# consumers.py - Fix the create_message method
62+
# consumers.py - Ensure proper message saving for posts
63+
@database_sync_to_async
64+
def create_message(self, data):
65+
try:
66+
room = Room.objects.get(room_name=data.get("room_name") or self.room_name)
67+
sender_user = UserModel.objects.get(username=data.get('sender'))
68+
69+
# If this is a post share
70+
if data.get("post_id"):
71+
try:
72+
post = PostModel.objects.get(id=data.get("post_id"))
73+
# Create message with post attached - this ensures persistence
74+
message_obj = Message.objects.create(
75+
room=room,
76+
sender=sender_user,
77+
post=post,
78+
message=data.get("message", f"Shared a {post.post_type}")
79+
)
80+
# Return the complete data for WebSocket broadcast
81+
return {
82+
"id": message_obj.id,
83+
"sender": sender_user.username,
84+
"post_id": post.id,
85+
"post_type": post.post_type,
86+
"caption": post.caption,
87+
"media_url": post.contentUrl.url,
88+
"username": post.userID.username,
89+
"message": data.get("message", f"Shared a {post.post_type}")
90+
}
91+
except PostModel.DoesNotExist:
92+
# Fallback if post doesn't exist
93+
message_obj = Message.objects.create(
94+
room=room,
95+
sender=sender_user,
96+
message=data.get("message", "Shared content")
97+
)
98+
return {"sender": sender_user.username, "message": data.get("message", "Shared content")}
99+
else:
100+
# Regular text message
101+
text = data.get("message")
102+
if text:
103+
message_obj = Message.objects.create(room=room, message=text, sender=sender_user)
104+
return {"sender": sender_user.username, "message": text}
105+
106+
except (Room.DoesNotExist, UserModel.DoesNotExist):
107+
return None
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# Generated by Django 5.2.3 on 2025-09-13 20:04
2+
3+
import django.db.models.deletion
4+
from django.conf import settings
5+
from django.db import migrations, models
6+
7+
8+
class Migration(migrations.Migration):
9+
10+
initial = True
11+
12+
dependencies = [
13+
('posts', '0001_initial'),
14+
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
15+
]
16+
17+
operations = [
18+
migrations.CreateModel(
19+
name='Room',
20+
fields=[
21+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
22+
('room_name', models.CharField(max_length=100, unique=True)),
23+
('chat_type', models.CharField(choices=[('private', 'Private'), ('public', 'Public')], default='public', max_length=10)),
24+
('members', models.ManyToManyField(related_name='chats', to=settings.AUTH_USER_MODEL)),
25+
],
26+
),
27+
migrations.CreateModel(
28+
name='Message',
29+
fields=[
30+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
31+
('message', models.CharField(max_length=255)),
32+
('created_at', models.DateTimeField(auto_now_add=True)),
33+
('post', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='posts.postmodel')),
34+
('sender', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
35+
('room', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='messages', to='chat.room')),
36+
],
37+
),
38+
]
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Generated by Django 5.2.3 on 2025-09-14 17:34
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
('chat', '0001_initial'),
10+
]
11+
12+
operations = [
13+
migrations.AlterField(
14+
model_name='message',
15+
name='message',
16+
field=models.CharField(blank=True, max_length=255, null=True),
17+
),
18+
]

instagram-clone-Django/chat/migrations/__init__.py

Whitespace-only changes.
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
from django.db import models
2+
3+
from posts.models import PostModel
4+
from users.models import UserModel
5+
6+
7+
class Room(models.Model):
8+
CHAT_TYPE_CHOICES = [
9+
('private', 'Private'),
10+
('public', 'Public'),
11+
]
12+
room_name = models.CharField(max_length=100, unique=True)
13+
members = models.ManyToManyField(UserModel, related_name='chats')
14+
chat_type = models.CharField(max_length=10, choices=CHAT_TYPE_CHOICES, default='public')
15+
16+
def __str__(self):
17+
return self.room_name
18+
19+
def can_add_member(self):
20+
if self.chat_type != 'private':
21+
return True
22+
if self.chat_type == 'private' and self.members.count() < 2:
23+
return True
24+
return False
25+
26+
27+
class Message(models.Model):
28+
room = models.ForeignKey(Room, on_delete=models.CASCADE, related_name='messages')
29+
message = models.CharField(max_length=255, blank=True, null=True)
30+
sender = models.ForeignKey(UserModel, on_delete=models.CASCADE)
31+
post = models.ForeignKey(PostModel, null=True, blank=True, on_delete=models.SET_NULL)
32+
created_at = models.DateTimeField(auto_now_add=True)
33+
34+
def __str__(self):
35+
return f'{self.sender} -> {self.room.room_name}'
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
from django.urls import path
2+
from .consumers import ChatConsumer
3+
4+
wsPatterns = [
5+
path("ws/messages/<str:room_name>/", ChatConsumer.as_asgi())
6+
]
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from django.test import TestCase
2+
3+
# Create your tests here.

0 commit comments

Comments
 (0)