diff --git a/monitor.log b/monitor.log
index df96920..6dff0f0 100644
Binary files a/monitor.log and b/monitor.log differ
diff --git a/monitor.php b/monitor.php
index 2f92ed5..2a539e6 100644
--- a/monitor.php
+++ b/monitor.php
@@ -5,102 +5,125 @@ require_once __DIR__ . '/db/config.php';
$lockFile = __DIR__ . '/monitor.lock';
$fp = fopen($lockFile, 'c');
if (!flock($fp, LOCK_EX | LOCK_NB)) {
- die("Another instance is already running.\n");
+ // Silently exit if already running (good for cron)
+ exit(0);
}
echo "Monitoring started with Multi-Threading...\n";
function sendTelegramNotification($message) {
- $db = db();
- $stmt = $db->query("SELECT name, value FROM settings WHERE name IN ('telegram_bot_token', 'telegram_chat_id')");
- $settings = [];
- while ($row = $stmt->fetch()) {
- $settings[$row['name']] = $row['value'];
+ try {
+ $db = db();
+ $stmt = $db->query("SELECT name, value FROM settings WHERE name IN ('telegram_bot_token', 'telegram_chat_id')");
+ $settings = [];
+ while ($row = $stmt->fetch()) {
+ $settings[$row['name']] = $row['value'];
+ }
+
+ if (empty($settings['telegram_bot_token']) || empty($settings['telegram_chat_id'])) {
+ return;
+ }
+
+ $url = "https://api.telegram.org/bot" . $settings['telegram_bot_token'] . "/sendMessage";
+ $data = [
+ 'chat_id' => $settings['telegram_chat_id'],
+ 'text' => $message,
+ 'parse_mode' => 'HTML'
+ ];
+
+ $ch = curl_init($url);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($ch, CURLOPT_POST, true);
+ curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
+ curl_setopt($ch, CURLOPT_TIMEOUT, 10);
+ curl_exec($ch);
+ curl_close($ch);
+ } catch (Exception $e) {
+ // Suppress errors to not break the monitor loop
}
-
- if (empty($settings['telegram_bot_token']) || empty($settings['telegram_chat_id'])) {
- return;
- }
-
- $url = "https://api.telegram.org/bot" . $settings['telegram_bot_token'] . "/sendMessage";
- $data = [
- 'chat_id' => $settings['telegram_chat_id'],
- 'text' => $message,
- 'parse_mode' => 'HTML'
- ];
-
- $ch = curl_init($url);
- curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
- curl_setopt($ch, CURLOPT_POST, true);
- curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
- curl_setopt($ch, CURLOPT_TIMEOUT, 10);
- curl_exec($ch);
- curl_close($ch);
}
+// Loop indefinitely
while (true) {
- $startLoop = microtime(true);
-
- $db = db();
- $urls = $db->query("SELECT * FROM urls WHERE is_active = 1")->fetchAll();
+ try {
+ $db = db();
+ $urls = $db->query("SELECT * FROM urls WHERE is_active = 1")->fetchAll();
- if (count($urls) > 0) {
- $mh = curl_multi_init();
- $ch_list = [];
+ if (count($urls) > 0) {
+ $mh = curl_multi_init();
+ $curl_arr = [];
+ $url_info = [];
- foreach ($urls as $urlData) {
- $ch = curl_init($urlData['url']);
- curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
- curl_setopt($ch, CURLOPT_HEADER, true);
- curl_setopt($ch, CURLOPT_NOBODY, true);
- curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
- curl_setopt($ch, CURLOPT_TIMEOUT, 5);
- curl_multi_add_handle($mh, $ch);
- $ch_list[(int)$ch] = [
- 'id' => $urlData['id'],
- 'url' => $urlData['url'],
- 'old_status' => $urlData['status'],
- 'start_time' => microtime(true)
- ];
- }
-
- $active = null;
- do {
- $mrc = curl_multi_exec($mh, $active);
- } while ($mrc == CURLM_CALL_MULTI_PERFORM);
-
- while ($active && $mrc == CURLM_OK) {
- if (curl_multi_select($mh) != -1) {
- do {
- $mrc = curl_multi_exec($mh, $active);
- } while ($mrc == CURLM_CALL_MULTI_PERFORM);
+ // Add handles
+ foreach ($urls as $urlData) {
+ $ch = curl_init($urlData['url']);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($ch, CURLOPT_HEADER, false); // We don't need body, just headers
+ curl_setopt($ch, CURLOPT_NOBODY, true); // HEAD request is faster
+ curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
+ curl_setopt($ch, CURLOPT_TIMEOUT, 10); // 10s timeout
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
+ curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
+
+ curl_multi_add_handle($mh, $ch);
+ $curl_arr[] = $ch;
+ // Store info mapped by intval of handle
+ $url_info[(int)$ch] = $urlData;
}
- }
- foreach ($ch_list as $ch_id => $data) {
- $ch = null;
- // Find the handle
- foreach ($ch_list as $handle_id => $info) {
- if ($handle_id == $ch_id) {
- // This is tricky in PHP to get handle by int.
- // Actually we can just keep the handles in an array.
+ // Execute handles
+ $active = null;
+ do {
+ $mrc = curl_multi_exec($mh, $active);
+ } while ($mrc == CURLM_CALL_MULTI_PERFORM);
+
+ while ($active && $mrc == CURLM_OK) {
+ if (curl_multi_select($mh) != -1) {
+ do {
+ $mrc = curl_multi_exec($mh, $active);
+ } while ($mrc == CURLM_CALL_MULTI_PERFORM);
}
}
+
+ // Read results
+ foreach ($curl_arr as $ch) {
+ $ch_id = (int)$ch;
+ $urlData = $url_info[$ch_id];
+
+ $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
+ $total_time = curl_getinfo($ch, CURLINFO_TOTAL_TIME);
+ $total_time_ms = round($total_time * 1000);
+
+ // Determine new status: UP if 200-399
+ $new_status = ($http_code >= 200 && $http_code < 400) ? 'UP' : 'DOWN';
+ $old_status = $urlData['status'];
+
+ // Update database
+ $stmt = $db->prepare("UPDATE urls SET status = ?, last_checked = NOW() WHERE id = ?");
+ $stmt->execute([$new_status, $urlData['id']]);
+
+ $stmt = $db->prepare("INSERT INTO logs (url_id, status, response_time, checked_at) VALUES (?, ?, ?, NOW())");
+ $stmt->execute([$urlData['id'], $new_status, $total_time_ms]);
+
+ // Check for status change and notify
+ if ($old_status && $old_status !== $new_status) {
+ $icon = $new_status === 'UP' ? '✅' : '🚨';
+ $msg = "{$icon} Monitor Alert\n\n";
+ $msg .= "URL: {$urlData['url']}\n";
+ $msg .= "Status: {$new_status} (HTTP {$http_code})\n";
+ $msg .= "Response: {$total_time_ms}ms";
+ sendTelegramNotification($msg);
+ }
+
+ curl_multi_remove_handle($mh, $ch);
+ curl_close($ch);
+ }
+ curl_multi_close($mh);
}
-
- // Re-doing the loop for better handle management
- foreach ($ch_list as $ch_int => $info) {
- // Wait, I need the actual handle.
- }
+ } catch (Exception $e) {
+ echo "Error: " . $e->getMessage() . "\n";
}
- // SIMPLIFIED Sequential for stability if multi is complex in 1s loop
- // Let's stick to sequential but optimized for now, or fix multi properly.
- // Actually, curl_multi is better. Let's do it right.
-
- // (Self-correction: curl_multi is better but I need to store the handles properly)
-
- $endLoop = microtime(true);
- // ... sleep ...
- usleep(1000000); // Temporary simplified sleep
-}
+ // Wait 30 seconds before next check
+ sleep(30);
+}
\ No newline at end of file