From 048fc726197d83eb7c0607cb9059c6111199d240 Mon Sep 17 00:00:00 2001 From: alperensert Date: Sun, 19 Dec 2021 23:40:40 +0300 Subject: [PATCH] Initial commit --- .github/workflows/maven.yml | 36 +++ .gitignore | 2 + LICENSE | 21 ++ pom.xml | 157 +++++++++++++ .../exceptions/CapmonsterException.java | 11 + .../capmonster_java/tasks/FunCaptchaTask.java | 126 +++++++++++ .../capmonster_java/tasks/GeeTestTask.java | 138 ++++++++++++ .../capmonster_java/tasks/HCaptchaTask.java | 168 ++++++++++++++ .../tasks/ImageToTextTask.java | 160 ++++++++++++++ .../tasks/RecaptchaV2Task.java | 160 ++++++++++++++ .../tasks/RecaptchaV3Task.java | 123 +++++++++++ .../capmonster_java/utilities/Client.java | 209 ++++++++++++++++++ .../capmonster_java/utilities/Cookies.java | 70 ++++++ .../capmonster_java/utilities/Proxy.java | 81 +++++++ .../utilities/RequestBuilder.java | 138 ++++++++++++ .../capmonster_java/utilities/UserAgent.java | 28 +++ .../capmonster_java/tasks/BaseTaskTest.java | 16 ++ .../tasks/FunCaptchaTaskTest.java | 48 ++++ .../tasks/HCaptchaTaskTest.java | 63 ++++++ .../tasks/RecaptchaV2TaskTest.java | 50 +++++ .../tasks/RecaptchaV3TaskTest.java | 38 ++++ 21 files changed, 1843 insertions(+) create mode 100644 .github/workflows/maven.yml create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 pom.xml create mode 100644 src/main/java/io/github/alperensert/capmonster_java/exceptions/CapmonsterException.java create mode 100644 src/main/java/io/github/alperensert/capmonster_java/tasks/FunCaptchaTask.java create mode 100644 src/main/java/io/github/alperensert/capmonster_java/tasks/GeeTestTask.java create mode 100644 src/main/java/io/github/alperensert/capmonster_java/tasks/HCaptchaTask.java create mode 100644 src/main/java/io/github/alperensert/capmonster_java/tasks/ImageToTextTask.java create mode 100644 src/main/java/io/github/alperensert/capmonster_java/tasks/RecaptchaV2Task.java create mode 100644 src/main/java/io/github/alperensert/capmonster_java/tasks/RecaptchaV3Task.java create mode 100644 src/main/java/io/github/alperensert/capmonster_java/utilities/Client.java create mode 100644 src/main/java/io/github/alperensert/capmonster_java/utilities/Cookies.java create mode 100644 src/main/java/io/github/alperensert/capmonster_java/utilities/Proxy.java create mode 100644 src/main/java/io/github/alperensert/capmonster_java/utilities/RequestBuilder.java create mode 100644 src/main/java/io/github/alperensert/capmonster_java/utilities/UserAgent.java create mode 100644 src/test/java/io/github/alperensert/capmonster_java/tasks/BaseTaskTest.java create mode 100644 src/test/java/io/github/alperensert/capmonster_java/tasks/FunCaptchaTaskTest.java create mode 100644 src/test/java/io/github/alperensert/capmonster_java/tasks/HCaptchaTaskTest.java create mode 100644 src/test/java/io/github/alperensert/capmonster_java/tasks/RecaptchaV2TaskTest.java create mode 100644 src/test/java/io/github/alperensert/capmonster_java/tasks/RecaptchaV3TaskTest.java diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml new file mode 100644 index 0000000..f40dc2c --- /dev/null +++ b/.github/workflows/maven.yml @@ -0,0 +1,36 @@ +name: OSSRH Release 📦 + +on: + release: + types: [published] + +jobs: + publish: + name: Publish to Maven Central + runs-on: ubuntu-20.04 + steps: + - uses: actions/checkout@v2 + - name: Set up Maven Central Repository + uses: actions/setup-java@v2 + with: + java-version: '8' + distribution: 'adopt' + server-id: ossrh + server-username: MAVEN_USERNAME + server-password: MAVEN_PASSWORD + + - name: Install GPG secret key + run: echo "${{ secrets.GPG_PRIVATE_KEY }}" | gpg --batch --import + + - name: Publish to Maven Central + run: | + mvn \ + --no-transfer-progress \ + --batch-mode \ + -Dgpg.passphrase=${{ secrets.GPG_PASSPHRASE }} \ + -DskipTests \ + -Prelease \ + deploy + env: + MAVEN_USERNAME: ${{ secrets.REPO_USERNAME }} + MAVEN_PASSWORD: ${{ secrets.REPO_PASSWORD }} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..981c582 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/.idea/ +/target/ \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..a9a469e --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..1cf2c19 --- /dev/null +++ b/pom.xml @@ -0,0 +1,157 @@ + + + 4.0.0 + + io.github.alperensert + capmonster_java + 1.3 + + capmonster_java + Capmonster.cloud package for Java + https://github.com/alperensert/capmonster_java + + + + MIT License + https://github.com/alperensert/capmonster_java/blob/master/LICENSE + repo + + + + + + Alperen Sert + mail@alperenn.com + https://github.com/alperensert + + + + + https://github.com/alperensert/capmonster_java.git + scm:git:git://github.com/alperensert/capmonster_java.git + scm:git:git@github.com:alperensert/capmonster_java.git + + + + + ossrh + Central Repository OSSRH + https://s01.oss.sonatype.org/content/repositories/snapshots + + + ossrh + https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/ + + + + + UTF-8 + 8 + 8 + + + + + org.json + json + 20211205 + + + junit + junit + 4.13.2 + test + + + org.junit.jupiter + junit-jupiter + 5.8.2 + test + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.22.2 + + + + + + + release + + + release + + + + + + org.apache.maven.plugins + maven-source-plugin + 3.2.1 + + + attach-sources + + jar + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.2.0 + + + attach-javadocs + + jar + + + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.6 + + + sign-artifacts + verify + + sign + + + + --pinentry-mode + loopback + + + + + + + org.sonatype.plugins + nexus-staging-maven-plugin + 1.6.8 + true + + ossrh + https://s01.oss.sonatype.org/ + true + + + + + + + + \ No newline at end of file diff --git a/src/main/java/io/github/alperensert/capmonster_java/exceptions/CapmonsterException.java b/src/main/java/io/github/alperensert/capmonster_java/exceptions/CapmonsterException.java new file mode 100644 index 0000000..4a63e86 --- /dev/null +++ b/src/main/java/io/github/alperensert/capmonster_java/exceptions/CapmonsterException.java @@ -0,0 +1,11 @@ +package io.github.alperensert.capmonster_java.exceptions; + +public class CapmonsterException extends RuntimeException { + public String CODE; + public String DESCRIPTION; + public CapmonsterException(String code, String description) { + super("[" + code + "] " + description); + this.DESCRIPTION = description; + this.CODE = code; + } +} \ No newline at end of file diff --git a/src/main/java/io/github/alperensert/capmonster_java/tasks/FunCaptchaTask.java b/src/main/java/io/github/alperensert/capmonster_java/tasks/FunCaptchaTask.java new file mode 100644 index 0000000..67062c3 --- /dev/null +++ b/src/main/java/io/github/alperensert/capmonster_java/tasks/FunCaptchaTask.java @@ -0,0 +1,126 @@ +package io.github.alperensert.capmonster_java.tasks; + +import io.github.alperensert.capmonster_java.utilities.*; +import org.json.JSONObject; + +/** + * This class contains everything for FunCaptcha solving task + * @see Client + * @since 1.1 + */ +public class FunCaptchaTask extends Client { + /** + * @param apiKey Your unique key for solving captchas + */ + public FunCaptchaTask(String apiKey) { + super(apiKey); + } + + /** + * Create Funcaptcha task easily with task builder + * @param taskBuilder TaskBuilder + * @return Created task's ID + */ + public int createTask(TaskBuilder taskBuilder) { + RequestBuilder request = new RequestBuilder(this.CLIENT_KEY, "FunCaptchaTask") + .addTask("websiteURL", taskBuilder.websiteUrl) + .addTask("websitePublicKey", taskBuilder.websitePublicKey) + .addTask("funcaptchaApiJSSubdomain", taskBuilder.apiJSSubdomain) + .addUserAgent(taskBuilder.userAgent) + .addProxy(taskBuilder.proxy) + .addCookies(taskBuilder.cookies); + JSONObject t = makeRequest("createTask", request.build()); + return t.getInt("taskId"); + } + + public static class TaskBuilder { + /** + * Address of a webpage with FunCaptcha + */ + private final String websiteUrl; + /** + * FunCaptcha website key. Mostly you can find in funcaptcha div + *
{@code
+         *  
+ * }
+ */ + private final String websitePublicKey; + /** + * A special subdomain of funcaptcha.com, from which the JS captcha widget should be loaded. + * Most FunCaptcha installations work from shared domains, so this option is only needed in certain rare cases. + */ + private String apiJSSubdomain; + /** + * @see Proxy + */ + private Proxy proxy; + /** + * @see UserAgent + */ + private UserAgent userAgent; + /** + * @see Cookies + */ + private Cookies cookies; + + /** + * @param websiteUrl Website URL + * @param websitePublicKey Website public key + * @see #websiteUrl + * @see #websitePublicKey + * @since 1.2 + */ + public TaskBuilder(String websiteUrl, String websitePublicKey) { + this.websiteUrl = websiteUrl; + this.websitePublicKey = websitePublicKey; + } + + /** + * @param subdomain API javascript subdomain + * @see #apiJSSubdomain + * @return TaskBuilder + */ + public TaskBuilder setApiSubdomain(String subdomain) { + this.apiJSSubdomain = subdomain; + return this; + } + + /** + * Additional cookies which we must use during interaction with target page or Google. + * @param cookies Cookies + * @see Cookies + * @return TaskBuilder + * @since 1.2 + */ + public TaskBuilder setCookies(Cookies cookies) { + this.cookies = cookies; + return this; + } + + /** + * Set proxy for the task. + * If the proxy is authorized by IP, then be sure to add 116.203.55.208 to the white list. + * @param proxy Proxy + * @see Proxy + * @return TaskBuilder + * @since 1.2 + */ + public TaskBuilder setProxy(Proxy proxy) { + if (proxy != null) this.proxy = proxy; + return this; + } + + /** + * Browser's User-Agent which is used in emulation. It is required that you use a signature of a modern browser, + * otherwise Google will ask you to "update your browser" + * @param ua UserAgent + * @see UserAgent + * @return TaskBuilder + * @since 1.2 + */ + public TaskBuilder setUserAgent(UserAgent ua) { + this.userAgent = ua; + return this; + } + } +} diff --git a/src/main/java/io/github/alperensert/capmonster_java/tasks/GeeTestTask.java b/src/main/java/io/github/alperensert/capmonster_java/tasks/GeeTestTask.java new file mode 100644 index 0000000..829a68a --- /dev/null +++ b/src/main/java/io/github/alperensert/capmonster_java/tasks/GeeTestTask.java @@ -0,0 +1,138 @@ +package io.github.alperensert.capmonster_java.tasks; + +import io.github.alperensert.capmonster_java.utilities.Client; +import io.github.alperensert.capmonster_java.utilities.Proxy; +import io.github.alperensert.capmonster_java.utilities.RequestBuilder; +import io.github.alperensert.capmonster_java.utilities.UserAgent; +import org.json.JSONObject; + +/** + * This class contains everything for GeeTest solving task + * @see Client + * @since 1.2 + */ +public class GeeTestTask extends Client { + /** + * @param apiKey Your unique key for solving captchas + */ + public GeeTestTask(String apiKey) { + super(apiKey); + } + + /** + * Create GeeTest task easily with task builder + * @param taskBuilder TaskBuilder + * @see TaskBuilder + * @return Created task's ID + */ + public int createTask(TaskBuilder taskBuilder) { + RequestBuilder request = new RequestBuilder(this.CLIENT_KEY, "GeeTestTask") + .addTask("websiteURL", taskBuilder.websiteUrl) + .addTask("gt", taskBuilder.gt) + .addTask("challenge", taskBuilder.challenge) + .addTask("geetestApiServerSubdomain", taskBuilder.apiServerSubdomain) + .addTask("geetestGetLib", taskBuilder.getLib) + .addProxy(taskBuilder.proxy) + .addUserAgent(taskBuilder.userAgent); + JSONObject t = makeRequest("createTask", request.build()); + return t.getInt("taskId"); + } + + public static class TaskBuilder { + /** + * Address of the page on which the captcha is recognized + */ + private final String websiteUrl; + /** + * The GeeTest identifier key for the domain. Static value, rarely updated. + */ + private final String gt; + /** + * A dynamic key. + * Each time our API is called, we need to get a new key value. + * If the captcha is loaded on the page, then the challenge value is no longer valid. + * It is necessary to examine the requests and find the one in which this value is returned and, + * before each creation of the recognition task, execute this request and parse the challenge from it. + */ + private final String challenge; + /** + * May be required for some sites. + */ + private String apiServerSubdomain; + /** + * Send JSON as a string. + */ + private String getLib; + /** + * @see UserAgent + */ + private UserAgent userAgent; + /** + * @see Proxy + */ + private Proxy proxy; + + /** + * @param websiteUrl WebsiteUrl + * @param gt GT + * @param challenge Challenge + * @see #challenge + * @see #websiteUrl + * @see #gt + * @since 1.2 + */ + public TaskBuilder(String websiteUrl, String gt, String challenge) { + this.websiteUrl = websiteUrl; + this.gt = gt; + this.challenge = challenge; + } + + /** + * @param subdomain Api server subdomain + * @see #apiServerSubdomain + * @return TaskBuilder + * @since 1.2 + */ + public TaskBuilder setServerSubdomain(String subdomain) { + this.apiServerSubdomain = subdomain; + return this; + } + + /** + * @param lib getLib + * @see #getLib + * @return TaskBuilder + * @since 1.2 + */ + public TaskBuilder setGetLib(String lib) { + this.getLib = lib; + return this; + } + + /** + * Set proxy for the task. + * If the proxy is authorized by IP, then be sure to add 116.203.55.208 to the white list. + * @param proxy Proxy + * @see Proxy + * @return TaskBuilder + * @since 1.2 + */ + public TaskBuilder setProxy(Proxy proxy) { + if (proxy != null) this.proxy = proxy; + return this; + } + + /** + * Browser's User-Agent which is used in emulation. It is required that you use a signature of a modern browser, + * otherwise Google will ask you to "update your browser" + * @param ua UserAgent + * @see UserAgent + * @return TaskBuilder + * @since 1.2 + */ + public TaskBuilder setUserAgent(UserAgent ua) { + this.userAgent = ua; + return this; + } + } +} diff --git a/src/main/java/io/github/alperensert/capmonster_java/tasks/HCaptchaTask.java b/src/main/java/io/github/alperensert/capmonster_java/tasks/HCaptchaTask.java new file mode 100644 index 0000000..b00cdd6 --- /dev/null +++ b/src/main/java/io/github/alperensert/capmonster_java/tasks/HCaptchaTask.java @@ -0,0 +1,168 @@ +package io.github.alperensert.capmonster_java.tasks; + +import io.github.alperensert.capmonster_java.utilities.*; +import org.json.JSONObject; + +/** + * This class contains everything for HCaptcha solving task + * @see Client + * @since 1.1 + */ +public class HCaptchaTask extends Client { + /** + * @param apiKey Your unique key for solving captchas + */ + public HCaptchaTask(String apiKey) { + super(apiKey); + } + + /** + * Create HCaptcha task easily with task builder + * @param taskBuilder TaskBuilder + * @see TaskBuilder + * @return Created task's ID + */ + public int createTask(TaskBuilder taskBuilder) { + RequestBuilder request = new RequestBuilder(this.CLIENT_KEY, "HCaptchaTask") + .addTask("websiteURL", taskBuilder.websiteUrl) + .addTask("websiteKey", taskBuilder.websiteKey) + .addTask("isInvisible", taskBuilder.isInvisible) + .addTask("data", taskBuilder.customData) + .addUserAgent(taskBuilder.userAgent) + .addCookies(taskBuilder.cookies) + .addProxy(taskBuilder.proxy) + .addNoCache(taskBuilder.cache); + JSONObject t = makeRequest("createTask", request.build()); + return t.getInt("taskId"); + } + + /** + * Task Builder helps you while creating credentials about task + * @since 1.2 + */ + public static class TaskBuilder { + /** + * Address of a webpage with hCaptcha + */ + private final String websiteUrl; + /** + * hCaptcha website key. + */ + private final String websiteKey; + /** + * Use true for invisible version of hcaptcha + */ + private boolean isInvisible = false; + /** + * Custom data that is used in some implementations of hCaptcha, mostly with isInvisible=true. + * In most cases you see it as rqdata inside network requests.
+ *

IMPORTANT!

+ * You must set userAgent if you submit captcha with data parameter. The value should match the + * User-Agent you use when interacting with the target website. + */ + private String customData; + /** + * @see Cookies + */ + private Cookies cookies; + /** + * @see UserAgent + */ + private UserAgent userAgent; + /** + * @see Proxy + */ + private Proxy proxy; + /** + * If you don't want cached results or experiencing any of the followings, this must be true. + * + */ + private boolean cache = false; + + /** + * @param websiteUrl WebsiteUrl + * @param websiteKey WebsiteKey + * @see #websiteUrl + * @see #websiteKey + * @since 1.2 + */ + public TaskBuilder(String websiteUrl, String websiteKey) { + this.websiteUrl = websiteUrl; + this.websiteKey = websiteKey; + } + + /** + * @param visible is Invisible + * @return TaskBuilder + * @see #isInvisible + * @since 1.2 + */ + public TaskBuilder setVisibility(boolean visible) { + this.isInvisible = visible; + return this; + } + + /** + * @param data customData + * @see #customData + * @since 1.2 + * @return TaskBuilder + */ + public TaskBuilder setCustomData(String data) { + this.customData = data; + return this; + } + + /** + * Browser's User-Agent which is used in emulation. It is required that you use a signature of a modern browser, + * otherwise Google will ask you to "update your browser" + * @param ua UserAgent + * @see UserAgent + * @return TaskBuilder + * @since 1.2 + */ + public TaskBuilder setUserAgent(UserAgent ua) { + this.userAgent = ua; + return this; + } + + /** + * Additional cookies which we must use during interaction with target page or Google. + * @param cookies Cookies + * @return TaskBuilder + * @see Cookies + * @since 1.2 + */ + public TaskBuilder setCookies(Cookies cookies) { + this.cookies = cookies; + return this; + } + + /** + * Set proxy for the task. + * If the proxy is authorized by IP, then be sure to add 116.203.55.208 to the white list. + * @param proxy Proxy + * @see Proxy + * @return TaskBuilder + * @since 1.2 + */ + public TaskBuilder setProxy(Proxy proxy) { + if (proxy != null) this.proxy = proxy; + return this; + } + + /** + * @see #cache + * @param cache . + * @return TaskBuilder + * @since 1.2 + */ + public TaskBuilder setCache(boolean cache) { + this.cache = cache; + return this; + } + } +} diff --git a/src/main/java/io/github/alperensert/capmonster_java/tasks/ImageToTextTask.java b/src/main/java/io/github/alperensert/capmonster_java/tasks/ImageToTextTask.java new file mode 100644 index 0000000..ec55839 --- /dev/null +++ b/src/main/java/io/github/alperensert/capmonster_java/tasks/ImageToTextTask.java @@ -0,0 +1,160 @@ +package io.github.alperensert.capmonster_java.tasks; + +import io.github.alperensert.capmonster_java.utilities.Client; +import io.github.alperensert.capmonster_java.utilities.RequestBuilder; +import org.json.JSONObject; + +/** + * Solve Image captchas + * @see Client + * @since 1.1 + */ +public class ImageToTextTask extends Client { + /** + * @param clientKey Unique key for solving captchas. a.k.a api key + * @since 1.1 + */ + public ImageToTextTask(String clientKey) { super(clientKey); } + + /** + * Create ImageToText task easily with using task builder + * @param taskBuilder TaskBuilder + * @see TaskBuilder + * @return Created task's ID + * @since 1.1 + */ + public int createTask(TaskBuilder taskBuilder) { + RequestBuilder request = new RequestBuilder(this.CLIENT_KEY, "ImageToTextTask") + .addTask("body", taskBuilder.base64EncodedImage) + .addTask("CapMonsterModule", taskBuilder.module) + .addTask("recognizingThreshold", taskBuilder.recognizingThreshold) + .addTask("Case", taskBuilder._case) + .addTask("numeric", taskBuilder.numeric) + .addTask("math", taskBuilder.math); + JSONObject t = makeRequest("createTask", request.build()); + return t.getInt("taskId"); + } + + /** + * Task builder helps you while creating credentials about task + * @since 1.2 + */ + public static class TaskBuilder { + /** + * Image's body encoded in base64. Make sure to send it without line breaks and as string. + * @see java.util.Base64 + */ + private final String base64EncodedImage; + /** + * Name of the recognizing module. + *
All available modules: + * + */ + private String module; + /** + * Required trust value of captcha result. Must between 0 and 100.

+ * For example, if you set this value to 90 and the system solved the captcha with confidence of 80, + * then the money for the solution will not be charged. + */ + private int recognizingThreshold; + /** + * Whether to consider case when deciding or not + */ + private boolean _case; + /** + * Default value is 0

+ * Pass 1 if the captcha consists of numbers only + */ + private int numeric; + /** + * Captcha requires a mathematical action or not + *

+ * If this is true, result will be mathematical action's result (e.g 2+5=7) return value will 7 + */ + private boolean math; + + + /** + * @param base64EncodedImage base64EncodedImage + * @see #base64EncodedImage + * @since 1.2 + */ + public TaskBuilder(String base64EncodedImage) { + this.base64EncodedImage = base64EncodedImage; + } + + /** + * Set module name of task + * @param name module + * @see #module + * @return TaskBuilder + * @since 1.2 + */ + public TaskBuilder setModuleName(String name) { + this.module = name; + return this; + } + + /** + * Set recognizing threshold + * @param value recognizingThreshold + * @see #recognizingThreshold + * @return TaskBuilder + * @since 1.2 + */ + public TaskBuilder setThreshold(int value) { + this.recognizingThreshold = value; + return this; + } + + /** + * @param _case _case + * @return TaskBuilder + * @see #_case + * @since 1.2 + */ + public TaskBuilder setCase(boolean _case) { + this._case = _case; + return this; + } + + /** + * If captcha only contains number, it's a numeric captcha. + * @see #numeric + * @param numeric numeric + * @return TaskBuilder + * @since 1.2 + */ + public TaskBuilder isNumeric(boolean numeric) { + if (numeric) this.numeric = 1; + return this; + } + + /** + * @param math Contains math or not + * @return TaskBuilder} + * @see #math + * @since 1.2 + */ + public TaskBuilder setMath(boolean math) { + this.math = math; + return this; + } + } +} diff --git a/src/main/java/io/github/alperensert/capmonster_java/tasks/RecaptchaV2Task.java b/src/main/java/io/github/alperensert/capmonster_java/tasks/RecaptchaV2Task.java new file mode 100644 index 0000000..dbe2c57 --- /dev/null +++ b/src/main/java/io/github/alperensert/capmonster_java/tasks/RecaptchaV2Task.java @@ -0,0 +1,160 @@ +package io.github.alperensert.capmonster_java.tasks; + +import io.github.alperensert.capmonster_java.utilities.*; +import org.json.JSONObject; + +/** + * This class contains everything for Google ReCaptcha2 solving task. + * @see Client + * @since 1.1 + */ +public class RecaptchaV2Task extends Client { + /** + * @param clientKey #CLIENT_KEY} + * @since 1.1 + */ + public RecaptchaV2Task(String clientKey) { + super(clientKey); + } + + /** + * Create RecaptchaV2 Task easily with using task builder + * @param taskBuilder TaskBuilder + * @see TaskBuilder + * @return Created task's ID + * @since 1.1 + */ + public int createTask(TaskBuilder taskBuilder) { + RequestBuilder request = new RequestBuilder(this.CLIENT_KEY, "NoCaptchaTask") + .addTask("websiteURL", taskBuilder.websiteUrl) + .addTask("websiteKey", taskBuilder.websiteKey) + .addNoCache(taskBuilder.cache) + .addCookies(taskBuilder.cookies) + .addUserAgent(taskBuilder.userAgent) + .addTask("recaptchaDataSValue", taskBuilder.recaptchaSValue) + .addProxy(taskBuilder.proxy); + JSONObject t = makeRequest("createTask", request.build()); + return t.getInt("taskId"); + } + + /** + * Task Builder helps you while creating credentials about task + * @since 1.2 + */ + public static class TaskBuilder { + /** + * Address of a webpage with Google ReCaptcha + */ + private final String websiteUrl; + /** + * Recaptcha website key. Mostly you can find it in g-recaptcha div. + *
{@code
+         *  
+ * }
+ */ + private final String websiteKey; + /** + * @see Proxy + */ + private Proxy proxy; + /** + * @see UserAgent + */ + private UserAgent userAgent; + /** + * @see Cookies + */ + private Cookies cookies; + /** + * Some custom implementations may contain additional "data-s" parameter in ReCaptcha2 div, + * which is in fact a one-time token and must be grabbed every time you want to solve a ReCaptcha2.

+ * Mostly you can find it in g-recaptcha div + *
{@code
+         * 
+ * }
+ */ + private String recaptchaSValue; + /** + * If you don't want cached results or experiencing any of the followings, this must be true. + * + */ + private boolean cache = false; + + /** + * @param websiteUrl WebsiteUrl + * @param websiteKey WebsiteKey + * @see #websiteUrl + * @see #websiteKey + * @since 1.2 + */ + public TaskBuilder(String websiteUrl, String websiteKey) { + this.websiteKey = websiteKey; + this.websiteUrl = websiteUrl; + } + + /** + * Additional cookies which we must use during interaction with target page or Google. + * @param cookies Cookies + * @see Cookies + * @return TaskBuilder + * @since 1.2 + */ + public TaskBuilder setCookies(Cookies cookies) { + this.cookies = cookies; + return this; + } + + /** + * Set proxy for the task. + * If the proxy is authorized by IP, then be sure to add 116.203.55.208 to the white list. + * @param proxy Proxy + * @see Proxy + * @return TaskBuilder + * @since 1.2 + */ + public TaskBuilder setProxy(Proxy proxy) { + if (proxy != null) this.proxy = proxy; + return this; + } + + /** + * Browser's User-Agent which is used in emulation. It is required that you use a signature of a modern browser, + * otherwise Google will ask you to "update your browser" + * @param ua UserAgent + * @see UserAgent + * @return TaskBuilder + * @since 1.2 + */ + public TaskBuilder setUserAgent(UserAgent ua) { + this.userAgent = ua; + return this; + } + + /** + * Some custom implementations may contain additional "data-s" parameter in ReCaptcha2 div, + * which is in fact a one-time token and must be grabbed every time you want to solve a ReCaptcha2. + * @see #recaptchaSValue + * @param value . + * @return TaskBuilder + * @since 1.2 + */ + public TaskBuilder setRecaptchaSValue(String value) { + this.recaptchaSValue = value; + return this; + } + + /** + * @see #cache + * @param cache Cached results or not + * @return TaskBuilder + * @since 1.2 + */ + public TaskBuilder setCache(boolean cache) { + this.cache = cache; + return this; + } + } +} diff --git a/src/main/java/io/github/alperensert/capmonster_java/tasks/RecaptchaV3Task.java b/src/main/java/io/github/alperensert/capmonster_java/tasks/RecaptchaV3Task.java new file mode 100644 index 0000000..ff859a7 --- /dev/null +++ b/src/main/java/io/github/alperensert/capmonster_java/tasks/RecaptchaV3Task.java @@ -0,0 +1,123 @@ +package io.github.alperensert.capmonster_java.tasks; + +import io.github.alperensert.capmonster_java.utilities.Client; +import io.github.alperensert.capmonster_java.utilities.RequestBuilder; +import org.json.JSONObject; + +/** + * This class contains everything for Google ReCaptcha3 solving task. + * @see Client + * @since 1.1 + */ +public class RecaptchaV3Task extends Client { + + /** + * @param clientKey Unique key for solving captchas + * @since 1.1 + */ + public RecaptchaV3Task(String clientKey) { + super(clientKey); + } + + /** + * Create RecaptchaV3 Task easily with using task builder + * @param taskBuilder TaskBuilder + * @see TaskBuilder + * @return Created task's ID + * @since 1.1 + */ + public int createTask(TaskBuilder taskBuilder) { + RequestBuilder request = new RequestBuilder(this.CLIENT_KEY, "RecaptchaV3TaskProxyless") + .addTask("websiteURL", taskBuilder.websiteUrl) + .addTask("websiteKey", taskBuilder.websiteKey) + .addNoCache(taskBuilder.cache) + .addTask("minScore", taskBuilder.minimumScore) + .addTask("pageAction", taskBuilder.pageAction); + JSONObject t = makeRequest("createTask", request.build()); + return t.getInt("taskId"); + } + + /** + * Task Builder helps you while creating credentials + * @since 1.2 + */ + public static class TaskBuilder { + /** + * Address of a webpage with Google ReCaptcha + */ + private final String websiteUrl; + /** + * Recaptcha website key. Mostly you can find it in render URL + *
+         * https://www.google.com/recaptcha/api.js?render="THAT_ONE"
+         * 
+ */ + private final String websiteKey; + /** + * It's like trust value. Must be 0.1 and 0.9 + */ + private double minimumScore; + /** + * Widget action value. Website owner defines what user is doing on the page through this parameter. + *

Default value is verify.

Example: + *
grecaptcha.execute('site_key', {action:'verify'})
+ */ + private String pageAction; + /** + * If you don't want cached results or experiencing any of the followings, this must be true. + * + */ + private boolean cache; + + /** + * @param websiteUrl WebsiteUrl + * @param websiteKey WebsiteKey + * @see #websiteKey + * @see #websiteUrl + * @since 1.2 + */ + public TaskBuilder(String websiteUrl, String websiteKey) { + this.websiteUrl = websiteUrl; + this.websiteKey = websiteKey; + } + + /** + * Set minimum score + * @param score minimumScore + * @see #minimumScore + * @return TaskBuilder + * @since 1.2 + */ + public TaskBuilder setMinScore(double score) { + if (0.1 <= score && score <= 0.9) { + this.minimumScore = score; + return this; + } throw new IllegalArgumentException("Minimum score must between 0.1 and 0.9"); + } + + /** + * @see #cache + * @param cache . + * @return TaskBuilder + * @since 1.2 + */ + public TaskBuilder setCache(boolean cache) { + this.cache = cache; + return this; + } + + /** + * @see #pageAction + * @param action . + * @return TaskBuilder + * @since 1.2 + */ + public TaskBuilder setPageAction(String action) { + this.pageAction = action; + return this; + } + } +} diff --git a/src/main/java/io/github/alperensert/capmonster_java/utilities/Client.java b/src/main/java/io/github/alperensert/capmonster_java/utilities/Client.java new file mode 100644 index 0000000..1f3a309 --- /dev/null +++ b/src/main/java/io/github/alperensert/capmonster_java/utilities/Client.java @@ -0,0 +1,209 @@ +package io.github.alperensert.capmonster_java.utilities; + +import io.github.alperensert.capmonster_java.exceptions.CapmonsterException; +import org.json.JSONObject; + +import javax.net.ssl.HttpsURLConnection; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.util.Objects; +import java.util.concurrent.TimeUnit; + +/** + * Abstract class for tasks + * @since 1.2 + */ +public abstract class Client { + /** + * Default time for JoinTaskResult method + * @see #joinTaskResult(int, int) + */ + private static final int maximumTime = 120; + /** + * Balance url address for api + * @see #getBalance() + */ + private static final String balanceUrl = "/getBalance"; + /** + * Task result url address for api + * @see #getTaskResult(int) + */ + private static final String taskResultUrl = "/getTaskResult"; + /** + * Task create url address for api + */ + private static final String createTaskUrl = "/createTask"; + /** + * Base host url for api + */ + private static final String hostUrl = "https://api.capmonster.cloud"; + /** + * Unique key of your account + */ + protected final String CLIENT_KEY; + + /** + * @param apiKey Your unique key for solving captchas + */ + public Client(String apiKey) { CLIENT_KEY = apiKey; } + + /** + * Get account's balance + * @return account balance + * @since 1.2 + */ + public int getBalance() { + JSONObject data = new JSONObject(); + data.put("clientKey", CLIENT_KEY); + return (int) makeRequest("getBalance", data).get("balance"); + } + + /** + * Get task result + * @see #joinTaskResult(int) + * @param taskId ID which was obtained in createTask method + * @return Task's result if is ready + * @since 1.2 + */ + public JSONObject getTaskResult(int taskId) { + JSONObject data = new JSONObject(); + data.put("clientKey", CLIENT_KEY); + data.put("taskId", taskId); + JSONObject result = makeRequest("getTaskResult", data); + boolean isReady = isReady(result); + return isReady ? (JSONObject) result.get("solution") : null; + } + + /** + * Check the task until successfully solve + * @param taskId ID which was obtained in createTask method + * @return Task's result when is ready + * @throws CapmonsterException Maximum time is exceed + * @throws InterruptedException . + * @since 1.2 + */ + public JSONObject joinTaskResult(int taskId) throws InterruptedException { + for (int i = 0; i <= maximumTime + 1; i += 2) { + JSONObject result = getTaskResult(taskId); + if (result != null) return result; + else TimeUnit.SECONDS.sleep(2); + } + throw new CapmonsterException("ERROR_MAXIMUM_TIME_EXCEED", "Maximum time is exceed."); + } + + /** + * Check the task until successfully solve + * @param taskId ID which was obtained in createTask method + * @param maximumTime How long will check + * @return Task's result when is ready + * @throws CapmonsterException Maximum time is exceed + * @throws InterruptedException . + * @since 1.2 + */ + public JSONObject joinTaskResult(int taskId, int maximumTime) throws InterruptedException { + for (int i = 0; i <= maximumTime + 1; i += 2) { + JSONObject result = getTaskResult(taskId); + if (result != null) return result; + else TimeUnit.SECONDS.sleep(2); + } + throw new CapmonsterException("ERROR_MAXIMUM_TIME_EXCEED", "Maximum time is exceed."); + } + + /** + * Check response has an error message or not + * @param response Response from api + * @since 1.2 + */ + private static void checkResponse(String response) { + JSONObject responseJson = new JSONObject(response); + if (responseJson.get("errorId") != null && (int)responseJson.get("errorId") == 0) { + return; + } + if ((int) responseJson.get("errorId") != 0) { + throw new CapmonsterException((String) responseJson.get("errorCode"), (String) responseJson.get("errorDescription")); + } else { + throw new CapmonsterException("[ERROR CODE: HTTP_ERROR]", "Sometimes can be happen if capmonster servers there is too much intensity"); + } + } + + /** + * Check task is ready or not + * @param response Response from api + * @return ready or not + * @since 1.2 + */ + private static boolean isReady(JSONObject response) { + String status = response.get("status").toString(); + + if (Objects.equals(status, "processing")) { + return false; + } else if (Objects.equals(status, "ready")) { + return true; + } else { + throw new CapmonsterException((String) response.get("errorCode"), (String) response.get("errorDescription")); + } + } + + /** + * Kinda request helper + * @param method Request's method like getBalance or createTask + * @param data Request data + * @return Response from api + * @since 1.2 + */ + protected JSONObject makeRequest(String method, JSONObject data) { + JSONObject response = null; + if (Objects.equals(method, "getBalance")) { + method = balanceUrl; + } else if (Objects.equals(method, "getTaskResult")) { + method = taskResultUrl; + } else if (Objects.equals(method, "createTask")) { + method = createTaskUrl; + data.put("softId", 30); + } + try { + response = requestHandler(hostUrl + method, data); + checkResponse(response.toString()); + } catch (IOException e) { + e.printStackTrace(); + } + return response; + } + + /** + * Handle with requests + * @param url Request URL + * @param data Request data + * @return Response from api + * @throws IOException # + * @since 1.2 + */ + private static JSONObject requestHandler(String url, JSONObject data) throws IOException { + URL parsedUrl = new URL(url); + HttpsURLConnection connection = (HttpsURLConnection)parsedUrl.openConnection(); + + connection.setRequestMethod("POST"); + connection.setRequestProperty("Connection-Type", "application/json; utf-8"); + connection.setRequestProperty("Accept", "application/json"); + connection.setDoOutput(true); + + try(OutputStream os = connection.getOutputStream()) { + byte[] input = data.toString().getBytes(StandardCharsets.UTF_8); + os.write(input, 0, input.length); + } + + try(BufferedReader br = new BufferedReader( + new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8))) { + StringBuilder response = new StringBuilder(); + String responseLine; + while ((responseLine = br.readLine()) != null) { + response.append(responseLine.trim()); + } + return new JSONObject(response.toString()); + } + } +} diff --git a/src/main/java/io/github/alperensert/capmonster_java/utilities/Cookies.java b/src/main/java/io/github/alperensert/capmonster_java/utilities/Cookies.java new file mode 100644 index 0000000..f9f0ae9 --- /dev/null +++ b/src/main/java/io/github/alperensert/capmonster_java/utilities/Cookies.java @@ -0,0 +1,70 @@ +package io.github.alperensert.capmonster_java.utilities; + +import org.json.JSONObject; +import java.io.Serializable; +import java.util.List; + +/** + * Cookies is the right way of creating cookies object for using in Tasks.
+ * Basically, Cookies can creatable from JSONObject, Serializable List or + * plain strings.

+ * String format must be like this: + *
+ * {@code
+ * String cookies = "cookiename1=cookievalue1;cookiename2=cookievalue2";
+ * }
+ * 
+ * @since 1.2 + */ +public class Cookies { + /** + * String cookies holder + */ + private final String cookies; + + /** + * Create cookies from string

+ * An string example available in class document, for information see Cookies + * @see Cookies + * @param cookies Cookies + * @since 1.2 + */ + public Cookies(String cookies) { + this.cookies = cookies; + } + + /** + * Create cookies from JSONObject + * @param cookies Cookies + * @since 1.2 + */ + public Cookies(JSONObject cookies) { + String strCookies = ""; + for (String key : cookies.keySet()) { + String value = (String) cookies.get(key); + strCookies = strCookies.concat(key + "=" + value + ";"); + } + this.cookies = strCookies; + } + + /** + * Create cookies from Serializable List + * @param cookies Cookies + * @since 1.2 + */ + public Cookies(List cookies) { + if (cookies.size() % 2 != 0) throw new Error("Array cookies length must be even numbers"); + String strCookies = ""; + for (Serializable value : cookies) { + strCookies = cookies.indexOf(value) % 2 == 0 ? strCookies.concat(value + "=") : strCookies.concat(value + ";"); + } + this.cookies = strCookies; + } + + /** + * Get cookies + * @return Cookies as string + * @since 1.2 + */ + public String get() { return this.cookies; } +} diff --git a/src/main/java/io/github/alperensert/capmonster_java/utilities/Proxy.java b/src/main/java/io/github/alperensert/capmonster_java/utilities/Proxy.java new file mode 100644 index 0000000..2203d98 --- /dev/null +++ b/src/main/java/io/github/alperensert/capmonster_java/utilities/Proxy.java @@ -0,0 +1,81 @@ +package io.github.alperensert.capmonster_java.utilities; + + +/** + * Proxy class helps you easily create proxy credentials and use it in tasks. + * @since 1.2 + */ +public class Proxy { + /** + * Proxy's type. Can be one of them below: + * + * @since 1.2 + */ + String type; + /** + * Proxy's IP address. Can be IPv4 or IPv6. Not allowed to use: + * + */ + String address; + /** + * Proxy's port + */ + int port; + /** + * Login for proxy which requires authorization (basic) + */ + String username; + /** + * Proxy's password + */ + String password; + + /** + * Create a proxy class without basic authentication (username and password).

+ *

Attention!

+ * If the proxy is authorized by IP, then be sure to add 116.203.55.208 to the white list. + * @param type Proxy type + * @param address Proxy address + * @param port Proxy port + * @see #type + * @see #address + * @see #port + * @since 1.2 + */ + public Proxy(String type, String address, int port) { + this.type = type; + this.address = address; + this.port = port; + } + + /** + * Create a proxy class with basic authentication (username and password) + * @param type Proxy type + * @param address Proxy address + * @param port Proxy port + * @param username Proxy login username + * @param password Proxy password + * @see #type + * @see #address + * @see #port + * @see #username + * @see #password + * @since 1.2 + */ + public Proxy(String type, String address, int port, String username, String password) { + this.type = type; + this.address = address; + this.port = port; + this.username = username; + this.password = password; + } +} diff --git a/src/main/java/io/github/alperensert/capmonster_java/utilities/RequestBuilder.java b/src/main/java/io/github/alperensert/capmonster_java/utilities/RequestBuilder.java new file mode 100644 index 0000000..a98b1bf --- /dev/null +++ b/src/main/java/io/github/alperensert/capmonster_java/utilities/RequestBuilder.java @@ -0,0 +1,138 @@ +package io.github.alperensert.capmonster_java.utilities; + +import org.json.JSONObject; + +/** + * Request builder is helps to build JSON data for tasks + * @since 1.2 + */ +public class RequestBuilder { + /** + * "task" data holder + */ + private final JSONObject TASK = new JSONObject(); + /** + * Main data holder + */ + private final JSONObject DATA = new JSONObject(); + + /** + * Create a request from scratch + * @param clientKey Api key + * @param taskType Task type + * @since 1.2 + */ + public RequestBuilder(String clientKey, String taskType) { + DATA.put("clientKey", clientKey); + TASK.put("type", taskType); + } + + /** + * Build the request data + * @return JSON data + * @since 1.2 + */ + public JSONObject build() { + DATA.put("task", TASK); + return DATA; + } + + public RequestBuilder addTask(String key, String value) { + if (value != null) TASK.put(key, value); + return this; + } + + public RequestBuilder addTask(String key, int value) { + TASK.put(key, value); + return this; + } + + public RequestBuilder addTask(String key, boolean value) { + TASK.put(key, value); + return this; + } + + public RequestBuilder addTask(String key, double value) { + TASK.put(key, value); + return this; + } + + public RequestBuilder addData(String key, String value) { + if (value != null) DATA.put(key, value); + return this; + } + + public RequestBuilder addData(String key, int value) { + DATA.put(key, value); + return this; + } + + public RequestBuilder addData(String key, boolean value) { + DATA.put(key, value); + return this; + } + + public RequestBuilder addData(String key, double value) { + DATA.put(key, value); + return this; + } + + /** + * Add cookies automatically. If the cookies aren't defined, this method does nothing like expected + * @param cookies Cookies + * @return RequestBuilder + * @since 1.2 + */ + public RequestBuilder addCookies(Cookies cookies) { + if (cookies != null) TASK.put("cookies", cookies.get()); + return this; + } + + /** + * Add no cache property to task + * @param cache - + * @return RequestBuilder + * @since 1.2 + */ + public RequestBuilder addNoCache(boolean cache) { + if (cache) TASK.put("nocache", true); + return this; + } + + /** + * Add user agent property to task + * @param ua UserAgent + * @see UserAgent + * @return RequestBuilder + * @since 1.2 + */ + public RequestBuilder addUserAgent(UserAgent ua) { + if (ua != null) TASK.put("userAgent", ua.get()); + return this; + } + + /** + * Add proxy credentials to task + * @param proxy Proxy + * @see Proxy + * @return RequestBuilder + * @since 1.2 + */ + public RequestBuilder addProxy(Proxy proxy) { + if (proxy == null) { + TASK.put("type", TASK.getString("type") + "Proxyless"); + return this; + } + if (proxy.type != null && proxy.address != null && proxy.port != 0) { + TASK.put("proxyType", proxy.type); + TASK.put("proxyAddress", proxy.address); + TASK.put("proxyPort", proxy.port); + + if (proxy.username != null && proxy.password != null) { + TASK.put("proxyLogin", proxy.username); + TASK.put("proxyPassword", proxy.password); + } + } + return this; + } +} diff --git a/src/main/java/io/github/alperensert/capmonster_java/utilities/UserAgent.java b/src/main/java/io/github/alperensert/capmonster_java/utilities/UserAgent.java new file mode 100644 index 0000000..6d20b89 --- /dev/null +++ b/src/main/java/io/github/alperensert/capmonster_java/utilities/UserAgent.java @@ -0,0 +1,28 @@ +package io.github.alperensert.capmonster_java.utilities; + +/** + * User Agent class helps you easily create user agent property and use it in tasks + * @see What is an user agent? + * @since 1.2 + */ +public class UserAgent { + /** + * User agent holder + */ + private final String userAgent; + + /** + * Create user agent class to easily use in tasks + * @param userAgent User Agent + */ + public UserAgent(String userAgent) { + this.userAgent = userAgent; + } + + /** + * Get user agent + * @return User Agent + * @since 1.2 + */ + public String get() { return userAgent; } +} \ No newline at end of file diff --git a/src/test/java/io/github/alperensert/capmonster_java/tasks/BaseTaskTest.java b/src/test/java/io/github/alperensert/capmonster_java/tasks/BaseTaskTest.java new file mode 100644 index 0000000..6639138 --- /dev/null +++ b/src/test/java/io/github/alperensert/capmonster_java/tasks/BaseTaskTest.java @@ -0,0 +1,16 @@ +package io.github.alperensert.capmonster_java.tasks; + +import io.github.alperensert.capmonster_java.utilities.Cookies; +import io.github.alperensert.capmonster_java.utilities.Proxy; +import io.github.alperensert.capmonster_java.utilities.UserAgent; + +public abstract class BaseTaskTest { + final Cookies cookies = new Cookies("cookiename1=cookievalue1;cookiename2=cookievalue2"); + final UserAgent userAgent = new UserAgent(System.getenv("USER_AGENT")); + final String[] proxyString = System.getenv("PROXY").split(",", -1); + final Proxy proxy = new Proxy(proxyString[0], proxyString[1], Integer.parseInt(proxyString[2]), + proxyString[3], proxyString[4]); + int taskId; + final String[] acceptable_errors = new String[]{"ERROR_CAPTCHA_UNSOLVABLE", "ERROR_MAXIMUM_TIME_EXCEED", + "ERROR_NO_SLOT_AVAILABLE"}; +} diff --git a/src/test/java/io/github/alperensert/capmonster_java/tasks/FunCaptchaTaskTest.java b/src/test/java/io/github/alperensert/capmonster_java/tasks/FunCaptchaTaskTest.java new file mode 100644 index 0000000..3b36040 --- /dev/null +++ b/src/test/java/io/github/alperensert/capmonster_java/tasks/FunCaptchaTaskTest.java @@ -0,0 +1,48 @@ +package io.github.alperensert.capmonster_java.tasks; + +import io.github.alperensert.capmonster_java.exceptions.CapmonsterException; +import org.json.JSONObject; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; + +import java.util.Arrays; + +class FunCaptchaTaskTest extends BaseTaskTest { + private final FunCaptchaTask funCaptchaTask = new FunCaptchaTask(System.getenv("CAPMONSTER_API_KEY")); + + @Test + void createTask() { + FunCaptchaTask.TaskBuilder taskBuilder = new FunCaptchaTask.TaskBuilder( + "https://funcaptcha.com/fc/api/nojs/?pkey=69A21A01-CC7B-B9C6-0F9A-E7FA06677FFC", + "69A21A01-CC7B-B9C6-0F9A-E7FA06677FFC") + .setCookies(cookies) + .setUserAgent(userAgent); + taskId = funCaptchaTask.createTask(taskBuilder); + } + + @Test + void createTaskProxy() { + FunCaptchaTask.TaskBuilder taskBuilder = new FunCaptchaTask.TaskBuilder( + "https://funcaptcha.com/fc/api/nojs/?pkey=69A21A01-CC7B-B9C6-0F9A-E7FA06677FFC", + "69A21A01-CC7B-B9C6-0F9A-E7FA06677FFC") + .setCookies(cookies) + .setProxy(proxy) + .setUserAgent(userAgent); + taskId = funCaptchaTask.createTask(taskBuilder); + } + + @AfterEach + void afterEach() throws InterruptedException { + JSONObject task; + try { + task = funCaptchaTask.joinTaskResult(taskId); + } catch (CapmonsterException e) { + if (Arrays.asList(acceptable_errors).contains(e.CODE)) return; + else throw e; + } + + if (!task.has("token")) { + throw new RuntimeException(); + } + } +} \ No newline at end of file diff --git a/src/test/java/io/github/alperensert/capmonster_java/tasks/HCaptchaTaskTest.java b/src/test/java/io/github/alperensert/capmonster_java/tasks/HCaptchaTaskTest.java new file mode 100644 index 0000000..49fce12 --- /dev/null +++ b/src/test/java/io/github/alperensert/capmonster_java/tasks/HCaptchaTaskTest.java @@ -0,0 +1,63 @@ +package io.github.alperensert.capmonster_java.tasks; + +import io.github.alperensert.capmonster_java.exceptions.CapmonsterException; +import org.json.JSONObject; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; +import java.util.Arrays; + +class HCaptchaTaskTest extends BaseTaskTest { + private final HCaptchaTask hCaptchaTask = new HCaptchaTask(System.getenv("CAPMONSTER_API_KEY")); + + @Test + void createTask() { + HCaptchaTask.TaskBuilder taskBuilder = new HCaptchaTask.TaskBuilder( + "https://lessons.zennolab.com/captchas/hcaptcha/?level=easy", + "472fc7af-86a4-4382-9a49-ca9090474471") + .setCache(true) + .setCookies(cookies) + .setUserAgent(userAgent); + taskId = hCaptchaTask.createTask(taskBuilder); + } + + @Test + void createTaskProxy() { + HCaptchaTask.TaskBuilder taskBuilder = new HCaptchaTask.TaskBuilder( + "https://lessons.zennolab.com/captchas/hcaptcha/?level=easy", + "472fc7af-86a4-4382-9a49-ca9090474471") + .setCache(true) + .setCookies(cookies) + .setProxy(proxy) + .setUserAgent(userAgent); + taskId = hCaptchaTask.createTask(taskBuilder); + } + + @Test + void createTaskInvisible() { + HCaptchaTask.TaskBuilder taskBuilder = new HCaptchaTask.TaskBuilder( + "https://lessons.zennolab.com/captchas/hcaptcha/invisible.php?level=moderate", + "d391ffb1-bc91-4ef8-a45a-2e2213af091b") + .setVisibility(true) + .setCache(true) + .setCookies(cookies) + .setProxy(proxy) + .setUserAgent(userAgent); + taskId = hCaptchaTask.createTask(taskBuilder); + } + + @AfterEach + void afterEach() throws InterruptedException { + JSONObject task; + try { + task = hCaptchaTask.joinTaskResult(taskId); + } catch (CapmonsterException e) { + if (Arrays.asList(acceptable_errors).contains(e.CODE)) return; + else throw e; + } + + if (!task.has("gRecaptchaResponse")) { + throw new RuntimeException(); + } + } + +} \ No newline at end of file diff --git a/src/test/java/io/github/alperensert/capmonster_java/tasks/RecaptchaV2TaskTest.java b/src/test/java/io/github/alperensert/capmonster_java/tasks/RecaptchaV2TaskTest.java new file mode 100644 index 0000000..c801bb6 --- /dev/null +++ b/src/test/java/io/github/alperensert/capmonster_java/tasks/RecaptchaV2TaskTest.java @@ -0,0 +1,50 @@ +package io.github.alperensert.capmonster_java.tasks; + +import io.github.alperensert.capmonster_java.exceptions.CapmonsterException; +import org.json.JSONObject; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; + +import java.util.Arrays; + +class RecaptchaV2TaskTest extends BaseTaskTest { + private final RecaptchaV2Task recaptchaV2Task = new RecaptchaV2Task(System.getenv("CAPMONSTER_API_KEY")); + + @Test + void createTask() { + RecaptchaV2Task.TaskBuilder taskBuilder = new RecaptchaV2Task.TaskBuilder( + "https://lessons.zennolab.com/captchas/recaptcha/v2_simple.php?level=high", + "6Lcg7CMUAAAAANphynKgn9YAgA4tQ2KI_iqRyTwd") + .setUserAgent(userAgent) + .setCache(true) + .setCookies(cookies); + taskId = recaptchaV2Task.createTask(taskBuilder); + } + + @Test + void createTaskProxy() { + RecaptchaV2Task.TaskBuilder taskBuilder = new RecaptchaV2Task.TaskBuilder( + "https://lessons.zennolab.com/captchas/recaptcha/v2_simple.php?level=high", + "6Lcg7CMUAAAAANphynKgn9YAgA4tQ2KI_iqRyTwd") + .setUserAgent(userAgent) + .setCache(true) + .setCookies(cookies) + .setProxy(proxy); + taskId = recaptchaV2Task.createTask(taskBuilder); + } + + @AfterEach + void afterEach() throws InterruptedException { + JSONObject task; + try { + task = recaptchaV2Task.joinTaskResult(taskId); + } catch (CapmonsterException e) { + if (Arrays.asList(acceptable_errors).contains(e.CODE)) return; + else throw e; + } + + if (!task.has("gRecaptchaResponse") ) { + throw new RuntimeException(); + } + } +} \ No newline at end of file diff --git a/src/test/java/io/github/alperensert/capmonster_java/tasks/RecaptchaV3TaskTest.java b/src/test/java/io/github/alperensert/capmonster_java/tasks/RecaptchaV3TaskTest.java new file mode 100644 index 0000000..eb823a1 --- /dev/null +++ b/src/test/java/io/github/alperensert/capmonster_java/tasks/RecaptchaV3TaskTest.java @@ -0,0 +1,38 @@ +package io.github.alperensert.capmonster_java.tasks; + +import io.github.alperensert.capmonster_java.exceptions.CapmonsterException; +import org.json.JSONObject; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; +import java.util.Arrays; + +class RecaptchaV3TaskTest extends BaseTaskTest { + private final RecaptchaV3Task recaptchaV3Task = new RecaptchaV3Task(System.getenv("CAPMONSTER_API_KEY")); + + @Test + void createTask() { + RecaptchaV3Task.TaskBuilder taskBuilder = new RecaptchaV3Task.TaskBuilder( + "https://lessons.zennolab.com/captchas/recaptcha/v3.php?level=beta", + "6Le0xVgUAAAAAIt20XEB4rVhYOODgTl00d8juDob") + .setPageAction("myverify") + .setMinScore(0.6) + .setCache(true); + taskId = recaptchaV3Task.createTask(taskBuilder); + } + + @AfterEach + void afterEach() throws InterruptedException { + JSONObject task; + try { + task = recaptchaV3Task.joinTaskResult(taskId); + } catch (CapmonsterException e) { + if (Arrays.asList(acceptable_errors).contains(e.CODE)) return; + else throw e; + } + + if (!task.has("gRecaptchaResponse") ) { + throw new RuntimeException(); + } + } + +} \ No newline at end of file