Forgets commited on
Commit
37632c8
Β·
verified Β·
1 Parent(s): 055607b

Update endpoints/antibot.js

Browse files
Files changed (1) hide show
  1. endpoints/antibot.js +42 -142
endpoints/antibot.js CHANGED
@@ -4,17 +4,19 @@ const { extractTextFromImage, uploadImageToHosting } = require('./imageProcessor
4
 
5
  async function extractTextFromBuffer(imageBuffer) {
6
  try {
7
- console.log('πŸ–ΌοΈ DEBUG extractTextFromBuffer: Membuat file temporary');
8
- const tempPath = path.join(__dirname, `temp_${Date.now()}.jpg`);
9
- fs.writeFileSync(tempPath, imageBuffer);
10
- console.log('πŸ“ DEBUG: File temporary dibuat:', tempPath);
11
-
12
- const result = await extractTextFromImage(tempPath);
 
 
 
 
 
 
13
  console.log('βœ… DEBUG extractTextFromBuffer: Hasil ekstraksi:', result);
14
-
15
- fs.unlinkSync(tempPath);
16
- console.log('🧹 DEBUG: File temporary dihapus');
17
-
18
  return result;
19
  } catch (error) {
20
  console.error('❌ DEBUG extractTextFromBuffer Error:', error.message);
@@ -35,42 +37,22 @@ function normalizeText(text) {
35
 
36
  function isValueMatch(value, targetSoal) {
37
  console.log(`πŸ” DEBUG isValueMatch: Value="${value}", Soal="${targetSoal}"`);
38
-
39
  const numberMap = {
40
- '0': 'zero', '1': 'one', '2': 'two', '3': 'three', '4': 'four',
41
- '5': 'five', '6': 'six', '7': 'seven', '8': 'eight', '9': 'nine', '10': 'ten',
42
- 'zero': '0', 'one': '1', 'two': '2', 'three': '3', 'four': '4',
43
- 'five': '5', 'six': '6', 'seven': '7', 'eight': '8', 'nine': '9', 'ten': '10',
44
- 'I': '1', 'II': '2', 'III': '3', 'IV': '4', 'V': '5',
45
- 'VI': '6', 'VII': '7', 'VIII': '8', 'IX': '9', 'X': '10',
46
- 'i': '1', 'ii': '2', 'iii': '3', 'iv': '4', 'v': '5',
47
- 'vi': '6', 'vii': '7', 'viii': '8', 'ix': '9', 'x': '10',
48
- 'slx': '6', 's1x': '6', 'six': '6',
49
- 'f0ur': '4', 'f0r': '4', 'fuor': '4',
50
- 'f1ve': '5', 'fiv': '5', 'f1v': '5',
51
- 'e1ght': '8', 'elght': '8', 'eight': '8',
52
- 'n1ne': '9', 'n1n': '9', 'nne': '9',
53
- 'se7en': '7', 'sven': '7', 'seven': '7',
54
- 'thre': '3', 'tree': '3', 'thr33': '3',
55
- 'tw0': '2', 'to': '2', 'tw': '2',
56
- '0ne': '1', 'on': '1', 'oen': '1'
57
  };
58
 
59
  const leetMap = {
60
- 'O': '0', 'o': '0',
61
- 'I': '1', 'i': '1', 'l': '1',
62
- 'Z': '2', 'z': '2',
63
- 'E': '3', 'e': '3',
64
- 'A': '4', 'a': '4',
65
- 'S': '5', 's': '5',
66
- 'G': '6', 'g': '6',
67
- 'T': '7', 't': '7',
68
- 'B': '8', 'b': '8',
69
- 'Q': '9', 'q': '9',
70
- 'U': '4', 'u': '4',
71
- 'R': '2', 'r': '2',
72
- 'N': '9', 'n': '9',
73
- 'V': '7', 'v': '7'
74
  };
75
 
76
  const normalizedValue = normalizeText(value);
@@ -81,43 +63,22 @@ function isValueMatch(value, targetSoal) {
81
  return true;
82
  }
83
 
84
- const convertLeet = (text) => {
85
- return text.split('').map(char => leetMap[char] || char).join('');
86
- };
87
-
88
  const leetValue = convertLeet(value);
89
  const leetSoal = convertLeet(targetSoal);
90
-
91
  console.log(`πŸ”’ DEBUG Leet: Value="${leetValue}", Soal="${leetSoal}"`);
92
 
93
- if (leetValue === normalizedSoal) {
94
- console.log('βœ… DEBUG: Match leet value -> normalized soal');
95
- return true;
96
- }
97
- if (normalizedValue === leetSoal) {
98
- console.log('βœ… DEBUG: Match normalized value -> leet soal');
99
- return true;
100
- }
101
- if (leetValue === leetSoal) {
102
- console.log('βœ… DEBUG: Match leet value -> leet soal');
103
  return true;
104
  }
105
 
106
  const mappedValue = numberMap[normalizedValue] || numberMap[value] || normalizedValue;
107
  const mappedSoal = numberMap[normalizedSoal] || numberMap[targetSoal] || normalizedSoal;
108
-
109
  console.log(`πŸ”„ DEBUG Number Map: Value="${mappedValue}", Soal="${mappedSoal}"`);
110
 
111
- if (mappedValue === normalizedSoal) {
112
- console.log('βœ… DEBUG: Match mapped value -> normalized soal');
113
- return true;
114
- }
115
- if (normalizedValue === mappedSoal) {
116
- console.log('βœ… DEBUG: Match normalized value -> mapped soal');
117
- return true;
118
- }
119
- if (mappedValue === mappedSoal) {
120
- console.log('βœ… DEBUG: Match mapped value -> mapped soal');
121
  return true;
122
  }
123
 
@@ -147,17 +108,13 @@ function isValueMatch(value, targetSoal) {
147
  function calculateSimilarity(str1, str2) {
148
  if (str1 === str2) return 1;
149
  if (str1.length === 0 || str2.length === 0) return 0;
150
-
151
  const longer = str1.length > str2.length ? str1 : str2;
152
  const shorter = str1.length > str2.length ? str2 : str1;
153
-
154
  if (longer.includes(shorter)) return shorter.length / longer.length;
155
-
156
  let matches = 0;
157
  for (let i = 0; i < shorter.length; i++) {
158
  if (shorter[i] === longer[i]) matches++;
159
  }
160
-
161
  return matches / longer.length;
162
  }
163
 
@@ -176,30 +133,24 @@ function evaluateSimpleMath(expression) {
176
 
177
  function parseSoalText(text) {
178
  console.log(`πŸ“ DEBUG parseSoalText: Input text: "${text}"`);
179
-
180
  const ignoreWords = [
181
- 'hi', 'how', 'are', 'you', 'hello', 'hey',
182
- 'tentu', 'berikut', 'adalah', 'teks', 'dari', 'gambar',
183
- 'dipisahkan', 'sesuai', 'permintaan', 'anda', 'hanya',
184
- 'berikan', 'jangan', 'tambahkan', 'kata', 'apapun', 'seperti',
185
- 'atau', 'penjelasan', 'lain', 'saja'
186
  ];
187
-
188
- const delimiters = /[.,:;\\/\s]+/;
189
  let parts = text.split(delimiters)
190
  .filter(part => part.trim() !== '')
191
  .filter(part => !ignoreWords.includes(part.toLowerCase()));
192
-
193
  if (parts.length === 0) {
194
  parts = text.split(/\s+/)
195
  .filter(part => part.trim() !== '')
196
  .filter(part => !ignoreWords.includes(part.toLowerCase()));
197
  }
198
-
199
  parts = parts.filter(part => part.length <= 3 || !isNaN(part));
200
-
201
  parts = parts.slice(0, 3);
202
-
203
  console.log(`πŸ“ DEBUG parseSoalText: Filtered parts (max 3):`, parts);
204
  return parts;
205
  }
@@ -207,30 +158,24 @@ function parseSoalText(text) {
207
  async function antibot(data) {
208
  console.log('πŸš€ DEBUG antibot: Memulai proses antibot');
209
  console.log('πŸ“Š DEBUG: Data received - main:', data.main ? 'βœ…' : '❌', 'bots:', data.bots?.length || 0);
210
-
211
  try {
212
  const { main, bots } = data;
213
-
214
  console.log('πŸ–ΌοΈ DEBUG: Processing main image...');
215
  const mainBuffer = Buffer.from(main, 'base64');
216
  const mainText = await extractTextFromBuffer(mainBuffer);
217
-
218
  console.log('πŸ“„ DEBUG Main Text Result:', mainText);
219
-
220
  if (!mainText.status) {
221
  throw new Error('Gagal mengekstrak teks dari gambar utama: ' + mainText.response);
222
  }
223
 
224
  const soalArray = parseSoalText(mainText.response);
225
  console.log(`πŸ“‹ DEBUG: Soal array:`, soalArray);
226
-
227
  if (soalArray.length === 0) {
228
  throw new Error('Tidak ada soal yang terdeteksi');
229
  }
230
 
231
  const botResults = [];
232
  console.log(`πŸ€– DEBUG: Processing ${bots.length} bots...`);
233
-
234
  for (let i = 0; i < bots.length; i++) {
235
  const bot = bots[i];
236
  console.log(`πŸ€– DEBUG: Processing bot ${i+1}/${bots.length} - ID: ${bot.id}`);
@@ -238,29 +183,11 @@ async function antibot(data) {
238
  const botBuffer = Buffer.from(bot.img, 'base64');
239
  const botText = await extractTextFromBuffer(botBuffer);
240
  const mappedValue = mapAnswer(soalArray, botText.response, i);
241
-
242
- botResults.push({
243
- id: bot.id,
244
- text: botText.response,
245
- value: mappedValue,
246
- normalized: normalizeText(botText.response)
247
- });
248
-
249
- console.log(`βœ… DEBUG Bot ${bot.id}:`, {
250
- text: botText.response,
251
- value: mappedValue,
252
- normalized: normalizeText(botText.response)
253
- });
254
-
255
  } catch (error) {
256
  console.error(`❌ DEBUG Bot ${bot.id} Error:`, error.message);
257
- botResults.push({
258
- id: bot.id,
259
- text: '',
260
- value: '',
261
- normalized: '',
262
- error: error.message
263
- });
264
  }
265
  }
266
 
@@ -269,13 +196,10 @@ async function antibot(data) {
269
  const usedIds = new Set();
270
  let successfulMatches = 0;
271
 
272
- // Step 1: Match setiap bot dengan soal yang tersedia
273
  const availableSoal = [...soalArray];
274
-
275
  for (const bot of botResults) {
276
  let matchedSoal = null;
277
  let matchIndex = -1;
278
-
279
  if (bot.value && bot.value.trim() !== '') {
280
  for (let i = 0; i < availableSoal.length; i++) {
281
  if (isValueMatch(bot.value, availableSoal[i])) {
@@ -287,27 +211,17 @@ async function antibot(data) {
287
  }
288
  }
289
  }
290
-
291
  if (matchedSoal) {
292
- result.push({
293
- id: bot.id,
294
- soal: matchedSoal,
295
- matchType: 'exact'
296
- });
297
  availableSoal.splice(matchIndex, 1);
298
  usedIds.add(bot.id);
299
  } else {
300
- result.push({
301
- id: null,
302
- soal: '',
303
- matchType: 'none'
304
- });
305
  }
306
  }
307
 
308
  console.log(`πŸ“Š DEBUG: Successful matches: ${successfulMatches}`);
309
 
310
- // Step 2: Jika minimal 2 match, isi bot yang belum match dengan soal tersisa
311
  if (successfulMatches >= 2) {
312
  console.log('βœ… DEBUG: Minimal 2 match terpenuhi, mengisi bot yang belum match');
313
  for (let i = 0; i < result.length; i++) {
@@ -321,7 +235,6 @@ async function antibot(data) {
321
  }
322
  }
323
 
324
- // Step 3: Handle remaining cases
325
  for (let i = 0; i < result.length; i++) {
326
  if (!result[i].id) {
327
  if (successfulMatches >= 2) {
@@ -346,28 +259,15 @@ async function antibot(data) {
346
  result: result.map(r => ({ id: r.id })),
347
  debug: {
348
  parsedSoal: soalArray,
349
- matches: result.map(r => ({
350
- id: r.id,
351
- matchType: r.matchType,
352
- soal: r.soal
353
- })),
354
  totalResults: result.length,
355
  successfulMatches: successfulMatches
356
  }
357
  }
358
  };
359
-
360
  } catch (error) {
361
  console.error('πŸ’₯ DEBUG antibot Error:', error.message);
362
- return {
363
- success: false,
364
- error: error.message,
365
- data: {
366
- soal: [],
367
- botResults: [],
368
- result: []
369
- }
370
- };
371
  }
372
  }
373
 
 
4
 
5
  async function extractTextFromBuffer(imageBuffer) {
6
  try {
7
+ if (!imageBuffer) {
8
+ throw new Error('No image buffer provided');
9
+ }
10
+ if (!Buffer.isBuffer(imageBuffer)) {
11
+ throw new Error('extractTextFromBuffer expects a Buffer');
12
+ }
13
+
14
+ console.log('πŸ–ΌοΈ DEBUG extractTextFromBuffer: Received buffer, size:', imageBuffer.length, 'bytes');
15
+
16
+ // Kirim buffer langsung ke extractTextFromImage (tidak perlu membuat file temporary)
17
+ const result = await extractTextFromImage(imageBuffer);
18
+
19
  console.log('βœ… DEBUG extractTextFromBuffer: Hasil ekstraksi:', result);
 
 
 
 
20
  return result;
21
  } catch (error) {
22
  console.error('❌ DEBUG extractTextFromBuffer Error:', error.message);
 
37
 
38
  function isValueMatch(value, targetSoal) {
39
  console.log(`πŸ” DEBUG isValueMatch: Value="${value}", Soal="${targetSoal}"`);
 
40
  const numberMap = {
41
+ '0': 'zero', '1': 'one', '2': 'two', '3': 'three', '4': 'four', '5': 'five',
42
+ '6': 'six', '7': 'seven', '8': 'eight', '9': 'nine', '10': 'ten',
43
+ 'zero': '0', 'one': '1', 'two': '2', 'three': '3', 'four': '4', 'five': '5',
44
+ 'six': '6', 'seven': '7', 'eight': '8', 'nine': '9', 'ten': '10',
45
+ 'I': '1','II': '2','III': '3','IV': '4','V': '5','VI': '6','VII': '7','VIII': '8','IX': '9','X': '10',
46
+ 'i': '1','ii': '2','iii': '3','iv': '4','v': '5','vi': '6','vii': '7','viii': '8','ix': '9','x': '10',
47
+ 'slx': '6','s1x': '6','six': '6','f0ur': '4','f0r': '4','fuor': '4','f1ve': '5','fiv': '5','f1v': '5',
48
+ 'e1ght': '8','elght': '8','eight': '8','n1ne': '9','n1n': '9','nne': '9','se7en': '7','sven': '7','seven': '7',
49
+ 'thre': '3','tree': '3','thr33': '3','tw0': '2','to': '2','tw': '2','0ne': '1','on': '1','oen': '1'
 
 
 
 
 
 
 
 
50
  };
51
 
52
  const leetMap = {
53
+ 'O': '0','o': '0','I': '1','i': '1','l': '1','Z': '2','z': '2','E': '3','e': '3',
54
+ 'A': '4','a': '4','S': '5','s': '5','G': '6','g': '6','T': '7','t': '7','B': '8','b': '8',
55
+ 'Q': '9','q': '9','U': '4','u': '4','R': '2','r': '2','N': '9','n': '9','V': '7','v': '7'
 
 
 
 
 
 
 
 
 
 
 
56
  };
57
 
58
  const normalizedValue = normalizeText(value);
 
63
  return true;
64
  }
65
 
66
+ const convertLeet = (text) => text.split('').map(char => leetMap[char] || char).join('');
 
 
 
67
  const leetValue = convertLeet(value);
68
  const leetSoal = convertLeet(targetSoal);
 
69
  console.log(`πŸ”’ DEBUG Leet: Value="${leetValue}", Soal="${leetSoal}"`);
70
 
71
+ if (leetValue === normalizedSoal || normalizedValue === leetSoal || leetValue === leetSoal) {
72
+ console.log('βœ… DEBUG: Match leet/normalized combination');
 
 
 
 
 
 
 
 
73
  return true;
74
  }
75
 
76
  const mappedValue = numberMap[normalizedValue] || numberMap[value] || normalizedValue;
77
  const mappedSoal = numberMap[normalizedSoal] || numberMap[targetSoal] || normalizedSoal;
 
78
  console.log(`πŸ”„ DEBUG Number Map: Value="${mappedValue}", Soal="${mappedSoal}"`);
79
 
80
+ if (mappedValue === normalizedSoal || normalizedValue === mappedSoal || mappedValue === mappedSoal) {
81
+ console.log('βœ… DEBUG: Match mapped combinations');
 
 
 
 
 
 
 
 
82
  return true;
83
  }
84
 
 
108
  function calculateSimilarity(str1, str2) {
109
  if (str1 === str2) return 1;
110
  if (str1.length === 0 || str2.length === 0) return 0;
 
111
  const longer = str1.length > str2.length ? str1 : str2;
112
  const shorter = str1.length > str2.length ? str2 : str1;
 
113
  if (longer.includes(shorter)) return shorter.length / longer.length;
 
114
  let matches = 0;
115
  for (let i = 0; i < shorter.length; i++) {
116
  if (shorter[i] === longer[i]) matches++;
117
  }
 
118
  return matches / longer.length;
119
  }
120
 
 
133
 
134
  function parseSoalText(text) {
135
  console.log(`πŸ“ DEBUG parseSoalText: Input text: "${text}"`);
 
136
  const ignoreWords = [
137
+ 'hi','how','are','you','hello','hey','tentu','berikut','adalah','teks','dari','gambar',
138
+ 'dipisahkan','sesuai','permintaan','anda','hanya','berikan','jangan','tambahkan',
139
+ 'kata','apapun','seperti','atau','penjelasan','lain','saja'
 
 
140
  ];
141
+ const delimiters = /[.,:;\\/\\s]+/;
 
142
  let parts = text.split(delimiters)
143
  .filter(part => part.trim() !== '')
144
  .filter(part => !ignoreWords.includes(part.toLowerCase()));
145
+
146
  if (parts.length === 0) {
147
  parts = text.split(/\s+/)
148
  .filter(part => part.trim() !== '')
149
  .filter(part => !ignoreWords.includes(part.toLowerCase()));
150
  }
151
+
152
  parts = parts.filter(part => part.length <= 3 || !isNaN(part));
 
153
  parts = parts.slice(0, 3);
 
154
  console.log(`πŸ“ DEBUG parseSoalText: Filtered parts (max 3):`, parts);
155
  return parts;
156
  }
 
158
  async function antibot(data) {
159
  console.log('πŸš€ DEBUG antibot: Memulai proses antibot');
160
  console.log('πŸ“Š DEBUG: Data received - main:', data.main ? 'βœ…' : '❌', 'bots:', data.bots?.length || 0);
 
161
  try {
162
  const { main, bots } = data;
 
163
  console.log('πŸ–ΌοΈ DEBUG: Processing main image...');
164
  const mainBuffer = Buffer.from(main, 'base64');
165
  const mainText = await extractTextFromBuffer(mainBuffer);
 
166
  console.log('πŸ“„ DEBUG Main Text Result:', mainText);
 
167
  if (!mainText.status) {
168
  throw new Error('Gagal mengekstrak teks dari gambar utama: ' + mainText.response);
169
  }
170
 
171
  const soalArray = parseSoalText(mainText.response);
172
  console.log(`πŸ“‹ DEBUG: Soal array:`, soalArray);
 
173
  if (soalArray.length === 0) {
174
  throw new Error('Tidak ada soal yang terdeteksi');
175
  }
176
 
177
  const botResults = [];
178
  console.log(`πŸ€– DEBUG: Processing ${bots.length} bots...`);
 
179
  for (let i = 0; i < bots.length; i++) {
180
  const bot = bots[i];
181
  console.log(`πŸ€– DEBUG: Processing bot ${i+1}/${bots.length} - ID: ${bot.id}`);
 
183
  const botBuffer = Buffer.from(bot.img, 'base64');
184
  const botText = await extractTextFromBuffer(botBuffer);
185
  const mappedValue = mapAnswer(soalArray, botText.response, i);
186
+ botResults.push({ id: bot.id, text: botText.response, value: mappedValue, normalized: normalizeText(botText.response) });
187
+ console.log(`βœ… DEBUG Bot ${bot.id}:`, { text: botText.response, value: mappedValue, normalized: normalizeText(botText.response) });
 
 
 
 
 
 
 
 
 
 
 
 
188
  } catch (error) {
189
  console.error(`❌ DEBUG Bot ${bot.id} Error:`, error.message);
190
+ botResults.push({ id: bot.id, text: '', value: '', normalized: '', error: error.message });
 
 
 
 
 
 
191
  }
192
  }
193
 
 
196
  const usedIds = new Set();
197
  let successfulMatches = 0;
198
 
 
199
  const availableSoal = [...soalArray];
 
200
  for (const bot of botResults) {
201
  let matchedSoal = null;
202
  let matchIndex = -1;
 
203
  if (bot.value && bot.value.trim() !== '') {
204
  for (let i = 0; i < availableSoal.length; i++) {
205
  if (isValueMatch(bot.value, availableSoal[i])) {
 
211
  }
212
  }
213
  }
 
214
  if (matchedSoal) {
215
+ result.push({ id: bot.id, soal: matchedSoal, matchType: 'exact' });
 
 
 
 
216
  availableSoal.splice(matchIndex, 1);
217
  usedIds.add(bot.id);
218
  } else {
219
+ result.push({ id: null, soal: '', matchType: 'none' });
 
 
 
 
220
  }
221
  }
222
 
223
  console.log(`πŸ“Š DEBUG: Successful matches: ${successfulMatches}`);
224
 
 
225
  if (successfulMatches >= 2) {
226
  console.log('βœ… DEBUG: Minimal 2 match terpenuhi, mengisi bot yang belum match');
227
  for (let i = 0; i < result.length; i++) {
 
235
  }
236
  }
237
 
 
238
  for (let i = 0; i < result.length; i++) {
239
  if (!result[i].id) {
240
  if (successfulMatches >= 2) {
 
259
  result: result.map(r => ({ id: r.id })),
260
  debug: {
261
  parsedSoal: soalArray,
262
+ matches: result.map(r => ({ id: r.id, matchType: r.matchType, soal: r.soal })),
 
 
 
 
263
  totalResults: result.length,
264
  successfulMatches: successfulMatches
265
  }
266
  }
267
  };
 
268
  } catch (error) {
269
  console.error('πŸ’₯ DEBUG antibot Error:', error.message);
270
+ return { success: false, error: error.message, data: { soal: [], botResults: [], result: [] } };
 
 
 
 
 
 
 
 
271
  }
272
  }
273