Update endpoints/antibot.js
Browse files- endpoints/antibot.js +35 -33
endpoints/antibot.js
CHANGED
|
@@ -8,7 +8,8 @@ const NUMBER_WORDS = {
|
|
| 8 |
'nol': '0', 'satu': '1', 'dua': '2', 'tiga': '3', 'empat': '4', 'lima': '5',
|
| 9 |
'enam': '6', 'tujuh': '7', 'delapan': '8', 'sembilan': '9', 'sepuluh': '10',
|
| 10 |
'sebelas': '11', 'one': '1', 'two': '2', 'three': '3', 'four': '4', 'five': '5',
|
| 11 |
-
'six': '6', 'seven': '7', 'eight': '8', 'nine': '9', 'ten': '10'
|
|
|
|
| 12 |
};
|
| 13 |
|
| 14 |
const LEET_MAP = {
|
|
@@ -20,19 +21,20 @@ const LEET_MAP = {
|
|
| 20 |
function safeString(s) { return (s || '').toString(); }
|
| 21 |
|
| 22 |
function normalizeText(text) {
|
| 23 |
-
|
| 24 |
-
let normalized = original.normalize('NFD').replace(/[\u0300-\u036f]/g, '');
|
| 25 |
normalized = normalized.toLowerCase();
|
| 26 |
-
|
|
|
|
| 27 |
let leetOut = '';
|
| 28 |
for (const ch of normalized) { leetOut += (LEET_MAP[ch] !== undefined) ? LEET_MAP[ch] : ch; }
|
| 29 |
normalized = leetOut;
|
| 30 |
-
|
|
|
|
| 31 |
normalized = normalized.replace(/[^a-z0-9\s]/g, ' ').replace(/\s+/g, ' ').trim();
|
| 32 |
-
|
|
|
|
| 33 |
const tokens = normalized.split(/\s+/);
|
| 34 |
-
|
| 35 |
-
return normalized;
|
| 36 |
}
|
| 37 |
|
| 38 |
function levenshtein(a = '', b = '') {
|
|
@@ -53,7 +55,7 @@ function levenshtein(a = '', b = '') {
|
|
| 53 |
|
| 54 |
function similarity(a, b) {
|
| 55 |
a = normalizeText(a); b = normalizeText(b);
|
| 56 |
-
if (a === b) return 1;
|
| 57 |
const dist = levenshtein(a, b);
|
| 58 |
const maxLen = Math.max(a.length, b.length);
|
| 59 |
return maxLen === 0 ? 1 : 1 - (dist / maxLen);
|
|
@@ -62,25 +64,26 @@ function similarity(a, b) {
|
|
| 62 |
// --- LOGIKA UTAMA SOLVER ---
|
| 63 |
async function solve(data) {
|
| 64 |
try {
|
| 65 |
-
console.log("🛠️
|
| 66 |
|
| 67 |
-
// 1. Convert Base64 ti PHP ka Buffer
|
| 68 |
const mainBuffer = Buffer.from(data.main, 'base64');
|
| 69 |
const botsBuffers = data.bots.map(b => Buffer.from(b, 'base64'));
|
| 70 |
|
| 71 |
-
//
|
| 72 |
const mainOCR = await extractTextFromImage(mainBuffer);
|
| 73 |
-
|
| 74 |
-
console.log("🎯
|
| 75 |
|
| 76 |
-
//
|
| 77 |
-
const targets =
|
| 78 |
-
.replace(/please
|
| 79 |
-
.replace(/[
|
| 80 |
-
.split(/\s+/)
|
| 81 |
-
.filter(t => t.length >
|
| 82 |
|
| 83 |
-
|
|
|
|
|
|
|
| 84 |
const botResults = [];
|
| 85 |
for (let i = 0; i < botsBuffers.length; i++) {
|
| 86 |
const res = await extractTextFromImage(botsBuffers[i]);
|
|
@@ -88,10 +91,10 @@ async function solve(data) {
|
|
| 88 |
index: (i + 1).toString(),
|
| 89 |
text: normalizeText(res.response || "")
|
| 90 |
});
|
| 91 |
-
console.log(`🖼️ Bot
|
| 92 |
}
|
| 93 |
|
| 94 |
-
//
|
| 95 |
let finalOrder = [];
|
| 96 |
let usedIndices = new Set();
|
| 97 |
|
|
@@ -107,31 +110,30 @@ async function solve(data) {
|
|
| 107 |
}
|
| 108 |
}
|
| 109 |
|
| 110 |
-
//
|
| 111 |
-
if (bestMatch.index && bestMatch.score > 0.
|
| 112 |
finalOrder.push(bestMatch.index);
|
| 113 |
usedIndices.add(bestMatch.index);
|
| 114 |
}
|
| 115 |
}
|
| 116 |
|
| 117 |
-
// Fallback
|
| 118 |
if (finalOrder.length < botsBuffers.length) {
|
| 119 |
botResults.forEach(b => {
|
| 120 |
if(!usedIndices.has(b.index)) finalOrder.push(b.index);
|
| 121 |
});
|
| 122 |
}
|
| 123 |
|
| 124 |
-
|
| 125 |
-
|
| 126 |
-
|
| 127 |
-
|
| 128 |
-
};
|
| 129 |
|
| 130 |
} catch (error) {
|
| 131 |
-
console.error("❌
|
| 132 |
return { status: "Error", message: error.message, result: ["1", "2", "3"] };
|
| 133 |
}
|
| 134 |
}
|
| 135 |
|
| 136 |
-
// --- PENTING: EXPORT SALAKU FUNGSI TUNGGAL ---
|
| 137 |
module.exports = solve;
|
|
|
|
| 8 |
'nol': '0', 'satu': '1', 'dua': '2', 'tiga': '3', 'empat': '4', 'lima': '5',
|
| 9 |
'enam': '6', 'tujuh': '7', 'delapan': '8', 'sembilan': '9', 'sepuluh': '10',
|
| 10 |
'sebelas': '11', 'one': '1', 'two': '2', 'three': '3', 'four': '4', 'five': '5',
|
| 11 |
+
'six': '6', 'seven': '7', 'eight': '8', 'nine': '9', 'ten': '10',
|
| 12 |
+
'zero': '0', 'eleven': '11', 'twelve': '12'
|
| 13 |
};
|
| 14 |
|
| 15 |
const LEET_MAP = {
|
|
|
|
| 21 |
function safeString(s) { return (s || '').toString(); }
|
| 22 |
|
| 23 |
function normalizeText(text) {
|
| 24 |
+
let normalized = safeString(text).normalize('NFD').replace(/[\u0300-\u036f]/g, '');
|
|
|
|
| 25 |
normalized = normalized.toLowerCase();
|
| 26 |
+
|
| 27 |
+
// Apply Leet Map (anti-deteksi karakter anéh)
|
| 28 |
let leetOut = '';
|
| 29 |
for (const ch of normalized) { leetOut += (LEET_MAP[ch] !== undefined) ? LEET_MAP[ch] : ch; }
|
| 30 |
normalized = leetOut;
|
| 31 |
+
|
| 32 |
+
// Beberesih karakter non-alfanumerik
|
| 33 |
normalized = normalized.replace(/[^a-z0-9\s]/g, ' ').replace(/\s+/g, ' ').trim();
|
| 34 |
+
|
| 35 |
+
// Mapping kecap angka jadi digit
|
| 36 |
const tokens = normalized.split(/\s+/);
|
| 37 |
+
return tokens.map(t => NUMBER_WORDS[t] !== undefined ? NUMBER_WORDS[t] : t).join(' ');
|
|
|
|
| 38 |
}
|
| 39 |
|
| 40 |
function levenshtein(a = '', b = '') {
|
|
|
|
| 55 |
|
| 56 |
function similarity(a, b) {
|
| 57 |
a = normalizeText(a); b = normalizeText(b);
|
| 58 |
+
if (a === b || a.includes(b) || b.includes(a)) return 1;
|
| 59 |
const dist = levenshtein(a, b);
|
| 60 |
const maxLen = Math.max(a.length, b.length);
|
| 61 |
return maxLen === 0 ? 1 : 1 - (dist / maxLen);
|
|
|
|
| 64 |
// --- LOGIKA UTAMA SOLVER ---
|
| 65 |
async function solve(data) {
|
| 66 |
try {
|
| 67 |
+
console.log("🛠️ Processing Antibot Challenge...");
|
| 68 |
|
|
|
|
| 69 |
const mainBuffer = Buffer.from(data.main, 'base64');
|
| 70 |
const botsBuffers = data.bots.map(b => Buffer.from(b, 'base64'));
|
| 71 |
|
| 72 |
+
// OCR Gambar Instruksi Utama
|
| 73 |
const mainOCR = await extractTextFromImage(mainBuffer);
|
| 74 |
+
let rawMain = (mainOCR.response || "").toLowerCase();
|
| 75 |
+
console.log("🎯 Raw Instruction:", rawMain);
|
| 76 |
|
| 77 |
+
// --- BAGIAN TARGET NU DIUBAH (LEMBUT TAPI TEGAS) ---
|
| 78 |
+
const targets = rawMain
|
| 79 |
+
.replace(/please\s*click\s*on\s*the\s*anti-bot\s*links\s*in\s*the\s*following\s*order/gi, '')
|
| 80 |
+
.replace(/[:.,|+&-]/g, ' ') // Ganti karakter separator ku spasi
|
| 81 |
+
.split(/\s+/)
|
| 82 |
+
.filter(t => t.length > 0 && t !== 'and');
|
| 83 |
|
| 84 |
+
console.log("🔍 Cleaned Targets:", targets);
|
| 85 |
+
|
| 86 |
+
// OCR Kabéh Gambar Pilihan (Bots)
|
| 87 |
const botResults = [];
|
| 88 |
for (let i = 0; i < botsBuffers.length; i++) {
|
| 89 |
const res = await extractTextFromImage(botsBuffers[i]);
|
|
|
|
| 91 |
index: (i + 1).toString(),
|
| 92 |
text: normalizeText(res.response || "")
|
| 93 |
});
|
| 94 |
+
console.log(`🖼️ Bot ${i+1} OCR: "${res.response}"`);
|
| 95 |
}
|
| 96 |
|
| 97 |
+
// Matching Strategy
|
| 98 |
let finalOrder = [];
|
| 99 |
let usedIndices = new Set();
|
| 100 |
|
|
|
|
| 110 |
}
|
| 111 |
}
|
| 112 |
|
| 113 |
+
// Skor minimal 0.3 (30%) bisi OCR-na rada burem
|
| 114 |
+
if (bestMatch.index && bestMatch.score > 0.3) {
|
| 115 |
finalOrder.push(bestMatch.index);
|
| 116 |
usedIndices.add(bestMatch.index);
|
| 117 |
}
|
| 118 |
}
|
| 119 |
|
| 120 |
+
// Fallback: Mun aya bot nu can kapaéh, asupkeun dumasar urutan
|
| 121 |
if (finalOrder.length < botsBuffers.length) {
|
| 122 |
botResults.forEach(b => {
|
| 123 |
if(!usedIndices.has(b.index)) finalOrder.push(b.index);
|
| 124 |
});
|
| 125 |
}
|
| 126 |
|
| 127 |
+
// Pastikeun ngan ngirim jumlah nu sarua jeung bot nu aya
|
| 128 |
+
finalOrder = finalOrder.slice(0, botsBuffers.length);
|
| 129 |
+
|
| 130 |
+
console.log("✅ Final Solution:", finalOrder.join(", "));
|
| 131 |
+
return { status: "Success", result: finalOrder };
|
| 132 |
|
| 133 |
} catch (error) {
|
| 134 |
+
console.error("❌ Solver Error:", error.message);
|
| 135 |
return { status: "Error", message: error.message, result: ["1", "2", "3"] };
|
| 136 |
}
|
| 137 |
}
|
| 138 |
|
|
|
|
| 139 |
module.exports = solve;
|