/** * NIMFinder Scraper — Pencarian Nama & NIM Mahasiswa Indonesia * Base: https://nimfinder.com * Supported Universities: ITB, UI, UGM, UNPAD, BINUS, UNDIP, ITS, IPB, UNAIR, UNBRAW, dll. */ import fetch from 'node-fetch' const BASE_API = 'https://xg1kctvm70.execute-api.ap-southeast-1.amazonaws.com' const USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36' export const UNIVERSITIES = { itb: 'Institut Teknologi Bandung (ITB)', ui: 'Universitas Indonesia (UI)', ugm: 'Universitas Gadjah Mada (UGM)', unpad: 'Universitas Padjadjaran (UNPAD)', binus: 'Bina Nusantara (BINUS)', undip: 'Universitas Diponegoro (UNDIP)', its: 'Institut Teknologi Sepuluh Nopember (ITS)', ipb: 'IPB University (IPB)', unair: 'Universitas Airlangga (UNAIR)', unbraw: 'Universitas Brawijaya (UB/UNBRAW)', upi: 'Universitas Pendidikan Indonesia (UPI)', uns: 'Universitas Sebelas Maret (UNS)', unhas: 'Universitas Hasanuddin (UNHAS)', unnes: 'Universitas Negeri Semarang (UNNES)', trisakti: 'Universitas Trisakti (TRISAKTI)' } /** * Mencari data mahasiswa berdasarkan Nama atau NIM di universitas tertentu * @param {string} query Nama atau NIM mahasiswa (contoh: "budi", "13520001", "if21") * @param {string} univ Kode universitas (default: "itb", opsi: "ui", "ugm", "unpad", "binus", "undip", "its", "ipb", "unair", "unbraw") * @param {number} page Halaman hasil pencarian (default: 0) */ export async function searchNim(query, univ = 'itb', page = 0) { if (!query) throw new Error('Kata kunci pencarian (Nama atau NIM) tidak boleh kosong.') const targetUniv = univ.toLowerCase().trim() const validUniv = UNIVERSITIES[targetUniv] ? targetUniv : 'itb' try { const url = `${BASE_API}/mahasiswa_${validUniv}?query=${encodeURIComponent(query)}&page=${page}` const res = await fetch(url, { headers: { 'Origin': 'https://nimfinder.com', 'Referer': 'https://nimfinder.com/', 'User-Agent': USER_AGENT, 'Accept': 'application/json, text/plain, */*' } }) if (!res.ok) throw new Error(`HTTP Error ${res.status}`) const json = await res.json() if (json.status !== 'OK') { throw new Error(json.message || 'Gagal mengambil data mahasiswa.') } const list = (json.payload || []).map(item => ({ name: item.name || item.nama || 'N/A', nim_tpb: item.nim_tpb || null, nim_jurusan: item.nim_jur || item.nim || 'N/A', prodi: item.prodi || item.jurusan || 'N/A', fakultas: item.fakultas || null, status: item.status || 'Aktif', jenis_kelamin: item.jenis_kelamin || null })) return { university: UNIVERSITIES[validUniv], university_code: validUniv, query, total: json.total || list.length, page: json.page || page, results: list } } catch (e) { console.error('[NIMFinder Error]:', e.message) throw e } } /** * Mencari data mahasiswa di SEMUA universitas besar sekaligus * @param {string} query Nama atau NIM */ export async function searchNimAll(query) { if (!query) throw new Error('Query tidak boleh kosong.') const univCodes = Object.keys(UNIVERSITIES) const promises = univCodes.map(async (code) => { try { const data = await searchNim(query, code, 0) return { university: UNIVERSITIES[code], code, total: data.total, results: data.results.slice(0, 5) } } catch { return null } }) const results = (await Promise.all(promises)).filter(r => r && r.results.length > 0) return { query, matched_universities: results.length, data: results } } export default { search: searchNim, searchAll: searchNimAll, UNIVERSITIES }