Files
wevads-platform/scripts/api_provider-manager.php
2026-02-26 04:53:11 +01:00

254 lines
12 KiB
PHP
Executable File

<?php
/**
* Provider Manager API — ALL providers, ALL accounts, ALL features
* Combines: hamid_providers + ia_provider_accounts + factory config
*/
header('Content-Type: application/json');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type');
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') { http_response_code(200); exit; }
$input = json_decode(file_get_contents('php://input'), true) ?: [];
$action = $_GET['action'] ?? $input['action'] ?? 'all_providers';
try {
$pdo = new PDO('pgsql:host=127.0.0.1;dbname=adx_system','admin','admin123');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (Exception $e) { die(json_encode(['error'=>'DB fail'])); }
switch ($action) {
case 'all_providers':
// Merge hamid_providers + ia_provider_accounts into ONE unified list
$hamid = $pdo->query("SELECT provider_name, model, api_url, api_key, is_active, priority,
COALESCE(requests_total,0) as requests_total, last_used, last_error
FROM admin.hamid_providers ORDER BY priority")->fetchAll(PDO::FETCH_ASSOC);
$multi = $pdo->query("SELECT provider_name,
COUNT(*) as total_accounts,
COUNT(*) FILTER (WHERE api_key NOT LIKE '%PENDING%' AND LENGTH(api_key)>10) as real_keys,
COUNT(*) FILTER (WHERE status='active') as active_accounts,
COUNT(*) FILTER (WHERE status='error') as error_accounts,
COUNT(*) FILTER (WHERE api_key LIKE '%PENDING%') as pending_keys,
SUM(COALESCE(requests_total,0)) as total_requests,
MAX(model) as model, MAX(api_url) as api_url, MAX(signup_url) as signup_url, MAX(plan_type) as plan_type
FROM admin.ia_provider_accounts
GROUP BY provider_name ORDER BY provider_name")->fetchAll(PDO::FETCH_ASSOC);
// Build unified map
$all = [];
$hamidMap = [];
foreach ($hamid as $h) {
$hamidMap[$h['provider_name']] = $h;
$all[$h['provider_name']] = [
'name' => $h['provider_name'],
'model' => $h['model'],
'api_url' => $h['api_url'],
'has_key' => !empty($h['api_key']) && strlen($h['api_key']) > 10,
'is_active' => $h['is_active'],
'priority' => $h['priority'],
'requests' => $h['requests_total'],
'last_used' => $h['last_used'],
'last_error' => $h['last_error'],
'source' => 'hamid',
'signup_url' => null,
'plan_type' => 'free',
'multi_accounts' => 0,
'real_keys' => 0,
'pending_keys' => 0,
'active_accounts' => 0
];
}
foreach ($multi as $m) {
$name = $m['provider_name'];
if (isset($all[$name])) {
$all[$name]['multi_accounts'] = (int)$m['total_accounts'];
$all[$name]['real_keys'] = (int)$m['real_keys'];
$all[$name]['pending_keys'] = (int)$m['pending_keys'];
$all[$name]['active_accounts'] = (int)$m['active_accounts'];
$all[$name]['signup_url'] = $m['signup_url'];
$all[$name]['plan_type'] = $m['plan_type'] ?: 'free';
} else {
$all[$name] = [
'name' => $name,
'model' => $m['model'],
'api_url' => $m['api_url'],
'has_key' => (int)$m['real_keys'] > 0,
'is_active' => (int)$m['active_accounts'] > 0,
'priority' => 99,
'requests' => (int)$m['total_requests'],
'last_used' => null,
'last_error' => null,
'source' => 'multi',
'signup_url' => $m['signup_url'],
'plan_type' => $m['plan_type'] ?: 'free',
'multi_accounts' => (int)$m['total_accounts'],
'real_keys' => (int)$m['real_keys'],
'pending_keys' => (int)$m['pending_keys'],
'active_accounts' => (int)$m['active_accounts']
];
}
}
// Sort: active first, then by name
usort($all, function($a, $b) {
if ($a['is_active'] !== $b['is_active']) return $b['is_active'] <=> $a['is_active'];
if ($a['has_key'] !== $b['has_key']) return $b['has_key'] <=> $a['has_key'];
return strcmp($a['name'], $b['name']);
});
$stats = [
'total_providers' => count($all),
'active' => count(array_filter($all, fn($p) => $p['is_active'])),
'with_keys' => count(array_filter($all, fn($p) => $p['has_key'])),
'free' => count(array_filter($all, fn($p) => $p['plan_type'] === 'free')),
'paid' => count(array_filter($all, fn($p) => $p['plan_type'] !== 'free')),
'total_accounts' => array_sum(array_column($all, 'multi_accounts')),
'total_real_keys' => array_sum(array_column($all, 'real_keys')),
'total_pending' => array_sum(array_column($all, 'pending_keys'))
];
echo json_encode(['status'=>'success', 'providers'=>array_values($all), 'stats'=>$stats]);
break;
case 'accounts':
$provider = $_GET['provider'] ?? $input['provider'] ?? '';
if (!$provider) { echo json_encode(['error'=>'provider required']); break; }
$stmt = $pdo->prepare("SELECT ia.id, ia.provider_name, ia.account_email, ia.model,
ia.status, ia.api_key IS NOT NULL AND LENGTH(ia.api_key)>10 AND ia.api_key NOT LIKE '%PENDING%' as has_real_key,
ia.requests_total, ia.tokens_used_today, ia.last_used, ia.last_error, ia.persona_id,
p.first_name, p.last_name
FROM admin.ia_provider_accounts ia
LEFT JOIN admin.personas p ON ia.persona_id = p.id
WHERE ia.provider_name = ? OR ia.provider_name LIKE ?
ORDER BY ia.status DESC, ia.id LIMIT 50");
$stmt->execute([$provider, $provider.'%']);
$accounts = $stmt->fetchAll(PDO::FETCH_ASSOC);
echo json_encode(['status'=>'success', 'provider'=>$provider, 'accounts'=>$accounts, 'count'=>count($accounts)]);
break;
case 'save_key':
$provider = $input['provider'] ?? '';
$key = $input['api_key'] ?? '';
$target = $input['target'] ?? 'hamid'; // hamid or account_id
$accountId = intval($input['account_id'] ?? 0);
if (!$key) { echo json_encode(['error'=>'api_key required']); break; }
$saved = [];
if ($target === 'hamid' && $provider) {
$stmt = $pdo->prepare("UPDATE admin.hamid_providers SET api_key=?, is_active=true, last_error=NULL WHERE provider_name=?");
$stmt->execute([$key, $provider]);
$saved[] = "hamid_providers: $provider";
}
if ($accountId > 0) {
$stmt = $pdo->prepare("UPDATE admin.ia_provider_accounts SET api_key=?, status='active', last_error=NULL WHERE id=?");
$stmt->execute([$key, $accountId]);
$saved[] = "ia_provider_accounts: #$accountId";
}
echo json_encode(['status'=>'success', 'saved'=>$saved]);
break;
case 'test_key':
$provider = $input['provider'] ?? '';
$key = $input['api_key'] ?? '';
$model = $input['model'] ?? '';
$url = $input['api_url'] ?? '';
if (!$key) {
// Try to get key from DB
$row = $pdo->prepare("SELECT api_key, model, api_url FROM admin.hamid_providers WHERE provider_name=? AND api_key IS NOT NULL");
$row->execute([$provider]);
$r = $row->fetch(PDO::FETCH_ASSOC);
if ($r) { $key=$r['api_key']; $model=$model?:$r['model']; $url=$url?:$r['api_url']; }
}
if (!$key) { echo json_encode(['error'=>'No key to test']); break; }
// Build request based on provider
$start = microtime(true);
$ch = curl_init();
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 15);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
if (stripos($provider, 'gemini') !== false) {
curl_setopt($ch, CURLOPT_URL, "https://generativelanguage.googleapis.com/v1beta/models/{$model}:generateContent?key={$key}");
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode(['contents'=>[['parts'=>[['text'=>'say OK']]]],'generationConfig'=>['maxOutputTokens'=>5]]));
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
} elseif (stripos($provider, 'claude') !== false) {
curl_setopt($ch, CURLOPT_URL, $url ?: 'https://api.anthropic.com/v1/messages');
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode(['model'=>$model,'max_tokens'=>5,'messages'=>[['role'=>'user','content'=>'say OK']]]));
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json','x-api-key: '.$key,'anthropic-version: 2023-06-01']);
} elseif (stripos($provider, 'cohere') !== false) {
curl_setopt($ch, CURLOPT_URL, $url ?: 'https://api.cohere.ai/v1/chat');
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode(['model'=>$model,'message'=>'say OK']));
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json','Authorization: Bearer '.$key]);
} else {
curl_setopt($ch, CURLOPT_URL, $url ?: 'https://api.openai.com/v1/chat/completions');
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode(['model'=>$model,'messages'=>[['role'=>'user','content'=>'say OK']],'max_tokens'=>5]));
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json','Authorization: Bearer '.$key]);
}
curl_setopt($ch, CURLOPT_POST, true);
$resp = curl_exec($ch);
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
$latency = round((microtime(true) - $start) * 1000);
$ok = $code === 200;
$data = json_decode($resp, true);
$error = '';
if (!$ok) {
$error = $data['error']['message'] ?? $data['detail'] ?? "HTTP $code";
}
// Update DB status
if ($ok) {
$pdo->prepare("UPDATE admin.hamid_providers SET last_error=NULL, is_active=true WHERE provider_name=?")->execute([$provider]);
} else {
$pdo->prepare("UPDATE admin.hamid_providers SET last_error=?, is_active=false WHERE provider_name=?")->execute([substr($error,0,100), $provider]);
}
echo json_encode(['status'=>$ok?'success':'error', 'provider'=>$provider, 'http_code'=>$code,
'latency_ms'=>$latency, 'error'=>$error, 'response'=>$ok?substr($resp,0,200):'']);
break;
case 'add_to_hamid':
// Add a provider from ia_provider_accounts to hamid_providers
$name = $input['provider_name'] ?? '';
$model = $input['model'] ?? '';
$url = $input['api_url'] ?? '';
$key = $input['api_key'] ?? '';
$priority = intval($input['priority'] ?? 12);
if (!$name) { echo json_encode(['error'=>'provider_name required']); break; }
// Check if already exists
$exists = $pdo->prepare("SELECT id FROM admin.hamid_providers WHERE provider_name=?");
$exists->execute([$name]);
if ($exists->fetch()) {
$pdo->prepare("UPDATE admin.hamid_providers SET model=COALESCE(NULLIF(?,'''),model), api_url=COALESCE(NULLIF(?,'''),api_url), api_key=COALESCE(NULLIF(?,'''),api_key), is_active=true, priority=? WHERE provider_name=?")
->execute([$model, $url, $key, $priority, $name]);
} else {
$pdo->prepare("INSERT INTO admin.hamid_providers (provider_name, model, api_url, api_key, is_active, priority) VALUES (?,?,?,?,true,?)")
->execute([$name, $model, $url, $key, $priority]);
}
echo json_encode(['status'=>'success', 'message'=>"$name added/updated in hamid_providers"]);
break;
case 'test_all':
// Quick connectivity test on all hamid providers with keys
$providers = $pdo->query("SELECT provider_name FROM admin.hamid_providers WHERE api_key IS NOT NULL AND LENGTH(api_key)>10 ORDER BY priority")->fetchAll(PDO::FETCH_COLUMN);
$results = [];
foreach ($providers as $pn) {
// Recursive self-call for test
$r = json_decode(file_get_contents("http://127.0.0.1:{$_SERVER['SERVER_PORT']}/api/provider-manager.php?action=test_key&provider=".urlencode($pn)), true);
$results[] = ['provider'=>$pn, 'ok'=>($r['status']??'')=='success', 'latency'=>$r['latency_ms']??0, 'error'=>$r['error']??''];
}
echo json_encode(['status'=>'success', 'results'=>$results]);
break;
default:
echo json_encode(['error'=>'Unknown action', 'actions'=>['all_providers','accounts','save_key','test_key','add_to_hamid','test_all']]);
}