import json import random import string import uuid 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 # 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 - Refined for better functional games def generate_game_script(prompt, genre): system_prompt = ( "You are an Advanced AI Game Programmer. Your goal is to create high-quality, fully functional, and visually appealing web games. " "The game MUST be a single-file HTML (including CSS and JS) that works perfectly in an iframe. " "Features to include: " "1. A polished Start Screen with a 'Play' button. " "2. Score tracking and a Game Over screen with a 'Restart' button. " "3. Mobile-friendly touch controls and desktop keyboard support. " "4. Vibrant, modern aesthetics using CSS gradients and clean shapes. " "5. Fluid animations and sound effects simulation (visual feedback). " "Return ONLY the source code starting with ." ) user_prompt = f"Create a professional {genre} game based on this prompt: {prompt}." 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', 'platformer') 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 and prompt: ai_script = generate_game_script(prompt, genre) if ai_script: script = ai_script else: messages.error(request, 'Falha ao gerar o script com AI.') GameProject.objects.create( title=title, prompt=prompt, genre=genre, image_reference=image, script_code=script, external_url=external_url, config_json={"player": {"speed": 200}, "entities": []} ) messages.success(request, f'Jogo "{title}" criado!') 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', '') 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 and project.prompt: ai_script = generate_game_script(project.prompt, project.genre) if ai_script: project.script_code = ai_script else: project.script_code = manual_script project.save() messages.success(request, f'Jogo "{project.title}" atualizado!') 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) # Code is initially None or a placeholder; will be set when "payment detected" 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): """ Simulates the intelligent anti-fraud system detecting a real payment. In a real scenario, this would be an endpoint called by a payment webhook. """ 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) # Intelligent System: Generates the real code ONLY when payment is successful 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': 'SISTEMA INTELIGENTE: Pagamento identificado e validado.' }) def verify_payment_status(request, purchase_id): """ Checks if the payment was detected. Returns the real code if paid, or an invalid random code if fraud/timeout. """ 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: # Anti-fraud logic: Generate a completely random invalid code invalid_code = ''.join(random.choices(string.digits, k=6)) # Reset the purchase state to allow retry 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}'})