| | const fs = require('fs'); |
| | const path = require('path'); |
| | |
| | const { extractTextFromImage } = require('./imageProcessor'); |
| |
|
| | |
| | const NUMBER_WORDS = { |
| | 'nol': '0', 'satu': '1', 'dua': '2', 'tiga': '3', 'empat': '4', 'lima': '5', |
| | 'enam': '6', 'tujuh': '7', 'delapan': '8', 'sembilan': '9', 'sepuluh': '10', |
| | 'sebelas': '11', 'one': '1', 'two': '2', 'three': '3', 'four': '4', 'five': '5', |
| | 'six': '6', 'seven': '7', 'eight': '8', 'nine': '9', 'ten': '10', |
| | 'zero': '0', 'eleven': '11', 'twelve': '12' |
| | }; |
| |
|
| | const LEET_MAP = { |
| | '4': 'a', '@': 'a', '8': 'b', '3': 'e', '6': 'g', '1': 'i', '!': 'i', '0': 'o', |
| | '5': 's', '$': 's', '7': 't', '+': 't', '2': 'z' |
| | }; |
| |
|
| | |
| | function safeString(s) { return (s || '').toString(); } |
| |
|
| | function normalizeText(text) { |
| | let normalized = safeString(text).normalize('NFD').replace(/[\u0300-\u036f]/g, ''); |
| | normalized = normalized.toLowerCase(); |
| | |
| | |
| | let leetOut = ''; |
| | for (const ch of normalized) { leetOut += (LEET_MAP[ch] !== undefined) ? LEET_MAP[ch] : ch; } |
| | normalized = leetOut; |
| | |
| | |
| | normalized = normalized.replace(/[^a-z0-9\s]/g, ' ').replace(/\s+/g, ' ').trim(); |
| | |
| | |
| | const tokens = normalized.split(/\s+/); |
| | return tokens.map(t => NUMBER_WORDS[t] !== undefined ? NUMBER_WORDS[t] : t).join(' '); |
| | } |
| |
|
| | function levenshtein(a = '', b = '') { |
| | const alen = a.length, blen = b.length; |
| | if (alen === 0) return blen; |
| | if (blen === 0) return alen; |
| | const matrix = Array.from({ length: alen + 1 }, () => new Array(blen + 1)); |
| | for (let i = 0; i <= alen; i++) matrix[i][0] = i; |
| | for (let j = 0; j <= blen; j++) matrix[0][j] = j; |
| | for (let i = 1; i <= alen; i++) { |
| | for (let j = 1; j <= blen; j++) { |
| | const cost = a[i - 1] === b[j - 1] ? 0 : 1; |
| | matrix[i][j] = Math.min(matrix[i - 1][j] + 1, matrix[i][j - 1] + 1, matrix[i - 1][j - 1] + cost); |
| | } |
| | } |
| | return matrix[alen][blen]; |
| | } |
| |
|
| | function similarity(a, b) { |
| | a = normalizeText(a); b = normalizeText(b); |
| | if (a === b || a.includes(b) || b.includes(a)) return 1; |
| | const dist = levenshtein(a, b); |
| | const maxLen = Math.max(a.length, b.length); |
| | return maxLen === 0 ? 1 : 1 - (dist / maxLen); |
| | } |
| |
|
| | |
| | async function solve(data) { |
| | try { |
| | console.log("🛠️ Processing Antibot Challenge..."); |
| | |
| | const mainBuffer = Buffer.from(data.main, 'base64'); |
| | const botsBuffers = data.bots.map(b => Buffer.from(b, 'base64')); |
| |
|
| | |
| | const mainOCR = await extractTextFromImage(mainBuffer); |
| | let rawMain = (mainOCR.response || "").toLowerCase(); |
| | console.log("🎯 Raw Instruction:", rawMain); |
| |
|
| | |
| | const targets = rawMain |
| | .replace(/please\s*click\s*on\s*the\s*anti-bot\s*links\s*in\s*the\s*following\s*order/gi, '') |
| | .replace(/[:.,|+&-]/g, ' ') |
| | .split(/\s+/) |
| | .filter(t => t.length > 0 && t !== 'and'); |
| |
|
| | console.log("🔍 Cleaned Targets:", targets); |
| |
|
| | |
| | const botResults = []; |
| | for (let i = 0; i < botsBuffers.length; i++) { |
| | const res = await extractTextFromImage(botsBuffers[i]); |
| | botResults.push({ |
| | index: (i + 1).toString(), |
| | text: normalizeText(res.response || "") |
| | }); |
| | console.log(`🖼️ Bot ${i+1} OCR: "${res.response}"`); |
| | } |
| |
|
| | |
| | let finalOrder = []; |
| | let usedIndices = new Set(); |
| |
|
| | for (const target of targets) { |
| | let bestMatch = { index: null, score: -1 }; |
| | |
| | for (const bot of botResults) { |
| | if (usedIndices.has(bot.index)) continue; |
| | |
| | const score = similarity(bot.text, target); |
| | if (score > bestMatch.score) { |
| | bestMatch = { index: bot.index, score: score }; |
| | } |
| | } |
| |
|
| | |
| | if (bestMatch.index && bestMatch.score > 0.3) { |
| | finalOrder.push(bestMatch.index); |
| | usedIndices.add(bestMatch.index); |
| | } |
| | } |
| |
|
| | |
| | if (finalOrder.length < botsBuffers.length) { |
| | botResults.forEach(b => { |
| | if(!usedIndices.has(b.index)) finalOrder.push(b.index); |
| | }); |
| | } |
| |
|
| | |
| | finalOrder = finalOrder.slice(0, botsBuffers.length); |
| |
|
| | console.log("✅ Final Solution:", finalOrder.join(", ")); |
| | return { status: "Success", result: finalOrder }; |
| |
|
| | } catch (error) { |
| | console.error("❌ Solver Error:", error.message); |
| | return { status: "Error", message: error.message, result: ["1", "2", "3"] }; |
| | } |
| | } |
| |
|
| | module.exports = solve; |
| |
|