docs: добавлены подробные docstrings для KworkClient
- KworkClient: полное описание класса, аутентификации, примеров - __init__: детальное описание параметров - login(): пошаговое описание процесса аутентификации - CatalogAPI: документация класса и методов get_list, get_details, get_details_extra - ProjectsAPI: документация класса и метода get_list - get_payer_orders/get_worker_orders: описание методов Все docstrings на русском языке с примерами использования.
This commit is contained in:
parent
305d934081
commit
a771a75c49
274
api_reference.md
274
api_reference.md
@ -398,17 +398,47 @@ Main client class with authentication and all API endpoints.
|
||||
class KworkClient()
|
||||
```
|
||||
|
||||
Kwork.ru API client.
|
||||
Асинхронный клиент для Kwork.ru API.
|
||||
|
||||
Usage:
|
||||
# Login with credentials
|
||||
client = await KworkClient.login("username", "password")
|
||||
Предоставляет доступ ко всем основным эндпоинтам Kwork API:
|
||||
- Каталог кворков и поиск
|
||||
- Биржа проектов (фриланс заказы)
|
||||
- Пользовательские данные и отзывы
|
||||
- Уведомления и сообщения
|
||||
- Справочные данные (города, страны, категории)
|
||||
|
||||
# Or restore from token
|
||||
client = KworkClient(token="your_web_auth_token")
|
||||
Аутентификация:
|
||||
Клиент использует двухэтапную аутентификацию Kwork:
|
||||
1. POST /signIn — получение session cookies
|
||||
2. POST /getWebAuthToken — получение web_auth_token
|
||||
|
||||
# Make requests
|
||||
catalog = await client.catalog.get_list(page=1)
|
||||
Примеры использования:
|
||||
# Вход по логину/паролю
|
||||
async with await KworkClient.login("username", "password") as client:
|
||||
catalog = await client.catalog.get_list(page=1)
|
||||
|
||||
# Восстановление сессии по токену
|
||||
client = KworkClient(token="saved_web_auth_token")
|
||||
user_info = await client.user.get_info()
|
||||
|
||||
# Работа с проектами
|
||||
projects = await client.projects.get_list(page=1)
|
||||
my_orders = await client.projects.get_payer_orders()
|
||||
|
||||
**Attributes**:
|
||||
|
||||
- `catalog` - Доступ к каталогу кворков
|
||||
- `projects` - Доступ к бирже проектов
|
||||
- `user` - Пользовательские эндпоинты
|
||||
- `reference` - Справочные данные
|
||||
- `notifications` - Уведомления и сообщения
|
||||
- `other` - Прочие эндпоинты
|
||||
|
||||
|
||||
**Notes**:
|
||||
|
||||
Клиент поддерживает context manager для автоматического закрытия соединения.
|
||||
Рекомендуется использовать `async with` для корректного освобождения ресурсов.
|
||||
|
||||
<a id="kwork_api.client.KworkClient.BASE_URL"></a>
|
||||
|
||||
@ -433,14 +463,37 @@ def __init__(token: Optional[str] = None,
|
||||
base_url: Optional[str] = None)
|
||||
```
|
||||
|
||||
Initialize client.
|
||||
Инициализация клиента.
|
||||
|
||||
Создаёт неаутентифицированный клиент или восстанавливает сессию
|
||||
по ранее полученному токену.
|
||||
|
||||
**Arguments**:
|
||||
|
||||
- `token` - Web auth token (from getWebAuthToken)
|
||||
- `cookies` - Session cookies (optional, will be set from token)
|
||||
- `timeout` - Request timeout in seconds
|
||||
- `base_url` - Custom base URL (for testing)
|
||||
- `token` - Web auth token, полученный через `getWebAuthToken` или `login()`.
|
||||
Если указан, автоматически добавляется в cookies.
|
||||
- `cookies` - Session cookies из предыдущей аутентификации.
|
||||
Обычно не требуется — устанавливаются автоматически из token.
|
||||
- `timeout` - Таймаут HTTP запросов в секундах. По умолчанию 30 секунд.
|
||||
- `base_url` - Кастомный базовый URL. Используется только для тестирования.
|
||||
|
||||
|
||||
**Example**:
|
||||
|
||||
# Новый клиент без аутентификации
|
||||
client = KworkClient()
|
||||
|
||||
# Восстановление сессии
|
||||
client = KworkClient(token="eyJ0eXAiOiJKV1QiLCJhbGc...")
|
||||
|
||||
# Клиент с кастомным таймаутом
|
||||
client = KworkClient(timeout=60.0)
|
||||
|
||||
|
||||
**Notes**:
|
||||
|
||||
Для полноценной работы API требуется аутентификация.
|
||||
Используйте `login()` или передайте сохранённый token.
|
||||
|
||||
<a id="kwork_api.client.KworkClient.login"></a>
|
||||
|
||||
@ -454,23 +507,55 @@ async def login(cls,
|
||||
timeout: float = 30.0) -> "KworkClient"
|
||||
```
|
||||
|
||||
Login with username and password.
|
||||
Аутентификация по логину и паролю.
|
||||
|
||||
Выполняет двухэтапный процесс аутентификации Kwork:
|
||||
1. POST /signIn — проверка учётных данных, получение session cookies
|
||||
2. POST /getWebAuthToken — обмен cookies на web_auth_token
|
||||
|
||||
Полученный токен и cookies сохраняются в клиенте для последующих запросов.
|
||||
|
||||
**Arguments**:
|
||||
|
||||
- `username` - Kwork username or email
|
||||
- `password` - Kwork password
|
||||
- `timeout` - Request timeout
|
||||
- `username` - Логин или email аккаунта Kwork.
|
||||
- `password` - Пароль аккаунта Kwork.
|
||||
- `timeout` - Таймаут запросов в секундах. Применяется к каждому этапу.
|
||||
|
||||
|
||||
**Returns**:
|
||||
|
||||
Authenticated KworkClient instance
|
||||
Полностью аутентифицированный экземпляр KworkClient,
|
||||
готовый к работе с API.
|
||||
|
||||
|
||||
**Raises**:
|
||||
|
||||
- `KworkAuthError` - If login fails
|
||||
- `KworkAuthError` - Если логин/пароль неверны или токен не получен.
|
||||
- `KworkNetworkError` - Если произошла ошибка сети.
|
||||
|
||||
|
||||
**Example**:
|
||||
|
||||
# Базовое использование
|
||||
client = await KworkClient.login("myuser", "mypassword")
|
||||
|
||||
# С кастомным таймаутом
|
||||
client = await KworkClient.login("user", "pass", timeout=60.0)
|
||||
|
||||
# Сохранение токена для повторного использования
|
||||
token = client._token
|
||||
# Позже: client = KworkClient(token=token)
|
||||
|
||||
Security:
|
||||
Пароль не сохраняется в клиенте. Только token и cookies.
|
||||
Рекомендуется сохранять token для повторного использования
|
||||
вместо хранения пароля.
|
||||
|
||||
|
||||
**Notes**:
|
||||
|
||||
Токен имеет ограниченное время жизни. При получении 401 ошибки
|
||||
необходимо выполнить повторный login().
|
||||
|
||||
<a id="kwork_api.client.KworkClient.close"></a>
|
||||
|
||||
@ -506,7 +591,23 @@ async def __aexit__(*args: Any) -> None
|
||||
class CatalogAPI()
|
||||
```
|
||||
|
||||
Catalog/Kworks API endpoints.
|
||||
API каталога кворков.
|
||||
|
||||
Предоставляет доступ к каталогу услуг Kwork:
|
||||
- Поиск и фильтрация кворков
|
||||
- Получение детальной информации
|
||||
- Категории и сортировка
|
||||
|
||||
**Example**:
|
||||
|
||||
# Получить первую страницу каталога
|
||||
catalog = await client.catalog.get_list(page=1)
|
||||
|
||||
# Фильтрация по категории
|
||||
catalog = await client.catalog.get_list(category_id=5)
|
||||
|
||||
# Детали конкретного кворка
|
||||
details = await client.catalog.get_details(kwork_id=12345)
|
||||
|
||||
<a id="kwork_api.client.KworkClient.CatalogAPI.__init__"></a>
|
||||
|
||||
@ -526,18 +627,48 @@ async def get_list(page: int = 1,
|
||||
sort: str = "recommend") -> CatalogResponse
|
||||
```
|
||||
|
||||
Get kworks catalog.
|
||||
Получить список кворков из каталога.
|
||||
|
||||
Основной эндпоинт для поиска и просмотра кворков.
|
||||
Возвращает пагинированный список с возможностью фильтрации.
|
||||
|
||||
**Arguments**:
|
||||
|
||||
- `page` - Page number
|
||||
- `category_id` - Category filter
|
||||
- `sort` - Sort option (recommend, price_asc, price_desc, etc.)
|
||||
- `page` - Номер страницы для пагинации (начиная с 1).
|
||||
- `category_id` - ID категории для фильтрации.
|
||||
Если None — все категории.
|
||||
- `sort` - Опция сортировки. Варианты:
|
||||
- "recommend" — по рекомендации (по умолчанию)
|
||||
- "price_asc" — по возрастанию цены
|
||||
- "price_desc" — по убыванию цены
|
||||
- "rating" — по рейтингу
|
||||
- "reviews" — по количеству отзывов
|
||||
- "newest" — по дате создания
|
||||
|
||||
|
||||
**Returns**:
|
||||
|
||||
CatalogResponse with kworks and pagination
|
||||
CatalogResponse содержащий:
|
||||
- kworks: список кворков на странице
|
||||
- pagination: информация о пагинации
|
||||
- filters: доступные фильтры
|
||||
- sort_options: доступные опции сортировки
|
||||
|
||||
|
||||
**Example**:
|
||||
|
||||
# Первая страница, сортировка по цене
|
||||
response = await client.catalog.get_list(
|
||||
page=1,
|
||||
sort="price_asc"
|
||||
)
|
||||
|
||||
for kwork in response.kworks:
|
||||
- `print(f"{kwork.title}` - {kwork.price} RUB")
|
||||
|
||||
# Пагинация
|
||||
if response.pagination and response.pagination.has_next:
|
||||
next_page = await client.catalog.get_list(page=2)
|
||||
|
||||
<a id="kwork_api.client.KworkClient.CatalogAPI.get_details"></a>
|
||||
|
||||
@ -547,16 +678,36 @@ Get kworks catalog.
|
||||
async def get_details(kwork_id: int) -> KworkDetails
|
||||
```
|
||||
|
||||
Get kwork details.
|
||||
Получить полную информацию о кворке.
|
||||
|
||||
Возвращает расширенную информацию о кворке включая:
|
||||
- Полное описание и требования
|
||||
- Сроки выполнения и количество правок
|
||||
- Дополнительные опции (features)
|
||||
- FAQ от продавца
|
||||
|
||||
**Arguments**:
|
||||
|
||||
- `kwork_id` - Kwork ID
|
||||
- `kwork_id` - Уникальный идентификатор кворка.
|
||||
|
||||
|
||||
**Returns**:
|
||||
|
||||
KworkDetails with full information
|
||||
KworkDetails с полной информацией о кворке.
|
||||
|
||||
|
||||
**Raises**:
|
||||
|
||||
- `KworkNotFoundError` - Если кворк с таким ID не найден.
|
||||
|
||||
|
||||
**Example**:
|
||||
|
||||
details = await client.catalog.get_details(12345)
|
||||
- `print(f"Название` - {details.title}")
|
||||
- `print(f"Цена` - {details.price} {details.currency}")
|
||||
- `print(f"Срок` - {details.delivery_time} дней")
|
||||
- `print(f"Правки` - {details.revisions}")
|
||||
|
||||
<a id="kwork_api.client.KworkClient.CatalogAPI.get_details_extra"></a>
|
||||
|
||||
@ -566,16 +717,30 @@ Get kwork details.
|
||||
async def get_details_extra(kwork_id: int) -> dict[str, Any]
|
||||
```
|
||||
|
||||
Get additional kwork details.
|
||||
Получить дополнительные детали кворка.
|
||||
|
||||
Возвращает расширенную информацию, которая не включена
|
||||
в основной ответ get_details(). Может содержать:
|
||||
- Дополнительные изображения
|
||||
- Видео обзоры
|
||||
- Детали пакетов услуг
|
||||
- Статистику продаж
|
||||
|
||||
**Arguments**:
|
||||
|
||||
- `kwork_id` - Kwork ID
|
||||
- `kwork_id` - Уникальный идентификатор кворка.
|
||||
|
||||
|
||||
**Returns**:
|
||||
|
||||
Extra details dict
|
||||
Словарь с дополнительными данными. Структура зависит
|
||||
от конкретного кворка и не гарантируется стабильной.
|
||||
|
||||
|
||||
**Notes**:
|
||||
|
||||
Этот эндпоинт возвращает "сырые" данные без валидации.
|
||||
Структура ответа может измениться без предупреждения.
|
||||
|
||||
<a id="kwork_api.client.KworkClient.ProjectsAPI"></a>
|
||||
|
||||
@ -585,7 +750,23 @@ Get additional kwork details.
|
||||
class ProjectsAPI()
|
||||
```
|
||||
|
||||
Projects (freelance orders) API endpoints.
|
||||
API биржи проектов (фриланс заказы).
|
||||
|
||||
Предоставляет доступ к заказам на фриланс:
|
||||
- Просмотр открытых проектов
|
||||
- Заказы где вы заказчик (payer)
|
||||
- Заказы где вы исполнитель (worker)
|
||||
|
||||
**Example**:
|
||||
|
||||
# Новые проекты
|
||||
projects = await client.projects.get_list(page=1)
|
||||
|
||||
# Мои заказы как заказчика
|
||||
my_orders = await client.projects.get_payer_orders()
|
||||
|
||||
# Мои заказы как исполнителя
|
||||
my_work = await client.projects.get_worker_orders()
|
||||
|
||||
<a id="kwork_api.client.KworkClient.ProjectsAPI.__init__"></a>
|
||||
|
||||
@ -604,17 +785,38 @@ async def get_list(page: int = 1,
|
||||
category_id: Optional[int] = None) -> ProjectsResponse
|
||||
```
|
||||
|
||||
Get projects list.
|
||||
Получить список проектов с биржи.
|
||||
|
||||
Основной эндпоинт для просмотра доступных заказов.
|
||||
Возвращает пагинированный список проектов.
|
||||
|
||||
**Arguments**:
|
||||
|
||||
- `page` - Page number
|
||||
- `category_id` - Category filter
|
||||
- `page` - Номер страницы (начиная с 1).
|
||||
- `category_id` - ID категории для фильтрации.
|
||||
Если None — все категории.
|
||||
|
||||
|
||||
**Returns**:
|
||||
|
||||
ProjectsResponse with projects and pagination
|
||||
ProjectsResponse содержащий:
|
||||
- projects: список проектов на странице
|
||||
- pagination: информация о пагинации
|
||||
|
||||
|
||||
**Example**:
|
||||
|
||||
# Все новые проекты
|
||||
response = await client.projects.get_list(page=1)
|
||||
|
||||
for project in response.projects:
|
||||
- `print(f"{project.title}` - {project.budget} {project.budget_type}")
|
||||
|
||||
# Только категория "Разработка"
|
||||
dev_projects = await client.projects.get_list(
|
||||
page=1,
|
||||
category_id=5
|
||||
)
|
||||
|
||||
<a id="kwork_api.client.KworkClient.ProjectsAPI.get_payer_orders"></a>
|
||||
|
||||
|
||||
@ -1,25 +0,0 @@
|
||||
# API Reference
|
||||
|
||||
Auto-generated API documentation using mkdocstrings.
|
||||
|
||||
## Client
|
||||
|
||||
::: kwork_api.client.KworkClient
|
||||
|
||||
## Models
|
||||
|
||||
::: kwork_api.models.Kwork
|
||||
|
||||
::: kwork_api.models.KworkDetails
|
||||
|
||||
::: kwork_api.models.Project
|
||||
|
||||
::: kwork_api.models.CatalogResponse
|
||||
|
||||
## Errors
|
||||
|
||||
::: kwork_api.errors.KworkError
|
||||
|
||||
::: kwork_api.errors.KworkAuthError
|
||||
|
||||
::: kwork_api.errors.KworkApiError
|
||||
@ -1,7 +0,0 @@
|
||||
# Client API
|
||||
|
||||
::: kwork_api.client.KworkClient
|
||||
options:
|
||||
show_root_heading: true
|
||||
show_source: true
|
||||
merge_init_into_class: true
|
||||
@ -1,23 +0,0 @@
|
||||
# Errors
|
||||
|
||||
Exception classes for error handling.
|
||||
|
||||
## KworkError
|
||||
|
||||
::: kwork_api.errors.KworkError
|
||||
|
||||
## KworkAuthError
|
||||
|
||||
::: kwork_api.errors.KworkAuthError
|
||||
|
||||
## KworkApiError
|
||||
|
||||
::: kwork_api.errors.KworkApiError
|
||||
|
||||
## KworkNotFoundError
|
||||
|
||||
::: kwork_api.errors.KworkNotFoundError
|
||||
|
||||
## KworkRateLimitError
|
||||
|
||||
::: kwork_api.errors.KworkRateLimitError
|
||||
@ -1,23 +0,0 @@
|
||||
# Models
|
||||
|
||||
Pydantic models used in API responses.
|
||||
|
||||
## Kwork
|
||||
|
||||
::: kwork_api.models.Kwork
|
||||
|
||||
## KworkDetails
|
||||
|
||||
::: kwork_api.models.KworkDetails
|
||||
|
||||
## Project
|
||||
|
||||
::: kwork_api.models.Project
|
||||
|
||||
## CatalogResponse
|
||||
|
||||
::: kwork_api.models.CatalogResponse
|
||||
|
||||
## PaginationInfo
|
||||
|
||||
::: kwork_api.models.PaginationInfo
|
||||
212
docs/examples.md
212
docs/examples.md
@ -1,212 +0,0 @@
|
||||
# Usage Examples
|
||||
|
||||
## Catalog
|
||||
|
||||
### Get Catalog List
|
||||
|
||||
```python
|
||||
from kwork_api import KworkClient
|
||||
|
||||
async with KworkClient(token="token") as client:
|
||||
catalog = await client.catalog.get_list(page=1, category_id=5)
|
||||
|
||||
for kwork in catalog.kworks:
|
||||
print(f"{kwork.title}: {kwork.price} RUB")
|
||||
|
||||
# Pagination
|
||||
if catalog.pagination:
|
||||
print(f"Page {catalog.pagination.current_page} of {catalog.pagination.total_pages}")
|
||||
```
|
||||
|
||||
### Get Kwork Details
|
||||
|
||||
```python
|
||||
details = await client.catalog.get_details(kwork_id=123)
|
||||
|
||||
print(f"Title: {details.title}")
|
||||
print(f"Price: {details.price}")
|
||||
print(f"Description: {details.full_description}")
|
||||
print(f"Delivery: {details.delivery_time} days")
|
||||
```
|
||||
|
||||
## Projects
|
||||
|
||||
### Get Projects List
|
||||
|
||||
```python
|
||||
projects = await client.projects.get_list(page=1)
|
||||
|
||||
for project in projects.projects:
|
||||
print(f"{project.title} - {project.budget} RUB")
|
||||
```
|
||||
|
||||
### Get Customer Orders
|
||||
|
||||
```python
|
||||
orders = await client.projects.get_payer_orders()
|
||||
|
||||
for order in orders:
|
||||
print(f"Order #{order.id}: {order.status}")
|
||||
```
|
||||
|
||||
### Get Performer Orders
|
||||
|
||||
```python
|
||||
orders = await client.projects.get_worker_orders()
|
||||
|
||||
for order in orders:
|
||||
print(f"Work #{order.id}: {order.status}")
|
||||
```
|
||||
|
||||
## User
|
||||
|
||||
### Get User Info
|
||||
|
||||
```python
|
||||
user_info = await client.user.get_info()
|
||||
print(f"Username: {user_info.get('username')}")
|
||||
```
|
||||
|
||||
### Get Reviews
|
||||
|
||||
```python
|
||||
reviews = await client.user.get_reviews(page=1)
|
||||
|
||||
for review in reviews.reviews:
|
||||
print(f"Rating: {review.rating}/5 - {review.comment}")
|
||||
```
|
||||
|
||||
### Get Favorite Kworks
|
||||
|
||||
```python
|
||||
favorites = await client.user.get_favorite_kworks()
|
||||
|
||||
for kwork in favorites:
|
||||
print(f"Favorite: {kwork.title}")
|
||||
```
|
||||
|
||||
## Reference Data
|
||||
|
||||
### Get Cities
|
||||
|
||||
```python
|
||||
cities = await client.reference.get_cities()
|
||||
|
||||
for city in cities:
|
||||
print(f"{city.id}: {city.name}")
|
||||
```
|
||||
|
||||
### Get Countries
|
||||
|
||||
```python
|
||||
countries = await client.reference.get_countries()
|
||||
|
||||
for country in countries:
|
||||
print(f"{country.id}: {country.name}")
|
||||
```
|
||||
|
||||
### Get Timezones
|
||||
|
||||
```python
|
||||
timezones = await client.reference.get_timezones()
|
||||
|
||||
for tz in timezones:
|
||||
print(f"{tz.id}: {tz.name} ({tz.offset})")
|
||||
```
|
||||
|
||||
## Notifications
|
||||
|
||||
### Get Notifications
|
||||
|
||||
```python
|
||||
notifications = await client.notifications.get_list()
|
||||
|
||||
for notif in notifications.notifications:
|
||||
print(f"{notif.title}: {notif.message}")
|
||||
|
||||
print(f"Unread: {notifications.unread_count}")
|
||||
```
|
||||
|
||||
### Fetch New Notifications
|
||||
|
||||
```python
|
||||
new_notifications = await client.notifications.fetch()
|
||||
print(f"New: {len(new_notifications.notifications)}")
|
||||
```
|
||||
|
||||
### Get Dialogs
|
||||
|
||||
```python
|
||||
dialogs = await client.notifications.get_dialogs()
|
||||
|
||||
for dialog in dialogs:
|
||||
print(f"Dialog with {dialog.participant.username}: {dialog.last_message}")
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
```python
|
||||
from kwork_api import KworkAuthError, KworkApiError, KworkNotFoundError
|
||||
|
||||
try:
|
||||
catalog = await client.catalog.get_list()
|
||||
except KworkAuthError as e:
|
||||
print(f"Authentication failed: {e}")
|
||||
except KworkNotFoundError as e:
|
||||
print(f"Resource 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
|
||||
|
||||
```python
|
||||
import asyncio
|
||||
|
||||
async def fetch_all_pages():
|
||||
all_kworks = []
|
||||
|
||||
for page in range(1, 10):
|
||||
try:
|
||||
catalog = await client.catalog.get_list(page=page)
|
||||
all_kworks.extend(catalog.kworks)
|
||||
|
||||
if not catalog.pagination or not catalog.pagination.has_next:
|
||||
break
|
||||
|
||||
# Delay to avoid rate limiting
|
||||
await asyncio.sleep(1)
|
||||
|
||||
except KworkRateLimitError:
|
||||
print("Rate limited, waiting...")
|
||||
await asyncio.sleep(5)
|
||||
|
||||
return all_kworks
|
||||
```
|
||||
|
||||
## Pagination Helper
|
||||
|
||||
```python
|
||||
async def fetch_all_catalog():
|
||||
"""Fetch all kworks from catalog with pagination."""
|
||||
all_kworks = []
|
||||
page = 1
|
||||
|
||||
while True:
|
||||
catalog = await client.catalog.get_list(page=page)
|
||||
all_kworks.extend(catalog.kworks)
|
||||
|
||||
if not catalog.pagination or not catalog.pagination.has_next:
|
||||
break
|
||||
|
||||
page += 1
|
||||
await asyncio.sleep(0.5) # Rate limiting
|
||||
|
||||
return all_kworks
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
*More examples in the API Reference.*
|
||||
@ -1,81 +0,0 @@
|
||||
# Kwork API Documentation
|
||||
|
||||
Unofficial Python client for Kwork.ru API.
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Installation
|
||||
|
||||
```bash
|
||||
pip install kwork-api
|
||||
```
|
||||
|
||||
### 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")
|
||||
```
|
||||
|
||||
### Basic Usage
|
||||
|
||||
```python
|
||||
async with KworkClient(token="token") as client:
|
||||
# Get catalog
|
||||
catalog = await client.catalog.get_list(page=1)
|
||||
|
||||
# Get kwork details
|
||||
details = await client.catalog.get_details(kwork_id=123)
|
||||
|
||||
# Get projects
|
||||
projects = await client.projects.get_list()
|
||||
```
|
||||
|
||||
## Documentation Sections
|
||||
|
||||
- **[API Reference](api-reference.md)** — All endpoints and methods
|
||||
- **[Models](api-reference.md#models)** — Pydantic models
|
||||
- **[Errors](api-reference.md#errors)** — Exception classes
|
||||
- **[Examples](examples.md)** — Usage examples
|
||||
|
||||
## Features
|
||||
|
||||
- ✅ Full API coverage (45 endpoints)
|
||||
- ✅ Async/await support
|
||||
- ✅ Pydantic models for type safety
|
||||
- ✅ Clear error handling
|
||||
- ✅ Session management
|
||||
|
||||
## 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
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
```python
|
||||
from kwork_api import KworkAuthError, KworkApiError
|
||||
|
||||
try:
|
||||
catalog = await client.catalog.get_list()
|
||||
except KworkAuthError as e:
|
||||
print(f"Auth failed: {e}")
|
||||
except KworkApiError as e:
|
||||
print(f"API error [{e.status_code}]: {e.message}")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
*Documentation auto-generated from source code.*
|
||||
@ -44,17 +44,44 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
class KworkClient:
|
||||
"""
|
||||
Kwork.ru API client.
|
||||
Асинхронный клиент для Kwork.ru API.
|
||||
|
||||
Usage:
|
||||
# Login with credentials
|
||||
client = await KworkClient.login("username", "password")
|
||||
Предоставляет доступ ко всем основным эндпоинтам Kwork API:
|
||||
- Каталог кворков и поиск
|
||||
- Биржа проектов (фриланс заказы)
|
||||
- Пользовательские данные и отзывы
|
||||
- Уведомления и сообщения
|
||||
- Справочные данные (города, страны, категории)
|
||||
|
||||
Аутентификация:
|
||||
Клиент использует двухэтапную аутентификацию Kwork:
|
||||
1. POST /signIn — получение session cookies
|
||||
2. POST /getWebAuthToken — получение web_auth_token
|
||||
|
||||
Примеры использования:
|
||||
# Вход по логину/паролю
|
||||
async with await KworkClient.login("username", "password") as client:
|
||||
catalog = await client.catalog.get_list(page=1)
|
||||
|
||||
# Or restore from token
|
||||
client = KworkClient(token="your_web_auth_token")
|
||||
# Восстановление сессии по токену
|
||||
client = KworkClient(token="saved_web_auth_token")
|
||||
user_info = await client.user.get_info()
|
||||
|
||||
# Make requests
|
||||
catalog = await client.catalog.get_list(page=1)
|
||||
# Работа с проектами
|
||||
projects = await client.projects.get_list(page=1)
|
||||
my_orders = await client.projects.get_payer_orders()
|
||||
|
||||
Attributes:
|
||||
catalog: Доступ к каталогу кворков
|
||||
projects: Доступ к бирже проектов
|
||||
user: Пользовательские эндпоинты
|
||||
reference: Справочные данные
|
||||
notifications: Уведомления и сообщения
|
||||
other: Прочие эндпоинты
|
||||
|
||||
Note:
|
||||
Клиент поддерживает context manager для автоматического закрытия соединения.
|
||||
Рекомендуется использовать `async with` для корректного освобождения ресурсов.
|
||||
"""
|
||||
|
||||
BASE_URL = "https://api.kwork.ru"
|
||||
@ -69,13 +96,32 @@ class KworkClient:
|
||||
base_url: Optional[str] = None,
|
||||
):
|
||||
"""
|
||||
Initialize client.
|
||||
Инициализация клиента.
|
||||
|
||||
Создаёт неаутентифицированный клиент или восстанавливает сессию
|
||||
по ранее полученному токену.
|
||||
|
||||
Args:
|
||||
token: Web auth token (from getWebAuthToken)
|
||||
cookies: Session cookies (optional, will be set from token)
|
||||
timeout: Request timeout in seconds
|
||||
base_url: Custom base URL (for testing)
|
||||
token: Web auth token, полученный через `getWebAuthToken` или `login()`.
|
||||
Если указан, автоматически добавляется в cookies.
|
||||
cookies: Session cookies из предыдущей аутентификации.
|
||||
Обычно не требуется — устанавливаются автоматически из token.
|
||||
timeout: Таймаут HTTP запросов в секундах. По умолчанию 30 секунд.
|
||||
base_url: Кастомный базовый URL. Используется только для тестирования.
|
||||
|
||||
Example:
|
||||
# Новый клиент без аутентификации
|
||||
client = KworkClient()
|
||||
|
||||
# Восстановление сессии
|
||||
client = KworkClient(token="eyJ0eXAiOiJKV1QiLCJhbGc...")
|
||||
|
||||
# Клиент с кастомным таймаутом
|
||||
client = KworkClient(timeout=60.0)
|
||||
|
||||
Note:
|
||||
Для полноценной работы API требуется аутентификация.
|
||||
Используйте `login()` или передайте сохранённый token.
|
||||
"""
|
||||
self.base_url = base_url or self.BASE_URL
|
||||
self.timeout = timeout
|
||||
@ -93,18 +139,46 @@ class KworkClient:
|
||||
timeout: float = 30.0,
|
||||
) -> "KworkClient":
|
||||
"""
|
||||
Login with username and password.
|
||||
Аутентификация по логину и паролю.
|
||||
|
||||
Выполняет двухэтапный процесс аутентификации Kwork:
|
||||
1. POST /signIn — проверка учётных данных, получение session cookies
|
||||
2. POST /getWebAuthToken — обмен cookies на web_auth_token
|
||||
|
||||
Полученный токен и cookies сохраняются в клиенте для последующих запросов.
|
||||
|
||||
Args:
|
||||
username: Kwork username or email
|
||||
password: Kwork password
|
||||
timeout: Request timeout
|
||||
|
||||
username: Логин или email аккаунта Kwork.
|
||||
password: Пароль аккаунта Kwork.
|
||||
timeout: Таймаут запросов в секундах. Применяется к каждому этапу.
|
||||
|
||||
Returns:
|
||||
Authenticated KworkClient instance
|
||||
|
||||
Полностью аутентифицированный экземпляр KworkClient,
|
||||
готовый к работе с API.
|
||||
|
||||
Raises:
|
||||
KworkAuthError: If login fails
|
||||
KworkAuthError: Если логин/пароль неверны или токен не получен.
|
||||
KworkNetworkError: Если произошла ошибка сети.
|
||||
|
||||
Example:
|
||||
# Базовое использование
|
||||
client = await KworkClient.login("myuser", "mypassword")
|
||||
|
||||
# С кастомным таймаутом
|
||||
client = await KworkClient.login("user", "pass", timeout=60.0)
|
||||
|
||||
# Сохранение токена для повторного использования
|
||||
token = client._token
|
||||
# Позже: client = KworkClient(token=token)
|
||||
|
||||
Security:
|
||||
Пароль не сохраняется в клиенте. Только token и cookies.
|
||||
Рекомендуется сохранять token для повторного использования
|
||||
вместо хранения пароля.
|
||||
|
||||
Note:
|
||||
Токен имеет ограниченное время жизни. При получении 401 ошибки
|
||||
необходимо выполнить повторный login().
|
||||
"""
|
||||
client = cls(timeout=timeout)
|
||||
|
||||
@ -261,7 +335,24 @@ class KworkClient:
|
||||
# ========== Catalog Endpoints ==========
|
||||
|
||||
class CatalogAPI:
|
||||
"""Catalog/Kworks API endpoints."""
|
||||
"""
|
||||
API каталога кворков.
|
||||
|
||||
Предоставляет доступ к каталогу услуг Kwork:
|
||||
- Поиск и фильтрация кворков
|
||||
- Получение детальной информации
|
||||
- Категории и сортировка
|
||||
|
||||
Example:
|
||||
# Получить первую страницу каталога
|
||||
catalog = await client.catalog.get_list(page=1)
|
||||
|
||||
# Фильтрация по категории
|
||||
catalog = await client.catalog.get_list(category_id=5)
|
||||
|
||||
# Детали конкретного кворка
|
||||
details = await client.catalog.get_details(kwork_id=12345)
|
||||
"""
|
||||
|
||||
def __init__(self, client: "KworkClient"):
|
||||
self.client = client
|
||||
@ -273,15 +364,43 @@ class KworkClient:
|
||||
sort: str = "recommend",
|
||||
) -> CatalogResponse:
|
||||
"""
|
||||
Get kworks catalog.
|
||||
Получить список кворков из каталога.
|
||||
|
||||
Основной эндпоинт для поиска и просмотра кворков.
|
||||
Возвращает пагинированный список с возможностью фильтрации.
|
||||
|
||||
Args:
|
||||
page: Page number
|
||||
category_id: Category filter
|
||||
sort: Sort option (recommend, price_asc, price_desc, etc.)
|
||||
|
||||
page: Номер страницы для пагинации (начиная с 1).
|
||||
category_id: ID категории для фильтрации.
|
||||
Если None — все категории.
|
||||
sort: Опция сортировки. Варианты:
|
||||
- "recommend" — по рекомендации (по умолчанию)
|
||||
- "price_asc" — по возрастанию цены
|
||||
- "price_desc" — по убыванию цены
|
||||
- "rating" — по рейтингу
|
||||
- "reviews" — по количеству отзывов
|
||||
- "newest" — по дате создания
|
||||
|
||||
Returns:
|
||||
CatalogResponse with kworks and pagination
|
||||
CatalogResponse содержащий:
|
||||
- kworks: список кворков на странице
|
||||
- pagination: информация о пагинации
|
||||
- filters: доступные фильтры
|
||||
- sort_options: доступные опции сортировки
|
||||
|
||||
Example:
|
||||
# Первая страница, сортировка по цене
|
||||
response = await client.catalog.get_list(
|
||||
page=1,
|
||||
sort="price_asc"
|
||||
)
|
||||
|
||||
for kwork in response.kworks:
|
||||
print(f"{kwork.title}: {kwork.price} RUB")
|
||||
|
||||
# Пагинация
|
||||
if response.pagination and response.pagination.has_next:
|
||||
next_page = await client.catalog.get_list(page=2)
|
||||
"""
|
||||
data = await self.client._request(
|
||||
"POST",
|
||||
@ -296,13 +415,29 @@ class KworkClient:
|
||||
|
||||
async def get_details(self, kwork_id: int) -> KworkDetails:
|
||||
"""
|
||||
Get kwork details.
|
||||
Получить полную информацию о кворке.
|
||||
|
||||
Возвращает расширенную информацию о кворке включая:
|
||||
- Полное описание и требования
|
||||
- Сроки выполнения и количество правок
|
||||
- Дополнительные опции (features)
|
||||
- FAQ от продавца
|
||||
|
||||
Args:
|
||||
kwork_id: Kwork ID
|
||||
|
||||
kwork_id: Уникальный идентификатор кворка.
|
||||
|
||||
Returns:
|
||||
KworkDetails with full information
|
||||
KworkDetails с полной информацией о кворке.
|
||||
|
||||
Raises:
|
||||
KworkNotFoundError: Если кворк с таким ID не найден.
|
||||
|
||||
Example:
|
||||
details = await client.catalog.get_details(12345)
|
||||
print(f"Название: {details.title}")
|
||||
print(f"Цена: {details.price} {details.currency}")
|
||||
print(f"Срок: {details.delivery_time} дней")
|
||||
print(f"Правки: {details.revisions}")
|
||||
"""
|
||||
data = await self.client._request(
|
||||
"POST",
|
||||
@ -313,13 +448,25 @@ class KworkClient:
|
||||
|
||||
async def get_details_extra(self, kwork_id: int) -> dict[str, Any]:
|
||||
"""
|
||||
Get additional kwork details.
|
||||
Получить дополнительные детали кворка.
|
||||
|
||||
Возвращает расширенную информацию, которая не включена
|
||||
в основной ответ get_details(). Может содержать:
|
||||
- Дополнительные изображения
|
||||
- Видео обзоры
|
||||
- Детали пакетов услуг
|
||||
- Статистику продаж
|
||||
|
||||
Args:
|
||||
kwork_id: Kwork ID
|
||||
|
||||
kwork_id: Уникальный идентификатор кворка.
|
||||
|
||||
Returns:
|
||||
Extra details dict
|
||||
Словарь с дополнительными данными. Структура зависит
|
||||
от конкретного кворка и не гарантируется стабильной.
|
||||
|
||||
Note:
|
||||
Этот эндпоинт возвращает "сырые" данные без валидации.
|
||||
Структура ответа может измениться без предупреждения.
|
||||
"""
|
||||
return await self.client._request(
|
||||
"POST",
|
||||
@ -330,7 +477,24 @@ class KworkClient:
|
||||
# ========== Projects Endpoints ==========
|
||||
|
||||
class ProjectsAPI:
|
||||
"""Projects (freelance orders) API endpoints."""
|
||||
"""
|
||||
API биржи проектов (фриланс заказы).
|
||||
|
||||
Предоставляет доступ к заказам на фриланс:
|
||||
- Просмотр открытых проектов
|
||||
- Заказы где вы заказчик (payer)
|
||||
- Заказы где вы исполнитель (worker)
|
||||
|
||||
Example:
|
||||
# Новые проекты
|
||||
projects = await client.projects.get_list(page=1)
|
||||
|
||||
# Мои заказы как заказчика
|
||||
my_orders = await client.projects.get_payer_orders()
|
||||
|
||||
# Мои заказы как исполнителя
|
||||
my_work = await client.projects.get_worker_orders()
|
||||
"""
|
||||
|
||||
def __init__(self, client: "KworkClient"):
|
||||
self.client = client
|
||||
@ -341,14 +505,33 @@ class KworkClient:
|
||||
category_id: Optional[int] = None,
|
||||
) -> ProjectsResponse:
|
||||
"""
|
||||
Get projects list.
|
||||
Получить список проектов с биржи.
|
||||
|
||||
Основной эндпоинт для просмотра доступных заказов.
|
||||
Возвращает пагинированный список проектов.
|
||||
|
||||
Args:
|
||||
page: Page number
|
||||
category_id: Category filter
|
||||
|
||||
page: Номер страницы (начиная с 1).
|
||||
category_id: ID категории для фильтрации.
|
||||
Если None — все категории.
|
||||
|
||||
Returns:
|
||||
ProjectsResponse with projects and pagination
|
||||
ProjectsResponse содержащий:
|
||||
- projects: список проектов на странице
|
||||
- pagination: информация о пагинации
|
||||
|
||||
Example:
|
||||
# Все новые проекты
|
||||
response = await client.projects.get_list(page=1)
|
||||
|
||||
for project in response.projects:
|
||||
print(f"{project.title}: {project.budget} {project.budget_type}")
|
||||
|
||||
# Только категория "Разработка"
|
||||
dev_projects = await client.projects.get_list(
|
||||
page=1,
|
||||
category_id=5
|
||||
)
|
||||
"""
|
||||
data = await self.client._request(
|
||||
"POST",
|
||||
@ -362,20 +545,36 @@ class KworkClient:
|
||||
|
||||
async def get_payer_orders(self) -> list[Project]:
|
||||
"""
|
||||
Get orders where user is customer.
|
||||
Получить заказы где вы являетесь заказчиком.
|
||||
|
||||
Возвращает все проекты, созданные текущим пользователем,
|
||||
независимо от их статуса (открыт, в работе, завершён).
|
||||
|
||||
Returns:
|
||||
List of projects
|
||||
Список проектов где текущий пользователь — заказчик.
|
||||
|
||||
Example:
|
||||
orders = await client.projects.get_payer_orders()
|
||||
for order in orders:
|
||||
print(f"Заказ #{order.id}: {order.status}")
|
||||
"""
|
||||
data = await self.client._request("POST", "/payerOrders")
|
||||
return [Project.model_validate(p) for p in data.get("orders", [])]
|
||||
|
||||
async def get_worker_orders(self) -> list[Project]:
|
||||
"""
|
||||
Get orders where user is performer.
|
||||
Получить заказы где вы являетесь исполнителем.
|
||||
|
||||
Возвращает все проекты, где текущий пользователь
|
||||
назначен исполнителем.
|
||||
|
||||
Returns:
|
||||
List of projects
|
||||
Список проектов где текущий пользователь — исполнитель.
|
||||
|
||||
Example:
|
||||
work = await client.projects.get_worker_orders()
|
||||
active = [p for p in work if p.status == "in_progress"]
|
||||
print(f"Активных заказов: {len(active)}")
|
||||
"""
|
||||
data = await self.client._request("POST", "/workerOrders")
|
||||
return [Project.model_validate(p) for p in data.get("orders", [])]
|
||||
|
||||
Loading…
Reference in New Issue
Block a user