Skip to content

Commit

Permalink
further down the api-wrapping road
Browse files Browse the repository at this point in the history
  • Loading branch information
evyatarmeged committed Oct 6, 2018
1 parent 4160f44 commit 949b53c
Show file tree
Hide file tree
Showing 7 changed files with 1,207 additions and 99 deletions.
28 changes: 28 additions & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"env": {
"es6": true
},
"extends": "eslint:recommended",
"parserOptions": {
"ecmaVersion": 2017,
"sourceType": "module"
},
"rules": {
"indent": [
"error",
"tab"
],
"linebreak-style": [
"error",
"unix"
],
"quotes": [
"error",
"double"
],
"semi": [
"error",
"always"
]
}
}
Empty file added cookieSupport.js
Empty file.
141 changes: 48 additions & 93 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,123 +1,79 @@
const fs = require("fs")
const axios = require("axios")
const cheerio = require("cheerio")
const URL = require("url-parse")
const tough = require('tough-cookie');
const safeEval = require("safe-eval")
const Cookie = tough.Cookie;
const fs = require("fs");
const cheerio = require("cheerio");
const safeEval = require("safe-eval");
const RequestHandler = require("./requestHandler")


class Humanoid {
constructor() {
this.cookieJar = new tough.CookieJar();
this.userAgents = fs.readFileSync(__dirname + "/ua.text").toString().split("\n");
this.setCookieJar(this.cookieJar);
this._userAgents = fs.readFileSync(__dirname + "/ua.text").toString().split("\n");
this._getRandomTimeout = () => Math.floor(Math.random() * (8000 - 5500 + 1)) + 5500;
this._parseOperator = expr => expr.slice(0, 2);
this._requestHandler = new RequestHandler();
}

// Adding cookie persistence to axios. Too bad for the hacky solution tbh
setCookieJar(cookieJar) {
axios.interceptors.request.use(function (config) {
cookieJar.getCookies(config.url, function(err, cookies) {
config.headers.cookie = cookies.join('; ');
});
return config;
});

axios.interceptors.response.use(function (response) {
if (response.headers['set-cookie'] instanceof Array) {
cookies = response.headers['set-cookie'].forEach(function (c) {
cookieJar.setCookie(Cookie.parse(c), response.config.url, function(err, cookie){});
});
}
return response;
});
}

// 1337 self-explanatory arrow funcs
getRandomUA() { return this.userAgents[Math.floor(Math.random() * this.userAgents.length)] }
getRandomTimeout() { return Math.floor(Math.random() * (8000 - 5500 + 1)) + 5500 }
extractHostFromUrl = url => URL(url).host
parseOperator = expr => expr.slice(0, 2)
/*
console.log($("input[name=jschl_vc]").val());
console.log($("input[name=pass]").val());
*/

// noinspection JSMethodCanBeStatic
extractChallengeFromHTML(html) {
_extractChallengeFromHTML(html) {
let $ = cheerio.load(html);
let script = $("script");
return script.html();
}

// noinspection JSMethodCanBeStatic
extractTimeoutFromScript(htmlResponse) {
let match = htmlResponse.match(/,\s[0-9]0{3}\);/g)
_extractTimeoutFromScript(htmlResponse) {
let match = htmlResponse.match(/,\s[0-9]0{3}\);/g);
if (match) {
match = match[0].replace(/,|\s|\)|;/g, "")
match = match[0].replace(/,|\s|\)|;/g, "");
}
return match;
}

javascriptChallengeInResponse(htmlResponse) {
return htmlResponse.indexOf("jschl") > -1 && htmlResponse.indexOf("DDoS protection by Cloudflare") > -1
}

getRequestHeaders(url, userAgent) {
let headers = {}
headers["Host"] = this.extractHostFromUrl(url)
headers["Connection"] = "keep-alive"
headers["Accept"] = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
headers["Accept-Encoding"] = "gzip, deflate, br"
headers["User-Agent"] = userAgent

return headers
}


async sendRequest(url, method=null, headers=null, userAgent=null) {
try {
let response = await axios({
method: method || "GET",
url: url,
headers: headers || this.getRequestHeaders(url, userAgent),
jar: this.cookieJar,
validateStatus: function (status) {
return status >= 200 && status < 600; // default
}
});
return response
} catch (err) {
throw Error(`An error occurred:
${err}`)
}
javascriptChallengeInResponse(html) {
return html.indexOf("jschl") > -1 && html.indexOf("DDoS protection by Cloudflare") > -1;
}

// noinspection JSMethodCanBeStatic
operateOnResult(operator, expr, result) {
_operateOnResult(operator, expr, result) {
switch(operator) {
case "+=":
return result += safeEval(expr);
case "*=":
return result *= safeEval(expr);
case "-=":
return result -= safeEval(expr);
case "/=":
return result /= safeEval(expr);
default:
throw Error("Could not match operator. Cannot")
case "+=":
return result += safeEval(expr);
case "*=":
return result *= safeEval(expr);
case "-=":
return result -= safeEval(expr);
case "/=":
return result /= safeEval(expr);
default:
throw Error("Could not match operator. Cannot");
}
}

buildAnswer(answerMutations, currResult) {
_buildAnswer(answerMutations, currResult) {
for (let ans of answerMutations) {
let operator = ans.slice(0,2);
let expr = ans.slice(0,3);
currResult = this.operateOnResult(operator, expr, currResult);
currResult = this._operateOnResult(operator, expr, currResult);
}
return currResult;
}

async sendRequest(url, method=null, headers=null) {
await this._requestHandler.sendRequest(url, method, headers)
.then(res => {
return res;
})
.catch(err => {
throw Error(`An error occurred:\n${err}`);
})
}

solveJSChallenge(html) {
let answerDeclaration, answerMutations, answer;
let script = this.extractChallengeFromHTML(html);
let timeout = this.extractTimeoutFromScript(script);
let script = this._extractChallengeFromHTML(html);
let timeout = this._extractTimeoutFromScript(script) || this._getRandomTimeout();
try {
// Parse only the actual math challenge parts from the script tag and assign them
let testMatches = script.match(/(.=\+)?(\(\(!\+).*/g); // Match the challenge part
Expand All @@ -126,23 +82,22 @@ class Humanoid {
// Perform the necessary parsing
answerDeclaration = answerDeclaration.replace(/[;}]/g, "");
answerMutations = answerMutations
.split(';')
.split(";")
.map(s => s.match(/(.=.)?(\(\(!\+).*/g))
.filter(s => s !== null)
.map(s => s[0])
answer = this.buildAnswer(answerMutations, safeEval(answerDeclaration));

return answer.toFixed(10);
answer = this._buildAnswer(answerMutations, safeEval(answerDeclaration));
answer = answer.toFixed(10);
}
} catch (err) {
throw Error(`Could not solve JavaScript challenge. Caused due to error:
${err}`)
throw Error(`Could not solve or parse JavaScript challenge. Caused due to error:\n${err}`);
}
}
}

let humanoid = new Humanoid();
humanoid.sendRequest("http://google.com")
humanoid.sendRequest("https://google.com")
.then(res => {
console.log(res)
})
Expand Down
Loading

0 comments on commit 949b53c

Please sign in to comment.