Fourstore commited on
Commit
c7e90cf
·
verified ·
1 Parent(s): 928b8e1

Update endpoints/antibot.js

Browse files
Files changed (1) hide show
  1. endpoints/antibot.js +42 -81
endpoints/antibot.js CHANGED
@@ -3,26 +3,30 @@ const path = require('path');
3
  const { extractTextFromImage } = require('./imageProcessor');
4
 
5
  function mapAnswer(soalArray, jawaban, botIndex) {
6
- console.log(`[DEBUG] Bot ${botIndex} jawaban: "${jawaban}"`);
7
  return jawaban;
8
  }
9
 
10
  function normalizeText(text) {
11
- const normalized = text.toLowerCase().replace(/[^\w\s]/g, '').trim();
12
- console.log(`[DEBUG] Normalize: "${text}" -> "${normalized}"`);
13
- return normalized;
14
  }
15
 
16
  function isValueMatch(value, targetSoal) {
17
- console.log(`[DEBUG] Compare: "${value}" vs "${targetSoal}"`);
18
-
19
  const numberMap = {
20
  '0': 'zero', '1': 'one', '2': 'two', '3': 'three', '4': 'four',
21
  '5': 'five', '6': 'six', '7': 'seven', '8': 'eight', '9': 'nine', '10': 'ten',
22
  'zero': '0', 'one': '1', 'two': '2', 'three': '3', 'four': '4',
23
  'five': '5', 'six': '6', 'seven': '7', 'eight': '8', 'nine': '9', 'ten': '10',
24
  'I': '1', 'II': '2', 'III': '3', 'IV': '4', 'V': '5',
25
- 'VI': '6', 'VII': '7', 'VIII': '8', 'IX': '9', 'X': '10'
 
 
 
 
 
 
 
 
 
26
  };
27
 
28
  const leetMap = {
@@ -35,14 +39,17 @@ function isValueMatch(value, targetSoal) {
35
  'G': '6', 'g': '6',
36
  'T': '7', 't': '7',
37
  'B': '8', 'b': '8',
38
- 'Q': '9', 'q': '9'
 
 
 
 
39
  };
40
 
41
  const normalizedValue = normalizeText(value);
42
  const normalizedSoal = normalizeText(targetSoal);
43
 
44
  if (normalizedValue === normalizedSoal) {
45
- console.log(`[DEBUG] ✅ Exact match`);
46
  return true;
47
  }
48
 
@@ -52,63 +59,55 @@ function isValueMatch(value, targetSoal) {
52
 
53
  const leetValue = convertLeet(value);
54
  const leetSoal = convertLeet(targetSoal);
55
-
56
- console.log(`[DEBUG] Leet converted: "${value}" -> "${leetValue}", "${targetSoal}" -> "${leetSoal}"`);
57
 
58
- if (leetValue === normalizedSoal) {
59
- console.log(`[DEBUG] Leet match (value -> soal)`);
60
- return true;
61
- }
62
-
63
- if (normalizedValue === leetSoal) {
64
- console.log(`[DEBUG] ✅ Leet match (soal -> value)`);
65
- return true;
66
- }
67
-
68
- if (leetValue === leetSoal) {
69
- console.log(`[DEBUG] ✅ Both leet match`);
70
- return true;
71
- }
72
 
73
  const mappedValue = numberMap[normalizedValue] || numberMap[value] || normalizedValue;
74
  const mappedSoal = numberMap[normalizedSoal] || numberMap[targetSoal] || normalizedSoal;
75
 
76
- console.log(`[DEBUG] Mapped: "${mappedValue}" vs "${mappedSoal}"`);
 
 
77
 
78
- if (mappedValue === normalizedSoal) {
79
- console.log(`[DEBUG] Number map match`);
80
- return true;
81
- }
82
- if (normalizedValue === mappedSoal) {
83
- console.log(`[DEBUG] ✅ Number map match reversed`);
84
- return true;
85
- }
86
- if (mappedValue === mappedSoal) {
87
- console.log(`[DEBUG] ✅ Both mapped match`);
88
  return true;
89
  }
90
 
91
  try {
92
  const valueResult = evaluateSimpleMath(value);
93
  const soalResult = evaluateSimpleMath(targetSoal);
94
-
95
  if (valueResult !== null && soalResult !== null && valueResult === soalResult) {
96
- console.log(`[DEBUG] ✅ Math match: ${valueResult}`);
97
  return true;
98
  }
99
- } catch (e) {
100
- }
101
 
102
- console.log(`[DEBUG] ❌ No match`);
103
  return false;
104
  }
105
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
106
  function evaluateSimpleMath(expression) {
107
  if (!expression) return null;
108
-
109
  const cleanExpr = expression.toString().replace(/[^\d+\-*/.()]/g, '');
110
  if (!cleanExpr) return null;
111
-
112
  try {
113
  if (cleanExpr.length > 10) return null;
114
  const result = Function(`"use strict"; return (${cleanExpr})`)();
@@ -119,34 +118,24 @@ function evaluateSimpleMath(expression) {
119
  }
120
 
121
  function parseSoalText(text) {
122
- console.log(`[DEBUG] Original text: "${text}"`);
123
-
124
  const delimiters = /[.,:;\\/\s]+/;
125
  let parts = text.split(delimiters).filter(part => part.trim() !== '');
126
-
127
  if (parts.length === 1) {
128
  parts = text.split(/\s+/).filter(part => part.trim() !== '');
129
  }
130
-
131
- console.log(`[DEBUG] Parsed soal: [${parts.join(', ')}]`);
132
  return parts;
133
  }
134
 
135
  async function antibot(data) {
136
- console.log('[DEBUG] ===== START ANTIBOT PROCESS =====');
137
-
138
  try {
139
  const { main, bots } = data;
140
- console.log(`[DEBUG] Processing ${bots.length} bots`);
141
 
142
  const mainBuffer = Buffer.from(main, 'base64');
143
  const mainText = await extractTextFromImage(mainBuffer);
144
- console.log(`[DEBUG] Main text extracted: "${mainText.response}"`);
145
 
146
  const soalArray = parseSoalText(mainText.response);
147
 
148
  if (soalArray.length === 0) {
149
- console.error('[DEBUG] ❌ No soal detected');
150
  throw new Error('Tidak ada soal yang terdeteksi');
151
  }
152
 
@@ -154,13 +143,9 @@ async function antibot(data) {
154
 
155
  for (let i = 0; i < bots.length; i++) {
156
  const bot = bots[i];
157
- console.log(`[DEBUG] Processing bot ${i}: ${bot.id}`);
158
-
159
  try {
160
  const botBuffer = Buffer.from(bot.img, 'base64');
161
  const botText = await extractTextFromImage(botBuffer);
162
- console.log(`[DEBUG] Bot ${bot.id} text: "${botText.response}"`);
163
-
164
  const mappedValue = mapAnswer(soalArray, botText.response, i);
165
 
166
  botResults.push({
@@ -171,7 +156,6 @@ async function antibot(data) {
171
  });
172
 
173
  } catch (error) {
174
- console.error(`[DEBUG] ❌ Bot ${bot.id} error:`, error.message);
175
  botResults.push({
176
  id: bot.id,
177
  text: '',
@@ -182,13 +166,10 @@ async function antibot(data) {
182
  }
183
  }
184
 
185
- console.log('[DEBUG] ===== MATCHING PHASE =====');
186
  const result = [];
187
  const usedIds = new Set();
188
  let matchedCount = 0;
189
 
190
- console.log(`[DEBUG] Soal to match: [${soalArray.join(', ')}]`);
191
-
192
  for (let i = 0; i < soalArray.length; i++) {
193
  const targetSoal = soalArray[i];
194
  let foundId = null;
@@ -199,7 +180,6 @@ async function antibot(data) {
199
  foundId = bot.id;
200
  usedIds.add(bot.id);
201
  matchedCount++;
202
- console.log(`[DEBUG] 🎯 Matched soal "${targetSoal}" with bot ${bot.id}`);
203
  break;
204
  }
205
  }
@@ -211,10 +191,7 @@ async function antibot(data) {
211
  });
212
  }
213
 
214
- console.log(`[DEBUG] After exact match: ${matchedCount} matches`);
215
-
216
  if (matchedCount < soalArray.length) {
217
- console.log('[DEBUG] ===== NORMALIZED MATCHING =====');
218
  for (let i = 0; i < result.length; i++) {
219
  if (!result[i].id) {
220
  const targetSoal = soalArray[i];
@@ -227,7 +204,6 @@ async function antibot(data) {
227
  result[i].matchType = 'normalized';
228
  usedIds.add(bot.id);
229
  matchedCount++;
230
- console.log(`[DEBUG] 🎯 Normalized match: "${targetSoal}" with bot ${bot.id}`);
231
  break;
232
  }
233
  }
@@ -236,10 +212,7 @@ async function antibot(data) {
236
  }
237
  }
238
 
239
- console.log(`[DEBUG] After normalized match: ${matchedCount} matches`);
240
-
241
  if (matchedCount >= 2) {
242
- console.log('[DEBUG] ===== FALLBACK MATCHING =====');
243
  for (let i = 0; i < result.length; i++) {
244
  if (!result[i].id) {
245
  for (const bot of botResults) {
@@ -247,23 +220,19 @@ async function antibot(data) {
247
  result[i].id = bot.id;
248
  result[i].matchType = 'fallback';
249
  usedIds.add(bot.id);
250
- console.log(`[DEBUG] 🔄 Fallback: soal ${i} with bot ${bot.id}`);
251
  break;
252
  }
253
  }
254
  }
255
  }
256
  } else if (matchedCount === 1) {
257
- console.log('[DEBUG] ===== INVALIDATING SINGLE MATCH =====');
258
  for (let i = 0; i < result.length; i++) {
259
  if (!result[i].id) {
260
  result[i].id = 'invalid';
261
  result[i].matchType = 'invalid';
262
- console.log(`[DEBUG] ❌ Marked soal ${i} as invalid`);
263
  }
264
  }
265
  } else {
266
- console.log('[DEBUG] ===== ALL INVALID =====');
267
  for (let i = 0; i < result.length; i++) {
268
  result[i].id = 'invalid';
269
  result[i].matchType = 'invalid';
@@ -274,14 +243,9 @@ async function antibot(data) {
274
  if (!result[i].id) {
275
  result[i].id = 'invalid';
276
  result[i].matchType = 'invalid';
277
- console.log(`[DEBUG] ⚠️ Forced invalid for soal ${i}`);
278
  }
279
  }
280
 
281
- console.log('[DEBUG] ===== FINAL RESULT =====');
282
- console.log(`[DEBUG] Result: ${JSON.stringify(result.map(r => r.id))}`);
283
- console.log(`[DEBUG] Match types: ${JSON.stringify(result.map(r => r.matchType))}`);
284
-
285
  return {
286
  success: true,
287
  data: {
@@ -298,7 +262,6 @@ async function antibot(data) {
298
  };
299
 
300
  } catch (error) {
301
- console.error("[DEBUG] ❌ ANTIBOT ERROR:", error);
302
  return {
303
  success: false,
304
  error: error.message,
@@ -308,8 +271,6 @@ async function antibot(data) {
308
  result: []
309
  }
310
  };
311
- } finally {
312
- console.log('[DEBUG] ===== END ANTIBOT PROCESS =====');
313
  }
314
  }
315
 
 
3
  const { extractTextFromImage } = require('./imageProcessor');
4
 
5
  function mapAnswer(soalArray, jawaban, botIndex) {
 
6
  return jawaban;
7
  }
8
 
9
  function normalizeText(text) {
10
+ return text.toLowerCase().replace(/[^\w\s]/g, '').trim();
 
 
11
  }
12
 
13
  function isValueMatch(value, targetSoal) {
 
 
14
  const numberMap = {
15
  '0': 'zero', '1': 'one', '2': 'two', '3': 'three', '4': 'four',
16
  '5': 'five', '6': 'six', '7': 'seven', '8': 'eight', '9': 'nine', '10': 'ten',
17
  'zero': '0', 'one': '1', 'two': '2', 'three': '3', 'four': '4',
18
  'five': '5', 'six': '6', 'seven': '7', 'eight': '8', 'nine': '9', 'ten': '10',
19
  'I': '1', 'II': '2', 'III': '3', 'IV': '4', 'V': '5',
20
+ 'VI': '6', 'VII': '7', 'VIII': '8', 'IX': '9', 'X': '10',
21
+ 'slx': '6', 's1x': '6', 'six': '6',
22
+ 'f0ur': '4', 'f0r': '4', 'fuor': '4',
23
+ 'f1ve': '5', 'fiv': '5', 'f1v': '5',
24
+ 'e1ght': '8', 'elght': '8', 'eight': '8',
25
+ 'n1ne': '9', 'n1n': '9', 'nne': '9',
26
+ 'se7en': '7', 'sven': '7', 'seven': '7',
27
+ 'thre': '3', 'tree': '3', 'thr33': '3',
28
+ 'tw0': '2', 'to': '2', 'tw': '2',
29
+ '0ne': '1', 'on': '1', 'oen': '1'
30
  };
31
 
32
  const leetMap = {
 
39
  'G': '6', 'g': '6',
40
  'T': '7', 't': '7',
41
  'B': '8', 'b': '8',
42
+ 'Q': '9', 'q': '9',
43
+ 'U': '4', 'u': '4',
44
+ 'R': '2', 'r': '2',
45
+ 'N': '9', 'n': '9',
46
+ 'V': '7', 'v': '7'
47
  };
48
 
49
  const normalizedValue = normalizeText(value);
50
  const normalizedSoal = normalizeText(targetSoal);
51
 
52
  if (normalizedValue === normalizedSoal) {
 
53
  return true;
54
  }
55
 
 
59
 
60
  const leetValue = convertLeet(value);
61
  const leetSoal = convertLeet(targetSoal);
 
 
62
 
63
+ if (leetValue === normalizedSoal) return true;
64
+ if (normalizedValue === leetSoal) return true;
65
+ if (leetValue === leetSoal) return true;
 
 
 
 
 
 
 
 
 
 
 
66
 
67
  const mappedValue = numberMap[normalizedValue] || numberMap[value] || normalizedValue;
68
  const mappedSoal = numberMap[normalizedSoal] || numberMap[targetSoal] || normalizedSoal;
69
 
70
+ if (mappedValue === normalizedSoal) return true;
71
+ if (normalizedValue === mappedSoal) return true;
72
+ if (mappedValue === mappedSoal) return true;
73
 
74
+ const similarity = calculateSimilarity(normalizedValue, normalizedSoal);
75
+ if (similarity >= 0.8) {
 
 
 
 
 
 
 
 
76
  return true;
77
  }
78
 
79
  try {
80
  const valueResult = evaluateSimpleMath(value);
81
  const soalResult = evaluateSimpleMath(targetSoal);
 
82
  if (valueResult !== null && soalResult !== null && valueResult === soalResult) {
 
83
  return true;
84
  }
85
+ } catch (e) {}
 
86
 
 
87
  return false;
88
  }
89
 
90
+ function calculateSimilarity(str1, str2) {
91
+ if (str1 === str2) return 1;
92
+ if (str1.length === 0 || str2.length === 0) return 0;
93
+
94
+ const longer = str1.length > str2.length ? str1 : str2;
95
+ const shorter = str1.length > str2.length ? str2 : str1;
96
+
97
+ if (longer.includes(shorter)) return shorter.length / longer.length;
98
+
99
+ let matches = 0;
100
+ for (let i = 0; i < shorter.length; i++) {
101
+ if (shorter[i] === longer[i]) matches++;
102
+ }
103
+
104
+ return matches / longer.length;
105
+ }
106
+
107
  function evaluateSimpleMath(expression) {
108
  if (!expression) return null;
 
109
  const cleanExpr = expression.toString().replace(/[^\d+\-*/.()]/g, '');
110
  if (!cleanExpr) return null;
 
111
  try {
112
  if (cleanExpr.length > 10) return null;
113
  const result = Function(`"use strict"; return (${cleanExpr})`)();
 
118
  }
119
 
120
  function parseSoalText(text) {
 
 
121
  const delimiters = /[.,:;\\/\s]+/;
122
  let parts = text.split(delimiters).filter(part => part.trim() !== '');
 
123
  if (parts.length === 1) {
124
  parts = text.split(/\s+/).filter(part => part.trim() !== '');
125
  }
 
 
126
  return parts;
127
  }
128
 
129
  async function antibot(data) {
 
 
130
  try {
131
  const { main, bots } = data;
 
132
 
133
  const mainBuffer = Buffer.from(main, 'base64');
134
  const mainText = await extractTextFromImage(mainBuffer);
 
135
 
136
  const soalArray = parseSoalText(mainText.response);
137
 
138
  if (soalArray.length === 0) {
 
139
  throw new Error('Tidak ada soal yang terdeteksi');
140
  }
141
 
 
143
 
144
  for (let i = 0; i < bots.length; i++) {
145
  const bot = bots[i];
 
 
146
  try {
147
  const botBuffer = Buffer.from(bot.img, 'base64');
148
  const botText = await extractTextFromImage(botBuffer);
 
 
149
  const mappedValue = mapAnswer(soalArray, botText.response, i);
150
 
151
  botResults.push({
 
156
  });
157
 
158
  } catch (error) {
 
159
  botResults.push({
160
  id: bot.id,
161
  text: '',
 
166
  }
167
  }
168
 
 
169
  const result = [];
170
  const usedIds = new Set();
171
  let matchedCount = 0;
172
 
 
 
173
  for (let i = 0; i < soalArray.length; i++) {
174
  const targetSoal = soalArray[i];
175
  let foundId = null;
 
180
  foundId = bot.id;
181
  usedIds.add(bot.id);
182
  matchedCount++;
 
183
  break;
184
  }
185
  }
 
191
  });
192
  }
193
 
 
 
194
  if (matchedCount < soalArray.length) {
 
195
  for (let i = 0; i < result.length; i++) {
196
  if (!result[i].id) {
197
  const targetSoal = soalArray[i];
 
204
  result[i].matchType = 'normalized';
205
  usedIds.add(bot.id);
206
  matchedCount++;
 
207
  break;
208
  }
209
  }
 
212
  }
213
  }
214
 
 
 
215
  if (matchedCount >= 2) {
 
216
  for (let i = 0; i < result.length; i++) {
217
  if (!result[i].id) {
218
  for (const bot of botResults) {
 
220
  result[i].id = bot.id;
221
  result[i].matchType = 'fallback';
222
  usedIds.add(bot.id);
 
223
  break;
224
  }
225
  }
226
  }
227
  }
228
  } else if (matchedCount === 1) {
 
229
  for (let i = 0; i < result.length; i++) {
230
  if (!result[i].id) {
231
  result[i].id = 'invalid';
232
  result[i].matchType = 'invalid';
 
233
  }
234
  }
235
  } else {
 
236
  for (let i = 0; i < result.length; i++) {
237
  result[i].id = 'invalid';
238
  result[i].matchType = 'invalid';
 
243
  if (!result[i].id) {
244
  result[i].id = 'invalid';
245
  result[i].matchType = 'invalid';
 
246
  }
247
  }
248
 
 
 
 
 
249
  return {
250
  success: true,
251
  data: {
 
262
  };
263
 
264
  } catch (error) {
 
265
  return {
266
  success: false,
267
  error: error.message,
 
271
  result: []
272
  }
273
  };
 
 
274
  }
275
  }
276