38461-vm/core/views.py

222 lines
9.1 KiB
Python

import os
import json
from functools import wraps
from django.shortcuts import render, get_object_or_404, redirect
from django.utils import timezone
from django.contrib import messages
from django.http import JsonResponse
from .models import Project, PipelineStep, CgiAsset, StudioConfig, Scene
from ai.local_ai_api import LocalAIApi
from .pexels import fetch_first
def studio_admin_required(view_func):
"""Decorator to restrict access to studio admin only."""
@wraps(view_func)
def _wrapped_view(request, *args, **kwargs):
if not request.session.get('is_studio_admin', False):
messages.warning(request, "Acesso restrito. Por favor, insira sua chave de administrador.")
return redirect('admin_login')
return view_func(request, *args, **kwargs)
return _wrapped_view
def home(request):
"""Render the CGI Studio Command Center."""
config, created = StudioConfig.objects.get_or_create(id=1)
if created or not config.admin_access_key:
config.save()
projects = Project.objects.prefetch_related('steps').all().order_by('-created_at')
total_projects = projects.count()
active_productions = projects.filter(status='PROD').count()
completed_projects = projects.filter(status='DONE').count()
context = {
"projects": projects,
"total_projects": total_projects,
"active_productions": active_productions,
"completed_projects": completed_projects,
"current_time": timezone.now(),
"is_admin": request.session.get('is_studio_admin', False),
}
return render(request, "core/index.html", context)
@studio_admin_required
def studio_ai(request):
"""Page to configure and launch AI-automated productions."""
return render(request, "core/studio_ai.html")
@studio_admin_required
def generate_production(request):
"""AI logic to create a full SUPER PRODUCTION automatically."""
if request.method == "POST":
category = request.POST.get("category", "Sci-Fi")
proj_type = request.POST.get("project_type", "MOVIE")
theme = request.POST.get("theme", "Future of humanity")
prompt = f"""
Create a detailed SUPER PRODUCTION plan for a {proj_type} in the {category} category.
Theme: {theme}
Requirements:
1. Unique Title and a compelling description.
2. A full cinematic screenplay (script) for the entire production, ready to be read.
3. A short query (2-4 words) for a cinematic visual image representing this production.
4. 3 Main Characters with names and detailed physical descriptions (based on REAL humans/actors style).
5. 8 Key Scenes with titles, narrative descriptions, and a unique 'visual_query' (2-4 words) for each scene.
6. Metadata: Estimated budget (e.g., $200M), Age Rating (e.g., PG-13, R), and Duration (e.g., 140 min).
Return the result ONLY in JSON format with the following structure:
{{
"title": "...",
"description": "...",
"full_script": "...",
"thumbnail_query": "...",
"budget": "...",
"rating": "...",
"duration": "...",
"characters": [
{{"name": "...", "description": "...", "type": "CHAR"}}
],
"scenes": [
{{"title": "...", "description": "...", "visual_query": "..."}}
]
}}
"""
response = LocalAIApi.create_response({
"input": [
{"role": "system", "content": "You are an expert Hollywood Producer and AI Cinema Director specialized in Super Productions."},
{"role": "user", "content": prompt},
],
"text": {"format": {"type": "json_object"}},
})
if response.get("success"):
try:
data = LocalAIApi.decode_json_from_response(response)
# Fetch thumbnail from Pexels
thumbnail_data = fetch_first(data.get('thumbnail_query', data['title']))
thumbnail_url = ""
if thumbnail_data:
thumbnail_url = thumbnail_data['local_path']
# Create the Project
project = Project.objects.create(
title=data['title'],
project_type=proj_type,
category=category,
description=data['description'],
full_script=data.get('full_script', ''),
thumbnail_url=thumbnail_url,
is_ai_generated=True,
status='DONE',
estimated_budget=data.get('budget', '$150M'),
rating=data.get('rating', 'PG-13'),
duration=data.get('duration', '120 min')
)
# Create default Pipeline Steps
stages = [s[0] for s in PipelineStep.STAGES]
for stage in stages:
PipelineStep.objects.create(project=project, name=stage, progress=100, is_completed=True)
# Create Characters (Assets)
for char in data['characters']:
CgiAsset.objects.create(
project=project,
name=char['name'],
asset_type='CHAR',
physical_description=char['description']
)
# Create Scenes and fetch images
for i, scene_data in enumerate(data['scenes']):
scene_image_url = ""
# Fetch image for EACH scene
v_query = scene_data.get('visual_query', scene_data['title'])
scene_img_data = fetch_first(f"{data['title']} {v_query}", orientation="landscape")
if scene_img_data:
scene_image_url = scene_img_data['local_path']
Scene.objects.create(
project=project,
number=i+1,
title=scene_data['title'],
description=scene_data['description'],
visual_prompt=scene_data.get('visual_query', ''),
image_url=scene_image_url
)
messages.success(request, f"Super Produção '{project.title}' criada e salva na Biblioteca!")
return redirect('production_library')
except Exception as e:
messages.error(request, f"Erro ao processar resposta da AI: {str(e)}")
else:
messages.error(request, f"Erro na API de IA: {response.get('error')}")
return redirect('studio_ai')
@studio_admin_required
def production_library(request):
"""View to see all completed AI productions."""
productions = Project.objects.filter(is_ai_generated=True).order_by('-created_at')
return render(request, "core/production_library.html", {"productions": productions})
@studio_admin_required
def watch_production(request, slug):
"""View to 'watch' (read and experience) a complete production."""
project = get_object_or_404(Project.objects.prefetch_related('assets', 'scenes'), slug=slug)
return render(request, "core/watch_production.html", {"project": project})
def admin_login(request):
"""View to enter the unique admin access key."""
if request.method == "POST":
key = request.POST.get("access_key")
try:
config = StudioConfig.objects.get(id=1)
if key == config.admin_access_key:
request.session['is_studio_admin'] = True
messages.success(request, "Bem-vindo, Comandante do Estúdio!")
return redirect('home')
else:
messages.error(request, "Chave de acesso inválida.")
except StudioConfig.DoesNotExist:
messages.error(request, "Configuração do estúdio não encontrada.")
return render(request, "core/admin_login.html")
def admin_logout(request):
"""Logout the studio admin."""
request.session['is_studio_admin'] = False
return redirect('home')
@studio_admin_required
def asset_library(request):
"""View all digital assets (Characters, Props, Environments)."""
assets = CgiAsset.objects.select_related('project').all()
asset_types = {
'CHAR': assets.filter(asset_type='CHAR'),
'PROP': assets.filter(asset_type='PROP'),
'ENV': assets.filter(asset_type='ENV'),
}
context = {
"assets": assets,
"asset_types": asset_types,
}
return render(request, "core/asset_library.html", context)
def project_detail(request, slug):
"""Render the detailed pipeline for a specific production."""
project = get_object_or_404(Project.objects.prefetch_related('steps', 'assets', 'scenes'), slug=slug)
context = {
"project": project,
"steps": project.steps.all(),
"assets": project.assets.all(),
"scenes": project.scenes.all(),
}
return render(request, "core/project_detail.html", context)