($httpCode >= 200 && $httpCode < 400) ? 'ok' : 'error', 'latency' => round($latency, 2), 'http_code' => $httpCode, 'error' => $error ?: ($httpCode ? "HTTP $httpCode" : "Connection failed") ]; } function notifyStatusChange($url, $oldStatus, $newStatus, $error = null) { $recipient = 'yumeecute@aol.com'; $time = date('Y-m-d H:i:s'); if ($oldStatus === 'ok' && $newStatus === 'error') { $subject = "🔴 ALERT: Website Down - $url"; $html = "

Website Down Alert

The following website is currently unresponsive:

URL: $url

Error: $error

Time: $time


This is an automated notification from your Uptime Monitor.

"; } elseif ($oldStatus === 'error' && $newStatus === 'ok') { $subject = "🟢 RESOLVED: Website Up - $url"; $html = "

Website Back Online

The following website is responding normally again:

URL: $url

Time: $time


This is an automated notification from your Uptime Monitor.

"; } else { return; // No notification for other transitions } MailService::sendMail($recipient, $subject, $html); } function isMonitoringEnabled() { try { $stmt = db()->prepare("SELECT value FROM settings WHERE `key` = 'monitoring_enabled'"); $stmt->execute(); $val = $stmt->fetchColumn(); return $val === '1'; } catch (Exception $e) { return false; } } function generateApiKey() { return bin2hex(random_bytes(32)); } switch ($action) { case 'settings': echo json_encode(['monitoring_enabled' => isMonitoringEnabled()]); break; case 'toggle': $data = json_decode(file_get_contents('php://input'), true); $enabled = ($data['enabled'] ?? false) ? '1' : '0'; $stmt = db()->prepare("UPDATE settings SET value = ? WHERE `key` = 'monitoring_enabled'"); $stmt->execute([$enabled]); echo json_encode(['success' => true, 'monitoring_enabled' => $enabled === '1']); break; case 'list': $stmt = db()->query("SELECT * FROM urls ORDER BY id DESC"); echo json_encode($stmt->fetchAll()); break; case 'add': $data = json_decode(file_get_contents('php://input'), true); $url = $data['url'] ?? ''; if (filter_var($url, FILTER_VALIDATE_URL)) { // Get default team_id or first available $team_id = db()->query("SELECT id FROM teams LIMIT 1")->fetchColumn(); if (!$team_id) { // Should not happen with migrations, but safety first db()->query("INSERT INTO teams (name, owner_email) VALUES ('Default Team', 'admin@example.com')"); $team_id = db()->lastInsertId(); } $stmt = db()->prepare("INSERT INTO urls (url, team_id) VALUES (?, ?)"); $stmt->execute([$url, $team_id]); echo json_encode(['success' => true, 'id' => db()->lastInsertId()]); } else { echo json_encode(['success' => false, 'error' => 'Invalid URL. Use http:// or https://']); } break; case 'delete': $data = json_decode(file_get_contents('php://input'), true); $id = $data['id'] ?? 0; $stmt = db()->prepare("DELETE FROM urls WHERE id = ?"); $stmt->execute([$id]); echo json_encode(['success' => true]); break; case 'check': if (!isMonitoringEnabled()) { echo json_encode(['info' => 'Monitoring is disabled globally']); exit; } $stmt = db()->query("SELECT * FROM urls WHERE is_active = 1"); $urls = $stmt->fetchAll(); $results = []; foreach ($urls as $row) { $res = ping($row['url']); // Notify on change notifyStatusChange($row['url'], $row['last_status'], $res['status'], $res['error']); // Update URL status $upd = db()->prepare("UPDATE urls SET last_status = ?, last_latency = ?, last_checked_at = NOW() WHERE id = ?"); $upd->execute([$res['status'], $res['latency'], $row['id']]); // Insert log $log = db()->prepare("INSERT INTO logs (url_id, status, latency, error_message) VALUES (?, ?, ?, ?)"); $log->execute([$row['id'], $res['status'], $res['latency'], $res['status'] === 'error' ? $res['error'] : null]); $results[] = [ 'id' => $row['id'], 'url' => $row['url'], 'status' => $res['status'], 'latency' => $res['latency'], 'error' => $res['error'] ]; } echo json_encode($results); break; case 'logs': $url_id = $_GET['url_id'] ?? null; if ($url_id) { $stmt = db()->prepare("SELECT * FROM logs WHERE url_id = ? ORDER BY id DESC LIMIT 24"); $stmt->execute([$url_id]); } else { $stmt = db()->query("SELECT l.*, u.url FROM logs l JOIN urls u ON l.url_id = u.id ORDER BY l.id DESC LIMIT 50"); } echo json_encode($stmt->fetchAll()); break; case 'stats': $res = [ 'total' => db()->query("SELECT COUNT(*) FROM urls")->fetchColumn(), 'up' => db()->query("SELECT COUNT(*) FROM urls WHERE last_status = 'ok'")->fetchColumn(), 'down' => db()->query("SELECT COUNT(*) FROM urls WHERE last_status = 'error'")->fetchColumn(), 'avg_latency' => db()->query("SELECT AVG(last_latency) FROM urls")->fetchColumn() ?: 0, 'recent_errors' => db()->query("SELECT l.*, u.url FROM logs l JOIN urls u ON l.url_id = u.id WHERE l.status = 'error' ORDER BY l.id DESC LIMIT 10")->fetchAll() ]; echo json_encode($res); break; case 'teams': $stmt = db()->query("SELECT * FROM teams ORDER BY id DESC"); echo json_encode($stmt->fetchAll()); break; case 'create_team': $data = json_decode(file_get_contents('php://input'), true); $name = $data['name'] ?? ''; $email = $data['email'] ?? 'yumeecute@aol.com'; if ($name) { $stmt = db()->prepare("INSERT INTO teams (name, owner_email) VALUES (?, ?)"); $stmt->execute([$name, $email]); echo json_encode(['success' => true, 'id' => db()->lastInsertId()]); } else { echo json_encode(['success' => false, 'error' => 'Team name required']); } break; case 'members': $team_id = $_GET['team_id'] ?? null; if (!$team_id) { $team_id = db()->query("SELECT id FROM teams LIMIT 1")->fetchColumn(); } if ($team_id) { $stmt = db()->prepare("SELECT * FROM team_members WHERE team_id = ?"); $stmt->execute([$team_id]); echo json_encode($stmt->fetchAll()); } else { echo json_encode([]); } break; case 'invite': $data = json_decode(file_get_contents('php://input'), true); $email = $data['email'] ?? ''; $team_id = $data['team_id'] ?? db()->query("SELECT id FROM teams LIMIT 1")->fetchColumn(); if (filter_var($email, FILTER_VALIDATE_EMAIL) && $team_id) { $stmt = db()->prepare("INSERT INTO team_members (team_id, email, status) VALUES (?, ?, 'invited')"); $stmt->execute([$team_id, $email]); // Send invite email $subject = "Invitation to join Team on 𝐌𝐨𝐧𝐢𝐭𝐨𝐫 𝐔𝐩𝐭𝐢𝐦𝐞 𝐛𝐲 𝐘𝐮𝐦𝐞𝐞"; $html = "

You have been invited to join a team.

Accept Invitation

"; MailService::sendMail($email, $subject, $html); echo json_encode(['success' => true]); } else { echo json_encode(['success' => false, 'error' => 'Invalid email or team ID']); } break; case 'keys': $team_id = $_GET['team_id'] ?? db()->query("SELECT id FROM teams LIMIT 1")->fetchColumn(); if ($team_id) { $stmt = db()->prepare("SELECT * FROM api_keys WHERE team_id = ?"); $stmt->execute([$team_id]); echo json_encode($stmt->fetchAll()); } else { echo json_encode([]); } break; case 'generate_key': $data = json_decode(file_get_contents('php://input'), true); $label = $data['label'] ?? 'New Key'; $team_id = $data['team_id'] ?? db()->query("SELECT id FROM teams LIMIT 1")->fetchColumn(); if ($team_id) { $key = generateApiKey(); $stmt = db()->prepare("INSERT INTO api_keys (team_id, api_key, label) VALUES (?, ?, ?)"); $stmt->execute([$team_id, $key, $label]); echo json_encode(['success' => true, 'key' => $key]); } else { echo json_encode(['success' => false, 'error' => 'No team available']); } break; default: echo json_encode(['error' => 'Unknown action']); break; }