*General*

2captcha solver:
- added cutCaptcha support via 2captcha.com/2captcha-api#cutcaptcha-method refs #87583
- implemented captcha feedback

git-svn-id: svn://svn.jdownloader.org/jdownloader/trunk@49687 ebf7c1c2-ba36-0410-9fe8-c592906822b4

Former-commit-id: 2acc45a410d5b8d9cb43e642819310be11f0ff0c
This commit is contained in:
psp 2024-08-29 16:20:36 +00:00
parent 1dc8a55579
commit 333b177c30
5 changed files with 71 additions and 64 deletions

View File

@ -6,7 +6,7 @@ import org.jdownloader.controlling.UniqueAlltimeID;
public class AbstractResponse<T> {
private final UniqueAlltimeID id = new UniqueAlltimeID();
private int priority;
private ValidationResult validation = null; ;
private ValidationResult validation = null;
public ValidationResult getValidation() {
return validation;
@ -14,8 +14,8 @@ public class AbstractResponse<T> {
public boolean setValidation(final ValidationResult validation) {
try {
// only validate once
if (this.validation != null) {
/* Already validated */
return false;
} else {
this.validation = validation;
@ -42,7 +42,7 @@ public class AbstractResponse<T> {
}
return true;
}
} catch (Throwable e) {
} catch (final Throwable e) {
this.validation = null;
LoggerFactory.getDefaultLogger().log(e);
return false;

View File

@ -18,20 +18,13 @@ public abstract class AbstractCaptchaHelperCutCaptcha<T extends Plugin> {
protected String siteKey;
protected String apiKey;
public AbstractCaptchaHelperCutCaptcha(T plugin, Browser br) {
this(plugin, br, null, null);
}
@Deprecated
public AbstractCaptchaHelperCutCaptcha(T plugin, Browser br, String siteKey) {
this.plugin = plugin;
if (br.getRequest() == null) {
throw new IllegalStateException("Browser.getRequest() == null!");
} else {
this.br = br;
}
if (plugin.getLogger() == null) {
logger = LogController.getInstance().getLogger(getClass().getSimpleName());
} else {
logger = plugin.getLogger();
}
this.siteKey = siteKey;
this.apiKey = null; // TODO
this(plugin, br, siteKey, null);
}
public AbstractCaptchaHelperCutCaptcha(final T plugin, final Browser br, final String siteKey, final String apiKey) {

View File

@ -1,5 +1,14 @@
package org.jdownloader.captcha.v2.challenge.cutcaptcha;
import org.appwork.utils.logging2.LogSource;
import org.jdownloader.captcha.blacklist.BlacklistEntry;
import org.jdownloader.captcha.blacklist.BlockAllCrawlerCaptchasEntry;
import org.jdownloader.captcha.blacklist.BlockCrawlerCaptchasByHost;
import org.jdownloader.captcha.blacklist.BlockCrawlerCaptchasByPackage;
import org.jdownloader.captcha.blacklist.CaptchaBlackList;
import org.jdownloader.captcha.v2.CaptchaCrawlerHelperInterface;
import org.jdownloader.captcha.v2.ChallengeResponseController;
import jd.controlling.captcha.SkipException;
import jd.controlling.downloadcontroller.SingleDownloadController;
import jd.controlling.linkcollector.LinkCollector;
@ -13,16 +22,11 @@ import jd.plugins.LinkStatus;
import jd.plugins.PluginException;
import jd.plugins.PluginForDecrypt;
import org.appwork.utils.logging2.LogSource;
import org.jdownloader.captcha.blacklist.BlacklistEntry;
import org.jdownloader.captcha.blacklist.BlockAllCrawlerCaptchasEntry;
import org.jdownloader.captcha.blacklist.BlockCrawlerCaptchasByHost;
import org.jdownloader.captcha.blacklist.BlockCrawlerCaptchasByPackage;
import org.jdownloader.captcha.blacklist.CaptchaBlackList;
import org.jdownloader.captcha.v2.CaptchaCrawlerHelperInterface;
import org.jdownloader.captcha.v2.ChallengeResponseController;
public class CaptchaHelperCrawlerPluginCutCaptcha extends AbstractCaptchaHelperCutCaptcha<PluginForDecrypt> implements CaptchaCrawlerHelperInterface {
public CaptchaHelperCrawlerPluginCutCaptcha(PluginForDecrypt plugin, Browser br) {
super(plugin, br, null);
}
public CaptchaHelperCrawlerPluginCutCaptcha(PluginForDecrypt plugin, Browser br, String siteKey) {
super(plugin, br, siteKey);
}

View File

@ -28,9 +28,12 @@ public abstract class CutCaptchaChallenge extends AbstractBrowserChallenge {
return siteKey;
}
public String getApiKey() {
return apiKey;
}
public String getSiteUrl() {
// TODO
return null;
return this.getPluginBrowser().getURL();
}
public CutCaptchaChallenge(final Plugin plugin, final String siteKey, final String apiKey) {
@ -39,8 +42,7 @@ public abstract class CutCaptchaChallenge extends AbstractBrowserChallenge {
// default: SAs61IAI
throw new WTFException("Bad SiteKey:" + siteKey);
} else if (!looksLikeValidApiKey(apiKey)) {
// default: SAs61IAI
throw new WTFException("Bad SiteKey:" + siteKey);
throw new WTFException("Bad APIKey:" + apiKey);
}
this.siteKey = siteKey;
this.apiKey = apiKey;
@ -49,7 +51,7 @@ public abstract class CutCaptchaChallenge extends AbstractBrowserChallenge {
private static boolean looksLikeValidSiteKey(final String siteKey) {
if (siteKey == null) {
return false;
} else if (!siteKey.matches("^[a-f0-9]{40}$")) {
} else if (siteKey.matches("^[a-f0-9]{40}$")) {
return true;
} else {
return false;
@ -59,7 +61,7 @@ public abstract class CutCaptchaChallenge extends AbstractBrowserChallenge {
private static boolean looksLikeValidApiKey(final String siteKey) {
if (siteKey == null) {
return false;
} else if (!siteKey.matches("^[\\w-]{5,}$")) {
} else if (siteKey.matches("^[\\w-]{5,}$")) {
return true;
} else {
return false;
@ -99,7 +101,7 @@ public abstract class CutCaptchaChallenge extends AbstractBrowserChallenge {
protected final boolean isCaptchaResponseValid() {
final String v = getResult().getValue();
if (isSolved() && isValidToken(v)) {
if (isSolved() && looksLikeValidToken(v)) {
return true;
} else {
return false;
@ -111,12 +113,12 @@ public abstract class CutCaptchaChallenge extends AbstractBrowserChallenge {
return "cut";
}
public static boolean isValidToken(String v) {
public static boolean looksLikeValidToken(String v) {
return v != null && v.matches("[\\w-]{10,}");
}
@Override
public boolean validateResponse(AbstractResponse<String> response) {
return super.validateResponse(response) && isValidToken(response.getValue());
return super.validateResponse(response) && looksLikeValidToken(response.getValue());
}
}

View File

@ -78,12 +78,13 @@ public class TwoCaptchaSolver extends AbstractTwoCaptchaSolver<String> {
handleCutCaptcha(job);
return;
}
/* Image captcha */
job.showBubble(this);
checkInterruption();
RequestOptions options = prepare(job);
try {
job.getChallenge().sendStatsSolving(this);
Browser br = new Browser();
final Browser br = new Browser();
br.setReadTimeout(5 * 60000);
// Put your CAPTCHA image file, file object, input stream,
// or vector of bytes here:
@ -91,10 +92,10 @@ public class TwoCaptchaSolver extends AbstractTwoCaptchaSolver<String> {
final byte[] data = IO.readFile(((ImageCaptchaChallenge) captchaChallenge).getImageFile());
UrlQuery qi = createQueryForUpload(job, options, data);
String json = br.postPage("https://2captcha.com/in.php", qi);
BalanceResponse response = JSonStorage.restoreFromString(json, new TypeRef<BalanceResponse>() {
final BalanceResponse response = JSonStorage.restoreFromString(json, new TypeRef<BalanceResponse>() {
});
if (1 == response.getStatus()) {
String id = response.getRequest();
final String id = response.getRequest();
job.setStatus(new SolverStatus(_GUI.T.DeathByCaptchaSolver_solveBasicCaptchaChallenge_solving(), NewTheme.I().getIcon(IconKey.ICON_WAIT, 10)));
while (job.getJob().isAlive() && !job.getJob().isSolved()) {
final UrlQuery queryPoll = createQueryForPolling();
@ -269,7 +270,7 @@ public class TwoCaptchaSolver extends AbstractTwoCaptchaSolver<String> {
q.appendEncoded("json", "1");
q.appendEncoded("soft_id", getSoftID());
q.appendEncoded("misery_key", challenge.getSiteKey());
q.appendEncoded("api_key", "TODO");
q.appendEncoded("api_key", challenge.getApiKey());
q.appendEncoded("pageurl", challenge.getSiteUrl());
final String json = br.getPage("https://2captcha.com/in.php?" + q.toString());
final BalanceResponse response = JSonStorage.restoreFromString(json, new TypeRef<BalanceResponse>() {
@ -307,44 +308,51 @@ public class TwoCaptchaSolver extends AbstractTwoCaptchaSolver<String> {
@Override
public boolean setInvalid(final AbstractResponse<?> response) {
// TODO: Add functionality
if (!DebugMode.TRUE_IN_IDE_ELSE_FALSE) {
return false;
}
/* https://2captcha.com/api-docs/report-incorrect */
final Browser br = new Browser();
try {
final Map<String, Object> postdata = new HashMap<String, Object>();
postdata.put("clientKey", this.config.getApiKey());
postdata.put("taskId", "TODO");
final PostRequest req = br.createJSonPostRequest(this.getApiBaseV2() + "/reportIncorrect", postdata);
br.getPage(req);
return true;
} catch (final Throwable e) {
e.printStackTrace();
}
return false;
return sendCaptchaFeedback(response, false);
}
@Override
public boolean setValid(AbstractResponse<?> response) {
// TODO: Add functionality
if (!DebugMode.TRUE_IN_IDE_ELSE_FALSE) {
public boolean setValid(final AbstractResponse<?> response) {
return sendCaptchaFeedback(response, true);
}
private final boolean sendCaptchaFeedback(final AbstractResponse<?> response, final boolean positiveFeedback) {
if (!this.config.isFeedBackSendingEnabled()) {
/* User has disabled feedback sending */
return false;
}
/* https://2captcha.com/api-docs/report-correct */
// TODO: Add functionality
// if (!(response instanceof TwoCaptchaResponse)) {
// /* This should never happen! */
// return false;
// }
final TwoCaptchaResponse twocaptcharesponse = (TwoCaptchaResponse) response;
final String captchaID = twocaptcharesponse.getCaptchaID();
final Browser br = new Browser();
try {
final String url;
if (positiveFeedback) {
/* https://2captcha.com/api-docs/report-correct */
url = "/reportCorrect";
} else {
/* https://2captcha.com/api-docs/report-incorrect */
url = "/reportIncorrect";
}
final Map<String, Object> postdata = new HashMap<String, Object>();
postdata.put("clientKey", this.config.getApiKey());
postdata.put("taskId", "TODO");
final PostRequest req = br.createJSonPostRequest(this.getApiBaseV2() + "/reportCorrect", postdata);
postdata.put("taskId", captchaID);
final PostRequest req = br.createJSonPostRequest(this.getApiBaseV2() + url, postdata);
br.getPage(req);
return true;
final Map<String, Object> entries = JSonStorage.restoreFromString(br.getRequest().getHtmlCode(), TypeRef.MAP);
if ("success".equalsIgnoreCase(entries.get("status").toString())) {
return true;
} else {
return false;
}
} catch (final Throwable e) {
e.printStackTrace();
return false;
}
return false;
}
public static class BalanceResponse implements Storable {
@ -373,7 +381,7 @@ public class TwoCaptchaSolver extends AbstractTwoCaptchaSolver<String> {
}
public TwoCaptchaAccount loadAccount() {
TwoCaptchaAccount ret = new TwoCaptchaAccount();
final TwoCaptchaAccount ret = new TwoCaptchaAccount();
try {
final Browser br = new Browser();
final UrlQuery q = new UrlQuery();