242 lines
13 KiB
PHP
242 lines
13 KiB
PHP
<?php
|
|
// bot_polling.php - Script untuk menjalankan Telegram Bot via Long Polling di Localhost
|
|
// Jalankan via CLI: php bot_polling.php
|
|
|
|
include 'koneksi.php';
|
|
|
|
$botToken = "8184881871:AAFOz6uzIgxE7rk3WttcKKrr0DtcNGIt-Ho";
|
|
$website = "https://api.telegram.org/bot" . $botToken;
|
|
|
|
echo "Memulai Telegram Bot (Polling Mode)...\n";
|
|
echo "Tekan Ctrl+C untuk berhenti.\n\n";
|
|
|
|
// Fungsi untuk request API
|
|
function request($url, $postData = []) {
|
|
$ch = curl_init($url);
|
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
|
if (!empty($postData)) {
|
|
curl_setopt($ch, CURLOPT_POST, 1);
|
|
// Penting: gunakan JSON untuk reply_markup jika berbentuk array
|
|
if(isset($postData['reply_markup']) && is_array($postData['reply_markup'])) {
|
|
$postData['reply_markup'] = json_encode($postData['reply_markup']);
|
|
}
|
|
curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
|
|
}
|
|
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
|
|
$res = curl_exec($ch);
|
|
curl_close($ch);
|
|
return json_decode($res, true);
|
|
}
|
|
|
|
// Fungsi Download File dari Telegram
|
|
function downloadTelegramFile($fileId, $botToken, $type, $originalName = "") {
|
|
$urlGetFile = "https://api.telegram.org/bot{$botToken}/getFile?file_id={$fileId}";
|
|
$res = json_decode(file_get_contents($urlGetFile), true);
|
|
|
|
if (isset($res['ok']) && $res['ok']) {
|
|
$filePathApi = $res['result']['file_path'];
|
|
$downloadUrl = "https://api.telegram.org/file/bot{$botToken}/{$filePathApi}";
|
|
|
|
$ext = pathinfo($filePathApi, PATHINFO_EXTENSION);
|
|
$fileName = time() . '_' . rand(1000, 9999) . '.' . $ext;
|
|
if (!empty($originalName)) {
|
|
$fileName = time() . '_' . preg_replace('/[^A-Za-z0-9.\-_]/', '', $originalName);
|
|
}
|
|
|
|
$savePath = __DIR__ . '/images/chat_uploads/' . $fileName;
|
|
file_put_contents($savePath, file_get_contents($downloadUrl));
|
|
|
|
$urlRelative = "images/chat_uploads/" . $fileName;
|
|
|
|
if ($type === "Photo") {
|
|
return "<a href='{$urlRelative}' target='_blank'><img src='{$urlRelative}' style='max-width:200px; border-radius:8px; display:block;'></a>";
|
|
} else if ($type === "Video") {
|
|
return "<video controls style='max-width:200px; border-radius:8px;'><source src='{$urlRelative}' type='video/mp4'></video>";
|
|
} else if ($type === "Voice") {
|
|
return "<audio controls style='max-width:220px;'><source src='{$urlRelative}' type='audio/ogg'></audio>";
|
|
} else {
|
|
return "<a href='{$urlRelative}' target='_blank' style='display:flex; align-items:center; gap:12px; padding:10px; background:rgba(0,0,0,0.05); border-radius:8px; text-decoration:none; color:inherit;'>
|
|
<i class='mdi mdi-file-document-outline' style='font-size:32px; color:#4b49ac;'></i>
|
|
<span style='font-weight:600; font-size:13px; word-break:break-all;'>{$fileName}</span>
|
|
</a>";
|
|
}
|
|
}
|
|
return "[Attachment Failed]";
|
|
}
|
|
|
|
// Hapus Webhook jika sebelumnya pernah diset (Webhook dan Polling tidak bisa bersamaan)
|
|
request($website . "/deleteWebhook");
|
|
|
|
$offset = 0;
|
|
|
|
while (true) {
|
|
// Ambil data (Long Polling)
|
|
$response = request($website . "/getUpdates", [
|
|
'offset' => $offset,
|
|
'timeout' => 20 // Tahan koneksi sampai 20 detik jika tak ada pesan baru
|
|
]);
|
|
|
|
if (!empty($response['ok']) && !empty($response['result'])) {
|
|
foreach ($response['result'] as $update) {
|
|
$offset = $update['update_id'] + 1; // Update offset agar pesan ini tidak ditarik lagi
|
|
|
|
if (isset($update["message"])) {
|
|
$chatId = $update["message"]["chat"]["id"];
|
|
$username = isset($update["message"]["from"]["first_name"]) ? $update["message"]["from"]["first_name"] : "User";
|
|
|
|
echo "[".date('Y-m-d H:i:s')."] Pesan dari $username ($chatId): ";
|
|
|
|
// Command /start
|
|
if (isset($update["message"]["text"]) && $update["message"]["text"] === "/start") {
|
|
echo "/start\n";
|
|
$text = "Halo! Saya adalah *Identia*.\n\n"
|
|
. "Penting untuk diketahui: *Ini bukanlah Bot otomatis yang bisa menjawab secara otomatis*. Ini adalah *saluran interaksi langsung* untuk terhubung secara personal dengan Admin Identia.\n\n"
|
|
. "Namun, untuk memulai obrolan langsung dengan Admin, kami perlu memverifikasi data Anda terlebih dahulu.\n\n"
|
|
. "👇 *Silakan klik tombol di bawah ini untuk Membagikan Kontak Anda* agar kami dapat mencocokkan nomor handphone Anda dengan sistem kami.";
|
|
|
|
$postData = [
|
|
'chat_id' => $chatId,
|
|
'text' => $text,
|
|
'parse_mode' => 'Markdown',
|
|
'reply_markup' => [
|
|
'keyboard' => [
|
|
[ ['text' => '📱 Bagikan Kontak Saya', 'request_contact' => true] ]
|
|
],
|
|
'resize_keyboard' => true,
|
|
'one_time_keyboard' => true
|
|
]
|
|
];
|
|
request($website."/sendMessage", $postData);
|
|
continue; // lanjut ke update berikutnya
|
|
}
|
|
|
|
// Konfirmasi / Cek Nomor HP
|
|
if (isset($update["message"]["contact"])) {
|
|
$phoneNumber = $update["message"]["contact"]["phone_number"];
|
|
echo "[Share Contact: $phoneNumber]\n";
|
|
|
|
$normalizedPhone = preg_replace('/^\+?62/', '0', $phoneNumber);
|
|
|
|
// Cek database di tabel occupant
|
|
try { $pdo->exec("ALTER TABLE occupant ADD COLUMN telegram_id VARCHAR(100) NULL AFTER no_hp"); } catch(PDOException $e) {}
|
|
|
|
$stmt = $pdo->prepare("SELECT id_occupant FROM occupant WHERE no_hp = ? OR no_hp = ? OR no_hp = ?");
|
|
$stmt->execute([
|
|
$phoneNumber,
|
|
$normalizedPhone,
|
|
"62" . ltrim($normalizedPhone, '0')
|
|
]);
|
|
$occupant = $stmt->fetch(PDO::FETCH_ASSOC);
|
|
|
|
if ($occupant) {
|
|
$updateStmt = $pdo->prepare("UPDATE occupant SET telegram_id = ? WHERE id_occupant = ?");
|
|
$updateStmt->execute([$chatId, $occupant['id_occupant']]);
|
|
|
|
$text = "✅ *Verifikasi Berhasil!*\n\n"
|
|
. "Nomor Anda telah terverifikasi sebagai Penghuni *Identia* yang sah.\n\n"
|
|
. "Saat ini, Anda sudah *Terhubung Langsung* dengan saluran pribadi Admin *Identia*.\n\n"
|
|
. "Silakan sampaikan pertanyaan, laporan kendala, atau pesan Anda di sini kapan pun Anda butuhkan. Admin akan membalas pesan Anda dari Control Panel sesegera mungkin.";
|
|
|
|
$postData = [
|
|
'chat_id' => $chatId,
|
|
'text' => $text,
|
|
'parse_mode' => 'Markdown',
|
|
'reply_markup' => ['remove_keyboard' => true]
|
|
];
|
|
request($website."/sendMessage", $postData);
|
|
} else {
|
|
$postData = [
|
|
'chat_id' => $chatId,
|
|
'text' => "❌ Maaf, nomor handphone Anda ($phoneNumber) tidak ditemukan pada daftar penghuni Identia.\n\nPastikan Anda mendaftar melalui Admin terlebih dahulu."
|
|
];
|
|
request($website."/sendMessage", $postData);
|
|
}
|
|
continue;
|
|
}
|
|
|
|
// Handle Teks Biasa (Occupant membalas/chat ke Admin)
|
|
if (isset($update["message"])) {
|
|
$msgObj = $update["message"];
|
|
$textMessage = "";
|
|
$captionStr = isset($msgObj["caption"]) ? htmlspecialchars($msgObj["caption"]) : "";
|
|
|
|
if (isset($msgObj["text"])) {
|
|
$textMessage = htmlspecialchars($msgObj["text"]);
|
|
echo "Teks: $textMessage\n";
|
|
} else {
|
|
// Kalau bukan text biasa, kita abaikan saja agar tidak tersimpan di database
|
|
continue;
|
|
}
|
|
|
|
if (!empty($textMessage)) {
|
|
try { $pdo->exec("ALTER TABLE occupant ADD COLUMN telegram_id VARCHAR(100) NULL AFTER no_hp"); } catch(PDOException $e) {}
|
|
|
|
$stmt = $pdo->prepare("SELECT id_occupant FROM occupant WHERE telegram_id = ?");
|
|
$stmt->execute([$chatId]);
|
|
$occupant = $stmt->fetch(PDO::FETCH_ASSOC);
|
|
|
|
if ($occupant) {
|
|
$id_account = 1;
|
|
try { $pdo->exec("ALTER TABLE chats ADD COLUMN reply_to_chat_id INT NULL AFTER telegram_msg_id"); } catch(PDOException $e) {}
|
|
|
|
$replyToId = null;
|
|
if (isset($msgObj['reply_to_message']) && isset($msgObj['reply_to_message']['message_id'])) {
|
|
$tgReplyId = $msgObj['reply_to_message']['message_id'];
|
|
// Temukan chat lokal berdasarkan telegram_msg_id
|
|
$qRep = $pdo->prepare("SELECT id_chat FROM chats WHERE telegram_msg_id = ? LIMIT 1");
|
|
$qRep->execute([$tgReplyId]);
|
|
$foundRep = $qRep->fetch();
|
|
if ($foundRep) $replyToId = $foundRep['id_chat'];
|
|
}
|
|
|
|
$insertStmt = $pdo->prepare("INSERT INTO chats (id_account, id_occupant, sender, message, is_read, telegram_msg_id, reply_to_chat_id) VALUES (?, ?, 'occupant', ?, 0, ?, ?)");
|
|
$insertStmt->execute([$id_account, $occupant['id_occupant'], $textMessage, $msgObj['message_id'], $replyToId]);
|
|
|
|
// ALL PREVIOUS MESSAGES TO THIS USER ARE NOW READ
|
|
try {
|
|
$pdo->exec("UPDATE chats SET is_read = 1 WHERE id_occupant = {$occupant['id_occupant']} AND sender = 'account'");
|
|
} catch(PDOException $e) {}
|
|
|
|
try { $pdo->exec("ALTER TABLE occupant ADD COLUMN last_active DATETIME NULL"); } catch(PDOException $e) {}
|
|
$updateLastActive = $pdo->prepare("UPDATE occupant SET last_active = NOW() WHERE id_occupant = ?");
|
|
$updateLastActive->execute([$occupant['id_occupant']]);
|
|
|
|
} else {
|
|
$postData = [
|
|
'chat_id' => $chatId,
|
|
'text' => "Sesi chat Anda belum terhubung dengan Identia.\n\nSilakan kirim perintah /start lalu klik tombol 'Bagikan Kontak Saya' terlebih dahulu untuk memulai obrolan dengan Admin."
|
|
];
|
|
request($website."/sendMessage", $postData);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Handle Pesan Diedit (Occupant mengedit pesan di Telegram)
|
|
if (isset($update["edited_message"])) {
|
|
$chatId = $update["edited_message"]["chat"]["id"];
|
|
|
|
if (isset($update["edited_message"]["text"])) {
|
|
$editedText = $update["edited_message"]["text"];
|
|
$messageId = $update["edited_message"]["message_id"];
|
|
|
|
$stmt = $pdo->prepare("SELECT id_occupant FROM occupant WHERE telegram_id = ?");
|
|
$stmt->execute([$chatId]);
|
|
$occupant = $stmt->fetch(PDO::FETCH_ASSOC);
|
|
|
|
if ($occupant) {
|
|
$newText = htmlspecialchars($editedText) . " <i class='mdi mdi-pencil-outline edit-tag' style='font-size:11px; margin-left:3px;' title='Diedit'></i>";
|
|
|
|
$updateStmt = $pdo->prepare("UPDATE chats SET message = ? WHERE telegram_msg_id = ? AND id_occupant = ?");
|
|
$updateStmt->execute([$newText, $messageId, $occupant['id_occupant']]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
// Sleep sebentar jika tidak ada payload baru sebelum lanjut polling
|
|
sleep(1);
|
|
}
|
|
}
|
|
?>
|