Metadata-Version: 2.4
Name: zefoy-client
Version: 0.1.4
Summary: Python client for zefoy.com — JSON-only API (login, services, send views/hearts/...)
Author: zefoy-client contributors
License-Expression: MIT
Project-URL: Homepage, https://github.com/deno4908/zefoy_lib
Project-URL: Repository, https://github.com/deno4908/zefoy_lib
Project-URL: Issues, https://github.com/deno4908/zefoy_lib/issues
Keywords: zefoy,tiktok,automation,api,client
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Internet :: WWW/HTTP
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: cloudscraper>=1.2.71
Requires-Dist: beautifulsoup4>=4.12.0
Requires-Dist: Pillow>=10.0.0
Requires-Dist: numpy>=1.24.0
Requires-Dist: ddddocr>=1.4.11
Requires-Dist: pycryptodome>=3.19.0
Requires-Dist: brotli>=1.1.0
Requires-Dist: requests>=2.31.0
Provides-Extra: ocr
Requires-Dist: pytesseract>=0.3.10; extra == "ocr"
Provides-Extra: socks
Requires-Dist: PySocks>=1.7.1; extra == "socks"
Requires-Dist: requests[socks]>=2.31.0; extra == "socks"
Provides-Extra: dev
Requires-Dist: build; extra == "dev"
Requires-Dist: twine; extra == "dev"
Requires-Dist: pytest; extra == "dev"
Dynamic: license-file

# zefoy-client

Python client library for [zefoy.com](https://zefoy.com).

- **JSON-only API** — every public method returns a `dict` (ready for `json.dumps`)
- No stdout noise from the library
- Captcha OCR ensemble via **ddddocr**, adaptive image preprocessing, and optional **Tesseract**
- Auto cooldown wait (IP-based server timer)
- Services: views, hearts, favorites, shares, followers, …

> **Disclaimer:** Unofficial. Use at your own risk. Respect site terms and local laws. For educational / automation research purposes.

---

## Install

Yêu cầu Python 3.9 trở lên. Nên cài trong môi trường ảo để không ảnh hưởng
những thư viện Python khác trên máy.

### Windows

```powershell
py -m venv .venv
.\.venv\Scripts\Activate.ps1
python -m pip install --upgrade pip
python -m pip install zefoy-client
```

Nếu PowerShell chặn script kích hoạt, chạy một lần trong cửa sổ hiện tại:

```powershell
Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass
.\.venv\Scripts\Activate.ps1
```

### Linux / macOS

```bash
python3 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install zefoy-client
```

### PyPI

```bash
python -m pip install zefoy-client
```

Optional extras:

```bash
python -m pip install "zefoy-client[socks]"       # SOCKS4/5 proxy
python -m pip install "zefoy-client[ocr]"         # pytesseract helper
python -m pip install "zefoy-client[socks,ocr]"   # install both
```

`ddddocr` và phần xử lý ảnh mới được cài tự động cùng package. Extra `ocr`
cài Python wrapper `pytesseract`, nhưng muốn dùng được Tesseract thì máy cũng
phải có chương trình Tesseract OCR:

- Windows: cài Tesseract OCR, rồi thêm thư mục chứa `tesseract.exe` vào `PATH`.
- Ubuntu/Debian: `sudo apt update && sudo apt install tesseract-ocr`
- macOS (Homebrew): `brew install tesseract`

Kiểm tra:

```bash
tesseract --version
python -c "from zefoy import Zefoy, __version__; print(__version__)"
```

Tesseract là tùy chọn. Nếu chưa cài, thư viện vẫn chạy bằng `ddddocr`.

### GitHub

Repo: [https://github.com/deno4908/zefoy_lib](https://github.com/deno4908/zefoy_lib)

```bash
# latest main
pip install git+https://github.com/deno4908/zefoy_lib.git

# specific branch / tag
pip install git+https://github.com/deno4908/zefoy_lib.git@main
pip install git+https://github.com/deno4908/zefoy_lib.git@v0.1.0
```

Clone rồi cài editable (dev):

```bash
git clone https://github.com/deno4908/zefoy_lib.git
cd zefoy_lib
pip install -e .
# pip install -e ".[socks,ocr]"
```

### From local folder

```bash
cd zefoy-client
pip install -e .
```

### Build / publish wheel

```bash
python -m pip install --upgrade build twine
python -m build
python -m twine check dist/*
# python -m twine upload dist/zefoy_client-0.1.4*
```

---

## Quick start

```python
import json
from zefoy import Zefoy

bot = Zefoy(
    use_ocr=True,       # ensemble OCR: ddddocr + optional Tesseract
    auto_wait=True,     # sleep on server cooldown
    # proxy="http://user:pass@host:port",
)

print(json.dumps(bot.login(), ensure_ascii=False, indent=2))
print(json.dumps(bot.services(), ensure_ascii=False, indent=2))

url = "https://www.tiktok.com/@user/video/1234567890"
print(json.dumps(bot.send_views(url), ensure_ascii=False, indent=2))
```

### Proxy

`proxy` áp dụng cho **toàn session** (login + captcha + services + send).  
Hỗ trợ URL string hoặc dict kiểu `requests`.

| Loại | Ví dụ |
|------|--------|
| HTTP | `http://host:8080` |
| HTTP + auth | `http://user:pass@host:8080` |
| HTTPS proxy | `https://user:pass@host:8443` |
| SOCKS5 | `socks5://user:pass@host:1080` |
| SOCKS5h (DNS qua proxy) | `socks5h://user:pass@host:1080` |
| SOCKS4 | `socks4://host:1080` |

```bash
# SOCKS cần thêm dependency
pip install -e ".[socks]"
# hoặc: pip install PySocks requests[socks]
```

```python
from zefoy import Zefoy
import json

# 1) HTTP proxy (string — gán cả http & https)
bot = Zefoy(proxy="http://1.2.3.4:8080")

# 2) HTTP có user/pass
bot = Zefoy(proxy="http://myuser:mypass@1.2.3.4:8080")

# 3) SOCKS5
bot = Zefoy(proxy="socks5://user:pass@1.2.3.4:1080")

# 4) SOCKS5 + resolve DNS trên proxy
bot = Zefoy(proxy="socks5h://user:pass@1.2.3.4:1080")

# 5) Dict tách http / https (giống requests)
bot = Zefoy(proxy={
    "http": "http://user:pass@1.2.3.4:8080",
    "https": "http://user:pass@1.2.3.4:8080",
})

# 6) Dùng với send
url = "https://www.tiktok.com/@user/video/123"
print(json.dumps(bot.login(), ensure_ascii=False, indent=2))
print(json.dumps(bot.send_views(url), ensure_ascii=False, indent=2))
print(json.dumps(bot.send_hearts(url), ensure_ascii=False, indent=2))
```

CLI:

```bash
zefoy --proxy "http://user:pass@host:8080" send views "https://www.tiktok.com/@u/video/123"
zefoy --proxy "socks5h://user:pass@host:1080" send hearts "https://..."
```

> Proxy đổi IP → tránh / giảm cooldown theo IP của Zefoy. Proxy chết sẽ làm `login`/`send` trả `ok: false`.

### Manual captcha

```python
bot = Zefoy(use_ocr=False)
img = bot.get_captcha_image("captcha.png")  # open image yourself
print(bot.login(captcha_text="flower"))
```

### Custom captcha solver

```python
def my_solver(image):
    # image: PIL.Image
    return "answer"

bot = Zefoy(captcha_solver=my_solver)
bot.login()
```

---

## OCR CAPTCHA improvements in 0.1.4

Phiên bản `0.1.4` nâng cấp toàn bộ pipeline nhận dạng CAPTCHA:

- Tạo 7 biến thể từ ảnh gốc thay vì chỉ xử lý một kiểu cố định.
- Dùng Otsu threshold thích nghi theo độ sáng của từng ảnh.
- Tách và chọn các kênh màu RGB có độ tương phản tốt nhất.
- Kết hợp kết quả của `ddddocr` với Tesseract khi Tesseract có trên máy.
- Biểu quyết có trọng số giữa các kết quả OCR gần giống nhau.
- Ưu tiên kết quả có độ dài hợp lý, không còn chọn chuỗi dài nhất chứa nhiễu.
- Chuẩn hóa kết quả từ custom captcha solver trước khi gửi.

Không có thay đổi phá vỡ API. Code đang dùng `Zefoy(use_ocr=True)` sẽ tự động
nhận pipeline OCR mới sau khi nâng cấp:

```bash
python -m pip install --upgrade zefoy-client
```

---

## API

### `Zefoy(...)`

| Arg | Type | Default | Description |
|-----|------|---------|-------------|
| `use_ocr` | `bool` | `True` | Auto-solve captcha |
| `auto_wait` | `bool` | `True` | Wait on IP cooldown |
| `max_cooldown_retries` | `int` | `5` | Max wait/retry loops |
| `proxy` | `str` \| `dict` | `None` | Proxy URL hoặc dict `requests` (HTTP/HTTPS/SOCKS) |
| `captcha_solver` | `callable` | `None` | `f(PIL.Image) -> str` |
| `user_agent` | `str` | Chrome 131 | Must stay consistent per session |
| `on_event` | `callable` | `None` | Optional debug hook `f(dict)` |

### Methods (all return `dict`)

| Method | Description |
|--------|-------------|
| `login(captcha_text=None, max_tries=5)` | Captcha + session |
| `submit_captcha(text)` | Submit captcha only |
| `services()` / `get_services()` | List available services |
| `send(service, url)` | Search + send order |
| `send_views(url)` | Shortcut |
| `send_hearts(url)` | Shortcut |
| `send_favorites(url)` | Shortcut |
| `send_shares(url)` | Shortcut |
| `send_followers(url)` | Shortcut |
| `Zefoy.to_json(data)` | `json.dumps` helper |

`service` name examples: `"views"`, `"t-views"`, `"hearts"`, `"favorites"`, …

---

## Response shape

Every call looks like:

```json
{
  "ok": true,
  "...": "..."
}
```

### `login()` success

```json
{
  "ok": true,
  "status": "logged_in",
  "captcha": "flower",
  "attempts": []
}
```

### `services()` success

```json
{
  "ok": true,
  "count": 8,
  "services": [
    {
      "name": "t-views",
      "disabled": false,
      "action": "https://zefoy.com/c2VuZC9mb2xeb3dlcnNfdGlrdG9V"
    }
  ]
}
```

### `send_views()` success

```json
{
  "ok": true,
  "status": "sent",
  "service": "t-views",
  "target": "https://www.tiktok.com/@u/video/123",
  "video_id": "123",
  "zefoy_amount": 1000,
  "zefoy_amount_label": "1000 views",
  "wait_seconds": 552,
  "summary": "sent 1000 views | next_wait 552s"
}
```

> **Note:** `zefoy_amount` is decided by Zefoy, not by the caller.

### Error

```json
{
  "ok": false,
  "error": "cooldown",
  "wait_seconds": 91,
  "message": "Please wait 91 seconds before trying again."
}
```

Common `error` codes: `login_failed`, `captcha_rejected`, `cooldown`, `service_not_found`, `no_send_form`, `send_failed`, `max_retries`.

---

## CLI

After install:

```bash
zefoy login
zefoy services
zefoy send views "https://www.tiktok.com/@u/video/123"
```

Or:

```bash
python -m zefoy send views "https://..."
```

---

## Flow (internal)

1. **Login** — fetch captcha image → OCR/manual → POST `captchalogin` + encrypted fingerprint  
2. **Search** — `POST /{base64_action}` with `HASH=full_tiktok_url`  
3. **Send** — `POST` same endpoint with `HASH=video_id`  
4. Response body is `reverse + base64` (same as site JS)

Server cooldown is **IP-based**, not local-session-based. New process on same IP still waits.

---

## Project layout

```text
zefoy-client/
├── pyproject.toml
├── README.md
├── LICENSE
├── MANIFEST.in
├── examples/
│   └── basic.py
└── src/
    └── zefoy/
        ├── __init__.py
        ├── __main__.py
        └── client.py
```

---

## Publish to PyPI

Phiên bản trong `pyproject.toml` và `src/zefoy/__init__.py` phải giống nhau,
và số phiên bản chưa từng được upload lên PyPI. PyPI không cho ghi đè một
release đã tồn tại.

```bash
python -m pip install --upgrade build twine
python -m build
python -m twine check dist/zefoy_client-0.1.4*
python -m twine upload dist/zefoy_client-0.1.4*
```

Nên upload TestPyPI trước nếu muốn kiểm tra metadata:

```bash
python -m twine upload --repository testpypi dist/zefoy_client-0.1.4*
```

Twine sẽ hỏi username/password. Khi dùng API token, username là
`__token__`, password là token bắt đầu bằng `pypi-`.

Sau khi upload, người dùng nâng cấp bằng:

```bash
python -m pip install --upgrade zefoy-client
# or from GitHub:
python -m pip install git+https://github.com/deno4908/zefoy_lib.git
```

---

## License

MIT
