['timeout'=>5,'ignore_errors'=>true]]); $t0 = microtime(true); $raw = @file_get_contents($url, false, $ctx); $ms = round((microtime(true)-$t0)*1000); if (!$raw) return ['status'=>'dead','ms'=>$ms,'error'=>'no_response']; if (strpos($raw,'Fatal error')!==false) return ['status'=>'php_error','ms'=>$ms,'error'=>'fatal']; if (strpos($raw,'Parse error')!==false) return ['status'=>'php_error','ms'=>$ms,'error'=>'parse']; $json = json_decode($raw, true); if (!$json) return ['status'=>'not_json','ms'=>$ms,'error'=>'invalid_json']; return ['status'=>'ok','ms'=>$ms,'keys'=>array_keys($json)]; } function testDB() { try { $db = new PDO('pgsql:host=localhost;dbname=adx_system','admin','admin123'); $db->exec("SET search_path TO admin,public"); $tables = $db->query("SELECT COUNT(*) FROM information_schema.tables WHERE table_schema='admin'")->fetchColumn(); $size = $db->query("SELECT pg_size_pretty(pg_database_size('adx_system'))")->fetchColumn(); $contacts = $db->query("SELECT COUNT(*) FROM send_contacts")->fetchColumn(); $accounts = $db->query("SELECT COUNT(*) FROM o365_accounts")->fetchColumn(); $offers = $db->query("SELECT COUNT(*) FROM affiliate.offers WHERE status='active'")->fetchColumn(); $personas = $db->query("SELECT COUNT(*) FROM personas")->fetchColumn(); $ia = $db->query("SELECT COUNT(*) FROM ia_provider_accounts")->fetchColumn(); $winners = $db->query("SELECT COUNT(*) FROM brain_winners")->fetchColumn(); $warmup = $db->query("SELECT COUNT(*) FROM warmup_accounts")->fetchColumn(); $kb = $db->query("SELECT COUNT(*) FROM knowledge_base")->fetchColumn(); return [ 'status'=>'connected','tables'=>(int)$tables,'size'=>$size, 'data'=>[ 'contacts'=>(int)$contacts,'o365_accounts'=>(int)$accounts, 'offers'=>(int)$offers,'personas'=>(int)$personas, 'ia_accounts'=>(int)$ia,'brain_winners'=>(int)$winners, 'warmup_accounts'=>(int)$warmup,'knowledge_base'=>(int)$kb ] ]; } catch(Exception $e) { return ['status'=>'error','error'=>$e->getMessage()]; } } function testServers() { $servers = []; // Main server $servers['hetzner'] = ['ip'=>'89.167.40.150','status'=>'online','uptime'=>trim(shell_exec('uptime -p')),'load'=>trim(shell_exec("cat /proc/loadavg | cut -d' ' -f1-3")),'disk'=>trim(shell_exec("df -h / | tail -1 | awk '{print $5}'"))]; // OVH tracking $ovh = @fsockopen('151.80.235.110', 80, $en, $es, 3); $servers['ovh_tracking'] = ['ip'=>'151.80.235.110','status'=>$ovh?'online':'offline','role'=>'tracking']; if($ovh) fclose($ovh); return $servers; } function auditScreens() { $dir = '/opt/wevads-arsenal/public/'; $results = ['total'=>0,'ok'=>0,'issues'=>[]]; foreach(glob($dir.'*.html') as $f) { $bn = basename($f); $sz = filesize($f); $c = file_get_contents($f); $results['total']++; $issues = []; // Raw PHP in body $body = preg_replace('/]*>.*?<\/script>/s', '', $c); if(strpos($body,'0) { $results['issues'][] = ['file'=>$bn,'size'=>$sz,'problems'=>$issues]; } else { $results['ok']++; } } return $results; } function auditAPIs() { $exclude = ['config.php','config-simple.php','db-connect.php','cron-ia-discover.php','tracking-config.php','tracking-standard.php','vault-guard.php','multichannel-bridge.php','brain_unified_send.php','hamid-engine-fixed.php','xc-dashboard-api.php','sentinel-brain.php','sentinel-engine.php']; $apis = glob('/opt/wevads-arsenal/public/api/*.php'); $results = ['total'=>count($apis),'ok'=>0,'errors'=>[],'tested'=>[],'excluded'=>count($exclude)]; foreach($apis as $f) { $bn = basename($f); if(in_array($bn, $exclude)){$results['ok']++;$results['tested'][]=['file'=>$bn,'status'=>'excluded','ms'=>0];continue;} // PHP syntax check $lint = shell_exec("php -l $f 2>&1"); if(strpos($lint,'No syntax errors')===false) { $results['errors'][] = ['file'=>$bn,'type'=>'syntax','detail'=>trim($lint)]; continue; } $t = testAPI($bn); if($t['status']==='ok') { $results['ok']++; } else { $results['errors'][] = ['file'=>$bn,'type'=>$t['status'],'detail'=>$t['error']??'','ms'=>$t['ms']]; } $results['tested'][] = ['file'=>$bn,'status'=>$t['status'],'ms'=>$t['ms']]; } return $results; } function vaultStatus() { $gold = glob('/opt/wevads/vault/*.gold'); return [ 'gold_files'=>count($gold), 'vault_size'=>trim(shell_exec('du -sh /opt/wevads/vault/ 2>/dev/null | cut -f1')), 'last_checksum'=>filemtime('/opt/wevads/vault/checksums.md5') ? date('Y-m-d H:i', filemtime('/opt/wevads/vault/checksums.md5')) : 'never', 'arsenal_html'=>count(glob('/opt/wevads-arsenal/public/*.html')), 'arsenal_api'=>count(glob('/opt/wevads-arsenal/public/api/*.php')), 'synced_html'=>count(glob('/opt/wevads/public/*.html')), 'synced_api'=>count(glob('/opt/wevads/public/api/*.php')) ]; } switch($action) { case 'full_audit': $t0 = microtime(true); $db = testDB(); $servers = testServers(); $screens = auditScreens(); $apis = auditAPIs(); $vault = vaultStatus(); $duration = round((microtime(true)-$t0)*1000); $health = 'EXCELLENT'; $php_errors = array_filter($apis['errors'], function($e){return $e['type']==='php_error'||$e['type']==='syntax';}); if(count($php_errors) > 5 || $screens['ok'] < $screens['total']*0.95) $health = 'DEGRADED'; if($db['status']!=='connected' || count($php_errors) > 15) $health = 'CRITICAL'; echo json_encode([ 'status'=>'success', 'health'=>$health, 'duration_ms'=>$duration, 'timestamp'=>date('c'), 'database'=>$db, 'servers'=>$servers, 'screens'=>$screens, 'apis'=>$apis, 'vault'=>$vault, 'score'=>round(((($apis['total']-count($php_errors))/max(1,$apis['total']))*50)+($screens['ok']/max(1,$screens['total'])*30)+($db['status']==='connected'?20:0),1),'php_errors'=>count($php_errors),'non_critical'=>count($apis['errors'])-count($php_errors) ], JSON_PRETTY_PRINT); break; case 'quick_health': $db = testDB(); echo json_encode([ 'status'=>'success', 'db'=>$db['status'], 'html'=>count(glob('/opt/wevads-arsenal/public/*.html')), 'apis'=>count(glob('/opt/wevads-arsenal/public/api/*.php')), 'gold'=>count(glob('/opt/wevads/vault/*.gold')), 'uptime'=>trim(shell_exec('uptime -p')), 'load'=>trim(shell_exec("cat /proc/loadavg | cut -d' ' -f1-3")) ]); break; case 'test_api': $api = $_GET['api'] ?? ''; $test_action = $_GET['test_action'] ?? 'status'; if(!$api) { echo json_encode(['error'=>'api parameter required']); break; } echo json_encode(testAPI($api, $test_action)); break; case 'sync': // Force full sync arsenal -> public $synced_html = 0; $synced_api = 0; foreach(glob('/opt/wevads-arsenal/public/*.html') as $f) { copy($f, '/opt/wevads/public/'.basename($f)); $synced_html++; } foreach(glob('/opt/wevads-arsenal/public/api/*.php') as $f) { copy($f, '/opt/wevads/public/api/'.basename($f)); $synced_api++; } echo json_encode(['status'=>'success','synced_html'=>$synced_html,'synced_api'=>$synced_api]); break; case 'vault_protect': // Gold all current files $golded = 0; foreach(glob('/opt/wevads-arsenal/public/api/*.php') as $f) { copy($f, '/opt/wevads/vault/api_'.basename($f).'.gold'); $golded++; } foreach(glob('/opt/wevads-arsenal/public/*.html') as $f) { copy($f, '/opt/wevads/vault/'.basename($f).'.gold'); $golded++; } shell_exec('cd /opt/wevads/vault && md5sum *.gold > checksums.md5 2>/dev/null'); echo json_encode(['status'=>'success','golded'=>$golded]); break; default: echo json_encode(['status'=>'success','service'=>'Sentinel Vault Controller','actions'=>['full_audit','quick_health','test_api','sync','vault_protect']]); }