Update endpoints/antibot.js
Browse files- endpoints/antibot.js +90 -67
endpoints/antibot.js
CHANGED
|
@@ -1,89 +1,112 @@
|
|
| 1 |
-
const Tesseract = require(
|
| 2 |
-
const
|
| 3 |
-
const
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4 |
|
| 5 |
function buf(b64) {
|
| 6 |
-
|
| 7 |
-
if (b64.startsWith("data:image")) b64 = b64.replace(/^data:image\/\w+;base64,/, "");
|
| 8 |
-
return Buffer.from(b64, "base64");
|
| 9 |
}
|
| 10 |
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 26 |
}
|
| 27 |
-
return
|
| 28 |
}
|
| 29 |
|
| 30 |
-
function
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 35 |
}
|
| 36 |
|
| 37 |
-
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
.
|
| 42 |
-
.
|
| 43 |
-
|
| 44 |
-
.resize({ w: 400 });
|
| 45 |
|
| 46 |
-
|
| 47 |
-
|
|
|
|
| 48 |
|
| 49 |
-
|
| 50 |
-
|
| 51 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 52 |
|
| 53 |
-
|
| 54 |
-
|
| 55 |
-
|
| 56 |
-
|
| 57 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 58 |
|
| 59 |
-
|
| 60 |
-
|
|
|
|
|
|
|
| 61 |
}
|
| 62 |
|
| 63 |
module.exports = async function (data) {
|
| 64 |
-
const mainText = await
|
| 65 |
-
const
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 66 |
|
| 67 |
const botResults = [];
|
| 68 |
-
for (let
|
| 69 |
-
const
|
| 70 |
-
const
|
| 71 |
-
|
|
|
|
| 72 |
}
|
| 73 |
|
| 74 |
-
const
|
| 75 |
-
|
| 76 |
-
|
| 77 |
-
|
| 78 |
-
const score = similarity(word, bot.text);
|
| 79 |
-
if (score > bestMatch.score) bestMatch = { id: bot.id, score };
|
| 80 |
-
}
|
| 81 |
-
order.push(bestMatch.score > 0.5 ? bestMatch.id : null);
|
| 82 |
-
}
|
| 83 |
|
| 84 |
-
return {
|
| 85 |
-
soal: mainWords,
|
| 86 |
-
botResults,
|
| 87 |
-
order: order.filter(id => id !== null)
|
| 88 |
-
};
|
| 89 |
};
|
|
|
|
| 1 |
+
const Tesseract = require("tesseract.js");
|
| 2 |
+
const fs = require("fs");
|
| 3 |
+
const path = require("path");
|
| 4 |
+
|
| 5 |
+
async function loadJimp() {
|
| 6 |
+
const jimp = await import("jimp");
|
| 7 |
+
return jimp.default;
|
| 8 |
+
}
|
| 9 |
|
| 10 |
function buf(b64) {
|
| 11 |
+
return Buffer.from(b64.replace(/^data:image\/\w+;base64,/, ""), "base64");
|
|
|
|
|
|
|
| 12 |
}
|
| 13 |
|
| 14 |
+
const SMALL = {
|
| 15 |
+
zero:0, one:1, two:2, three:3, four:4,
|
| 16 |
+
five:5, six:6, seven:7, eight:8, nine:9,
|
| 17 |
+
ten:10, eleven:11, twelve:12, thirteen:13, fourteen:14,
|
| 18 |
+
fifteen:15, sixteen:16, seventeen:17, eighteen:18, nineteen:19
|
| 19 |
+
};
|
| 20 |
+
|
| 21 |
+
const TENS = {
|
| 22 |
+
twenty:20, thirty:30, forty:40, fifty:50,
|
| 23 |
+
sixty:60, seventy:70, eighty:80, ninety:90
|
| 24 |
+
};
|
| 25 |
+
|
| 26 |
+
function wordsToNumber(words) {
|
| 27 |
+
let total = 0, current = 0;
|
| 28 |
+
for (let w of words) {
|
| 29 |
+
if (SMALL[w] !== undefined) current += SMALL[w];
|
| 30 |
+
else if (TENS[w] !== undefined) current += TENS[w];
|
| 31 |
+
else if (w === "hundred") current *= 100;
|
| 32 |
+
else if (w === "thousand") { total += current * 1000; current = 0; }
|
| 33 |
+
else if (w === "million") { total += current * 1000000; current = 0; }
|
| 34 |
}
|
| 35 |
+
return total + current;
|
| 36 |
}
|
| 37 |
|
| 38 |
+
function solveMath(tokens) {
|
| 39 |
+
const expr = tokens.join(" ")
|
| 40 |
+
.replace(/x/g, "*")
|
| 41 |
+
.replace(/times/g, "*")
|
| 42 |
+
.replace(/plus/g, "+")
|
| 43 |
+
.replace(/minus/g, "-")
|
| 44 |
+
.replace(/divide/g, "/")
|
| 45 |
+
.replace(/divided/g, "/");
|
| 46 |
+
|
| 47 |
+
try { return Function("return " + expr)(); }
|
| 48 |
+
catch { return null; }
|
| 49 |
}
|
| 50 |
|
| 51 |
+
function normalizeWords(t) {
|
| 52 |
+
return t.replace(/[^a-z0-9 ]/g, " ")
|
| 53 |
+
.replace(/\s+/g, " ")
|
| 54 |
+
.trim()
|
| 55 |
+
.split(" ")
|
| 56 |
+
.filter(Boolean);
|
| 57 |
+
}
|
|
|
|
| 58 |
|
| 59 |
+
function convertSmart(tokens) {
|
| 60 |
+
if (tokens.every(x => /^[0-9]+$/.test(x)))
|
| 61 |
+
return parseInt(tokens.join(""));
|
| 62 |
|
| 63 |
+
if (tokens.every(x =>
|
| 64 |
+
SMALL[x] !== undefined ||
|
| 65 |
+
TENS[x] !== undefined ||
|
| 66 |
+
x === "hundred" ||
|
| 67 |
+
x === "thousand" ||
|
| 68 |
+
x === "million"
|
| 69 |
+
)) return wordsToNumber(tokens);
|
| 70 |
|
| 71 |
+
return solveMath(tokens);
|
| 72 |
+
}
|
| 73 |
+
|
| 74 |
+
async function readTextFromBase64(b64) {
|
| 75 |
+
const Jimp = await loadJimp();
|
| 76 |
+
const img = await Jimp.read(buf(b64));
|
| 77 |
+
|
| 78 |
+
img.greyscale().contrast(0.7).normalize().resize(500, Jimp.AUTO);
|
| 79 |
+
|
| 80 |
+
const tmp = path.join(__dirname, "tmp_" + Date.now() + ".png");
|
| 81 |
+
await img.write(tmp);
|
| 82 |
|
| 83 |
+
const res = await Tesseract.recognize(tmp, "eng", { logger: () => {} });
|
| 84 |
+
fs.unlinkSync(tmp);
|
| 85 |
+
|
| 86 |
+
return res.data.text.toLowerCase().replace(/[^a-z0-9 ]/g, " ").trim();
|
| 87 |
}
|
| 88 |
|
| 89 |
module.exports = async function (data) {
|
| 90 |
+
const mainText = await readTextFromBase64(data.main);
|
| 91 |
+
const tokens = normalizeWords(mainText);
|
| 92 |
+
const orderVal = convertSmart(tokens);
|
| 93 |
+
|
| 94 |
+
let orderNumbers = [];
|
| 95 |
+
if (typeof orderVal === "number" && !Number.isNaN(orderVal))
|
| 96 |
+
orderNumbers = [orderVal];
|
| 97 |
|
| 98 |
const botResults = [];
|
| 99 |
+
for (let b of data.bots) {
|
| 100 |
+
const raw = await readTextFromBase64(b.img);
|
| 101 |
+
const t = normalizeWords(raw);
|
| 102 |
+
const val = convertSmart(t);
|
| 103 |
+
botResults.push({ id: b.id, number: Number.isNaN(val) ? null : val });
|
| 104 |
}
|
| 105 |
|
| 106 |
+
const finalOrder = orderNumbers.map(n => {
|
| 107 |
+
const f = botResults.find(x => x.number === n);
|
| 108 |
+
return f ? f.id : null;
|
| 109 |
+
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 110 |
|
| 111 |
+
return { tokens, orderNumbers, botResults, result: finalOrder };
|
|
|
|
|
|
|
|
|
|
|
|
|
| 112 |
};
|