All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.twocaptcha.TwoCaptcha Maven / Gradle / Ivy

package com.twocaptcha;

import com.twocaptcha.captcha.Captcha;
import com.twocaptcha.captcha.ReCaptcha;
import com.twocaptcha.exceptions.ApiException;
import com.twocaptcha.exceptions.NetworkException;
import com.twocaptcha.exceptions.TimeoutException;
import com.twocaptcha.exceptions.ValidationException;

import java.io.File;
import java.util.HashMap;
import java.util.Map;

/**
 * Class TwoCaptcha
 */
public class TwoCaptcha {

    /**
     * API KEY
     */
    private String apiKey;

    /**
     * ID of software developer. Developers who integrated their software
     * with our service get reward: 10% of spendings of their software users.
     */
    private int softId;

    /**
     * URL to which the result will be sent
     */
    private String callback;

    /**
     * How long should wait for captcha result (in seconds)
     */
    private int defaultTimeout = 120;

    /**
     * How long should wait for recaptcha result (in seconds)
     */
    private int recaptchaTimeout = 600;

    /**
     * How often do requests to `/res.php` should be made
     * in order to check if a result is ready (in seconds)
     */
    private int pollingInterval = 10;

    /**
     * Helps to understand if there is need of waiting
     * for result or not (because callback was used)
     */
    private boolean lastCaptchaHasCallback;

    /**
     * Network client
     */
    private ApiClient apiClient;

    /**
     * TwoCaptcha constructor
     */
    public TwoCaptcha() {
        this.apiClient = new ApiClient();
    }

    /**
     * TwoCaptcha constructor
     *
     * @param apiKey
     */
    public TwoCaptcha(String apiKey) {
        this();
        setApiKey(apiKey);
    }

    /**
     * @param apiKey
     */
    public void setApiKey(String apiKey) {
        this.apiKey = apiKey;
    }

    /**
     * @param softId
     */
    public void setSoftId(int softId) {
        this.softId = softId;
    }

    /**
     * @param callback
     */
    public void setCallback(String callback) {
        this.callback = callback;
    }

    /**
     * @param timeout
     */
    public void setDefaultTimeout(int timeout) {
        this.defaultTimeout = timeout;
    }

    /**
     * @param timeout
     */
    public void setRecaptchaTimeout(int timeout) {
        this.recaptchaTimeout = timeout;
    }

    /**
     * @param interval
     */
    public void setPollingInterval(int interval) {
        this.pollingInterval = interval;
    }

    /**
     * @param apiClient
     */
    public void setHttpClient(ApiClient apiClient) {
        this.apiClient = apiClient;
    }

    /**
     * Sends captcha to `/in.php` and waits for it's result.
     * This helper can be used instead of manual using of `send` and `getResult` functions.
     *
     * @param captcha
     * @throws Exception
     */
    public void solve(Captcha captcha) throws Exception {
        Map waitOptions = new HashMap<>();

        if (captcha instanceof ReCaptcha) {
            waitOptions.put("timeout", recaptchaTimeout);
        }

        solve(captcha, waitOptions);
    }

    /**
     * Sends captcha to `/in.php` and waits for it's result.
     * This helper can be used instead of manual using of `send` and `getResult` functions.
     *
     * @param captcha
     * @param waitOptions
     * @throws Exception
     */
    public void solve(Captcha captcha, Map waitOptions) throws Exception {
        captcha.setId(send(captcha));

        if (!lastCaptchaHasCallback) {
            waitForResult(captcha, waitOptions);
        }
    }

    /**
     * This helper waits for captcha result, and when result is ready, returns it
     *
     * @param captcha
     * @param waitOptions
     * @throws Exception
     */
    public void waitForResult(Captcha captcha, Map waitOptions) throws Exception {
        long startedAt = (long)(System.currentTimeMillis() / 1000);

        int timeout = waitOptions.getOrDefault("timeout", this.defaultTimeout);
        int pollingInterval = waitOptions.getOrDefault("pollingInterval", this.pollingInterval);

        while (true) {
            long now = (long)(System.currentTimeMillis() / 1000);

            if (now - startedAt < timeout) {
                Thread.sleep(pollingInterval * 1000);
            } else {
                break;
            }

            try {
                String result = getResult(captcha.getId());
                if (result != null) {
                    captcha.setCode(result);
                    return;
                }
            } catch (NetworkException e) {
                // ignore network errors
            }
        }

        throw new TimeoutException("Timeout " + timeout + " seconds reached");
    }

    /**
     * Sends captcha to '/in.php', and returns its `id`
     *
     * @param captcha
     * @return
     * @throws Exception
     */
    public String send(Captcha captcha) throws Exception {
        Map params = captcha.getParams();
        Map files = captcha.getFiles();

        sendAttachDefaultParams(params);

        validateFiles(files);

        String response = apiClient.in(params, files);

        if (!response.startsWith("OK|")) {
            throw new ApiException("Cannot recognise api response (" + response + ")");
        }

        return response.substring(3);
    }

    /**
     * Returns result of captcha if it was solved or `null`, if result is not ready
     *
     * @param id
     * @return
     * @throws Exception
     */
    public String getResult(String id) throws Exception {
        Map params = new HashMap<>();
        params.put("action", "get");
        params.put("id", id);

        String response = res(params);

        if (response.equals("CAPCHA_NOT_READY")) {
            return null;
        }

        if (!response.startsWith("OK|")) {
            throw new ApiException("Cannot recognise api response (" + response + ")");
        }

        return response.substring(3);
    }

    /**
     * Gets account's balance
     *
     * @return
     * @throws Exception
     */
    public double balance() throws Exception {
        String response = res("getbalance");
        return Double.parseDouble(response);
    }

    /**
     * Reports if captcha was solved correctly (sends `reportbad` or `reportgood` to `/res.php`)
     *
     * @param id
     * @param correct
     * @throws Exception
     */
    public void report(String id, boolean correct) throws Exception {
        Map params = new HashMap<>();
        params.put("id", id);

        if (correct) {
            params.put("action", "reportgood");
        } else {
            params.put("action", "reportbad");
        }

        res(params);
    }

    /**
     * Makes request to `/res.php`
     *
     * @param action
     * @return
     * @throws Exception
     */
    private String res(String action) throws Exception {
        Map params = new HashMap<>();
        params.put("action", action);
        return res(params);
    }

    /**
     * Makes request to `/res.php`
     *
     * @param params
     * @return
     * @throws Exception
     */
    private String res(Map params) throws Exception {
        params.put("key", apiKey);
        return apiClient.res(params);
    }

    /**
     * Attaches default parameters to request
     *
     * @param params
     */
    private void sendAttachDefaultParams(Map params) {
        params.put("key", apiKey);

        if (callback != null) {
            if (!params.containsKey("pingback")) {
                params.put("pingback", callback);
            } else if (params.get("pingback").length() == 0) {
                params.remove("pingback");
            }
        }

        lastCaptchaHasCallback = params.containsKey("pingback");

        if (softId != 0 && !params.containsKey("soft_id")) {
            params.put("soft_id", String.valueOf(softId));
        }
    }

    /**
     * Validates if files parameters are correct
     *
     * @param files
     * @throws ValidationException
     */
    private void validateFiles(Map files) throws ValidationException {
        for (Map.Entry entry : files.entrySet()) {
            File file = entry.getValue();

            if (!file.exists()) {
                throw new ValidationException("File not found: " + file.getAbsolutePath());
            }

            if (!file.isFile()) {
                throw new ValidationException("Resource is not a file: " + file.getAbsolutePath());
            }
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy