Skip to content

Commit 16cbf98

Browse files
committed
chore(client): prepare release 1.2.4
1 parent 680cade commit 16cbf98

8 files changed

Lines changed: 277 additions & 236 deletions

File tree

CHANGELOG.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,19 @@
11
# Changelog
22

3+
## [1.2.4] - 2025-09-19
4+
5+
### Added
6+
- Поддержан новый статус задач `submitted` в `TaskStatus`.
7+
8+
### Changed
9+
- Логи больше не содержат открытого `apiKey`: в debug‑логах ключ маскируется.
10+
- Ретраи при `429` сохраняют `task_id` для корректной диагностики ошибок.
11+
- Сообщение `RateLimitError` обобщено (без фиксированного значения 50 rps) — лимиты управляются на стороне провайдера.
12+
- Документация и примеры обновлены: убран вывод токена из ответа создания задачи (нужно получать через `getStatus`/`wait_for_result`).
13+
14+
### Fixed
15+
- Тексты в README/примерaх приведены в соответствие текущим параметрам и ответам Key API.
16+
317
## [1.2.3] - 2025-01-13
418

519
### Improved

README.md

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# REGHelp Python Client / REGHelp Python Client (Русская версия ниже)
22

33
![Python](https://img.shields.io/badge/python-3.8%2B-blue.svg)
4-
![Version](https://img.shields.io/badge/version-1.2.3-green.svg)
4+
![Version](https://img.shields.io/badge/version-1.2.4-green.svg)
55
![License](https://img.shields.io/badge/license-MIT-blue.svg)
66

77
---
@@ -11,7 +11,7 @@
1111
1. [Features](#-features)
1212
2. [Installation](#-installation)
1313
3. [Quick start](#-quick-start)
14-
4. [What's new](#-whats-new-in-123)
14+
4. [What's new](#-whats-new-in-124)
1515
5. [Environment variables](#-environment-variables)
1616
6. [Testing](#-testing)
1717
7. [Contributing](#-contributing)
@@ -29,12 +29,20 @@ Modern asynchronous Python library for interacting with the REGHelp Key API. It
2929
* **Asynchronous first** – full `async`/`await` support powered by `httpx`.
3030
* **Type-safe** – strict typing with Pydantic data models.
3131
* **Retries with exponential back-off** built-in.
32-
* **Smart rate-limit handling** (50 requests per second).
32+
* **Smart rate-limit handling** (provider-configurable).
3333
* **Async context-manager** for automatic resource management.
3434
* **Webhook support** out of the box.
3535
* **Comprehensive error handling** with dedicated exception classes.
3636

37-
### 🆕 What's new in 1.2.3
37+
### 🆕 What's new in 1.2.4
38+
39+
* Added `submitted` task status support in client models
40+
* Masked `apiKey` in debug logs
41+
* Preserved `task_id` across 429 retries for better error context
42+
* Generalized rate-limit messaging (provider-configurable limits)
43+
* Quick start fixed to not read token from create response
44+
45+
### What was new in 1.2.3
3846

3947
* **Improved error handling for TASK_NOT_FOUND** – when task ID is known, returns TaskNotFoundError with specific ID; when unknown, returns generic RegHelpError instead of confusing "unknown" message.
4048

@@ -84,7 +92,7 @@ async def main():
8492
app_name="tgiOS",
8593
app_device=AppDevice.IOS
8694
)
87-
print(f"Push token: {task.token}")
95+
print(f"Task created: {task.id}")
8896

8997
# Wait for result
9098
result = await client.wait_for_result(task.id, "push")
@@ -105,7 +113,7 @@ if __name__ == "__main__":
105113
- **Асинхронность**: Полная поддержка async/await
106114
- **Типизация**: Полная типизация с Pydantic моделями
107115
- **Retry логика**: Автоматические повторы с exponential backoff
108-
- **Rate limiting**: Умная обработка rate limits (50 rps)
116+
- **Rate limiting**: Умная обработка rate limits (динамические лимиты провайдера)
109117
- **Context manager**: Поддержка async context manager
110118
- **Webhook support**: Поддержка webhook уведомлений
111119
- **Comprehensive error handling**: Детальная обработка всех ошибок API
@@ -384,7 +392,7 @@ from reghelp_client import (
384392
try:
385393
task = await client.get_push_token("tgiOS", AppDevice.IOS)
386394
except RateLimitError:
387-
print("Превышен лимит запросов (50/сек)")
395+
print("Превышен лимит запросов")
388396
except UnauthorizedError:
389397
print("Неверный API ключ")
390398
except TaskNotFoundError as e:

basic_usage.py

Lines changed: 58 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -15,21 +15,17 @@
1515
from typing import Optional
1616

1717
from reghelp_client import (
18-
RegHelpClient,
1918
AppDevice,
2019
EmailType,
21-
ProxyConfig,
22-
ProxyType,
23-
RegHelpError,
2420
RateLimitError,
21+
RegHelpClient,
22+
RegHelpError,
2523
UnauthorizedError,
2624
)
2725

28-
2926
# Setup logging
3027
logging.basicConfig(
31-
level=logging.INFO,
32-
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
28+
level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s"
3329
)
3430
logger = logging.getLogger(__name__)
3531

@@ -39,10 +35,10 @@ async def check_balance(client: RegHelpClient) -> None:
3935
try:
4036
balance = await client.get_balance()
4137
logger.info(f"💰 Current balance: {balance.balance} {balance.currency}")
42-
38+
4339
if balance.balance < 10:
4440
logger.warning("⚠️ Low balance! Consider topping up your account")
45-
41+
4642
except Exception as e:
4743
logger.error(f"❌ Error getting balance: {e}")
4844

@@ -51,31 +47,29 @@ async def get_telegram_push_token(client: RegHelpClient) -> Optional[str]:
5147
"""Get push token for Telegram iOS."""
5248
try:
5349
logger.info("📱 Creating task for Telegram iOS push token...")
54-
50+
5551
# Create task
5652
task = await client.get_push_token(
57-
app_name="tgiOS",
58-
app_device=AppDevice.IOS,
59-
ref="demo_example"
53+
app_name="tgiOS", app_device=AppDevice.IOS, ref="demo_example"
6054
)
61-
55+
6256
logger.info(f"✅ Task created: {task.id} (price: {task.price} RUB)")
63-
57+
6458
# Wait for result with automatic polling
6559
result = await client.wait_for_result(
6660
task_id=task.id,
6761
service="push",
6862
timeout=60.0, # 1 minute
69-
poll_interval=3.0 # check every 3 seconds
63+
poll_interval=3.0, # check every 3 seconds
7064
)
71-
65+
7266
if result.token:
7367
logger.info(f"🎉 Push token received: {result.token[:50]}...")
7468
return result.token
7569
else:
7670
logger.error("❌ Token not received")
7771
return None
78-
72+
7973
except Exception as e:
8074
logger.error(f"❌ Error getting push token: {e}")
8175
return None
@@ -85,36 +79,34 @@ async def get_temporary_email(client: RegHelpClient) -> Optional[str]:
8579
"""Get temporary email address."""
8680
try:
8781
logger.info("📧 Getting temporary email address...")
88-
82+
8983
# Get email
9084
email_task = await client.get_email(
9185
app_name="tg",
9286
app_device=AppDevice.IOS,
9387
phone="+15551234567", # Test number
94-
email_type=EmailType.ICLOUD
88+
email_type=EmailType.ICLOUD,
9589
)
96-
90+
9791
logger.info(f"✅ Email received: {email_task.email}")
98-
92+
9993
# Can wait for verification code
10094
logger.info("⏳ Waiting for verification code (30 sec)...")
101-
95+
10296
try:
10397
email_result = await client.wait_for_result(
104-
task_id=email_task.id,
105-
service="email",
106-
timeout=30.0
98+
task_id=email_task.id, service="email", timeout=30.0
10799
)
108-
100+
109101
if email_result.code:
110102
logger.info(f"📬 Verification code: {email_result.code}")
111103
return email_result.code
112-
104+
113105
except asyncio.TimeoutError:
114106
logger.info("⏰ Verification code not received within 30 seconds")
115-
107+
116108
return email_task.email
117-
109+
118110
except Exception as e:
119111
logger.error(f"❌ Error getting email: {e}")
120112
return None
@@ -124,26 +116,22 @@ async def demonstrate_turnstile(client: RegHelpClient) -> Optional[str]:
124116
"""Demonstrate Turnstile challenge solving."""
125117
try:
126118
logger.info("🔐 Solving Cloudflare Turnstile...")
127-
119+
128120
task = await client.get_turnstile_token(
129121
url="https://demo.example.com",
130122
site_key="0x4AAAA-demo-site-key",
131123
action="demo",
132124
)
133-
125+
134126
logger.info(f"✅ Turnstile task created: {task.id}")
135-
127+
136128
# Wait for result
137-
result = await client.wait_for_result(
138-
task_id=task.id,
139-
service="turnstile",
140-
timeout=120.0
141-
)
142-
129+
result = await client.wait_for_result(task_id=task.id, service="turnstile", timeout=120.0)
130+
143131
if result.token:
144132
logger.info(f"🎉 Turnstile token: {result.token[:50]}...")
145133
return result.token
146-
134+
147135
except Exception as e:
148136
logger.error(f"❌ Turnstile error: {e}")
149137
return None
@@ -152,15 +140,15 @@ async def demonstrate_turnstile(client: RegHelpClient) -> Optional[str]:
152140
async def demonstrate_error_handling(client: RegHelpClient) -> None:
153141
"""Demonstrate various error handling."""
154142
logger.info("🚨 Demonstrating error handling...")
155-
143+
156144
try:
157145
# Try to get status of non-existent task
158146
await client.get_push_status("invalid_task_id")
159-
147+
160148
except UnauthorizedError:
161149
logger.error("🔑 Authorization error: invalid API key")
162150
except RateLimitError:
163-
logger.error("🚦 Rate limit exceeded (50/sec)")
151+
logger.error("🚦 Rate limit exceeded")
164152
except RegHelpError as e:
165153
logger.error(f"🔴 API error: {e}")
166154
except Exception as e:
@@ -170,29 +158,32 @@ async def demonstrate_error_handling(client: RegHelpClient) -> None:
170158
async def parallel_tasks_example(client: RegHelpClient) -> None:
171159
"""Example of parallel task execution."""
172160
logger.info("🔄 Demonstrating parallel execution...")
173-
161+
174162
try:
175163
# Create multiple tasks in parallel
176-
tasks = await asyncio.gather(*[
177-
client.get_push_token("tgiOS", AppDevice.IOS, ref=f"parallel_{i}")
178-
for i in range(3)
179-
], return_exceptions=True)
180-
164+
tasks = await asyncio.gather(
165+
*[client.get_push_token("tgiOS", AppDevice.IOS, ref=f"parallel_{i}") for i in range(3)],
166+
return_exceptions=True,
167+
)
168+
181169
# Filter successful tasks
182170
successful_tasks = [task for task in tasks if not isinstance(task, Exception)]
183-
171+
184172
logger.info(f"✅ Created {len(successful_tasks)} tasks in parallel")
185-
173+
186174
# Can wait for results in parallel
187175
if successful_tasks:
188-
results = await asyncio.gather(*[
189-
client.get_push_status(task.id)
190-
for task in successful_tasks
191-
if hasattr(task, 'id')
192-
], return_exceptions=True)
193-
176+
results = await asyncio.gather(
177+
*[
178+
client.get_push_status(task.id)
179+
for task in successful_tasks
180+
if hasattr(task, "id")
181+
],
182+
return_exceptions=True,
183+
)
184+
194185
logger.info(f"📊 Received {len(results)} statuses")
195-
186+
196187
except Exception as e:
197188
logger.error(f"❌ Parallel execution error: {e}")
198189

@@ -205,26 +196,22 @@ async def main() -> None:
205196
logger.error("❌ API key not found in REGHELP_API_KEY environment variable")
206197
logger.info("💡 Set the variable: export REGHELP_API_KEY=your_api_key")
207198
return
208-
199+
209200
logger.info("🚀 Starting REGHelp Python Client demonstration")
210-
201+
211202
# Use context manager for automatic connection cleanup
212-
async with RegHelpClient(
213-
api_key=api_key,
214-
timeout=30.0,
215-
max_retries=3
216-
) as client:
217-
203+
async with RegHelpClient(api_key=api_key, timeout=30.0, max_retries=3) as client:
204+
218205
# Check API availability
219206
if await client.health_check():
220207
logger.info("✅ API is available")
221208
else:
222209
logger.error("❌ API is unavailable")
223210
return
224-
211+
225212
# Demonstrate various functions
226213
await check_balance(client)
227-
214+
228215
# Only if balance allows
229216
balance = await client.get_balance()
230217
if balance.balance > 1:
@@ -234,13 +221,13 @@ async def main() -> None:
234221
await parallel_tasks_example(client)
235222
else:
236223
logger.warning("⚠️ Insufficient funds to demonstrate paid functions")
237-
224+
238225
# Demonstrate error handling
239226
await demonstrate_error_handling(client)
240-
227+
241228
logger.info("🏁 Demonstration completed")
242229

243230

244231
if __name__ == "__main__":
245232
# Run async function
246-
asyncio.run(main())
233+
asyncio.run(main())

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "reghelp-client"
7-
version = "1.2.3"
7+
version = "1.2.4"
88
description = "Современная асинхронная Python библиотека для работы с REGHelp Key API"
99
readme = "README.md"
1010
license = {file = "LICENSE"}

0 commit comments

Comments
 (0)