Skip to content

Commit

Permalink
Merge pull request #1 from eclipxe13/improvements
Browse files Browse the repository at this point in the history
Versión 0.2.0
  • Loading branch information
eclipxe13 committed Jul 29, 2021
2 parents 51bb7bb + f98ac55 commit 13469ef
Show file tree
Hide file tree
Showing 35 changed files with 811 additions and 85 deletions.
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ composer dev:test
composer dev:build
```

# Ejecutar GitHub Actions localmente
## Ejecutar GitHub Actions localmente

Puedes utilizar la herramienta [`act`](https://github.com/nektos/act) para ejecutar las GitHub Actions localmente.
Según [`actions/setup-php-action`](https://github.com/marketplace/actions/setup-php-action#local-testing-setup)
Expand Down
47 changes: 44 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ y que la imagen del captcha se encuentra como imagen embedida y su contenido en

use PhpCfdi\ImageCaptchaResolver\CaptchaImage;
use PhpCfdi\ImageCaptchaResolver\CaptchaResolverInterface;
use PhpCfdi\ImageCaptchaResolver\UnableToResolveCaptcha;
use PhpCfdi\ImageCaptchaResolver\UnableToResolveCaptchaException;

/**
* @var string $theImgElementSrcAtributte
Expand All @@ -66,7 +66,7 @@ $image = CaptchaImage::newFromInlineHtml($theImgElementSrcAtributte);

try {
$answer = $resolver->resolve($image);
} catch (UnableToResolveCaptcha $exception) {
} catch (UnableToResolveCaptchaException $exception) {
echo 'No se pudo resolver el captcha', PHP_EOL;
return;
}
Expand Down Expand Up @@ -142,8 +142,49 @@ $resolverConstructed = new CaptchaLocalResolver(
);
```

### Creación de un resolvedor de captchas basado en línea de comandos

La implementación dependerá siempre de la herramienta que se esté utilizando, es probable que fabrique
su propio punto de entrada a la herramienta para que devuelva el *exit code* correcto y la respuesta.

Esta herramienta podría ser útil en caso de que el captcha se pueda resolver utilizando alguna herramienta
como [`tesseract`](https://github.com/tesseract-ocr/tesseract).

El siguiente ejemplo supone que tiene la imagen del captcha a resolver en `$image` y que existe un commando
llamado `my-captcha-breaker` que se le entrega una imagen y devuelve en el último renglón de la salida
la respuesta del captcha.

```php
<?php declare(strict_types=1);

use PhpCfdi\ImageCaptchaResolver\CaptchaImageInterface;
use PhpCfdi\ImageCaptchaResolver\Resolvers\CommandLineResolver;
use PhpCfdi\ImageCaptchaResolver\UnableToResolveCaptchaException;

/**
* @var CaptchaImageInterface $image
*/

$resolver = CommandLineResolver::create(explode(' ', 'my-captcha-breaker --in {file} --stdout'));

try {
$answer = $resolver->resolve($image);
} catch (UnableToResolveCaptchaException $exception) {
echo 'No se pudo resolver el captcha: ', $exception->getMessage(), PHP_EOL;
return;
}

echo $answer, PHP_EOL;
```

## Resolvedores

### Multiresolvedor

El resolvedor `MultiResolver` es en sí mismo un resolvedor que intenta resolver el captcha usando un conjunto
predefinido de resolvedores. Podría ser útil para intentar resolver utilizando diferentes estrategias
o reintentando con un mismo resolvedor el número de veces en las que esté incluído.

### Resolvedores para pruebas

El resolvedor `CaptchaLocalResolver` usa servicio de resolución de captchas local y es comúnmente utilizado para pruebas.
Expand All @@ -154,7 +195,7 @@ ejecutando el proceso. Solo es útil si puede escribir la respuesta. Si no se re
en un tiempo predeterminado el resolvedor fallará lo tomará como una respuesta vacía.

Si está haciendo pruebas unitarias, la mejor alternativa es usar el resolvedor `MockResolver`, que se construye
con respuestas prestablecidas `CaptchaAnswerInterface` o excepciones `UnableToResolveCaptcha` y falla con una
con respuestas prestablecidas `CaptchaAnswerInterface` o excepciones `UnableToResolveCaptchaException` y falla con una
excepción `OutOfRangeException` si se le pide una respuesta y ya no tiene más.

### Nuevos resolvedores
Expand Down
6 changes: 5 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,11 @@
"vlucas/phpdotenv": "^5.3",
"guzzlehttp/guzzle": "^7.3",
"guzzlehttp/psr7": "^2.0",
"php-http/guzzle7-adapter": "^1.0"
"php-http/guzzle7-adapter": "^1.0",
"symfony/process": "^5.3"
},
"suggest": {
"symfony/process": "To implement recommended CommandLineResolver"
},
"autoload": {
"psr-4": {
Expand Down
16 changes: 15 additions & 1 deletion docs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,21 @@

Utilizamos [Versionado Semántico 2.0.0](SEMVER.md).

## Versión 0.1.0
## Versión 0.2.0 2021-07-28

Se agrega el resolvedor `CommandLineResolver` que pasa la imagen del captcha como un archivo temporal
para ser resuelto por un commando externo.

Se agrega el resolvedor `MultiResolver` que contiene un conjunto de resolvedores para intentar resolver
con ellos uno a uno.

Se cambia el nombre de la excepción `UnableToResolveCaptcha` a `UnableToResolveCaptchaException`.

Se cambia el nombre de la excepción `UndiscoverableClient` a `UndiscoverableClientException`.

Se agrega la clase interna `TemporaryFile` para crear y eliminar archivos temporales.

## Versión 0.1.0 2021-07-26

Versión inicial, implementa los siguientes resolvedores:

Expand Down
2 changes: 1 addition & 1 deletion src/CaptchaResolverInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ interface CaptchaResolverInterface
*
* @param CaptchaImageInterface $image
* @return CaptchaAnswerInterface
* @throws UnableToResolveCaptcha
* @throws UnableToResolveCaptchaException
*/
public function resolve(CaptchaImageInterface $image): CaptchaAnswerInterface;
}
6 changes: 4 additions & 2 deletions src/HttpClient/HttpClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public function __construct(
/**
* Create the object with discovered PSR http client, PSR request factory and PSR stream factory
*
* @throws UndiscoverableClient
* @throws UndiscoverableClientException
*/
public static function discover(): self
{
Expand All @@ -49,9 +49,11 @@ public static function discover(): self
Psr17FactoryDiscovery::findRequestFactory(),
Psr17FactoryDiscovery::findStreamFactory()
);
// @codeCoverageIgnoreStart
} catch (Throwable $exception) {
throw new UndiscoverableClient('Cannot discover the HttpClient', $exception);
throw new UndiscoverableClientException($exception);
}
// @codeCoverageIgnoreEnd
}

/**
Expand Down
16 changes: 0 additions & 16 deletions src/HttpClient/UndiscoverableClient.php

This file was deleted.

16 changes: 16 additions & 0 deletions src/HttpClient/UndiscoverableClientException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

declare(strict_types=1);

namespace PhpCfdi\ImageCaptchaResolver\HttpClient;

use RuntimeException;
use Throwable;

class UndiscoverableClientException extends RuntimeException
{
public function __construct(Throwable $previous)
{
parent::__construct('Cannot discover the HttpClient', 0, $previous);
}
}
50 changes: 50 additions & 0 deletions src/Internal/TemporaryFile.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

declare(strict_types=1);

namespace PhpCfdi\ImageCaptchaResolver\Internal;

use RuntimeException;

/**
* Class to create a temporary file and remove it on object destruction
* @internal
*/
final class TemporaryFile
{
/** @var string */
private $path;

public function __construct(string $prefix = '', string $directory = '')
{
$tempnam = tempnam($directory, $prefix);
if (false === $tempnam) {
/** @noinspection PhpUnhandledExceptionInspection */
throw new RuntimeException('Unable to create a temporary file'); // @codeCoverageIgnore
}
$this->path = $tempnam;
}

public function __destruct()
{
if (file_exists($this->path)) {
/** @noinspection PhpUsageOfSilenceOperatorInspection */
@unlink($this->path);
}
}

public function getPath(): string
{
return $this->path;
}

public function getContents(): string
{
return file_get_contents($this->path) ?: '';
}

public function putContents(string $data): void
{
file_put_contents($this->path, $data);
}
}
8 changes: 4 additions & 4 deletions src/Resolvers/AntiCaptchaResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@
use PhpCfdi\ImageCaptchaResolver\CaptchaAnswerInterface;
use PhpCfdi\ImageCaptchaResolver\CaptchaImageInterface;
use PhpCfdi\ImageCaptchaResolver\CaptchaResolverInterface;
use PhpCfdi\ImageCaptchaResolver\HttpClient\UndiscoverableClient;
use PhpCfdi\ImageCaptchaResolver\HttpClient\UndiscoverableClientException;
use PhpCfdi\ImageCaptchaResolver\Resolvers\AntiCaptchaResolver\AntiCaptchaConnector;
use PhpCfdi\ImageCaptchaResolver\Timer\Timer;
use PhpCfdi\ImageCaptchaResolver\Timer\TimerInterface;
use PhpCfdi\ImageCaptchaResolver\UnableToResolveCaptcha;
use PhpCfdi\ImageCaptchaResolver\UnableToResolveCaptchaException;
use RuntimeException;
use Throwable;

Expand Down Expand Up @@ -56,7 +56,7 @@ public function getTimer(): TimerInterface
* @param int $timeoutSeconds
* @param int $waitMilliseconds
* @return self
* @throws UndiscoverableClient
* @throws UndiscoverableClientException
*/
public static function create(
string $clientKey,
Expand All @@ -75,7 +75,7 @@ public function resolve(CaptchaImageInterface $image): CaptchaAnswerInterface
try {
return $this->resolveImage($image);
} catch (Throwable $exception) {
throw new UnableToResolveCaptcha($this, $image, $exception);
throw new UnableToResolveCaptchaException($this, $image, $exception);
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/Resolvers/AntiCaptchaResolver/AntiCaptchaConnector.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
use PhpCfdi\ImageCaptchaResolver\HttpClient\HttpClient;
use PhpCfdi\ImageCaptchaResolver\HttpClient\HttpClientInterface;
use PhpCfdi\ImageCaptchaResolver\HttpClient\HttpException;
use PhpCfdi\ImageCaptchaResolver\HttpClient\UndiscoverableClient;
use PhpCfdi\ImageCaptchaResolver\HttpClient\UndiscoverableClientException;
use RuntimeException;
use stdClass;
use Stringable;
Expand All @@ -33,7 +33,7 @@ class AntiCaptchaConnector
*
* @param string $clientKey
* @param HttpClientInterface|null $httpClient
* @throws UndiscoverableClient
* @throws UndiscoverableClientException
*/
public function __construct(string $clientKey, HttpClientInterface $httpClient = null)
{
Expand Down
8 changes: 4 additions & 4 deletions src/Resolvers/CaptchaLocalResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@
use PhpCfdi\ImageCaptchaResolver\CaptchaAnswerInterface;
use PhpCfdi\ImageCaptchaResolver\CaptchaImageInterface;
use PhpCfdi\ImageCaptchaResolver\CaptchaResolverInterface;
use PhpCfdi\ImageCaptchaResolver\HttpClient\UndiscoverableClient;
use PhpCfdi\ImageCaptchaResolver\HttpClient\UndiscoverableClientException;
use PhpCfdi\ImageCaptchaResolver\Resolvers\CaptchaLocalResolver\CaptchaLocalResolverConnector;
use PhpCfdi\ImageCaptchaResolver\Timer\Timer;
use PhpCfdi\ImageCaptchaResolver\Timer\TimerInterface;
use PhpCfdi\ImageCaptchaResolver\UnableToResolveCaptcha;
use PhpCfdi\ImageCaptchaResolver\UnableToResolveCaptchaException;
use Throwable;

class CaptchaLocalResolver implements CaptchaResolverInterface
Expand Down Expand Up @@ -42,7 +42,7 @@ public function __construct(
* @param int $timeoutSeconds
* @param int $sleepMilliseconds
* @return self
* @throws UndiscoverableClient
* @throws UndiscoverableClientException
*/
public static function create(
string $baseUrl,
Expand Down Expand Up @@ -71,7 +71,7 @@ public function resolve(CaptchaImageInterface $image): CaptchaAnswerInterface
try {
return $this->connector->resolveImage($image, $this->timer);
} catch (Throwable $exception) {
throw new UnableToResolveCaptcha($this, $image, $exception);
throw new UnableToResolveCaptchaException($this, $image, $exception);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
use PhpCfdi\ImageCaptchaResolver\HttpClient\HttpClient;
use PhpCfdi\ImageCaptchaResolver\HttpClient\HttpClientInterface;
use PhpCfdi\ImageCaptchaResolver\HttpClient\HttpException;
use PhpCfdi\ImageCaptchaResolver\HttpClient\UndiscoverableClient;
use PhpCfdi\ImageCaptchaResolver\HttpClient\UndiscoverableClientException;
use PhpCfdi\ImageCaptchaResolver\Timer\TimerInterface;
use RuntimeException;

Expand All @@ -33,7 +33,7 @@ class CaptchaLocalResolverConnector
*
* @param string $baseUrl Full URL to access service, by example http://localhost:9095
* @param HttpClientInterface|null $httpClient
* @throws UndiscoverableClient
* @throws UndiscoverableClientException
*/
public function __construct(string $baseUrl, HttpClientInterface $httpClient = null)
{
Expand Down

0 comments on commit 13469ef

Please sign in to comment.