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 .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') # Generate 6 digit code for platform access 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 - PROGRAMADOR AI AUTOMATIZADO def generate_game_script(prompt, genre): system_prompt = ( "You are an expert game developer. Create a complete, single-file HTML/JavaScript/CSS game. " "The game MUST be fully functional, self-contained, and playable in a browser iframe. " "Use modern JavaScript (ES6+), HTML5 Canvas, or CSS animations. " "The game MUST have: " "1. A 'Start Game' screen with instructions. " "2. Smooth controls (keyboard or touch). " "3. A scoring system and a 'Game Over' state with a 'Restart' button. " "4. A polished, modern visual style (dark theme preferred). " "5. Responsive design to fit any screen size. " "Return ONLY the raw source code starting with and ending with . " "Do not include any explanations, markdown fences, or text outside the HTML tags." ) user_prompt = f"Develop a complete {genre} game based on this request: {prompt}. Ensure it's a real, playable game." 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') 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. Usando script manual ou vazio.') project = GameProject.objects.create( title=title, prompt=prompt, genre=genre, image_reference=image, script_code=script, config_json={"player": {"speed": 200}, "entities": []} ) messages.success(request, f'Jogo "{title}" criado 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') 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: messages.error(request, 'Falha ao gerar o script com AI.') 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 com sucesso.') 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: 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 de confirmação incorreto.') 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) # Generate 6 digit confirmation code (as requested) conf_code = ''.join(random.choices(string.digits, k=6)) expires = timezone.now() + timedelta(days=option.duration_days) purchase = UserPurchase.objects.create( user_session=user, game=game, rental_option=option, confirmation_code=conf_code, expires_at=expires, is_confirmed=False ) return JsonResponse({ 'success': True, 'purchase_id': purchase.id, 'confirmation_code': conf_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: # Check if user has active purchase 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}'})