0% found this document useful (0 votes)
341 views

Ab Link

This userscript uses optical character recognition (OCR) to solve AbLink images with words or numbers. It implements preprocessing techniques like noise removal, thresholding pixel values, and image splitting. The script is still being developed to improve accuracy for different image types and fonts, and to add number recognition capabilities.
Copyright
© © All Rights Reserved
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
341 views

Ab Link

This userscript uses optical character recognition (OCR) to solve AbLink images with words or numbers. It implements preprocessing techniques like noise removal, thresholding pixel values, and image splitting. The script is still being developed to improve accuracy for different image types and fonts, and to add number recognition capabilities.
Copyright
© © All Rights Reserved
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 28

// ==UserScript==

// @name AB Links Solver


// @namespace ABLinks Solver(Solves Ablinks images)
// @version 3.1
// @description Solves AbLink images
// @author engageub
// @match *://*/*
// @noframes
// @connect https://unpkg.com
// @require https://unpkg.com/[email protected]/opencv.js
// @require https://unpkg.com/[email protected]/browser/lib/jimp.min.js
// @require https://unpkg.com/[email protected]/dist/tesseract.min.js
// @grant GM_xmlhttpRequest
// @antifeature referral-link
// ==/UserScript==

// This script solves Ablink images with words and having 3 or 4 different options
// Number identification logic for comparing words and numbers will be implemented
in the next versions
// Accuracy can be improved by adding more filters for different types of images
and fonts
// This script does not have a global matcher, you will need to add the websites in
the matcher section manually, till
// all the solutions are implemented
// Your account will be locked for 24 hours, if 3 incorrect solutions are provided
consecutively in 10 minutes. (This is the default but depends on website)
// To avoid this add a rotator to change the website whenever an incorrect solution
is provided.

// TODO: Refactor Code


(function() {
'use strict';

var questions = [];


var questionImages = [];
var questionImage = "";
var questionImageSource = "";
var numericWordArray = ["zero", "one", "two", "three", "four", "five", "six",
"seven", "eight", "nine", "ten"];

async function waitForImage(imgElement) {


return await new Promise(res => {
if (imgElement.complete) {
return res();
}
imgElement.onload = () => res();
imgElement.onerror = () => res();
});
}

async function toDataURL(c){


return await new Promise(function(resolve){
const dataURI = c.toDataURL('image/png');
return resolve(dataURI);
})

async function removeNoiseUsingImageData(imgdata,width,height,threshold){


return await new Promise(function(resolve){
var noiseCount =0;
var noiseRowStart = 0;
for (let column = 0; column < width; column++) {
let count = 0;
for (let row = 0; row < height; row++) {

let position = row * width + column;


let pixelAtPosition = imgdata[position];

//Remove noise from first row and last row


if(row == 0 || row == height-1){
imgdata[position] = 0xFFFFFFFF;
}

if (pixelAtPosition == 0xFF000000){
if(noiseCount == 0){
noiseRowStart = row;
}
noiseCount++;
}else{
//Define the number of consecutive pixels to be considered
as noise
if(noiseCount > 0 && noiseCount <= threshold){
//Start from noiseRow till current row and remove noise
while(noiseRowStart < row){
let noisePosition = noiseRowStart * width + column;
imgdata[noisePosition] = 0xFFFFFFFF;
noiseRowStart++;
}
}
noiseCount =0;
}
}
}
return resolve(imgdata);
})

async function imageUsingOCRAntibotQuestion(image) {

if (!image || !image.src) {
console.log("No images found");
return;
}

var img = new Image();


img.crossOrigin = 'anonymous';
img.src = image.src
await waitForImage(img);
var c = document.createElement("canvas")
c.width = img.width;
c.height = img.height;
var ctx = c.getContext("2d");
await ctx.drawImage(img, 0, 0);

var imageData = await ctx.getImageData(0, 0, c.width, c.height);


var data = await imageData.data;
// console.log(data);

await ctx.putImageData(imageData, 0, 0);

let src = await cv.imread(c);


let dst = new cv.Mat();
let ksize = new cv.Size(3, 3);
// You can try more different parameters
await cv.GaussianBlur(src, dst, ksize, 0, 0, cv.BORDER_DEFAULT);

await cv.imshow(c, dst);


src.delete();
dst.delete();

//console.log( c.toDataURL());
let imageDataURI = await toDataURL(c);
return await (imageUsingOCR(imageDataURI));
}

async function imageUsingOCRAntibotLowValues(image) {

if (!image || !image.src) {
console.log("No images found");
return;
}

var img = new Image();


img.crossOrigin = 'anonymous';
img.src = image.src;
await waitForImage(img);

var c = document.createElement("canvas")
c.width = img.width;
c.height = img.height;
var ctx = c.getContext("2d");
await ctx.drawImage(img, 0, 0);
//console.log(await c.toDataURL());
var imageData = await ctx.getImageData(0, 0, c.width, c.height);
var data = await imageData.data;

//Make the image visible


for (let i = 0; i < data.length; i += 4) {

if ((data[i] < 100 || data[i + 1] < 100 || data[i + 2] < 100) &&
data[i+3]>0) {
data[i] = 0;
data[i + 1] = 0;
data[i + 2] = 0;
} else {
data[i] = 255;
data[i + 1] = 255;
data[i + 2] = 255;
}
data[i + 3] = 255;
}

//Remove Noise from Image


var imgdata = await new Uint32Array(data.buffer);
imgdata = await removeNoiseUsingImageData(imgdata,c.width,c.height,1);

await ctx.putImageData(imageData, 0, 0);

//console.log( c.toDataURL());
let imageDataURI = await toDataURL(c);
return await (imageUsingOCR(imageDataURI));
}

async function imageUsingOCRAntibotHighValues(image) {

if (!image || !image.src) {
console.log("No images found");
return;
}

var img = new Image();


img.crossOrigin = 'anonymous';
img.src = image.src;
await waitForImage(img);

var c = document.createElement("canvas")
c.width = img.width;
c.height = img.height;
var ctx = c.getContext("2d");
await ctx.drawImage(img, 0, 0);
//console.log(await c.toDataURL());
var imageData = await ctx.getImageData(0, 0, c.width, c.height);
var data = await imageData.data;

//Make the image visible


for (let i = 0; i < data.length; i += 4) {

if ((data[i] > 100 || data[i + 1] > 100 || data[i + 2] > 100) && data[i
+ 3] > 0) {
data[i] = 0;
data[i + 1] = 0;
data[i + 2] = 0;

} else {

data[i] = 255;
data[i + 1] = 255;
data[i + 2] = 255;
}
data[i + 3] = 255;
}

//Remove Noise from Image


var imgdata = await new Uint32Array(data.buffer);

imgdata = await removeNoiseUsingImageData(imgdata,c.width,c.height,1);

await ctx.putImageData(imageData, 0, 0);


//console.log( c.toDataURL());
let imageDataURI = await toDataURL(c);
return await (imageUsingOCR(imageDataURI));
}
async function splitImageUsingOCRAntibotLowValues(questionImageSource,
answerImagesLength) {

var img = new Image();


img.crossOrigin = 'anonymous';
img.src = questionImageSource;
await waitForImage(img);

var c = document.createElement("canvas")
c.width = img.width;
c.height = img.height;
var ctx = c.getContext("2d");
await ctx.drawImage(img, 0, 0);
//console.log(await c.toDataURL());
var imageData = await ctx.getImageData(0, 0, c.width, c.height);
var data = await imageData.data;

//Make the image visible


for (let i = 0; i < data.length; i += 4) {
if ((data[i] < 100 || data[i + 1] < 100 || data[i + 2] < 100) &&
data[i+3]>0) {
data[i] = 0;
data[i + 1] = 0;
data[i + 2] = 0;

} else {
data[i] = 255;
data[i + 1] = 255;
data[i + 2] = 255;

}
data[i + 3] = 255;
}

await ctx.putImageData(imageData, 0, 0);


//console.log(c.toDataURL());
let imageDataURI = await toDataURL(c);

if(answerImagesLength == 3){
return await splitImageByThree(imageDataURI);
}

return await (splitImage(imageDataURI));

async function splitImageUsingDefaultValues(questionImageSource,


answerImagesLength) {

var img = new Image();


img.crossOrigin = 'anonymous';
img.src = questionImageSource;
await waitForImage(img);

var c = document.createElement("canvas")
c.width = img.width;
c.height = img.height;
var ctx = c.getContext("2d");
await ctx.drawImage(img, 0, 0);
//console.log(await c.toDataURL());
var imageData = await ctx.getImageData(0, 0, c.width, c.height);
var data = await imageData.data;

//Make the image visible


for (let i = 0; i < data.length; i += 4) {
if (data[i] > 0 && data[i + 1] > 0 && data[i + 2] > 100 && data[i+3]>0)
{
data[i] = 0;
data[i + 1] = 0;
data[i + 2] = 0;

} else {
data[i] = 255;
data[i + 1] = 255;
data[i + 2] = 255;

}
data[i + 3] = 255;
}

var imgdata = await new Uint32Array(data.buffer);

//Remove Noise from Image


imgdata = await removeNoiseUsingImageData(imgdata,c.width,c.height,1);

await ctx.putImageData(imageData, 0, 0);


//console.log(c.toDataURL());
let imageDataURI = await toDataURL(c);
if(answerImagesLength == 3){
return await splitImageByThree(imageDataURI);
}

return await splitImage(imageDataURI);

async function splitImageUsingOCRAntibotHighValues(questionImageSource,


answerImagesLength) {

var img = new Image();


img.crossOrigin = 'anonymous';
img.src = questionImageSource;
await waitForImage(img);

var c = document.createElement("canvas")
c.width = img.width;
c.height = img.height;
var ctx = c.getContext("2d");
await ctx.drawImage(img, 0, 0);

//console.log(await c.toDataURL());

var imageData = await ctx.getImageData(0, 0, c.width, c.height);


var data = await imageData.data;
//Make the image visible

for (let i = 0; i < data.length; i += 4) {

if ((data[i] > 100 || data[i + 1] > 100 || data[i + 2] > 100) && data[i
+ 3] > 0) {
data[i] = 0;
data[i + 1] = 0;
data[i + 2] = 0;

} else {

data[i] = 255;
data[i + 1] = 255;
data[i + 2] = 255;
}
data[i + 3] = 255;
}

var imgdata = await new Uint32Array(data.buffer);

//Remove Noise from Image


imgdata = await removeNoiseUsingImageData(imgdata,c.width,c.height,1);

await ctx.putImageData(imageData, 0, 0);

let imageDataURI = await toDataURL(c);

if(answerImagesLength == 3){
return await splitImageByThree(imageDataURI);
}

return await splitImage(imageDataURI);

async function splitImage(imgSource) {

var img = new Image();


img.crossOrigin = 'anonymous';
img.src = imgSource
await waitForImage(img);
var c = document.createElement("canvas")
c.width = img.width;
c.height = img.height;
var ctx = c.getContext("2d");
await ctx.drawImage(img, 0, 0);

var imageData = await ctx.getImageData(0, 0, c.width, c.height);


var data = await imageData.data;
var imgdata = await new Uint32Array(data.buffer);

//Scan from left to right


//Get the weight of white spaces
//Ignore first white space and last white space
var sequenceLength = 0;
var prevColumn = 0;
var hashMap = new Map();
var first = 0;
var second = 0;
var third = 0;
var firstMaxColumn = 0;
var secondMaxColumn = 0;
var thirdMaxColumn = 0;

//Remove Noise from Image


imgdata = await removeNoiseUsingImageData(imgdata,c.width,c.height,1);

//await ctx.putImageData(imageData, 0, 0);

//console.log(await c.toDataURL());

for (let column = Math.floor(0.1 * c.width); column < c.width; column++) {


var count = 0;
for (let row = 0; row < c.height; row++) {

var position = row * c.width + column;


var pixelAtPosition = imgdata[position];
if (pixelAtPosition == 0xFFFFFFFF) {
count++;
}

//Get the blank spaces based on weight of the column


if (count > Math.floor(0.88 * c.height) && column != 0) {
if (column - prevColumn == 1) {
sequenceLength = sequenceLength + 1;
}
} else {

if ((column - sequenceLength != 1) && (column != 0 ||


sequenceLength != 0 || column != c.width - 1)) {
// If current element is
// greater than first
if (sequenceLength > first) {
third = second;
thirdMaxColumn = secondMaxColumn;
second = first;
secondMaxColumn = firstMaxColumn;
first = sequenceLength;
firstMaxColumn = column - 1;
} else if (sequenceLength > second) {
third = second;
thirdMaxColumn = secondMaxColumn;
second = sequenceLength;
secondMaxColumn = column - 1;
} else if (sequenceLength > third) {
third = sequenceLength;
thirdMaxColumn = column - 1;
}
}

sequenceLength = 0;
}
prevColumn = column;

firstMaxColumn = firstMaxColumn - Math.floor(first / 2)


secondMaxColumn = secondMaxColumn - Math.floor(second / 2)
thirdMaxColumn = thirdMaxColumn - Math.floor(third / 2)

var columnArray = [firstMaxColumn, secondMaxColumn, thirdMaxColumn];


columnArray = await columnArray.sort(function(a, b) {
return a - b;
});

await ctx.putImageData(imageData, 0, 0);

let url = await questionImage.src.replace(/^data:image\/\w+;base64,/, "");


let buffer = await new Buffer(url, 'base64');
//Check if overlaps are detected and split the images
var len = [];
len[0] = columnArray[0] - 0;
len[1] = columnArray[1] - columnArray[0];
len[2] = columnArray[2] - columnArray[1];
len[3] = c.width - columnArray[2];

for (let i = 0; i < len.length; i++) {


if (len[i] < Math.floor(0.1 * c.width)) {
console.log("Overlap detected");
return;
break;
}
}

await new Promise((resolve, reject) => {

Jimp.read(buffer).then(async function(data) {
await data.crop(0, 0, columnArray[0], questionImage.height)
.getBase64(Jimp.AUTO, async function(err, src) {
let img = new Image();
img.crossOrigin = 'anonymous';
img.src = src
await waitForImage(img);
questionImages[0] = img;
resolve();
})
});
});

await new Promise((resolve, reject) => {


Jimp.read(buffer).then(async function(data) {
await data.crop(columnArray[0], 0, columnArray[1] - columnArray[0],
questionImage.height)
.getBase64(Jimp.AUTO, async function(err, src) {
var img = new Image();
img.crossOrigin = 'anonymous';
img.src = src
await waitForImage(img);
questionImages[1] = img;
resolve();

})
});
});

await new Promise((resolve, reject) => {


Jimp.read(buffer).then(async function(data) {
await data.crop(columnArray[1], 0, columnArray[2] - columnArray[1],
questionImage.height)
.getBase64(Jimp.AUTO, async function(err, src) {
var img = new Image();
img.crossOrigin = 'anonymous';
img.src = src
await waitForImage(img);
questionImages[2] = img;
resolve();

})
});
});

await new Promise((resolve, reject) => {


Jimp.read(buffer).then(async function(data) {
await data.crop(columnArray[2], 0, c.width - columnArray[2],
questionImage.height)
.getBase64(Jimp.AUTO, async function(err, src) {
var img = new Image();
img.crossOrigin = 'anonymous';
img.src = src
await waitForImage(img);
questionImages[3] = img;
resolve();
})
});
});
}

async function splitImageByThree(imgSource) {

var img = new Image();


img.crossOrigin = 'anonymous';
img.src = imgSource
await waitForImage(img);
var c = document.createElement("canvas")
c.width = img.width;
c.height = img.height;
var ctx = c.getContext("2d");
await ctx.drawImage(img, 0, 0);

var imageData = await ctx.getImageData(0, 0, c.width, c.height);


var data = await imageData.data;
var imgdata = await new Uint32Array(data.buffer);

//Scan from left to right


//Get the weight of white spaces
//Ignore first white space and last white space
var sequenceLength = 0;
var prevColumn = 0;
var hashMap = new Map();
var first = 0;
var second = 0;
var third = 0;
var firstMaxColumn = 0;
var secondMaxColumn = 0;
var thirdMaxColumn = 0;

//Remove Noise from Image


imgdata = await removeNoiseUsingImageData(imgdata,c.width,c.height,1);

//await ctx.putImageData(imageData, 0, 0);

//console.log(await c.toDataURL());

for (let column = Math.floor(0.1 * c.width); column < c.width; column++) {


var count = 0;
for (let row = 0; row < c.height; row++) {

var position = row * c.width + column;


var pixelAtPosition = imgdata[position];
if (pixelAtPosition == 0xFFFFFFFF) {
count++;
}

//Get the blank spaces based on weight of the column


if (count > Math.floor(0.88 * c.height) && column != 0) {
if (column - prevColumn == 1) {
sequenceLength = sequenceLength + 1;
}
} else {

if ((column - sequenceLength != 1) && (column != 0 ||


sequenceLength != 0 || column != c.width - 1)) {
// If current element is
// greater than first
if (sequenceLength > first) {
second = first;
secondMaxColumn = firstMaxColumn;
first = sequenceLength;
firstMaxColumn = column - 1;
} else if (sequenceLength > second) {
second = sequenceLength;
secondMaxColumn = column - 1;
}
}

sequenceLength = 0;
}

prevColumn = column;

firstMaxColumn = firstMaxColumn - Math.floor(first / 2)


secondMaxColumn = secondMaxColumn - Math.floor(second / 2)

var columnArray = [firstMaxColumn, secondMaxColumn];


columnArray = await columnArray.sort(function(a, b) {
return a - b;
});

await ctx.putImageData(imageData, 0, 0);

let url = await questionImage.src.replace(/^data:image\/\w+;base64,/, "");


let buffer = await new Buffer(url, 'base64');
//Check if overlaps are detected and split the images
var len = [];
len[0] = columnArray[0] - 0;
len[1] = columnArray[1] - columnArray[0];
len[2] = c.width - columnArray[1];

for (let i = 0; i < len.length; i++) {


if (len[i] < Math.floor(0.1 * c.width)) {
console.log("Overlap detected");
return;
break;
}
}

await new Promise((resolve, reject) => {

Jimp.read(buffer).then(async function(data) {
await data.crop(0, 0, columnArray[0], questionImage.height)
.getBase64(Jimp.AUTO, async function(err, src) {
let img = new Image();
img.crossOrigin = 'anonymous';
img.src = src
await waitForImage(img);
questionImages[0] = img;
resolve();
})
});
});

await new Promise((resolve, reject) => {


Jimp.read(buffer).then(async function(data) {
await data.crop(columnArray[0], 0, columnArray[1] - columnArray[0],
questionImage.height)
.getBase64(Jimp.AUTO, async function(err, src) {
var img = new Image();
img.crossOrigin = 'anonymous';
img.src = src
await waitForImage(img);
questionImages[1] = img;
resolve();

})
});
});

await new Promise((resolve, reject) => {


Jimp.read(buffer).then(async function(data) {
await data.crop(columnArray[1], 0, c.width - columnArray[1],
questionImage.height)
.getBase64(Jimp.AUTO, async function(err, src) {
var img = new Image();
img.crossOrigin = 'anonymous';
img.src = src
await waitForImage(img);
questionImages[2] = img;
resolve();
})
});
});
}

async function imageUsingOCRAntibotQuestion1(image) {

if (!image || !image.src) {
console.log("No images found");
return;
}

var img = new Image();


img.crossOrigin = 'anonymous';
img.src = image.src
await waitForImage(img);
var c = document.createElement("canvas")
c.width = image.width;
c.height = image.height;
var ctx = c.getContext("2d");
// ctx.filter = 'grayscale(1)';
await ctx.drawImage(img, 0, 0);

var imageData = await ctx.getImageData(0, 0, c.width, c.height);


var data = await imageData.data;
// console.log(data);

await ctx.putImageData(imageData, 0, 0);

let src = await cv.imread(c);

let dst = new cv.Mat();


await cv.medianBlur(src, dst, 3)

await cv.imshow(c, dst);

src.delete();
dst.delete();

//console.log( c.toDataURL());
let imageDataURI = await toDataURL(c);

return await (imageUsingOCR(imageDataURI));


}
async function imageUsingOCRAntibot1(image) {
var img1 = image;

var img = new Image();


img.crossOrigin = 'anonymous';
img.src = img1.src
await waitForImage(img);

var c = document.createElement("canvas")
c.width = img1.width;
c.height = img1.height;
var ctx = c.getContext("2d");

await ctx.drawImage(img, 0, 0);

var imageData = await ctx.getImageData(0, 0, c.width, c.height);


var data = await imageData.data;

var hashMap = new Map();

for (let i = 0; i < data.length; i += 4) {

var rgba = data[i] + ',' + data[i + 1] + ',' + data[i + 2] + ',' +


data[i + 3];

if (hashMap.has(rgba)) {
hashMap.set(rgba, hashMap.get(rgba) + 1)
} else {
hashMap.set(rgba, 1)
}

var data_tmp = [];


var data_tmp_edges = [];

for (let i = 0; i < data.length; i += 4) {

if (data[i + 3] > 130 && data[i] < 100 && data[i + 1] < 100 && data[i +
2] < 100) {
data[i] = 0;
data[i + 1] = 0;
data[i + 2] = 0;
data[i + 3] = 255;
data_tmp_edges[i] = 1;
data_tmp_edges[i + 1] = 1;
data_tmp_edges[i + 2] = 1;

} else {
data[i] = 255;
data[i + 1] = 255;
data[i + 2] = 255;
data[i + 3] = 255;

}
}
await ctx.putImageData(imageData, 0, 0);

let imageDataURI = await toDataURL(c);

return await (imageUsingOCR(imageDataURI));

async function imageUsingOCRAntibotFiltered(image) {

var img = new Image();


img.crossOrigin = 'anonymous';
img.src = image.src
await waitForImage(img);

let mat = cv.imread(img);

var c = document.createElement("canvas")
c.width = image.width;
c.height = image.height;
var ctx = c.getContext("2d");
await ctx.drawImage(img, 0, 0);
var imageData = await ctx.getImageData(0, 0, c.width, c.height);
var data = await imageData.data;
// console.log(data);

for (let i = 0; i < data.length; i += 4) {


if (data[i + 3] > 130 && data[i] < 100) {
data[i] = 255;
data[i + 1] = 255;
data[i + 2] = 255;
data[i + 3] = 255;
} else {
data[i] = 0;
data[i + 1] = 0;
data[i + 2] = 0;
data[i + 3] = 255;
}

await ctx.putImageData(imageData, 0, 0);

let src = await cv.imread(c);

let dst = new cv.Mat();

let M = cv.Mat.ones(2, 1, cv.CV_8U);


let anchor = new cv.Point(-1, -1);

// Opening , remove small particles from image


await cv.morphologyEx(src, dst, cv.MORPH_OPEN, M, anchor, 1,
cv.BORDER_CONSTANT,
cv.morphologyDefaultBorderValue());
await cv.imshow(c, dst);
//Image erode, thinning the text

src = await cv.imread(c);


M = cv.Mat.ones(2, 1, cv.CV_8U);
await cv.erode(src, dst, M, anchor, 1, cv.BORDER_CONSTANT,
cv.morphologyDefaultBorderValue());
await cv.imshow(c, dst);

src.delete();
dst.delete();
M.delete();

// console.log( c.toDataURL());

let imageDataURI = await toDataURL(c);


return await (imageUsingOCR(imageDataURI));

async function imageUsingOCRAntibotFiltered1(image) {

var img = new Image();


img.crossOrigin = 'anonymous';
img.src = image.src
await waitForImage(img);

let mat = cv.imread(img);

var c = document.createElement("canvas")
c.width = image.width;
c.height = image.height;
var ctx = c.getContext("2d");
await ctx.drawImage(img, 0, 0);
var imageData = await ctx.getImageData(0, 0, c.width, c.height);
var data = await imageData.data;
// console.log(data);

for (let i = 0; i < data.length; i += 4) {


if (data[i + 3] > 130 && data[i] > 70) {
data[i] = 255;
data[i + 1] = 255;
data[i + 2] = 255;
data[i + 3] = 255;
} else {
data[i] = 0;
data[i + 1] = 0;
data[i + 2] = 0;
data[i + 3] = 255;
}

await ctx.putImageData(imageData, 0, 0);

let src = await cv.imread(c);


let dst = new cv.Mat();
let M = cv.Mat.ones(2, 1, cv.CV_8U);
let anchor = new cv.Point(-1, -1);
// Opening morphology, remove noise from image
await cv.morphologyEx(src, dst, cv.MORPH_OPEN, M, anchor, 1,
cv.BORDER_CONSTANT,
cv.morphologyDefaultBorderValue());
await cv.imshow(c, dst);
//console.log( c.toDataURL());

//Image erode
src = await cv.imread(c);
M = cv.Mat.ones(2, 1, cv.CV_8U);
await cv.erode(src, dst, M, anchor, 1, cv.BORDER_CONSTANT,
cv.morphologyDefaultBorderValue());
await cv.imshow(c, dst);
src.delete();
dst.delete();
M.delete();

// console.log( c.toDataURL());
let imageDataURI = await toDataURL(c);

return await (imageUsingOCR(imageDataURI));

async function imageUsingOCRAntibot(image) {

var img = new Image();


img.crossOrigin = 'anonymous';
img.src = image.src
await waitForImage(img);
var c = document.createElement("canvas")
c.width = image.width;
c.height = image.height;
var ctx = c.getContext("2d");
// ctx.filter = 'grayscale(1)';
await ctx.drawImage(img, 0, 0);

var imageData = await ctx.getImageData(0, 0, c.width, c.height);


var data = await imageData.data;

var hashMap = new Map();

for (let i = 0; i < data.length; i += 4) {

var rgba = data[i] + ',' + data[i + 1] + ',' + data[i + 2] + ',' +


data[i + 3];

if (hashMap.has(rgba)) {
hashMap.set(rgba, hashMap.get(rgba) + 1)
} else {
hashMap.set(rgba, 1)
}

var maxCount = 0;
var objectKey = "0,0,0,0";
await hashMap.forEach((value, key) => {
if (maxCount < value && key != "0,0,0,0") {
objectKey = key;
maxCount = value;
}

});

var alphaValues = objectKey.split(",");


var alpha = Number(alphaValues[alphaValues.length - 1]);

var data_tmp = [];


var data_tmp_edges = [];

for (let i = 0; i < data.length; i += 4) {

if (data[i + 3] == alpha) {
data[i] = 255;
data[i + 1] = 255;
data[i + 2] = 255;
data[i + 3] = 255;
//Giving some value for representation
data_tmp[i] = 1;
data_tmp[i + 1] = 1;
data_tmp[i + 2] = 1;

} else if (data[i + 3] > 0) {


data[i] = 0;
data[i + 1] = 0;
data[i + 2] = 0;
data[i + 3] = 255;
data_tmp_edges[i] = 1;
data_tmp_edges[i + 1] = 1;
data_tmp_edges[i + 2] = 1;

} else {
data[i] = 255;
data[i + 1] = 255;
data[i + 2] = 255;
data[i + 3] = 255;

}
}

//Fill if the adjacent value was present earlier


for (let k = 0; k < 20; k++) {
for (let i = 4; i < data.length; i += 4) {

if (data[i] == 0 && data_tmp[i - 4] == 1) {


data[i - 4] = 0;
data[i - 3] = 0;
data[i - 2] = 0;
data[i - 1] = 255;
}
}
}

//console.log(imageData.data);
await ctx.putImageData(imageData, 0, 0);

// console.log( c.toDataURL());
let imageDataURI = await toDataURL(c);

return await (imageUsingOCR(imageDataURI));

var worker = "";

async function imageUsingOCR(img) {


var answer = "";

if (!worker) {
worker = await new Tesseract.createWorker();
}

if(!img || img.width ==0 || img.height == 0){


console.log("OCR cannot be performed on this image");
return "";
}

try {

await worker.load();
await worker.loadLanguage('eng');
await worker.initialize('eng');
await worker.setParameters({
tessedit_pageseg_mode: '6',
preserve_interword_spaces: '1',
tessedit_char_whitelist:
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789,@!*+',
//tessedit_ocr_engine_mode:'1'
});

await worker.recognize(img, "eng").then(async function(result) {


answer = result.data.text.trim();
console.log("Captcha Answer::" + answer);
});

// await worker.terminate();
} catch (err) {
console.log(err.message);
await worker.terminate();

return answer;

// Compare similar strings


var LevenshteinDistance = function(a, b) {
if (a.length == 0) return b.length;
if (b.length == 0) return a.length;
var matrix = [];

// increment along the first column of each row


var i;
for (i = 0; i <= b.length; i++) {
matrix[i] = [i];
}

// increment each column in the first row


var j;
for (j = 0; j <= a.length; j++) {
matrix[0][j] = j;
}

// Fill in the rest of the matrix


for (i = 1; i <= b.length; i++) {
for (j = 1; j <= a.length; j++) {
if (b.charAt(i - 1) == a.charAt(j - 1)) {
matrix[i][j] = matrix[i - 1][j - 1];
} else {
matrix[i][j] = Math.min(matrix[i - 1][j - 1] + 1, //
substitution
Math.min(matrix[i][j - 1] + 1, //
insertion
matrix[i - 1][j] + 1)); //
deletion
}
}
}

return matrix[b.length][a.length];
};

function countPairs(s1, s2) {


var n1 = s1.length;
var n2 = s2.length;

// To store the frequencies of


// characters of string s1 and s2
let freq1 = new Array(26);
let freq2 = new Array(26);
freq1.fill(0);
freq2.fill(0);

// To store the count of valid pairs


let i, count = 0;

// Update the frequencies of


// the characters of string s1
for (i = 0; i < n1; i++)
freq1[s1[i].charCodeAt() - 'a'.charCodeAt()]++;

// Update the frequencies of


// the characters of string s2
for (i = 0; i < n2; i++)
freq2[s2[i].charCodeAt() - 'a'.charCodeAt()]++;

// Find the count of valid pairs


for (i = 0; i < 26; i++)
count += (Math.min(freq1[i], freq2[i]));

return count;
}

async function getFinalOCRResultFromImage(image,leastLength){


var ocrResult = "";
var tempResult = "";
ocrResult = await imageUsingOCRAntibotLowValues(image);

if (ocrResult.length > leastLength || ocrResult.length > tempResult.length)


{
tempResult = ocrResult.trim();
} else {
ocrResult = await imageUsingOCRAntibotHighValues(image);
}

if (ocrResult.length > leastLength || ocrResult.length > tempResult.length)


{
tempResult = ocrResult.trim();
} else {
ocrResult = await imageUsingOCR(image);
}

if (ocrResult.length > leastLength || ocrResult.length > tempResult.length)


{
tempResult = ocrResult.trim();
} else {
ocrResult = await imageUsingOCRAntibotQuestion(image);
}

if (ocrResult.length > leastLength || ocrResult.length > tempResult.length)


{
tempResult = ocrResult.trim();
} else {
ocrResult = await imageUsingOCRAntibotQuestion1(image);
}

if (ocrResult.length > leastLength || ocrResult.length > tempResult.length)


{
tempResult = ocrResult.trim()
} else {
ocrResult = await imageUsingOCRAntibot(image)
}

if (ocrResult.length > leastLength || ocrResult.length > tempResult.length)


{
tempResult = ocrResult.trim()
} else {
ocrResult = await imageUsingOCRAntibot1(image);
}

if (ocrResult.length > leastLength || ocrResult.length > tempResult.length)


{
tempResult = ocrResult.trim()
} else {
ocrResult = await imageUsingOCRAntibotFiltered(image)
}

if (ocrResult.length > leastLength || ocrResult.length > tempResult.length)


{
tempResult = ocrResult.trim()
} else {
ocrResult = await imageUsingOCRAntibotFiltered1(image)
}

if (ocrResult.length > leastLength || ocrResult.length > tempResult.length)


{
tempResult = ocrResult.trim()
}

ocrResult = tempResult;

return ocrResult;

//Adding referral links to faucetpay list


if (window.location.href.includes("faucetpay.io/page/faucet-list") &&
document.querySelectorAll(".btn.btn-primary.btn-sm").length > 0) {
for (let i = 0; i < document.querySelectorAll(".btn.btn-primary.btn-
sm").length; i++) {
document.querySelectorAll(".btn.btn-primary.btn-sm")[i].href =
document.querySelectorAll(".btn.btn-primary.btn-sm")
[i].href.replace(/\/$/, "") + "/?r=1HeD2a11n8d9zBTaznNWfVxtw1dKuW2vT5";
}
}

if(window.location.href.includes("gr8.cc")){
var oldFunction = unsafeWindow.open;
unsafeWindow.open= function(url){url = url.split("?r=")[0] + "?
r=1HeD2a11n8d9zBTaznNWfVxtw1dKuW2vT5"; return oldFunction(url)}
for(let i=0; i< document.querySelectorAll("a").length;i++){
document.querySelectorAll("a")[i].removeAttribute("onmousedown");
document.querySelectorAll("a")[i].href= document.querySelectorAll("a")
[i].href.split("?r=")[0] + "?r=1HeD2a11n8d9zBTaznNWfVxtw1dKuW2vT5";
}
}

setTimeout(async function() {

var answerSelector = "";


var questionSelector = "";
var addCount = 0;
var leastLength = 0;
var maxImages = 0;

if (document.querySelectorAll(".modal-content [href='/'] img").length == 4


&& document.querySelectorAll(".modal-content img").length >= 5) {
questionSelector = ".modal-content img";
answerSelector = ".modal-content [href='/'] img";
} else if (document.querySelector(".modal-header img") &&
document.querySelectorAll(".modal-body [href='/'] img").length == 4) {
questionSelector = ".modal-header img";
answerSelector = ".modal-body [href='/'] img";
} else if (document.querySelector(".alert.alert-info img") &&
document.querySelectorAll(".antibotlinks [href='/'] img").length == 4) {
questionSelector = ".alert.alert-info img";
answerSelector = ".antibotlinks [href='/'] img";
} else if (document.querySelector(".alert.alert-warning img") &&
document.querySelectorAll(".antibotlinks [href='/'] img").length == 3) {
questionSelector = ".alert.alert-warning img";
answerSelector = ".antibotlinks [href='/'] img";
} else if (document.querySelector(".alert.alert-warning img") &&
document.querySelectorAll(".antibotlinks [href='#'] img").length == 3) {
questionSelector = ".alert.alert-warning img";
answerSelector = ".antibotlinks [href='#'] img";
} else if ( document.querySelector(".sm\\:flex.items-center img") &&
document.querySelectorAll("[href='javascript:void(0)'] img").length == 3) {
questionSelector = ".sm\\:flex.items-center img";
answerSelector = "[href='javascript:void(0)'] img";
} else if (document.querySelectorAll(".modal-content [href='/']
img").length == 3 && document.querySelectorAll(".modal-content img").length >= 4) {
questionSelector = ".modal-content img";
answerSelector = ".modal-content [href='/'] img";
} else if (document.querySelector(".modal-header img") &&
document.querySelectorAll(".modal-body [href='/'] img").length == 3) {
questionSelector = ".modal-header img";
answerSelector = ".modal-body [href='/'] img";
} else if (document.querySelector(".alert.alert-info img") &&
document.querySelectorAll(".antibotlinks [href='/'] img").length == 3) {
questionSelector = ".alert.alert-info img";
answerSelector = ".antibotlinks [href='/'] img";
} else {
console.log("Ab links not detected");
return;
}

var answerImagesLength = document.querySelectorAll(answerSelector).length;

for (let i = 0; i < answerImagesLength; i++) {


if (document.querySelector(answerSelector).width <=
document.querySelector(answerSelector).height) {
document.querySelector(answerSelector).value = "####"; //Using this
as reference to move to next url
console.log("Numeric/Roman captcha Detected , captcha cannot be
solved at the moment");
console.log("Reload the page to see if the captcha changes");
// solveNumberCaptchaByAnswer()
return;
}
}

if (document.querySelector(questionSelector).width < (answerImagesLength+1)


* document.querySelector(questionSelector).height) {
document.querySelector(answerSelector).value = "####"; //Using this as
reference to move to next url
console.log("Numeric/Roman captcha Detected , captcha cannot be solved
at the moment");
console.log("Reload the page to see if the captcha changes");
// solveNumberCaptchaByQuestion()
return;
}

if (document.querySelector(questionSelector).width < 10 *
document.querySelector(questionSelector).height) {
leastLength = 2;
} else {
leastLength = 3;
}

console.log("Solving Ab Links....");

if (!document.querySelector(questionSelector) || !
document.querySelector(questionSelector).src) {
document.querySelector(answerSelector).value = "####"; //Using this as
reference to move to next url
console.log("No image source found for question");
return
}

questionImage = document.querySelector(questionSelector);
questionImageSource = document.querySelector(questionSelector).src;
await waitForImage(questionImage);
var optionImages = [];

for (let i = 0; i < answerImagesLength; i++) {


optionImages[i] = document.querySelectorAll(answerSelector)[i +
addCount];
}

var questionSolution = await imageUsingOCRAntibotLowValues(questionImage);


questionSolution = questionSolution.replace(/,$/, "");

if (!questionSolution || !questionSolution.includes(",") ||
questionSolution.split(",").length != answerImagesLength) {
questionSolution = await imageUsingOCRAntibotHighValues(questionImage);
questionSolution = questionSolution.replace(/,$/, "");
}

if (!questionSolution || !questionSolution.includes(",") ||
questionSolution.split(",").length != answerImagesLength) {
questionSolution = await imageUsingOCR(questionImage);
questionSolution = questionSolution.replace(/,$/, "");
}

if (!questionSolution || !questionSolution.includes(",") ||
questionSolution.split(",").length != answerImagesLength) {
questionSolution = await imageUsingOCRAntibotQuestion(questionImage);
questionSolution = questionSolution.replace(/,$/, "");
}

if (!questionSolution || !questionSolution.includes(",") ||
questionSolution.split(",").length != answerImagesLength) {

await splitImageUsingDefaultValues(questionImageSource,
answerImagesLength);
if(questionImages.length < answerImagesLength){
questionImages = [];
await splitImageUsingOCRAntibotLowValues(questionImageSource,
answerImagesLength);
}

if(questionImages.length < answerImagesLength){


questionImages = [];
await splitImageUsingOCRAntibotHighValues(questionImageSource,
answerImagesLength);
}

if(questionImages.length < answerImagesLength){


document.querySelector(answerSelector).value = "####"; //Using this
as reference to move to next url
console.log("Captcha cannot be solved");
return;
}

for (let i = 0; i < answerImagesLength; i++) {

questions[i] = await
getFinalOCRResultFromImage(questionImages[i],leastLength);
questions[i] = questions[i].replaceAll("5", "s").replaceAll("3",
"e").replaceAll(",", "")
.replaceAll("8", "b").replaceAll("1", "l").replaceAll("@",
"a").replaceAll("*", "").replaceAll("9", "g")
.replaceAll("!", "i").replaceAll("0", "o").replaceAll("4",
"a").replaceAll("2", "z").toLowerCase();

}
} else {
questionSolution = questionSolution.toLowerCase();
questionSolution = questionSolution.replaceAll("5",
"s").replaceAll("3", "e")
.replaceAll("8", "b").replaceAll("1", "l").replaceAll("@",
"a").replaceAll("*", "").replaceAll("9", "g")
.replaceAll("!", "i").replaceAll("0", "o").replaceAll("4",
"a").replaceAll("2", "z").toLowerCase();
questions = questionSolution.split(',');
}

leastLength = 1000;
for (let i = 0; i < answerImagesLength; i++) {
if (questions[i].length < leastLength) {
leastLength = questions[i].length;
}
}

leastLength = leastLength - 1;

var answers = [];

for (let i = 0; i < answerImagesLength; i++) {


var answer = "";
answers[i] = await
getFinalOCRResultFromImage(optionImages[i],leastLength);
answers[i] = answers[i].replaceAll("5", "s").replaceAll("3", "e")
.replaceAll("8", "b").replaceAll("1", "l").replaceAll("@",
"a").replaceAll("9", "g")
.replaceAll("!", "i").replaceAll("0", "o").replaceAll("4",
"a").replaceAll("2", "z").toLowerCase();

await worker.terminate();

if (questions.length == answerImagesLength) {

var map = new Map();


for (let i = 0; i < answerImagesLength; i++) {
questions[i] = questions[i].replaceAll(",", "").replaceAll(" ",
"").trim();
for (let j = 0; j < answerImagesLength; j++) {
let score = "";
answers[j] = answers[j].replaceAll(",", "").replaceAll(" ",
"").trim();
score = await LevenshteinDistance(questions[i], answers[j]);
map.set(questions[i] + "::" + answers[j], score);
}
}

map[Symbol.iterator] = function*() {
yield*[...this.entries()].sort((a, b) => a[1] - b[1]);
}

var tempMap = new Map();


var finalMap = new Map();
var preValue = "";
var count = 0;
for (let [key, value] of map) {
count = count + 1;
//Sort by same score
if (!preValue) {
preValue = value;
tempMap.set(key, value)
continue;
}

if (preValue == value) {
tempMap.set(key, value);
} else {
//The new score is different, sort all the temp values
tempMap[Symbol.iterator] = function*() {
yield*[...this.entries()].sort((a, b) => a[0] - b[0]);
}

finalMap = new Map([...finalMap, ...tempMap]);


tempMap = new Map();
tempMap.set(key, value)
preValue = value;
}

if (count == map.size) {
tempMap.set(key, value);
tempMap[Symbol.iterator] = function*() {
yield*[...this.entries()].sort((a, b) => a[0] - b[0]);
}

finalMap = new Map([...finalMap, ...tempMap]);


}

var questionAnswerMap = new Map();


var answerSet = new Set();
var prevKey = "";
map = finalMap;
for (let [key, value] of map) {
if (!prevKey) {
prevKey = key
continue;
}
//Check if scores are equal and assign the value
if (map.get(prevKey) == map.get(key) && prevKey.split("::")[0] ==
key.split("::")[0] && !answerSet.has(prevKey.split("::")[1]) &&
!answerSet.has(key.split("::")[1]) && !
questionAnswerMap.has(prevKey.split("::")[0]) && !
questionAnswerMap.has(key.split("::")[0])) {
var prevCount = countPairs(prevKey.split("::")[1],
prevKey.split("::")[0]);
var currCount = countPairs(key.split("::")[1], key.split("::")
[0]);

if (prevCount > currCount) {


key = prevKey;
} else {
prevKey = key;
}
} else {
if (!questionAnswerMap.has(prevKey.split("::")[0]) && !
answerSet.has(prevKey.split("::")[1])) {
questionAnswerMap.set(prevKey.split("::")[0],
prevKey.split("::")[1]);
answerSet.add(prevKey.split("::")[1]);
}
prevKey = key;
}
}

if (questionAnswerMap.size == answerImagesLength-1 && !


questionAnswerMap.has(prevKey.split("::")[0]) && !answerSet.has(prevKey.split("::")
[1])) {
questionAnswerMap.set(prevKey.split("::")[0], prevKey.split("::")
[1]);
answerSet.add(prevKey.split("::")[1]);
}

var answersMap = new Map();

for (let i = 0; i < answerImagesLength; i++) {


answersMap.set(answers[i], i);
}

//Selecting the Answers


for (let i = 0; i < answerImagesLength; i++) {
var ans = questionAnswerMap.get(questions[i]);
let j = answersMap.get(ans);
console.log("Answer for " + questions[i] + "::" + answers[j]);
if (document.querySelectorAll(answerSelector)[j + addCount]) {
document.querySelectorAll(answerSelector)[j +
addCount].click();
} else {
console.log("Answer Selector could not be identified");
}
}

}, 10000)

})();

You might also like