Metadata-Version: 2.4
Name: captcha-cli
Version: 1.0.1
Summary: A simple captcha generator
License-File: LICENSE
Requires-Python: >=3.14
Requires-Dist: audioop-lts>=0.2.2
Requires-Dist: click>=8.1.8
Requires-Dist: numpy>=2.4.2
Requires-Dist: pillow>=12.1.1
Requires-Dist: prettytable>=3.17.0
Requires-Dist: pydantic>=2.12.5
Requires-Dist: pydub>=0.25.1
Provides-Extra: api
Requires-Dist: aiosqlite>=0.22.1; extra == 'api'
Requires-Dist: click>=8.1.8; extra == 'api'
Requires-Dist: fastapi>=0.131.0; extra == 'api'
Requires-Dist: prettytable>=3.17.0; extra == 'api'
Requires-Dist: sqlalchemy[asyncio]>=2.0.46; extra == 'api'
Requires-Dist: sqlmodel>=0.0.35; extra == 'api'
Requires-Dist: uvicorn>=0.41.0; extra == 'api'
Provides-Extra: manage
Requires-Dist: aiosqlite>=0.22.1; extra == 'manage'
Requires-Dist: sqlalchemy[asyncio]>=2.0.46; extra == 'manage'
Requires-Dist: sqlmodel>=0.0.35; extra == 'manage'
Description-Content-Type: text/markdown

# captcha-cli

A simple captcha generator

## I. Introduction
This is a simple captcha generator that utilizing pillow and pydub to generate captcha.

This also include a simple CLI to help you manage captcha level and data.

## II. Installation

### 1. Base installation
You can install this package using `pip`:
```
pip install captcha-cli
```
or with `uv`:
```
uv add captcha-cli
```

### 2. `manage` installation
You can install this package with DB driver using `pip`:
```
pip install 'captcha-cli[manage]'
```
or with `uv`:
```
uv add 'captcha-cli[manage]'
```
This package comes with DB library (`sqlalchemy`) and default driver (`aiosqlite`)


### 3. `api` installation
You can install this package with API support using `pip`:
```
pip install 'captcha-cli[api]'
```
or with `uv`:
```
uv add 'captcha-cli[api]'
```
This package comes with DB part (`sqlalchemy` and `aiosqlite`) and API part (`fastapi`)

### 4. Using Docker
You can pull latest Docker image to your machine and use it:
```
docker pull git.vaito.dev/vair.nooi/captcha:latest
```
Or using dev image:
```
docker pull git.vaito.dev/vair.nooi/captcha:dev-latest
```
Or any dev build image:
```
docker pull git.vaito.dev/vair.nooi/captcha:<image id>
```

## III. Usage
### 1. CLI
#### a. Add captcha level
+ Text captcha:
    
    ```
    captcha add text --level <int> --angle <int> <int> --lines <int> <int> --dots <int> <int> --amplitude <int> --wavelength <int>
    ```
    + `-L / --level <int>` act as the level id
    + `-a / --angle <int> <int>` the range of the rotation angle of each character
    + `-l / --lines <int> <int>` the range of the number of lines will be on the image
    + `-d / --dots <int> <int>` the range of the number of dots will be on the image
    + `-A / --amplitude <int>` the amplitude of distortion
    + `-w / --wavelength <int>` the wavelength of distortion
    + **Note** `amplitude` and `wavelength` will decide how the picture will be bent


+ Audio captcha:
    
    ```
    captcha add audio --level <int> --white-noise <int> <int> --pitch-shift <int> <int>
    ```
    + `-L / --level <int>` act as the level id
    + `-w / --white-noise <int> <int>` the range of the volume of the background noise, both int are negative number
    + `-p / --pitch-shift <int> <int>` the range of the shift of each character pitch
    + **Notes**:
        + For white noise volumne, -35 is very quiet, 0 is super dupper loud
        + The pitch shift should be from 1 to 12
        + The pitch is kinda useless

#### b. Delete captcha level

```
captcha delete --type [audio | text] --level <string>
```
+ `-t / --type [audio | test]` the type of the captcha
+ `-l / --level <string>` the level id

#### c. List captcha levels
```
captcha list --type [audio | text]
```
+ `-t / --type [audio | test]` the type of the captcha

#### d. Generate captcha
```
captcha generate --type [audio | text] --level <string> --text <string> --length <int> --preview
```
+ `-t / --type [audio | test]` the type of the captcha
+ `-L / --level <string>` the level id
+ `--text <string>` the text to generate
+ `-k / --length <int>` the length of random text
+ `-p / --preview` preview the captcha
+ **Notes**
    + To use given text to generate captcha, use `--text` option
    + To use random text to generate captcha, use `--length` option
    + `--preview` option use [pillow `Image.show()`](https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.Image.show) for text captcha and [pydub `play()`](https://github.com/jiaaro/pydub#playback) for audio captcha
    + `--preview` is required if you don't install [package with DB option](#2-manage-installation)

#### e. Get all generated captcha (require [DB installation](#2-manage-installation))
```
captcha all --type [audio | text | both]
```
+ `-t / --type [audio | text | both]` captcha type filter

#### f. Start API server
```
captcha api --host <string> --port <int>
```
+ `-h / --host` the host adress
+ `-p / --port` the server port

### 2. API
Beside using CLI, you can also interact with app using API.

#### a. Start API
You can use [this method](#f-start-api-server) 

Or using Docker image:
```
docker run --name captcha -p 8000:8000 -v <path on your host>:/app/file git.vaito.dev/vair.nooi/captcha
```

#### b. Endpoints

+ POST `/captcha`

    Create a new captcha

    + Query:
        + `type: "text" / "audio"` captcha type
        + `noise_level: string` captcha level
        + `text: string | null` (default: `null`) predefined captcha answer, if null, use random text
        + `include_data: boolean` (default: `false`) include base64 encoded captcha in the response

    + Return:
        + `id: string` captcha id, use for getting answer
        + `type: "text" / "audio"` captcha type, should match with the requested one
        + `data: string | null` base64 encoded captcha

+ POST `/solve`

    Solve the captcha

    + Query:
        + `id: string` captcha id
        + `answer: string` captcha answer
    
    + Return:
        + `status: "accepted" / "wrong"` if the answer was true

+ GET `/captcha`

    Get the captcha detail

    + Query:
        + `id: string` captcha id
        + `with_answer: boolean` (default `false`) captcha answer, return error if env variable `ALLOW_GET_ANSWER` is unset or set to false

    + Return:
        + `id: string` captcha id, use for getting answer
        + `type: "text" / "audio"` captcha type
        + `answer: string` captcha answer

    + Note: Field `answer` in reponse would be omitted if query `with_answer` is false

+ GET `/captcha/file`

    Get the captcha data

    + Query:
        + `id: string` captcha id

    + Return:
        + A JPG file if the captcha type is text
        + or A WAV file if the captcha type is audio

## IV. Env variables

|Name            |Default value                     |Data type        |Note|
|----------------|----------------------------------|-----------------|----|
|APP_LEVEL       |Base on your installation         |simple/manage/api|`simple` if you install `captcha-cli`<br>`manage` if you install `captcha-cli[manage]`<br>`api` if you install `captcha-cli[api]`
|DB_URL          |sqlite+aiosqlite:///file/db.sqlite|string           |Have to have the async dialect (driver) of the database (e.g. `aiosqlite` for sqlite)<br>Should be accepted by sqlalchemy
|ALLOW_GET_ANSWER|false                             |boolean          |Set this to `true` to be able to get the captcha answer in API response|
|HOST            |127.0.0.1                         |Any IP           |    |
|PORT            |8000                              |integer          |    |