Back to Home
Gistify Snippet
Public
Scraper akunlama.com
Scraper email sementara akunlama.com via REST API tanpa dependencies (fetch native). Support cek inbox, ekstrak OTP/link, dan watch real-time.
#javascript#scraper#tempmail#api
8
Rawakunlama-scraper.jsjavascript
290 lines| 1 | /** |
| 2 | * Usage: |
| 3 | * node scripts/akunlama-scraper.js -> Jalankan auto-test lengkap & generate akun |
| 4 | * node scripts/akunlama-scraper.js admin -> Cek pesan & detail inbox admin |
| 5 | * node scripts/akunlama-scraper.js generate -> Generate alamat email acak baru |
| 6 | * node scripts/akunlama-scraper.js admin watch -> Tunggu email baru masuk secara real-time |
| 7 | */ |
| 8 | |
| 9 | const BASE_URL = 'https://akunlama.com/api'; |
| 10 | const DEFAULT_HEADERS = { |
| 11 | 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', |
| 12 | 'Accept': 'application/json, text/plain, */*', |
| 13 | 'Referer': 'https://akunlama.com/' |
| 14 | }; |
| 15 | |
| 16 | const ADJECTIVES = [ |
| 17 | 'sleepy', 'fluffy', 'sneaky', 'bouncy', 'fuzzy', 'lazy', 'happy', 'silly', 'clever', |
| 18 | 'tiny', 'giant', 'swift', 'calm', 'wild', 'gentle', 'brave', 'quiet', 'loud', |
| 19 | 'smooth', 'rough', 'bright', 'dark', 'warm', 'cool', 'playful', 'curious' |
| 20 | ]; |
| 21 | |
| 22 | const ANIMALS = [ |
| 23 | 'kitten', 'cat', 'tiger', 'lion', 'panda', 'fox', 'wolf', 'bear', 'rabbit', |
| 24 | 'mouse', 'bird', 'fish', 'frog', 'bee', 'butterfly', 'owl', 'penguin', 'dolphin' |
| 25 | ]; |
| 26 | |
| 27 | function cleanRecipient(recipient) { |
| 28 | if (!recipient) return ''; |
| 29 | return recipient.trim().replace(/@.*$/, ''); |
| 30 | } |
| 31 | |
| 32 | function generateRandomEmail() { |
| 33 | const adj = ADJECTIVES[Math.floor(Math.random() * ADJECTIVES.length)]; |
| 34 | const animal = ANIMALS[Math.floor(Math.random() * ANIMALS.length)]; |
| 35 | const num = Math.floor(Math.random() * 990) + 10; |
| 36 | return `${adj}-${animal}-${num}@akunlama.com`; |
| 37 | } |
| 38 | |
| 39 | function htmlToPlainText(html) { |
| 40 | if (!html) return ''; |
| 41 | return html |
| 42 | .replace(/<style[^>]*>[\s\S]*?<\/style>/gi, '') |
| 43 | .replace(/<script[^>]*>[\s\S]*?<\/script>/gi, '') |
| 44 | .replace(/<br\s*[\/]?>/gi, '\n') |
| 45 | .replace(/<\/(p|div|tr|h[1-6]|li)>/gi, '\n') |
| 46 | .replace(/<[^>]+>/g, '') |
| 47 | .replace(/ /g, ' ') |
| 48 | .replace(/&/g, '&') |
| 49 | .replace(/</g, '<') |
| 50 | .replace(/>/g, '>') |
| 51 | .replace(/"/g, '"') |
| 52 | .replace(/'/g, "'") |
| 53 | .split('\n') |
| 54 | .map(line => line.trim()) |
| 55 | .filter(Boolean) |
| 56 | .join('\n'); |
| 57 | } |
| 58 | |
| 59 | async function listMessages(recipient) { |
| 60 | const user = cleanRecipient(recipient); |
| 61 | const url = `${BASE_URL}/list?recipient=${encodeURIComponent(user)}`; |
| 62 | const res = await fetch(url, { headers: DEFAULT_HEADERS }); |
| 63 | if (!res.ok) { |
| 64 | throw new Error(`Failed to fetch message list: ${res.status} ${res.statusText}`); |
| 65 | } |
| 66 | return await res.json(); |
| 67 | } |
| 68 | |
| 69 | async function getMessageDetail(region, key) { |
| 70 | const metaUrl = `${BASE_URL}/getKey?region=${encodeURIComponent(region)}&key=${encodeURIComponent(key)}`; |
| 71 | const htmlUrl = `${BASE_URL}/getHtml?region=${encodeURIComponent(region)}&key=${encodeURIComponent(key)}`; |
| 72 | |
| 73 | const [metaRes, htmlRes] = await Promise.all([ |
| 74 | fetch(metaUrl, { headers: DEFAULT_HEADERS }), |
| 75 | fetch(htmlUrl, { headers: DEFAULT_HEADERS }) |
| 76 | ]); |
| 77 | |
| 78 | const metadata = metaRes.ok ? await metaRes.json() : {}; |
| 79 | const html = htmlRes.ok ? await htmlRes.text() : ''; |
| 80 | const plainText = htmlToPlainText(html); |
| 81 | |
| 82 | const codeMatches = plainText.match(/\b\d{4,8}\b/g) || []; |
| 83 | const extractedCodes = [...new Set(codeMatches)]; |
| 84 | |
| 85 | const linkMatches = html.match(/href=["'](https?:\/\/[^"']+)["']/gi) || []; |
| 86 | const extractedLinks = [...new Set(linkMatches.map(m => m.replace(/^href=["']|["']$/gi, '')))]; |
| 87 | |
| 88 | return { |
| 89 | metadata, |
| 90 | plainText, |
| 91 | html, |
| 92 | extractedCodes, |
| 93 | extractedLinks |
| 94 | }; |
| 95 | } |
| 96 | |
| 97 | async function watchInbox(recipient, intervalMs = 5000, timeoutMs = 60000) { |
| 98 | const user = cleanRecipient(recipient); |
| 99 | console.log(`[*] Watching inbox: ${user}@akunlama.com...`); |
| 100 | |
| 101 | const initialList = await listMessages(user); |
| 102 | const knownKeys = new Set( |
| 103 | initialList.map(m => m.storage?.key).filter(Boolean) |
| 104 | ); |
| 105 | console.log(`[*] ${knownKeys.size} pesan yang sudah ada.`); |
| 106 | |
| 107 | const startTime = Date.now(); |
| 108 | while (Date.now() - startTime < timeoutMs) { |
| 109 | await new Promise(resolve => setTimeout(resolve, intervalMs)); |
| 110 | process.stdout.write('.'); |
| 111 | |
| 112 | try { |
| 113 | const currentList = await listMessages(user); |
| 114 | for (const msg of currentList) { |
| 115 | const key = msg.storage?.key; |
| 116 | if (key && !knownKeys.has(key)) { |
| 117 | console.log('\n\n[+] Email baru diterima!'); |
| 118 | const region = msg.storage?.region || 'us'; |
| 119 | return await getMessageDetail(region, key); |
| 120 | } |
| 121 | } |
| 122 | } catch (err) { |
| 123 | console.error(`\n[!] Error polling: ${err.message}`); |
| 124 | } |
| 125 | } |
| 126 | |
| 127 | console.log('\n[-] Waktu habis tanpa pesan baru.'); |
| 128 | return null; |
| 129 | } |
| 130 | |
| 131 | async function runSelfTest() { |
| 132 | console.log('\n============================================================='); |
| 133 | console.log(' AKUNLAMA.COM SCRAPER - TEST OTOMATIS & GENERATE AKUN '); |
| 134 | console.log('=============================================================\n'); |
| 135 | |
| 136 | console.log('[1] MEMBUAT AKUN TEMPORARY BARU...'); |
| 137 | const newEmail = generateRandomEmail(); |
| 138 | const username = cleanRecipient(newEmail); |
| 139 | console.log(` ✓ Alamat Email : ${newEmail}`); |
| 140 | console.log(` ✓ Username : ${username}`); |
| 141 | console.log(` ✓ Web Inbox : https://akunlama.com/inbox/${newEmail}`); |
| 142 | console.log(` ✓ API Endpoint : ${BASE_URL}/list?recipient=${username}`); |
| 143 | |
| 144 | console.log('\n[2] CEK STATUS INBOX AKUN BARU...'); |
| 145 | const newInboxMessages = await listMessages(username); |
| 146 | console.log(' ✓ Status HTTP : 200 OK'); |
| 147 | console.log(` ✓ Jumlah Pesan : ${newInboxMessages.length} (Inbox siap digunakan)`); |
| 148 | |
| 149 | console.log('\n[3] PENGUJIAN SCRAPER LENGKAP PADA INBOX AKTIF (admin)...'); |
| 150 | const testUser = 'admin'; |
| 151 | const messages = await listMessages(testUser); |
| 152 | console.log(` ✓ Ditemukan ${messages.length} pesan di inbox '${testUser}@akunlama.com'`); |
| 153 | |
| 154 | if (messages.length > 0) { |
| 155 | const sampleMsg = messages[0]; |
| 156 | const storage = sampleMsg.storage || {}; |
| 157 | const headers = sampleMsg.message?.headers || {}; |
| 158 | |
| 159 | console.log('\n --- Ringkasan Pesan ---'); |
| 160 | console.log(` • Subject : ${headers.subject || '(Tanpa Subject)'}`); |
| 161 | console.log(` • From : ${headers.from || '(Tidak diketahui)'}`); |
| 162 | console.log(` • Preview : ${(sampleMsg.preview || '').trim().slice(0, 100)}`); |
| 163 | console.log(` • Region : ${storage.region} | Storage Key: ${storage.key}`); |
| 164 | |
| 165 | if (storage.key && storage.region) { |
| 166 | console.log('\n[4] MENGAMBIL DETAIL KONTEN LENGKAP & EKSTRAKSI DATA...'); |
| 167 | const detail = await getMessageDetail(storage.region, storage.key); |
| 168 | |
| 169 | console.log(` ✓ Metadata Subject : ${detail.metadata.subject}`); |
| 170 | console.log(` ✓ Pengirim Asli : ${detail.metadata.name} <${detail.metadata.emailAddress}>`); |
| 171 | console.log(` ✓ Waktu Kirim : ${detail.metadata.Date}`); |
| 172 | console.log(` ✓ Ukuran Raw HTML : ${detail.html.length} bytes`); |
| 173 | console.log(` ✓ Panjang Teks : ${detail.plainText.length} karakter`); |
| 174 | |
| 175 | if (detail.extractedCodes.length > 0) { |
| 176 | console.log(` ✓ Kode OTP/Verifikasi Terdeteksi: [ ${detail.extractedCodes.join(', ')} ]`); |
| 177 | } else { |
| 178 | console.log(' • Kode OTP/Verifikasi: Tidak ada kode angka'); |
| 179 | } |
| 180 | |
| 181 | if (detail.extractedLinks.length > 0) { |
| 182 | console.log(` ✓ Link/URL Terdeteksi (${detail.extractedLinks.length} link):`); |
| 183 | detail.extractedLinks.slice(0, 3).forEach((link, i) => { |
| 184 | const displayLink = link.length > 80 ? link.slice(0, 80) + '...' : link; |
| 185 | console.log(` [${i + 1}] ${displayLink}`); |
| 186 | }); |
| 187 | } |
| 188 | |
| 189 | console.log('\n --- Cuplikan Teks Bersih ---'); |
| 190 | const snippetLines = detail.plainText.split('\n').filter(l => l.trim().length > 0).slice(0, 5); |
| 191 | snippetLines.forEach(l => console.log(` | ${l}`)); |
| 192 | console.log(' ----------------------------'); |
| 193 | } |
| 194 | } |
| 195 | |
| 196 | console.log('\n============================================================='); |
| 197 | console.log(' PENGUJIAN SELESAI & SEMUA FUNGSI NORMAL '); |
| 198 | console.log('=============================================================\n'); |
| 199 | } |
| 200 | |
| 201 | async function main() { |
| 202 | const [target, action] = process.argv.slice(2); |
| 203 | |
| 204 | if (!target) { |
| 205 | await runSelfTest(); |
| 206 | return; |
| 207 | } |
| 208 | |
| 209 | if (target === 'generate') { |
| 210 | const email = generateRandomEmail(); |
| 211 | console.log(`Email Baru : ${email}`); |
| 212 | console.log(`Web Inbox URL: https://akunlama.com/inbox/${email}`); |
| 213 | return; |
| 214 | } |
| 215 | |
| 216 | if (action === 'watch') { |
| 217 | const result = await watchInbox(target); |
| 218 | if (result) { |
| 219 | console.log('\n========================================'); |
| 220 | console.log(`Subject : ${result.metadata.subject || '(Tanpa Subject)'}`); |
| 221 | console.log(`From : ${result.metadata.name || ''} <${result.metadata.emailAddress}>`); |
| 222 | console.log(`Date : ${result.metadata.Date}`); |
| 223 | if (result.extractedCodes.length > 0) { |
| 224 | console.log(`OTP : ${result.extractedCodes.join(', ')}`); |
| 225 | } |
| 226 | if (result.extractedLinks.length > 0) { |
| 227 | console.log(`Links : ${result.extractedLinks.slice(0, 3).join('\n ')}`); |
| 228 | } |
| 229 | console.log(`\nKonten:\n${result.plainText.slice(0, 400)}...\n`); |
| 230 | } |
| 231 | return; |
| 232 | } |
| 233 | |
| 234 | const user = cleanRecipient(target); |
| 235 | const messages = await listMessages(user); |
| 236 | |
| 237 | console.log('\n======================================================='); |
| 238 | console.log(` Inbox: ${user}@akunlama.com`); |
| 239 | console.log(` Total Pesan: ${messages.length}`); |
| 240 | console.log('=======================================================\n'); |
| 241 | |
| 242 | if (messages.length === 0) { |
| 243 | console.log('Inbox kosong. Belum ada pesan masuk.'); |
| 244 | return; |
| 245 | } |
| 246 | |
| 247 | for (let i = 0; i < messages.length; i++) { |
| 248 | const msg = messages[i]; |
| 249 | const headers = msg.message?.headers || {}; |
| 250 | const storage = msg.storage || {}; |
| 251 | |
| 252 | console.log(`[${i + 1}] Subject : ${headers.subject || '(Tanpa Subject)'}`); |
| 253 | console.log(` From : ${headers.from}`); |
| 254 | console.log(` Preview : ${(msg.preview || '').trim().slice(0, 80)}`); |
| 255 | console.log(` Region : ${storage.region} | Key: ${storage.key}`); |
| 256 | |
| 257 | if (storage.key && storage.region) { |
| 258 | const detail = await getMessageDetail(storage.region, storage.key); |
| 259 | if (detail.extractedCodes.length > 0) { |
| 260 | console.log(` >> Kode OTP: ${detail.extractedCodes.join(', ')}`); |
| 261 | } |
| 262 | if (detail.extractedLinks.length > 0) { |
| 263 | console.log(` >> Link (${detail.extractedLinks.length}):`); |
| 264 | detail.extractedLinks.slice(0, 3).forEach(link => console.log(` - ${link}`)); |
| 265 | } |
| 266 | console.log('\n --- Isi Pesan ---'); |
| 267 | detail.plainText.split('\n').slice(0, 6).forEach(line => console.log(` ${line}`)); |
| 268 | console.log(' -----------------\n'); |
| 269 | } |
| 270 | console.log('-------------------------------------------------------'); |
| 271 | } |
| 272 | } |
| 273 | |
| 274 | module.exports = { |
| 275 | cleanRecipient, |
| 276 | generateRandomEmail, |
| 277 | htmlToPlainText, |
| 278 | listMessages, |
| 279 | getMessageDetail, |
| 280 | watchInbox, |
| 281 | runSelfTest |
| 282 | }; |
| 283 | |
| 284 | if (require.main === module) { |
| 285 | main().catch(err => { |
| 286 | console.error('Error:', err.message); |
| 287 | process.exit(1); |
| 288 | }); |
| 289 | } |
| 290 | |
Discussion & Comments0
No comments yet — be the first to leave feedback or start a code discussion.
Sign in with your GitHub account to write comments and join the discussion.