211 lines
10 KiB
PHP
211 lines
10 KiB
PHP
<?php
|
|
// growth-engine-api.php v2 — Backend unifié Growth Engine
|
|
// Branche: CRM, Plausible, SearXNG (Dark Scout), Twenty, Ethica, Brain Engine
|
|
header('Content-Type: application/json');
|
|
header('Access-Control-Allow-Origin: *');
|
|
header('Access-Control-Allow-Headers: Content-Type');
|
|
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') { http_response_code(200); exit; }
|
|
|
|
$action = $_GET['action'] ?? '';
|
|
$stateFile = '/opt/wevia-brain/growth-state.json';
|
|
$state = file_exists($stateFile) ? json_decode(file_get_contents($stateFile), true) : [
|
|
'actions_done' => [], 'last_scan' => null, 'proposals' => [],
|
|
'pipeline' => ['ideas'=>12,'planned'=>6,'active'=>3,'signed'=>0],
|
|
'revenue' => 0, 'target' => 1400000, 'leads' => [], 'intel' => []
|
|
];
|
|
|
|
switch ($action) {
|
|
|
|
case 'status':
|
|
$pages = (int)trim(shell_exec("find /var/www/html -maxdepth 2 -name '*.html' 2>/dev/null | wc -l"));
|
|
$apis = (int)trim(shell_exec("find /var/www/html/api -name '*.php' 2>/dev/null | wc -l"));
|
|
$products = (int)trim(shell_exec("ls /var/www/html/products/*.html 2>/dev/null | wc -l"));
|
|
$docker = (int)trim(shell_exec("docker ps -q 2>/dev/null | wc -l"));
|
|
$crons = (int)trim(shell_exec("crontab -l -u www-data 2>/dev/null | grep -cv '^#\|^$'"));
|
|
$ollama = (int)trim(shell_exec("curl -s http://localhost:11435/api/tags 2>/dev/null | python3 -c \"import sys,json;print(len(json.load(sys.stdin).get('models',[])))\" 2>&1"));
|
|
echo json_encode(['state'=>$state,'live'=>compact('pages','apis','products','docker','crons','ollama')+([ 'timestamp'=>date('c')])]);
|
|
break;
|
|
|
|
case 'crm_leads':
|
|
// CRM interne via crm-api.php
|
|
$r = @file_get_contents('https://127.0.0.1/api/crm-api.php?action=stats', false,
|
|
stream_context_create(['http'=>['timeout'=>10,'header'=>"Host: weval-consulting.com\n"],'ssl'=>['verify_peer'=>false,'verify_peer_name'=>false]]));
|
|
$crm = @json_decode($r, true) ?: ['error'=>'CRM unavailable'];
|
|
echo json_encode($crm);
|
|
break;
|
|
|
|
case 'ethica_stats':
|
|
$r = @file_get_contents('https://127.0.0.1/api/ethica-stats.php', false,
|
|
stream_context_create(['http'=>['timeout'=>10,'header'=>"Host: weval-consulting.com\n"],'ssl'=>['verify_peer'=>false,'verify_peer_name'=>false]]));
|
|
echo $r ?: json_encode(['error'=>'Ethica unavailable']);
|
|
break;
|
|
|
|
case 'dark_scout':
|
|
// Veille concurrentielle via SearXNG
|
|
$query = $_GET['q'] ?? $_POST['q'] ?? 'email marketing pharma Maghreb';
|
|
$r = @file_get_contents("http://localhost:8888/search?q=" . urlencode($query) . "&format=json&categories=general&language=fr", false,
|
|
stream_context_create(['http'=>['timeout'=>15]]));
|
|
$data = @json_decode($r, true);
|
|
$results = [];
|
|
foreach (array_slice($data['results'] ?? [], 0, 10) as $res) {
|
|
$results[] = [
|
|
'title' => $res['title'] ?? '',
|
|
'url' => $res['url'] ?? '',
|
|
'content' => substr($res['content'] ?? '', 0, 300),
|
|
'engine' => $res['engine'] ?? ''
|
|
];
|
|
}
|
|
echo json_encode(['query'=>$query,'results'=>$results,'count'=>count($results),'source'=>'searxng']);
|
|
break;
|
|
|
|
case 'seo_audit':
|
|
// SEO quick audit du site
|
|
$url = $_GET['url'] ?? 'https://weval-consulting.com';
|
|
$ch = curl_init($url);
|
|
curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER=>true, CURLOPT_TIMEOUT=>15, CURLOPT_FOLLOWLOCATION=>true,
|
|
CURLOPT_HEADER=>true, CURLOPT_SSL_VERIFYPEER=>false, CURLOPT_USERAGENT=>'WEVAL-SEO-Bot/1.0']);
|
|
$resp = curl_exec($ch);
|
|
$info = curl_getinfo($ch);
|
|
curl_close($ch);
|
|
|
|
$headerSize = $info['header_size'];
|
|
$body = substr($resp, $headerSize);
|
|
|
|
$seo = [
|
|
'url' => $url,
|
|
'http_code' => $info['http_code'],
|
|
'load_time' => round($info['total_time'], 2),
|
|
'size_kb' => round(strlen($body)/1024, 1),
|
|
'has_title' => (bool)preg_match('/<title>([^<]+)/', $body, $m) ? $m[1] : false,
|
|
'has_meta_desc' => (bool)preg_match('/meta.*description.*content="([^"]+)/', $body),
|
|
'has_og_tags' => (bool)preg_match('/og:title/', $body),
|
|
'has_h1' => (bool)preg_match('/<h1/', $body),
|
|
'has_structured_data' => (bool)preg_match('/application\/ld\+json/', $body),
|
|
'has_sitemap' => false,
|
|
'has_robots' => false,
|
|
];
|
|
// Check sitemap
|
|
$sm = @file_get_contents($url . '/sitemap.xml', false, stream_context_create(['http'=>['timeout'=>5],'ssl'=>['verify_peer'=>false]]));
|
|
$seo['has_sitemap'] = $sm && strpos($sm, '<urlset') !== false;
|
|
// Check robots
|
|
$rb = @file_get_contents($url . '/robots.txt', false, stream_context_create(['http'=>['timeout'=>5],'ssl'=>['verify_peer'=>false]]));
|
|
$seo['has_robots'] = $rb && strlen($rb) > 10;
|
|
|
|
$score = 0;
|
|
if ($seo['http_code'] == 200) $score += 15;
|
|
if ($seo['has_title']) $score += 15;
|
|
if ($seo['has_meta_desc']) $score += 15;
|
|
if ($seo['has_og_tags']) $score += 10;
|
|
if ($seo['has_h1']) $score += 10;
|
|
if ($seo['has_structured_data']) $score += 10;
|
|
if ($seo['has_sitemap']) $score += 10;
|
|
if ($seo['has_robots']) $score += 5;
|
|
if ($seo['load_time'] < 3) $score += 10;
|
|
$seo['score'] = $score;
|
|
|
|
echo json_encode($seo);
|
|
break;
|
|
|
|
case 'scan':
|
|
$scan = [
|
|
'pages' => (int)trim(shell_exec("find /var/www/html -maxdepth 2 -name '*.html' 2>/dev/null | wc -l")),
|
|
'apis' => (int)trim(shell_exec("find /var/www/html/api -name '*.php' 2>/dev/null | wc -l")),
|
|
'products' => (int)trim(shell_exec("ls /var/www/html/products/*.html 2>/dev/null | wc -l")),
|
|
'docker' => (int)trim(shell_exec("docker ps -q 2>/dev/null | wc -l")),
|
|
'disk' => trim(shell_exec("df -h / | tail -1 | awk '{print \$5}'")),
|
|
'nonreg' => trim(shell_exec("grep -o '[0-9]*/[0-9]*' /tmp/nonreg-result.txt 2>/dev/null | tail -1")),
|
|
'timestamp' => date('c')
|
|
];
|
|
|
|
// Dark Scout auto-scan: veille concurrentielle
|
|
$queries = ['email marketing pharma Maroc 2026', 'IA souveraine Afrique SaaS', 'API médecins Maghreb healthtech'];
|
|
$intel = [];
|
|
foreach ($queries as $q) {
|
|
$r = @file_get_contents("http://localhost:8888/search?q=" . urlencode($q) . "&format=json&categories=news&language=fr", false,
|
|
stream_context_create(['http'=>['timeout'=>10]]));
|
|
$d = @json_decode($r, true);
|
|
foreach (array_slice($d['results'] ?? [], 0, 3) as $res) {
|
|
$intel[] = ['title'=>$res['title']??'','url'=>$res['url']??'','snippet'=>substr($res['content']??'',0,200),'query'=>$q,'date'=>date('c')];
|
|
}
|
|
}
|
|
|
|
// SEO auto-audit
|
|
$seoR = @file_get_contents('https://127.0.0.1/api/growth-engine-api.php?action=seo_audit', false,
|
|
stream_context_create(['http'=>['timeout'=>15,'header'=>"Host: weval-consulting.com\n"],'ssl'=>['verify_peer'=>false]]));
|
|
$seo = @json_decode($seoR, true);
|
|
|
|
// WEVIA Master proposals
|
|
$ch = curl_init('https://127.0.0.1/api/wevia-master-api.php');
|
|
curl_setopt_array($ch, [CURLOPT_POST=>true,CURLOPT_POSTFIELDS=>json_encode([
|
|
'message'=>"Scan: {$scan['pages']} pages, {$scan['apis']} APIs, {$scan['products']} products, disk {$scan['disk']}. Propose 3 nouvelles opportunites de monetisation innovantes pas encore identifiees. Revenu estime et 2 actions concretes par opportunite.",
|
|
'session'=>'growth-autoscan-'.date('Ymd-H')
|
|
]),CURLOPT_HTTPHEADER=>['Content-Type: application/json','Host: weval-consulting.com'],
|
|
CURLOPT_RETURNTRANSFER=>true,CURLOPT_TIMEOUT=>45,CURLOPT_SSL_VERIFYPEER=>false]);
|
|
$proposals = @json_decode(curl_exec($ch), true);
|
|
curl_close($ch);
|
|
|
|
$state['last_scan'] = date('c');
|
|
$state['intel'] = array_merge($state['intel'] ?? [], $intel);
|
|
$state['intel'] = array_slice($state['intel'], -30); // keep last 30
|
|
$state['proposals'][] = ['date'=>date('c'),'scan'=>$scan,'seo'=>$seo,'proposal'=>$proposals['content']??''];
|
|
$state['proposals'] = array_slice($state['proposals'], -10);
|
|
file_put_contents($stateFile, json_encode($state, JSON_PRETTY_PRINT));
|
|
|
|
echo json_encode(['ok'=>true,'scan'=>$scan,'intel_count'=>count($intel),'seo_score'=>$seo['score']??0,'proposal'=>$proposals['content']??'']);
|
|
break;
|
|
|
|
case 'toggle_action':
|
|
$input = json_decode(file_get_contents('php://input'), true);
|
|
$id = $input['id'] ?? '';
|
|
if ($id) {
|
|
if (in_array($id, $state['actions_done'])) {
|
|
$state['actions_done'] = array_values(array_diff($state['actions_done'], [$id]));
|
|
} else {
|
|
$state['actions_done'][] = $id;
|
|
}
|
|
file_put_contents($stateFile, json_encode($state, JSON_PRETTY_PRINT));
|
|
}
|
|
echo json_encode(['ok'=>true,'done'=>count($state['actions_done'])]);
|
|
break;
|
|
|
|
case 'add_lead':
|
|
$input = json_decode(file_get_contents('php://input'), true);
|
|
$lead = [
|
|
'name' => $input['name'] ?? '',
|
|
'company' => $input['company'] ?? '',
|
|
'email' => $input['email'] ?? '',
|
|
'opportunity' => $input['opportunity'] ?? '',
|
|
'stage' => $input['stage'] ?? 'lead',
|
|
'value' => $input['value'] ?? 0,
|
|
'created' => date('c')
|
|
];
|
|
$state['leads'][] = $lead;
|
|
file_put_contents($stateFile, json_encode($state, JSON_PRETTY_PRINT));
|
|
echo json_encode(['ok'=>true,'lead'=>$lead,'total_leads'=>count($state['leads'])]);
|
|
break;
|
|
|
|
default:
|
|
echo json_encode([
|
|
'name' => 'WEVAL Growth Engine API v2',
|
|
'endpoints' => [
|
|
'GET ?action=status' => 'Dashboard KPIs + live metrics',
|
|
'GET ?action=crm_leads' => 'CRM leads from crm-api.php',
|
|
'GET ?action=ethica_stats' => 'Ethica HCP database stats',
|
|
'GET ?action=dark_scout&q=...' => 'Competitive intelligence via SearXNG',
|
|
'GET ?action=seo_audit&url=...' => 'SEO audit of any URL',
|
|
'GET ?action=scan' => 'Full scan: infra + dark scout + SEO + WEVIA proposals',
|
|
'POST ?action=toggle_action' => 'Toggle action done/undone',
|
|
'POST ?action=add_lead' => 'Add lead to pipeline'
|
|
],
|
|
'connected_services' => [
|
|
'crm' => 'crm-api.php (internal)',
|
|
'twenty' => 'Twenty CRM :3000',
|
|
'plausible' => 'Plausible Analytics :8000',
|
|
'searxng' => 'SearXNG :8888 (Dark Scout)',
|
|
'ethica' => 'ethica-stats.php',
|
|
'wevia_master' => 'wevia-master-api.php (proposals)',
|
|
'brain_engine' => 'Brain Engine (email optimization)'
|
|
]
|
|
]);
|
|
}
|