import json import requests import threading # 🟢 برای اجرای بک‌گراند from django.conf import settings from django.http import JsonResponse from django.shortcuts import render, get_object_or_404 from django.views.decorators.http import require_http_methods from django.db.models import Q from django.utils.translation import gettext_lazy as _ from apps.chat.models import RoomMessage, ChatMessage from utils.admin import project_admin_site def send_webhook_to_fastapi(room_id, message_data): fastapi_url = f"{getattr(settings, 'FASTAPI_SERVER_URL', 'http://127.0.0.1:8000')}/api/internal/webhook/chat-message/" headers = { "Authorization": getattr(settings, 'INTERNAL_WEBHOOK_SECRET', 'super-secret-key-12345'), "Content-Type": "application/json" } payload = { "room_id": room_id, "message": message_data } try: # با تایم‌اوت 2 ثانیه می‌فرستیم که اگر سرور گیر بود، پروسه متوقف نشود requests.post(fastapi_url, json=payload, headers=headers, timeout=2.0) except Exception as e: print(f"⚠️ Webhook to FastAPI failed: {e}") def live_chat_dashboard_view(request): """رندر کردن اسکلت اصلی صفحه چت""" context = { **project_admin_site.each_context(request), "title": _("Live Support Chat"), } return render(request, "admin/chat/live_chat.html", context) def api_get_rooms(request): """گرفتن لیست روم‌ها بر اساس دسترسی ادمین""" user = request.user # ادمین کل همه روم‌ها رو میبینه، استاد فقط روم‌های خودش رو if user.is_superuser or user.has_role('admin'): rooms = RoomMessage.objects.all().order_by('-updated_at')[:50] else: rooms = RoomMessage.objects.filter( Q(initiator=user) | Q(recipient=user) | Q(course__professor=user) ).distinct().order_by('-updated_at')[:50] data = [] for r in rooms: title = r.name or f"Room #{r.id}" if r.room_type == 'group' and r.course: title = r.course.title data.append({ "id": r.id, "title": title, "type": r.room_type, "unread": r.unread_messages_count, "time": r.updated_at.strftime("%H:%M") if r.updated_at else "" }) return JsonResponse({"rooms": data}) def api_get_messages(request, room_id): """گرفتن پیام‌های یک روم خاص (فقط پیام‌های جدیدتر از last_id)""" last_id = int(request.GET.get('last_id', 0)) room = get_object_or_404(RoomMessage, id=room_id) messages = ChatMessage.objects.filter( room=room, id__gt=last_id, # جادوی پولینگ: فقط آیدی‌های بزرگتر از آخرین پیامی که داریم رو بگیر is_deleted=False ).order_by('id') data = [] for m in messages: avatar = m.sender.avatar.url if getattr(m.sender, 'avatar', None) else None sender_name = m.sender.fullname or m.sender.email or "Unknown" data.append({ "id": m.id, "sender_id": m.sender_id, "sender_name": sender_name, "avatar": avatar, "content": m.content, "type": m.content_type, "file_url": m.file_url, # از پراپرتی مدلت استفاده کردیم "sent_at": m.sent_at.strftime("%H:%M"), "is_me": m.sender_id == request.user.id }) return JsonResponse({"messages": data}) @require_http_methods(["POST"]) def api_send_message(request, room_id): """ارسال پیام جدید از طریق ایجکس (AJAX)""" try: body = json.loads(request.body) content = body.get('content', '').strip() if not content: return JsonResponse({"error": "Empty content"}, status=400) room = get_object_or_404(RoomMessage, id=room_id) # ذخیره در دیتابیس msg = ChatMessage.objects.create( room=room, sender=request.user, content=content, content_type='text' ) # آپدیت کردن زمان روم room.updated_at = msg.sent_at room.save(update_fields=['updated_at']) # 🟢 ساخت ساختار JSON پیام دقیقاً شبیه به چیزی که FastAPI به فرانت می‌فرستد avatar_url = request.user.avatar.url if getattr(request.user, 'avatar', None) else None sender_name = request.user.fullname or request.user.email or "Support" message_data = { "id": msg.id, "room_id": room_id, "sender": { "id": request.user.id, "email": request.user.email, "fullname": sender_name, "user_type": getattr(request.user, 'user_type', 'admin'), "avatar": avatar_url }, "content": msg.content, "content_type": msg.content_type, "content_size": msg.content_size, "sent_at": msg.sent_at.isoformat(), "metadata": msg.message_metadata, "updated_at": None, "is_deleted": False } # 🟢 شلیک به سمت FastAPI در یک Thread جداگانه threading.Thread(target=send_webhook_to_fastapi, args=(room_id, message_data)).start() return JsonResponse({"success": True, "message_id": msg.id}) except Exception as e: return JsonResponse({"error": str(e)}, status=500)