from fastapi import FastAPI, HTTPException, Query from fastapi.middleware.cors import CORSMiddleware from fastapi.staticfiles import StaticFiles from typing import Optional import json import os app = FastAPI( title="Naruto API", description="API didática para consulta de personagens, clãs, vilas e informações do universo Naruto.", version="1.0.0" ) # Permite que a API seja consumida por aplicações externas, como React, HTML e JavaScript. app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) BASE_DIR = os.path.dirname(os.path.abspath(__file__)) DATA_PATH = os.path.join(BASE_DIR, "data", "naruto.json") STATIC_PATH = os.path.join(BASE_DIR, "static") # Disponibiliza arquivos estáticos, como imagens dos personagens. app.mount("/static", StaticFiles(directory=STATIC_PATH), name="static") def carregar_dados(): """Carrega os dados do arquivo JSON.""" with open(DATA_PATH, "r", encoding="utf-8") as arquivo: return json.load(arquivo) @app.get("/") def inicio(): return { "mensagem": "Bem-vindo à Naruto API!", "descricao": "API didática para consulta de dados do universo Naruto.", "documentacao": "/docs", "endpoints": { "informacoes_gerais": "/anime", "listar_personagens": "/personagens", "buscar_personagem_por_id": "/personagens/{id}", "buscar_por_nome": "/buscar?q=naruto", "listar_clas": "/clas", "buscar_por_cla": "/clas/Uzumaki", "listar_vilas": "/vilas", "buscar_por_vila": "/vilas/Konoha", "ranking_poder": "/ranking-poder", "estatisticas": "/estatisticas" } } @app.get("/anime") def informacoes_gerais(): dados = carregar_dados() return dados["anime"] @app.get("/personagens") def listar_personagens( cla: Optional[str] = Query(None, description="Filtrar por clã"), vila: Optional[str] = Query(None, description="Filtrar por vila"), tipo: Optional[str] = Query(None, description="Filtrar por tipo: ninja, sensei, ninja médica, vilão etc."), limite: int = Query(20, ge=1, le=100, description="Quantidade máxima de resultados") ): dados = carregar_dados() personagens = dados["personagens"] if cla: personagens = [ p for p in personagens if cla.lower() == p["cla"].lower() ] if vila: personagens = [ p for p in personagens if vila.lower() == p["vila"].lower() ] if tipo: personagens = [ p for p in personagens if tipo.lower() == p["tipo"].lower() ] return { "total": len(personagens[:limite]), "resultados": personagens[:limite] } @app.get("/personagens/{personagem_id}") def buscar_personagem_por_id(personagem_id: int): dados = carregar_dados() for personagem in dados["personagens"]: if personagem["id"] == personagem_id: return personagem raise HTTPException(status_code=404, detail="Personagem não encontrado.") @app.get("/buscar") def buscar_por_nome(q: str = Query(..., min_length=1, description="Nome ou parte do nome do personagem")): dados = carregar_dados() resultado = [ personagem for personagem in dados["personagens"] if q.lower() in personagem["nome"].lower() ] return { "termo_pesquisado": q, "total": len(resultado), "resultados": resultado } @app.get("/clas") def listar_clas(): dados = carregar_dados() clas = sorted( set(personagem["cla"] for personagem in dados["personagens"]) ) return { "total": len(clas), "clas": clas } @app.get("/clas/{cla}") def buscar_por_cla(cla: str): dados = carregar_dados() resultado = [ personagem for personagem in dados["personagens"] if cla.lower() == personagem["cla"].lower() ] if not resultado: raise HTTPException( status_code=404, detail="Nenhum personagem encontrado para este clã." ) return { "cla": cla, "total": len(resultado), "resultados": resultado } @app.get("/vilas") def listar_vilas(): dados = carregar_dados() vilas = sorted( set(personagem["vila"] for personagem in dados["personagens"]) ) return { "total": len(vilas), "vilas": vilas } @app.get("/vilas/{vila}") def buscar_por_vila(vila: str): dados = carregar_dados() resultado = [ personagem for personagem in dados["personagens"] if vila.lower() == personagem["vila"].lower() ] if not resultado: raise HTTPException( status_code=404, detail="Nenhum personagem encontrado para esta vila." ) return { "vila": vila, "total": len(resultado), "resultados": resultado } @app.get("/ranking-poder") def ranking_poder(limite: int = Query(10, ge=1, le=100, description="Quantidade máxima de personagens no ranking")): dados = carregar_dados() ranking = sorted( dados["personagens"], key=lambda personagem: personagem["nivel_poder"], reverse=True ) return { "total": len(ranking[:limite]), "ranking": ranking[:limite] } @app.get("/estatisticas") def estatisticas(): dados = carregar_dados() personagens = dados["personagens"] total_personagens = len(personagens) total_por_vila = {} total_por_cla = {} total_por_tipo = {} for personagem in personagens: vila = personagem["vila"] cla = personagem["cla"] tipo = personagem["tipo"] total_por_vila[vila] = total_por_vila.get(vila, 0) + 1 total_por_cla[cla] = total_por_cla.get(cla, 0) + 1 total_por_tipo[tipo] = total_por_tipo.get(tipo, 0) + 1 return { "total_personagens": total_personagens, "total_por_vila": total_por_vila, "total_por_cla": total_por_cla, "total_por_tipo": total_por_tipo }