exec("CREATE TABLE IF NOT EXISTS chats ( id_chat INT AUTO_INCREMENT PRIMARY KEY, id_account INT NOT NULL, id_occupant INT NOT NULL, sender ENUM('account', 'occupant') NOT NULL, message TEXT NOT NULL, is_read TINYINT DEFAULT 0, deleted_by_occupant TINYINT DEFAULT 0, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4"); // Automatically add columns to existing tables if updating try { $pdo->exec("ALTER TABLE chats ADD COLUMN deleted_by_occupant TINYINT DEFAULT 0 AFTER is_read"); } catch(PDOException $e) { /* Column likely exists */ } try { $pdo->exec("ALTER TABLE occupant ADD COLUMN last_active DATETIME NULL"); } catch(PDOException $e) { /* Column likely exists */ } try { $pdo->exec("ALTER TABLE occupant ADD COLUMN telegram_id VARCHAR(100) NULL AFTER no_hp"); } catch(PDOException $e) { /* Column likely exists */ } try { $pdo->exec("ALTER TABLE chats ADD COLUMN telegram_msg_id INT NULL AFTER id_chat"); } catch(PDOException $e) { /* Column likely exists */ } try { $pdo->exec("ALTER TABLE chats ADD COLUMN reply_to_chat_id INT NULL AFTER telegram_msg_id"); } catch(PDOException $e) { /* Column likely exists */ } try { $pdo->exec("ALTER TABLE chats ADD COLUMN is_pinned TINYINT DEFAULT 0 AFTER reply_to_chat_id"); } catch(PDOException $e) { /* Column likely exists */ } // AUTO CLEANUP: Hapus chat yang usianya lebih dari 3 hari (72 Jam) try { $pdo->exec("DELETE FROM chats WHERE created_at < NOW() - INTERVAL 3 DAY AND is_pinned = 0"); } catch(PDOException $e) {} if ($action === 'get_contacts') { // Fetch all occupants, join with latest message and unread count $stmt = $pdo->query("SELECT o.*, (SELECT message FROM chats c WHERE c.id_occupant = o.id_occupant AND c.id_account = $id_account ORDER BY c.created_at DESC LIMIT 1) as last_message, (SELECT created_at FROM chats c WHERE c.id_occupant = o.id_occupant AND c.id_account = $id_account ORDER BY c.created_at DESC LIMIT 1) as last_time, (SELECT COUNT(*) FROM chats c WHERE c.id_occupant = o.id_occupant AND c.id_account = $id_account AND c.sender = 'occupant' AND c.is_read = 0) as unread_count FROM occupant o WHERE (SELECT id_chat FROM chats c WHERE c.id_occupant = o.id_occupant AND c.id_account = $id_account LIMIT 1) IS NOT NULL OR o.telegram_id IS NOT NULL ORDER BY last_time DESC, o.name ASC"); $contacts = $stmt->fetchAll(); // Add default avatar handling foreach ($contacts as &$contact) { if (empty($contact['foto']) || !file_exists($contact['foto'])) { $contact['foto'] = 'images/faces/user.jpg'; } } echo json_encode(['status' => 'success', 'data' => $contacts]); exit; } if ($action === 'get_messages') { $id_occupant = isset($_POST['id_occupant']) ? (int)$_POST['id_occupant'] : 0; // Optional parameter to know who is fetching $viewer = isset($_POST['viewer']) ? $_POST['viewer'] : 'account'; if ($viewer === 'occupant') { // Update their online status since they are fetching messages $updateLastActive = $pdo->prepare("UPDATE occupant SET last_active = NOW() WHERE id_occupant = ?"); $updateLastActive->execute([$id_occupant]); } // Mark messages as read based on who is viewing if ($viewer === 'account') { $updateStmt = $pdo->prepare("UPDATE chats SET is_read = 1 WHERE id_account = ? AND id_occupant = ? AND sender = 'occupant' AND is_read = 0"); } else { $updateStmt = $pdo->prepare("UPDATE chats SET is_read = 1 WHERE id_account = ? AND id_occupant = ? AND sender = 'account' AND is_read = 0"); } $updateStmt->execute([$id_account, $id_occupant]); // Fetch messages if ($viewer === 'occupant') { // If viewed by occupant, don't show deleted ones $stmt = $pdo->prepare(" SELECT c.*, r.message as reply_message, r.sender as reply_sender, r.id_chat as reply_id_chat FROM chats c LEFT JOIN chats r ON c.reply_to_chat_id = r.id_chat WHERE c.id_account = ? AND c.id_occupant = ? AND c.deleted_by_occupant = 0 ORDER BY c.created_at ASC "); } else { $stmt = $pdo->prepare(" SELECT c.*, r.message as reply_message, r.sender as reply_sender, r.id_chat as reply_id_chat FROM chats c LEFT JOIN chats r ON c.reply_to_chat_id = r.id_chat WHERE c.id_account = ? AND c.id_occupant = ? ORDER BY c.created_at ASC "); } $stmt->execute([$id_account, $id_occupant]); $messages = $stmt->fetchAll(); // Fetch pinned message $pinStmt = $pdo->prepare("SELECT * FROM chats WHERE id_account = ? AND id_occupant = ? AND is_pinned = 1 ORDER BY created_at DESC LIMIT 1"); $pinStmt->execute([$id_account, $id_occupant]); $pinned = $pinStmt->fetch(); // Fetch occupant details for header $occStmt = $pdo->prepare("SELECT * FROM occupant WHERE id_occupant = ?"); $occStmt->execute([$id_occupant]); $occupant = $occStmt->fetch(); if (empty($occupant['foto']) || !file_exists($occupant['foto'])) { $occupant['foto'] = 'images/faces/user.jpg'; } echo json_encode(['status' => 'success', 'data' => $messages, 'occupant' => $occupant, 'pinned' => $pinned]); exit; } if ($action === 'send_message') { $id_occupant = isset($_POST['id_occupant']) ? (int)$_POST['id_occupant'] : 0; $message = isset($_POST['message']) ? trim($_POST['message']) : ''; $sender = isset($_POST['sender']) ? $_POST['sender'] : 'account'; $reply_to_chat_id = isset($_POST['reply_to_chat_id']) ? (int)$_POST['reply_to_chat_id'] : null; // Process File Upload if present $hasAttachment = false; $attachmentPath = ""; $attachmentName = ""; $tgEndpoint = "sendMessage"; $tgFileType = ""; $localHtml = ""; if (isset($_FILES['attachment']) && $_FILES['attachment']['error'] === UPLOAD_ERR_OK) { $hasAttachment = true; $tmpName = $_FILES['attachment']['tmp_name']; $attachmentName = $_FILES['attachment']['name']; $ext = strtolower(pathinfo($attachmentName, PATHINFO_EXTENSION)); $newFileName = time() . '_' . rand(1000, 9999) . '.' . $ext; $uploadDir = __DIR__ . '/images/chat_uploads/'; if (!is_dir($uploadDir)) mkdir($uploadDir, 0755, true); $attachmentPath = $uploadDir . $newFileName; move_uploaded_file($tmpName, $attachmentPath); $urlRelative = "images/chat_uploads/" . $newFileName; // Determine type for local HTML and Telegram API $photoExts = ['jpg', 'jpeg', 'png', 'gif', 'webp']; $audioExts = ['webm', 'ogg', 'mp3', 'wav', 'oga']; if (in_array($ext, $photoExts)) { $tgEndpoint = "sendPhoto"; $tgFileType = "photo"; // msg-type-img will be applied via JS if the content only contains this wrap $localHtml = "
"; } else if (in_array($ext, $audioExts)) { $tgEndpoint = "sendVoice"; $tgFileType = "voice"; $localHtml = "
0:00
"; } else { $tgEndpoint = "sendDocument"; $tgFileType = "document"; $extLow = strtolower($ext); $iconClass = 'mdi-file-document-outline'; $bgIconColor = '#94a3b8'; // default slate if ($extLow === 'pdf') { $iconClass = 'mdi-file-pdf-box'; $bgIconColor = '#ef4444'; } // red else if (in_array($extLow, ['doc','docx'])) { $iconClass = 'mdi-file-word-box'; $bgIconColor = '#3b82f6'; } // blue else if (in_array($extLow, ['xls','xlsx'])) { $iconClass = 'mdi-file-excel-box'; $bgIconColor = '#10b981'; } // green $fileSize = round(filesize($attachmentPath) / 1024); $sizeStr = $fileSize > 1024 ? round($fileSize/1024, 1) . ' MB' : $fileSize . ' KB'; $typeStr = strtoupper($extLow); $localHtml = "
Open Save as...
"; } // Append text message as caption to local HTML if (!empty($message)) { $localHtml .= "
".htmlspecialchars($message)."
"; } } else { $localHtml = htmlspecialchars($message); // no attachment, just text } if ($sender === 'occupant') { // Keeps occupant online $updateLastActive = $pdo->prepare("UPDATE occupant SET last_active = NOW() WHERE id_occupant = ?"); $updateLastActive->execute([$id_occupant]); } // Only proceed if there is text or an attachment if ($id_occupant > 0 && (!empty($message) || $hasAttachment)) { $stmt = $pdo->prepare("INSERT INTO chats (id_account, id_occupant, sender, message, reply_to_chat_id) VALUES (?, ?, ?, ?, ?)"); if ($stmt->execute([$id_account, $id_occupant, $sender, $localHtml, $reply_to_chat_id])) { $id_chat = $pdo->lastInsertId(); // Fetch Telegram Reply ID if replying $tgReplyId = null; if ($reply_to_chat_id) { $qRep = $pdo->prepare("SELECT telegram_msg_id FROM chats WHERE id_chat = ? LIMIT 1"); $qRep->execute([$reply_to_chat_id]); $fRep = $qRep->fetch(); if ($fRep && $fRep['telegram_msg_id']) { $tgReplyId = $fRep['telegram_msg_id']; } } // +++++ SEND TO TELEGRAM IF SENDER IS ACCOUNT +++++ if ($sender === 'account') { $telStmt = $pdo->prepare("SELECT telegram_id FROM occupant WHERE id_occupant = ?"); $telStmt->execute([$id_occupant]); $telegramUser = $telStmt->fetch(); if ($telegramUser && !empty($telegramUser['telegram_id'])) { $botToken = "8184881871:AAFOz6uzIgxE7rk3WttcKKrr0DtcNGIt-Ho"; $website = "https://api.telegram.org/bot".$botToken; $postData = [ 'chat_id' => $telegramUser['telegram_id'] ]; // IF Replying if ($tgReplyId) { $postData['reply_to_message_id'] = $tgReplyId; } // IF Attachment if ($hasAttachment) { $postData[$tgFileType] = new CURLFile($attachmentPath); if (!empty($message)) { $postData['caption'] = $message; } } else { $postData['text'] = $message; } $ch = curl_init($website."/".$tgEndpoint); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $postData); curl_setopt($ch, CURLOPT_TIMEOUT, 30); $result = curl_exec($ch); curl_close($ch); if ($result) { $resJson = json_decode($result, true); if (isset($resJson['ok']) && $resJson['ok'] && isset($resJson['result']['message_id'])) { $tgMsgId = $resJson['result']['message_id']; $updateMsg = $pdo->prepare("UPDATE chats SET telegram_msg_id = ? WHERE id_chat = ?"); $updateMsg->execute([$tgMsgId, $id_chat]); } } } } // +++++++++++++++++++++++++++++++++++++++++++++++++ // WEB PUSH NOTIFICATION DISPATCH if ($sender === 'occupant') { // Occupant sends message -> Notify Admins // Fetch occupant name to display in the push body $qOcc = $pdo->prepare("SELECT name FROM occupant WHERE id_occupant = ?"); $qOcc->execute([$id_occupant]); $occName = $qOcc->fetchColumn() ?: "Resident"; $pushTitle = "New Message from {$occName}"; $pushBody = strip_tags($localHtml); PushHelper::broadcastToAdmins($pdo, $pushTitle, $pushBody, '/chats.php'); } else { // Admin sends message -> Notify the specific Occupant $pushTitle = "New Message from Admin"; $pushBody = strip_tags($localHtml); PushHelper::sendPush($pdo, $id_occupant, $pushTitle, $pushBody, '/chats.php'); } $msgStmt = $pdo->prepare("SELECT * FROM chats WHERE id_chat = ?"); $msgStmt->execute([$id_chat]); $newMsg = $msgStmt->fetch(); echo json_encode(['status' => 'success', 'data' => $newMsg]); exit; } } echo json_encode(['status' => 'error', 'message' => 'Invalid data']); exit; } if ($action === 'login_occupant') { $no_hp = isset($_POST['no_hp']) ? trim($_POST['no_hp']) : ''; $pin = isset($_POST['pin']) ? trim($_POST['pin']) : ''; if (empty($no_hp) || empty($pin)) { echo json_encode(['status' => 'error', 'message' => 'Lengkapi form.']); exit; } $stmt = $pdo->prepare("SELECT id_occupant, name, status, access FROM occupant WHERE no_hp = ?"); $stmt->execute([$no_hp]); $occ = $stmt->fetch(); if ($occ) { if ($occ['status'] !== 'approved' || $occ['access'] !== 'active') { echo json_encode(['status' => 'error', 'message' => 'Akun belum disetujui atau sedang tidak aktif.']); exit; } $verifyStmt = $pdo->prepare("SELECT id_occupant FROM occupant WHERE no_hp = ? AND pin = ?"); $verifyStmt->execute([$no_hp, $pin]); if ($verifyStmt->fetch()) { $_SESSION['chat_occupant_id'] = $occ['id_occupant']; echo json_encode(['status' => 'success', 'data' => $occ]); exit; } } echo json_encode(['status' => 'error', 'message' => 'No HP atau PIN salah.']); exit; } if ($action === 'delete_history') { $id_occupant = isset($_POST['id_occupant']) ? (int)$_POST['id_occupant'] : 0; if ($id_occupant > 0) { $stmt = $pdo->prepare("UPDATE chats SET deleted_by_occupant = 1 WHERE id_account = ? AND id_occupant = ?"); $stmt->execute([$id_account, $id_occupant]); echo json_encode(['status' => 'success', 'message' => 'Chat history deleted from your view.']); exit; } echo json_encode(['status' => 'error', 'message' => 'Invalid occupant ID.']); exit; } if ($action === 'delete_message') { $id_chat = isset($_POST['id_chat']) ? (int)$_POST['id_chat'] : 0; $delete_type = isset($_POST['delete_type']) ? $_POST['delete_type'] : 'me'; // 'me' or 'everyone' // Validate message belongs to account before deleting $stmt = $pdo->prepare("SELECT c.sender, c.telegram_msg_id, o.telegram_id FROM chats c LEFT JOIN occupant o ON c.id_occupant = o.id_occupant WHERE c.id_chat = ? AND c.id_account = ?"); $stmt->execute([$id_chat, $id_account]); $msg = $stmt->fetch(); if ($msg) { if ($msg['sender'] === 'account') { // It's the admin's message // Delete from Database $delStmt = $pdo->prepare("DELETE FROM chats WHERE id_chat = ?"); $delStmt->execute([$id_chat]); // Delete from Telegram if exists AND delete_type is 'everyone' if ($delete_type === 'everyone' && !empty($msg['telegram_msg_id']) && !empty($msg['telegram_id'])) { $botToken = "8184881871:AAFOz6uzIgxE7rk3WttcKKrr0DtcNGIt-Ho"; $website = "https://api.telegram.org/bot".$botToken; $postData = [ 'chat_id' => $msg['telegram_id'], 'message_id' => $msg['telegram_msg_id'] ]; $ch = curl_init($website."/deleteMessage"); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postData)); curl_setopt($ch, CURLOPT_TIMEOUT, 2); curl_exec($ch); curl_close($ch); } echo json_encode(['status' => 'success']); exit; } else { // It's the occupant's message // Based on user request, admin can now delete occupant messages from their own view (Delete for Me) // Occupant messages cannot be deleted from Telegram via bot API anyway $delStmt = $pdo->prepare("DELETE FROM chats WHERE id_chat = ?"); $delStmt->execute([$id_chat]); echo json_encode(['status' => 'success']); exit; } } echo json_encode(['status' => 'error', 'message' => 'Message not found']); exit; } // ── FORWARD MESSAGE ── if ($action === 'forward_message') { $id_chat = isset($_POST['id_chat']) ? (int)$_POST['id_chat'] : 0; $target_occupant = isset($_POST['target_occupant']) ? (int)$_POST['target_occupant'] : 0; if ($id_chat > 0 && $target_occupant > 0) { $srcStmt = $pdo->prepare("SELECT message FROM chats WHERE id_chat = ?"); $srcStmt->execute([$id_chat]); $srcMsg = $srcStmt->fetch(); if ($srcMsg) { $fwdHtml = "
Diteruskan
" . $srcMsg['message']; $insStmt = $pdo->prepare("INSERT INTO chats (id_account, id_occupant, sender, message) VALUES (?, ?, 'account', ?)"); $insStmt->execute([$id_account, $target_occupant, $fwdHtml]); $newId = $pdo->lastInsertId(); // Send to Telegram $telStmt = $pdo->prepare("SELECT telegram_id FROM occupant WHERE id_occupant = ?"); $telStmt->execute([$target_occupant]); $tgUser = $telStmt->fetch(); if ($tgUser && !empty($tgUser['telegram_id'])) { $botToken = "8184881871:AAFOz6uzIgxE7rk3WttcKKrr0DtcNGIt-Ho"; $plainText = strip_tags($srcMsg['message']); $postData = ['chat_id' => $tgUser['telegram_id'], 'text' => "[Diteruskan]\n" . $plainText]; $ch = curl_init("https://api.telegram.org/bot{$botToken}/sendMessage"); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $postData); curl_setopt($ch, CURLOPT_TIMEOUT, 5); $res = curl_exec($ch); curl_close($ch); if ($res) { $rj = json_decode($res, true); if (isset($rj['ok']) && $rj['ok'] && isset($rj['result']['message_id'])) { $pdo->prepare("UPDATE chats SET telegram_msg_id = ? WHERE id_chat = ?")->execute([$rj['result']['message_id'], $newId]); } } } echo json_encode(['status' => 'success']); exit; } } echo json_encode(['status' => 'error', 'message' => 'Invalid forward data']); exit; } // ── EDIT MESSAGE ── if ($action === 'edit_message') { $id_chat = isset($_POST['id_chat']) ? (int)$_POST['id_chat'] : 0; $new_message = isset($_POST['new_message']) ? trim($_POST['new_message']) : ''; if ($id_chat > 0 && !empty($new_message)) { // Only allow editing account messages $stmt = $pdo->prepare("SELECT sender, telegram_msg_id, (SELECT telegram_id FROM occupant WHERE id_occupant = chats.id_occupant) as telegram_id FROM chats WHERE id_chat = ? AND id_account = ?"); $stmt->execute([$id_chat, $id_account]); $msg = $stmt->fetch(); if ($msg && $msg['sender'] === 'account') { $formattedHtml = htmlspecialchars($new_message) . " "; // Update local DB $updStmt = $pdo->prepare("UPDATE chats SET message = ? WHERE id_chat = ?"); $updStmt->execute([$formattedHtml, $id_chat]); // Update Telegram if telegram_msg_id exists if (!empty($msg['telegram_msg_id']) && !empty($msg['telegram_id'])) { $botToken = "8184881871:AAFOz6uzIgxE7rk3WttcKKrr0DtcNGIt-Ho"; $postData = [ 'chat_id' => $msg['telegram_id'], 'message_id' => $msg['telegram_msg_id'], 'text' => $new_message ]; $ch = curl_init("https://api.telegram.org/bot{$botToken}/editMessageText"); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $postData); curl_setopt($ch, CURLOPT_TIMEOUT, 5); curl_exec($ch); curl_close($ch); } echo json_encode(['status' => 'success', 'new_message' => $formattedHtml]); exit; } } echo json_encode(['status' => 'error', 'message' => 'Cannot edit this message']); exit; } // ── BULK DELETE MESSAGES ── if ($action === 'bulk_delete_messages') { $ids = isset($_POST['id_chats']) ? $_POST['id_chats'] : []; $deleteType = isset($_POST['delete_type']) ? $_POST['delete_type'] : 'me'; // 'everyone' or 'me' if (is_array($ids) && count($ids) > 0) { $deletedCount = 0; foreach ($ids as $mid) { $mid = (int)$mid; if ($mid <= 0) continue; // Validate message ownership and info $stmt = $pdo->prepare("SELECT sender, telegram_msg_id, telegram_id FROM chats c LEFT JOIN occupant o ON c.id_occupant = o.id_occupant WHERE id_chat = ? AND id_account = ?"); $stmt->execute([$mid, $id_account]); $msg = $stmt->fetch(); if ($msg) { // Determine if we can delete from Telegram // Only 'account' messages can be deleted from Telegram by the bot. if ($deleteType === 'everyone' && $msg['sender'] === 'account' && !empty($msg['telegram_msg_id']) && !empty($msg['telegram_id'])) { $botToken = "8184881871:AAFOz6uzIgxE7rk3WttcKKrr0DtcNGIt-Ho"; $ch = curl_init("https://api.telegram.org/bot{$botToken}/deleteMessage"); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, [ 'chat_id' => $msg['telegram_id'], 'message_id' => $msg['telegram_msg_id'] ]); curl_setopt($ch, CURLOPT_TIMEOUT, 2); curl_exec($ch); curl_close($ch); } // Delete from DB (applies for both 'me' and 'everyone' types) $delStmt = $pdo->prepare("DELETE FROM chats WHERE id_chat = ? AND id_account = ?"); $delStmt->execute([$mid, $id_account]); $deletedCount++; } } echo json_encode(['status' => 'success', 'message' => "Berhasil menghapus $deletedCount pesan."]); exit; } echo json_encode(['status' => 'error', 'message' => 'Tidak ada pesan yang dipilih']); exit; } // ── PIN / UNPIN MESSAGE ── if ($action === 'pin_message') { $id_chat = isset($_POST['id_chat']) ? (int)$_POST['id_chat'] : 0; $id_occupant = isset($_POST['id_occupant']) ? (int)$_POST['id_occupant'] : 0; if ($id_chat > 0 && $id_occupant > 0) { // Unpin all first $pdo->prepare("UPDATE chats SET is_pinned = 0 WHERE id_account = ? AND id_occupant = ?")->execute([$id_account, $id_occupant]); // Pin this one $pdo->prepare("UPDATE chats SET is_pinned = 1 WHERE id_chat = ?")->execute([$id_chat]); echo json_encode(['status' => 'success']); exit; } echo json_encode(['status' => 'error']); exit; } if ($action === 'unpin_message') { $id_chat = isset($_POST['id_chat']) ? (int)$_POST['id_chat'] : 0; if ($id_chat > 0) { $pdo->prepare("UPDATE chats SET is_pinned = 0 WHERE id_chat = ?")->execute([$id_chat]); echo json_encode(['status' => 'success']); exit; } echo json_encode(['status' => 'error']); exit; } // ── DELETE MULTIPLE MESSAGES ── if ($action === 'delete_multiple') { $ids = isset($_POST['ids']) ? json_decode($_POST['ids'], true) : []; if (is_array($ids) && count($ids) > 0) { foreach ($ids as $mid) { $mid = (int)$mid; $stmt = $pdo->prepare("SELECT sender, telegram_msg_id, (SELECT telegram_id FROM occupant WHERE id_occupant = chats.id_occupant) as telegram_id FROM chats WHERE id_chat = ? AND id_account = ?"); $stmt->execute([$mid, $id_account]); $m = $stmt->fetch(); if ($m && $m['sender'] === 'account') { $pdo->prepare("DELETE FROM chats WHERE id_chat = ?")->execute([$mid]); if (!empty($m['telegram_msg_id']) && !empty($m['telegram_id'])) { $botToken = "8184881871:AAFOz6uzIgxE7rk3WttcKKrr0DtcNGIt-Ho"; $ch = curl_init("https://api.telegram.org/bot{$botToken}/deleteMessage"); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, ['chat_id' => $m['telegram_id'], 'message_id' => $m['telegram_msg_id']]); curl_setopt($ch, CURLOPT_TIMEOUT, 2); curl_exec($ch); curl_close($ch); } } } echo json_encode(['status' => 'success']); exit; } echo json_encode(['status' => 'error', 'message' => 'No IDs provided']); exit; } if ($action === 'request_call' && $id_occupant) { $telStmt = $pdo->prepare("SELECT telegram_id FROM occupant WHERE id_occupant = ?"); $telStmt->execute([$id_occupant]); $telegramUser = $telStmt->fetch(); if ($telegramUser && !empty($telegramUser['telegram_id'])) { $botToken = "8184881871:AAFOz6uzIgxE7rk3WttcKKrr0DtcNGIt-Ho"; $website = "https://api.telegram.org/bot".$botToken; $msg = "📞 *PANGGILAN DARI ADMIN*\n\nAdmin SkyDash sedang mencoba menghubungi Anda via sistem. Silakan merespon melalui obrolan ini."; $postData = [ 'chat_id' => $telegramUser['telegram_id'], 'text' => $msg, 'parse_mode' => 'Markdown' ]; $ch = curl_init($website."/sendMessage"); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $postData); curl_setopt($ch, CURLOPT_TIMEOUT, 10); $result = curl_exec($ch); curl_close($ch); if ($result) { $resJson = json_decode($result, true); if (isset($resJson['ok']) && $resJson['ok']) { echo json_encode(['status' => 'success']); exit; } } } echo json_encode(['status' => 'error', 'message' => 'Gagal menghubungi Telegram bot penghuni.']); exit; } echo json_encode(['status' => 'error', 'message' => 'Invalid action']);