diff --git a/system/plugin/pppoe_monitor.php b/system/plugin/pppoe_monitor.php new file mode 100644 index 0000000..4358ddd --- /dev/null +++ b/system/plugin/pppoe_monitor.php @@ -0,0 +1,418 @@ +assign('_title', 'PPPoE Monitor'); + $ui->assign('_system_menu', 'PPPoE Monitor'); + $admin = Admin::_info(); + $ui->assign('_admin', $admin); + $routers = ORM::for_table('tbl_routers')->where('enabled', '1')->find_many(); + $router = $routes['2'] ?? $routers[0]['id']; + $ui->assign('routers', $routers); + $ui->assign('router', $router); + $ui->assign('interfaces', pppoe_monitor_router_getInterface()); + + $ui->display('pppoe_monitor.tpl'); +} + +function pppoe_monitor_router_getInterface() +{ + global $routes; + $routerId = $routes['2'] ?? null; + + if (!$routerId) { + return []; + } + + $mikrotik = ORM::for_table('tbl_routers')->where('enabled', '1')->find_one($routerId); + + if (!$mikrotik) { + return []; + } + + $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); + $interfaces = $client->sendSync(new RouterOS\Request('/interface/print')); + + $interfaceList = []; + foreach ($interfaces as $interface) { + $name = $interface->getProperty('name'); + $interfaceList[] = $name; // Jangan menghapus karakter < dan > dari nama interface + } + + return $interfaceList; +} + +function pppoe_get_combined_users() { + global $routes; + $router = $routes['2']; + $mikrotik = ORM::for_table('tbl_routers')->where('enabled', '1')->find_one($router); + + if (!$mikrotik) { + header('Content-Type: application/json'); + echo json_encode(['error' => 'Router not found']); + return; + } + + try { + $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); + + // Fetch PPP online users + $pppUsers = $client->sendSync(new RouterOS\Request('/ppp/active/print')); + $interfaceTraffic = $client->sendSync(new RouterOS\Request('/interface/print')); + $pppSecrets = $client->sendSync(new RouterOS\Request('/ppp/secret/print')); + + + $interfaceData = []; + foreach ($interfaceTraffic as $interface) { + $name = $interface->getProperty('name'); + if (empty($name)) { + continue; + } + + $interfaceData[$name] = [ + 'status' => $interface->getProperty('running') === 'true' ? 'Connected' : 'Disconnected', + 'txBytes' => intval($interface->getProperty('tx-byte')), + 'rxBytes' => intval($interface->getProperty('rx-byte')), + ]; + } + + + $pppUserList = []; + foreach ($pppUsers as $pppUser) { + $username = $pppUser->getProperty('name'); + if (empty($username)) { + continue; + } + $address = $pppUser->getProperty('address'); + $uptime = $pppUser->getProperty('uptime'); + $service = $pppUser->getProperty('service'); + $callerid = $pppUser->getProperty('caller-id'); + $bytes_in = $pppUser->getProperty('limit-bytes-in'); + $bytes_out = $pppUser->getProperty('limit-bytes-out'); + $id = $pppUser->getProperty('.id'); + + $interfaceName = ""; + + if (isset($interfaceData[$interfaceName])) { + $trafficData = $interfaceData[$interfaceName]; + $txBytes = $trafficData['txBytes']; + $rxBytes = $trafficData['rxBytes']; + $status = $trafficData['status']; + } else { + $txBytes = 0; + $rxBytes = 0; + $status = 'Disconnected'; + } + + // Get device information + $manufacturer = "Unknown"; + if ($callerid) { + $manufacturer = get_manufacturer_from_mac($callerid); + } + + // Check if MAC is bound in ppp secrets + $isBound = false; + foreach ($pppSecrets as $secret) { + if ($secret->getProperty('name') === $username && $secret->getProperty('caller-id') === $callerid) { + $isBound = true; + break; + } + } + + $pppUserList[$username] = [ + 'id' => $id, + 'username' => $username, + 'address' => $address, + 'uptime' => $uptime, + 'service' => $service, + 'caller_id' => $callerid, + 'bytes_in' => $bytes_in, + 'bytes_out' => $bytes_out, + 'tx' => pppoe_monitor_router_formatBytes($txBytes), + 'rx' => pppoe_monitor_router_formatBytes($rxBytes), + 'total' => pppoe_monitor_router_formatBytes($txBytes + $rxBytes), + 'status' => $status, + 'manufacturer' => $manufacturer, + 'is_bound' => $isBound + ]; + } + + // Convert the user list to a regular array for JSON encoding + $userList = array_values($pppUserList); + + // Return the combined user list as JSON + header('Content-Type: application/json'); + echo json_encode($userList); + } catch (Exception $e) { + header('Content-Type: application/json'); + echo json_encode(['error' => $e->getMessage()]); + } +} + +function get_manufacturer_from_mac($mac_address) { + // Normalize the MAC address + $mac_address = strtoupper(preg_replace('/[^A-F0-9]/', '', $mac_address)); + + // Check if MAC address is valid (at least 6 hex characters required) + if (strlen($mac_address) < 6) { + return 'Invalid MAC address'; + } + + // Construct the API URL + $url = "https://www.macvendorlookup.com/api/v2/{$mac_address}"; + + // Initialize cURL session + $ch = curl_init(); + + // Set cURL options + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // For testing purposes, handle SSL properly in production + + // Execute cURL request + $response = curl_exec($ch); + + // Check for cURL errors + if (curl_errno($ch)) { + $error = curl_error($ch); + curl_close($ch); + return "Error: $error"; + } + + // Get HTTP response code + $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); + curl_close($ch); + + // Check if API returned a valid response + if ($http_code === 204) { + return 'Unknown'; + } + + // Decode JSON response + $data = json_decode($response, true); + + // Check if the response contains manufacturer information + if (isset($data[0]['company'])) { + return trim($data[0]['company']); + } else { + return 'Unknown'; + } +} + +function pppoe_monitor_router_formatMaxLimit($max_limit) { + $limits = explode('/', $max_limit); + if (count($limits) == 2) { + $downloadLimit = intval($limits[0]); + $uploadLimit = intval($limits[1]); + $formattedDownloadLimit = ceil($downloadLimit / (1024 * 1024)) . ' MB'; + $formattedUploadLimit = ceil($uploadLimit / (1024 * 1024)) . ' MB'; + return $formattedDownloadLimit . '/' . $formattedUploadLimit; + } + return 'N/A'; +} + +// Fungsi untuk menghitung total data yang digunakan per harinya + +function pppoe_monitor_router_formatBytes($bytes, $precision = 2) +{ + $units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']; + $bytes = max($bytes, 0); + $pow = floor(($bytes ? log($bytes) : 0) / log(1024)); + $pow = min($pow, count($units) - 1); + $bytes /= pow(1024, $pow); + return round($bytes, $precision) . ' ' . $units[$pow]; +} + +function pppoe_monitor_router_traffic() +{ + $interface = $_GET["interface"]; // Ambil interface dari parameter GET + + // Contoh koneksi ke MikroTik menggunakan library tertentu (misalnya menggunakan ORM dan MikroTik API wrapper) + global $routes; + $router = $routes['2']; + $mikrotik = ORM::for_table('tbl_routers')->where('enabled', '1')->find_one($router); + $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); + + try { + $results = $client->sendSync( + (new RouterOS\Request('/interface/monitor-traffic')) + ->setArgument('interface', $interface) + ->setArgument('once', '') + ); + + $rows = array(); + $rows2 = array(); + $labels = array(); + + foreach ($results as $result) { + $ftx = $result->getProperty('tx-bits-per-second'); + $frx = $result->getProperty('rx-bits-per-second'); + + // Timestamp dalam milidetik (millisecond) + $timestamp = time() * 1000; + + $rows[] = $ftx; + $rows2[] = $frx; + $labels[] = $timestamp; // Tambahkan timestamp ke dalam array labels + } + + $result = array( + 'labels' => $labels, + 'rows' => array( + 'tx' => $rows, + 'rx' => $rows2 + ) + ); + } catch (Exception $e) { + $result = array('error' => $e->getMessage()); + } + + // Set header untuk respons JSON + header('Content-Type: application/json'); + echo json_encode($result); +} + +function pppoe_monitor_router_online() +{ + global $routes; + $router = $routes['2']; + $mikrotik = ORM::for_table('tbl_routers')->where('enabled', '1')->find_one($router); + $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); + $pppUsers = $client->sendSync(new RouterOS\Request('/ppp/active/print')); + + $pppoeInterfaces = []; + + foreach ($pppUsers as $pppUser) { + $username = $pppUser->getProperty('name'); + $interfaceName = ""; // Tambahkan karakter < dan > + + // Ensure interface name is not empty and it's not already in the list + if (!empty($interfaceName) && !in_array($interfaceName, $pppoeInterfaces)) { + $pppoeInterfaces[] = $interfaceName; + } + } + + // Return the list of PPPoE interfaces + return $pppoeInterfaces; +} + +function pppoe_monitor_router_delete_ppp_user() +{ + global $routes; + $router = $routes['2']; + $id = $_POST['id']; // Ambil .id dari POST data + + // Cek apakah ID ada di POST data + if (empty($id)) { + header('Content-Type: application/json'); + echo json_encode(['success' => false, 'message' => 'ID is missing.']); + return; + } + + // Ambil detail router dari database + $mikrotik = ORM::for_table('tbl_routers')->where('enabled', '1')->find_one($router); + + if (!$mikrotik) { + header('Content-Type: application/json'); + echo json_encode(['success' => false, 'message' => 'Router not found.']); + return; + } + + // Dapatkan klien MikroTik + $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); + + if (!$client) { + header('Content-Type: application/json'); + echo json_encode(['success' => false, 'message' => 'Failed to connect to the router.']); + return; + } + + try { + // Buat permintaan untuk menghapus koneksi aktif PPPoE + $request = new RouterOS\Request('/ppp/active/remove'); + $request->setArgument('.id', $id); // Gunakan .id yang sesuai + $client->sendSync($request); + + header('Content-Type: application/json'); + echo json_encode(['success' => true, 'message' => 'PPPoE user successfully deleted.']); + } catch (Exception $e) { + // Log error untuk debugging + error_log('Failed to delete PPPoE user: ' . $e->getMessage()); + + header('Content-Type: application/json'); + echo json_encode(['success' => false, 'message' => 'Failed to delete PPPoE user: ' . $e->getMessage()]); + } +} + +// ====================================================================== +// NEW FUNCTIONS: + +// Fungsi untuk menghitung total data yang digunakan per harinya +function pppoe_monitor_router_daily_data_usage() +{ + global $routes; + $router = $routes['2']; + $mikrotik = ORM::for_table('tbl_routers')->where('enabled', '1')->find_one($router); + $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); + + // Ambil semua pengguna aktif PPPoE + $pppUsers = $client->sendSync(new RouterOS\Request('/ppp/active/print')); + $interfaceTraffic = $client->sendSync(new RouterOS\Request('/interface/print')); + + // Array untuk menyimpan data penggunaan harian + $daily_usage = []; + + // Looping untuk setiap pengguna PPPoE + foreach ($pppUsers as $pppUser) { + $username = $pppUser->getProperty('name'); + $interfaceName = ""; // Nama interface sesuai format PPPoE + + // Ambil data traffic untuk interface ini + $interfaceData = []; + foreach ($interfaceTraffic as $interface) { + $name = $interface->getProperty('name'); + if ($name === $interfaceName) { + $interfaceData = [ + 'txBytes' => intval($interface->getProperty('tx-byte')), + 'rxBytes' => intval($interface->getProperty('rx-byte')) + ]; + break; + } + } + + // Hitung total penggunaan harian + $txBytes = $interfaceData['txBytes'] ?? 0; + $rxBytes = $interfaceData['rxBytes'] ?? 0; + $totalDataMB = ($txBytes + $rxBytes) / (1024 * 1024); // Konversi ke MB + + // Ambil tanggal dari waktu saat ini + $date = date('Y-m-d', time()); + + // Jika belum ada data untuk tanggal ini, inisialisasi + if (!isset($daily_usage[$date])) { + $daily_usage[$date] = [ + 'total' => 0, + 'users' => [] + ]; + } + + // Tambahkan penggunaan harian untuk pengguna ini + $daily_usage[$date]['total'] += $totalDataMB; + $daily_usage[$date]['users'][] = [ + 'username' => $username, + 'tx' => pppoe_monitor_router_formatBytes($txBytes), + 'rx' => pppoe_monitor_router_formatBytes($rxBytes), + 'total' => pppoe_monitor_router_formatBytes($txBytes + $rxBytes) + ]; + } + + // Kembalikan hasil dalam format JSON + header('Content-Type: application/json'); + echo json_encode($daily_usage); // $daily_usage adalah array yang berisi data harian dalam format yang sesuai +} +// Fungsi untuk mendapatkan pengguna terbatas pada MikroTik diff --git a/system/plugin/user.png b/system/plugin/user.png new file mode 100644 index 0000000..7af1f56 Binary files /dev/null and b/system/plugin/user.png differ