You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

170 lines
5.3 KiB

from django.db import models
from django.utils import timezone
from apps.account.models import User, User
from apps.course.models import Course
def chat_upload_path(instance, filename):
"""
Generate upload path for chat attachments
Format: chat/room_{room_id}/YYYY/MM/DD/filename
"""
date = timezone.now()
return f'chat/room_{instance.room_id}/{date.year}/{date.month:02d}/{date.day:02d}/{filename}'
class RoomMessage(models.Model):
class RoomTypeChoices(models.TextChoices):
GROUP = 'group', 'Group'
PRIVATE = 'private', 'Private'
name = models.CharField(
max_length=255,
verbose_name="Room Name"
)
description = models.TextField(
verbose_name="Description",
blank=True,
null=True
)
course = models.ForeignKey(Course,on_delete=models.CASCADE, null=True, blank=True ,related_name="room_messages", verbose_name="Course")
initiator = models.ForeignKey(
User,
on_delete=models.CASCADE,
related_name="initiated_rooms",
verbose_name="Initiator"
)
recipient = models.ForeignKey(
User,
on_delete=models.CASCADE,
related_name="messages_received",
verbose_name="Recipient",
null=True,
blank=True
)
created_at = models.DateTimeField(auto_now_add=True, verbose_name="Created At")
updated_at = models.DateTimeField(
auto_now=True,
verbose_name="Updated At"
)
room_type = models.CharField(
max_length=10,
choices=RoomTypeChoices.choices,
default=RoomTypeChoices.GROUP,
verbose_name="Room Type"
)
unread_messages_count = models.IntegerField(default=0)
def __str__(self):
if self.room_type == self.RoomTypeChoices.GROUP:
return f"Group Room: {self.course.title if self.course else 'N/A'}"
return f"Private Room with {self.recipient}"
class ChatMessage(models.Model):
class ChatTypeChoices(models.TextChoices):
TEXT = 'text', 'Text'
FILE = 'file', 'File'
AUDIO = 'audio', 'Audio'
IMAGE = 'image', 'Image'
room = models.ForeignKey(
RoomMessage,
on_delete=models.CASCADE,
related_name="messages",
verbose_name="Room",
)
sender = models.ForeignKey(
User,
on_delete=models.CASCADE,
related_name="messages_sent",
verbose_name="Sender"
)
content = models.TextField(verbose_name="Message Content")
content_type = models.CharField(
max_length=10,
choices=ChatTypeChoices.choices,
default=ChatTypeChoices.TEXT,
verbose_name="Chat Type"
)
content_size = models.PositiveIntegerField(
verbose_name="Content Size (bytes)",
blank=True,
null=True
)
file_attachment = models.FileField(
upload_to=chat_upload_path,
blank=True,
null=True,
max_length=500,
verbose_name="File Attachment",
help_text="For file and audio messages"
)
image_attachment = models.ImageField(
upload_to=chat_upload_path,
blank=True,
null=True,
max_length=500,
verbose_name="Image Attachment",
help_text="For image messages"
)
is_read = models.BooleanField(default=False, verbose_name="Is Read")
message_metadata = models.JSONField(blank=True, null=True)
sent_at = models.DateTimeField(auto_now_add=True, verbose_name="Sent At")
updated_at = models.DateTimeField(auto_now=True, verbose_name="Updated At")
deleted_at = models.DateTimeField(null=True, blank=True, verbose_name="Deleted At")
is_deleted = models.BooleanField(default=False, verbose_name="Is deleted")
@property
def file_url(self):
"""
Get file URL - works for both old and new messages
For backward compatibility with messages using content field
"""
if self.image_attachment:
return self.image_attachment.url
elif self.file_attachment:
return self.file_attachment.url
elif self.content and self.content_type != 'text':
# Legacy messages with URL in content field
return self.content
return None
def delete(self, *args, **kwargs):
"""Override delete to remove uploaded files"""
if self.file_attachment:
self.file_attachment.delete(save=False)
if self.image_attachment:
self.image_attachment.delete(save=False)
super().delete(*args, **kwargs)
def __str__(self):
return f"Message from {self.sender} in {self.room}"
class MessageReadStatus(models.Model):
user = models.ForeignKey(
User,
on_delete=models.CASCADE,
related_name="read_statuses",
verbose_name="User"
)
message = models.ForeignKey(
ChatMessage,
on_delete=models.CASCADE,
related_name="read_statuses",
verbose_name="Message"
)
is_read = models.BooleanField(default=False, verbose_name="Is Read")
read_at = models.DateTimeField(null=True, blank=True, verbose_name="Read At")
class Meta:
unique_together = ("user", "message") # جلوگیری از ثبت تکراری
def __str__(self):
return f"User {self.user.fullname} read Message {self.message.id}: {self.is_read}"