Files
weval-consulting/api/wevads-p1-api.php
2026-04-08 21:10:02 +02:00

146 lines
8.9 KiB
PHP

<?php
header('Content-Type: application/json; charset=utf-8');
header('Access-Control-Allow-Origin: *');
$token = $_GET['token'] ?? $_POST['token'] ?? '';
if (!in_array($token, ['WEVADS2026','ETHICA_API_2026_SECURE'])) die(json_encode(['error'=>'auth']));
$action = $_GET['action'] ?? '';
// S95 DB
function s95db() {
static $pdo;
if (!$pdo) $pdo = new PDO("pgsql:host=10.1.0.3;port=5432;dbname=adx_system", "admin", "admin123");
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
return $pdo;
}
function qa($db,$q){$r=$db->query($q);return $r?$r->fetchAll(PDO::FETCH_ASSOC):[];}
function q1($db,$q){$r=$db->query($q);return $r?$r->fetch(PDO::FETCH_ASSOC):null;}
function ok($d){echo json_encode(array_merge(['ok'=>1],$d));exit;}
function err($m){echo json_encode(['error'=>$m]);exit;}
switch($action) {
// ═══════════════════════════════════════
// MODULE 1: SCRAPING CONTROL (international)
// ═══════════════════════════════════════
case 'scrapers':
$db = s95db();
// Ethica scraper stats
$ethica_total = (int)q1($db,"SELECT COUNT(*) as c FROM ethica.medecins_validated")['c'];
$ethica_emails = (int)q1($db,"SELECT COUNT(*) as c FROM ethica.medecins_validated WHERE email IS NOT NULL AND email!=''")['c'];
// WEVAL leads
$weval_leads = 0; try{$weval_leads=(int)q1($db,"SELECT COUNT(*) as c FROM admin.weval_leads")['c'];}catch(Exception $e){}
$linkedin = 0; try{$linkedin=(int)q1($db,"SELECT COUNT(*) as c FROM admin.linkedin_profiles")['c'];}catch(Exception $e){}
$companies = 0; try{$companies=(int)q1($db,"SELECT COUNT(*) as c FROM admin.pipeline_companies")['c'];}catch(Exception $e){}
$harvested = 0; try{$harvested=(int)q1($db,"SELECT COUNT(*) as c FROM admin.harvested_leads")['c'];}catch(Exception $e){}
$contacts = 0; try{$contacts=(int)q1($db,"SELECT COUNT(*) as c FROM admin.send_contacts")['c'];}catch(Exception $e){}
// Scraper log
$logs = []; try{$logs=qa($db,"SELECT source, status, records_found, created_at FROM ethica.scraping_log ORDER BY created_at DESC LIMIT 20");}catch(Exception $e){}
// Read cron logs timestamps
$cron_status = [];
$log_files = [
['name'=>'Ethica Master','file'=>'/var/log/ethica-autonomous.log','server'=>'S95','type'=>'HCP'],
['name'=>'1Sante Deep','file'=>'/var/log/ethica-1sante-deep.log','server'=>'S95','type'=>'HCP'],
['name'=>'DabaDoc MA','file'=>'/var/log/ethica-dabadoc-ma.log','server'=>'S95','type'=>'HCP'],
['name'=>'DabaDoc TN','file'=>'/var/log/ethica-dabadoc-tn.log','server'=>'S95','type'=>'HCP'],
['name'=>'GMap MA','file'=>'/var/log/ethica-gmap-ma.log','server'=>'S95','type'=>'HCP'],
['name'=>'GMap TN','file'=>'/var/log/ethica-gmap-tn.log','server'=>'S95','type'=>'HCP'],
['name'=>'Email Drip','file'=>'/var/log/ethica-email-drip.log','server'=>'S95','type'=>'enrichment'],
['name'=>'Email Enricher','file'=>'/var/log/ethica-enricher-auto.log','server'=>'S95','type'=>'enrichment'],
['name'=>'LinkedIn Drip','file'=>'/var/log/linkedin-scrape.log','server'=>'S95','type'=>'B2B'],
['name'=>'Ville Enricher','file'=>'/var/log/ethica-ville-enrich.log','server'=>'S95','type'=>'enrichment'],
['name'=>'Scraper Engine','file'=>'/var/log/wevads/scraper-engine.log','server'=>'S95','type'=>'OSINT'],
];
foreach($log_files as &$lf) {
$ts = @filemtime($lf['file']); $lf['last_run'] = $ts ? date('Y-m-d H:i', $ts) : null;
$lf['active'] = $ts && (time()-$ts < 7200);
$last = @trim(shell_exec("tail -1 ".escapeshellarg($lf['file'])." 2>/dev/null"));
$lf['last_line'] = substr($last, 0, 100);
}
ok([
'sources' => [
['name'=>'HCP Database','table'=>'ethica.medecins_validated','count'=>$ethica_total,'emails'=>$ethica_emails,'type'=>'pharma','server'=>'S95'],
['name'=>'WEVAL Leads','table'=>'admin.weval_leads','count'=>$weval_leads,'type'=>'B2B','server'=>'S95'],
['name'=>'LinkedIn Profiles','table'=>'admin.linkedin_profiles','count'=>$linkedin,'type'=>'B2B','server'=>'S95'],
['name'=>'Companies','table'=>'admin.pipeline_companies','count'=>$companies,'type'=>'B2B','server'=>'S95'],
['name'=>'Harvested Leads','table'=>'admin.harvested_leads','count'=>$harvested,'type'=>'OSINT','server'=>'S95'],
['name'=>'Send Contacts','table'=>'admin.send_contacts','count'=>$contacts,'type'=>'all','server'=>'S95'],
],
'total_records' => $ethica_total + $weval_leads + $linkedin + $companies + $harvested,
'scrapers' => $log_files,
'recent_logs' => $logs,
'crons' => ['s95_ethica'=>17,'s95_wevads'=>8,'s204'=>11,'total'=>36]
]);
break;
// ═══════════════════════════════════════
// MODULE 2: CONSENT MANAGEMENT (international GDPR)
// ═══════════════════════════════════════
case 'consent':
$db = s95db();
$tokens = 0; try{$tokens=(int)q1($db,"SELECT COUNT(*) as c FROM ethica.consent_tokens")['c'];}catch(Exception $e){}
$logs_cnt = 0; try{$logs_cnt=(int)q1($db,"SELECT COUNT(*) as c FROM ethica.consent_log")['c'];}catch(Exception $e){}
$opted_in = 0; try{$opted_in=(int)q1($db,"SELECT COUNT(*) as c FROM ethica.consent_tokens WHERE status='accepted'")['c'];}catch(Exception $e){}
$opted_out = 0; try{$opted_out=(int)q1($db,"SELECT COUNT(*) as c FROM ethica.consent_tokens WHERE status='rejected'")['c'];}catch(Exception $e){}
$pending = 0; try{$pending=(int)q1($db,"SELECT COUNT(*) as c FROM ethica.consent_tokens WHERE status='pending' OR status IS NULL")['c'];}catch(Exception $e){}
$recent = []; try{$recent=qa($db,"SELECT email, action, method, created_at FROM ethica.consent_log ORDER BY created_at DESC LIMIT 20");}catch(Exception $e){}
// Suppression requests
$unsubs = 0; try{$unsubs=(int)q1($db,"SELECT COUNT(*) as c FROM tracking_events WHERE event_type='unsub'")['c'];}catch(Exception $e){}
ok([
'total_tokens' => $tokens,
'total_logs' => $logs_cnt,
'opted_in' => $opted_in,
'opted_out' => $opted_out,
'pending' => $pending,
'unsub_requests' => $unsubs,
'consent_rate' => $tokens > 0 ? round(($opted_in / max($tokens,1)) * 100, 1) : 0,
'recent_activity' => $recent,
'consent_url' => 'https://consent.wevup.app',
'gdpr_compliant' => true,
'regions' => ['MA','TN','DZ','FR','EU']
]);
break;
// ═══════════════════════════════════════
// MODULE 3: BOUNCE MANAGER (ISP-level)
// ═══════════════════════════════════════
case 'bounces':
$db = s95db();
$total = 0; try{$total=(int)q1($db,"SELECT COUNT(*) as c FROM admin.bounces")['c'];}catch(Exception $e){}
$hard = 0; try{$hard=(int)q1($db,"SELECT COUNT(*) as c FROM admin.bounces WHERE type='hard'")['c'];}catch(Exception $e){}
$soft = 0; try{$soft=(int)q1($db,"SELECT COUNT(*) as c FROM admin.bounces WHERE type='soft'")['c'];}catch(Exception $e){}
$recent_7d = 0; try{$recent_7d=(int)q1($db,"SELECT COUNT(*) as c FROM admin.bounces WHERE created_at > NOW()-INTERVAL '7 days'")['c'];}catch(Exception $e){}
// ISP breakdown
$by_isp = []; try{$by_isp=qa($db,"SELECT CASE
WHEN email LIKE '%gmail%' THEN 'Gmail'
WHEN email LIKE '%hotmail%' OR email LIKE '%outlook%' OR email LIKE '%live.%' THEN 'Microsoft'
WHEN email LIKE '%yahoo%' OR email LIKE '%ymail%' THEN 'Yahoo'
WHEN email LIKE '%orange%' OR email LIKE '%wanadoo%' THEN 'Orange'
WHEN email LIKE '%free.fr%' THEN 'Free'
WHEN email LIKE '%sfr%' THEN 'SFR'
WHEN email LIKE '%gmx%' THEN 'GMX'
WHEN email LIKE '%proton%' THEN 'Proton'
WHEN email LIKE '%icloud%' OR email LIKE '%me.com%' THEN 'Apple'
WHEN email LIKE '%aol%' THEN 'AOL'
ELSE 'Other'
END as isp, type, COUNT(*) as cnt FROM admin.bounces GROUP BY 1,2 ORDER BY cnt DESC");}catch(Exception $e){}
// Recent bounces
$recent = []; try{$recent=qa($db,"SELECT email, type, reason, created_at FROM admin.bounces ORDER BY created_at DESC LIMIT 20");}catch(Exception $e){}
// Bounce rate
$sent_total = 0; try{$sent_total=(int)q1($db,"SELECT COUNT(*) as c FROM admin.graph_send_log")['c'];}catch(Exception $e){}
ok([
'total' => $total,
'hard' => $hard,
'soft' => $soft,
'recent_7d' => $recent_7d,
'bounce_rate' => $sent_total > 0 ? round(($total / max($sent_total,1)) * 100, 2) : 0,
'by_isp' => $by_isp,
'recent' => $recent,
'sent_total' => $sent_total,
'suppression_list_size' => $hard
]);
break;
default:
ok(['actions'=>['scrapers','consent','bounces']]);
}