mirror of
https://github.com/pacnpal/thrillwiki_django_no_react.git
synced 2026-02-05 15:55:19 -05:00
140 lines
5.2 KiB
Python
140 lines
5.2 KiB
Python
import logging
|
|
|
|
import requests
|
|
from django.conf import settings
|
|
from django.core.exceptions import ImproperlyConfigured
|
|
from rest_framework import status
|
|
from rest_framework.permissions import IsAuthenticated
|
|
from rest_framework.response import Response
|
|
from rest_framework.views import APIView
|
|
|
|
from apps.core.utils import capture_and_log
|
|
from apps.core.utils.cloudflare import get_direct_upload_url
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class GenerateUploadURLView(APIView):
|
|
permission_classes = [IsAuthenticated]
|
|
|
|
def post(self, request):
|
|
try:
|
|
# Pass user_id for metadata if needed
|
|
result = get_direct_upload_url(user_id=str(request.user.id))
|
|
return Response(result, status=status.HTTP_200_OK)
|
|
except ImproperlyConfigured as e:
|
|
capture_and_log(e, 'Generate upload URL - configuration error', source='api')
|
|
return Response({"detail": "Server configuration error."}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
|
except requests.RequestException as e:
|
|
capture_and_log(e, 'Generate upload URL - Cloudflare API error', source='api')
|
|
return Response({"detail": "Failed to generate upload URL."}, status=status.HTTP_502_BAD_GATEWAY)
|
|
except Exception as e:
|
|
capture_and_log(e, 'Generate upload URL - unexpected error', source='api')
|
|
return Response({"detail": "An unexpected error occurred."}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
|
|
|
|
|
class DeleteImageView(APIView):
|
|
"""
|
|
POST /images/delete/
|
|
Delete an image from Cloudflare Images.
|
|
"""
|
|
|
|
permission_classes = [IsAuthenticated]
|
|
|
|
def post(self, request):
|
|
image_id = request.data.get("image_id")
|
|
|
|
if not image_id:
|
|
return Response(
|
|
{"detail": "image_id is required"},
|
|
status=status.HTTP_400_BAD_REQUEST,
|
|
)
|
|
|
|
try:
|
|
# Get Cloudflare credentials
|
|
account_id = getattr(settings, "CLOUDFLARE_IMAGES_ACCOUNT_ID", None)
|
|
api_token = getattr(settings, "CLOUDFLARE_IMAGES_API_TOKEN", None)
|
|
|
|
if not account_id or not api_token:
|
|
logger.warning("Cloudflare Images not configured, mock deleting image")
|
|
return Response({"success": True, "mock": True})
|
|
|
|
# Delete from Cloudflare
|
|
url = f"https://api.cloudflare.com/client/v4/accounts/{account_id}/images/v1/{image_id}"
|
|
response = requests.delete(
|
|
url,
|
|
headers={"Authorization": f"Bearer {api_token}"},
|
|
timeout=10,
|
|
)
|
|
|
|
if response.status_code in (200, 404): # 404 = already deleted
|
|
return Response({"success": True})
|
|
else:
|
|
logger.error(f"Cloudflare delete failed: {response.text}")
|
|
return Response(
|
|
{"detail": "Failed to delete image"},
|
|
status=status.HTTP_502_BAD_GATEWAY,
|
|
)
|
|
|
|
except requests.RequestException as e:
|
|
capture_and_log(e, "Delete image - Cloudflare API error", source="api")
|
|
return Response(
|
|
{"detail": "Failed to delete image"},
|
|
status=status.HTTP_502_BAD_GATEWAY,
|
|
)
|
|
except Exception as e:
|
|
capture_and_log(e, "Delete image - unexpected error", source="api")
|
|
return Response(
|
|
{"detail": "An unexpected error occurred"},
|
|
status=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
)
|
|
|
|
|
|
class GenerateOGImageView(APIView):
|
|
"""
|
|
POST /images/og-image/
|
|
Generate an Open Graph image for social sharing.
|
|
"""
|
|
|
|
permission_classes = [] # Public endpoint
|
|
|
|
def post(self, request):
|
|
title = request.data.get("title", "")
|
|
description = request.data.get("description", "")
|
|
entity_type = request.data.get("entity_type", "")
|
|
image_url = request.data.get("image_url", "")
|
|
|
|
if not title:
|
|
return Response(
|
|
{"detail": "title is required"},
|
|
status=status.HTTP_400_BAD_REQUEST,
|
|
)
|
|
|
|
try:
|
|
# This is a placeholder for OG image generation
|
|
# In production, you would:
|
|
# 1. Use an image generation service (Cloudinary, imgix, etc.)
|
|
# 2. Or use a headless browser service (Puppeteer, Playwright)
|
|
# 3. Or use a dedicated OG image service
|
|
|
|
# For now, return a template URL or placeholder
|
|
base_url = getattr(settings, "SITE_URL", "https://thrillwiki.com")
|
|
og_image_url = f"{base_url}/api/v1/images/og-preview/?title={title[:100]}"
|
|
|
|
return Response({
|
|
"success": True,
|
|
"og_image_url": og_image_url,
|
|
"title": title,
|
|
"description": description[:200] if description else "",
|
|
"entity_type": entity_type,
|
|
"note": "Placeholder - configure OG image service for production",
|
|
})
|
|
|
|
except Exception as e:
|
|
capture_and_log(e, "Generate OG image", source="api")
|
|
return Response(
|
|
{"detail": str(e)},
|
|
status=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
)
|
|
|