vk-captcha-bypass
Version:
Обход VK Captcha
116 lines • 4.72 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.VKCaptchaBypasser = exports.APIError = exports.VKCaptchaBypasserError = void 0;
const utils_1 = require("./utils");
class VKCaptchaBypasserError extends Error {
constructor(message) {
super(message);
}
}
exports.VKCaptchaBypasserError = VKCaptchaBypasserError;
class APIError extends Error {
error;
constructor(error) {
super(`${error.error_msg} (Code: ${error.error_code})`);
this.error = error;
}
get code() {
return this.error.error_code;
}
get params() {
return this.error.request_params;
}
}
exports.APIError = APIError;
class VKCaptchaBypasser {
version;
baseApiUrl;
maxSensorsDataSizeKb;
constructor(options) {
this.version = options?.version || '5.199';
this.baseApiUrl = options?.baseApiUrl || 'https://api.vk.ru/';
this.maxSensorsDataSizeKb = options?.maxSensorsDataSizeKb || 900;
}
async bypass(redirectUri, mouseTraceParams) {
const pow = await this.loadPoWChallengeParams(redirectUri);
const hash = await (0, utils_1.generatePoW)(pow.input, pow.difficulty);
const queryParams = new URLSearchParams(redirectUri.replace(/(.*)\?/, ''));
const { session_token, domain } = Object.fromEntries(queryParams.entries());
const initialParams = { session_token, domain };
const { bridge_sensors_list: sensorsList } = await this.request('captchaNotRobot.settings', initialParams);
await this.request('captchaNotRobot.componentDone', initialParams);
const sensorsData = this.buildSensorsData(sensorsList, mouseTraceParams);
const captcha = await this.request('captchaNotRobot.check', {
...initialParams,
...sensorsData,
hash,
answer: 'e30=',
});
await this.request('captchaNotRobot.endSession', initialParams);
return captcha;
}
async request(method, params) {
const entries = Object.entries({ ...params, v: this.version });
const encoded = entries.map(([key, value]) => {
if (typeof value === 'object' && value !== null)
return [key, JSON.stringify(value)];
return [key, String(value)];
});
const body = new URLSearchParams(Object.fromEntries(encoded));
const contentLength = Buffer.from(body.toString()).byteLength;
const url = new URL(`/method/${method}`, this.baseApiUrl);
const fetchResponse = await fetch(url.toString(), {
headers: {
'content-type': 'application/x-www-form-urlencoded',
'content-length': contentLength.toString(),
},
body,
method: 'POST',
});
const response = (await fetchResponse.json());
if ('error' in response)
throw new APIError(response.error);
if ('status' in response && response.status === 'ERROR')
throw new APIError({
error_code: 0,
error_msg: `APIError: ${JSON.stringify(response)}`,
request_params: [
...body
.entries()
.map(([key, value]) => ({ key, value }))
.toArray(),
],
});
return response.response;
}
async loadPoWChallengeParams(redirectUri) {
const fetchResponse = await fetch(redirectUri);
const html = await fetchResponse.text();
const [, input] = html.match(/const powInput\s*=\s*"([^']+)";/i) || [];
if (typeof input !== 'string') {
throw new VKCaptchaBypasserError(`No "powInput" value`);
}
const [, rawDifficulty] = html.match(/const difficulty\s*=\s*(\d+);/) || [];
if (typeof rawDifficulty !== 'string') {
throw new VKCaptchaBypasserError(`No "difficulty" value`);
}
const difficulty = Number(rawDifficulty);
return { difficulty, input };
}
buildSensorsData(sensorsList, mouseTraceParams) {
let cursor = (0, utils_1.generateMouseTrace)(mouseTraceParams);
const maxBytes = this.maxSensorsDataSizeKb * 1024;
const avgBytesPerPoint = 20;
let maxPoints = Math.floor(maxBytes / avgBytesPerPoint);
if (cursor.length > maxPoints) {
cursor = cursor.slice(0, maxPoints);
}
let sensors = {};
for (const sensor of sensorsList) {
sensors[sensor] = sensor === 'cursor' ? cursor : [];
}
return sensors;
}
}
exports.VKCaptchaBypasser = VKCaptchaBypasser;
//# sourceMappingURL=bypasser.js.map
;