110 lines
3.6 KiB
JavaScript
110 lines
3.6 KiB
JavaScript
const axios = require("axios");
|
|
const PLAY_AUDIO_BTN_ID = ".audio-captcha-play-button"
|
|
const wget = require('node-wget');
|
|
const crypto = require('crypto');
|
|
const fs = require("fs");
|
|
const homedir = require('os').homedir();
|
|
const dest_dir = homedir + "/wavs/"
|
|
const AUDIO_CAPTCHA_TRACK = ".audio-captcha-track";
|
|
const CAPTCHA_CONTAINER = "#captcha-container";
|
|
const WAV_URL_REGEX = "https:.+.wav";
|
|
const re = new RegExp(WAV_URL_REGEX);
|
|
|
|
function delay(delayInMs) {
|
|
return new Promise(resolve => {
|
|
setTimeout(() => {
|
|
resolve(2);
|
|
}, delayInMs);
|
|
});
|
|
}
|
|
|
|
function getRandom() {
|
|
return Math.floor(Math.random() * 3);
|
|
}
|
|
|
|
function getRandomWaitTime() {
|
|
return getRandom() * 1000
|
|
}
|
|
|
|
|
|
async function sendRequest(fileName, callback) {
|
|
const fileStream = fs.createReadStream(fileName);
|
|
let response = await axios.post('http://127.0.0.1:8000', fileStream, {
|
|
headers: {
|
|
'Content-Type': 'wav'
|
|
}
|
|
})
|
|
if (response.status === 200) {
|
|
let result = response.data;
|
|
console.log(result);
|
|
callback(result);
|
|
console.log("will delete wav file: " + fileName);
|
|
await fs.unlink(fileName, (err) => {
|
|
if (err) throw err;
|
|
console.log(fileName + ' was deleted');
|
|
})
|
|
} else {
|
|
console.log("error");
|
|
callback([]);
|
|
console.log("will delete wav file: " + fileName);
|
|
}
|
|
}
|
|
|
|
class GeoCaptchaSolver {
|
|
constructor(page) {
|
|
this.page = page;
|
|
}
|
|
|
|
|
|
async solve() {
|
|
console.log("solve() called.")
|
|
console.log("play audio")
|
|
let iframeHandler = await this.page.frameLocator("body > iframe");
|
|
let playAudioBtn = await iframeHandler.locator(PLAY_AUDIO_BTN_ID);
|
|
playAudioBtn.click();
|
|
await delay(5000 + getRandomWaitTime());
|
|
let captcha_container = await iframeHandler.locator(CAPTCHA_CONTAINER)
|
|
let html = await captcha_container.innerHTML()
|
|
console.log("audio_tag: " + html);
|
|
// find wav from html
|
|
await this.findTextFromWavFile(html, async (number_list) => {
|
|
for (let i = 1; i <= number_list.length; i++) {
|
|
let selector = "#captcha__audio > div.audio-captcha-input-container > input:nth-child(" + i + ")"
|
|
console.log("selector is " + selector)
|
|
await iframeHandler.locator(selector).focus()
|
|
await iframeHandler.locator(selector).fill("" + number_list[i - 1])
|
|
// fieldInputs[i].value = number_list[i];
|
|
await delay(2000 + getRandomWaitTime());
|
|
}
|
|
}
|
|
)
|
|
}
|
|
|
|
async findTextFromWavFile(html, callback) {
|
|
let result = re.exec(html);
|
|
//create the directory if not exist
|
|
await fs.promises.mkdir(dest_dir, {recursive: true});
|
|
if (result) {
|
|
let audioUrl = result[0];
|
|
let fileName = crypto.randomUUID() + ".wav";
|
|
wget({url: audioUrl, dest: dest_dir + fileName}, function (error, response, body) {
|
|
if (error) {
|
|
console.log('--- error:');
|
|
console.log(error); // error encountered
|
|
} else {
|
|
console.log('download the file successfully');
|
|
// send request to get numbers
|
|
sendRequest(dest_dir + fileName, callback);
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
|
|
module.exports = GeoCaptchaSolver
|
|
|
|
// sendRequest("/Users/lpan/wavs/42f90d53-17c0-4a9b-a585-59eaa737a80d.wav").then(r => {
|
|
// console.log(r)
|
|
// })
|