Skip to content

Commit

Permalink
Complete task mapping. Some tests.
Browse files Browse the repository at this point in the history
  • Loading branch information
Dmitry Gladyshev committed Mar 10, 2022
1 parent 794be79 commit a2f8a2a
Show file tree
Hide file tree
Showing 25 changed files with 419 additions and 45 deletions.
5 changes: 1 addition & 4 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
check-all: lint cs psalm test
check-all: lint cs test

cs:
composer cs-check

cs-fix:
composer cs-fix

psalm:
composer psalm

lint:
composer lint

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ $client = new \Anticaptcha\Client(
$httpClient
);

$result = $client->resolveImage(__DIR__.'/data/yandex.gif');
$result = $client->resolveImage(__DIR__.'/data/captcha.png');

var_dump($result->solution);

Expand Down
1 change: 0 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
"require-dev": {
"guzzlehttp/guzzle": "~7.4",
"phpunit/phpunit": "~9.5",
"vimeo/psalm": "^4.15",
"squizlabs/php_codesniffer": "^3.6",
"overtrue/phplint": "^4.1",
"dg/bypass-finals": "^1.3"
Expand Down
36 changes: 36 additions & 0 deletions examples/antigate_task.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

require __DIR__ . '/../vendor/autoload.php';

$configuration = \Anticaptcha\Configuration::fromClientKey(
getenv('__ANTICAPTCHA_KEY__')
);

$httpClient = new \GuzzleHttp\Client();

$client = new \Anticaptcha\Client(
$configuration,
$httpClient
);

$task = new \Anticaptcha\Task\AntiGateTask([
'websiteURL' => 'http://antigate.com/logintest.php',
'templateName' => 'Sign-in and wait for control text',
'variables' => [
"login_input_css" => "#login",
"login_input_value" => "the login",
"password_input_css" => "#password",
"password_input_value" => "test password",
"control_text" => "You have been logged successfully"
]
]);

$createTaskResponse = $client->createTask($task);

$getTaskResponse = $client->getTaskResult($createTaskResponse->getTaskId());
$getTaskResponse->wait(5, 600);

var_dump(
$getTaskResponse->getTaskId(),
$getTaskResponse->solution
);
4 changes: 2 additions & 2 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.5/phpunit.xsd"
bootstrap="vendor/autoload.php"
cacheResultFile="./runtime/phpunit/test-results"
cacheResultFile="./var/phpunit/test-results"
executionOrder="depends,defects"
beStrictAboutCoversAnnotation="true"
beStrictAboutOutputDuringTests="true"
Expand All @@ -20,7 +20,7 @@
</testsuite>
</testsuites>

<coverage cacheDirectory="./runtime/phpunit/code-coverage" processUncoveredFiles="true">
<coverage cacheDirectory="./var/phpunit/code-coverage" processUncoveredFiles="true">
<include>
<directory suffix=".php">src</directory>
</include>
Expand Down
16 changes: 0 additions & 16 deletions psalm.xml

This file was deleted.

6 changes: 3 additions & 3 deletions src/Client.php
Original file line number Diff line number Diff line change
Expand Up @@ -424,21 +424,21 @@ public function getAppStats(

/**
* @param string $uri
* @param array $params
* @param array $payload
*
* @return RequestInterface
*
* @throws JsonException
*/
private function createRequest(string $uri, array $params = []): RequestInterface
private function createRequest(string $uri, array $payload = []): RequestInterface
{
return new Request(
'POST',
$uri,
[
'Content-Type' => 'application/json'
],
json_encode($params, JSON_THROW_ON_ERROR),
json_encode($payload, JSON_THROW_ON_ERROR),
'1.1'
);
}
Expand Down
4 changes: 3 additions & 1 deletion src/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,16 @@

final class Configuration implements ConfigurationInterface
{
public const DEFAULT_API_URL = 'https://api.anti-captcha.com';

private string $apiKey;
private string $apiUrl;
private ?string $languagePool;
private ?string $callbackUrl;

public function __construct(
string $clientKey,
string $apiUrl = 'https://api.anti-captcha.com',
string $apiUrl = self::DEFAULT_API_URL,
?string $languagePool = null,
?string $callbackUrl = null
) {
Expand Down
35 changes: 35 additions & 0 deletions src/Entity.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,24 @@

namespace Anticaptcha;

use InvalidArgumentException;
use ReflectionClass;
use ReflectionProperty;

abstract class Entity
{
public function __construct(array $properties = [])
{
/* Validate required */

foreach ($this->getRequiredProperties() as $property) {
if (!isset($properties[$property])) {
throw new InvalidArgumentException(
sprintf('Property "%s" is required.', $property)
);
}
}

/**
* @var string $option
* @var mixed $value
Expand All @@ -16,7 +30,28 @@ public function __construct(array $properties = [])
call_user_func([$this, $setter], $value);
} elseif (property_exists($this, $option)) {
$this->$option = $value;
} else {
throw new InvalidArgumentException(
sprintf('Property "%s" not found in class "%s".', $option, static::class)
);
}
}
}

/**
* @return string[]
*/
protected function getRequiredProperties(): array
{
$properties = [];

foreach ((new ReflectionClass(static::class))->getProperties(ReflectionProperty::IS_PUBLIC) as $reflection) {
if ($reflection->hasDefaultValue()) {
continue;
}
$properties[] = $reflection->getName();
}

return $properties;
}
}
10 changes: 5 additions & 5 deletions src/Response/AbstractResponse.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,23 +30,23 @@ abstract class AbstractResponse extends Entity
public string $errorDescription = '';

/**
* @param ResponseInterface $response
* @param ResponseInterface $httpResponse
*
* @return $this
*
* @throws Exception
*/
public static function fromHttpResponse(ResponseInterface $response): self
public static function fromHttpResponse(ResponseInterface $httpResponse): self
{
$properties = json_decode(
$response->getBody()->__toString(),
$httpResponse->getBody()->__toString(),
true,
JSON_THROW_ON_ERROR
);

if (!is_array($properties)) {
throw new RuntimeException(
sprintf('Unexpected API response. Dump: %s', var_export($response, true))
sprintf('Unexpected API response. Dump: %s', var_export($httpResponse, true))
);
}

Expand All @@ -55,7 +55,7 @@ public static function fromHttpResponse(ResponseInterface $response): self

public function hasError(): bool
{
return $this->errorId > 1;
return $this->errorId > 0;
}

public function getErrorId(): int
Expand Down
7 changes: 6 additions & 1 deletion src/Task/AbstractTask.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,12 @@

abstract class AbstractTask extends Entity
{
abstract public function getType(): string;
public function getType(): string
{
$parts = explode('\\', static::class);

return end($parts);
}

public function toArray(): array
{
Expand Down
43 changes: 43 additions & 0 deletions src/Task/AntiGateTask.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

namespace Anticaptcha\Task;

class AntiGateTask extends AbstractTask
{
/*
* Address of a target web page. Can be located anywhere on the web site, even in a member area. Our workers don't
* navigate there but simulate the visit instead.
*/
public string $websiteURL;

/*
* Name of a scenario template from our database. You can use an existing template or create your own. You may
* search for an existing template below this table.
*/
public string $templateName;

/*
* An object containing template's variables and their values.
*/
public array $variables;

/*
* Proxy IP address ipv4/ipv6. No host names or IP addresses from local networks.
*/
public ?string $proxyAddress = null;

/*
* Proxy port
*/
public ?int $proxyPort = null;

/*
* Login for proxy which requires authorization (basic)
*/
public ?string $proxyLogin = null;

/*
* Proxy password
*/
public ?string $proxyPassword = null;
}
8 changes: 8 additions & 0 deletions src/Task/FunCaptchaTask.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

namespace Anticaptcha\Task;

class FunCaptchaTask extends FunCaptchaTaskProxyless
{
use ProxyTrait;
}
30 changes: 30 additions & 0 deletions src/Task/FunCaptchaTaskProxyless.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

namespace Anticaptcha\Task;

class FunCaptchaTaskProxyless extends AbstractTask
{
/*
* Address of a target web page. Can be located anywhere on the web site, even in a member area. Our workers don't
* navigate there but simulate the visit instead.
*/
public string $websiteURL;

/*
* Arkose Labs public key
*/
public string $websitePublicKey;

/*
* Custom Arkose Labs subdomain from which the Javascript widget is loaded. Required for some cases, but most
* Arkose Labs integrations run without it.
*/
public ?string $funcaptchaApiJSSubdomain = null;

/*
* An additional parameter that may be required by Arkose Labs implementation. Use this property to send "blob"
* value as an object converted to a string. See an example of what it might look like.
* {"\blob\":\"HERE_COMES_THE_blob_VALUE\"}
*/
public ?string $data = null;
}
8 changes: 8 additions & 0 deletions src/Task/GeeTestTask.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

namespace Anticaptcha\Task;

class GeeTestTask extends GeeTestTaskProxyless
{
use ProxyTrait;
}
34 changes: 34 additions & 0 deletions src/Task/GeeTestTaskProxyless.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

namespace Anticaptcha\Task;

class GeeTestTaskProxyless extends AbstractTask
{
/*
* Address of a target web page. Can be located anywhere on the web site, even in a member area. Our workers don't
* navigate there but simulate the visit instead.
*/
public string $websiteURL;

/*
* The domain public key, rarely updated.
*/
public string $gt;

/*
* Changing token key. Make sure you grab a fresh one for each captcha; otherwise, you'll be charged for an error
* task.
*/
public string $challenge;

/*
* Optional API subdomain. May be required for some implementations.
*/
public ?string $geetestApiServerSubdomain = null;

/*
* Required for some implementations. Send the JSON encoded into a string. The value can be traced in browser
* developer tools. Put a breakpoint before calling the "initGeetest" function.
*/
public ?string $geetestGetLib = null;
}
8 changes: 8 additions & 0 deletions src/Task/HCaptchaTask.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

namespace Anticaptcha\Task;

class HCaptchaTask extends HCaptchaTaskProxyless
{
use ProxyTrait;
}
Loading

0 comments on commit a2f8a2a

Please sign in to comment.