194 lines
13 KiB
PHP
Executable File
194 lines
13 KiB
PHP
Executable File
<?php
|
|
/**
|
|
* WEVAL SEND ALERT SYSTEM
|
|
* Notifications via Email & Telegram
|
|
*/
|
|
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->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
|
}
|
|
return $pdo;
|
|
}
|
|
|
|
// Ensure tables exist
|
|
function ensureTables($pdo) {
|
|
$pdo->exec("CREATE TABLE IF NOT EXISTS admin.alert_config (key VARCHAR(100) PRIMARY KEY, value TEXT, updated_at TIMESTAMP DEFAULT NOW())");
|
|
$pdo->exec("CREATE TABLE IF NOT EXISTS admin.alert_history (id SERIAL PRIMARY KEY, type VARCHAR(50), severity VARCHAR(20), title VARCHAR(255), message TEXT, data JSONB, sent_email BOOLEAN DEFAULT FALSE, sent_telegram BOOLEAN DEFAULT FALSE, acknowledged BOOLEAN DEFAULT FALSE, created_at TIMESTAMP DEFAULT NOW())");
|
|
}
|
|
|
|
if (isset($_GET['action'])) {
|
|
header('Content-Type: application/json');
|
|
$pdo = getDb();
|
|
ensureTables($pdo);
|
|
|
|
switch ($_GET['action']) {
|
|
case 'run_checks':
|
|
$alerts = [];
|
|
|
|
// Check blocked accounts
|
|
$stats = $pdo->query("SELECT COUNT(*) FILTER (WHERE status = 'Blocked') as blocked, COUNT(*) as total FROM admin.office_accounts")->fetch(PDO::FETCH_ASSOC);
|
|
$blockedPercent = $stats['total'] > 0 ? ($stats['blocked'] / $stats['total']) * 100 : 0;
|
|
|
|
if ($blockedPercent > 30) {
|
|
$alerts[] = ['type' => 'blocked_high', 'severity' => $blockedPercent > 50 ? 'critical' : 'warning', 'title' => "⚠️ High Blocked Rate: " . round($blockedPercent, 1) . "%", 'message' => "{$stats['blocked']} of {$stats['total']} accounts blocked"];
|
|
}
|
|
|
|
// Save alerts
|
|
foreach ($alerts as $alert) {
|
|
$stmt = $pdo->prepare("INSERT INTO admin.alert_history (type, severity, title, message, data) VALUES (?, ?, ?, ?, ?)");
|
|
$stmt->execute([$alert['type'], $alert['severity'], $alert['title'], $alert['message'], json_encode($alert)]);
|
|
|
|
// Send Telegram if configured
|
|
$tgToken = $pdo->query("SELECT value FROM admin.alert_config WHERE key = 'telegram_bot_token'")->fetchColumn();
|
|
$tgChat = $pdo->query("SELECT value FROM admin.alert_config WHERE key = 'telegram_chat_id'")->fetchColumn();
|
|
if ($tgToken && $tgChat) {
|
|
$text = "🚨 *WEVAL SEND ALERT*\n\n*{$alert['title']}*\n\n{$alert['message']}";
|
|
@file_get_contents("https://api.telegram.org/bot{$tgToken}/sendMessage?" . http_build_query(['chat_id' => $tgChat, 'text' => $text, 'parse_mode' => 'Markdown']));
|
|
}
|
|
}
|
|
|
|
echo json_encode(['alerts' => $alerts, 'checked_at' => date('Y-m-d H:i:s')]);
|
|
break;
|
|
|
|
case 'history':
|
|
$history = $pdo->query("SELECT * FROM admin.alert_history ORDER BY created_at DESC LIMIT 50")->fetchAll(PDO::FETCH_ASSOC);
|
|
echo json_encode($history);
|
|
break;
|
|
|
|
case 'config':
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
foreach ($_POST as $key => $value) {
|
|
$stmt = $pdo->prepare("INSERT INTO admin.alert_config (key, value, updated_at) VALUES (?, ?, NOW()) ON CONFLICT (key) DO UPDATE SET value = EXCLUDED.value, updated_at = NOW()");
|
|
$stmt->execute([$key, $value]);
|
|
}
|
|
echo json_encode(['success' => true]);
|
|
} else {
|
|
$config = $pdo->query("SELECT key, value FROM admin.alert_config")->fetchAll(PDO::FETCH_KEY_PAIR);
|
|
echo json_encode($config);
|
|
}
|
|
break;
|
|
|
|
case 'test':
|
|
$tgToken = $pdo->query("SELECT value FROM admin.alert_config WHERE key = 'telegram_bot_token'")->fetchColumn();
|
|
$tgChat = $pdo->query("SELECT value FROM admin.alert_config WHERE key = 'telegram_chat_id'")->fetchColumn();
|
|
$result = ['telegram' => false, 'email' => false];
|
|
if ($tgToken && $tgChat) {
|
|
$text = "🧪 *Test Alert from WEVAL SEND*\n\nYour alert system is working!";
|
|
$response = @file_get_contents("https://api.telegram.org/bot{$tgToken}/sendMessage?" . http_build_query(['chat_id' => $tgChat, 'text' => $text, 'parse_mode' => 'Markdown']));
|
|
$result['telegram'] = $response !== false;
|
|
}
|
|
echo json_encode($result);
|
|
break;
|
|
|
|
default:
|
|
echo json_encode(['error' => 'Unknown action']);
|
|
}
|
|
exit;
|
|
}
|
|
?>
|
|
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Alert System - WEVAL SEND</title>
|
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
|
<style>
|
|
:root{--bg:#0a0a0f;--card:#12121a;--card2:#1a1a25;--border:#2a2a3a;--text:#e4e4e7;--text2:#9ca3af;--primary:#6366f1;--success:#10b981;--warning:#f59e0b;--danger:#ef4444}
|
|
*{margin:0;padding:0;box-sizing:border-box}
|
|
body{font-family:'Inter',sans-serif;background:var(--bg);color:var(--text);padding:20px}
|
|
.container{max-width:1000px;margin:0 auto}
|
|
h1{margin-bottom:24px;display:flex;align-items:center;gap:12px}
|
|
h1 i{color:var(--warning)}
|
|
.grid{display:grid;grid-template-columns:1fr 1fr;gap:20px;margin-bottom:20px}
|
|
@media(max-width:768px){.grid{grid-template-columns:1fr}}
|
|
.card{background:var(--card);border-radius:12px;border:1px solid var(--border);overflow:hidden}
|
|
.card-header{padding:16px 20px;border-bottom:1px solid var(--border);display:flex;justify-content:space-between;align-items:center}
|
|
.card-header h2{font-size:16px;display:flex;align-items:center;gap:8px}
|
|
.card-body{padding:20px}
|
|
.form-group{margin-bottom:16px}
|
|
.form-group label{display:block;margin-bottom:6px;font-size:13px;color:var(--text2)}
|
|
.form-group input{width:100%;padding:10px 14px;background:var(--card2);border:1px solid var(--border);border-radius:8px;color:var(--text);font-size:14px}
|
|
.btn{padding:10px 20px;border:none;border-radius:8px;cursor:pointer;font-weight:600;font-size:13px;display:inline-flex;align-items:center;gap:8px}
|
|
.btn-primary{background:var(--primary);color:white}
|
|
.btn-success{background:var(--success);color:white}
|
|
.btn-warning{background:var(--warning);color:black}
|
|
.btn-sm{padding:6px 12px;font-size:12px}
|
|
.alert-item{padding:14px;background:var(--card2);border-radius:8px;margin-bottom:10px;border-left:4px solid var(--border)}
|
|
.alert-item.critical{border-left-color:var(--danger)}
|
|
.alert-item.warning{border-left-color:var(--warning)}
|
|
.alert-item.info{border-left-color:var(--primary)}
|
|
.alert-title{font-weight:600;margin-bottom:6px}
|
|
.alert-meta{font-size:12px;color:var(--text2)}
|
|
.badge{padding:3px 8px;border-radius:12px;font-size:11px;font-weight:600}
|
|
.badge-success{background:rgba(16,185,129,0.2);color:var(--success)}
|
|
.badge-danger{background:rgba(239,68,68,0.2);color:var(--danger)}
|
|
.status-dot{width:8px;height:8px;border-radius:50%;display:inline-block;margin-right:6px}
|
|
.status-dot.ok{background:var(--success)}
|
|
.status-dot.error{background:var(--danger)}
|
|
.toast{position:fixed;bottom:20px;right:20px;background:var(--card);border:1px solid var(--border);padding:14px 20px;border-radius:8px;display:none}
|
|
.toast.show{display:flex;align-items:center;gap:10px}
|
|
.toast.success{border-left:4px solid var(--success)}
|
|
.toast.error{border-left:4px solid var(--danger)}
|
|
</style>
|
|
|
|
</head>
|
|
<body>
|
|
<div class="container">
|
|
<h1><i class="fas fa-bell"></i> Alert System Configuration</h1>
|
|
<div class="grid">
|
|
<div class="card">
|
|
<div class="card-header"><h2><i class="fab fa-telegram"></i> Telegram</h2><span id="tgStatus"></span></div>
|
|
<div class="card-body">
|
|
<div class="form-group"><label>Bot Token</label><input type="text" id="telegram_bot_token" placeholder="123456:ABC-DEF..."></div>
|
|
<div class="form-group"><label>Chat ID</label><input type="text" id="telegram_chat_id" placeholder="-1001234567890"></div>
|
|
<button class="btn btn-primary" onclick="saveConfig()"><i class="fas fa-save"></i> Save</button>
|
|
<button class="btn btn-warning btn-sm" onclick="testNotif()"><i class="fas fa-paper-plane"></i> Test</button>
|
|
</div>
|
|
</div>
|
|
<div class="card">
|
|
<div class="card-header"><h2><i class="fas fa-envelope"></i> Email</h2><span id="emailStatus"></span></div>
|
|
<div class="card-body">
|
|
<div class="form-group"><label>Alert Email</label><input type="email" id="alert_email" placeholder="admin@example.com"></div>
|
|
<button class="btn btn-primary" onclick="saveConfig()"><i class="fas fa-save"></i> Save</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="card" style="margin-bottom:20px">
|
|
<div class="card-header"><h2><i class="fas fa-cogs"></i> Actions</h2></div>
|
|
<div class="card-body" style="display:flex;gap:10px;flex-wrap:wrap">
|
|
<button class="btn btn-success" onclick="runChecks()"><i class="fas fa-play"></i> Run All Checks Now</button>
|
|
<button class="btn btn-warning" onclick="loadHistory()"><i class="fas fa-history"></i> Refresh History</button>
|
|
</div>
|
|
</div>
|
|
<div class="card">
|
|
<div class="card-header"><h2><i class="fas fa-history"></i> Alert History</h2><span class="badge badge-warning" id="alertCount">0 alerts</span></div>
|
|
<div class="card-body" id="historyContainer" style="max-height:400px;overflow-y:auto"><p style="color:var(--text2);text-align:center">Loading...</p></div>
|
|
</div>
|
|
<div class="card" style="margin-top:20px">
|
|
<div class="card-header"><h2><i class="fas fa-clock"></i> Cron Setup</h2></div>
|
|
<div class="card-body">
|
|
<p style="margin-bottom:12px;color:var(--text2)">Add this cron job to run checks every 15 minutes:</p>
|
|
<code style="display:block;background:var(--card2);padding:12px;border-radius:6px;font-size:13px">*/15 * * * * curl -s "http://localhost:5821/alert-system.php?action=run_checks" > /dev/null</code>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="toast" id="toast"><i class="fas fa-check"></i><span id="toastText"></span></div>
|
|
<script>
|
|
async function loadConfig(){const c=await fetch('?action=config').then(r=>r.json());document.getElementById('telegram_bot_token').value=c.telegram_bot_token||'';document.getElementById('telegram_chat_id').value=c.telegram_chat_id||'';document.getElementById('alert_email').value=c.alert_email||'';document.getElementById('tgStatus').innerHTML=c.telegram_bot_token?'<span class="status-dot ok"></span>Configured':'<span class="status-dot error"></span>Not configured';document.getElementById('emailStatus').innerHTML=c.alert_email?'<span class="status-dot ok"></span>Configured':'<span class="status-dot error"></span>Not configured'}
|
|
async function saveConfig(){const d=new FormData();d.append('telegram_bot_token',document.getElementById('telegram_bot_token').value);d.append('telegram_chat_id',document.getElementById('telegram_chat_id').value);d.append('alert_email',document.getElementById('alert_email').value);await fetch('?action=config',{method:'POST',body:d});toast('Configuration saved!','success');loadConfig()}
|
|
async function testNotif(){toast('Sending test...','warning');const r=await fetch('?action=test').then(r=>r.json());if(r.telegram)toast('Telegram test sent!','success');else toast('Telegram test failed','error')}
|
|
async function runChecks(){toast('Running checks...','info');const r=await fetch('?action=run_checks').then(r=>r.json());if(r.alerts&&r.alerts.length>0)toast(`Found ${r.alerts.length} alert(s)!`,'warning');else toast('All checks passed!','success');loadHistory()}
|
|
async function loadHistory(){const h=await fetch('?action=history').then(r=>r.json());document.getElementById('alertCount').textContent=h.length+' alerts';const c=document.getElementById('historyContainer');if(!h.length){c.innerHTML='<p style="color:var(--text2);text-align:center">No alerts yet</p>';return}c.innerHTML=h.map(a=>`<div class="alert-item ${a.severity}"><div class="alert-title">${a.title}</div><div style="font-size:13px;color:var(--text2);margin-bottom:8px">${a.message}</div><div class="alert-meta"><i class="fas fa-clock"></i> ${new Date(a.created_at).toLocaleString()} | Telegram: ${a.sent_telegram?'✓':'✗'}</div></div>`).join('')}
|
|
function toast(msg,type='info'){const t=document.getElementById('toast');t.className='toast show '+type;document.getElementById('toastText').textContent=msg;setTimeout(()=>t.classList.remove('show'),3000)}
|
|
loadConfig();loadHistory();
|
|
</script>
|
|
|
|
</body>
|
|
</html>
|