# Open Puzzle Captcha
**Open Puzzle Captcha** is a open-source interactive captcha which use puzzle solve for bot filtration \
![Open Puzzle Captcha DEMO](https://media.fullgream.tech/gif-for-openpuzzle.gif)
## How use NPM module
You can use NPM module for generate tasks. Install the module:
```bash
npm i openpuzzle-captcha
```
**It's required:** install Graphics Magick
- For Windows: http://www.graphicsmagick.org/INSTALL-windows.html (**Add gm.exe to PATH!!**)
- For linux (debian): `sudo apt-get update && sudo apt install graphicsmagick -y`

And include it in the project:
```js
const opc = require("openpuzzle-captcha");
opc.generateTask("/path/to/images/folder").then(console.log);
```
## How add the widget
Clone the repository:
```bash
git clone https://git.fullgream.tech/fullgream/openpuzzle-captcha.git
```
You can include this widget in your HTML (take code from widget/opc-widget.html):
```html
    <div value="" success="false" class="opc-widget" captcha-url='http://example.org/<captcha_id>' style='border: 1px solid; border-color: #AFAFAF; border-radius: 15px; width: 365px; padding-top: 10px; padding-left: 10px; font: 12px system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif'>
        <canvas width="350" height="350">Your browser don't support Canvas</canvas>
        <!-- Required by license -->
        <a href="https://git.fullgream.tech/fullgream/openpuzzle-captcha">OpenPuzzle Captcha</a>
    </div>
```
And in your JavaScript:
```js
// Take opc-widget.js from widget/opc-widget.js
import { initOPCWidgets } from "/path/to/opc-widget.js";
initOPCWidgets();
```
In HTML attribute "captcha-url", fill the address of API.
## How it works
**Open Puzzle Captcha** separated by two parts - client widget (for next: widget) and open puzzle captcha API (for next: API). For first, the widget sends request to the API, the API takes random picture (150x150px), splits the picture by 9 fragments (in future version, I can add 4 parts mode), adds changes for this fragments (**It's important. After it, fragments change their hash-sum**). the API generates unique key for every fragment and summorize it by solve key. After it, the API shuffle the parts of picture and send them as response to the widget. The widget don't know which combination is correct (It dictated by abuse safety), the widget spawns the parts of picture in field (for next: shards) and waits before user not solve the puzzle. Every cell of the field has number 1..9:

| 1 | 2 | 3 |
|--|--|--|
| 4 | 5 | 6 |
| 7 | 8 | 9 |

When user grabbing the shard to the cell, the widget remembers number of this cell and writes key of the cell to the chain of responses. It forms answer of the Captcha. For Example:

| 1d23af | 2fde09 | e389a1 |
|--|--|--|
| 4f441d | 5cd456 | 6ff1ce |
| 7a1def | 8df780 | 9a1d8f |

Captcha answer: 1d23af2fde09e389a14f441d5cd4566ff1ce7a1def8df7809a1d8f  \
This answer will sent to the API and after it, the API compare the answer with the correct solve and return result to widget. If captcha answer is wrong, the API generates new captcha's task and deletes old. Else - the API leave the Success Code which may use for forms in the website.
More details: [In develop]
## API
The widget sends GET-request to website which includes in attribute "captcha-url". The widget awaits next JSON response:
```js
{
    "isError": false,
    "mode": "3x3",  // <-- for now, supports only 3x3 mode
    "fragments": {
        "<fragment-id-1>": "http://url.of/image's/fragment/1",
        "<fragment-id-2>": "http://url.of/image's/fragment/2",
        ...
        "<fragment-id-9>": "http://url.of/image's/fragment/9"
    }
}
```
After user solve the captcha and press button "Send Result", the widget send POST-request to **the same address** which contains next JSON body:
```json
{
    "answer": "<captcha-answer>",
}
```
And we have 2 awaited ways: \
**First**: Correct answer, server send:
```json
{
    "isError": false,
    "isSuccess": true,
    "successCode": "<secret-success-code>"
}
```
The Widget get successCode and change attribute "value" inside itself to successCode's value. \
**Second**: Wrong answer, server send:
```json
{
    "isError": false,
    "isSuccess": false,
    "tryAgain": "/path/to/new/captcha"
}
```
### API errors
If in the runtime in the API occured errors, the widget get errors from the API:
```json
{
    "isError": true,
    "message": "Error message"
}
```
