100 lines
18 KiB
PHP
100 lines
18 KiB
PHP
<?php
|
|
require_once('/opt/wevads/config/credentials.php');
|
|
try{$pdo=get_pdo('adx_system');$pdo->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);}catch(PDOException $e){die("DB Error: ".$e->getMessage());}
|
|
function gc($p,$q){try{return $p->query($q)->fetchColumn()?:0;}catch(Exception $e){return 0;}}
|
|
function ga($p,$q){try{return $p->query($q)->fetchAll(PDO::FETCH_ASSOC)?:[];}catch(Exception $e){return[];}}
|
|
$knownMethods=[
|
|
['id'=>'O365_SMTP','name'=>'Office 365 SMTP','icon'=>'📧','category'=>'Microsoft','description'=>'SMTP smtp.office365.com:587','requires'=>['o365_account'],'best_for'=>['Gmail','Outlook','Yahoo'],'cost_per_1k'=>0.50,'capacity'=>'50k/j','reliability'=>95],
|
|
['id'=>'O365_RELAY','name'=>'Office 365 Relay','icon'=>'🔄','category'=>'Microsoft','description'=>'PMTA route *.onmicrosoft.com','requires'=>['o365_domain','pmta'],'best_for'=>['Gmail','Outlook','GMX'],'cost_per_1k'=>0.45,'capacity'=>'100k/j','reliability'=>97],
|
|
['id'=>'O365_EXCHANGE','name'=>'O365+Exchange Headers','icon'=>'🏢','category'=>'Microsoft','description'=>'Headers Exchange sans X-Mailer (97% inbox)','requires'=>['o365_domain'],'best_for'=>['T-Online','GMX','Web.de'],'cost_per_1k'=>0.55,'capacity'=>'80k/j','reliability'=>98],
|
|
['id'=>'GSUITE_RELAY','name'=>'GSuite Relay','icon'=>'🔵','category'=>'Google','description'=>'Google Workspace SMTP','requires'=>['gsuite_account'],'best_for'=>['Gmail','Yahoo','AOL'],'cost_per_1k'=>0.40,'capacity'=>'30k/j','reliability'=>90],
|
|
['id'=>'PMTA_DIRECT','name'=>'PMTA Direct','icon'=>'⚡','category'=>'MTA','description'=>'PowerMTA direct (4.0-5.0r3)','requires'=>['pmta_server','dedicated_ip'],'best_for'=>['Videotron','GMX','Free'],'cost_per_1k'=>0.10,'capacity'=>'500k/j','reliability'=>85],
|
|
['id'=>'DOMAIN_IP','name'=>'Domain+IP','icon'=>'🌐','category'=>'MTA','description'=>'PMTA+domaine dédié+IP','requires'=>['domain','ip','spf_dkim'],'best_for'=>['Ziggo','KPN','T-Online'],'cost_per_1k'=>0.15,'capacity'=>'200k/j','reliability'=>88],
|
|
['id'=>'HYBRID_ROTATION','name'=>'Hybrid Rotation','icon'=>'🔀','category'=>'Smart','description'=>'Rotation intelligente','requires'=>['multi_methods'],'best_for'=>['All'],'cost_per_1k'=>0.35,'capacity'=>'1M/j','reliability'=>92],
|
|
['id'=>'WARMERLESS','name'=>'Warmerless','icon'=>'🚀','category'=>'Advanced','description'=>'Sans warmup','requires'=>['fresh_accounts'],'best_for'=>['All'],'cost_per_1k'=>0.60,'capacity'=>'10k/j','reliability'=>80],
|
|
['id'=>'SES_RELAY','name'=>'Amazon SES','icon'=>'🟠','category'=>'Cloud','description'=>'AWS SES','requires'=>['aws_account'],'best_for'=>['Gmail','Yahoo'],'cost_per_1k'=>0.10,'capacity'=>'50k/j','reliability'=>94],
|
|
['id'=>'SENDGRID','name'=>'SendGrid','icon'=>'🔷','category'=>'Cloud','description'=>'Twilio SendGrid','requires'=>['sendgrid_key'],'best_for'=>['Gmail','Outlook'],'cost_per_1k'=>0.25,'capacity'=>'100k/j','reliability'=>93],
|
|
['id'=>'MAILGUN','name'=>'Mailgun','icon'=>'🔫','category'=>'Cloud','description'=>'Mailgun API','requires'=>['mailgun_key'],'best_for'=>['Gmail','Yahoo'],'cost_per_1k'=>0.80,'capacity'=>'50k/j','reliability'=>91],
|
|
['id'=>'FIREBASE','name'=>'Firebase','icon'=>'🔥','category'=>'Google','description'=>'FCM+Email','requires'=>['firebase'],'best_for'=>['Transactional'],'cost_per_1k'=>0.30,'capacity'=>'10k/j','reliability'=>85],
|
|
['id'=>'IP_HUAWEI','name'=>'IP Huawei+PTR','icon'=>'🇨🇳','category'=>'Cloud','description'=>'Huawei Cloud IPs','requires'=>['huawei_ecs'],'best_for'=>['Ziggo','KPN','EU'],'cost_per_1k'=>0.08,'capacity'=>'300k/j','reliability'=>87],
|
|
['id'=>'OVH_RELAY','name'=>'OVH Servers','icon'=>'🇫🇷','category'=>'Cloud','description'=>'OVH IPs EU','requires'=>['ovh_server'],'best_for'=>['EU','T-Online','Free'],'cost_per_1k'=>0.12,'capacity'=>'200k/j','reliability'=>86],
|
|
['id'=>'SCALEWAY','name'=>'Scaleway','icon'=>'🟣','category'=>'Cloud','description'=>'Scaleway EU','requires'=>['scaleway'],'best_for'=>['FR','EU'],'cost_per_1k'=>0.15,'capacity'=>'150k/j','reliability'=>84],
|
|
['id'=>'VMTA_ROTATION','name'=>'VMTA Rotation','icon'=>'🔁','category'=>'MTA','description'=>'Virtual MTA pools','requires'=>['pmta_pools'],'best_for'=>['High Volume'],'cost_per_1k'=>0.08,'capacity'=>'2M/j','reliability'=>90],
|
|
['id'=>'POSTFIX_RELAY','name'=>'Postfix','icon'=>'📮','category'=>'MTA','description'=>'Postfix MTA','requires'=>['postfix'],'best_for'=>['Low Volume'],'cost_per_1k'=>0.05,'capacity'=>'20k/j','reliability'=>75]
|
|
];
|
|
$discoveredMethods=ga($pdo,"SELECT DISTINCT send_method as id,send_method as name,COUNT(*) as test_count,AVG(inbox_rate)::numeric(5,2) as avg_inbox,MAX(inbox_rate)::numeric(5,2) as best_inbox FROM admin.brain_configs WHERE send_method IS NOT NULL GROUP BY send_method ORDER BY avg_inbox DESC");
|
|
$dbMethods=ga($pdo,"SELECT * FROM admin.brain_send_methods ORDER BY success_rate DESC");
|
|
$winningMethods=ga($pdo,"SELECT send_method,isp_target,inbox_rate,domain_used,total_sent,inbox_count FROM admin.brain_configs WHERE status='winner' OR inbox_rate>=85 ORDER BY inbox_rate DESC LIMIT 20");
|
|
$stats=['total_methods'=>count($knownMethods),'discovered'=>count($discoveredMethods),'winning_configs'=>gc($pdo,"SELECT COUNT(*) FROM admin.brain_configs WHERE status='winner'"),'total_tests'=>gc($pdo,"SELECT COUNT(*) FROM admin.brain_test_results"),'o365_accounts'=>gc($pdo,"SELECT COUNT(*) FROM admin.office_accounts WHERE status='Active'"),'domains'=>gc($pdo,"SELECT COUNT(*) FROM admin.domains WHERE status='active'"),'avg_inbox'=>gc($pdo,"SELECT AVG(inbox_rate)::numeric(5,2) FROM admin.brain_configs WHERE inbox_rate>0")?:0];
|
|
$categories=array_unique(array_column($knownMethods,'category'));
|
|
if(isset($_GET['action'])){header('Content-Type:application/json');switch($_GET['action']){case'get_methods':echo json_encode(['known'=>$knownMethods,'discovered'=>$discoveredMethods,'db'=>$dbMethods,'winning'=>$winningMethods]);exit;case'get_stats':echo json_encode($stats);exit;}}
|
|
?><!DOCTYPE html><html><head><meta charset="UTF-8"><title>🧠 Brain Send Methods</title>
|
|
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;700&family=Outfit:wght@400;600;700&display=swap" rel="stylesheet">
|
|
<style>:root{--bg:#0a0a0f;--card:#12121a;--border:#2a2a3a;--text:#e0e0e0;--muted:#888;--purple:#a855f7;--blue:#3b82f6;--green:#22c55e;--orange:#f97316;--cyan:#06b6d4;--yellow:#eab308}*{margin:0;padding:0;box-sizing:border-box}body{font-family:'Outfit',sans-serif;background:var(--bg);color:var(--text);min-height:100vh}.header{background:linear-gradient(180deg,rgba(168,85,247,0.1),transparent);border-bottom:1px solid var(--border);padding:20px 30px;display:flex;justify-content:space-between;align-items:center}.logo{display:flex;align-items:center;gap:15px}.logo-icon{width:50px;height:50px;background:linear-gradient(135deg,var(--purple),var(--blue));border-radius:12px;display:flex;align-items:center;justify-content:center;font-size:24px}.logo-text h1{font-size:1.5rem;background:linear-gradient(90deg,var(--purple),var(--cyan));-webkit-background-clip:text;-webkit-text-fill-color:transparent}.nav-links{display:flex;gap:10px}.nav-link{padding:10px 20px;background:var(--card);border:1px solid var(--border);border-radius:8px;color:var(--text);text-decoration:none}.nav-link:hover,.nav-link.active{background:var(--purple)}.container{max-width:1800px;margin:0 auto;padding:30px}.stats-bar{display:grid;grid-template-columns:repeat(7,1fr);gap:15px;margin-bottom:30px}.stat-card{background:var(--card);border:1px solid var(--border);border-radius:12px;padding:20px;text-align:center}.stat-value{font-size:2rem;font-weight:700;font-family:'JetBrains Mono';background:linear-gradient(90deg,var(--purple),var(--cyan));-webkit-background-clip:text;-webkit-text-fill-color:transparent}.stat-label{font-size:0.8rem;color:var(--muted);text-transform:uppercase}.section-title{display:flex;align-items:center;gap:15px;margin:30px 0 20px;padding-bottom:15px;border-bottom:1px solid var(--border)}.section-icon{width:40px;height:40px;background:linear-gradient(135deg,var(--purple),var(--blue));border-radius:10px;display:flex;align-items:center;justify-content:center;font-size:20px}.section-badge{background:var(--purple);color:white;padding:4px 12px;border-radius:20px;font-size:0.8rem}.methods-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:20px}.method-card{background:var(--card);border:1px solid var(--border);border-radius:16px;padding:20px;transition:all 0.3s}.method-card:hover{transform:translateY(-5px);border-color:var(--purple);box-shadow:0 15px 40px rgba(168,85,247,0.2)}.method-card.winning{border-color:var(--yellow);background:linear-gradient(135deg,rgba(234,179,8,0.1),var(--card))}.method-card.discovered{border-color:var(--green)}.method-header{display:flex;align-items:center;gap:12px;margin-bottom:15px}.method-icon{width:45px;height:45px;background:var(--bg);border-radius:10px;display:flex;align-items:center;justify-content:center;font-size:22px}.method-info h3{font-size:1.1rem}.method-info .category{font-size:0.75rem;color:var(--purple);text-transform:uppercase}.method-desc{font-size:0.85rem;color:var(--muted);margin-bottom:15px}.method-stats{display:grid;grid-template-columns:repeat(3,1fr);gap:10px;margin-bottom:15px}.method-stat{background:var(--bg);padding:10px;border-radius:8px;text-align:center}.method-stat .value{font-size:1.1rem;font-weight:700;font-family:'JetBrains Mono';color:var(--cyan)}.method-stat .label{font-size:0.7rem;color:var(--muted)}.method-tags{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:15px}.tag{padding:4px 10px;border-radius:6px;font-size:0.75rem}.tag.isp{background:rgba(59,130,246,0.2);color:var(--blue)}.tag.require{background:rgba(168,85,247,0.2);color:var(--purple)}.method-actions{display:flex;gap:10px}.btn{flex:1;padding:10px;border:none;border-radius:8px;cursor:pointer;font-size:0.85rem;font-weight:600}.btn-test{background:linear-gradient(135deg,var(--purple),var(--blue));color:white}.btn-config{background:var(--bg);color:var(--text);border:1px solid var(--border)}.winning-table{width:100%;border-collapse:collapse;background:var(--card);border-radius:12px;overflow:hidden}.winning-table th{background:var(--bg);padding:15px;text-align:left;color:var(--muted);text-transform:uppercase}.winning-table td{padding:15px;border-bottom:1px solid var(--border)}.inbox-rate{font-family:'JetBrains Mono';font-weight:700;padding:5px 12px;border-radius:6px}.inbox-rate.high{background:rgba(34,197,94,0.2);color:var(--green)}.inbox-rate.medium{background:rgba(234,179,8,0.2);color:var(--yellow)}.filter-btn{padding:8px 16px;background:var(--card);border:1px solid var(--border);border-radius:8px;color:var(--text);cursor:pointer;margin-right:10px;margin-bottom:10px}.filter-btn:hover,.filter-btn.active{background:var(--purple)}.flow-container{background:var(--card);border:1px solid var(--border);border-radius:16px;padding:30px;margin-bottom:30px}.flow-steps{display:flex;justify-content:space-between}.flow-step{background:var(--bg);border:2px solid var(--border);border-radius:12px;padding:15px;text-align:center;width:100px}.flow-step .icon{font-size:22px}.flow-step .name{font-size:0.75rem;margin-top:5px}.live-dot{width:8px;height:8px;background:var(--green);border-radius:50%;display:inline-block;animation:pulse 2s infinite}@keyframes pulse{0%,100%{opacity:1}50%{opacity:0.5}}</style>
|
|
|
|
</head><body>
|
|
<header class="header"><div class="logo"><div class="logo-icon">🧠</div><div class="logo-text"><h1>Brain Send Methods</h1><span style="color:var(--muted)">Supervision Méthodes</span></div></div>
|
|
<nav class="nav-links"><a href="brain-orchestrator.php" class="nav-link">← Orchestrator</a><a href="brain-send-methods.php" class="nav-link active">Send Methods</a><a href="brain-admin.php" class="nav-link">Admin</a></nav></header>
|
|
<div class="container">
|
|
<div class="stats-bar">
|
|
<div class="stat-card"><div class="stat-value"><?=$stats['total_methods']?></div><div class="stat-label">Méthodes</div></div>
|
|
<div class="stat-card"><div class="stat-value"><?=$stats['discovered']?></div><div class="stat-label">Discovered</div></div>
|
|
<div class="stat-card"><div class="stat-value"><?=$stats['winning_configs']?></div><div class="stat-label">Winners</div></div>
|
|
<div class="stat-card"><div class="stat-value"><?=$stats['total_tests']?></div><div class="stat-label">Tests</div></div>
|
|
<div class="stat-card"><div class="stat-value"><?=$stats['o365_accounts']?></div><div class="stat-label">O365</div></div>
|
|
<div class="stat-card"><div class="stat-value"><?=$stats['domains']?></div><div class="stat-label">Domains</div></div>
|
|
<div class="stat-card"><div class="stat-value"><?=$stats['avg_inbox']?>%</div><div class="stat-label">Avg Inbox</div></div>
|
|
</div>
|
|
<div class="flow-container"><div style="text-align:center;margin-bottom:20px"><h3>🔄 Pipeline Sélection <span class="live-dot"></span></h3></div>
|
|
<div class="flow-steps">
|
|
<div class="flow-step"><div class="icon">🎯</div><div class="name">ISP</div></div>
|
|
<div class="flow-step"><div class="icon">🔍</div><div class="name">Analyse</div></div>
|
|
<div class="flow-step"><div class="icon">📊</div><div class="name">Score</div></div>
|
|
<div class="flow-step"><div class="icon">🔀</div><div class="name">Méthode</div></div>
|
|
<div class="flow-step"><div class="icon">⚙️</div><div class="name">Config</div></div>
|
|
<div class="flow-step"><div class="icon">📧</div><div class="name">Send</div></div>
|
|
<div class="flow-step"><div class="icon">✅</div><div class="name">Track</div></div>
|
|
</div></div>
|
|
<?php if($winningMethods):?>
|
|
<div class="section-title"><div class="section-icon">🏆</div><h2>Winners</h2><span class="section-badge"><?=count($winningMethods)?></span></div>
|
|
<table class="winning-table"><thead><tr><th>ISP</th><th>Méthode</th><th>Domaine</th><th>Inbox%</th><th>Tests</th></tr></thead><tbody>
|
|
<?php foreach($winningMethods as $w):$r=floatval($w['inbox_rate']);$c=$r>=90?'high':'medium';?>
|
|
<tr><td><strong><?=htmlspecialchars($w['isp_target'])?></strong></td><td><span class="tag isp"><?=htmlspecialchars($w['send_method'])?></span></td><td><code style="color:var(--cyan)"><?=substr($w['domain_used']??'',0,25)?></code></td><td><span class="inbox-rate <?=$c?>"><?=$w['inbox_rate']?>%</span></td><td><?=$w['total_sent']?></td></tr>
|
|
<?php endforeach;?></tbody></table>
|
|
<?php endif;?>
|
|
<div class="section-title"><div class="section-icon">📋</div><h2>Méthodes Connues</h2><span class="section-badge"><?=count($knownMethods)?></span></div>
|
|
<div><?php foreach($categories as $c):?><button class="filter-btn" onclick="filterCat('<?=strtolower($c)?>')"><?=$c?></button><?php endforeach;?><button class="filter-btn active" onclick="filterCat('all')">Toutes</button></div>
|
|
<div class="methods-grid" id="grid">
|
|
<?php foreach($knownMethods as $m):?>
|
|
<div class="method-card" data-cat="<?=strtolower($m['category'])?>">
|
|
<div class="method-header"><div class="method-icon"><?=$m['icon']?></div><div class="method-info"><h3><?=$m['name']?></h3><span class="category"><?=$m['category']?></span></div></div>
|
|
<p class="method-desc"><?=$m['description']?></p>
|
|
<div class="method-stats"><div class="method-stat"><div class="value"><?=$m['reliability']?>%</div><div class="label">Fiabilité</div></div><div class="method-stat"><div class="value"><?=$m['capacity']?></div><div class="label">Cap</div></div><div class="method-stat"><div class="value">€<?=number_format($m['cost_per_1k'],2)?></div><div class="label">/1k</div></div></div>
|
|
<div class="method-tags"><?php foreach($m['best_for'] as $i):?><span class="tag isp"><?=$i?></span><?php endforeach;?></div>
|
|
<div class="method-actions"><button class="btn btn-test" onclick="alert('Test <?=$m['id']?>')">🧪 Test</button><button class="btn btn-config" onclick="location='brain-admin.php?m=<?=$m['id']?>'">⚙️</button></div>
|
|
</div>
|
|
<?php endforeach;?>
|
|
</div>
|
|
<?php if($discoveredMethods):?>
|
|
<div class="section-title"><div class="section-icon">🔬</div><h2>Discovered</h2><span class="section-badge" style="background:var(--green)"><?=count($discoveredMethods)?></span></div>
|
|
<div class="methods-grid">
|
|
<?php foreach($discoveredMethods as $m):$avg=floatval($m['avg_inbox']);$win=$avg>=85;?>
|
|
<div class="method-card <?=$win?'winning':'discovered'?>">
|
|
<div class="method-header"><div class="method-icon"><?=$win?'🏆':'🔬'?></div><div class="method-info"><h3><?=htmlspecialchars($m['name'])?></h3><span class="category"><?=$win?'WINNER':'DISCOVERED'?></span></div></div>
|
|
<div class="method-stats"><div class="method-stat"><div class="value" style="color:<?=$avg>=85?'var(--green)':'var(--orange)'?>"><?=$m['avg_inbox']?>%</div><div class="label">Avg</div></div><div class="method-stat"><div class="value"><?=$m['best_inbox']?>%</div><div class="label">Best</div></div><div class="method-stat"><div class="value"><?=$m['test_count']?></div><div class="label">Tests</div></div></div>
|
|
</div>
|
|
<?php endforeach;?>
|
|
</div>
|
|
<?php endif;?>
|
|
<?php if($dbMethods):?>
|
|
<div class="section-title"><div class="section-icon">💾</div><h2>En Base</h2><span class="section-badge"><?=count($dbMethods)?></span></div>
|
|
<table class="winning-table"><thead><tr><th>Méthode</th><th>ISPs</th><th>Success</th><th>Status</th></tr></thead><tbody>
|
|
<?php foreach($dbMethods as $m):?>
|
|
<tr><td><strong><?=htmlspecialchars($m['method_name'])?></strong></td><td><?=htmlspecialchars($m['best_for_isps']??'-')?></td><td><span class="inbox-rate <?=($m['success_rate']??0)>=80?'high':'medium'?>"><?=$m['success_rate']??0?>%</span></td><td style="color:<?=($m['is_active']??0)?'var(--green)':'var(--muted)'?>"><?=($m['is_active']??0)?'✓':'✗'?></td></tr>
|
|
<?php endforeach;?></tbody></table>
|
|
<?php endif;?>
|
|
</div>
|
|
<script>function filterCat(c){document.querySelectorAll('#grid .method-card').forEach(e=>{e.style.display=(c==='all'||e.dataset.cat===c)?'block':'none'});document.querySelectorAll('.filter-btn').forEach(b=>b.classList.remove('active'));event.target.classList.add('active')}</script>
|
|
|
|
</body></html>
|