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.
 
 
 
 

227 lines
7.5 KiB

from rest_framework import serializers
from apps.support.models import SupportRoom, SupportMessage
from utils import absolute_https_url
class SupportMessageSerializer(serializers.ModelSerializer):
sender_name = serializers.SerializerMethodField()
timestamp_ms = serializers.SerializerMethodField()
class Meta:
model = SupportMessage
fields = (
'id',
'room',
'sender_type',
'sender_name',
'content',
'is_read',
'created_at',
'timestamp_ms',
)
read_only_fields = fields
def get_sender_name(self, obj: SupportMessage) -> str:
if obj.sender_type == SupportMessage.SenderType.SUPPORT:
if obj.sender and obj.sender.fullname:
return obj.sender.fullname
return 'Support Specialist'
if obj.sender and obj.sender.fullname:
return obj.sender.fullname
return 'You'
def get_timestamp_ms(self, obj: SupportMessage) -> int:
if not obj.created_at:
return 0
return int(obj.created_at.timestamp() * 1000)
class SendSupportMessageSerializer(serializers.Serializer):
content = serializers.CharField(
required=True,
allow_blank=False,
max_length=4000,
trim_whitespace=True,
)
class SupportRoomSerializer(serializers.ModelSerializer):
class Meta:
model = SupportRoom
fields = (
'id',
'status',
'unread_by_user',
'last_message_at',
'created_at',
)
read_only_fields = fields
def serialize_admin_chat_user(user, request=None) -> dict:
if not user:
return {
'id': 0,
'email': '',
'fullname': 'Unknown User',
'avatar': '',
'phone_number': '',
'language': '',
'gender': '',
'user_type': 'client',
'is_guest': True,
}
is_guest = getattr(user, 'is_guest', False) or not bool(user.email)
fullname = (user.fullname or '').strip()
if not fullname:
if user.email:
fullname = user.email.split('@')[0]
else:
fullname = f"Guest #{user.id}"
avatar_url = ''
if getattr(user, 'avatar', None):
try:
avatar_url = (
absolute_https_url(user.avatar.url, request)
if request
else user.avatar.url
) or ''
except Exception:
avatar_url = ''
return {
'id': user.id,
'email': user.email or '',
'fullname': fullname,
'avatar': avatar_url,
'phone_number': str(user.phone_number) if getattr(user, 'phone_number', None) else '',
'language': str(user.language) if getattr(user, 'language', None) else '',
'gender': user.gender or '',
'user_type': 'guest' if is_guest else (user.user_type or 'client'),
'is_guest': is_guest,
}
def detect_content_type(content: str) -> str:
if not content:
return 'text'
lower = content.lower().strip()
if lower.startswith(('http://', 'https://', '/media/')):
if any(lower.endswith(ext) for ext in ('.png', '.jpg', '.jpeg', '.gif', '.webp', '.svg')):
return 'image'
if any(lower.endswith(ext) for ext in ('.mp3', '.wav', '.ogg', '.webm', '.m4a')):
return 'audio'
if any(lower.endswith(ext) for ext in ('.mp4', '.mov', '.mkv')):
return 'video'
return 'text'
class AdminSupportMessageSerializer(serializers.ModelSerializer):
room_id = serializers.IntegerField(read_only=True)
sender = serializers.SerializerMethodField()
content_type = serializers.SerializerMethodField()
sent_at = serializers.SerializerMethodField()
updated_at = serializers.SerializerMethodField()
is_deleted = serializers.SerializerMethodField()
class Meta:
model = SupportMessage
fields = (
'id',
'room_id',
'sender_type',
'sender',
'content',
'content_type',
'sent_at',
'updated_at',
'is_read',
'is_deleted',
)
read_only_fields = fields
def get_sender(self, obj: SupportMessage) -> dict:
request = self.context.get('request')
if obj.sender_type == SupportMessage.SenderType.SUPPORT:
sender_user = obj.sender or (request.user if request and request.user.is_authenticated else None)
data = serialize_admin_chat_user(sender_user, request=request)
if not sender_user:
data['fullname'] = 'Support Specialist'
return data
sender_user = obj.sender or (obj.room.user if obj.room_id else None)
return serialize_admin_chat_user(sender_user, request=request)
def get_content_type(self, obj: SupportMessage) -> str:
return detect_content_type(obj.content)
def get_sent_at(self, obj: SupportMessage) -> str:
return obj.created_at.isoformat() if obj.created_at else ''
def get_updated_at(self, obj: SupportMessage) -> str:
return obj.created_at.isoformat() if obj.created_at else ''
def get_is_deleted(self, obj: SupportMessage) -> bool:
return False
class AdminSupportRoomSerializer(serializers.ModelSerializer):
name = serializers.SerializerMethodField()
room_type = serializers.SerializerMethodField()
initiator = serializers.SerializerMethodField()
recipient = serializers.SerializerMethodField()
participants = serializers.SerializerMethodField()
unread_messages_count = serializers.IntegerField(source='unread_by_admin', read_only=True)
last_message = serializers.SerializerMethodField()
class Meta:
model = SupportRoom
fields = (
'id',
'name',
'room_type',
'status',
'initiator',
'recipient',
'participants',
'unread_messages_count',
'last_message',
'created_at',
'updated_at',
)
read_only_fields = fields
def get_name(self, obj: SupportRoom) -> str:
request = self.context.get('request')
user_data = serialize_admin_chat_user(obj.user, request=request)
return user_data['fullname']
def get_room_type(self, obj: SupportRoom) -> str:
return 'private'
def get_initiator(self, obj: SupportRoom) -> dict:
request = self.context.get('request')
return serialize_admin_chat_user(obj.user, request=request)
def get_recipient(self, obj: SupportRoom) -> dict:
request = self.context.get('request')
specialist = obj.assigned_to or (request.user if request and request.user.is_authenticated else None)
return serialize_admin_chat_user(specialist, request=request)
def get_participants(self, obj: SupportRoom) -> list:
return [self.get_initiator(obj), self.get_recipient(obj)]
def get_last_message(self, obj: SupportRoom):
last_msg = getattr(obj, '_prefetched_last_message', None)
if last_msg is None:
last_msg = obj.messages.order_by('-id').first()
if not last_msg:
return None
return {
'id': last_msg.id,
'content': last_msg.content,
'content_type': detect_content_type(last_msg.content),
'sent_at': last_msg.created_at.isoformat() if last_msg.created_at else '',
'sender_type': last_msg.sender_type,
}