using System; using System.Linq; using System.Net.Http; using System.Text.Json; using System.Threading.Tasks; namespace Gott.Services { public class GoogleCheckResult { public string Status { get; set; } // "ok", "invalid", "disabled", "error" public string Message { get; set; } public string[] Models { get; set; } } public static class GoogleKeyChecker { public static async Task CheckKeyAsync(IHttpClientFactory httpFactory, string apiKey) { try { var client = httpFactory.CreateClient(); client.Timeout = TimeSpan.FromSeconds(30); // Gemini / Generative Language API – listet verfügbare Modelle var url = "https://generativelanguage.googleapis.com/v1/models?key=" + apiKey; var resp = await client.GetAsync(url); var statusCode = (int)resp.StatusCode; if (statusCode == 400) return new GoogleCheckResult { Status = "invalid", Message = "API-Key ungültig (400)" }; if (statusCode == 403) { // Key gültig, aber Gemini API nicht aktiviert (z.B. Maps-Key) var errorBody = await resp.Content.ReadAsStringAsync(); if (errorBody.Contains("API_KEY_INVALID", StringComparison.OrdinalIgnoreCase)) return new GoogleCheckResult { Status = "invalid", Message = "API-Key ungültig (403)" }; return new GoogleCheckResult { Status = "disabled", Message = "Key gültig, aber Gemini API nicht aktiviert (403)" }; } if (statusCode == 429) return new GoogleCheckResult { Status = "rate_limited", Message = "Rate Limited (429)" }; if (statusCode >= 400) return new GoogleCheckResult { Status = "error", Message = "API-Fehler (" + statusCode + ")" }; // 200 OK → Key gültig + Gemini API aktiv var body = await resp.Content.ReadAsStringAsync(); var doc = JsonDocument.Parse(body); string[] models = Array.Empty(); if (doc.RootElement.TryGetProperty("models", out var modelsArr)) { var interestingPrefixes = new[] { "gemini" }; models = modelsArr.EnumerateArray() .Where(m => m.TryGetProperty("name", out _)) .Select(m => m.GetProperty("name").GetString()) .Where(n => n != null) .Select(n => n.StartsWith("models/", StringComparison.Ordinal) ? n.Substring(7) : n) .Where(n => interestingPrefixes.Any(p => n.StartsWith(p, StringComparison.OrdinalIgnoreCase))) .Distinct() .OrderBy(x => x) .ToArray(); } // Plan-Erkennung string plan; if (models.Any(m => m.Contains("2.5", StringComparison.OrdinalIgnoreCase) || m.Contains("ultra", StringComparison.OrdinalIgnoreCase))) plan = "Premium"; else if (models.Any(m => m.Contains("pro", StringComparison.OrdinalIgnoreCase))) plan = "Standard"; else if (models.Any(m => m.Contains("flash", StringComparison.OrdinalIgnoreCase))) plan = "Basic"; else plan = "Free"; return new GoogleCheckResult { Status = "ok", Message = models.Length + " Gemini-Modelle · " + plan, Models = models }; } catch (Exception ex) { return new GoogleCheckResult { Status = "error", Message = ex.Message }; } } } }