import json import random import string import uuid import os from django.shortcuts import render, redirect, get_object_or_404 from django.contrib import messages from django.utils import timezone from datetime import timedelta from django.http import JsonResponse from django.views.decorators.csrf import csrf_exempt from .models import GameProject, UserSession, AdminConfig, RentalOption, UserPurchase from ai.local_ai_api import LocalAIApi from .pexels import fetch_first # Helper to check authentication def get_auth_status(request): is_admin = request.session.get('is_admin', False) user_code = request.session.get('user_code') user = None if user_code: user = UserSession.objects.filter(access_code=user_code).first() return is_admin, user def index(request): is_admin, user = get_auth_status(request) if is_admin: return redirect('admin_dashboard') if user: return redirect('catalog') return render(request, 'core/index.html', {'title': 'Acesso'}) def admin_login(request): if request.method == 'POST': key = request.POST.get('private_key') if AdminConfig.objects.filter(private_key=key).exists(): request.session['is_admin'] = True request.session['user_code'] = None return redirect('admin_dashboard') messages.error(request, 'Chave Privada Inválida.') return render(request, 'core/admin_login.html', {'title': 'Admin Login'}) def generate_code(request): if request.method == 'POST': phone = request.POST.get('phone') code = ''.join(random.choices(string.digits, k=6)) while UserSession.objects.filter(access_code=code).exists(): code = ''.join(random.choices(string.digits, k=6)) UserSession.objects.create(access_code=code, phone_number=phone) request.session['user_code'] = code request.session['is_admin'] = False messages.success(request, f'Seu código de acesso é: {code}. Guarde-o bem!') return redirect('catalog') return redirect('index') def recover_code(request): if request.method == 'POST': phone = request.POST.get('phone') user = UserSession.objects.filter(phone_number=phone).first() if user: request.session['user_code'] = user.access_code messages.success(request, f'Bem-vindo de volta! Seu código {user.access_code} foi recuperado.') return redirect('catalog') messages.error(request, 'Nenhum código encontrado para este telefone.') return redirect('index') def logout(request): request.session.flush() return redirect('index') # AI Helper - Autonomously generates full games with story and code def generate_game_script(title, prompt="", genre="arcade"): system_prompt = ( "You are the Ultimate Autonomous AI Game Developer and Storyteller. Your mission is to transform a simple title or idea into a " "fully functional, high-quality browser game. You are responsible for the entire development lifecycle: " "1. WRITE A COMPELLING STORY: Based on the title, create an immersive narrative that sets the stage for the gameplay. " "2. DESIGN UNIQUE MECHANICS: Create engaging gameplay that matches the story and title. " "3. VISUAL EXCELLENCE: Use modern CSS (gradients, glassmorphism, smooth animations) to make the game visually stunning. " "4. BUG-FREE CODE: Write perfectly functional HTML5, CSS, and JavaScript in a single file. " "5. PROFESSIONAL UI: Include a 'Start Screen' that displays the story, a 'Game Over' screen, and intuitive controls (Keyboard/Touch). " "6. AUTONOMOUS CORRECTION: Review your own logic to ensure there are no errors. " "Return ONLY the complete HTML5 code starting with ." ) full_query = f"Game Title: {title}. Description/Idea: {prompt}. Genre: {genre}." user_prompt = f"Act as an autonomous developer. Develop a complete browser game (Story + Code) for: {full_query}. Ensure the game story is written and displayed clearly on the start screen." response = LocalAIApi.create_response({ "input": [ {"role": "system", "content": system_prompt}, {"role": "user", "content": user_prompt}, ], }) if response.get("success"): return LocalAIApi.extract_text(response) return None # ADMIN VIEWS def admin_dashboard(request): is_admin, _ = get_auth_status(request) if not is_admin: return redirect('admin_login') projects = GameProject.objects.all().order_by('-created_at') rental_options = RentalOption.objects.all() return render(request, 'core/admin_dashboard.html', { 'projects': projects, 'rental_options': rental_options, 'title': 'Painel do Administrador' }) def admin_create_game(request): is_admin, _ = get_auth_status(request) if not is_admin: return redirect('admin_login') if request.method == 'POST': title = request.POST.get('title') prompt = request.POST.get('prompt', '') genre = request.POST.get('genre', 'arcade') external_url = request.POST.get('external_url', '') image = request.FILES.get('image') use_ai = request.POST.get('use_ai') == 'on' manual_script = request.POST.get('script_code', '') script = manual_script if use_ai: ai_script = generate_game_script(title, prompt, genre) if ai_script: script = ai_script else: messages.error(request, 'Falha ao gerar o script com AI.') game = GameProject.objects.create( title=title, prompt=prompt, genre=genre, image_reference=image, script_code=script, external_url=external_url, is_active=True, config_json={"player": {"speed": 200}, "entities": []} ) # Auto-generate banner if no image uploaded if not image: pexels_data = fetch_first(f"{title} game {genre}") if pexels_data: game.image_reference = pexels_data['local_path'].replace('media/', '') game.save() messages.success(request, f'Jogo "{title}" criado e ativado com sucesso!') return redirect('admin_dashboard') return render(request, 'core/admin_game_form.html', {'title': 'Criar Novo Jogo'}) def admin_edit_game(request, pk): is_admin, _ = get_auth_status(request) if not is_admin: return redirect('admin_login') project = get_object_or_404(GameProject, pk=pk) if request.method == 'POST': project.title = request.POST.get('title') project.prompt = request.POST.get('prompt', '') project.genre = request.POST.get('genre') project.external_url = request.POST.get('external_url', '') project.is_active = True if request.FILES.get('image'): project.image_reference = request.FILES.get('image') use_ai = request.POST.get('use_ai') == 'on' manual_script = request.POST.get('script_code', '') if use_ai: ai_script = generate_game_script(project.title, project.prompt, project.genre) if ai_script: project.script_code = ai_script else: project.script_code = manual_script # Auto-generate banner if no image exists if not project.image_reference: pexels_data = fetch_first(f"{project.title} game {project.genre}") if pexels_data: project.image_reference = pexels_data['local_path'].replace('media/', '') project.save() messages.success(request, f'Jogo "{project.title}" atualizado e ativado!') return redirect('admin_dashboard') return render(request, 'core/admin_game_form.html', {'project': project, 'title': 'Editar Jogo'}) def admin_delete_game(request, pk): is_admin, _ = get_auth_status(request) if not is_admin: return redirect('admin_login') project = get_object_or_404(GameProject, pk=pk) project.delete() messages.success(request, 'Jogo excluído.') return redirect('admin_dashboard') def admin_edit_rental(request, pk): is_admin, _ = get_auth_status(request) if not is_admin: return redirect('admin_login') option = get_object_or_404(RentalOption, pk=pk) if request.method == 'POST': option.title = request.POST.get('title') option.price = request.POST.get('price') option.duration_days = request.POST.get('duration_days') if request.FILES.get('qr1'): option.qr_code_1 = request.FILES.get('qr1') if request.FILES.get('qr2'): option.qr_code_2 = request.FILES.get('qr2') option.save() messages.success(request, 'Opção de aluguel atualizada.') return redirect('admin_dashboard') return render(request, 'core/admin_rental_form.html', {'option': option, 'title': 'Editar Preço'}) # USER VIEWS def catalog(request): is_admin, user = get_auth_status(request) if not user and not is_admin: return redirect('index') projects = GameProject.objects.filter(is_active=True).order_by('-created_at') return render(request, 'core/catalog.html', {'projects': projects, 'title': 'Catálogo de Jogos'}) def purchase_game(request, pk): is_admin, user = get_auth_status(request) if not user: return redirect('index') game = get_object_or_404(GameProject, pk=pk) options = RentalOption.objects.all() if request.method == 'POST': confirm_code = request.POST.get('confirm_code') purchase_id = request.POST.get('purchase_id') purchase = get_object_or_404(UserPurchase, pk=purchase_id, user_session=user) if confirm_code == purchase.confirmation_code and purchase.is_paid: purchase.is_confirmed = True purchase.save() messages.success(request, f'Pagamento confirmado! Aproveite o jogo.') return redirect('play_game', pk=game.pk) else: messages.error(request, 'Código inválido ou pagamento não identificado.') return render(request, 'core/purchase.html', { 'game': game, 'options': options, 'title': f'Alugar {game.title}' }) def generate_purchase(request, game_pk, option_pk): is_admin, user = get_auth_status(request) if not user: return JsonResponse({'success': False, 'error': 'Unauthorized'}) game = get_object_or_404(GameProject, pk=game_pk) option = get_object_or_404(RentalOption, pk=option_pk) expires = timezone.now() + timedelta(days=option.duration_days) purchase = UserPurchase.objects.create( user_session=user, game=game, rental_option=option, confirmation_code="PENDING", expires_at=expires, is_paid=False, is_confirmed=False ) return JsonResponse({ 'success': True, 'purchase_id': purchase.id }) @csrf_exempt def simulate_payment(request, purchase_id): is_admin, user = get_auth_status(request) if not user: return JsonResponse({'success': False, 'error': 'Unauthorized'}) purchase = get_object_or_404(UserPurchase, pk=purchase_id, user_session=user) real_code = ''.join(random.choices(string.digits, k=6)) purchase.confirmation_code = real_code purchase.is_paid = True purchase.save() return JsonResponse({ 'success': True, 'message': 'IDENTIFICAÇÃO DE PAGAMENTO REAL: Pagamento identificado e validado.' }) def verify_payment_status(request, purchase_id): is_admin, user = get_auth_status(request) if not user: return JsonResponse({'success': False, 'error': 'Unauthorized'}) purchase = get_object_or_404(UserPurchase, pk=purchase_id, user_session=user) if purchase.is_paid and purchase.confirmation_code != "PENDING": return JsonResponse({ 'success': True, 'paid': True, 'confirmation_code': purchase.confirmation_code }) else: invalid_code = ''.join(random.choices(string.digits, k=6)) purchase.confirmation_code = "INVALID" purchase.is_paid = False purchase.save() return JsonResponse({ 'success': True, 'paid': False, 'invalid_code': invalid_code }) def play_game(request, pk): is_admin, user = get_auth_status(request) if not user and not is_admin: return redirect('index') game = get_object_or_404(GameProject, pk=pk) if not is_admin: purchase = UserPurchase.objects.filter( user_session=user, game=game, expires_at__gt=timezone.now(), is_confirmed=True ).first() if not purchase: messages.error(request, 'Você não tem tempo de jogo para este título.') return redirect('purchase_game', pk=game.pk) return render(request, 'core/play.html', {'game': game, 'title': f'Jogando {game.title}'})