mirror of
https://github.com/dartdavros/chatballs.git
synced 2026-10-10 11:25:00 +03:00
123 lines
4.9 KiB
Python
123 lines
4.9 KiB
Python
from django.http import HttpResponse
|
|
from django.views import View
|
|
from rest_framework.permissions import AllowAny
|
|
from rest_framework.request import Request
|
|
from rest_framework.response import Response
|
|
from rest_framework.views import APIView
|
|
|
|
from hub_platform.webchat import services
|
|
from hub_platform.webchat.loader import LOADER_JS
|
|
|
|
|
|
def _origin(request: Request) -> str:
|
|
return request.headers.get("Origin") or request.headers.get("Referer") or ""
|
|
|
|
|
|
def _token(request: Request) -> str:
|
|
auth = request.headers.get("Authorization", "")
|
|
if auth.startswith("Bearer "):
|
|
return auth[7:]
|
|
if request.method == "POST":
|
|
return str(request.data.get("token", ""))
|
|
return request.GET.get("token", "")
|
|
|
|
|
|
class _Public(APIView):
|
|
authentication_classes: list = [] # публичные endpoint'ы: токен сессии, без CSRF/сессии Django
|
|
permission_classes = [AllowAny]
|
|
|
|
|
|
class WebchatConfigView(_Public):
|
|
def get(self, request: Request) -> Response:
|
|
return Response(services.public_config(request.GET.get("channel", ""), _origin(request)))
|
|
|
|
|
|
class WebchatSessionView(_Public):
|
|
def post(self, request: Request) -> Response:
|
|
result = services.issue_session(str(request.data.get("channel", "")))
|
|
if result is None:
|
|
return Response({"detail": "Канал недоступен"}, status=404)
|
|
return Response(result, status=201)
|
|
|
|
|
|
class WebchatMessagesView(_Public):
|
|
def post(self, request: Request) -> Response:
|
|
session = services.resolve_session(_token(request))
|
|
if session is None:
|
|
return Response({"detail": "Сессия не найдена"}, status=401)
|
|
text = str(request.data.get("text", "")).strip()
|
|
if not text:
|
|
return Response({"detail": "Пустое сообщение"}, status=400)
|
|
services.post_message(session, text[:4000])
|
|
return Response({"ok": True}, status=201)
|
|
|
|
def get(self, request: Request) -> Response:
|
|
session = services.resolve_session(_token(request))
|
|
if session is None:
|
|
return Response({"detail": "Сессия не найдена"}, status=401)
|
|
try:
|
|
since = int(request.GET.get("since", "0") or 0)
|
|
except ValueError:
|
|
since = 0
|
|
return Response(services.messages_payload(session, since))
|
|
|
|
|
|
class WebchatContactView(_Public):
|
|
def post(self, request: Request) -> Response:
|
|
session = services.resolve_session(_token(request))
|
|
if session is None:
|
|
return Response({"detail": "Сессия не найдена"}, status=401)
|
|
phone = services.normalize_phone(str(request.data.get("phone", "")))
|
|
if not phone:
|
|
return Response({"detail": "Некорректный номер телефона"}, status=400)
|
|
services.post_contact(session, phone)
|
|
return Response({"ok": True}, status=201)
|
|
|
|
|
|
class WebchatCallOpenView(_Public):
|
|
def post(self, request: Request) -> Response:
|
|
from hub_platform.calls.errors import CallTokenError
|
|
from hub_platform.calls.serializers import ice_servers_payload, public_invite_payload
|
|
from hub_platform.calls.services import open_call_for_identity
|
|
|
|
session = services.resolve_session(_token(request))
|
|
if session is None:
|
|
return Response({"detail": "Сессия не найдена"}, status=401)
|
|
try:
|
|
resolved = open_call_for_identity(identity=session.identity)
|
|
except CallTokenError:
|
|
return Response({"detail": "Активное приглашение не найдено"}, status=404)
|
|
response = Response(
|
|
{
|
|
"call": public_invite_payload(resolved.invite.call_session, resolved.invite.expires_at),
|
|
"accessToken": resolved.customer_access_token,
|
|
"iceServers": ice_servers_payload(),
|
|
}
|
|
)
|
|
response["Cache-Control"] = "no-store"
|
|
return response
|
|
|
|
|
|
class WebchatCallDeclineView(_Public):
|
|
def post(self, request: Request) -> Response:
|
|
from hub_platform.calls.errors import CallConflict, CallTokenError
|
|
from hub_platform.calls.services import decline_call_for_identity
|
|
|
|
session = services.resolve_session(_token(request))
|
|
if session is None:
|
|
return Response({"detail": "Сессия не найдена"}, status=401)
|
|
try:
|
|
decline_call_for_identity(identity=session.identity)
|
|
except CallTokenError:
|
|
return Response({"detail": "Активное приглашение не найдено"}, status=404)
|
|
except CallConflict as error:
|
|
return Response({"detail": str(error)}, status=409)
|
|
return Response({"ok": True})
|
|
|
|
|
|
class WidgetLoaderView(View):
|
|
def get(self, request) -> HttpResponse:
|
|
response = HttpResponse(LOADER_JS, content_type="application/javascript; charset=utf-8")
|
|
response["Cache-Control"] = "public, max-age=300"
|
|
return response
|