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

284 lines
29 KiB
PHP
Executable File
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
error_reporting(E_ALL);
ini_set('display_errors', 0);
function getDB() {
static $pdo = null;
if ($pdo === null) {
$pdo = new PDO("pgsql:host=localhost;dbname=adx_system", "admin", "admin123", [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);
}
return $pdo;
}
function ensureTables() {
$pdo = getDB();
$pdo->exec("CREATE TABLE IF NOT EXISTS admin.telegram_config (id SERIAL PRIMARY KEY, bot_token VARCHAR(255), chat_id VARCHAR(100), is_active BOOLEAN DEFAULT true)");
$pdo->exec("CREATE TABLE IF NOT EXISTS admin.ai_config (id SERIAL PRIMARY KEY, provider VARCHAR(50), api_key VARCHAR(500), model VARCHAR(100), is_active BOOLEAN DEFAULT true)");
$pdo->exec("CREATE TABLE IF NOT EXISTS admin.imap_checkers (id SERIAL PRIMARY KEY, name VARCHAR(255), email VARCHAR(255), password VARCHAR(255), imap_host VARCHAR(255), imap_port INTEGER DEFAULT 993, spam_folder VARCHAR(100) DEFAULT 'Junk', last_check TIMESTAMP, inbox_count INTEGER DEFAULT 0, spam_count INTEGER DEFAULT 0, is_active BOOLEAN DEFAULT true)");
$pdo->exec("CREATE TABLE IF NOT EXISTS admin.wevads_config (id SERIAL PRIMARY KEY, api_url VARCHAR(500) DEFAULT 'http://api.weval.digital:58081', username VARCHAR(255), password VARCHAR(255), auth_cookie TEXT, is_active BOOLEAN DEFAULT true)");
}
class TelegramBot {
private $token, $chatId;
public function __construct() {
$pdo = getDB();
$config = $pdo->query("SELECT * FROM admin.telegram_config WHERE is_active = true LIMIT 1")->fetch(PDO::FETCH_ASSOC);
if ($config) { $this->token = $config['bot_token']; $this->chatId = $config['chat_id']; }
}
public function send($message, $parseMode = 'HTML') {
if (!$this->token || !$this->chatId) return false;
$ch = curl_init("https://api.telegram.org/bot{$this->token}/sendMessage");
curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_POSTFIELDS => ['chat_id' => $this->chatId, 'text' => $message, 'parse_mode' => $parseMode]]);
$result = curl_exec($ch); curl_close($ch);
return json_decode($result, true);
}
public function alert($title, $msg, $sev = 'info') {
$emoji = ['info' => '', 'warning' => '⚠️', 'error' => '🚨', 'success' => '✅'];
return $this->send("{$emoji[$sev]} <b>{$title}</b>\n\n{$msg}\n\n🕐 " . date('Y-m-d H:i:s'));
}
}
class AIHelper {
private $provider, $apiKey, $model;
public function __construct() {
$pdo = getDB();
$config = $pdo->query("SELECT * FROM admin.ai_config WHERE is_active = true LIMIT 1")->fetch(PDO::FETCH_ASSOC);
if ($config) { $this->provider = $config['provider']; $this->apiKey = $config['api_key']; $this->model = $config['model']; }
}
public function generate($prompt) {
if (!$this->apiKey) return ['success' => false, 'error' => 'No API key configured'];
switch ($this->provider) {
case 'anthropic': return $this->claude($prompt);
case 'openai': return $this->openai($prompt);
case 'groq': return $this->groq($prompt);
case 'deepseek': return $this->deepseek($prompt);
default: return ['success' => false, 'error' => 'Unknown provider'];
}
}
private function claude($prompt) {
$ch = curl_init('https://api.anthropic.com/v1/messages');
curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'x-api-key: ' . $this->apiKey, 'anthropic-version: 2023-06-01'], CURLOPT_POSTFIELDS => json_encode(['model' => $this->model ?: 'claude-3-haiku-20240307', 'max_tokens' => 1024, 'messages' => [['role' => 'user', 'content' => $prompt]]])]);
$r = json_decode(curl_exec($ch), true); curl_close($ch);
return isset($r['content'][0]['text']) ? ['success' => true, 'text' => $r['content'][0]['text']] : ['success' => false, 'error' => $r['error']['message'] ?? 'Error'];
}
private function openai($prompt) {
$ch = curl_init('https://api.openai.com/v1/chat/completions');
curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Authorization: Bearer ' . $this->apiKey], CURLOPT_POSTFIELDS => json_encode(['model' => $this->model ?: 'gpt-3.5-turbo', 'messages' => [['role' => 'user', 'content' => $prompt]], 'max_tokens' => 1024])]);
$r = json_decode(curl_exec($ch), true); curl_close($ch);
return isset($r['choices'][0]['message']['content']) ? ['success' => true, 'text' => $r['choices'][0]['message']['content']] : ['success' => false, 'error' => $r['error']['message'] ?? 'Error'];
}
private function groq($prompt) {
$ch = curl_init('https://api.groq.com/openai/v1/chat/completions');
curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Authorization: Bearer ' . $this->apiKey], CURLOPT_POSTFIELDS => json_encode(['model' => $this->model ?: 'llama3-8b-8192', 'messages' => [['role' => 'user', 'content' => $prompt]], 'max_tokens' => 1024])]);
$r = json_decode(curl_exec($ch), true); curl_close($ch);
return isset($r['choices'][0]['message']['content']) ? ['success' => true, 'text' => $r['choices'][0]['message']['content']] : ['success' => false, 'error' => $r['error']['message'] ?? 'Error'];
}
private function deepseek($prompt) {
$ch = curl_init('https://api.deepseek.com/v1/chat/completions');
curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Authorization: Bearer ' . $this->apiKey], CURLOPT_POSTFIELDS => json_encode(['model' => $this->model ?: 'deepseek-chat', 'messages' => [['role' => 'user', 'content' => $prompt]], 'max_tokens' => 1024])]);
$r = json_decode(curl_exec($ch), true); curl_close($ch);
return isset($r['choices'][0]['message']['content']) ? ['success' => true, 'text' => $r['choices'][0]['message']['content']] : ['success' => false, 'error' => $r['error']['message'] ?? 'Error'];
}
}
class InboxChecker {
public static function check($acc) {
$mailbox = "{" . $acc['imap_host'] . ":" . $acc['imap_port'] . "/imap/ssl/novalidate-cert}";
$result = ['success' => false, 'inbox' => 0, 'spam' => 0, 'recent' => []];
$imap = @imap_open($mailbox . "INBOX", $acc['email'], $acc['password'], 0, 1);
if (!$imap) return ['success' => false, 'error' => imap_last_error()];
$info = imap_check($imap);
$result['inbox'] = $info->Nmsgs ?? 0;
if ($result['inbox'] > 0) {
$start = max(1, $result['inbox'] - 10);
$emails = imap_fetch_overview($imap, "$start:{$result['inbox']}");
foreach ($emails as $e) $result['recent'][] = ['subject' => imap_utf8($e->subject ?? ''), 'from' => imap_utf8($e->from ?? ''), 'date' => $e->date ?? ''];
}
imap_close($imap);
$imapSpam = @imap_open($mailbox . ($acc['spam_folder'] ?: 'Junk'), $acc['email'], $acc['password'], 0, 1);
if ($imapSpam) { $spamInfo = imap_check($imapSpam); $result['spam'] = $spamInfo->Nmsgs ?? 0; imap_close($imapSpam); }
$result['success'] = true;
return $result;
}
}
class WevadsAPI {
private $baseUrl, $cookie;
public function __construct() {
$pdo = getDB();
$config = $pdo->query("SELECT * FROM admin.wevads_config WHERE is_active = true LIMIT 1")->fetch(PDO::FETCH_ASSOC);
if ($config) { $this->baseUrl = $config['api_url']; $this->cookie = $config['auth_cookie']; }
}
public function request($endpoint, $method = 'GET', $data = null) {
$ch = curl_init($this->baseUrl . $endpoint);
curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER => true, CURLOPT_COOKIE => $this->cookie, CURLOPT_CUSTOMREQUEST => $method, CURLOPT_TIMEOUT => 30]);
if ($data) { curl_setopt($ch, CURLOPT_POSTFIELDS, is_array($data) ? http_build_query($data) : $data); }
$response = curl_exec($ch); $code = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch);
return ['code' => $code, 'data' => json_decode($response, true) ?: $response];
}
public function getServers() { return $this->request('/api/servers'); }
public function getVMTAs() { return $this->request('/api/vmtas'); }
public function sendTest($params) { return $this->request('/api/send/test', 'POST', $params); }
}
if (isset($_GET['action']) || isset($_POST['action'])) {
header('Content-Type: application/json');
ensureTables();
$action = $_GET['action'] ?? $_POST['action'];
$pdo = getDB();
try {
switch ($action) {
case 'stats':
$stats = [
'campaigns' => ['total' => $pdo->query("SELECT COUNT(*) FROM admin.campaigns")->fetchColumn(), 'running' => $pdo->query("SELECT COUNT(*) FROM admin.campaigns WHERE status = 'running'")->fetchColumn(), 'completed' => $pdo->query("SELECT COUNT(*) FROM admin.campaigns WHERE status = 'completed'")->fetchColumn()],
'warmup' => ['accounts' => $pdo->query("SELECT COUNT(*) FROM admin.warmup_accounts")->fetchColumn(), 'active' => $pdo->query("SELECT COUNT(*) FROM admin.warmup_accounts WHERE status = 'active'")->fetchColumn(), 'sent_today' => $pdo->query("SELECT COALESCE(SUM(emails_sent_today), 0) FROM admin.warmup_accounts")->fetchColumn()],
'pmta' => ['servers' => $pdo->query("SELECT COUNT(*) FROM admin.pmta_servers")->fetchColumn(), 'queued' => $pdo->query("SELECT COALESCE(SUM(queued_emails), 0) FROM admin.pmta_servers")->fetchColumn()],
'cloud' => ['huawei' => $pdo->query("SELECT COUNT(*) FROM admin.huawei_accounts")->fetchColumn(), 'scaleway' => $pdo->query("SELECT COUNT(*) FROM admin.scaleway_accounts")->fetchColumn()],
'dns' => ['cloudflare' => $pdo->query("SELECT COUNT(*) FROM admin.cloudflare_zones")->fetchColumn(), 'freedns' => $pdo->query("SELECT COUNT(*) FROM admin.freedns_domains")->fetchColumn()],
'alerts' => $pdo->query("SELECT COUNT(*) FROM admin.monitoring_alerts WHERE acknowledged = false")->fetchColumn()
];
echo json_encode(['success' => true, 'stats' => $stats]);
break;
case 'tg_get': echo json_encode(['success' => true, 'config' => $pdo->query("SELECT bot_token, chat_id FROM admin.telegram_config LIMIT 1")->fetch(PDO::FETCH_ASSOC)]); break;
case 'tg_save': $pdo->exec("DELETE FROM admin.telegram_config"); $stmt = $pdo->prepare("INSERT INTO admin.telegram_config (bot_token, chat_id) VALUES (?, ?)"); $stmt->execute([$_POST['bot_token'], $_POST['chat_id']]); echo json_encode(['success' => true]); break;
case 'tg_test': $bot = new TelegramBot(); $r = $bot->alert('Test Alert', 'WEVAL SEND Dashboard is working!', 'success'); echo json_encode(['success' => isset($r['ok']) && $r['ok']]); break;
case 'tg_send': $bot = new TelegramBot(); $r = $bot->send($_POST['message']); echo json_encode(['success' => isset($r['ok']) && $r['ok']]); break;
case 'ai_get': echo json_encode(['success' => true, 'config' => $pdo->query("SELECT provider, model FROM admin.ai_config LIMIT 1")->fetch(PDO::FETCH_ASSOC)]); break;
case 'ai_save': $pdo->exec("DELETE FROM admin.ai_config"); $stmt = $pdo->prepare("INSERT INTO admin.ai_config (provider, api_key, model) VALUES (?, ?, ?)"); $stmt->execute([$_POST['provider'], $_POST['api_key'], $_POST['model']]); echo json_encode(['success' => true]); break;
case 'ai_generate': $ai = new AIHelper(); echo json_encode($ai->generate($_POST['prompt'])); break;
case 'ai_email': $ai = new AIHelper(); $prompt = "Generate email marketing subject line and from name for:\nOffer: {$_POST['offer']}\nSponsor: {$_POST['sponsor']}\n\nFormat:\nSUBJECT: [subject]\nFROM: [from name]"; echo json_encode($ai->generate($prompt)); break;
case 'imap_list': echo json_encode(['success' => true, 'checkers' => $pdo->query("SELECT id, name, email, imap_host, last_check, inbox_count, spam_count FROM admin.imap_checkers ORDER BY id")->fetchAll(PDO::FETCH_ASSOC)]); break;
case 'imap_add': $stmt = $pdo->prepare("INSERT INTO admin.imap_checkers (name, email, password, imap_host, imap_port, spam_folder) VALUES (?, ?, ?, ?, ?, ?)"); $stmt->execute([$_POST['name'], $_POST['email'], $_POST['password'], $_POST['imap_host'], $_POST['imap_port'] ?? 993, $_POST['spam_folder'] ?? 'Junk']); echo json_encode(['success' => true]); break;
case 'imap_check': $stmt = $pdo->prepare("SELECT * FROM admin.imap_checkers WHERE id = ?"); $stmt->execute([$_POST['id']]); $acc = $stmt->fetch(PDO::FETCH_ASSOC); $r = InboxChecker::check($acc); if ($r['success']) $pdo->exec("UPDATE admin.imap_checkers SET inbox_count = {$r['inbox']}, spam_count = {$r['spam']}, last_check = NOW() WHERE id = {$acc['id']}"); echo json_encode($r); break;
case 'imap_delete': $pdo->exec("DELETE FROM admin.imap_checkers WHERE id = " . intval($_POST['id'])); echo json_encode(['success' => true]); break;
case 'wevads_get': echo json_encode(['success' => true, 'config' => $pdo->query("SELECT api_url FROM admin.wevads_config LIMIT 1")->fetch(PDO::FETCH_ASSOC)]); break;
case 'wevads_save': $pdo->exec("DELETE FROM admin.wevads_config"); $stmt = $pdo->prepare("INSERT INTO admin.wevads_config (api_url, username, password) VALUES (?, ?, ?)"); $stmt->execute([$_POST['api_url'], $_POST['username'], $_POST['password']]); echo json_encode(['success' => true]); break;
case 'activity': $activity = $pdo->query("SELECT 'campaign' as type, name as title, status, created_at FROM admin.campaigns UNION ALL SELECT 'alert', title, severity, created_at FROM admin.monitoring_alerts ORDER BY created_at DESC LIMIT 15")->fetchAll(PDO::FETCH_ASSOC); echo json_encode(['success' => true, 'activity' => $activity]); break;
default: echo json_encode(['success' => false, 'error' => 'Unknown action']);
}
} catch (Exception $e) { echo json_encode(['success' => false, 'error' => $e->getMessage()]); }
exit;
}
ensureTables();
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>WEVAL SEND - Central Dashboard</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
:root{--bg:#0a0a0f;--bg2:#12121a;--bg3:#1a1a25;--primary:#6366f1;--success:#10b981;--warning:#f59e0b;--danger:#ef4444;--text:#e2e8f0;--text2:#94a3b8;--border:#2a2a3a}
*{margin:0;padding:0;box-sizing:border-box}body{font-family:'Inter',sans-serif;background:var(--bg);color:var(--text);min-height:100vh}
.header{background:linear-gradient(135deg,#6366f1,#8b5cf6);padding:1.25rem 2rem;display:flex;justify-content:space-between;align-items:center}
.header h1{font-size:1.4rem;color:white;display:flex;align-items:center;gap:.5rem}
.header-links{display:flex;gap:.5rem}.header-links a{padding:.4rem .8rem;background:rgba(255,255,255,.15);border-radius:6px;color:white;text-decoration:none;font-size:.75rem}
.header-links a:hover{background:rgba(255,255,255,.25)}
.container{max-width:1600px;margin:0 auto;padding:1.5rem}
.grid-4{display:grid;grid-template-columns:repeat(4,1fr);gap:1rem;margin-bottom:1.5rem}
.grid-3{display:grid;grid-template-columns:repeat(3,1fr);gap:1rem}
.grid-2{display:grid;grid-template-columns:1fr 1fr;gap:1rem}
.stat{background:var(--bg2);border:1px solid var(--border);border-radius:10px;padding:1rem}
.stat h4{color:var(--text2);font-size:.7rem;margin-bottom:.5rem;display:flex;align-items:center;gap:.3rem}
.stat .main{font-size:1.8rem;font-weight:700}.stat .sub{font-size:.75rem;color:var(--text2)}
.stat.purple .main{color:#8b5cf6}.stat.orange .main{color:#ff6b35}.stat.green .main{color:#10b981}.stat.blue .main{color:#3b82f6}
.card{background:var(--bg2);border:1px solid var(--border);border-radius:10px;padding:1.25rem;margin-bottom:1rem}
.card h3{margin-bottom:1rem;font-size:.95rem;display:flex;align-items:center;gap:.5rem}
.form-row{display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:.75rem;margin-bottom:.75rem}
.form-group{display:flex;flex-direction:column;gap:.2rem}
.form-group label{font-size:.65rem;color:var(--text2)}
.form-group input,.form-group select,.form-group textarea{padding:.45rem .6rem;background:var(--bg3);border:1px solid var(--border);border-radius:5px;color:var(--text);font-size:.8rem}
.form-group textarea{min-height:70px}
.btn{padding:.45rem .9rem;border:none;border-radius:5px;font-weight:600;cursor:pointer;font-size:.75rem;display:inline-flex;align-items:center;gap:.3rem}
.btn:hover{opacity:.9}.btn-primary{background:var(--primary);color:white}.btn-success{background:var(--success);color:white}
.btn-danger{background:var(--danger);color:white}.btn-telegram{background:#0088cc;color:white}.btn-ai{background:linear-gradient(135deg,#8b5cf6,#a855f7);color:white}
.btn-sm{padding:.3rem .5rem;font-size:.7rem}
.modules{display:grid;grid-template-columns:repeat(6,1fr);gap:.75rem;margin-bottom:1.5rem}
.module{background:var(--bg2);border:1px solid var(--border);border-radius:8px;padding:1rem;text-align:center;text-decoration:none;color:var(--text);transition:all .2s}
.module:hover{transform:translateY(-2px);border-color:var(--primary)}
.module i{font-size:1.5rem;margin-bottom:.5rem;display:block}
.module span{font-size:.75rem}
.module.m1 i{color:#8b5cf6}.module.m2 i{color:#ff6b35}.module.m3 i{color:#10b981}.module.m4 i{color:#3b82f6}.module.m5 i{color:#f59e0b}.module.m6 i{color:#ec4899}
table{width:100%;border-collapse:collapse;font-size:.75rem}
th,td{padding:.4rem .5rem;text-align:left;border-bottom:1px solid var(--border)}
th{color:var(--text2);font-size:.65rem}
.badge{padding:.15rem .4rem;border-radius:8px;font-size:.6rem;font-weight:600}
.badge-running{background:rgba(99,102,241,.15);color:var(--primary)}.badge-completed{background:rgba(16,185,129,.15);color:var(--success)}
.tabs{display:flex;gap:.4rem;margin-bottom:.75rem}.tab{padding:.4rem .8rem;background:var(--bg3);border-radius:5px;cursor:pointer;font-size:.75rem}.tab.active{background:var(--primary);color:white}
.activity-item{display:flex;align-items:center;gap:.6rem;padding:.5rem;background:var(--bg3);border-radius:5px;margin-bottom:.4rem;font-size:.75rem}
.activity-item i{width:26px;height:26px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:.7rem}
.activity-item.campaign i{background:rgba(139,92,246,.15);color:#8b5cf6}.activity-item.alert i{background:rgba(239,68,68,.15);color:#ef4444}
.ai-out{background:var(--bg3);border-radius:6px;padding:.75rem;margin-top:.75rem;white-space:pre-wrap;font-family:monospace;font-size:.75rem;max-height:200px;overflow-y:auto}
</style>
</head>
<body>
<div class="header">
<h1><i class="fas fa-rocket"></i> WEVAL SEND</h1>
<div class="header-links">
<a href="http://89.167.40.150:5678" target="_blank"><i class="fas fa-project-diagram"></i> n8n</a>
<a href="campaign-orchestrator.php"><i class="fas fa-play"></i> Orchestrator</a>
<a href="automation-hub.php"><i class="fas fa-robot"></i> Automation</a>
</div>
</div>
<div class="container">
<div class="grid-4">
<div class="stat purple"><h4><i class="fas fa-rocket"></i> Campaigns</h4><div class="main" id="sCamp">0</div><div class="sub"><span id="sCampRun">0</span> running</div></div>
<div class="stat orange"><h4><i class="fas fa-fire"></i> Warmup</h4><div class="main" id="sWarm">0</div><div class="sub"><span id="sWarmSent">0</span> sent today</div></div>
<div class="stat green"><h4><i class="fas fa-server"></i> PMTA</h4><div class="main" id="sPmta">0</div><div class="sub"><span id="sPmtaQ">0</span> queued</div></div>
<div class="stat blue"><h4><i class="fas fa-cloud"></i> Cloud</h4><div class="main" id="sCloud">0</div><div class="sub">Huawei + Scaleway</div></div>
</div>
<div class="modules">
<a href="campaign-orchestrator.php" class="module m1"><i class="fas fa-rocket"></i><span>Orchestrator</span></a>
<a href="warmup-system.php" class="module m2"><i class="fas fa-fire"></i><span>Warmup</span></a>
<a href="automation-hub.php" class="module m3"><i class="fas fa-robot"></i><span>Automation</span></a>
<a href="cloud-manager.php" class="module m4"><i class="fas fa-cloud"></i><span>Cloud</span></a>
<a href="dns-manager.php" class="module m5"><i class="fas fa-globe"></i><span>DNS</span></a>
<a href="import-system.php" class="module m6"><i class="fas fa-upload"></i><span>Import</span></a>
</div>
<div class="grid-2">
<div>
<div class="card"><h3><i class="fab fa-telegram" style="color:#0088cc"></i> Telegram</h3>
<div class="form-row"><div class="form-group"><label>Bot Token</label><input type="text" id="tgToken" placeholder="123456:ABC..."></div><div class="form-group"><label>Chat ID</label><input type="text" id="tgChat" placeholder="-100..."></div></div>
<div style="display:flex;gap:.5rem"><button class="btn btn-telegram" onclick="saveTg()"><i class="fas fa-save"></i> Save</button><button class="btn btn-telegram" onclick="testTg()"><i class="fas fa-paper-plane"></i> Test</button></div></div>
<div class="card"><h3><i class="fas fa-brain" style="color:#8b5cf6"></i> AI Integration</h3>
<div class="form-row"><div class="form-group"><label>Provider</label><select id="aiProv"><option value="anthropic">Claude</option><option value="openai">OpenAI</option><option value="groq">Groq</option><option value="deepseek">DeepSeek</option></select></div><div class="form-group"><label>API Key</label><input type="password" id="aiKey" placeholder="sk-..."></div><div class="form-group"><label>Model</label><input type="text" id="aiModel" placeholder="claude-3-haiku"></div></div>
<button class="btn btn-ai" onclick="saveAi()"><i class="fas fa-save"></i> Save</button>
<div style="margin-top:1rem"><div class="form-row"><div class="form-group"><input type="text" id="aiOffer" placeholder="Offer"></div><div class="form-group"><input type="text" id="aiSponsor" placeholder="Sponsor"></div><div class="form-group"><button class="btn btn-ai" onclick="genEmail()"><i class="fas fa-magic"></i> Generate</button></div></div><div class="ai-out" id="aiOut" style="display:none"></div></div></div>
<div class="card"><h3><i class="fas fa-link" style="color:#3b82f6"></i> WEVAL API</h3>
<div class="form-row"><div class="form-group"><label>API URL</label><input type="text" id="wevUrl" value="http://api.weval.digital:58081"></div><div class="form-group"><label>Username</label><input type="text" id="wevUser"></div><div class="form-group"><label>Password</label><input type="password" id="wevPass"></div></div>
<button class="btn btn-primary" onclick="saveWev()"><i class="fas fa-save"></i> Save</button></div>
</div>
<div>
<div class="card"><h3><i class="fas fa-inbox" style="color:#10b981"></i> Inbox Checkers</h3>
<div class="tabs"><div class="tab active" onclick="showImap('list')">Accounts</div><div class="tab" onclick="showImap('add')">Add</div></div>
<div id="imapList"><table><thead><tr><th>Name</th><th>Email</th><th>Inbox</th><th>Spam</th><th>Actions</th></tr></thead><tbody id="imapTbl"></tbody></table></div>
<div id="imapAdd" style="display:none">
<div class="form-row"><div class="form-group"><label>Name</label><input type="text" id="imName"></div><div class="form-group"><label>Email</label><input type="email" id="imEmail"></div></div>
<div class="form-row"><div class="form-group"><label>Password</label><input type="password" id="imPass"></div><div class="form-group"><label>IMAP Host</label><input type="text" id="imHost"></div></div>
<div class="form-row"><div class="form-group"><label>Port</label><input type="number" id="imPort" value="993"></div><div class="form-group"><label>Spam Folder</label><input type="text" id="imSpam" value="Junk"></div></div>
<button class="btn btn-success" onclick="addImap()"><i class="fas fa-plus"></i> Add</button></div></div>
<div class="card"><h3><i class="fas fa-history"></i> Recent Activity</h3><div id="actList"></div></div>
</div>
</div>
</div>
<script>
function load(){fetch('?action=stats').then(r=>r.json()).then(d=>{if(d.success){const s=d.stats;document.getElementById('sCamp').textContent=s.campaigns.total;document.getElementById('sCampRun').textContent=s.campaigns.running;document.getElementById('sWarm').textContent=s.warmup.accounts;document.getElementById('sWarmSent').textContent=s.warmup.sent_today;document.getElementById('sPmta').textContent=s.pmta.servers;document.getElementById('sPmtaQ').textContent=Number(s.pmta.queued).toLocaleString();document.getElementById('sCloud').textContent=Number(s.cloud.huawei)+Number(s.cloud.scaleway);}});}
function loadTg(){fetch('?action=tg_get').then(r=>r.json()).then(d=>{if(d.success&&d.config){document.getElementById('tgToken').value=d.config.bot_token||'';document.getElementById('tgChat').value=d.config.chat_id||'';}});}
function saveTg(){const fd=new FormData();fd.append('action','tg_save');fd.append('bot_token',document.getElementById('tgToken').value);fd.append('chat_id',document.getElementById('tgChat').value);fetch('',{method:'POST',body:fd}).then(r=>r.json()).then(d=>alert(d.success?'Saved!':'Error'));}
function testTg(){fetch('',{method:'POST',body:new URLSearchParams({action:'tg_test'})}).then(r=>r.json()).then(d=>alert(d.success?'✅ Sent!':'❌ Failed'));}
function loadAi(){fetch('?action=ai_get').then(r=>r.json()).then(d=>{if(d.success&&d.config){document.getElementById('aiProv').value=d.config.provider||'anthropic';document.getElementById('aiModel').value=d.config.model||'';}});}
function saveAi(){const fd=new FormData();fd.append('action','ai_save');fd.append('provider',document.getElementById('aiProv').value);fd.append('api_key',document.getElementById('aiKey').value);fd.append('model',document.getElementById('aiModel').value);fetch('',{method:'POST',body:fd}).then(r=>r.json()).then(d=>alert(d.success?'Saved!':'Error'));}
function genEmail(){const fd=new FormData();fd.append('action','ai_email');fd.append('offer',document.getElementById('aiOffer').value);fd.append('sponsor',document.getElementById('aiSponsor').value);document.getElementById('aiOut').style.display='block';document.getElementById('aiOut').textContent='Generating...';fetch('',{method:'POST',body:fd}).then(r=>r.json()).then(d=>{document.getElementById('aiOut').textContent=d.success?d.text:'Error: '+d.error;});}
function loadWev(){fetch('?action=wevads_get').then(r=>r.json()).then(d=>{if(d.success&&d.config)document.getElementById('wevUrl').value=d.config.api_url||'';});}
function saveWev(){const fd=new FormData();fd.append('action','wevads_save');fd.append('api_url',document.getElementById('wevUrl').value);fd.append('username',document.getElementById('wevUser').value);fd.append('password',document.getElementById('wevPass').value);fetch('',{method:'POST',body:fd}).then(r=>r.json()).then(d=>alert(d.success?'Saved!':'Error'));}
function loadImap(){fetch('?action=imap_list').then(r=>r.json()).then(d=>{if(d.success){document.getElementById('imapTbl').innerHTML=d.checkers.length?d.checkers.map(c=>'<tr><td>'+c.name+'</td><td>'+c.email+'</td><td style="color:var(--success)">'+c.inbox_count+'</td><td style="color:var(--danger)">'+c.spam_count+'</td><td><button class="btn btn-success btn-sm" onclick="checkImap('+c.id+')"><i class="fas fa-sync"></i></button> <button class="btn btn-danger btn-sm" onclick="delImap('+c.id+')"><i class="fas fa-trash"></i></button></td></tr>').join(''):'<tr><td colspan="5" style="text-align:center;color:var(--text2)">No accounts</td></tr>';}});}
function showImap(t){document.querySelectorAll('.tabs .tab').forEach(x=>x.classList.remove('active'));event.target.classList.add('active');document.getElementById('imapList').style.display=t==='list'?'block':'none';document.getElementById('imapAdd').style.display=t==='add'?'block':'none';}
function addImap(){const fd=new FormData();fd.append('action','imap_add');fd.append('name',document.getElementById('imName').value);fd.append('email',document.getElementById('imEmail').value);fd.append('password',document.getElementById('imPass').value);fd.append('imap_host',document.getElementById('imHost').value);fd.append('imap_port',document.getElementById('imPort').value);fd.append('spam_folder',document.getElementById('imSpam').value);fetch('',{method:'POST',body:fd}).then(()=>{loadImap();showImap('list');});}
function checkImap(id){fetch('',{method:'POST',body:new URLSearchParams({action:'imap_check',id:id})}).then(r=>r.json()).then(d=>{alert(d.success?'✅ Inbox: '+d.inbox+' | Spam: '+d.spam:'❌ '+d.error);loadImap();});}
function delImap(id){if(!confirm('Delete?'))return;fetch('',{method:'POST',body:new URLSearchParams({action:'imap_delete',id:id})}).then(()=>loadImap());}
function loadAct(){fetch('?action=activity').then(r=>r.json()).then(d=>{if(d.success){document.getElementById('actList').innerHTML=d.activity.length?d.activity.slice(0,10).map(a=>'<div class="activity-item '+a.type+'"><i class="fas fa-'+(a.type==='campaign'?'rocket':'bell')+'"></i><div style="flex:1"><div>'+a.title+'</div><div style="font-size:.65rem;color:var(--text2)">'+new Date(a.created_at).toLocaleString()+'</div></div><span class="badge badge-'+a.status+'">'+a.status+'</span></div>').join(''):'<div style="text-align:center;color:var(--text2);padding:1rem">No activity</div>';}});}
load();loadTg();loadAi();loadWev();loadImap();loadAct();setInterval(load,30000);
</script>
</body>
</html>