Update .gitignore and remove ignored files

This commit is contained in:
WD - Dev
2025-07-05 15:59:20 +07:00
parent b440b80882
commit bc6d99d252
17 changed files with 342 additions and 80200 deletions
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
-8
View File
@@ -1,8 +0,0 @@
2025-05-25 09:22:06 Exception ResponAI: SQLSTATE[22001]: String data, right truncated: 1406 Data too long for column 'nomor_whatsapp' at row 1
2025-05-25 09:22:16 Exception ResponAI: SQLSTATE[22001]: String data, right truncated: 1406 Data too long for column 'nomor_whatsapp' at row 1
2025-05-25 09:22:26 Exception ResponAI: SQLSTATE[22001]: String data, right truncated: 1406 Data too long for column 'nomor_whatsapp' at row 1
2025-05-25 09:22:36 Exception ResponAI: SQLSTATE[22001]: String data, right truncated: 1406 Data too long for column 'nomor_whatsapp' at row 1
2025-05-30 22:04:51 Exception ResponAI: SQLSTATE[22001]: String data, right truncated: 1406 Data too long for column 'nomor_whatsapp' at row 1
2025-05-30 22:05:01 Exception ResponAI: SQLSTATE[22001]: String data, right truncated: 1406 Data too long for column 'nomor_whatsapp' at row 1
2025-05-30 22:05:11 Exception ResponAI: SQLSTATE[22001]: String data, right truncated: 1406 Data too long for column 'nomor_whatsapp' at row 1
2025-05-30 22:05:21 Exception ResponAI: SQLSTATE[22001]: String data, right truncated: 1406 Data too long for column 'nomor_whatsapp' at row 1
-111
View File
@@ -1,111 +0,0 @@
<?php
include __DIR__ . "/../../config/whatsapp_api.php";
include __DIR__ . "/respon_ai.php";
// Setup error reporting untuk debugging
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
// Simpan log raw input untuk debug paling awal
// file_put_contents(__DIR__ . "/debug_raw_input.log", date('Y-m-d H:i:s') . " Input:\n" . print_r(file_get_contents('php://input'), true) . "\n", FILE_APPEND);
try {
// Ambil dan decode input JSON
$data = file_get_contents('php://input');
$json_data = json_decode($data, true);
if (!isset($json_data['results']['apiKey'])) {
http_response_code(400);
echo "apiKey tidak ditemukan.";
exit;
}
$apiKey = $json_data['results']['apiKey'];
// file_put_contents(__DIR__ . "/debug_apikey.log", date('Y-m-d H:i:s') . " apiKey: $apiKey\n", FILE_APPEND);
if (
isset($json_data['type']) && $json_data['type'] === 'message' &&
isset($json_data['results']['fromMe']) && $json_data['results']['fromMe'] === false &&
isset($json_data['results']['isGroupMsg']) && $json_data['results']['isGroupMsg'] === false
) {
$sender = $json_data['results']['sender'] ?? 'Tidak diketahui';
$sender = str_replace("@s.whatsapp.net", "", $sender);
$body = $json_data['results']['body'] ?? '';
// file_put_contents(__DIR__ . "/debug_sender_body.log", date('Y-m-d H:i:s') . " Sender: $sender, Body: $body\n", FILE_APPEND);
$filtered = [
'sender' => $sender,
'body' => $body,
'apiKey' => $apiKey
];
$log_file = __DIR__ . "/" . $apiKey . ".log";
$log_entry = "[" . date('Y-m-d H:i:s') . "] Masuk: " . print_r($filtered, true);
// Pastikan kelas ResponAI ada
if (!class_exists('ResponAI')) {
file_put_contents(__DIR__ . "/error.log", date('Y-m-d H:i:s') . " Class ResponAI tidak ditemukan!\n", FILE_APPEND);
http_response_code(500);
exit("Server error: ResponAI class missing");
}
$ResAI = new ResponAI();
// Tangkap exception saat proses respon_chat
try {
$Respon = $ResAI->respon_chat($body, $sender, $apiKey);
} catch (Exception $e) {
file_put_contents(__DIR__ . "/error.log", date('Y-m-d H:i:s') . " Exception ResponAI: " . $e->getMessage() . "\n", FILE_APPEND);
http_response_code(500);
exit("Server error: gagal proses AI");
}
// file_put_contents(__DIR__ . "/step2_respon_ai.log", date('Y-m-d H:i:s') . " " . print_r($Respon, true), FILE_APPEND);
if (!empty($Respon['id']) && !empty($Respon['nomor'])) {
if (!class_exists('PesanWA')) {
file_put_contents(__DIR__ . "/error.log", date('Y-m-d H:i:s') . " Class PesanWA tidak ditemukan!\n", FILE_APPEND);
http_response_code(500);
exit("Server error: PesanWA class missing");
}
$API_WA = new PesanWA();
try {
$send_result = $API_WA->Send_Pesan($Respon['id'], 'sendMessage', array($Respon['nomor']), $Respon['respon']);
} catch (Exception $e) {
file_put_contents(__DIR__ . "/error.log", date('Y-m-d H:i:s') . " Exception Send_Pesan: " . $e->getMessage() . "\n", FILE_APPEND);
http_response_code(500);
exit("Server error: gagal kirim pesan");
}
// file_put_contents(__DIR__ . "/step3_send_pesan.log", date('Y-m-d H:i:s') . " Kirim pesan ke: {$Respon['nomor']}\nResponse Send_Pesan: " . print_r($send_result, true), FILE_APPEND);
$log_entry .= "[" . date('Y-m-d H:i:s') . "] Balasan AI: " . print_r($Respon, true) . PHP_EOL;
// file_put_contents($log_file, $log_entry, FILE_APPEND);
http_response_code(200);
exit;
} else {
// file_put_contents(__DIR__ . "/error_send_pesan.log", date('Y-m-d H:i:s') . " Gagal kirim pesan, id atau nomor kosong: " . print_r($Respon, true) . "\n", FILE_APPEND);
http_response_code(500);
echo "Gagal mengirim pesan: data tidak lengkap.";
exit;
}
} else {
http_response_code(400);
echo "Data tidak valid atau bukan pesan yang diinginkan.";
exit;
}
} catch (Throwable $t) {
// Tangkap semua error fatal / throwable
file_put_contents(__DIR__ . "/error.log", date('Y-m-d H:i:s') . " Fatal error: " . $t->getMessage() . "\n", FILE_APPEND);
http_response_code(500);
echo "Server error: " . $t->getMessage();
exit;
}
-276
View File
@@ -1,276 +0,0 @@
<?php
class ResponAI {
private function connectDB() {
include __DIR__ . "/../../config/connect.php"; // Harus mengisi $pdo
return $pdo;
}
private function deteksi_topik($message) {
$rules = [
'gangguan' => ['lambat', 'tidak konek', 'jaringan', 'trouble', 'gangguan', 'internet mati'],
'tagihan' => ['tagihan', 'bayar', 'invoice', 'pembayaran', 'rekening'],
'pemasangan' => ['pasang', 'berlangganan', 'pemasangan', 'registrasi', 'daftar', 'masang'],
'umum' => []
];
$message = strtolower($message);
foreach ($rules as $topik => $keywords) {
foreach ($keywords as $keyword) {
if (strpos($message, $keyword) !== false) {
return $topik;
}
}
}
return 'umum';
}
private function get_data_pelanggan($sender) {
$pdo = $this->connectDB();
$stmt = $pdo->prepare("SELECT nama, nama_paket, status, akun, status_koneksi FROM v_pelanggan WHERE nomor_whatsapp = ?");
$stmt->execute([$sender]);
$pelanggan = $stmt->fetch(PDO::FETCH_ASSOC);
if ($pelanggan) {
return "Pelanggan atas nama {$pelanggan['nama']} (ID: {$pelanggan['akun']}) menggunakan paket {$pelanggan['nama_paket']} dan status koneksi {$pelanggan['status_koneksi']}. Status langganan: {$pelanggan['status']}.";
}
return "Data pelanggan tidak ditemukan.";
}
private function get_id_server($apikey_wa) {
$pdo = $this->connectDB();
$stmt = $pdo->prepare("SELECT id FROM data_server WHERE apikey_whatsapp = ?");
$stmt->execute([$apikey_wa]);
$row = $stmt->fetch(PDO::FETCH_ASSOC);
return $row['id'] ?? null;
}
private function get_paket_berlangganan($id) {
$pdo = $this->connectDB();
$stmt = $pdo->prepare("SELECT nama, harga_paket FROM profile_paket WHERE id_data_server = ?");
$stmt->execute([$id]);
$pakets = $stmt->fetchAll(PDO::FETCH_ASSOC);
if (!$pakets) return "Paket berlangganan belum tersedia.";
$list = "Berikut adalah daftar paket layanan:\n";
foreach ($pakets as $p) {
$list .= "- {$p['nama']}: Rp " . number_format($p['harga_paket'], 0, ',', '.') . "\n";
}
return trim($list);
}
private function haversine($lat1, $lon1, $lat2, $lon2) {
$earthRadius = 6371;
$dLat = deg2rad($lat2 - $lat1);
$dLon = deg2rad($lon2 - $lon1);
$a = sin($dLat / 2) ** 2 + cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * sin($dLon / 2) ** 2;
$c = 2 * atan2(sqrt($a), sqrt(1 - $a));
return $earthRadius * $c;
}
private function get_info_pemasangan($id, $lat = null, $lon = null) {
$pdo = $this->connectDB();
$stmt1 = $pdo->prepare("SELECT harga_sewa FROM data_server WHERE id = ?");
$stmt1->execute([$id]);
$row = $stmt1->fetch(PDO::FETCH_ASSOC);
$biaya = isset($row['harga_sewa']) ? "Biaya pemasangan sebesar Rp " . number_format($row['harga_sewa'], 0, ',', '.') . "." : "";
$stmt2 = $pdo->prepare("SELECT nama FROM master_desa WHERE id_data_server = ?");
$stmt2->execute([$id]);
$desas = $stmt2->fetchAll(PDO::FETCH_ASSOC);
$wilayah = $desas ? implode(", ", array_column($desas, 'nama')) : "Wilayah layanan belum terdaftar.";
$stmt3 = $pdo->prepare("SELECT titik_koordinat FROM master_topologi WHERE id_data_server = ?");
$stmt3->execute([$id]);
$koordinats = $stmt3->fetchAll(PDO::FETCH_ASSOC);
if ($lat !== null && $lon !== null && $koordinats) {
foreach ($koordinats as $k) {
$raw = $k['titik_koordinat'];
// Cek apakah tidak kosong dan mengandung koma
if (!empty($raw) && strpos($raw, ',') !== false) {
$parts = explode(',', $raw);
// Pastikan hasil explode memiliki dua elemen
if (count($parts) === 2) {
$latParsed = trim($parts[0]);
$lonParsed = trim($parts[1]);
// Validasi bahwa lat dan lon adalah angka
if (is_numeric($latParsed) && is_numeric($lonParsed)) {
$distance = $this->haversine($lat, $lon, (float)$latParsed, (float)$lonParsed);
if ($distance <= 0.3) {
$formulir = "Anda berada dalam jangkauan layanan kami.\n\nSilakan lengkapi data berikut untuk registrasi:\n"
. "- Nama lengkap\n"
. "- NIK\n"
. "- Alamat Lengkap\n"
. "- Titik Koordinat\n"
. "- Nomor WhatsApp\n"
. "- Paket Layanan";
return "$biaya\n$formulir";
}
}
}
}
}
return "Mohon maaf, titik koordinat Anda belum terjangkau jaringan kami.";
}
return "$biaya Wilayah layanan mencakup: $wilayah.\n\nSilakan kirimkan titik koordinat lokasi Anda agar kami bisa melakukan pengecekan jangkauan.";
}
private function get_data_tagihan($sender) {
$pdo = $this->connectDB();
$stmt = $pdo->prepare("SELECT nama, total_tagihan, limit_pembayaran, tanggal_bayar, status FROM v_tagihan WHERE nomor_whatsapp = ? ORDER BY tanggal_bayar DESC");
$stmt->execute([$sender]);
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
if (!$rows) return "Tidak ada tagihan yang ditemukan.";
$list = "Riwayat tagihan:\n";
foreach ($rows as $row) {
$list .= "- Tagihan: Rp " . number_format($row['total_tagihan'], 0, ',', '.') . " | Jatuh Tempo: {$row['limit_pembayaran']} | Status: {$row['status']}\n";
}
return trim($list);
}
private function simpan_sesi($sender, $topik) {
$pdo = $this->connectDB();
$stmt = $pdo->prepare("INSERT INTO chat_session (nomor_whatsapp, topik_terakhir) VALUES (?, ?) ON DUPLICATE KEY UPDATE topik_terakhir = VALUES(topik_terakhir)");
$stmt->execute([$sender, $topik]);
}
private function ambil_sesi($sender) {
$pdo = $this->connectDB();
$stmt = $pdo->prepare("SELECT topik_terakhir FROM chat_session WHERE nomor_whatsapp = ?");
$stmt->execute([$sender]);
$row = $stmt->fetch(PDO::FETCH_ASSOC);
return $row['topik_terakhir'] ?? null;
}
private function simpan_log($sender, $role, $pesan, $id) {
$pdo = $this->connectDB();
$stmt = $pdo->prepare("INSERT INTO chat_log (nomor_whatsapp, role, pesan, id_data_server) VALUES (?, ?, ?, ?)");
$stmt->execute([$sender, $role, $pesan, $id]);
}
public function respon_chat($message, $sender, $apikey_wa) {
$OPENAI_API_KEY = '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'; // Ganti dengan API key valid
$id = $this->get_id_server($apikey_wa);
if (empty($message) || empty($sender) || !$id) {
return [
'id' => $id,
'nomor' => $sender,
'respon' => 'Input tidak valid atau data server tidak ditemukan.'
];
}
$topik = $this->deteksi_topik($message);
$topik_sesi = $this->ambil_sesi($sender);
if (!$topik && $topik_sesi) {
$topik = $topik_sesi;
}
if ($topik) {
$this->simpan_sesi($sender, $topik);
}
$this->simpan_log($sender, 'user', $message, $id);
$pdo = $this->connectDB();
$stmt = $pdo->prepare("SELECT role, pesan FROM chat_log WHERE id_data_server = ? AND nomor_whatsapp = ? ORDER BY id DESC LIMIT 10");
$stmt->execute([$id, $sender]);
$riwayat = array_reverse($stmt->fetchAll(PDO::FETCH_ASSOC));
$messages = [];
foreach ($riwayat as $log) {
$messages[] = ['role' => $log['role'], 'content' => $log['pesan']];
}
$messages[] = ['role' => 'user', 'content' => $message];
$data_pelanggan = $this->get_data_pelanggan($sender);
$info_paket = $this->get_paket_berlangganan($id);
$info_pasang = $this->get_info_pemasangan($id);
$data_tagihan = $this->get_data_tagihan($sender);
$roles = [
'gangguan' => 'Kamu adalah customer service penyedia layanan internet untuk masalah teknis.',
'tagihan' => 'Kamu adalah customer service penyedia layanan internet untuk urusan tagihan.',
'pemasangan' => 'Kamu adalah customer service penyedia layanan internet untuk pemasangan baru.',
'umum' => 'Kamu adalah customer service penyedia layanan internet untuk pertanyaan umum.'
];
$topik_final = $topik ?: 'umum';
switch ($topik_final) {
case 'tagihan':
$tambahan = $data_tagihan;
break;
case 'pemasangan':
$tambahan = $info_paket . "\n" . $info_pasang;
break;
default:
$tambahan = '';
break;
}
$system_message = $roles[$topik_final] . " Data pelanggan: $data_pelanggan\n$tambahan\nJawaban maksimal 3 kalimat, singkat, sopan, dan informatif.";
array_unshift($messages, ['role' => 'system', 'content' => $system_message]);
$payload = [
'model' => 'gpt-3.5-turbo',
'messages' => $messages,
'temperature' => 0.7,
'max_tokens' => 100
];
$ch = curl_init('https://api.openai.com/v1/chat/completions');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: application/json',
'Authorization: Bearer ' . $OPENAI_API_KEY,
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
$response = curl_exec($ch);
if (curl_errno($ch)) {
$error = curl_error($ch);
curl_close($ch);
return [
'id' => $id,
'nomor' => $sender,
'respon' => 'Terjadi kesalahan koneksi ke OpenAI: ' . $error
];
}
curl_close($ch);
$data = json_decode($response, true);
$reply = $data['choices'][0]['message']['content'] ?? 'Maaf, tidak dapat memberikan jawaban saat ini.';
$this->simpan_log($sender, 'assistant', $reply, $id);
$hasil = [
'id' => $id,
'nomor' => $sender,
'respon' => trim($reply)
];
// Debug log
// file_put_contents("debug_respon_chat.log",
// "====\n[" . date("Y-m-d H:i:s") . "]\n".
// "Payload:\n" . print_r($payload, true) .
// "Response:\n" . print_r($data, true) .
// "Final:\n" . print_r($hasil, true),
// FILE_APPEND
// );
return $hasil;
}
}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
-39
View File
@@ -1,39 +0,0 @@
<?php
// Menangkap data JSON dari webhook
$data = file_get_contents('php://input');
// Decode JSON untuk membaca isinya
$json_data = json_decode($data, true);
// Validasi payload JSON
if (isset($json_data['results']['apiKey'])) {
$apiKey = $json_data['results']['apiKey'];
// Periksa jika bukan pesan grup
if (isset($json_data['results']['isGroupMsg']) && $json_data['results']['isGroupMsg'] === false) {
// Nama file log berdasarkan apiKey
$log_file = $apiKey . ".log";
// Menambahkan data baru dengan waktu (opsional)
$log_entry = "[" . date('Y-m-d H:i:s') . "] " . $data . PHP_EOL;
// Simpan ke file log sesuai apiKey
if (file_put_contents($log_file, $log_entry, FILE_APPEND) !== false) {
// Tanggapan ke pengirim webhook
http_response_code(200);
echo "Data webhook diterima dan disimpan di $log_file";
} else {
// Gagal menyimpan file log
http_response_code(500);
echo "Gagal menyimpan data ke file log.";
}
} else {
// Pesan grup tidak diproses
http_response_code(400);
echo "Pesan grup tidak diproses.";
}
} else {
// Jika `apiKey` tidak ditemukan
http_response_code(400);
}
?>