diff --git a/src/client/BaseClient.js b/src/client/BaseClient.js index cedb9f9..73b4039 100644 --- a/src/client/BaseClient.js +++ b/src/client/BaseClient.js @@ -16,6 +16,9 @@ class BaseClient extends EventEmitter { if (options.intents) { process.emitWarning('Intents is not available.', 'DeprecationWarning'); } + if (typeof options.captchaSolver === 'function') { + options.captchaService = 'custom'; + } /** * The options the client was instantiated with * @type {ClientOptions} diff --git a/src/client/Client.js b/src/client/Client.js index 0f1cdb7..0c29cff 100644 --- a/src/client/Client.js +++ b/src/client/Client.js @@ -984,7 +984,7 @@ class Client extends BaseClient { throw new TypeError('CLIENT_INVALID_OPTION', 'captchaService', captchaServices.join(', ')); } // Parse captcha key - if (options && captchaServices.includes(options.captchaService)) { + if (options && captchaServices.includes(options.captchaService) && options.captchaService !== 'custom') { if (typeof options.captchaKey !== 'string') { throw new TypeError('CLIENT_INVALID_OPTION', 'captchaKey', 'a string'); } @@ -996,6 +996,9 @@ class Client extends BaseClient { break; } } + if (options && typeof options.captchaSolver !== 'function') { + throw new TypeError('CLIENT_INVALID_OPTION', 'captchaSolver', 'a function'); + } if (options && typeof options.DMSync !== 'boolean') { throw new TypeError('CLIENT_INVALID_OPTION', 'DMSync', 'a boolean'); } diff --git a/src/rest/CaptchaSolver.js b/src/rest/CaptchaSolver.js index dc2c4a2..6e68d37 100644 --- a/src/rest/CaptchaSolver.js +++ b/src/rest/CaptchaSolver.js @@ -1,8 +1,9 @@ 'use strict'; module.exports = class CaptchaSolver { - constructor(service, key) { - this.service = ''; + constructor(service, key, defaultCaptchaSolver) { + this.service = 'custom'; this.solver = undefined; + this.defaultCaptchaSolver = defaultCaptchaSolver; this._setup(service, key); } _missingModule(name) { @@ -37,6 +38,9 @@ module.exports = class CaptchaSolver { throw this._missingModule('2captcha'); } } + default: { + this.solve = this.defaultCaptchaSolver; + } } } solve() {} diff --git a/src/rest/RESTManager.js b/src/rest/RESTManager.js index c742cc5..dddf785 100644 --- a/src/rest/RESTManager.js +++ b/src/rest/RESTManager.js @@ -28,7 +28,11 @@ class RESTManager { } setup() { - this.captchaService = new CaptchaSolver(this.client.options.captchaService, this.client.options.captchaKey); + this.captchaService = new CaptchaSolver( + this.client.options.captchaService, + this.client.options.captchaKey, + this.client.options.captchaSolver, + ); } get api() { diff --git a/src/util/Constants.js b/src/util/Constants.js index 16ac995..7cc91c1 100644 --- a/src/util/Constants.js +++ b/src/util/Constants.js @@ -23,7 +23,7 @@ exports.MaxBulkDeletableMessageAge = 1_209_600_000; * * `2captcha` - 2captcha.com * @typedef {string[]} captchaServices */ -exports.captchaServices = ['2captcha']; +exports.captchaServices = ['2captcha', 'custom']; /** * Automatically scan and delete direct messages you receive that contain explicit media content. diff --git a/src/util/Options.js b/src/util/Options.js index ce4b6ff..fb02dc3 100644 --- a/src/util/Options.js +++ b/src/util/Options.js @@ -92,6 +92,15 @@ const { randomUA } = require('../util/Constants'); * @property {SweeperOptions} [sweepers={}] Options for cache sweeping * @property {WebsocketOptions} [ws] Options for the WebSocket * @property {HTTPOptions} [http] HTTP options + * @property {CustomCaptchaSolver} [captchaSolver] Function to solve a captcha (custom) + */ + +/** + * Function to solve a captcha + * @typedef {function} CustomCaptchaSolver + * @param {Captcha} captcha The captcha to solve + * @param {string} userAgent The user agent to use for the request + * @returns {Promise} hcaptcha token */ /** @@ -148,6 +157,7 @@ class Options extends null { static createDefault() { return { jsonTransformer: object => JSONBig.stringify(object), + captchaSolver: captcha => Promise.reject(new Error('CAPTCHA_SOLVER_NOT_IMPLEMENTED', captcha)), closeTimeout: 5_000, checkUpdate: true, readyStatus: true, diff --git a/typings/index.d.ts b/typings/index.d.ts index c8febc9..7bb9b1a 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -4773,6 +4773,7 @@ export interface ClientOptions { proxy?: string; captchaService?: captchaServices; captchaKey?: string; + captchaSolver?: (data: Captcha, userAgent: string) => Promise; interactionTimeout?: number; usingNewAttachmentAPI?: boolean; }