# services/validator.py import googlemaps import requests from google import genai from openai import OpenAI class APIValidator: # 1. Google Maps (ID Only = Free) @staticmethod def test_google_maps(api_key: str) -> str: if not api_key: return "⚠️ Please enter a key first." try: gmaps = googlemaps.Client(key=api_key) # 使用 Taipei 101 ID 測試,只請求 ID 欄位 = 免費 Essentials SKU gmaps.place(place_id='ChIJH56c2rarQjQRphD9gvC8BhI', fields=['place_id']) return "✅ Google Maps Key is Valid!" except Exception as e: err = str(e) if "REQUEST_DENIED" in err: return "❌ Invalid Key" return f"❌ Error: {err.split(':')[0]}" # 2. OpenWeather (原本就是 call API 才會驗證,無法避開,但極便宜) @staticmethod def test_openweather(api_key: str) -> str: if not api_key: return "⚠️ Please enter a key first." try: # 隨便查個座標 url = f"https://api.openweathermap.org/data/2.5/weather?lat=25&lon=121&appid={api_key}" resp = requests.get(url, timeout=5) if resp.status_code == 200: return "✅ OpenWeather Key is Valid!" if resp.status_code == 401: return "❌ Invalid Key" return f"❌ Error: {resp.status_code}" except: return "❌ Connection Failed" # 3. LLM (List Models = Free) @staticmethod def test_llm(provider: str, api_key: str, model_id: str = None) -> str: if not api_key: return "⚠️ Please enter a key first." try: if provider == "Gemini": # Google GenAI: 列出模型是免費的管理操作 client = genai.Client(api_key=api_key) # 試著抓取第一個模型就好,不用全部列出來 client.models.list() return "✅ Gemini Key is Valid!" elif provider == "OpenAI": # OpenAI: 列出模型是免費的 client = OpenAI(api_key=api_key) client.models.list() return "✅ OpenAI Key is Valid!" elif provider == "Groq": # Groq: 相容 OpenAI 介面,列出模型也是免費的 client = OpenAI( api_key=api_key, base_url="https://api.groq.com/openai/v1" ) client.models.list() return "✅ Groq Key is Valid!" else: return "⚠️ Unknown Provider" except Exception as e: err = str(e).lower() if "401" in err or "invalid_api_key" in err: return "❌ Invalid Key" if "429" in err: return "❌ Rate Limit Exceeded" # 雖然免費,但如果按太快還是會擋 return f"❌ Error: {str(e)[:20]}..."