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.
225 lines
7.4 KiB
225 lines
7.4 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:
|
|
return 'Islamic Scholar'
|
|
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,
|
|
}
|