Spaces:
Running
Running
| """ | |
| Art Providers - Museu, Galeria e Geração de Imagens | |
| """ | |
| import requests | |
| import logging | |
| from typing import Dict, Optional, List | |
| logger = logging.getLogger("ArtProviders") | |
| class ArtProviders: | |
| """Gerencia múltiplos provedores de arte e criatividade""" | |
| API_TIMEOUT = 5.0 | |
| def search_metropolitan_museum(query: str, max_results: int = 5) -> Optional[Dict]: | |
| """ | |
| Busca no acervo do Museu Metropolitano (470k+ obras) | |
| Sem autenticação necessária! | |
| """ | |
| try: | |
| logger.info(f"🖼️ Buscando no Met Museum por '{query}'") | |
| # Busca IDs de objetos | |
| search_url = "https://collectionapi.metmuseum.org/public/collection/v1/search" | |
| search_params = { | |
| "q": query, | |
| "hasImages": "true", | |
| "isPublicDomain": "true" | |
| } | |
| response = requests.get(search_url, params=search_params, timeout=ArtProviders.API_TIMEOUT) | |
| if response.status_code != 200: | |
| logger.warning(f"❌ Met Museum search retornou {response.status_code}") | |
| return None | |
| data = response.json() | |
| object_ids = data.get("objectIDs", [])[:max_results] | |
| if not object_ids: | |
| logger.warning(f"❌ Nenhuma obra encontrada para '{query}'") | |
| return None | |
| # Busca detalhes das obras | |
| obras = [] | |
| for obj_id in object_ids[:max_results]: | |
| try: | |
| obj_url = f"https://collectionapi.metmuseum.org/public/collection/v1/objects/{obj_id}" | |
| obj_response = requests.get(obj_url, timeout=ArtProviders.API_TIMEOUT) | |
| if obj_response.status_code == 200: | |
| obj_data = obj_response.json() | |
| obras.append({ | |
| "titulo": obj_data.get("title", "Desconhecido"), | |
| "artista": obj_data.get("artistDisplayName", "Artista desconhecido"), | |
| "ano": obj_data.get("objectDate", "Data desconhecida"), | |
| "tecnica": obj_data.get("medium", "Técnica desconhecida"), | |
| "url_imagem": obj_data.get("primaryImage"), | |
| "url_met": obj_data.get("objectURL"), | |
| "descricao": obj_data.get("creditLine", ""), | |
| "departamento": obj_data.get("department", "") | |
| }) | |
| except Exception as e: | |
| logger.debug(f"Erro ao buscar objeto {obj_id}: {e}") | |
| continue | |
| return { | |
| "sucesso": True, | |
| "tipo": "museum_search", | |
| "query": query, | |
| "obras": obras, | |
| "total": len(obras), | |
| "fonte": "met_museum" | |
| } | |
| except requests.Timeout: | |
| logger.warning("⏱️ Met Museum timeout") | |
| return None | |
| except Exception as e: | |
| logger.error(f"💥 Erro em Met Museum: {e}") | |
| return None | |
| def generate_with_pollinations(prompt: str, style: str = None) -> Optional[Dict]: | |
| """ | |
| Gera imagem com Pollinations AI (fallback para Flux) | |
| Vantagem: Sem autenticação, resposta direta (binary) | |
| Desvantagem: Menos controle, qualidade variável | |
| """ | |
| try: | |
| logger.info(f"🤖 Gerando imagem com Pollinations AI: {prompt}") | |
| # Pollinations retorna imagem diretamente como URL | |
| # Devemos usar endpoint especial para json | |
| api_url = "https://api.pollinations.ai/v1/images/generations" | |
| payload = { | |
| "prompt": prompt, | |
| "model": "flux", | |
| "width": 1024, | |
| "height": 1024 | |
| } | |
| response = requests.post( | |
| api_url, | |
| json=payload, | |
| timeout=ArtProviders.API_TIMEOUT | |
| ) | |
| if response.status_code != 200: | |
| logger.warning(f"❌ Pollinations retornou {response.status_code}") | |
| return None | |
| data = response.json() | |
| # Pollinations retorna URL da imagem gerada | |
| if "data" in data and len(data["data"]) > 0: | |
| return { | |
| "sucesso": True, | |
| "tipo": "image_generation", | |
| "prompt": prompt, | |
| "url_imagem": data["data"][0].get("url"), | |
| "modelo": "flux", | |
| "fonte": "pollinations_ai" | |
| } | |
| return None | |
| except requests.Timeout: | |
| logger.warning("⏱️ Pollinations timeout") | |
| return None | |
| except Exception as e: | |
| logger.error(f"💥 Erro em Pollinations: {e}") | |
| return None | |
| def generate_simple_ascii_art(theme: str) -> Dict: | |
| """ | |
| Fallback: ASCII art simples | |
| Quando tudo falha, pelo menos retorna algo criativo | |
| """ | |
| ascii_arts = { | |
| "cat": """ | |
| /\\_/\\ | |
| ( o.o ) | |
| > ^ < | |
| /| |\\ | |
| | | | |
| """, | |
| "heart": """ | |
| ❤️ ❤️ ❤️ | |
| ❤️ ❤️ ❤️ | |
| ❤️ ❤️ ❤️ | |
| ❤️ ❤️ | |
| ❤️ ❤️ | |
| ❤️ ❤️ | |
| ❤️ ❤️ | |
| ❤️ ❤️ | |
| ❤️ ❤️ | |
| ❤️ ❤️ | |
| ❤️❤️ | |
| """, | |
| "rocket": """ | |
| /\\ | |
| / \\ | |
| / \\ | |
| /______\\ | |
| | | | |
| /| |\\ | |
| / | | \\ | |
| / |______| \\ | |
| / /\\ \\ | |
| / / \\ \\ | |
| (_/ \\_) | |
| """, | |
| "tree": """ | |
| * | |
| /|\\ | |
| | | |
| /*\\ | |
| / \\ | |
| | | |
| /**\\ | |
| / \\ | |
| | | |
| /***\\ | |
| / \\ | |
| || | |
| /||\\ | |
| /_||_\\ | |
| """ | |
| } | |
| art = ascii_arts.get(theme, ascii_arts["cat"]) | |
| return { | |
| "sucesso": True, | |
| "tipo": "ascii_art", | |
| "tema": theme, | |
| "arte": art, | |
| "fonte": "fallback_ascii" | |
| } | |