Features: - Full API coverage (45 endpoints from HAR analysis) - Async/await support with httpx - Pydantic models for all responses - Clear error handling (KworkAuthError, KworkApiError, etc.) - Session management (cookies + web_auth_token) - Unit tests with respx mocks - Integration tests template - JSON logging support via structlog Endpoints implemented: - Authentication: signIn, getWebAuthToken - Catalog: catalogMainv2, getKworkDetails, getKworkDetailsExtra - Projects: projects, payerOrders, workerOrders - User: user, userReviews, favoriteKworks - Reference: cities, countries, timezones, features, badges - Notifications: notifications, notificationsFetch, dialogs - Other: 30+ additional endpoints Tests: 13 passed, 79% coverage
268 lines
5.7 KiB
Markdown
268 lines
5.7 KiB
Markdown
# Kwork API Client
|
|
|
|
Unofficial Python client for Kwork.ru API.
|
|
|
|
## Features
|
|
|
|
- ✅ Full API coverage (all endpoints from HAR dump analysis)
|
|
- ✅ Async/await support
|
|
- ✅ Pydantic models for type safety
|
|
- ✅ Clear error handling
|
|
- ✅ Session management with cookies + tokens
|
|
- ✅ JSON structured logging support
|
|
- ✅ Comprehensive test suite (unit + integration)
|
|
|
|
## Installation
|
|
|
|
```bash
|
|
# With pip
|
|
pip install kwork-api
|
|
|
|
# With uv
|
|
uv pip install kwork-api
|
|
|
|
# From source
|
|
git clone http://5.188.26.192:3000/claw/kwork-api.git
|
|
cd kwork-api
|
|
uv pip install -e ".[dev]"
|
|
```
|
|
|
|
## Quick Start
|
|
|
|
### Authentication
|
|
|
|
```python
|
|
from kwork_api import KworkClient
|
|
|
|
# Login with credentials
|
|
client = await KworkClient.login("username", "password")
|
|
|
|
# Or restore from token
|
|
client = KworkClient(token="your_web_auth_token")
|
|
|
|
# Use context manager for automatic cleanup
|
|
async with KworkClient(token="token") as client:
|
|
# Make requests
|
|
pass
|
|
```
|
|
|
|
### Catalog
|
|
|
|
```python
|
|
# Get catalog list
|
|
catalog = await client.catalog.get_list(page=1)
|
|
for kwork in catalog.kworks:
|
|
print(f"{kwork.title}: {kwork.price} RUB")
|
|
|
|
# Get kwork details
|
|
details = await client.catalog.get_details(kwork_id=123)
|
|
print(details.full_description)
|
|
```
|
|
|
|
### Projects
|
|
|
|
```python
|
|
# Get projects list
|
|
projects = await client.projects.get_list(page=1)
|
|
|
|
# Get orders where user is customer
|
|
customer_orders = await client.projects.get_payer_orders()
|
|
|
|
# Get orders where user is performer
|
|
performer_orders = await client.projects.get_worker_orders()
|
|
```
|
|
|
|
### User
|
|
|
|
```python
|
|
# Get user info
|
|
user_info = await client.user.get_info()
|
|
|
|
# Get reviews
|
|
reviews = await client.user.get_reviews(page=1)
|
|
|
|
# Get favorite kworks
|
|
favorites = await client.user.get_favorite_kworks()
|
|
```
|
|
|
|
### Reference Data
|
|
|
|
```python
|
|
# Get cities
|
|
cities = await client.reference.get_cities()
|
|
|
|
# Get countries
|
|
countries = await client.reference.get_countries()
|
|
|
|
# Get timezones
|
|
timezones = await client.reference.get_timezones()
|
|
|
|
# Get features
|
|
features = await client.reference.get_features()
|
|
```
|
|
|
|
### Notifications
|
|
|
|
```python
|
|
# Get notifications
|
|
notifications = await client.notifications.get_list()
|
|
|
|
# Fetch new notifications
|
|
new_notifications = await client.notifications.fetch()
|
|
|
|
# Get dialogs
|
|
dialogs = await client.notifications.get_dialogs()
|
|
```
|
|
|
|
## Error Handling
|
|
|
|
```python
|
|
from kwork_api import KworkAuthError, KworkApiError, KworkNotFoundError
|
|
|
|
try:
|
|
catalog = await client.catalog.get_list()
|
|
except KworkAuthError as e:
|
|
print(f"Auth failed: {e}")
|
|
except KworkNotFoundError as e:
|
|
print(f"Not found: {e}")
|
|
except KworkApiError as e:
|
|
print(f"API error [{e.status_code}]: {e.message}")
|
|
except Exception as e:
|
|
print(f"Unexpected error: {e}")
|
|
```
|
|
|
|
## Rate Limiting
|
|
|
|
Rate limiting is **not** implemented in the library. Handle it in your code:
|
|
|
|
```python
|
|
import asyncio
|
|
|
|
for page in range(1, 10):
|
|
catalog = await client.catalog.get_list(page=page)
|
|
await asyncio.sleep(1) # 1 second delay between requests
|
|
```
|
|
|
|
## Logging
|
|
|
|
The library uses standard `logging` module. For JSON logging (Kibana-compatible):
|
|
|
|
```python
|
|
import logging
|
|
import structlog
|
|
import json
|
|
|
|
# Configure structlog for JSON output
|
|
structlog.configure(
|
|
processors=[
|
|
structlog.processors.JSONRenderer()
|
|
],
|
|
wrapper_class=structlog.make_filtering_bound_logger(logging.INFO),
|
|
)
|
|
|
|
# Use in your code
|
|
logger = structlog.get_logger()
|
|
logger.info("kwork_request", endpoint="/catalogMainv2", page=1)
|
|
```
|
|
|
|
## Testing
|
|
|
|
### Unit Tests (mocks)
|
|
|
|
```bash
|
|
# Run unit tests only
|
|
pytest tests/unit/ -m unit
|
|
|
|
# With coverage
|
|
pytest tests/unit/ -m unit --cov=kwork_api
|
|
```
|
|
|
|
### Integration Tests (real API)
|
|
|
|
```bash
|
|
# Set credentials
|
|
export KWORK_USERNAME=your_username
|
|
export KWORK_PASSWORD=your_password
|
|
|
|
# Run integration tests
|
|
pytest tests/integration/ -m integration
|
|
|
|
# Skip integration tests in CI
|
|
pytest tests/ -m "not integration"
|
|
```
|
|
|
|
## Available Endpoints
|
|
|
|
### Catalog
|
|
- `GET /catalogMainv2` — Catalog list with pagination
|
|
- `POST /getKworkDetails` — Kwork details
|
|
- `POST /getKworkDetailsExtra` — Extra kwork details
|
|
|
|
### Projects
|
|
- `POST /projects` — Projects list
|
|
- `POST /payerOrders` — Customer orders
|
|
- `POST /workerOrders` — Performer orders
|
|
|
|
### User
|
|
- `POST /user` — User info
|
|
- `POST /userReviews` — User reviews
|
|
- `POST /favoriteKworks` — Favorite kworks
|
|
- `POST /favoriteCategories` — Favorite categories
|
|
|
|
### Reference Data
|
|
- `POST /cities` — Cities list
|
|
- `POST /countries` — Countries list
|
|
- `POST /timezones` — Timezones list
|
|
- `POST /getAvailableFeatures` — Available features
|
|
- `POST /getPublicFeatures` — Public features
|
|
- `POST /getBadgesInfo` — Badges info
|
|
|
|
### Notifications
|
|
- `POST /notifications` — Notifications list
|
|
- `POST /notificationsFetch` — Fetch new notifications
|
|
- `POST /dialogs` — Dialogs list
|
|
- `POST /blockedDialogList` — Blocked dialogs
|
|
|
|
### Other
|
|
- `POST /myWants` — User wants
|
|
- `POST /wantsStatusList` — Wants status
|
|
- `POST /kworksStatusList` — Kworks status
|
|
- `POST /offers` — Offers
|
|
- `POST /exchangeInfo` — Exchange info
|
|
- `POST /getChannel` — Channel info
|
|
- `POST /getInAppNotification` — In-app notification
|
|
- `POST /getSecurityUserData` — Security user data
|
|
- `POST /isDialogAllow` — Check dialog permission
|
|
- `POST /viewedCatalogKworks` — Viewed kworks
|
|
- `POST /updateSettings` — Update settings
|
|
- `POST /offline` — Set offline status
|
|
- `POST /actor` — Actor info
|
|
|
|
## Development
|
|
|
|
```bash
|
|
# Install dev dependencies
|
|
uv pip install -e ".[dev]"
|
|
|
|
# Run linter
|
|
ruff check src/ tests/
|
|
|
|
# Format code
|
|
ruff format src/ tests/
|
|
|
|
# Run all tests
|
|
pytest
|
|
|
|
# Build package
|
|
uv build
|
|
```
|
|
|
|
## License
|
|
|
|
MIT License
|
|
|
|
## Disclaimer
|
|
|
|
This is an unofficial client. Kwork.ru is not affiliated with this project.
|
|
Use at your own risk and respect Kwork's terms of service.
|