Files
gott/Services/KeyCheckDispatcher.cs
MelekiandClaude Opus 4.6 3e19da4d48 refactor: Backend-Deduplizierung – Parameter-Objekte, Shared Helpers, KeyCheckDispatcher
- ToolDefinitionOptions + ToolExecutionContext ersetzen lange Parameterlisten in ToolService
- AppendToLastMessage-Helper in ChatService eliminiert 5x duplizierte Logik
- OpenAiService: ResolveProviderConfig + BuildApiMessages + ConvertToOpenAiTools statt doppeltem Code
- Tool-Definitionen aus einer Quelle (Anthropic→OpenAI Konvertierung statt hardcodierter Liste)
- KeyCheckDispatcher zentralisiert Key-Check-Dispatch (ApiKeysEndpoint, KeyScanner, GitHubEventScanner)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 08:01:49 +01:00

97 lines
3.7 KiB
C#

using System.Net.Http;
using System.Threading.Tasks;
namespace Gott.Services;
/// <summary>
/// Normalisiertes Key-Check-Ergebnis für alle Provider.
/// Provider-spezifische Details über ProviderResult (cast zum konkreten Typ).
/// </summary>
public class UnifiedKeyCheckResult
{
/// <summary>Normalisierter DB-Status: "valid", "invalid", "rate_limited", "quota_exceeded", "error"</summary>
public string DbStatus { get; set; }
public string Message { get; set; }
public string Plan { get; set; }
public double? Usage7d { get; set; }
public double? Usage5h { get; set; }
/// <summary>Original-Result des Providers (KeyCheckResult, OpenAiCheckResult, etc.)</summary>
public object ProviderResult { get; set; }
}
/// <summary>
/// Zentraler Dispatcher für Key-Checks aller Provider.
/// Normalisiert den Status und gibt ein einheitliches Ergebnis zurück.
/// Eliminiert die wiederholten switch/if-Ketten in ApiKeysEndpoint, KeyScannerService, GitHubEventScannerService.
/// </summary>
public static class KeyCheckDispatcher
{
/// <summary>
/// Prüft einen API-Key anhand des Providers.
/// Provider: "anthropic", "openai", "google", "stripe".
/// Gibt null zurück bei unbekanntem Provider.
/// </summary>
public static async Task<UnifiedKeyCheckResult> CheckByProvider(IHttpClientFactory httpFactory, string provider, string apiKey)
{
switch (provider)
{
case "anthropic":
{
var r = await AnthropicKeyChecker.CheckKeyAsync(httpFactory, apiKey);
return new UnifiedKeyCheckResult
{
DbStatus = (r.Status == "ok" || r.Status == "usage_limited") ? "valid" : r.Status,
Message = r.Message, Plan = r.Plan,
Usage7d = r.Usage7d, Usage5h = r.Usage5h,
ProviderResult = r
};
}
case "openai":
{
var r = await OpenAiKeyChecker.CheckKeyAsync(httpFactory, apiKey);
return new UnifiedKeyCheckResult
{
DbStatus = r.Status == "ok" ? "valid" : r.Status,
Message = r.Message, Plan = r.Message,
ProviderResult = r
};
}
case "google":
{
var r = await GoogleKeyChecker.CheckKeyAsync(httpFactory, apiKey);
return new UnifiedKeyCheckResult
{
DbStatus = r.Status == "ok" ? "valid" : r.Status,
Message = r.Message, Plan = r.Message,
ProviderResult = r
};
}
case "stripe":
{
var r = await StripeKeyChecker.CheckKeyAsync(httpFactory, apiKey);
return new UnifiedKeyCheckResult
{
DbStatus = r.Status == "ok" ? "valid" : r.Status,
Message = r.Message, Plan = r.IsLiveKey ? "Live" : "Test",
ProviderResult = r
};
}
default:
return null;
}
}
/// <summary>
/// Prüft einen API-Key anhand des Key-Typs (z.B. "openai_project", "anthropic_oauth").
/// Nutzt KeyPatterns.GetCheckerProvider() für die Zuordnung.
/// Gibt null zurück wenn kein Checker für den Typ existiert.
/// </summary>
public static Task<UnifiedKeyCheckResult> CheckByKeyType(IHttpClientFactory httpFactory, string keyType, string apiKey)
{
var provider = KeyPatterns.GetCheckerProvider(keyType);
if (provider == null) return Task.FromResult<UnifiedKeyCheckResult>(null);
return CheckByProvider(httpFactory, provider, apiKey);
}
}